claude-code-session-manager 0.103.0 → 0.104.1

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.
Files changed (33) hide show
  1. package/README.md +6 -0
  2. package/dist/assets/{DataModel-Bgw2VqmP.js → DataModel-BHcPa2nA.js} +1 -1
  3. package/dist/assets/{History-De6GeUyP.js → History-BP6KKda_.js} +1 -1
  4. package/dist/assets/{Hooks-CgpCEy1J.js → Hooks-CnJnddP6.js} +1 -1
  5. package/dist/assets/{Library-D90JNcU4.js → Library-BprXNJCG.js} +1 -1
  6. package/dist/assets/{MarkdownEditor-BaGbbB4D.js → MarkdownEditor-1KlkRAqT.js} +1 -1
  7. package/dist/assets/{McpServers-DtzyQXmJ.js → McpServers-FUDN7EnU.js} +1 -1
  8. package/dist/assets/{Memory-CrkSYaZs.js → Memory-DryJweXu.js} +1 -1
  9. package/dist/assets/{Permissions-C9R1FK2q.js → Permissions-Df-LWvdk.js} +1 -1
  10. package/dist/assets/{Plugins-Dg-pT2P9.js → Plugins-CIUOw9B2.js} +2 -2
  11. package/dist/assets/{ProvenanceBadge-D6DNK8MW.js → ProvenanceBadge-6Hj42klQ.js} +1 -1
  12. package/dist/assets/{SaveBar-lMVYV4IY.js → SaveBar-xSfjUPiu.js} +1 -1
  13. package/dist/assets/{Scheduler-DhRGmvfB.js → Scheduler-Beh3Vj-Z.js} +1 -1
  14. package/dist/assets/{ScopeSwitcher-CrmoviYs.js → ScopeSwitcher-9R1ANwns.js} +1 -1
  15. package/dist/assets/{Settings-BTyqKJWr.js → Settings-gkp0WfEm.js} +1 -1
  16. package/dist/assets/{SkillReferenceGraph-Bi1KZT00.js → SkillReferenceGraph-CYLTGabR.js} +1 -1
  17. package/dist/assets/{Skills-Cw31oTfc.js → Skills-Dw5Am-f-.js} +1 -1
  18. package/dist/assets/{SystemPrompt-D_QGdY-s.js → SystemPrompt-B3GwTLqh.js} +1 -1
  19. package/dist/assets/{TagLibrary-BhflRcxf.js → TagLibrary-Dj46gOG2.js} +1 -1
  20. package/dist/assets/{TiptapBody-DmzoRaV0.js → TiptapBody-l-BMtrPd.js} +1 -1
  21. package/dist/assets/{Toggle-BaBCNHq8.js → Toggle-Bj2Ia7AE.js} +1 -1
  22. package/dist/assets/{ViewTabs-DTrlvEUf.js → ViewTabs-BQ_HbQFq.js} +1 -1
  23. package/dist/assets/{index-ByE44RSO.js → index-DbR91Z5j.js} +3 -3
  24. package/dist/assets/{settingsSchema-BLYLb3ul.js → settingsSchema-cR833AB2.js} +1 -1
  25. package/dist/index.html +1 -1
  26. package/package.json +27 -10
  27. package/scripts/scheduler-mcp-server.cjs +47 -0
  28. package/src/main/build-info.json +4 -4
  29. package/src/main/index.cjs +2 -0
  30. package/src/main/lib/macroAdminRoutes.cjs +111 -0
  31. package/src/main/lib/mcpToolCatalog.cjs +36 -1
  32. package/src/main/lib/projectHomeAdminRoutes.cjs +1 -0
  33. package/src/main/otel.cjs +7 -7
@@ -1 +1 @@
1
- import{ax as b,ai as n,S as N,aO as O,av as K}from"./index-ByE44RSO.js";function T({node:e,targetScope:r,onOverride:s,schema:a,rootLabel:m}){const[f,x]=b.useState(""),[u,o]=b.useState(!0),g=[],d=e.kind==="object"&&Object.keys(e.children).length===0,y=((a==null?void 0:a.rootKeys())??[]).length>0;return n.jsxs("div",{className:"h-full flex flex-col",children:[n.jsxs("div",{className:"shrink-0 border-b border-line bg-bg-elev px-3 py-1.5 flex items-center gap-2 text-xs",children:[n.jsxs("span",{className:"text-fg-faint",children:["merged · overrides → ",n.jsx("span",{className:"text-fg-dim",children:N[r].label})]}),y&&n.jsxs("label",{className:"flex items-center gap-1 text-fg-faint cursor-pointer",children:[n.jsx("input",{type:"checkbox",checked:u,onChange:t=>o(t.target.checked),className:"accent-accent"}),"show unset keys"]}),n.jsx("div",{className:"flex-1"}),n.jsx("input",{value:f,onChange:t=>x(t.target.value),placeholder:"filter keys or descriptions…",className:"bg-bg border border-line rounded px-2 py-0.5 text-xs text-fg w-56"})]}),n.jsx("div",{className:"flex-1 overflow-auto px-3 py-2 font-mono text-xs",children:d&&!u?n.jsx("div",{className:"text-fg-faint italic px-2 py-4",children:"no settings resolved — all scope files empty or missing"}):n.jsx(E,{node:e,path:g,label:m??"(root)",targetScope:r,onOverride:s,filter:f,depth:0,schema:a,showGhosts:u,defaultOpen:!0})})]})}function E(e){return e.node.kind==="object"?n.jsx(P,{...e,node:e.node}):e.node.kind==="array"?n.jsx(J,{...e,node:e.node}):n.jsx(R,{...e,node:e.node})}function A(e,r){return r.trim()?e.toLowerCase().includes(r.toLowerCase()):!0}function w(e,r,s){return!!(!s.trim()||e.some(a=>A(a,s))||r!=null&&r.description&&A(r.description,s))}function P({node:e,path:r,label:s,targetScope:a,onOverride:m,filter:f,depth:x,schema:u,showGhosts:o,defaultOpen:g}){const[d,h]=b.useState(g??x<2),y=(u==null?void 0:u.at(r))??null,t=new Set(Object.keys(e.children)),i=o?(y==null?void 0:y.knownChildren)??[]:[],c=Array.from(new Set([...t,...i])).sort(),l=b.useMemo(()=>f.trim()?c.filter(p=>{const v=(u==null?void 0:u.at([...r,p]))??null;return w([...r,p],v,f)?!0:t.has(p)?L(e.children[p],[...r,p],f,u):!1}):c,[c.join(","),f,e,r.join("."),u]);if(f.trim()&&l.length===0&&!w(r,y,f))return null;if(r.length===0)return n.jsx("div",{children:l.map(p=>j(p))});return n.jsxs("div",{children:[n.jsxs("div",{className:"flex items-center gap-1 py-0.5 hover:bg-bg-elev/50 rounded cursor-pointer",style:{paddingLeft:x*14},onClick:()=>h(!d),children:[n.jsx("span",{className:"text-fg-faint w-3 shrink-0",children:d?"▾":"▸"}),n.jsx("span",{className:"text-fg",children:s}),n.jsxs("span",{className:"text-fg-faint",children:[" {",t.size,i.length>t.size?`/${new Set([...t,...i]).size}`:"","}"]}),(y==null?void 0:y.description)&&n.jsxs("span",{className:"text-fg-faint truncate max-w-md",title:y.description,children:["— ",y.description]})]}),d&&l.map(p=>j(p))]});function j(p){if(t.has(p))return n.jsx(E,{node:e.children[p],path:[...r,p],label:p,targetScope:a,onOverride:m,filter:f,depth:x+1,schema:u,showGhosts:o},p);const v=(u==null?void 0:u.at([...r,p]))??null;return v?n.jsx(I,{path:[...r,p],label:p,info:v,targetScope:a,onSet:m,depth:x+1,filter:f},p):null}}function L(e,r,s,a){const m=(a==null?void 0:a.at(r))??null;if(w(r,m,s))return!0;if(e.kind!=="object")return!1;for(const f of Object.keys(e.children))if(L(e.children[f],[...r,f],s,a))return!0;return!1}function J({node:e,path:r,label:s,filter:a,depth:m,schema:f}){const[x,u]=b.useState(!0),o=(f==null?void 0:f.at(r))??null;return w(r,o,a)?n.jsxs("div",{children:[n.jsxs("div",{className:"flex items-center gap-1 py-0.5 hover:bg-bg-elev/50 rounded cursor-pointer",style:{paddingLeft:m*14},onClick:()=>u(!x),children:[n.jsx("span",{className:"text-fg-faint w-3 shrink-0",children:x?"▾":"▸"}),n.jsx("span",{className:"text-fg",children:s}),n.jsxs("span",{className:"text-fg-faint",children:[" [",e.items.length,"]"]}),n.jsx(S,{tone:"warn",children:"accumulated"}),(o==null?void 0:o.description)&&n.jsxs("span",{className:"text-fg-faint truncate max-w-md",title:o.description,children:["— ",o.description]})]}),x&&e.items.map((g,d)=>n.jsxs("div",{className:"flex items-start gap-2 py-0.5",style:{paddingLeft:(m+1)*14},children:[n.jsx("span",{className:"text-fg-faint w-3 shrink-0"}),n.jsxs("span",{className:"text-fg-faint",children:[d,":"]}),n.jsx("span",{className:"text-fg-dim truncate max-w-xl",children:k(g.value)}),n.jsx(C,{scope:g.fromScope})]},d))]}):null}function R({node:e,path:r,label:s,targetScope:a,onOverride:m,filter:f,depth:x,schema:u}){const[o,g]=b.useState(!1),d=(u==null?void 0:u.at(r))??null;if(!w(r,d,f))return null;const h=e.winner!==a,y=e.shadowed.length>0;return n.jsxs("div",{children:[n.jsxs("div",{className:"group flex items-center gap-2 py-0.5 hover:bg-bg-elev/50 rounded",style:{paddingLeft:x*14},children:[n.jsx("span",{className:`w-3 shrink-0 ${y?"text-fg-faint cursor-pointer":""}`,onClick:()=>y&&g(!o),children:y?o?"▾":"▸":""}),n.jsxs("span",{className:"text-fg",children:[s,":"]}),n.jsx("span",{className:"text-fg-dim truncate max-w-md",children:k(e.value)}),n.jsx(C,{scope:e.winner}),(d==null?void 0:d.deprecated)&&n.jsx(S,{tone:"warn",children:"deprecated"}),(d==null?void 0:d.default)!==void 0&&_(e.value,d.default)&&n.jsx(S,{tone:"dim",children:"= default"}),e.typeMismatch&&n.jsx("span",{className:"text-yellow-500/80",title:"shadowed scopes have a different value type",children:"⚠"}),(d==null?void 0:d.description)&&n.jsxs("span",{className:"text-fg-faint truncate max-w-md",title:d.description,children:["— ",d.description]}),n.jsx("div",{className:"flex-1"}),(d==null?void 0:d.enum)&&n.jsx(F,{values:d.enum}),n.jsx("button",{disabled:!h,onClick:()=>m(r,e.value),className:`opacity-0 group-hover:opacity-100 px-1.5 py-0 text-[10px] border rounded transition-opacity ${h?"border-accent/50 text-accent hover:bg-accent hover:text-bg":"border-line text-fg-faint cursor-not-allowed"}`,title:h?`copy into ${N[a].label} draft`:`already winning in ${N[a].label}`,children:"override"})]}),o&&e.shadowed.map((t,i)=>n.jsxs("div",{className:"flex items-center gap-2 py-0.5 text-fg-faint line-through",style:{paddingLeft:(x+1)*14+12},children:[n.jsx("span",{children:"shadowed:"}),n.jsx("span",{className:"truncate max-w-xl",children:k(t.value)}),n.jsx(C,{scope:t.scope,dim:!0})]},i))]})}function I({path:e,label:r,info:s,targetScope:a,onSet:m,depth:f,filter:x}){if(!w(e,s,x))return null;const u=s.default!==void 0?s.default:M(s.type),o=Array.isArray(s.type)?s.type.join("|"):s.type??"?";return n.jsxs("div",{className:"group flex items-center gap-2 py-0.5 hover:bg-bg-elev/50 rounded opacity-60",style:{paddingLeft:f*14},children:[n.jsx("span",{className:"w-3 shrink-0"}),n.jsx("span",{className:"text-fg-dim",children:r}),n.jsx(S,{tone:"dim",children:o}),s.required&&n.jsx(S,{tone:"warn",children:"required"}),s.default!==void 0&&n.jsxs("span",{className:"text-fg-faint",children:["default: ",k(s.default)]}),s.description&&n.jsxs("span",{className:"text-fg-faint truncate max-w-md",title:s.description,children:["— ",s.description]}),n.jsx("div",{className:"flex-1"}),s.enum&&n.jsx(F,{values:s.enum}),n.jsx("button",{onClick:()=>m(e,u),className:"opacity-0 group-hover:opacity-100 px-1.5 py-0 text-[10px] border border-accent/50 rounded text-accent hover:bg-accent hover:text-bg transition-opacity",title:`write to ${N[a].label} draft`,children:"set"})]})}function _(e,r){return e===r?!0:typeof e!=typeof r?!1:e&&r&&typeof e=="object"?JSON.stringify(e)===JSON.stringify(r):!1}function M(e){switch(Array.isArray(e)?e[0]:e){case"boolean":return!1;case"integer":case"number":return 0;case"string":return"";case"array":return[];case"object":return{};case"null":return null;default:return null}}function k(e){if(typeof e=="string")return JSON.stringify(e);if(e===null)return"null";if(typeof e=="object"){const r=JSON.stringify(e);return r.length>100?r.slice(0,100)+"…":r}return String(e)}function C({scope:e,dim:r}){const s=e==="user"?"bg-bg-hi text-fg-dim border-line":e==="project"?"bg-blue-950/30 text-blue-400/80 border-blue-900/40":"bg-purple-950/30 text-purple-400/80 border-purple-900/40";return n.jsx("span",{className:`text-[10px] px-1 py-0 rounded border uppercase tracking-wide shrink-0 ${s} ${r?"opacity-60":""}`,children:N[e].label})}function S({children:e,tone:r="default"}){const s={default:"bg-bg-hi text-fg-dim border-line",warn:"bg-yellow-950/30 text-yellow-500/80 border-yellow-900/40",dim:"bg-bg-elev text-fg-faint border-line"}[r];return n.jsx("span",{className:`text-[10px] px-1 py-0 rounded border uppercase tracking-wide shrink-0 ${s}`,children:e})}function F({values:e}){const r=e.map(s=>String(s)).join(" | ");return n.jsxs("span",{className:"text-[10px] text-fg-faint truncate max-w-xs",title:`allowed: ${r}`,children:["∈ ",r.length>30?r.slice(0,30)+"…":r]})}function G(e,r,s){const a=O(o=>o.files),m=O(o=>o.loadJson),f=O(o=>o.watchFile),x=O(o=>o.unwatchFile),u=b.useMemo(()=>{const o={};for(const g of e.scopes){const d=e.resolve(g,r??"",s);d&&(o[g]=d)}return o},[e,r,s]);return b.useEffect(()=>{const o=Object.values(u).filter(Boolean);return o.forEach(g=>{a[g]||m(g),f(g)}),()=>{o.forEach(g=>x(g))}},[JSON.stringify(u)]),u}function B(e){const r=e??{},s={...r.$defs??{},...r.definitions??{}},a=t=>{if(!t)return{};if(!t.$ref)return x(t);const i=/^#\/(\$defs|definitions)\/(.+)$/.exec(t.$ref);if(!i)return x(t);const c=s[i[2]];return c?a({...c,...u(t)}):x(t)},m=new Set(["__proto__","constructor","prototype"]),f=t=>{if(!t)return{};const i={};for(const[c,l]of Object.entries(t))m.has(c)||(i[c]=l);return i},x=t=>{if(!t.allOf||t.allOf.length===0)return t;const i={...t};delete i.allOf;for(const c of t.allOf){const l=a(c);Object.assign(i,{properties:{...f(i.properties),...f(l.properties)},required:q([...i.required??[],...l.required??[]])}),!i.description&&l.description&&(i.description=l.description),i.default===void 0&&l.default!==void 0&&(i.default=l.default),!i.type&&l.type&&(i.type=l.type)}return i},u=t=>{const{$ref:i,...c}=t;return c},o=(t,i)=>{let c=a(t);for(const l of i){if(!c)return null;if(/^\d+$/.test(l)){const v=Array.isArray(c.items)?c.items[Number(l)]:c.items;c=v?a(v):null;continue}const j=c.properties;if(j&&!m.has(l)&&l in j){c=a(j[l]);continue}const p=c.additionalProperties;if(p&&typeof p=="object"){c=a(p);continue}return null}return c},g=(t,i,c)=>{if(!t)return null;const l={};if(t.description&&(l.description=t.description),t.type&&(l.type=t.type),t.default!==void 0&&(l.default=t.default),t.enum&&(l.enum=t.enum),t.const!==void 0&&(l.const=t.const),t.deprecated&&(l.deprecated=!0),t.examples&&(l.examples=t.examples),t.properties&&(l.knownChildren=Object.keys(t.properties)),c&&(i!=null&&i.includes(c))&&(l.required=!0),t.items&&!Array.isArray(t.items)){const j=a(t.items),p=g(j,void 0,null);p&&(l.itemsInfo=p)}return(t.additionalProperties===!0||typeof t.additionalProperties=="object")&&(l.open=!0),l},d=t=>i=>{if(i.length===0)return g(a(t),void 0,null);const c=o(t,i.slice(0,-1));if(!c)return null;const l=i[i.length-1],j=o(c,[l]);return g(j,c.required,l)},h=t=>{const i=a(t);return Object.keys(i.properties??{})},y=t=>({at:d(t),rootKeys:()=>h(t),rootedAt:i=>{const c=o(t,i);return y(c??{})}});return y(r)}function q(e){return Array.from(new Set(e))}let $=null;function V(){return $||($=B(K)),$}export{T as E,V as s,G as u};
1
+ import{ax as b,ai as n,S as N,aO as O,av as K}from"./index-DbR91Z5j.js";function T({node:e,targetScope:r,onOverride:s,schema:a,rootLabel:m}){const[f,x]=b.useState(""),[u,o]=b.useState(!0),g=[],d=e.kind==="object"&&Object.keys(e.children).length===0,y=((a==null?void 0:a.rootKeys())??[]).length>0;return n.jsxs("div",{className:"h-full flex flex-col",children:[n.jsxs("div",{className:"shrink-0 border-b border-line bg-bg-elev px-3 py-1.5 flex items-center gap-2 text-xs",children:[n.jsxs("span",{className:"text-fg-faint",children:["merged · overrides → ",n.jsx("span",{className:"text-fg-dim",children:N[r].label})]}),y&&n.jsxs("label",{className:"flex items-center gap-1 text-fg-faint cursor-pointer",children:[n.jsx("input",{type:"checkbox",checked:u,onChange:t=>o(t.target.checked),className:"accent-accent"}),"show unset keys"]}),n.jsx("div",{className:"flex-1"}),n.jsx("input",{value:f,onChange:t=>x(t.target.value),placeholder:"filter keys or descriptions…",className:"bg-bg border border-line rounded px-2 py-0.5 text-xs text-fg w-56"})]}),n.jsx("div",{className:"flex-1 overflow-auto px-3 py-2 font-mono text-xs",children:d&&!u?n.jsx("div",{className:"text-fg-faint italic px-2 py-4",children:"no settings resolved — all scope files empty or missing"}):n.jsx(E,{node:e,path:g,label:m??"(root)",targetScope:r,onOverride:s,filter:f,depth:0,schema:a,showGhosts:u,defaultOpen:!0})})]})}function E(e){return e.node.kind==="object"?n.jsx(P,{...e,node:e.node}):e.node.kind==="array"?n.jsx(J,{...e,node:e.node}):n.jsx(R,{...e,node:e.node})}function A(e,r){return r.trim()?e.toLowerCase().includes(r.toLowerCase()):!0}function w(e,r,s){return!!(!s.trim()||e.some(a=>A(a,s))||r!=null&&r.description&&A(r.description,s))}function P({node:e,path:r,label:s,targetScope:a,onOverride:m,filter:f,depth:x,schema:u,showGhosts:o,defaultOpen:g}){const[d,h]=b.useState(g??x<2),y=(u==null?void 0:u.at(r))??null,t=new Set(Object.keys(e.children)),i=o?(y==null?void 0:y.knownChildren)??[]:[],c=Array.from(new Set([...t,...i])).sort(),l=b.useMemo(()=>f.trim()?c.filter(p=>{const v=(u==null?void 0:u.at([...r,p]))??null;return w([...r,p],v,f)?!0:t.has(p)?L(e.children[p],[...r,p],f,u):!1}):c,[c.join(","),f,e,r.join("."),u]);if(f.trim()&&l.length===0&&!w(r,y,f))return null;if(r.length===0)return n.jsx("div",{children:l.map(p=>j(p))});return n.jsxs("div",{children:[n.jsxs("div",{className:"flex items-center gap-1 py-0.5 hover:bg-bg-elev/50 rounded cursor-pointer",style:{paddingLeft:x*14},onClick:()=>h(!d),children:[n.jsx("span",{className:"text-fg-faint w-3 shrink-0",children:d?"▾":"▸"}),n.jsx("span",{className:"text-fg",children:s}),n.jsxs("span",{className:"text-fg-faint",children:[" {",t.size,i.length>t.size?`/${new Set([...t,...i]).size}`:"","}"]}),(y==null?void 0:y.description)&&n.jsxs("span",{className:"text-fg-faint truncate max-w-md",title:y.description,children:["— ",y.description]})]}),d&&l.map(p=>j(p))]});function j(p){if(t.has(p))return n.jsx(E,{node:e.children[p],path:[...r,p],label:p,targetScope:a,onOverride:m,filter:f,depth:x+1,schema:u,showGhosts:o},p);const v=(u==null?void 0:u.at([...r,p]))??null;return v?n.jsx(I,{path:[...r,p],label:p,info:v,targetScope:a,onSet:m,depth:x+1,filter:f},p):null}}function L(e,r,s,a){const m=(a==null?void 0:a.at(r))??null;if(w(r,m,s))return!0;if(e.kind!=="object")return!1;for(const f of Object.keys(e.children))if(L(e.children[f],[...r,f],s,a))return!0;return!1}function J({node:e,path:r,label:s,filter:a,depth:m,schema:f}){const[x,u]=b.useState(!0),o=(f==null?void 0:f.at(r))??null;return w(r,o,a)?n.jsxs("div",{children:[n.jsxs("div",{className:"flex items-center gap-1 py-0.5 hover:bg-bg-elev/50 rounded cursor-pointer",style:{paddingLeft:m*14},onClick:()=>u(!x),children:[n.jsx("span",{className:"text-fg-faint w-3 shrink-0",children:x?"▾":"▸"}),n.jsx("span",{className:"text-fg",children:s}),n.jsxs("span",{className:"text-fg-faint",children:[" [",e.items.length,"]"]}),n.jsx(S,{tone:"warn",children:"accumulated"}),(o==null?void 0:o.description)&&n.jsxs("span",{className:"text-fg-faint truncate max-w-md",title:o.description,children:["— ",o.description]})]}),x&&e.items.map((g,d)=>n.jsxs("div",{className:"flex items-start gap-2 py-0.5",style:{paddingLeft:(m+1)*14},children:[n.jsx("span",{className:"text-fg-faint w-3 shrink-0"}),n.jsxs("span",{className:"text-fg-faint",children:[d,":"]}),n.jsx("span",{className:"text-fg-dim truncate max-w-xl",children:k(g.value)}),n.jsx(C,{scope:g.fromScope})]},d))]}):null}function R({node:e,path:r,label:s,targetScope:a,onOverride:m,filter:f,depth:x,schema:u}){const[o,g]=b.useState(!1),d=(u==null?void 0:u.at(r))??null;if(!w(r,d,f))return null;const h=e.winner!==a,y=e.shadowed.length>0;return n.jsxs("div",{children:[n.jsxs("div",{className:"group flex items-center gap-2 py-0.5 hover:bg-bg-elev/50 rounded",style:{paddingLeft:x*14},children:[n.jsx("span",{className:`w-3 shrink-0 ${y?"text-fg-faint cursor-pointer":""}`,onClick:()=>y&&g(!o),children:y?o?"▾":"▸":""}),n.jsxs("span",{className:"text-fg",children:[s,":"]}),n.jsx("span",{className:"text-fg-dim truncate max-w-md",children:k(e.value)}),n.jsx(C,{scope:e.winner}),(d==null?void 0:d.deprecated)&&n.jsx(S,{tone:"warn",children:"deprecated"}),(d==null?void 0:d.default)!==void 0&&_(e.value,d.default)&&n.jsx(S,{tone:"dim",children:"= default"}),e.typeMismatch&&n.jsx("span",{className:"text-yellow-500/80",title:"shadowed scopes have a different value type",children:"⚠"}),(d==null?void 0:d.description)&&n.jsxs("span",{className:"text-fg-faint truncate max-w-md",title:d.description,children:["— ",d.description]}),n.jsx("div",{className:"flex-1"}),(d==null?void 0:d.enum)&&n.jsx(F,{values:d.enum}),n.jsx("button",{disabled:!h,onClick:()=>m(r,e.value),className:`opacity-0 group-hover:opacity-100 px-1.5 py-0 text-[10px] border rounded transition-opacity ${h?"border-accent/50 text-accent hover:bg-accent hover:text-bg":"border-line text-fg-faint cursor-not-allowed"}`,title:h?`copy into ${N[a].label} draft`:`already winning in ${N[a].label}`,children:"override"})]}),o&&e.shadowed.map((t,i)=>n.jsxs("div",{className:"flex items-center gap-2 py-0.5 text-fg-faint line-through",style:{paddingLeft:(x+1)*14+12},children:[n.jsx("span",{children:"shadowed:"}),n.jsx("span",{className:"truncate max-w-xl",children:k(t.value)}),n.jsx(C,{scope:t.scope,dim:!0})]},i))]})}function I({path:e,label:r,info:s,targetScope:a,onSet:m,depth:f,filter:x}){if(!w(e,s,x))return null;const u=s.default!==void 0?s.default:M(s.type),o=Array.isArray(s.type)?s.type.join("|"):s.type??"?";return n.jsxs("div",{className:"group flex items-center gap-2 py-0.5 hover:bg-bg-elev/50 rounded opacity-60",style:{paddingLeft:f*14},children:[n.jsx("span",{className:"w-3 shrink-0"}),n.jsx("span",{className:"text-fg-dim",children:r}),n.jsx(S,{tone:"dim",children:o}),s.required&&n.jsx(S,{tone:"warn",children:"required"}),s.default!==void 0&&n.jsxs("span",{className:"text-fg-faint",children:["default: ",k(s.default)]}),s.description&&n.jsxs("span",{className:"text-fg-faint truncate max-w-md",title:s.description,children:["— ",s.description]}),n.jsx("div",{className:"flex-1"}),s.enum&&n.jsx(F,{values:s.enum}),n.jsx("button",{onClick:()=>m(e,u),className:"opacity-0 group-hover:opacity-100 px-1.5 py-0 text-[10px] border border-accent/50 rounded text-accent hover:bg-accent hover:text-bg transition-opacity",title:`write to ${N[a].label} draft`,children:"set"})]})}function _(e,r){return e===r?!0:typeof e!=typeof r?!1:e&&r&&typeof e=="object"?JSON.stringify(e)===JSON.stringify(r):!1}function M(e){switch(Array.isArray(e)?e[0]:e){case"boolean":return!1;case"integer":case"number":return 0;case"string":return"";case"array":return[];case"object":return{};case"null":return null;default:return null}}function k(e){if(typeof e=="string")return JSON.stringify(e);if(e===null)return"null";if(typeof e=="object"){const r=JSON.stringify(e);return r.length>100?r.slice(0,100)+"…":r}return String(e)}function C({scope:e,dim:r}){const s=e==="user"?"bg-bg-hi text-fg-dim border-line":e==="project"?"bg-blue-950/30 text-blue-400/80 border-blue-900/40":"bg-purple-950/30 text-purple-400/80 border-purple-900/40";return n.jsx("span",{className:`text-[10px] px-1 py-0 rounded border uppercase tracking-wide shrink-0 ${s} ${r?"opacity-60":""}`,children:N[e].label})}function S({children:e,tone:r="default"}){const s={default:"bg-bg-hi text-fg-dim border-line",warn:"bg-yellow-950/30 text-yellow-500/80 border-yellow-900/40",dim:"bg-bg-elev text-fg-faint border-line"}[r];return n.jsx("span",{className:`text-[10px] px-1 py-0 rounded border uppercase tracking-wide shrink-0 ${s}`,children:e})}function F({values:e}){const r=e.map(s=>String(s)).join(" | ");return n.jsxs("span",{className:"text-[10px] text-fg-faint truncate max-w-xs",title:`allowed: ${r}`,children:["∈ ",r.length>30?r.slice(0,30)+"…":r]})}function G(e,r,s){const a=O(o=>o.files),m=O(o=>o.loadJson),f=O(o=>o.watchFile),x=O(o=>o.unwatchFile),u=b.useMemo(()=>{const o={};for(const g of e.scopes){const d=e.resolve(g,r??"",s);d&&(o[g]=d)}return o},[e,r,s]);return b.useEffect(()=>{const o=Object.values(u).filter(Boolean);return o.forEach(g=>{a[g]||m(g),f(g)}),()=>{o.forEach(g=>x(g))}},[JSON.stringify(u)]),u}function B(e){const r=e??{},s={...r.$defs??{},...r.definitions??{}},a=t=>{if(!t)return{};if(!t.$ref)return x(t);const i=/^#\/(\$defs|definitions)\/(.+)$/.exec(t.$ref);if(!i)return x(t);const c=s[i[2]];return c?a({...c,...u(t)}):x(t)},m=new Set(["__proto__","constructor","prototype"]),f=t=>{if(!t)return{};const i={};for(const[c,l]of Object.entries(t))m.has(c)||(i[c]=l);return i},x=t=>{if(!t.allOf||t.allOf.length===0)return t;const i={...t};delete i.allOf;for(const c of t.allOf){const l=a(c);Object.assign(i,{properties:{...f(i.properties),...f(l.properties)},required:q([...i.required??[],...l.required??[]])}),!i.description&&l.description&&(i.description=l.description),i.default===void 0&&l.default!==void 0&&(i.default=l.default),!i.type&&l.type&&(i.type=l.type)}return i},u=t=>{const{$ref:i,...c}=t;return c},o=(t,i)=>{let c=a(t);for(const l of i){if(!c)return null;if(/^\d+$/.test(l)){const v=Array.isArray(c.items)?c.items[Number(l)]:c.items;c=v?a(v):null;continue}const j=c.properties;if(j&&!m.has(l)&&l in j){c=a(j[l]);continue}const p=c.additionalProperties;if(p&&typeof p=="object"){c=a(p);continue}return null}return c},g=(t,i,c)=>{if(!t)return null;const l={};if(t.description&&(l.description=t.description),t.type&&(l.type=t.type),t.default!==void 0&&(l.default=t.default),t.enum&&(l.enum=t.enum),t.const!==void 0&&(l.const=t.const),t.deprecated&&(l.deprecated=!0),t.examples&&(l.examples=t.examples),t.properties&&(l.knownChildren=Object.keys(t.properties)),c&&(i!=null&&i.includes(c))&&(l.required=!0),t.items&&!Array.isArray(t.items)){const j=a(t.items),p=g(j,void 0,null);p&&(l.itemsInfo=p)}return(t.additionalProperties===!0||typeof t.additionalProperties=="object")&&(l.open=!0),l},d=t=>i=>{if(i.length===0)return g(a(t),void 0,null);const c=o(t,i.slice(0,-1));if(!c)return null;const l=i[i.length-1],j=o(c,[l]);return g(j,c.required,l)},h=t=>{const i=a(t);return Object.keys(i.properties??{})},y=t=>({at:d(t),rootKeys:()=>h(t),rootedAt:i=>{const c=o(t,i);return y(c??{})}});return y(r)}function q(e){return Array.from(new Set(e))}let $=null;function V(){return $||($=B(K)),$}export{T as E,V as s,G as u};
package/dist/index.html CHANGED
@@ -7,7 +7,7 @@
7
7
  <link rel="preconnect" href="https://fonts.googleapis.com">
8
8
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
9
  <link href="https://fonts.googleapis.com/css2?family=Newsreader:ital,opsz,wght@0,6..72,400;0,6..72,500;0,6..72,600;0,6..72,700;1,6..72,400&family=Geist:wght@300;400;500;600;700&family=IBM+Plex+Mono:wght@400;500;600&display=swap" rel="stylesheet">
10
- <script type="module" crossorigin src="./assets/index-ByE44RSO.js"></script>
10
+ <script type="module" crossorigin src="./assets/index-DbR91Z5j.js"></script>
11
11
  <link rel="modulepreload" crossorigin href="./assets/monaco-editor-BW5C4Iv1.js">
12
12
  <link rel="stylesheet" crossorigin href="./assets/monaco-editor-BTnBOi8r.css">
13
13
  <link rel="stylesheet" crossorigin href="./assets/index-D89EUizB.css">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-session-manager",
3
- "version": "0.103.0",
3
+ "version": "0.104.1",
4
4
  "description": "Local cockpit for the Claude Code CLI — multi-tab terminal, full config surface, scheduler, voice dictation, and live observability.",
5
5
  "type": "module",
6
6
  "main": "src/main/index.cjs",
@@ -85,7 +85,7 @@
85
85
  ],
86
86
  "author": "bilkobibitkov",
87
87
  "license": "MIT",
88
- "homepage": "https://github.com/StanislavBG/claude-code-session-manager#readme",
88
+ "homepage": "https://bilko.run/projects/session-manager/",
89
89
  "repository": {
90
90
  "type": "git",
91
91
  "url": "https://github.com/StanislavBG/claude-code-session-manager.git"
@@ -93,6 +93,16 @@
93
93
  "bugs": {
94
94
  "url": "https://github.com/StanislavBG/claude-code-session-manager/issues"
95
95
  },
96
+ "funding": [
97
+ {
98
+ "type": "individual",
99
+ "url": "https://bilko.run/coffee"
100
+ },
101
+ {
102
+ "type": "individual",
103
+ "url": "https://bilko.run/projects/session-manager/"
104
+ }
105
+ ],
96
106
  "publishConfig": {
97
107
  "access": "public"
98
108
  },
@@ -100,23 +110,30 @@
100
110
  "node": ">=22.12.0"
101
111
  },
102
112
  "overrides": {
103
- "dompurify": "^3.4.8"
113
+ "dompurify": "^3.4.8",
114
+ "@hono/node-server": "^1.19.15",
115
+ "fast-uri": "^3.1.8",
116
+ "hono": "^4.13.7",
117
+ "ip-address": "^10.7.1",
118
+ "qs": "^6.16.0",
119
+ "tar": "^7.5.21",
120
+ "undici": "^7.29.1"
104
121
  },
105
122
  "os": [
106
123
  "darwin",
107
124
  "linux"
108
125
  ],
109
126
  "dependencies": {
110
- "@electron/rebuild": "4.0.4",
127
+ "@electron/rebuild": "4.2.0",
111
128
  "@modelcontextprotocol/sdk": "^1.29.0",
112
129
  "@opentelemetry/api": "^1.9.0",
113
- "@opentelemetry/exporter-trace-otlp-http": "^0.57.0",
114
- "@opentelemetry/resources": "^1.30.0",
115
- "@opentelemetry/sdk-trace-base": "^1.30.0",
116
- "@opentelemetry/sdk-trace-node": "^1.30.0",
117
- "@opentelemetry/semantic-conventions": "^1.28.0",
130
+ "@opentelemetry/exporter-trace-otlp-http": "^0.222.0",
131
+ "@opentelemetry/resources": "^2.11.0",
132
+ "@opentelemetry/sdk-trace-base": "^2.11.0",
133
+ "@opentelemetry/sdk-trace-node": "^2.11.0",
134
+ "@opentelemetry/semantic-conventions": "^1.43.0",
118
135
  "chokidar": "^4.0.1",
119
- "electron": "42.1.0",
136
+ "electron": "42.11.10",
120
137
  "marked": "^14.0.0",
121
138
  "node-pty": "^1.2.0-beta.12",
122
139
  "zod": "^3.23.8"
@@ -14,6 +14,9 @@
14
14
  * project_home_write({ cwd?, html }) -> POST /admin/project-home/write
15
15
  * project_demo_video_write({ cwd?, html }) -> POST /admin/project-home/demo-video/write
16
16
  *
17
+ * macro_list({ cwd? }) -> GET /admin/macros?cwd=<encoded>
18
+ * macro_save({ cwd?, id?, label, agentName, tag, prompt }) -> POST /admin/macros/save
19
+ *
17
20
  * This is a separate process from the Electron app — it only ever reaches
18
21
  * it over the token-authed loopback HTTP API in admin-api.json, never by
19
22
  * requiring scheduler.cjs/localAdminHttp.cjs directly. The admin server IS the
@@ -395,6 +398,32 @@ const TOOLS = [
395
398
  required: ['html'],
396
399
  },
397
400
  },
401
+ {
402
+ name: 'macro_list',
403
+ description: descriptionFor('macro_list'),
404
+ inputSchema: {
405
+ type: 'object',
406
+ properties: {
407
+ cwd: { type: 'string', description: "Optional: absolute path to the target project. Defaults to the calling session's own project root (SM_PROJECT_ROOT or process.cwd()) when omitted." },
408
+ },
409
+ },
410
+ },
411
+ {
412
+ name: 'macro_save',
413
+ description: descriptionFor('macro_save'),
414
+ inputSchema: {
415
+ type: 'object',
416
+ properties: {
417
+ cwd: { type: 'string', description: "Optional: absolute path to the target project. Defaults to the calling session's own project root (SM_PROJECT_ROOT or process.cwd()) when omitted." },
418
+ id: { type: 'string', description: 'Optional: id of an existing macro (already visible to this project) to update. Omit to create a new macro scoped to this project.' },
419
+ label: { type: 'string', description: 'Short label shown on the HOT KEYS button.' },
420
+ agentName: { type: 'string', description: 'Persona to run the macro as (e.g. "builder").' },
421
+ tag: { type: 'string', description: 'Mission tag for the macro.' },
422
+ prompt: { type: 'string', description: 'The opening prompt the macro sends.' },
423
+ },
424
+ required: ['label', 'agentName', 'tag', 'prompt'],
425
+ },
426
+ },
398
427
  {
399
428
  name: 'session_manager_help',
400
429
  description: descriptionFor('session_manager_help'),
@@ -627,6 +656,24 @@ async function handleCallTool(request) {
627
656
  const result = await adminRequest('POST', '/admin/project-home/demo-video/write', { cwd, html: args.html });
628
657
  return { content: [{ type: 'text', text: JSON.stringify(result) }] };
629
658
  }
659
+ if (name === 'macro_list') {
660
+ const cwd = resolveCwdArg(args);
661
+ const result = await adminRequest('GET', `/admin/macros?cwd=${encodeURIComponent(cwd)}`);
662
+ return { content: [{ type: 'text', text: JSON.stringify(result) }] };
663
+ }
664
+ if (name === 'macro_save') {
665
+ const missing = ['label', 'agentName', 'tag', 'prompt'].filter(
666
+ (field) => !args || typeof args[field] !== 'string',
667
+ );
668
+ if (missing.length > 0) {
669
+ return errorResult(`missing or invalid required argument(s): ${missing.join(', ')}`);
670
+ }
671
+ const cwd = resolveCwdArg(args);
672
+ const payload = { cwd, label: args.label, agentName: args.agentName, tag: args.tag, prompt: args.prompt };
673
+ if (typeof args.id === 'string' && args.id) payload.id = args.id;
674
+ const result = await adminRequest('POST', '/admin/macros/save', payload);
675
+ return { content: [{ type: 'text', text: JSON.stringify(result) }] };
676
+ }
630
677
  if (name === 'session_manager_help') {
631
678
  const toolName = args && typeof args.tool === 'string' ? args.tool : null;
632
679
  const topic = args && typeof args.topic === 'string' ? args.topic : null;
@@ -1,8 +1,8 @@
1
1
  {
2
- "version": "0.103.0",
3
- "gitSha": "dd29df2049979c09e87925296058af065d827ddd",
4
- "gitShortSha": "dd29df20",
2
+ "version": "0.104.1",
3
+ "gitSha": "2ca4f607b6a59d11f3087f0dd8890eb6b3f57bab",
4
+ "gitShortSha": "2ca4f607",
5
5
  "gitBranch": "HEAD",
6
- "builtAt": "2026-10-03T20:25:48.708Z",
6
+ "builtAt": "2026-10-03T22:49:52.241Z",
7
7
  "dirty": false
8
8
  }
@@ -33,6 +33,7 @@ const { createAdminHttp } = require('./lib/localAdminHttp.cjs');
33
33
  const prdCreate = require('./lib/prdCreate.cjs');
34
34
  const prdAdminRoutes = require('./lib/prdAdminRoutes.cjs');
35
35
  const projectHomeAdminRoutes = require('./lib/projectHomeAdminRoutes.cjs');
36
+ const macroAdminRoutes = require('./lib/macroAdminRoutes.cjs');
36
37
  const { smfileResponseHeaders, shouldBlockFrameNavigation } = require('./lib/smfileHeaders.cjs');
37
38
  const { appendAuditEvent } = require('./lib/auditLog.cjs');
38
39
  const chatRunner = require('./chatRunner.cjs');
@@ -60,6 +61,7 @@ scheduler.registerAdminRoutes(adminHttp);
60
61
  prdCreate.registerAdminRoute(adminHttp, scheduler.remote);
61
62
  prdAdminRoutes.registerAdminRoute(adminHttp, scheduler.remote);
62
63
  projectHomeAdminRoutes.registerAdminRoute(adminHttp);
64
+ macroAdminRoutes.registerAdminRoute(adminHttp, { onChanged: () => broadcastMacrosChanged() });
63
65
  chatRunner.registerAdminRoute(adminHttp);
64
66
  // Project-to-project feedback conduit — the app is the only process holding
65
67
  // several projects' operations roots open, so it performs the cross-folder
@@ -0,0 +1,111 @@
1
+ /**
2
+ * macroAdminRoutes.cjs — loopback admin HTTP routes so an agent session (via
3
+ * the scheduler MCP, next PRD) can list and create/update a HOT KEYS macro
4
+ * for its own project, through the existing macroLibrary.cjs store:
5
+ * GET /admin/macros?cwd=… -> { ok, macros }
6
+ * POST /admin/macros/save {cwd, id?, label, agentName, tag, prompt}
7
+ *
8
+ * cwd resolution matches projectHomeAdminRoutes.cjs's resolveCwd exactly
9
+ * (reused, not copied). A create always stores `projects: [resolvedCwd]`,
10
+ * `surface: 'sessions'`; an update is refused (400) if the resolved cwd is
11
+ * not already in the macro's `projects` (no cross-project hijack), if `id`
12
+ * starts with `builtin-`, or if `id` is not found. Field validation reuses
13
+ * macroLibrary's `MacroSaveSchema`.
14
+ *
15
+ * A successful save calls `onChanged()` exactly once so the Sessions HOT
16
+ * KEYS strip updates live, matching the IPC handlers in index.cjs.
17
+ */
18
+ 'use strict';
19
+
20
+ const { readBody, sendJson } = require('./localAdminHttp.cjs');
21
+ const { resolveCwd } = require('./projectHomeAdminRoutes.cjs');
22
+ const macroLibrary = require('./macroLibrary.cjs');
23
+
24
+ function listHandler(onChanged, libOpts) {
25
+ return async (_req, res, query) => {
26
+ const resolved = resolveCwd(query.get('cwd'));
27
+ if (!resolved.ok) {
28
+ sendJson(res, resolved.status, { ok: false, error: resolved.error });
29
+ return;
30
+ }
31
+ const macros = await macroLibrary.listMacros(libOpts);
32
+ const visible = macros.filter(
33
+ (m) => m.projects.includes(resolved.cwd) || m.projects.includes(macroLibrary.ALL_PROJECTS),
34
+ );
35
+ sendJson(res, 200, { ok: true, macros: visible });
36
+ };
37
+ }
38
+
39
+ function saveHandler(onChanged, libOpts) {
40
+ return async (req, res) => {
41
+ let raw;
42
+ try {
43
+ raw = await readBody(req);
44
+ } catch (e) {
45
+ sendJson(res, 400, { ok: false, error: `request body rejected: ${e?.message ?? 'unreadable'}` });
46
+ return;
47
+ }
48
+ let body;
49
+ try {
50
+ body = raw ? JSON.parse(raw) : {};
51
+ } catch {
52
+ sendJson(res, 400, { ok: false, error: 'invalid JSON body' });
53
+ return;
54
+ }
55
+ const resolved = resolveCwd(body.cwd);
56
+ if (!resolved.ok) {
57
+ sendJson(res, resolved.status, { ok: false, error: resolved.error });
58
+ return;
59
+ }
60
+ if (typeof body.id === 'string' && body.id.startsWith('builtin-')) {
61
+ sendJson(res, 400, { ok: false, error: 'built-in macros cannot be edited through this route' });
62
+ return;
63
+ }
64
+ let input;
65
+ try {
66
+ input = macroLibrary.MacroSaveSchema.parse({
67
+ id: body.id,
68
+ label: body.label,
69
+ agentName: body.agentName,
70
+ tag: body.tag,
71
+ prompt: body.prompt,
72
+ });
73
+ } catch (e) {
74
+ sendJson(res, 400, { ok: false, error: e?.issues?.[0]?.message ?? e?.message ?? 'invalid payload' });
75
+ return;
76
+ }
77
+ if (input.id) {
78
+ const macros = await macroLibrary.listMacros(libOpts);
79
+ const existing = macros.find((m) => m.id === input.id);
80
+ if (!existing) {
81
+ sendJson(res, 400, { ok: false, error: `macro not found: ${input.id}` });
82
+ return;
83
+ }
84
+ if (!existing.projects.includes(resolved.cwd)) {
85
+ sendJson(res, 400, { ok: false, error: `macro ${input.id} is not visible to ${resolved.cwd}` });
86
+ return;
87
+ }
88
+ } else {
89
+ input = { ...input, projects: [resolved.cwd], surface: 'sessions' };
90
+ }
91
+ let macro;
92
+ try {
93
+ macro = await macroLibrary.saveMacro(input, libOpts);
94
+ } catch (e) {
95
+ sendJson(res, 400, { ok: false, error: e?.message ?? 'save failed' });
96
+ return;
97
+ }
98
+ if (onChanged) onChanged();
99
+ sendJson(res, 200, { ok: true, macro });
100
+ };
101
+ }
102
+
103
+ function registerAdminRoute(adminHttp, { onChanged } = {}, opts = {}) {
104
+ const libOpts = opts.filePath ? { filePath: opts.filePath } : undefined;
105
+ adminHttp.registerRoute('GET', '/admin/macros', listHandler(onChanged, libOpts));
106
+ adminHttp.registerRoute('POST', '/admin/macros/save', saveHandler(onChanged, libOpts));
107
+ }
108
+
109
+ module.exports = {
110
+ registerAdminRoute,
111
+ };
@@ -23,7 +23,7 @@ const { z } = require('zod');
23
23
 
24
24
  const CatalogEntrySchema = z.object({
25
25
  name: z.string().min(1),
26
- group: z.enum(['scheduler', 'chat', 'feedback', 'help', 'project-home']),
26
+ group: z.enum(['scheduler', 'chat', 'feedback', 'help', 'project-home', 'macros']),
27
27
  purpose: z.string().min(1),
28
28
  whenToUse: z.string().min(1),
29
29
  whenNotToUse: z.string().min(1),
@@ -293,6 +293,41 @@ const MCP_TOOL_CATALOG = [
293
293
  notes: "cwd is optional — defaults to the calling session's own project root (SM_PROJECT_ROOT or process.cwd()) when omitted. "
294
294
  + 'The document is CSP-stamped after it is written, so the viewer sandbox is the real network fence — these checks are defence in depth.',
295
295
  },
296
+ {
297
+ name: 'macro_list',
298
+ group: 'macros',
299
+ purpose: "List this project's HOT KEYS macros — the saved (agent, tag, prompt) one-click buttons shown "
300
+ + "in the Sessions tab's HOT KEYS strip, via the session-manager app's admin API.",
301
+ whenToUse: 'Use to see what macros already exist for this project (including machine-wide `*` macros and '
302
+ + 'built-ins) before deciding whether to add or update one.',
303
+ whenNotToUse: 'WHEN NOT TO USE IT: macros are scoped to the caller\'s own project — this only ever returns '
304
+ + "macros visible to the resolved cwd, never another project's.",
305
+ exampleArgs: { cwd: '/home/bilko/Projects/session-manager' },
306
+ notes: "cwd is optional — defaults to the calling session's own project root (SM_PROJECT_ROOT or process.cwd()) when omitted.",
307
+ },
308
+ {
309
+ name: 'macro_save',
310
+ group: 'macros',
311
+ purpose: "Create or update one of this project's HOT KEYS macros — a saved (agentName, tag, prompt) "
312
+ + 'one-click button — via the session-manager app\'s admin API, through the same macroLibrary.cjs store '
313
+ + 'the Sessions HOT KEYS strip reads from.',
314
+ whenToUse: 'Pass `id` to update an existing macro already visible to this project; omit `id` to create a new '
315
+ + 'one scoped to this project. Use for things like a "Publish git + npm" macro a human will press '
316
+ + 'repeatedly, when they have asked for that macro to exist.',
317
+ whenNotToUse: 'WHEN NOT TO USE IT: macros are scoped to the caller\'s own project — this call is refused if '
318
+ + '`id` resolves to a macro not visible to this project. Built-in macros (`id` starting with `builtin-`) '
319
+ + "cannot be edited through this route. A macro is a HUMAN's one-click button, not a task runner — never "
320
+ + 'create or update one unless the human has actually asked for that macro to exist.',
321
+ exampleArgs: {
322
+ cwd: '/home/bilko/Projects/session-manager',
323
+ label: 'Publish git + npm',
324
+ agentName: 'builder',
325
+ tag: 'feature',
326
+ prompt: 'Run the full publish flow: commit, bump version, gate, npm publish, push.',
327
+ },
328
+ notes: "cwd is optional — defaults to the calling session's own project root (SM_PROJECT_ROOT or "
329
+ + 'process.cwd()) when omitted. label, agentName, tag and prompt are all required strings.',
330
+ },
296
331
  {
297
332
  name: 'session_manager_help',
298
333
  group: 'help',
@@ -243,4 +243,5 @@ module.exports = {
243
243
  DEMO_VIDEO_CSP,
244
244
  MAX_HTML_BYTES,
245
245
  MAX_DEMO_VIDEO_BYTES,
246
+ resolveCwd,
246
247
  };
package/src/main/otel.cjs CHANGED
@@ -35,9 +35,9 @@ function loadDeps() {
35
35
  const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
36
36
  const { BatchSpanProcessor } = require('@opentelemetry/sdk-trace-base');
37
37
  const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');
38
- const { Resource } = require('@opentelemetry/resources');
39
- const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
40
- return { api, NodeTracerProvider, BatchSpanProcessor, OTLPTraceExporter, Resource, SemanticResourceAttributes };
38
+ const { resourceFromAttributes } = require('@opentelemetry/resources');
39
+ const { ATTR_SERVICE_NAME } = require('@opentelemetry/semantic-conventions');
40
+ return { api, NodeTracerProvider, BatchSpanProcessor, OTLPTraceExporter, resourceFromAttributes, ATTR_SERVICE_NAME };
41
41
  } catch (err) {
42
42
  return { error: err };
43
43
  }
@@ -83,7 +83,7 @@ async function init({ endpoint, headers, serviceName, includeContent: ic } = {})
83
83
  return { ok: false, error: lastError };
84
84
  }
85
85
 
86
- const { NodeTracerProvider, BatchSpanProcessor, OTLPTraceExporter, Resource, SemanticResourceAttributes } = deps;
86
+ const { NodeTracerProvider, BatchSpanProcessor, OTLPTraceExporter, resourceFromAttributes, ATTR_SERVICE_NAME } = deps;
87
87
 
88
88
  try {
89
89
  const exporter = new OTLPTraceExporter({
@@ -91,11 +91,11 @@ async function init({ endpoint, headers, serviceName, includeContent: ic } = {})
91
91
  headers: typeof headers === 'object' && headers ? headers : {},
92
92
  });
93
93
  const tp = new NodeTracerProvider({
94
- resource: new Resource({
95
- [SemanticResourceAttributes.SERVICE_NAME]: String(serviceName || 'session-manager'),
94
+ resource: resourceFromAttributes({
95
+ [ATTR_SERVICE_NAME]: String(serviceName || 'session-manager'),
96
96
  }),
97
+ spanProcessors: [new BatchSpanProcessor(exporter)],
97
98
  });
98
- tp.addSpanProcessor(new BatchSpanProcessor(exporter));
99
99
  // Note: we deliberately do NOT call tp.register() — that installs a global
100
100
  // tracer provider, which would intercept any other OTEL user in the
101
101
  // process. We only want to emit our own spans, so we use the provider