botnote 0.1.16 → 0.1.19

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.md CHANGED
@@ -145,7 +145,7 @@ setup is required.
145
145
 
146
146
  ```text
147
147
  # In Claude Code
148
- /plugin marketplace add jianhuawang/botnote
148
+ /plugin marketplace add jianhua-wang/botnote
149
149
  /plugin install botnote@botnote
150
150
 
151
151
  # Claude Code will prompt for:
@@ -167,9 +167,10 @@ Slash commands:
167
167
  ```
168
168
 
169
169
  Plugin distribution lives at
170
- [jianhuawang/botnote](https://github.com/jianhuawang/botnote). The MCP server
171
- inside the plugin uses the URL + token from the install prompt and calls the
172
- `botnote` CLI from PATH. Install the npm package first on non-dev machines.
170
+ [jianhua-wang/botnote](https://github.com/jianhua-wang/botnote). The MCP server
171
+ inside the plugin uses the URL + token from the install prompt. A global
172
+ `botnote` CLI install is optional: the plugin runs `npx -y botnote@<plugin-version> mcp`
173
+ when no matching local CLI is available.
173
174
 
174
175
  ### Codex
175
176
 
@@ -177,8 +178,8 @@ Add the plugin through `/settings -> plugin` in Codex, or add this marketplace
177
178
  from the public repository without a full source checkout:
178
179
 
179
180
  ```bash
180
- codex plugin marketplace add https://github.com/jianhuawang/botnote.git \
181
- --sparse .codex-plugin \
181
+ codex plugin marketplace add https://github.com/jianhua-wang/botnote.git \
182
+ --sparse marketplace.json \
182
183
  --sparse plugins/botnote
183
184
 
184
185
  codex plugin add botnote@botnote-plugins
@@ -225,9 +226,10 @@ source = "/absolute/path/to/botnote"
225
226
  ```
226
227
 
227
228
  The Codex plugin starts `./scripts/run-mcp.sh`. It defaults to
228
- `BOTNOTE_URL=http://127.0.0.1:4280`, calls `botnote mcp` from PATH, and falls
229
- back to `npx -y botnote mcp`. Set `BOTNOTE_URL` and `BOTNOTE_TOKEN` only when
230
- using a remote daemon.
229
+ `BOTNOTE_URL=https://botnote.net`, reads `~/.config/botnote/config.json` when
230
+ available, uses a matching `botnote` CLI from PATH when present, and otherwise
231
+ runs the exact plugin version with `npx -y botnote@<plugin-version> mcp`. Set
232
+ `BOTNOTE_URL` and `BOTNOTE_TOKEN` only when using a custom daemon.
231
233
 
232
234
  ### Cursor
233
235
 
@@ -237,7 +239,7 @@ same MCP server and workflow skills without a second plugin implementation.
237
239
 
238
240
  ```bash
239
241
  # Marketplace root for Cursor plugin clients:
240
- https://github.com/jianhuawang/botnote
242
+ https://github.com/jianhua-wang/botnote
241
243
  ```
242
244
 
243
245
  The Cursor plugin manifest is `plugins/botnote/.cursor-plugin/plugin.json` and
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "botnote",
3
- "version": "0.1.16",
3
+ "version": "0.1.19",
4
4
  "description": "Notion for bots. Lightweight project + notes + memory store, agent-first.",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.33.0",
@@ -8,7 +8,7 @@
8
8
  "homepage": "https://botnote.net",
9
9
  "repository": {
10
10
  "type": "git",
11
- "url": "git+https://github.com/Jianhua-Wang/botnote.git"
11
+ "url": "https://github.com/Jianhua-Wang/botnote"
12
12
  },
13
13
  "bugs": {
14
14
  "url": "https://github.com/Jianhua-Wang/botnote/issues"
@@ -482,7 +482,8 @@ BOTNOTE_URL=http://127.0.0.1:4280 botnote today
482
482
 
483
483
  # Config file (preferred for the daemon host):
484
484
  # ~/.config/botnote/config.json
485
- # { "baseUrl": "http://127.0.0.1:4280" }`})]})}function rU(){return O.jsxs(O.Fragment,{children:[O.jsx(Xl,{title:"Plugin",blurb:"Install the botnote runtime once, then add the plugin for each agent client. The plugin bundles MCP, slash commands, and workflow skills, so Letheia / Plane MCP setup should stay retired."}),O.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-2",children:[O.jsx(kO,{icon:zS,title:"1. Runtime",body:"Install or update the npm binary on every device. Plugins call this binary for MCP."}),O.jsx(kO,{icon:LB,title:"2. Client plugin",body:"Install the marketplace plugin in Claude Code, Codex, Cursor, or another agent client."}),O.jsx(kO,{icon:FT,title:"3. Update both",body:"Runtime and plugin cache update separately. Refresh the client after updating."})]}),O.jsxs("div",{className:"border border-accent/20 bg-accentSoft/50 rounded-md px-4 py-3 text-xs text-accentText leading-relaxed",children:["Use ",O.jsx("code",{className:"text-ink",children:"https://botnote.net"})," with an API token from this settings page on remote devices. On the daemon host, use"," ",O.jsx("code",{className:"text-ink",children:"http://127.0.0.1:4280"})," and skip the token."]}),O.jsx(xo,{icon:zS,title:"Runtime",subtitle:"Required first. Claude Code, Codex, and Cursor all launch this binary for MCP."}),O.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-3",children:[O.jsx(on,{title:"Install runtime",code:`# Runtime used by Claude Code, Codex, and Cursor plugins.
485
+ # { "baseUrl": "http://127.0.0.1:4280" }`})]})}function rU(){return O.jsxs(O.Fragment,{children:[O.jsx(Xl,{title:"Plugin",blurb:"Install the botnote runtime once, then add the plugin for each agent client. The plugin bundles MCP, slash commands, and workflow skills, so Letheia / Plane MCP setup should stay retired."}),O.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-2",children:[O.jsx(kO,{icon:zS,title:"1. Runtime",body:"Install or update the npm binary on every device. Plugins call this binary for MCP."}),O.jsx(kO,{icon:LB,title:"2. Client plugin",body:"Install the marketplace plugin in Claude Code, Codex, Cursor, or another agent client."}),O.jsx(kO,{icon:FT,title:"3. Update both",body:"Runtime and plugin cache update separately. Refresh the client after updating."})]}),O.jsxs("div",{className:"border border-accent/20 bg-accentSoft/50 rounded-md px-4 py-3 text-xs text-accentText leading-relaxed",children:["Use ",O.jsx("code",{className:"text-ink",children:"https://botnote.net"})," with an API token from this settings page on remote devices. On the daemon host, use"," ",O.jsx("code",{className:"text-ink",children:"http://127.0.0.1:4280"})," and skip the token."]}),O.jsx(xo,{icon:zS,title:"Runtime",subtitle:"Required first. Claude Code, Codex, and Cursor all launch this binary for MCP."}),O.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-3",children:[O.jsx(on,{title:"Install runtime",code:`# Optional helper CLI for login and manual commands.
486
+ # Plugins can run without a global CLI by using npx.
486
487
  npm i -g botnote@latest
487
488
 
488
489
  # Remote clients: save https://botnote.net + a bearer token.
@@ -505,7 +506,7 @@ botnote --version`})]}),O.jsx(xo,{icon:NB,title:"Claude Code",subtitle:"Recommen
505
506
  # Manual update, if available in your Claude Code build:
506
507
  claude plugin update botnote@botnote`})]}),O.jsx(xo,{icon:GT,title:"Codex",subtitle:"Use the Git marketplace flow; sparse checkout means no full botnote source checkout."}),O.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-3",children:[O.jsx(on,{title:"Install",code:`# No full source checkout required.
507
508
  codex plugin marketplace add https://github.com/jianhua-wang/botnote.git \\
508
- --sparse .codex-plugin \\
509
+ --sparse marketplace.json \\
509
510
  --sparse plugins/botnote
510
511
 
511
512
  codex plugin add botnote@botnote-plugins`}),O.jsx(on,{title:"Update",code:`# Codex refreshes Git marketplaces, then installs from the fresh snapshot.
@@ -583,4 +584,4 @@ curl -X POST '${Vf}/v1/notes' \\
583
584
  curl -X POST '${Vf}/v1/search' \\
584
585
  -H 'authorization: Bearer bn_...' \\
585
586
  -H 'content-type: application/json' \\
586
- -d '{ "query": "deployment", "limit": 10 }'`;return O.jsxs(O.Fragment,{children:[O.jsx(Xl,{title:"MCP (raw integration)",blurb:"Skip the Claude Code plugin and wire the MCP server in by hand — for Codex, custom agents, or any MCP-aware client. The botnote binary doubles as the MCP stdio server."}),O.jsx(on,{title:"Claude Code (~/.claude.json or project-local .mcp.json)",code:n}),O.jsx(on,{title:"Codex (~/.codex/config.toml)",code:e}),O.jsx(on,{title:"REST · curl",code:t}),O.jsxs("div",{className:"border border-line rounded-md bg-surface px-4 py-3 text-xs text-muted leading-relaxed",children:["Requires the ",O.jsx("code",{className:"text-ink",children:"botnote"})," binary in",O.jsx("code",{className:"text-ink",children:" PATH"})," ","(",O.jsx("code",{className:"text-ink",children:"npm i -g botnote"}),"). The MCP server has no DB connection of its own; it speaks HTTP to whichever ",O.jsx("code",{className:"text-ink",children:"BOTNOTE_URL"})," you set."]})]})}function oU(){const{data:n,isLoading:e}=Lq(),t=n!=null&&n.version?`v${n.version}`:e?"loading...":"unknown";return O.jsxs(O.Fragment,{children:[O.jsx(Xl,{title:"About",blurb:"Build + runtime info for this daemon."}),O.jsxs("div",{className:"border border-line rounded-md bg-surface px-4 py-3 text-xs text-muted space-y-2",children:[O.jsxs("div",{children:[O.jsxs("span",{className:"text-ink",children:["botnote ",t]})," — Postgres 16 + pgvector + Fastify 5 + MCP SDK"]}),O.jsxs("div",{children:["REST: ",O.jsx("code",{className:"text-ink",children:Vf})," · docs:"," ",O.jsx("a",{className:"text-accent hover:underline",href:"/docs",target:"_blank",rel:"noreferrer",children:"/docs"})]}),O.jsxs("div",{className:"pt-1 border-t border-lineSoft",children:["Auth is enforced when ",O.jsx("code",{className:"text-ink",children:"BOTNOTE_REQUIRE_AUTH=1"})," on the daemon. Direct connections from loopback or private networks are trusted; requests via Cloudflare Tunnel (or any proxy that sets ",O.jsx("code",{children:"cf-connecting-ip"})," /"," ",O.jsx("code",{children:"x-forwarded-for"}),") require a bearer token or a browser session cookie."]})]})]})}function on({title:n,code:e}){const[t,r]=N.useState(!1);function i(){navigator.clipboard.writeText(e).then(()=>{r(!0),setTimeout(()=>r(!1),1400)})}return O.jsxs("div",{className:"border border-line rounded-md bg-surface overflow-hidden",children:[O.jsxs("div",{className:"px-3 py-1.5 border-b border-lineSoft flex items-center justify-between bg-sidebar/40",children:[O.jsx("span",{className:"text-xxs uppercase tracking-wider text-muted font-medium",children:n}),O.jsxs("button",{onClick:i,className:"text-xxs text-muted hover:text-ink flex items-center gap-1",children:[t?O.jsx(Nc,{size:11}):O.jsx(Wy,{size:11}),t?"Copied":"Copy"]})]}),O.jsx("pre",{className:"px-3 py-2 text-xs font-mono leading-relaxed overflow-x-auto whitespace-pre bg-sidebar/20 text-ink2",children:e})]})}function aU(){const{data:n,isLoading:e}=qq(),t=Fq(),r=Yq(),[i,s]=N.useState(""),[l,o]=N.useState(null),[u,h]=N.useState(null),[f,p]=N.useState(null),[m,y]=N.useState(null);function k(S){navigator.clipboard.writeText(S.plaintext).then(()=>{y(S.id),setTimeout(()=>y(C=>C===S.id?null:C),1400)})}async function b(S){if(S.preventDefault(),!i.trim())return;const C=await t.mutateAsync(i.trim());o(C),s("")}async function w(S,C){if(!u&&confirm(`Revoke token "${C}"? Any client using it stops working.`)){h(S),p(null);try{await r.mutateAsync(S),(l==null?void 0:l.id)===S&&o(null)}catch(Q){const A=Q instanceof Error?Q.message:String(Q);p(`Could not revoke "${C}": ${A}`)}finally{h(Q=>Q===S?null:Q)}}}return O.jsxs(O.Fragment,{children:[O.jsx(Xl,{title:"API tokens",blurb:"Bearer tokens for the CLI, MCP server, and direct REST calls. New tokens keep their full value available for copying here; older tokens created before this change only have a prefix and must be regenerated if the full value was lost."}),l&&O.jsxs("div",{className:"border border-warn rounded-md bg-warn/10 p-3 space-y-2",children:[O.jsxs("div",{className:"flex items-center gap-2 text-xs font-medium text-warn",children:[O.jsx(o6,{size:13}),"Copy this token now, or later from the token list."]}),O.jsxs("div",{className:"flex items-center gap-2",children:[O.jsx("code",{className:"flex-1 text-xs font-mono bg-surface border border-line rounded px-2 py-1 overflow-x-auto whitespace-nowrap",children:l.plaintext}),O.jsxs("button",{className:"btn",onClick:()=>navigator.clipboard.writeText(l.plaintext),children:[O.jsx(Wy,{size:11})," Copy"]}),O.jsx("button",{className:"btn",onClick:()=>o(null),children:"Done"})]})]}),f&&O.jsx("div",{className:"border border-danger/30 rounded-md bg-danger/10 px-3 py-2 text-xs text-danger",children:f}),O.jsxs("form",{onSubmit:b,className:"flex gap-2",children:[O.jsx("input",{className:"input flex-1",placeholder:"Token name (e.g. claude-code-laptop)",value:i,onChange:S=>s(S.target.value)}),O.jsxs("button",{type:"submit",className:"btn btn-primary",disabled:!i.trim()||t.isPending,children:[O.jsx(rp,{size:11})," ",t.isPending?"Generating…":"Generate"]})]}),O.jsxs("div",{className:"border border-line rounded-md bg-surface divide-y divide-lineSoft overflow-hidden",children:[e&&O.jsx("div",{className:"p-3 text-xs text-muted",children:"Loading…"}),!e&&(!n||n.length===0)&&O.jsx("div",{className:"p-4 text-xs text-faint text-center",children:"No tokens yet."}),n==null?void 0:n.map(S=>{const C=m===S.id;return O.jsxs("div",{className:"flex items-center gap-3 px-3 py-2",children:[O.jsxs("div",{className:"flex-1 min-w-0",children:[O.jsx("div",{className:"text-sm text-ink truncate",children:S.name}),O.jsxs("div",{className:"text-xxs text-muted flex items-center gap-3 mt-0.5",children:[O.jsxs("code",{className:"font-mono text-faint",children:[S.prefix,"…"]}),O.jsxs("span",{children:["created ",s0(new Date(S.createdAt),{addSuffix:!0})]}),O.jsx("span",{children:S.lastUsedAt?`used ${s0(new Date(S.lastUsedAt),{addSuffix:!0})}`:"never used"})]})]}),S.plaintext?O.jsxs("button",{type:"button",onClick:()=>k({id:S.id,plaintext:S.plaintext}),className:`btn gap-1.5 ${C?"!border-emerald-500/30 !text-emerald-600":""}`,title:"Copy full token",children:[C?O.jsx(Nc,{size:11}):O.jsx(Wy,{size:11}),C?"Copied":"Copy token"]}):O.jsx("span",{className:"text-xxs text-faint border border-line rounded px-2 py-1",title:"Full token is unavailable for tokens created before recoverable storage was enabled.",children:"Unavailable"}),O.jsx("button",{type:"button",className:"text-faint hover:text-danger p-1 -m-1",disabled:u!==null,onClick:()=>w(S.id,S.name),title:u===S.id?"Revoking":"Revoke",children:u===S.id?O.jsx("span",{className:"text-xxs text-muted",children:"Revoking…"}):O.jsx(KT,{size:12})})]},S.id)})]})]})}function uU({anchor:n,projectIds:e}){const t=Xx("day",n),{data:r}=Sa({from:t.from.toISOString(),to:t.to.toISOString(),projectIds:e??null,includeBacklog:!1,includeDone:!0}),{data:i}=sr(),s=N.useMemo(()=>Ca(i),[i]),{open:l}=Dt(),o=(r==null?void 0:r.overdue)??[],u=((r==null?void 0:r.scheduled)??[]).slice().sort(pp),h=fp(n);return O.jsx("div",{className:"h-full overflow-y-auto scrollbar-thin",children:O.jsxs("div",{className:"max-w-4xl mx-auto py-4",children:[h&&o.length>0&&O.jsx(ZP,{title:"Overdue",count:o.length,accent:"text-danger",tasks:o,projectMap:s}),O.jsx(ZP,{title:h?"Today":un(n,"EEEE"),count:u.length,accent:"text-ink",tasks:u,projectMap:s,emptyAction:O.jsx("button",{className:"text-accent text-xs hover:underline",onClick:()=>l({kind:"quick-create"}),children:"+ add a task for this day"})})]})})}function ZP({title:n,count:e,accent:t,tasks:r,projectMap:i,emptyAction:s}){return O.jsxs("section",{className:"mb-6",children:[O.jsxs("div",{className:"px-4 py-1.5 flex items-baseline gap-2 sticky top-0 bg-bg z-10",children:[O.jsx("h2",{className:`text-xs font-semibold ${t}`,children:n}),O.jsx("span",{className:"text-xxs text-faint tabular-nums",children:e})]}),r.length===0?O.jsx("div",{className:"px-4 py-2 text-xs text-muted",children:s??"Nothing here."}):O.jsx("div",{className:"bg-surface border-y border-lineSoft",children:r.map(l=>O.jsx(dp,{task:l,project:l.projectId?i.get(l.projectId):void 0},l.id))})]})}function cU({projectIds:n,collapsed:e,onToggle:t}){const{data:r}=Sa({projectIds:n??null,includeBacklog:!0,includeDone:!1}),{data:i}=sr(),s=N.useMemo(()=>Ca(i),[i]),l=((r==null?void 0:r.backlog)??[]).filter(o=>o.status!=="rejected");return e?O.jsxs("button",{className:"shrink-0 w-8 border-l border-line bg-sidebar/50 hover:bg-sidebar flex flex-col items-center pt-2 gap-2 group",onClick:t,title:"Expand Inbox",children:[O.jsx(Td,{size:14,className:"text-muted group-hover:text-ink"}),l.length>0&&O.jsx("div",{className:"text-xxs text-muted bg-surface border border-line rounded-full w-5 h-5 flex items-center justify-center",children:l.length})]}):O.jsxs("aside",{className:"shrink-0 w-72 border-l border-line bg-surface flex flex-col",children:[O.jsxs("div",{className:"px-3 h-9 flex items-center justify-between border-b border-lineSoft",children:[O.jsxs("div",{className:"flex items-center gap-2 text-muted",children:[O.jsx(Td,{size:12}),O.jsx("h2",{className:"text-xs font-medium text-ink2",children:"Inbox"}),O.jsx("span",{className:"text-xxs text-faint tabular-nums",children:l.length})]}),O.jsx("button",{onClick:t,className:"btn-ghost btn !h-6 !w-6 !p-0",title:"Collapse",children:"→"})]}),O.jsx("div",{className:"flex-1 overflow-y-auto scrollbar-thin",children:l.length===0?O.jsxs("div",{className:"text-xs text-muted text-center py-8 px-4",children:["No tasks without due date.",O.jsx("div",{className:"text-faint mt-1",children:"Tasks without due date appear here."})]}):l.map(o=>O.jsx(dp,{task:o,project:o.projectId?s.get(o.projectId):void 0,compact:!0},o.id))})]})}function PE({task:n,project:e}){const t=Vi(),r=n.dueAt&&new Date(n.dueAt).getTime()<Date.now()&&n.status!=="done"&&n.status!=="in_progress";return O.jsxs("div",{role:"button",tabIndex:0,draggable:!0,onDragStart:i=>{i.dataTransfer.setData("text/task-id",n.id),i.dataTransfer.effectAllowed="move",i.stopPropagation()},onClick:()=>t.open(n.id),onKeyDown:i=>{i.key!=="Enter"&&i.key!==" "||(i.preventDefault(),t.open(n.id))},className:`group w-full text-left flex items-center gap-1.5 pl-1 pr-1.5 py-1 rounded text-xs hover:bg-sidebarHover transition-colors cursor-grab active:cursor-grabbing ${r?"bg-danger/5":""}`,title:e?`${e.key} · ${vn(n)}`:vn(n),children:[O.jsx("span",{className:"w-[2px] self-stretch rounded-sm shrink-0",style:{backgroundColor:(e==null?void 0:e.color)??"#a8a8af"}}),O.jsx(cp,{task:n,size:11}),O.jsx("span",{className:`truncate flex-1 min-w-0 ${n.status==="done"?"line-through text-muted":n.status==="rejected"?"text-muted":fi(n)?"italic text-muted":"text-ink2"}`,children:vn(n)}),n.priority!=="none"&&O.jsx(aa,{priority:n.priority,size:11})]})}const hU=["Mon","Tue","Wed","Thu","Fri","Sat","Sun"];function fU({anchor:n,projectIds:e}){const t=Xx("month",n),r=SE(t.from,t.to),{data:i}=Sa({from:t.from.toISOString(),to:t.to.toISOString(),projectIds:e??null,includeBacklog:!1,includeDone:!0}),{data:s}=sr(),l=N.useMemo(()=>Ca(s),[s]),o=N.useMemo(()=>bE((i==null?void 0:i.scheduled)??[]),[i]);return O.jsxs("div",{className:"h-full flex flex-col",children:[O.jsx("div",{className:"grid grid-cols-7 border-b border-lineSoft bg-sidebar/50",children:hU.map(u=>O.jsx("div",{className:"px-2 py-1 text-xxs uppercase tracking-wider text-muted text-center",children:u},u))}),O.jsx("div",{className:"flex-1 grid grid-cols-7 grid-rows-6 bg-line/30 gap-px overflow-y-auto scrollbar-thin",children:r.map(u=>{const h=o.get(wE(u))??[],f=!IY(u,n),p=fp(u);return O.jsx(dU,{day:u,tasks:h,projectMap:l,outOfMonth:f,today:p},u.toISOString())})})]})}function dU({day:n,tasks:e,projectMap:t,outOfMonth:r,today:i}){const{open:s}=Dt(),l=zl(),[o,u]=N.useState(!1),h=e.slice().sort(pp),f=h.filter(k=>k.status==="done").length,p=h.length,m=p>0&&f===p;function y(k){k.preventDefault(),u(!1);const b=k.dataTransfer.getData("text/task-id");if(!b)return;const w=new Date(n);w.setHours(12,0,0,0),l.mutate({id:b,fields:{dueAt:w.toISOString()}})}return O.jsxs("div",{className:`group bg-surface p-1 min-h-[112px] flex flex-col transition-colors ${r?"opacity-50":""} ${o?"ring-2 ring-accent ring-inset bg-accentSoft/40":i?"ring-1 ring-accent ring-inset bg-accentSoft/30":""}`,onDragOver:k=>{k.preventDefault(),o||u(!0)},onDragLeave:()=>u(!1),onDrop:y,children:[O.jsxs("div",{className:"flex items-center justify-between mb-1 px-1",children:[O.jsxs("div",{className:"flex items-baseline gap-1.5 min-w-0",children:[O.jsx("span",{className:`text-xs tabular-nums ${i?"font-semibold text-accent":"text-muted"}`,children:un(n,"d")}),p>0&&O.jsxs("span",{className:`text-xxs tabular-nums ${m?"text-statusDone font-medium":"text-faint"}`,title:`${f} done · ${p} total`,children:[f,"/",p]})]}),O.jsx("button",{className:"text-xs text-faint hover:text-accent opacity-0 group-hover:opacity-100 transition-opacity",onClick:()=>s({kind:"quick-create"}),title:"Add task",children:"+"})]}),O.jsxs("div",{className:"flex-1 space-y-0.5 min-h-0 overflow-hidden",children:[h.slice(0,4).map(k=>O.jsx(PE,{task:k,project:k.projectId?t.get(k.projectId):void 0},k.id)),h.length>4&&O.jsxs("div",{className:"text-xxs text-muted pl-1",children:["+",h.length-4]})]})]})}function pU({view:n,setView:e,anchor:t,setAnchor:r,projectIds:i,setProjectIds:s}){var h;const{data:l}=sr(),{open:o}=Dt(),u=i?i.length===1?((h=l==null?void 0:l.find(f=>f.id===i[0]))==null?void 0:h.key)??"1 project":`${i.length} projects`:"All projects";return O.jsx("div",{className:"border-b border-line bg-surface",children:O.jsxs("div",{className:"flex items-center justify-between h-11 px-3",children:[O.jsxs("div",{className:"flex items-center gap-3",children:[O.jsx("h1",{className:"text-xs font-semibold text-ink",children:"Tasks"}),O.jsx("div",{className:"seg",children:["day","week","month"].map(f=>O.jsx("button",{onClick:()=>e(f),"data-active":n===f,className:"capitalize",children:f},f))}),O.jsxs("div",{className:"flex items-center gap-1 ml-1",children:[O.jsx("button",{onClick:()=>r(OO(n,t,-1)),className:"btn btn-ghost !h-6 !w-6 !p-0",title:"Previous",children:O.jsx(zT,{size:12})}),O.jsx("button",{onClick:()=>r(OO(n,t,0)),className:"btn !h-6 px-2 text-xxs",title:"Today",children:"Today"}),O.jsx("button",{onClick:()=>r(OO(n,t,1)),className:"btn btn-ghost !h-6 !w-6 !p-0",title:"Next",children:O.jsx(ZT,{size:12})}),O.jsx("div",{className:"ml-2 text-xs font-medium text-ink2 tabular-nums",children:ZY(n,t)})]})]}),O.jsxs("div",{className:"flex items-center gap-1.5",children:[O.jsx(mU,{projects:l??[],projectIds:i,setProjectIds:s,label:u}),O.jsxs("button",{className:"btn btn-primary",onClick:()=>o({kind:"quick-create"}),title:"New task (c)",children:[O.jsx(rp,{size:11}),O.jsx("span",{className:"text-xs",children:"Task"}),O.jsx("kbd",{className:"!bg-white/15 !border-white/25 !text-white",children:"c"})]})]})]})})}function mU({projects:n,projectIds:e,setProjectIds:t,label:r}){return O.jsxs("details",{className:"relative",children:[O.jsxs("summary",{className:"btn list-none cursor-pointer",children:[O.jsx(zB,{size:11}),O.jsx("span",{className:"text-xs",children:r})]}),O.jsxs("div",{className:"popover top-9 right-0 w-56 px-1 py-1.5",children:[O.jsxs("button",{className:`popover-item ${e?"":"bg-accentSoft text-accentText"}`,onClick:()=>t(null),children:[O.jsx("span",{children:"All projects"}),!e&&O.jsx("span",{className:"ml-auto text-faint",children:"✓"})]}),O.jsx("div",{className:"divider my-1"}),n.map(i=>{const s=(e==null?void 0:e.includes(i.id))??!1;return O.jsxs("label",{className:"popover-item gap-2 cursor-pointer",children:[O.jsx("input",{type:"checkbox",className:"cursor-pointer",checked:s,onChange:()=>{if(!e)t([i.id]);else if(s){const l=e.filter(o=>o!==i.id);t(l.length?l:null)}else t([...e,i.id])}}),O.jsx("span",{className:"font-mono text-xxs text-faint tabular-nums",children:i.key}),O.jsx("span",{className:"text-ink2 truncate",children:i.name})]},i.id)})]})]})}function gU({anchor:n,projectIds:e}){const t=Xx("week",n),r=SE(t.from,t.to),i=hp(r[r.length-1],1),s=[...r,i],l=new Date(i);l.setHours(23,59,59,999);const{data:o}=Sa({from:t.from.toISOString(),to:l.toISOString(),projectIds:e??null,includeBacklog:!1,includeDone:!0}),{data:u}=sr(),h=N.useMemo(()=>Ca(u),[u]),f=N.useMemo(()=>bE((o==null?void 0:o.scheduled)??[]),[o]),p=s.slice(0,4),m=s.slice(4);return O.jsxs("div",{className:"h-full flex flex-col bg-bg",children:[O.jsx(XP,{days:p,byDay:f,projectMap:h,anchor:n}),O.jsx(XP,{days:m,byDay:f,projectMap:h,anchor:n})]})}function XP({days:n,byDay:e,projectMap:t,anchor:r}){return O.jsx("div",{className:"flex-1 min-h-0 flex border-b border-line last:border-b-0",children:n.map(i=>{const s=e.get(wE(i))??[],l=!DY(i,r,{weekStartsOn:1});return O.jsx(OU,{day:i,tasks:s,projectMap:t,outOfWeek:l},i.toISOString())})})}function OU({day:n,tasks:e,projectMap:t,outOfWeek:r}){const i=fp(n),{open:s}=Dt(),l=zl(),o=e.slice().sort(pp),u=o.filter(m=>m.status==="done").length,h=o.length,f=h>0&&u===h;function p(m){m.preventDefault();const y=m.dataTransfer.getData("text/task-id");if(!y)return;const k=new Date(n);k.setHours(12,0,0,0),l.mutate({id:y,fields:{dueAt:k.toISOString()}})}return O.jsxs("div",{className:`flex-1 min-w-0 border-r border-lineSoft last:border-r-0 flex flex-col group/col ${i?"bg-accentSoft/30":r?"bg-sidebar/40":"bg-surface"}`,onDragOver:m=>m.preventDefault(),onDrop:p,children:[O.jsxs("div",{className:"px-3 py-1.5 flex items-baseline justify-between border-b border-lineSoft",children:[O.jsxs("div",{className:"flex items-baseline gap-2 min-w-0",children:[O.jsx("span",{className:"text-xxs uppercase tracking-wider text-muted",children:un(n,"EEE")}),O.jsx("span",{className:`text-sm tabular-nums font-semibold ${i?"text-accent":r?"text-muted":"text-ink2"}`,children:un(n,"d")}),h>0&&O.jsxs("span",{className:`text-xxs tabular-nums ${f?"text-statusDone font-medium":"text-faint"}`,title:`${u} done · ${h} total`,children:[u,"/",h]}),r&&O.jsx("span",{className:"text-xxs text-faint italic",children:"next"})]}),O.jsx("button",{className:"text-faint hover:text-accent text-xs opacity-0 group-hover/col:opacity-100",title:"Add task",onClick:()=>s({kind:"quick-create"}),children:"+"})]}),O.jsx("div",{className:"flex-1 overflow-y-auto scrollbar-thin p-1.5 space-y-1",children:o.length===0?O.jsx("div",{className:"text-xxs text-faint px-1 py-0.5",children:"—"}):o.map(m=>O.jsx(PE,{task:m,project:m.projectId?t.get(m.projectId):void 0},m.id))})]})}function yU(){const[n,e]=N.useState("week"),[t,r]=N.useState(()=>new Date),[i,s]=N.useState(null),[l,o]=N.useState(!1);return O.jsxs("div",{className:"h-full flex flex-col",children:[O.jsx(pU,{view:n,setView:e,anchor:t,setAnchor:r,projectIds:i,setProjectIds:s}),O.jsxs("div",{className:"flex-1 min-h-0 flex",children:[O.jsxs("div",{className:"flex-1 min-w-0 overflow-hidden bg-bg",children:[n==="day"&&O.jsx(uU,{anchor:t,projectIds:i}),n==="week"&&O.jsx(gU,{anchor:t,projectIds:i}),n==="month"&&O.jsx(fU,{anchor:t,projectIds:i})]}),O.jsx(cU,{projectIds:i,collapsed:l,onToggle:()=>o(u=>!u)})]})]})}function xU(){const n=new Date,{data:e}=sr(),t=N.useMemo(()=>Ca(e),[e]),r=N.useMemo(()=>{const h=new Date(n);h.setHours(0,0,0,0);const f=new Date(n);return f.setHours(23,59,59,999),{from:h.toISOString(),to:f.toISOString()}},[]),{data:i,isLoading:s}=Sa({from:r.from,to:r.to,includeBacklog:!1,includeDone:!0}),{open:l}=Dt(),o=((i==null?void 0:i.overdue)??[]).filter(h=>h.status!=="rejected"),u=((i==null?void 0:i.scheduled)??[]).slice().sort(pp);return O.jsx("div",{className:"h-full overflow-y-auto scrollbar-thin",children:O.jsxs("div",{className:"max-w-3xl mx-auto px-6 py-6 space-y-6",children:[O.jsxs("header",{className:"flex items-baseline gap-3",children:[O.jsx(HT,{size:18,className:"text-accent"}),O.jsx("h1",{className:"text-lg font-semibold",children:"Today"}),O.jsx("span",{className:"text-xs text-muted",children:un(n,"EEEE, MMM d")})]}),s&&O.jsx("div",{className:"text-sm text-muted",children:"Loading…"}),!s&&O.jsxs(O.Fragment,{children:[O.jsx(BP,{title:"Overdue",count:o.length,accent:"text-danger",tasks:o,projectMap:t}),O.jsx(BP,{title:fp(n)?"Today":un(n,"EEEE"),count:u.length,accent:"text-ink",tasks:u,projectMap:t,emptyAction:O.jsx("button",{className:"text-accent text-xs hover:underline",onClick:()=>l({kind:"quick-create"}),children:"+ add a task"})})]})]})})}function BP({title:n,count:e,accent:t,tasks:r,projectMap:i,emptyAction:s}){if(r.length===0&&!s)return null;const l=new Map;for(const o of r){const u=o.projectId??null;l.has(u)||l.set(u,[]),l.get(u).push(o)}return O.jsxs("section",{className:"space-y-1.5",children:[O.jsxs("div",{className:"flex items-baseline gap-2",children:[O.jsx("h2",{className:`text-xs font-semibold ${t}`,children:n}),O.jsx("span",{className:"text-xxs text-faint tabular-nums",children:e})]}),r.length===0?O.jsx("div",{className:"text-xs text-muted py-1",children:s??"Nothing here."}):O.jsx("div",{className:"border border-line rounded-md overflow-hidden bg-surface",children:Array.from(l.entries()).map(([o,u])=>{const h=o?i.get(o):void 0;return O.jsxs("div",{children:[O.jsxs("div",{className:"px-3 py-1 border-b border-lineSoft bg-sidebar/40 flex items-center gap-1.5 text-xxs",children:[h?O.jsxs(O.Fragment,{children:[O.jsx(Fs,{color:h.color,icon:h.icon,size:10}),O.jsx("span",{className:"font-mono tabular-nums",style:{color:h.color},children:h.key}),O.jsx("span",{className:"text-muted truncate",children:h.name})]}):O.jsx("span",{className:"text-faint",children:"no project"}),O.jsx("span",{className:"text-faint ml-auto tabular-nums",children:u.length})]}),u.map(f=>O.jsx(dp,{task:f,project:h},f.id))]},o??"_none")})})]})}function kU(){return O.jsxs(w5,{children:[O.jsxs(a5,{children:[O.jsx(dr,{path:"/login",element:O.jsx(qY,{})}),O.jsxs(dr,{element:O.jsx(hF,{}),children:[O.jsx(dr,{path:"/",element:O.jsx(yU,{})}),O.jsx(dr,{path:"/today",element:O.jsx(xU,{})}),O.jsx(dr,{path:"/inbox",element:O.jsx(BY,{})}),O.jsx(dr,{path:"/dashboard",element:O.jsx(kF,{})}),O.jsx(dr,{path:"/settings",element:O.jsx(eU,{})}),O.jsx(dr,{path:"/p/:key",element:O.jsx(GY,{})}),O.jsx(dr,{path:"/p/:key/e/:id",element:O.jsx(bF,{})}),O.jsx(dr,{path:"/p/:key/agents-md",element:O.jsx(xF,{})}),O.jsx(dr,{path:"/search",element:O.jsx(KY,{})})]})]}),O.jsx(OF,{})]})}const vU=new UA({defaultOptions:{queries:{staleTime:1e4,gcTime:5*6e4,retry:1,refetchOnWindowFocus:!0}}});pR.createRoot(document.getElementById("root")).render(O.jsx(h2.StrictMode,{children:O.jsx(GA,{client:vU,children:O.jsx(O5,{children:O.jsx(kU,{})})})}));
587
+ -d '{ "query": "deployment", "limit": 10 }'`;return O.jsxs(O.Fragment,{children:[O.jsx(Xl,{title:"MCP (raw integration)",blurb:"Skip the Claude Code plugin and wire the MCP server in by hand — for Codex, custom agents, or any MCP-aware client. The botnote binary doubles as the MCP stdio server."}),O.jsx(on,{title:"Claude Code (~/.claude.json or project-local .mcp.json)",code:n}),O.jsx(on,{title:"Codex (~/.codex/config.toml)",code:e}),O.jsx(on,{title:"REST · curl",code:t}),O.jsxs("div",{className:"border border-line rounded-md bg-surface px-4 py-3 text-xs text-muted leading-relaxed",children:["Raw MCP configuration requires the ",O.jsx("code",{className:"text-ink",children:"botnote"})," binary in",O.jsx("code",{className:"text-ink",children:" PATH"})," ","(",O.jsx("code",{className:"text-ink",children:"npm i -g botnote"}),"). The Claude Code and Codex plugins do not require a global CLI install; they run the matching npm package version automatically. The MCP server has no DB connection of its own; it speaks HTTP to whichever"," ",O.jsx("code",{className:"text-ink",children:"BOTNOTE_URL"})," you set."]})]})}function oU(){const{data:n,isLoading:e}=Lq(),t=n!=null&&n.version?`v${n.version}`:e?"loading...":"unknown";return O.jsxs(O.Fragment,{children:[O.jsx(Xl,{title:"About",blurb:"Build + runtime info for this daemon."}),O.jsxs("div",{className:"border border-line rounded-md bg-surface px-4 py-3 text-xs text-muted space-y-2",children:[O.jsxs("div",{children:[O.jsxs("span",{className:"text-ink",children:["botnote ",t]})," — Postgres 16 + pgvector + Fastify 5 + MCP SDK"]}),O.jsxs("div",{children:["REST: ",O.jsx("code",{className:"text-ink",children:Vf})," · docs:"," ",O.jsx("a",{className:"text-accent hover:underline",href:"/docs",target:"_blank",rel:"noreferrer",children:"/docs"})]}),O.jsxs("div",{className:"pt-1 border-t border-lineSoft",children:["Auth is enforced when ",O.jsx("code",{className:"text-ink",children:"BOTNOTE_REQUIRE_AUTH=1"})," on the daemon. Direct connections from loopback or private networks are trusted; requests via Cloudflare Tunnel (or any proxy that sets ",O.jsx("code",{children:"cf-connecting-ip"})," /"," ",O.jsx("code",{children:"x-forwarded-for"}),") require a bearer token or a browser session cookie."]})]})]})}function on({title:n,code:e}){const[t,r]=N.useState(!1);function i(){navigator.clipboard.writeText(e).then(()=>{r(!0),setTimeout(()=>r(!1),1400)})}return O.jsxs("div",{className:"border border-line rounded-md bg-surface overflow-hidden",children:[O.jsxs("div",{className:"px-3 py-1.5 border-b border-lineSoft flex items-center justify-between bg-sidebar/40",children:[O.jsx("span",{className:"text-xxs uppercase tracking-wider text-muted font-medium",children:n}),O.jsxs("button",{onClick:i,className:"text-xxs text-muted hover:text-ink flex items-center gap-1",children:[t?O.jsx(Nc,{size:11}):O.jsx(Wy,{size:11}),t?"Copied":"Copy"]})]}),O.jsx("pre",{className:"px-3 py-2 text-xs font-mono leading-relaxed overflow-x-auto whitespace-pre bg-sidebar/20 text-ink2",children:e})]})}function aU(){const{data:n,isLoading:e}=qq(),t=Fq(),r=Yq(),[i,s]=N.useState(""),[l,o]=N.useState(null),[u,h]=N.useState(null),[f,p]=N.useState(null),[m,y]=N.useState(null);function k(S){navigator.clipboard.writeText(S.plaintext).then(()=>{y(S.id),setTimeout(()=>y(C=>C===S.id?null:C),1400)})}async function b(S){if(S.preventDefault(),!i.trim())return;const C=await t.mutateAsync(i.trim());o(C),s("")}async function w(S,C){if(!u&&confirm(`Revoke token "${C}"? Any client using it stops working.`)){h(S),p(null);try{await r.mutateAsync(S),(l==null?void 0:l.id)===S&&o(null)}catch(Q){const A=Q instanceof Error?Q.message:String(Q);p(`Could not revoke "${C}": ${A}`)}finally{h(Q=>Q===S?null:Q)}}}return O.jsxs(O.Fragment,{children:[O.jsx(Xl,{title:"API tokens",blurb:"Bearer tokens for the CLI, MCP server, and direct REST calls. New tokens keep their full value available for copying here; older tokens created before this change only have a prefix and must be regenerated if the full value was lost."}),l&&O.jsxs("div",{className:"border border-warn rounded-md bg-warn/10 p-3 space-y-2",children:[O.jsxs("div",{className:"flex items-center gap-2 text-xs font-medium text-warn",children:[O.jsx(o6,{size:13}),"Copy this token now, or later from the token list."]}),O.jsxs("div",{className:"flex items-center gap-2",children:[O.jsx("code",{className:"flex-1 text-xs font-mono bg-surface border border-line rounded px-2 py-1 overflow-x-auto whitespace-nowrap",children:l.plaintext}),O.jsxs("button",{className:"btn",onClick:()=>navigator.clipboard.writeText(l.plaintext),children:[O.jsx(Wy,{size:11})," Copy"]}),O.jsx("button",{className:"btn",onClick:()=>o(null),children:"Done"})]})]}),f&&O.jsx("div",{className:"border border-danger/30 rounded-md bg-danger/10 px-3 py-2 text-xs text-danger",children:f}),O.jsxs("form",{onSubmit:b,className:"flex gap-2",children:[O.jsx("input",{className:"input flex-1",placeholder:"Token name (e.g. claude-code-laptop)",value:i,onChange:S=>s(S.target.value)}),O.jsxs("button",{type:"submit",className:"btn btn-primary",disabled:!i.trim()||t.isPending,children:[O.jsx(rp,{size:11})," ",t.isPending?"Generating…":"Generate"]})]}),O.jsxs("div",{className:"border border-line rounded-md bg-surface divide-y divide-lineSoft overflow-hidden",children:[e&&O.jsx("div",{className:"p-3 text-xs text-muted",children:"Loading…"}),!e&&(!n||n.length===0)&&O.jsx("div",{className:"p-4 text-xs text-faint text-center",children:"No tokens yet."}),n==null?void 0:n.map(S=>{const C=m===S.id;return O.jsxs("div",{className:"flex items-center gap-3 px-3 py-2",children:[O.jsxs("div",{className:"flex-1 min-w-0",children:[O.jsx("div",{className:"text-sm text-ink truncate",children:S.name}),O.jsxs("div",{className:"text-xxs text-muted flex items-center gap-3 mt-0.5",children:[O.jsxs("code",{className:"font-mono text-faint",children:[S.prefix,"…"]}),O.jsxs("span",{children:["created ",s0(new Date(S.createdAt),{addSuffix:!0})]}),O.jsx("span",{children:S.lastUsedAt?`used ${s0(new Date(S.lastUsedAt),{addSuffix:!0})}`:"never used"})]})]}),S.plaintext?O.jsxs("button",{type:"button",onClick:()=>k({id:S.id,plaintext:S.plaintext}),className:`btn gap-1.5 ${C?"!border-emerald-500/30 !text-emerald-600":""}`,title:"Copy full token",children:[C?O.jsx(Nc,{size:11}):O.jsx(Wy,{size:11}),C?"Copied":"Copy token"]}):O.jsx("span",{className:"text-xxs text-faint border border-line rounded px-2 py-1",title:"Full token is unavailable for tokens created before recoverable storage was enabled.",children:"Unavailable"}),O.jsx("button",{type:"button",className:"text-faint hover:text-danger p-1 -m-1",disabled:u!==null,onClick:()=>w(S.id,S.name),title:u===S.id?"Revoking":"Revoke",children:u===S.id?O.jsx("span",{className:"text-xxs text-muted",children:"Revoking…"}):O.jsx(KT,{size:12})})]},S.id)})]})]})}function uU({anchor:n,projectIds:e}){const t=Xx("day",n),{data:r}=Sa({from:t.from.toISOString(),to:t.to.toISOString(),projectIds:e??null,includeBacklog:!1,includeDone:!0}),{data:i}=sr(),s=N.useMemo(()=>Ca(i),[i]),{open:l}=Dt(),o=(r==null?void 0:r.overdue)??[],u=((r==null?void 0:r.scheduled)??[]).slice().sort(pp),h=fp(n);return O.jsx("div",{className:"h-full overflow-y-auto scrollbar-thin",children:O.jsxs("div",{className:"max-w-4xl mx-auto py-4",children:[h&&o.length>0&&O.jsx(ZP,{title:"Overdue",count:o.length,accent:"text-danger",tasks:o,projectMap:s}),O.jsx(ZP,{title:h?"Today":un(n,"EEEE"),count:u.length,accent:"text-ink",tasks:u,projectMap:s,emptyAction:O.jsx("button",{className:"text-accent text-xs hover:underline",onClick:()=>l({kind:"quick-create"}),children:"+ add a task for this day"})})]})})}function ZP({title:n,count:e,accent:t,tasks:r,projectMap:i,emptyAction:s}){return O.jsxs("section",{className:"mb-6",children:[O.jsxs("div",{className:"px-4 py-1.5 flex items-baseline gap-2 sticky top-0 bg-bg z-10",children:[O.jsx("h2",{className:`text-xs font-semibold ${t}`,children:n}),O.jsx("span",{className:"text-xxs text-faint tabular-nums",children:e})]}),r.length===0?O.jsx("div",{className:"px-4 py-2 text-xs text-muted",children:s??"Nothing here."}):O.jsx("div",{className:"bg-surface border-y border-lineSoft",children:r.map(l=>O.jsx(dp,{task:l,project:l.projectId?i.get(l.projectId):void 0},l.id))})]})}function cU({projectIds:n,collapsed:e,onToggle:t}){const{data:r}=Sa({projectIds:n??null,includeBacklog:!0,includeDone:!1}),{data:i}=sr(),s=N.useMemo(()=>Ca(i),[i]),l=((r==null?void 0:r.backlog)??[]).filter(o=>o.status!=="rejected");return e?O.jsxs("button",{className:"shrink-0 w-8 border-l border-line bg-sidebar/50 hover:bg-sidebar flex flex-col items-center pt-2 gap-2 group",onClick:t,title:"Expand Inbox",children:[O.jsx(Td,{size:14,className:"text-muted group-hover:text-ink"}),l.length>0&&O.jsx("div",{className:"text-xxs text-muted bg-surface border border-line rounded-full w-5 h-5 flex items-center justify-center",children:l.length})]}):O.jsxs("aside",{className:"shrink-0 w-72 border-l border-line bg-surface flex flex-col",children:[O.jsxs("div",{className:"px-3 h-9 flex items-center justify-between border-b border-lineSoft",children:[O.jsxs("div",{className:"flex items-center gap-2 text-muted",children:[O.jsx(Td,{size:12}),O.jsx("h2",{className:"text-xs font-medium text-ink2",children:"Inbox"}),O.jsx("span",{className:"text-xxs text-faint tabular-nums",children:l.length})]}),O.jsx("button",{onClick:t,className:"btn-ghost btn !h-6 !w-6 !p-0",title:"Collapse",children:"→"})]}),O.jsx("div",{className:"flex-1 overflow-y-auto scrollbar-thin",children:l.length===0?O.jsxs("div",{className:"text-xs text-muted text-center py-8 px-4",children:["No tasks without due date.",O.jsx("div",{className:"text-faint mt-1",children:"Tasks without due date appear here."})]}):l.map(o=>O.jsx(dp,{task:o,project:o.projectId?s.get(o.projectId):void 0,compact:!0},o.id))})]})}function PE({task:n,project:e}){const t=Vi(),r=n.dueAt&&new Date(n.dueAt).getTime()<Date.now()&&n.status!=="done"&&n.status!=="in_progress";return O.jsxs("div",{role:"button",tabIndex:0,draggable:!0,onDragStart:i=>{i.dataTransfer.setData("text/task-id",n.id),i.dataTransfer.effectAllowed="move",i.stopPropagation()},onClick:()=>t.open(n.id),onKeyDown:i=>{i.key!=="Enter"&&i.key!==" "||(i.preventDefault(),t.open(n.id))},className:`group w-full text-left flex items-center gap-1.5 pl-1 pr-1.5 py-1 rounded text-xs hover:bg-sidebarHover transition-colors cursor-grab active:cursor-grabbing ${r?"bg-danger/5":""}`,title:e?`${e.key} · ${vn(n)}`:vn(n),children:[O.jsx("span",{className:"w-[2px] self-stretch rounded-sm shrink-0",style:{backgroundColor:(e==null?void 0:e.color)??"#a8a8af"}}),O.jsx(cp,{task:n,size:11}),O.jsx("span",{className:`truncate flex-1 min-w-0 ${n.status==="done"?"line-through text-muted":n.status==="rejected"?"text-muted":fi(n)?"italic text-muted":"text-ink2"}`,children:vn(n)}),n.priority!=="none"&&O.jsx(aa,{priority:n.priority,size:11})]})}const hU=["Mon","Tue","Wed","Thu","Fri","Sat","Sun"];function fU({anchor:n,projectIds:e}){const t=Xx("month",n),r=SE(t.from,t.to),{data:i}=Sa({from:t.from.toISOString(),to:t.to.toISOString(),projectIds:e??null,includeBacklog:!1,includeDone:!0}),{data:s}=sr(),l=N.useMemo(()=>Ca(s),[s]),o=N.useMemo(()=>bE((i==null?void 0:i.scheduled)??[]),[i]);return O.jsxs("div",{className:"h-full flex flex-col",children:[O.jsx("div",{className:"grid grid-cols-7 border-b border-lineSoft bg-sidebar/50",children:hU.map(u=>O.jsx("div",{className:"px-2 py-1 text-xxs uppercase tracking-wider text-muted text-center",children:u},u))}),O.jsx("div",{className:"flex-1 grid grid-cols-7 grid-rows-6 bg-line/30 gap-px overflow-y-auto scrollbar-thin",children:r.map(u=>{const h=o.get(wE(u))??[],f=!IY(u,n),p=fp(u);return O.jsx(dU,{day:u,tasks:h,projectMap:l,outOfMonth:f,today:p},u.toISOString())})})]})}function dU({day:n,tasks:e,projectMap:t,outOfMonth:r,today:i}){const{open:s}=Dt(),l=zl(),[o,u]=N.useState(!1),h=e.slice().sort(pp),f=h.filter(k=>k.status==="done").length,p=h.length,m=p>0&&f===p;function y(k){k.preventDefault(),u(!1);const b=k.dataTransfer.getData("text/task-id");if(!b)return;const w=new Date(n);w.setHours(12,0,0,0),l.mutate({id:b,fields:{dueAt:w.toISOString()}})}return O.jsxs("div",{className:`group bg-surface p-1 min-h-[112px] flex flex-col transition-colors ${r?"opacity-50":""} ${o?"ring-2 ring-accent ring-inset bg-accentSoft/40":i?"ring-1 ring-accent ring-inset bg-accentSoft/30":""}`,onDragOver:k=>{k.preventDefault(),o||u(!0)},onDragLeave:()=>u(!1),onDrop:y,children:[O.jsxs("div",{className:"flex items-center justify-between mb-1 px-1",children:[O.jsxs("div",{className:"flex items-baseline gap-1.5 min-w-0",children:[O.jsx("span",{className:`text-xs tabular-nums ${i?"font-semibold text-accent":"text-muted"}`,children:un(n,"d")}),p>0&&O.jsxs("span",{className:`text-xxs tabular-nums ${m?"text-statusDone font-medium":"text-faint"}`,title:`${f} done · ${p} total`,children:[f,"/",p]})]}),O.jsx("button",{className:"text-xs text-faint hover:text-accent opacity-0 group-hover:opacity-100 transition-opacity",onClick:()=>s({kind:"quick-create"}),title:"Add task",children:"+"})]}),O.jsxs("div",{className:"flex-1 space-y-0.5 min-h-0 overflow-hidden",children:[h.slice(0,4).map(k=>O.jsx(PE,{task:k,project:k.projectId?t.get(k.projectId):void 0},k.id)),h.length>4&&O.jsxs("div",{className:"text-xxs text-muted pl-1",children:["+",h.length-4]})]})]})}function pU({view:n,setView:e,anchor:t,setAnchor:r,projectIds:i,setProjectIds:s}){var h;const{data:l}=sr(),{open:o}=Dt(),u=i?i.length===1?((h=l==null?void 0:l.find(f=>f.id===i[0]))==null?void 0:h.key)??"1 project":`${i.length} projects`:"All projects";return O.jsx("div",{className:"border-b border-line bg-surface",children:O.jsxs("div",{className:"flex items-center justify-between h-11 px-3",children:[O.jsxs("div",{className:"flex items-center gap-3",children:[O.jsx("h1",{className:"text-xs font-semibold text-ink",children:"Tasks"}),O.jsx("div",{className:"seg",children:["day","week","month"].map(f=>O.jsx("button",{onClick:()=>e(f),"data-active":n===f,className:"capitalize",children:f},f))}),O.jsxs("div",{className:"flex items-center gap-1 ml-1",children:[O.jsx("button",{onClick:()=>r(OO(n,t,-1)),className:"btn btn-ghost !h-6 !w-6 !p-0",title:"Previous",children:O.jsx(zT,{size:12})}),O.jsx("button",{onClick:()=>r(OO(n,t,0)),className:"btn !h-6 px-2 text-xxs",title:"Today",children:"Today"}),O.jsx("button",{onClick:()=>r(OO(n,t,1)),className:"btn btn-ghost !h-6 !w-6 !p-0",title:"Next",children:O.jsx(ZT,{size:12})}),O.jsx("div",{className:"ml-2 text-xs font-medium text-ink2 tabular-nums",children:ZY(n,t)})]})]}),O.jsxs("div",{className:"flex items-center gap-1.5",children:[O.jsx(mU,{projects:l??[],projectIds:i,setProjectIds:s,label:u}),O.jsxs("button",{className:"btn btn-primary",onClick:()=>o({kind:"quick-create"}),title:"New task (c)",children:[O.jsx(rp,{size:11}),O.jsx("span",{className:"text-xs",children:"Task"}),O.jsx("kbd",{className:"!bg-white/15 !border-white/25 !text-white",children:"c"})]})]})]})})}function mU({projects:n,projectIds:e,setProjectIds:t,label:r}){return O.jsxs("details",{className:"relative",children:[O.jsxs("summary",{className:"btn list-none cursor-pointer",children:[O.jsx(zB,{size:11}),O.jsx("span",{className:"text-xs",children:r})]}),O.jsxs("div",{className:"popover top-9 right-0 w-56 px-1 py-1.5",children:[O.jsxs("button",{className:`popover-item ${e?"":"bg-accentSoft text-accentText"}`,onClick:()=>t(null),children:[O.jsx("span",{children:"All projects"}),!e&&O.jsx("span",{className:"ml-auto text-faint",children:"✓"})]}),O.jsx("div",{className:"divider my-1"}),n.map(i=>{const s=(e==null?void 0:e.includes(i.id))??!1;return O.jsxs("label",{className:"popover-item gap-2 cursor-pointer",children:[O.jsx("input",{type:"checkbox",className:"cursor-pointer",checked:s,onChange:()=>{if(!e)t([i.id]);else if(s){const l=e.filter(o=>o!==i.id);t(l.length?l:null)}else t([...e,i.id])}}),O.jsx("span",{className:"font-mono text-xxs text-faint tabular-nums",children:i.key}),O.jsx("span",{className:"text-ink2 truncate",children:i.name})]},i.id)})]})]})}function gU({anchor:n,projectIds:e}){const t=Xx("week",n),r=SE(t.from,t.to),i=hp(r[r.length-1],1),s=[...r,i],l=new Date(i);l.setHours(23,59,59,999);const{data:o}=Sa({from:t.from.toISOString(),to:l.toISOString(),projectIds:e??null,includeBacklog:!1,includeDone:!0}),{data:u}=sr(),h=N.useMemo(()=>Ca(u),[u]),f=N.useMemo(()=>bE((o==null?void 0:o.scheduled)??[]),[o]),p=s.slice(0,4),m=s.slice(4);return O.jsxs("div",{className:"h-full flex flex-col bg-bg",children:[O.jsx(XP,{days:p,byDay:f,projectMap:h,anchor:n}),O.jsx(XP,{days:m,byDay:f,projectMap:h,anchor:n})]})}function XP({days:n,byDay:e,projectMap:t,anchor:r}){return O.jsx("div",{className:"flex-1 min-h-0 flex border-b border-line last:border-b-0",children:n.map(i=>{const s=e.get(wE(i))??[],l=!DY(i,r,{weekStartsOn:1});return O.jsx(OU,{day:i,tasks:s,projectMap:t,outOfWeek:l},i.toISOString())})})}function OU({day:n,tasks:e,projectMap:t,outOfWeek:r}){const i=fp(n),{open:s}=Dt(),l=zl(),o=e.slice().sort(pp),u=o.filter(m=>m.status==="done").length,h=o.length,f=h>0&&u===h;function p(m){m.preventDefault();const y=m.dataTransfer.getData("text/task-id");if(!y)return;const k=new Date(n);k.setHours(12,0,0,0),l.mutate({id:y,fields:{dueAt:k.toISOString()}})}return O.jsxs("div",{className:`flex-1 min-w-0 border-r border-lineSoft last:border-r-0 flex flex-col group/col ${i?"bg-accentSoft/30":r?"bg-sidebar/40":"bg-surface"}`,onDragOver:m=>m.preventDefault(),onDrop:p,children:[O.jsxs("div",{className:"px-3 py-1.5 flex items-baseline justify-between border-b border-lineSoft",children:[O.jsxs("div",{className:"flex items-baseline gap-2 min-w-0",children:[O.jsx("span",{className:"text-xxs uppercase tracking-wider text-muted",children:un(n,"EEE")}),O.jsx("span",{className:`text-sm tabular-nums font-semibold ${i?"text-accent":r?"text-muted":"text-ink2"}`,children:un(n,"d")}),h>0&&O.jsxs("span",{className:`text-xxs tabular-nums ${f?"text-statusDone font-medium":"text-faint"}`,title:`${u} done · ${h} total`,children:[u,"/",h]}),r&&O.jsx("span",{className:"text-xxs text-faint italic",children:"next"})]}),O.jsx("button",{className:"text-faint hover:text-accent text-xs opacity-0 group-hover/col:opacity-100",title:"Add task",onClick:()=>s({kind:"quick-create"}),children:"+"})]}),O.jsx("div",{className:"flex-1 overflow-y-auto scrollbar-thin p-1.5 space-y-1",children:o.length===0?O.jsx("div",{className:"text-xxs text-faint px-1 py-0.5",children:"—"}):o.map(m=>O.jsx(PE,{task:m,project:m.projectId?t.get(m.projectId):void 0},m.id))})]})}function yU(){const[n,e]=N.useState("week"),[t,r]=N.useState(()=>new Date),[i,s]=N.useState(null),[l,o]=N.useState(!1);return O.jsxs("div",{className:"h-full flex flex-col",children:[O.jsx(pU,{view:n,setView:e,anchor:t,setAnchor:r,projectIds:i,setProjectIds:s}),O.jsxs("div",{className:"flex-1 min-h-0 flex",children:[O.jsxs("div",{className:"flex-1 min-w-0 overflow-hidden bg-bg",children:[n==="day"&&O.jsx(uU,{anchor:t,projectIds:i}),n==="week"&&O.jsx(gU,{anchor:t,projectIds:i}),n==="month"&&O.jsx(fU,{anchor:t,projectIds:i})]}),O.jsx(cU,{projectIds:i,collapsed:l,onToggle:()=>o(u=>!u)})]})]})}function xU(){const n=new Date,{data:e}=sr(),t=N.useMemo(()=>Ca(e),[e]),r=N.useMemo(()=>{const h=new Date(n);h.setHours(0,0,0,0);const f=new Date(n);return f.setHours(23,59,59,999),{from:h.toISOString(),to:f.toISOString()}},[]),{data:i,isLoading:s}=Sa({from:r.from,to:r.to,includeBacklog:!1,includeDone:!0}),{open:l}=Dt(),o=((i==null?void 0:i.overdue)??[]).filter(h=>h.status!=="rejected"),u=((i==null?void 0:i.scheduled)??[]).slice().sort(pp);return O.jsx("div",{className:"h-full overflow-y-auto scrollbar-thin",children:O.jsxs("div",{className:"max-w-3xl mx-auto px-6 py-6 space-y-6",children:[O.jsxs("header",{className:"flex items-baseline gap-3",children:[O.jsx(HT,{size:18,className:"text-accent"}),O.jsx("h1",{className:"text-lg font-semibold",children:"Today"}),O.jsx("span",{className:"text-xs text-muted",children:un(n,"EEEE, MMM d")})]}),s&&O.jsx("div",{className:"text-sm text-muted",children:"Loading…"}),!s&&O.jsxs(O.Fragment,{children:[O.jsx(BP,{title:"Overdue",count:o.length,accent:"text-danger",tasks:o,projectMap:t}),O.jsx(BP,{title:fp(n)?"Today":un(n,"EEEE"),count:u.length,accent:"text-ink",tasks:u,projectMap:t,emptyAction:O.jsx("button",{className:"text-accent text-xs hover:underline",onClick:()=>l({kind:"quick-create"}),children:"+ add a task"})})]})]})})}function BP({title:n,count:e,accent:t,tasks:r,projectMap:i,emptyAction:s}){if(r.length===0&&!s)return null;const l=new Map;for(const o of r){const u=o.projectId??null;l.has(u)||l.set(u,[]),l.get(u).push(o)}return O.jsxs("section",{className:"space-y-1.5",children:[O.jsxs("div",{className:"flex items-baseline gap-2",children:[O.jsx("h2",{className:`text-xs font-semibold ${t}`,children:n}),O.jsx("span",{className:"text-xxs text-faint tabular-nums",children:e})]}),r.length===0?O.jsx("div",{className:"text-xs text-muted py-1",children:s??"Nothing here."}):O.jsx("div",{className:"border border-line rounded-md overflow-hidden bg-surface",children:Array.from(l.entries()).map(([o,u])=>{const h=o?i.get(o):void 0;return O.jsxs("div",{children:[O.jsxs("div",{className:"px-3 py-1 border-b border-lineSoft bg-sidebar/40 flex items-center gap-1.5 text-xxs",children:[h?O.jsxs(O.Fragment,{children:[O.jsx(Fs,{color:h.color,icon:h.icon,size:10}),O.jsx("span",{className:"font-mono tabular-nums",style:{color:h.color},children:h.key}),O.jsx("span",{className:"text-muted truncate",children:h.name})]}):O.jsx("span",{className:"text-faint",children:"no project"}),O.jsx("span",{className:"text-faint ml-auto tabular-nums",children:u.length})]}),u.map(f=>O.jsx(dp,{task:f,project:h},f.id))]},o??"_none")})})]})}function kU(){return O.jsxs(w5,{children:[O.jsxs(a5,{children:[O.jsx(dr,{path:"/login",element:O.jsx(qY,{})}),O.jsxs(dr,{element:O.jsx(hF,{}),children:[O.jsx(dr,{path:"/",element:O.jsx(yU,{})}),O.jsx(dr,{path:"/today",element:O.jsx(xU,{})}),O.jsx(dr,{path:"/inbox",element:O.jsx(BY,{})}),O.jsx(dr,{path:"/dashboard",element:O.jsx(kF,{})}),O.jsx(dr,{path:"/settings",element:O.jsx(eU,{})}),O.jsx(dr,{path:"/p/:key",element:O.jsx(GY,{})}),O.jsx(dr,{path:"/p/:key/e/:id",element:O.jsx(bF,{})}),O.jsx(dr,{path:"/p/:key/agents-md",element:O.jsx(xF,{})}),O.jsx(dr,{path:"/search",element:O.jsx(KY,{})})]})]}),O.jsx(OF,{})]})}const vU=new UA({defaultOptions:{queries:{staleTime:1e4,gcTime:5*6e4,retry:1,refetchOnWindowFocus:!0}}});pR.createRoot(document.getElementById("root")).render(O.jsx(h2.StrictMode,{children:O.jsx(GA,{client:vU,children:O.jsx(O5,{children:O.jsx(kU,{})})})}));
@@ -8,7 +8,7 @@
8
8
  <link rel="preconnect" href="https://fonts.googleapis.com" />
9
9
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
10
10
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
11
- <script type="module" crossorigin src="/assets/index-C3jrWZov.js"></script>
11
+ <script type="module" crossorigin src="/assets/index-D2D52jSx.js"></script>
12
12
  <link rel="stylesheet" crossorigin href="/assets/index-DBDF6wZm.css">
13
13
  </head>
14
14
  <body>