claude-code-session-manager 0.107.0 → 0.108.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/dist/assets/{AgentLibrary-Bjeq2-kp.js → AgentLibrary-Co54GThg.js} +1 -1
- package/dist/assets/{Button-CRLhoI2K.js → Button-DC6VzovQ.js} +1 -1
- package/dist/assets/{DataModel-iPJw5jcG.js → DataModel-DZ0vyJau.js} +1 -1
- package/dist/assets/{History-DfPR3_6N.js → History-Df3YwpPe.js} +1 -1
- package/dist/assets/{Hooks-Bw7H_DmC.js → Hooks-DplG6roH.js} +1 -1
- package/dist/assets/{Library-rqaJJJ1b.js → Library-DLmnlfQt.js} +1 -1
- package/dist/assets/{ListDetail-qI27OYfy.js → ListDetail-YylbvUj_.js} +1 -1
- package/dist/assets/{MarkdownEditor-BEFuHVNz.js → MarkdownEditor-DMPKWHTF.js} +1 -1
- package/dist/assets/{McpServers-Bz9O79rz.js → McpServers-Da-Ty5nc.js} +1 -1
- package/dist/assets/{Memory-DobxIoZ-.js → Memory-C3rUQ_cg.js} +1 -1
- package/dist/assets/{Panel-Cyt1wpUf.js → Panel-CC3JTnOI.js} +1 -1
- package/dist/assets/{Permissions-ChSNRUJJ.js → Permissions-XvBiMj1-.js} +1 -1
- package/dist/assets/{Plugins-CII221R2.js → Plugins-CzHY1mgS.js} +2 -2
- package/dist/assets/{ProvenanceBadge-C_sk5-v3.js → ProvenanceBadge-DaJIWVcg.js} +1 -1
- package/dist/assets/{SaveBar-BuYrg5E9.js → SaveBar-C06rFT34.js} +1 -1
- package/dist/assets/{Scheduler-eixbMGEk.js → Scheduler-BehadU-0.js} +1 -1
- package/dist/assets/{ScopeSwitcher-BM0gLPhd.js → ScopeSwitcher-Cp5mxblN.js} +1 -1
- package/dist/assets/{Settings-qD-0W-Ut.js → Settings-Cg9LIni0.js} +1 -1
- package/dist/assets/{SkillReferenceGraph-D0Hgdfxq.js → SkillReferenceGraph-DuWRmT_f.js} +1 -1
- package/dist/assets/{Skills-C3T_2_2o.js → Skills-CMmCZfIv.js} +1 -1
- package/dist/assets/{SystemPrompt-B-xTy9Qn.js → SystemPrompt-D_-MV025.js} +1 -1
- package/dist/assets/{TagLibrary-BH67tR5z.js → TagLibrary-D9Tv3yOJ.js} +1 -1
- package/dist/assets/{TiptapBody-CP_F_mwb.js → TiptapBody-1r4ODLJ7.js} +1 -1
- package/dist/assets/{Toggle-haRPHS5N.js → Toggle-BGT68XHP.js} +1 -1
- package/dist/assets/{ViewTabs-BHV3MA5u.js → ViewTabs-T0NBc8uv.js} +1 -1
- package/dist/assets/{index-v_3LvhMx.js → index-3_AtCAyd.js} +3 -3
- package/dist/assets/{settingsSchema-CE46TA3V.js → settingsSchema-CvoNk3Ye.js} +1 -1
- package/dist/assets/useAgentsDirWatch-1C2CBBya.js +1 -0
- package/dist/assets/{useConfigDirWatch-CjcswsWR.js → useConfigDirWatch-Cd5PnTkB.js} +1 -1
- package/dist/index.html +1 -1
- package/package.json +1 -1
- package/scripts/scheduler-mcp-server.cjs +38 -5
- package/src/main/build-info.json +4 -4
- package/src/main/lib/builtinMacros.cjs +2 -2
- package/src/main/lib/mcpToolCatalog.cjs +3 -1
- package/src/main/lib/shippedPersonaSeeds.cjs +11 -0
- package/src/seed/agents/demo-video-builder.md +69 -48
- package/dist/assets/useAgentsDirWatch-BZTi2K2e.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{aw as b,ah as n,S as N,aN as O}from"./index-v_3LvhMx.js";import{r as K}from"./claude-settings-schema-COigsajx.js";function G({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 V(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 D(){return $||($=B(K)),$}export{G as E,D as s,V as u};
|
|
1
|
+
import{aw as b,ah as n,S as N,aN as O}from"./index-3_AtCAyd.js";import{r as K}from"./claude-settings-schema-COigsajx.js";function G({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 V(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 D(){return $||($=B(K)),$}export{G as E,D as s,V as u};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{aS as u}from"./index-3_AtCAyd.js";import{u as a}from"./useConfigDirWatch-Cd5PnTkB.js";function r(e,s){const o=u();a([o?`${o}/.claude/agents`:null,e?`${e}/.claude/agents`:null],s)}export{r as u};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{aw as c}from"./index-
|
|
1
|
+
import{aw as c}from"./index-3_AtCAyd.js";function s(t){const n=t.replace(/\/{2,}/g,"/");return n.length>1?n.replace(/\/+$/,""):n}function u(t,n){const r=c.useRef(n);r.current=n;const e=Array.from(new Set(t.filter(o=>!!o).map(s))),i=e.slice().sort().join("\0");c.useEffect(()=>{if(e.length===0)return;window.api.config.watch(e);const o=window.api.config.onChanged(a=>{e.includes(a.path)&&r.current()});return()=>{o(),window.api.config.unwatch(e)}},[i])}export{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-
|
|
10
|
+
<script type="module" crossorigin src="./assets/index-3_AtCAyd.js"></script>
|
|
11
11
|
<link rel="modulepreload" crossorigin href="./assets/monaco-editor-BsIlgG7c.js">
|
|
12
12
|
<link rel="stylesheet" crossorigin href="./assets/monaco-editor-Cu5D__1H.css">
|
|
13
13
|
<link rel="stylesheet" crossorigin href="./assets/index-tr1w3hHB.css">
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-code-session-manager",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.108.0",
|
|
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",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* feedback_open_session({ ... }) -> POST /admin/feedback/open-session
|
|
13
13
|
*
|
|
14
14
|
* project_home_write({ cwd?, html }) -> POST /admin/project-home/write
|
|
15
|
-
* project_demo_video_write({ cwd?, html }) -> POST /admin/project-home/demo-video/write
|
|
15
|
+
* project_demo_video_write({ cwd?, html? | htmlPath? }) -> POST /admin/project-home/demo-video/write
|
|
16
16
|
*
|
|
17
17
|
* macro_list({ cwd? }) -> GET /admin/macros?cwd=<encoded>
|
|
18
18
|
* macro_save({ cwd?, id?, label, agentName, tag, prompt }) -> POST /admin/macros/save
|
|
@@ -55,6 +55,24 @@ function withPointer(text) {
|
|
|
55
55
|
return str.endsWith(HELP_POINTER) ? str : str + HELP_POINTER;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
const MAX_DEMO_VIDEO_BYTES = 2 * 1024 * 1024;
|
|
59
|
+
|
|
60
|
+
/** Reads a local .html/.htm file for project_demo_video_write; errors carry only the reason, never file contents. */
|
|
61
|
+
async function readDemoVideoHtmlFile(p) {
|
|
62
|
+
if (typeof p !== 'string' || !path.isAbsolute(p)) return { error: 'htmlPath must be an absolute path' };
|
|
63
|
+
if (!/\.html?$/i.test(p)) return { error: 'htmlPath must end in .html or .htm' };
|
|
64
|
+
try {
|
|
65
|
+
const st = await fsp.stat(p);
|
|
66
|
+
if (!st.isFile()) return { error: 'htmlPath is not a regular file' };
|
|
67
|
+
if (st.size > MAX_DEMO_VIDEO_BYTES) return { error: `htmlPath file exceeds ${MAX_DEMO_VIDEO_BYTES} bytes` };
|
|
68
|
+
const html = await fsp.readFile(p, 'utf8');
|
|
69
|
+
if (html.length === 0) return { error: 'htmlPath file is empty' };
|
|
70
|
+
return { html };
|
|
71
|
+
} catch (err) {
|
|
72
|
+
return { error: `cannot read htmlPath: ${err && err.code ? err.code : 'read failed'}` };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
58
76
|
function errorResult(text) {
|
|
59
77
|
return { content: [{ type: 'text', text: withPointer(text) }], isError: true };
|
|
60
78
|
}
|
|
@@ -396,8 +414,12 @@ const TOOLS = [
|
|
|
396
414
|
+ 'any http(s)/// src or href (no network-capable APIs — the document is CSP-fenced after it is written); '
|
|
397
415
|
+ 'or missing a <meta name="sm-demo-duration" content="N"> tag with 5 <= N <= 30.',
|
|
398
416
|
},
|
|
417
|
+
htmlPath: {
|
|
418
|
+
type: 'string',
|
|
419
|
+
description: 'Absolute path to a local .html/.htm file holding the complete document (same rules as html; <= 2MB). '
|
|
420
|
+
+ 'Prefer this when the document embeds a base64 narration/image data URI — the server reads the file, so the large payload never passes through the model. Give exactly one of html / htmlPath.',
|
|
421
|
+
},
|
|
399
422
|
},
|
|
400
|
-
required: ['html'],
|
|
401
423
|
},
|
|
402
424
|
},
|
|
403
425
|
{
|
|
@@ -675,11 +697,22 @@ async function handleCallTool(request) {
|
|
|
675
697
|
return { content: [{ type: 'text', text: JSON.stringify(result) }] };
|
|
676
698
|
}
|
|
677
699
|
if (name === 'project_demo_video_write') {
|
|
678
|
-
|
|
679
|
-
|
|
700
|
+
const hasHtml = !!args && args.html !== undefined && args.html !== null && args.html !== '';
|
|
701
|
+
const hasPath = !!args && args.htmlPath !== undefined && args.htmlPath !== null && args.htmlPath !== '';
|
|
702
|
+
if (hasHtml === hasPath) {
|
|
703
|
+
return errorResult('provide exactly one of html or htmlPath');
|
|
704
|
+
}
|
|
705
|
+
let html;
|
|
706
|
+
if (hasPath) {
|
|
707
|
+
const loaded = await readDemoVideoHtmlFile(args.htmlPath);
|
|
708
|
+
if (loaded.error) return errorResult(loaded.error);
|
|
709
|
+
html = loaded.html;
|
|
710
|
+
} else {
|
|
711
|
+
if (typeof args.html !== 'string') return errorResult('missing required argument: html');
|
|
712
|
+
html = args.html;
|
|
680
713
|
}
|
|
681
714
|
const cwd = resolveCwdArg(args);
|
|
682
|
-
const result = await adminRequest('POST', '/admin/project-home/demo-video/write', { cwd, html
|
|
715
|
+
const result = await adminRequest('POST', '/admin/project-home/demo-video/write', { cwd, html });
|
|
683
716
|
return { content: [{ type: 'text', text: JSON.stringify(result) }] };
|
|
684
717
|
}
|
|
685
718
|
if (name === 'macro_list') {
|
package/src/main/build-info.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.
|
|
3
|
-
"gitSha": "
|
|
4
|
-
"gitShortSha": "
|
|
2
|
+
"version": "0.108.0",
|
|
3
|
+
"gitSha": "6abcc4e355e214ed60fe76291081712aa98d44c2",
|
|
4
|
+
"gitShortSha": "6abcc4e3",
|
|
5
5
|
"gitBranch": "HEAD",
|
|
6
|
-
"builtAt": "2026-10-
|
|
6
|
+
"builtAt": "2026-10-09T19:19:08.109Z",
|
|
7
7
|
"dirty": false
|
|
8
8
|
}
|
|
@@ -30,9 +30,9 @@ const BUILTIN_MACROS = Object.freeze([
|
|
|
30
30
|
tag: 'project-home-builder',
|
|
31
31
|
surface: 'project-home',
|
|
32
32
|
projects: ['*'],
|
|
33
|
-
builtinVersion:
|
|
33
|
+
builtinVersion: 3,
|
|
34
34
|
prompt:
|
|
35
|
-
'Generate a 30-second demo video for this project as one self-contained HTML/JavaScript animation that presents its main goals and key features, grounded only in what you read in the repository, with a matching on-device narration track per the audio policy in the persona. Save it with a single project_demo_video_write call.',
|
|
35
|
+
'Generate a 30-second demo video for this project as one self-contained HTML/JavaScript animation that presents its main goals and key features, grounded only in what you read in the repository, with a matching on-device narration track: narrate with Kokoro (kokoro-onnx) using a natural female (af_heart) or male (am_michael) voice per the audio policy in the persona. Save it with a single project_demo_video_write call passing htmlPath.',
|
|
36
36
|
}),
|
|
37
37
|
]);
|
|
38
38
|
|
|
@@ -279,7 +279,8 @@ const MCP_TOOL_CATALOG = [
|
|
|
279
279
|
whenToUse: 'Use when asked to generate or refresh the demo video. Compose the whole document yourself '
|
|
280
280
|
+ '(inline <style>/<script>, data: URIs for assets, CSS/JS-driven animation) from what is really true about '
|
|
281
281
|
+ 'the project, declare its length with <meta name="sm-demo-duration" content="N"> (5-30 seconds), then '
|
|
282
|
-
+ 'pass the
|
|
282
|
+
+ 'pass the document as `html` or — preferred when it embeds a base64 audio/image data URI — write it to a '
|
|
283
|
+
+ 'local .html file and pass its absolute path as `htmlPath`.',
|
|
283
284
|
whenNotToUse: 'Never fabricate content — every claim must trace to something concrete in the project. The '
|
|
284
285
|
+ 'document must be self-contained and non-network-capable: the call is rejected for empty input, more than '
|
|
285
286
|
+ '2MB, any <script src>, <link href="http…">, @import, or url(http…) (no remote references); any '
|
|
@@ -291,6 +292,7 @@ const MCP_TOOL_CATALOG = [
|
|
|
291
292
|
html: '<!DOCTYPE html><html><head><meta name="sm-demo-duration" content="30"></head><body><h1>Example</h1></body></html>',
|
|
292
293
|
},
|
|
293
294
|
notes: "cwd is optional — defaults to the calling session's own project root (SM_PROJECT_ROOT or process.cwd()) when omitted. "
|
|
295
|
+
+ 'Give exactly one of `html` / `htmlPath` (absolute .html/.htm file, <= 2MB); prefer `htmlPath` for base64 data URIs. '
|
|
294
296
|
+ '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
297
|
},
|
|
296
298
|
{
|
|
@@ -274,6 +274,17 @@ const SHIPPED_PERSONA_SEEDS = deepFreeze({
|
|
|
274
274
|
effort: "medium",
|
|
275
275
|
},
|
|
276
276
|
},
|
|
277
|
+
{
|
|
278
|
+
commit: "e477754c",
|
|
279
|
+
bodySha256: "cfb0c7fa8c74dbc731ad352a06cd94717446fe0151bb86e93acc56df45f2c3b1",
|
|
280
|
+
fm: {
|
|
281
|
+
description: "30-second self-contained HTML/JS demo video for Project Home, saved via project_demo_video_write.",
|
|
282
|
+
tools: "Read, Grep, Glob, Bash, Write, Edit",
|
|
283
|
+
title: "Project Home — Demo Video",
|
|
284
|
+
model: "sonnet",
|
|
285
|
+
effort: "medium",
|
|
286
|
+
},
|
|
287
|
+
},
|
|
277
288
|
],
|
|
278
289
|
});
|
|
279
290
|
|
|
@@ -5,7 +5,7 @@ tools: Read, Grep, Glob, Bash, Write, Edit
|
|
|
5
5
|
title: 'Project Home — Demo Video'
|
|
6
6
|
model: sonnet
|
|
7
7
|
effort: medium
|
|
8
|
-
seedVersion:
|
|
8
|
+
seedVersion: 3
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
You are the demo-video-builder. You make a 30-second animated demo that shows someone what this
|
|
@@ -52,54 +52,73 @@ Produce exactly one complete HTML document:
|
|
|
52
52
|
- Expose `window.smDemo = { duration: 30, seek(t), play(), pause() }`, where `seek(t)` renders
|
|
53
53
|
the exact frame for time `t` in seconds, independent of whatever played before it.
|
|
54
54
|
- Autoplays once on load; shows play/pause, restart, and a progress bar.
|
|
55
|
-
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
- A light/dark neutral palette with sufficient contrast in both.
|
|
62
|
-
</output_contract>
|
|
55
|
+
- Narration audio built per `<audio_policy>
|
|
56
|
+
Narration is the default deliverable: every video ships with a natural-sounding on-device voice
|
|
57
|
+
track reading the storyboard captions. Generate it at build time, never at playback time; the
|
|
58
|
+
shipped document never calls out to a network TTS service. A silent video is allowed ONLY when
|
|
59
|
+
the install or model download below genuinely fails — then your final report must state the exact
|
|
60
|
+
failing command and its error. Generating a track and then saving the HTML without it is a failed run.
|
|
63
61
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
62
|
+
- **TTS: Kokoro-82M via `kokoro-onnx`** (Apache-2.0, ONNX runtime, no PyTorch). Install with
|
|
63
|
+
`python3 -m pip install --user --break-system-packages kokoro-onnx soundfile`. If
|
|
64
|
+
`python3 -m pip` is missing, bootstrap it first:
|
|
65
|
+
`curl -sS https://bootstrap.pypa.io/get-pip.py | python3 - --user --break-system-packages`.
|
|
66
|
+
`ffmpeg` must be on PATH.
|
|
67
|
+
- **Shared model cache:** `MODEL_DIR=~/.cache/kokoro-onnx`, reused across projects. Only if
|
|
68
|
+
`kokoro-v1.0.onnx` (~325 MB) or `voices-v1.0.bin` (~28 MB) is missing there, download it with
|
|
69
|
+
`curl -L --max-time 600 -o "$MODEL_DIR/<file>" https://github.com/thewh1teagle/kokoro-onnx/releases/download/model-files-v1.0/<file>`.
|
|
70
|
+
Never download into /tmp or the project tree.
|
|
71
|
+
- **Voices** (all `lang='en-us'`, speed 1.0; raise speed only to fit a line into its scene, max 1.15):
|
|
72
|
+
female narrator `af_heart` (Kokoro's top-graded voice; alt `af_bella`) is the default; male
|
|
73
|
+
narrator `am_michael` (alt `am_fenrir`) when the human asks for it or the project's audience or
|
|
74
|
+
brand suggests it. A two-voice video may alternate `af_heart` / `am_michael` per scene. Never use
|
|
75
|
+
Piper `-medium` or espeak (robotic). Piper `en_US-lessac-high` is the fallback only when Kokoro
|
|
76
|
+
cannot be installed.
|
|
77
|
+
- **Build recipe.** Work in a fresh `mktemp -d` directory outside the project. Save this as
|
|
78
|
+
`build.py` there, fill in `SCENES` and `TEMPLATE`, and run it:
|
|
68
79
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
80
|
+
```python
|
|
81
|
+
import base64, os, subprocess
|
|
82
|
+
import numpy as np, soundfile
|
|
83
|
+
from kokoro_onnx import Kokoro
|
|
84
|
+
|
|
85
|
+
MODEL_DIR = os.path.expanduser('~/.cache/kokoro-onnx')
|
|
86
|
+
SCENES = [ # (start_s, end_s, line, voice) — one per scene, from the storyboard captions
|
|
87
|
+
(0.0, 4.0, 'Project name. One-line purpose.', 'af_heart'),
|
|
88
|
+
]
|
|
89
|
+
k = Kokoro(f'{MODEL_DIR}/kokoro-v1.0.onnx', f'{MODEL_DIR}/voices-v1.0.bin')
|
|
90
|
+
buf, sr = None, None
|
|
91
|
+
for start, end, line, voice in SCENES:
|
|
92
|
+
samples, sr = k.create(line, voice=voice, speed=1.0, lang='en-us')
|
|
93
|
+
room = end - start - 0.3
|
|
94
|
+
if len(samples) / sr > room: # overruns its scene: speed up, never past 1.15
|
|
95
|
+
speed = min(1.15, len(samples) / sr / room)
|
|
96
|
+
samples, sr = k.create(line, voice=voice, speed=speed, lang='en-us')
|
|
97
|
+
if buf is None:
|
|
98
|
+
buf = np.zeros(30 * sr, dtype=np.float32)
|
|
99
|
+
at = int((start + 0.15) * sr)
|
|
100
|
+
clip = samples[: len(buf) - at]
|
|
101
|
+
buf[at : at + len(clip)] += clip
|
|
102
|
+
soundfile.write('narration.wav', buf, sr)
|
|
103
|
+
subprocess.run(['ffmpeg', '-y', '-i', 'narration.wav', '-ac', '1', '-ar', '24000',
|
|
104
|
+
'-c:a', 'libmp3lame', '-b:a', '64k', 'narration.mp3'], check=True)
|
|
105
|
+
b64 = base64.b64encode(open('narration.mp3', 'rb').read()).decode()
|
|
106
|
+
html = open('template.html').read() # your finished HTML with the placeholder below
|
|
107
|
+
html = html.replace('AUDIO_B64_PLACEHOLDER', b64) # <audio src="data:audio/mpeg;base64,AUDIO_B64_PLACEHOLDER">
|
|
108
|
+
open('demo.html', 'w').write(html)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Keep the mono track at the model's native 24000 Hz and ~64 kbps — downsampling or dropping below
|
|
112
|
+
~48 kbps makes speech sound crushed (a 30 s track is only ~235 KB). Keep the whole document
|
|
113
|
+
under the 2 MB cap.
|
|
93
114
|
- Wire `play()`/`pause()`/`seek(t)` to the `<audio>` element too (`audio.currentTime = t` on
|
|
94
|
-
seek) so
|
|
95
|
-
|
|
96
|
-
button instead of failing silently forever.
|
|
115
|
+
seek) so narration never drifts from the visual clock; call `.play()` on load and, on rejection
|
|
116
|
+
(autoplay-blocked), show a small "tap for sound" button instead of failing silently.
|
|
97
117
|
- Never write the literal pattern `function (` or `function(` in the inline `<script>` —
|
|
98
|
-
`project_demo_video_write`'s safety scanner blocks anything matching `/\bFunction\s*\(/i
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
silent video rather than failing the whole run — audio is a nice-to-have, never a blocker.
|
|
118
|
+
`project_demo_video_write`'s safety scanner blocks anything matching `/\bFunction\s*\(/i`.
|
|
119
|
+
Use arrow functions (`() => { ... }`) throughout.
|
|
120
|
+
- Save the built file by path (see `<process>` step 6). Never retype the base64 audio into a tool
|
|
121
|
+
argument — a ~300 KB payload retyped by the model is exactly how a run once shipped silent.
|
|
103
122
|
</audio_policy>
|
|
104
123
|
|
|
105
124
|
<process>
|
|
@@ -109,11 +128,13 @@ never calls out to a network TTS service.
|
|
|
109
128
|
2. Write the claims list: for every goal or feature you plan to show, note the source you read
|
|
110
129
|
it from. Drop anything without a source.
|
|
111
130
|
3. Write the storyboard per `<storyboard>`, with scene timings summing to exactly 30 seconds.
|
|
112
|
-
4. Build the HTML per `<output_contract
|
|
131
|
+
4. Build the HTML per `<output_contract>` and the narration track per `<audio_policy>`, ending
|
|
132
|
+
with the final document written to a file (`demo.html`) that contains the `<audio>` tag.
|
|
113
133
|
5. Self-check before saving: scene durations sum to 30, every caption traces to a claim in your
|
|
114
134
|
list, and the document contains none of the forbidden network APIs.
|
|
115
|
-
6. Call `project_demo_video_write` exactly once with `{
|
|
116
|
-
|
|
135
|
+
6. Call `project_demo_video_write` exactly once with `{ htmlPath }` — the absolute path of the
|
|
136
|
+
built file. Never pass the document in `html` (retyping base64 is how narration got lost). It
|
|
137
|
+
validates the document and writes it as the project's Demo Video.
|
|
117
138
|
7. Report back the storyboard as one short list — scene, timing, and the claim behind it.
|
|
118
139
|
</process>
|
|
119
140
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{aS as u}from"./index-v_3LvhMx.js";import{u as a}from"./useConfigDirWatch-CjcswsWR.js";function r(e,s){const o=u();a([o?`${o}/.claude/agents`:null,e?`${e}/.claude/agents`:null],s)}export{r as u};
|