heyio 0.17.2 β†’ 0.18.0

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
@@ -313,8 +313,13 @@ npm run tui
313
313
 
314
314
  # Run the daemon directly
315
315
  npm run daemon
316
+
317
+ # Run the test suite
318
+ npm test
316
319
  ```
317
320
 
321
+ Tests use the Node.js built-in test runner with [tsx](https://github.com/privatenumber/tsx) for TypeScript support. Test files live alongside source files as `*.test.ts`.
322
+
318
323
  See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed development guidelines.
319
324
 
320
325
  ## πŸ“„ License
@@ -65,7 +65,9 @@ export async function startApiServer() {
65
65
  supabaseAnonKey: config.supabaseAnonKey ?? null,
66
66
  });
67
67
  });
68
- // Skills read endpoints β€” public (no auth required; read-only local filesystem)
68
+ // Apply auth middleware β€” all routes below require a valid JWT
69
+ api.use(requireAuth);
70
+ // Skills read endpoints
69
71
  api.get("/skills", (_req, res) => {
70
72
  try {
71
73
  const skills = listSkills();
@@ -97,7 +99,7 @@ export async function startApiServer() {
97
99
  res.status(500).json({ error: e instanceof Error ? e.message : String(e) });
98
100
  }
99
101
  });
100
- // Inbox read endpoints β€” public (nav badge needs count without auth timing issues)
102
+ // Inbox read endpoints
101
103
  api.get("/inbox/count", (_req, res) => {
102
104
  try {
103
105
  const count = countInboxEntries();
@@ -118,11 +120,11 @@ export async function startApiServer() {
118
120
  res.status(500).json({ error: e instanceof Error ? e.message : String(e) });
119
121
  }
120
122
  });
121
- // Status endpoint β€” public (non-sensitive version/uptime info)
123
+ // Status endpoint
122
124
  api.get("/status", (_req, res) => {
123
125
  res.json({ version: IO_VERSION, uptime: process.uptime() });
124
126
  });
125
- // Notifications read endpoint β€” public (local-only app, nav badge needs data without auth race)
127
+ // Notifications endpoint
126
128
  api.get("/notifications", (_req, res) => {
127
129
  try {
128
130
  const unreadOnly = _req.query.unread === "true";
@@ -155,7 +157,7 @@ export async function startApiServer() {
155
157
  res.status(500).json({ error: "Failed to list notifications" });
156
158
  }
157
159
  });
158
- // SSE events β€” public (AppNav subscribes on load before auth resolves)
160
+ // SSE events endpoint
159
161
  api.get("/events", (req, res) => {
160
162
  res.setHeader("Content-Type", "text/event-stream");
161
163
  res.setHeader("Cache-Control", "no-cache");
@@ -166,8 +168,6 @@ export async function startApiServer() {
166
168
  sseConnections.delete(res);
167
169
  });
168
170
  });
169
- // Apply auth middleware to all subsequent routes
170
- api.use(requireAuth);
171
171
  // Install a skill from pasted SKILL.md content (issue #117)
172
172
  api.post("/skills/paste", (req, res) => {
173
173
  const { content: skillContent, slug } = req.body;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "heyio",
3
- "version": "0.17.2",
3
+ "version": "0.18.0",
4
4
  "description": "IO β€” a personal AI assistant built on the GitHub Copilot SDK",
5
5
  "bin": {
6
6
  "io": "dist/index.js"
@@ -0,0 +1 @@
1
+ import{d as L,o as Z,c as n,a,t as i,b as m,e as f,f as p,F as H,r as E,g as u,h as g,i as l,w as T,u as V,j as S,_ as v}from"./index-6BKFZclJ.js";const j={class:"flex flex-col h-full p-3 sm:p-6"},D={class:"flex justify-between items-center mb-6"},C={key:0,class:"text-[10px] font-mono text-accent bg-accent/10 border border-accent/20 px-2 py-0.5 rounded-full"},N={key:0,class:"flex-1 flex items-center justify-center"},$={key:1,class:"flex-1 flex flex-col items-center justify-center"},z={class:"w-14 h-14 rounded-xl bg-surface-2 border border-edge flex items-center justify-center mb-4"},F={key:2,class:"space-y-2 overflow-y-auto flex-1 pr-1"},A=["onClick"],B={class:"flex-1 min-w-0"},I={class:"flex items-start justify-between gap-2"},P={class:"text-sm font-semibold text-txt-primary leading-snug"},W={class:"text-[10px] text-txt-muted font-mono shrink-0 mt-0.5"},q={key:0,class:"text-xs text-txt-secondary mt-1 line-clamp-2 leading-relaxed"},G=["onClick","disabled"],J={key:0,class:"px-4 pb-4"},K=["innerHTML"],O={key:3,class:"mt-3 flex items-center gap-2 text-sm text-red-400 bg-red-500/10 border border-red-500/20 rounded-xl px-3.5 py-2.5"},U=L({__name:"InboxView",setup(Q){const o=u([]),h=u(!0),r=u(new Set),d=u(new Set),c=u(null);function b(t){try{const e=t.includes("T")||t.endsWith("Z")?t:t.replace(" ","T")+"Z";return new Date(e).toLocaleString()}catch{return t}}function _(t){return t.replace(/[#*`_~[\]()]/g,"").slice(0,200)}function w(t){const e=new Set(r.value);e.has(t)?e.delete(t):e.add(t),r.value=e}async function y(){h.value=!0,c.value=null;try{const t=await g("/api/inbox");if(t.ok){const e=await t.json();o.value=e.entries??[]}}catch{}h.value=!1}async function k(t){if(!window.confirm("Delete this inbox entry?"))return;const e=new Set(d.value);e.add(t),d.value=e;try{const s=await g(`/api/inbox/${t}`,{method:"DELETE"});if(s.ok){o.value=o.value.filter(M=>M.id!==t);const x=new Set(r.value);x.delete(t),r.value=x}else c.value=`Failed to delete entry (HTTP ${s.status})`}catch(s){c.value=s instanceof Error?s.message:"Delete failed"}finally{const s=new Set(d.value);s.delete(t),d.value=s}}return Z(y),(t,e)=>(l(),n("div",j,[a("div",D,[e[0]||(e[0]=a("div",null,[a("h2",{class:"text-xl font-semibold text-txt-primary tracking-tight"},"Inbox"),a("p",{class:"text-xs text-txt-muted mt-0.5"},"Messages & incoming items")],-1)),o.value.length>0?(l(),n("span",C,i(o.value.length)+" item"+i(o.value.length===1?"":"s"),1)):m("",!0)]),h.value?(l(),n("div",N,[...e[1]||(e[1]=[a("div",{class:"flex items-center gap-3 text-txt-muted text-sm"},[a("div",{class:"w-1.5 h-1.5 rounded-full bg-accent animate-pulse"}),f(" Loading… ")],-1)])])):o.value.length===0?(l(),n("div",$,[a("div",z,[p(v,{paths:'<path d="M6 3a3 3 0 0 0-3 3v8a3 3 0 0 0 3 3h8a3 3 0 0 0 3-3V6a3 3 0 0 0-3-3H6Zm10 7h-3.5a.5.5 0 0 0-.5.5v.01a1.75 1.75 0 0 1-.03.3c-.04.2-.1.46-.23.72-.13.25-.3.49-.57.66-.26.18-.63.31-1.17.31-.54 0-.9-.13-1.17-.3a1.7 1.7 0 0 1-.57-.67A2.57 2.57 0 0 1 8 10.5v-.01a.5.5 0 0 0-.5-.5H4V6c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2v4ZM4 11h3.05c.05.26.14.62.32.97.18.38.47.76.9 1.06.45.29 1.02.47 1.73.47s1.28-.18 1.72-.47c.44-.3.73-.68.91-1.06.18-.35.27-.7.32-.97H16v3a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-3Z"/>',size:28,class:"text-txt-muted"})]),e[2]||(e[2]=a("p",{class:"text-txt-muted text-sm font-medium"},"Inbox is empty",-1)),e[3]||(e[3]=a("p",{class:"text-txt-muted/60 text-xs mt-1"},"No messages right now",-1))])):(l(),n("ul",F,[(l(!0),n(H,null,E(o.value,s=>(l(),n("li",{key:s.id,class:"group bg-surface-2/50 border border-edge rounded-xl hover:border-edge-bright hover:shadow-card transition-all duration-200 overflow-hidden animate-fade-in glow-inner"},[a("div",{class:"flex items-start gap-3 p-4 cursor-pointer",onClick:x=>w(s.id)},[e[4]||(e[4]=a("div",{class:"mt-1.5 w-1.5 h-1.5 rounded-full bg-accent shadow-glow-sm shrink-0"},null,-1)),a("div",B,[a("div",I,[a("span",P,i(s.title),1),a("span",W,i(b(s.created_at)),1)]),r.value.has(s.id)?m("",!0):(l(),n("p",q,i(_(s.body)),1))]),a("button",{onClick:T(x=>k(s.id),["stop"]),disabled:d.value.has(s.id),class:"opacity-0 group-hover:opacity-100 shrink-0 p-1.5 rounded-lg text-txt-muted hover:text-red-400 hover:bg-red-500/10 border border-transparent hover:border-red-500/20 disabled:opacity-30 transition-all duration-200",title:"Delete entry"},[p(v,{paths:'<path d="M8.5 4h3a1.5 1.5 0 0 0-3 0Zm-1 0a2.5 2.5 0 0 1 5 0h5a.5.5 0 0 1 0 1h-1.05l-1.2 10.34A3 3 0 0 1 12.27 18H7.73a3 3 0 0 1-2.98-2.66L3.55 5H2.5a.5.5 0 0 1 0-1h5ZM5.74 15.23A2 2 0 0 0 7.73 17h4.54a2 2 0 0 0 1.99-1.77L15.44 5H4.56l1.18 10.23ZM8.5 7.5c.28 0 .5.22.5.5v6a.5.5 0 0 1-1 0V8c0-.28.22-.5.5-.5ZM12 8a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V8Z"/>',size:14})],8,G)],8,A),r.value.has(s.id)?(l(),n("div",J,[a("div",{class:"text-sm text-txt-secondary bg-surface-0/60 rounded-xl p-4 border border-edge/50 wiki-content leading-relaxed",innerHTML:V(S)(s.body)},null,8,K)])):m("",!0)]))),128))])),c.value?(l(),n("div",O,[p(v,{paths:'<path d="m4.09 4.22.06-.07a.5.5 0 0 1 .63-.06l.07.06L10 9.29l5.15-5.14a.5.5 0 0 1 .63-.06l.07.06c.18.17.2.44.06.63l-.06.07L10.71 10l5.14 5.15c.18.17.2.44.06.63l-.06.07a.5.5 0 0 1-.63.06l-.07-.06L10 10.71l-5.15 5.14a.5.5 0 0 1-.63.06l-.07-.06a.5.5 0 0 1-.06-.63l.06-.07L9.29 10 4.15 4.85a.5.5 0 0 1-.06-.63l.06-.07-.06.07Z"/>',size:16,class:"shrink-0"}),f(" "+i(c.value),1)])):m("",!0)]))}});export{U as default};