@chatpanel/events 0.108.0 → 0.108.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.
- package/package.json +1 -1
- package/sideline.js +11 -11
- package/slash-commands.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chatpanel/events",
|
|
3
|
-
"version": "0.108.
|
|
3
|
+
"version": "0.108.1",
|
|
4
4
|
"description": "The canonical ChatPanel event-log and capability contracts — typed durable facts, clock-free deterministic linearization, schema upcasting, and the invariants the replay harness asserts. Pure, dependency-free ESM shared by the ChatPanel extension, gateway and bridge.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
package/sideline.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import{approxTokens as x,queryTerms as S}from"./sources-retrieval.js";const M=Object.freeze(["sideline","breakout"]),I="bringback",h="thread"
|
|
2
|
-
`)){const a=/^(#{1,6})\s+(.*)$/.exec(r);if(a){n(),
|
|
3
|
-
`);continue}
|
|
4
|
-
`:"")+r}return n(),e.map((r,a)=>({n:a+1,label:r.label||`paragraph ${a+1}`,text:r.text}))}function p(t){if(!t)return{kind:"text",title:"",units:[],focus:"",sources:[]};if(Array.isArray(t.units))return{kind:t.kind||"text",title:t.title||"",units:t.units,focus:t.focus||"",sources:t.sources||[]};const e=t.body||t,n=!!(t.sidelineOf||t.meta?.sidelineOf)?"sideline":t.kind||(Array.isArray(e.messages)?"chat":e.markdown!=null?"note":Array.isArray(e.segments)?"meeting":"text"),r=t.title||"",a=(e.attachments||[]).filter(o=>o&&o.kind!=="image"&&(o.title||o.url));if(n==="chat"||n==="sideline"){const o=$(e.messages||[]),c=[...o].reverse().find(l=>l.role==="user"),
|
|
1
|
+
import{approxTokens as x,queryTerms as S}from"./sources-retrieval.js";const M=Object.freeze(["sideline","breakout"]),I="bringback",h="thread";import{SIDELINE_SLASH_ITEMS as R}from"./slash-commands.js";function w(t){const e=/^\/(sideline|breakout)\b\s*([\s\S]*)$/i.exec(String(t||"").trim());if(!e)return null;let s=e[2].trim(),n=null;const r=/^@(?:(team|agent|cli|model):)?(?:"([^"]+)"|([^\s]+))\s*/i.exec(s);return r&&(n={kind:r[1]?r[1].toLowerCase():null,name:(r[2]||r[3]||"").trim()},s=s.slice(r[0].length).trim()),{question:s,target:n}}function L(t){const e=/^\/bringback\b\s*(full|brief)?\s*$/i.exec(String(t||"").trim());return e?{mode:e[1]?e[1].toLowerCase():"brief"}:null}function j(t,{teams:e=[],agents:s=[],clis:n=[],models:r=[]}={}){if(!t?.name)return null;const a=t.name.toLowerCase(),o=i=>String(i||"").toLowerCase()===a,c=[["team",e,i=>o(i.name)||o(i.id)],["agent",s,i=>o(i.name)||o(i.id)],["cli",n,i=>o(i.id)||o(i.label)||o(i.name)],["model",r,i=>o(i.id)||o(i.label)||o(i.model)||o(i.name)]];for(const[i,l,u]of c){if(t.kind&&t.kind!==i)continue;const f=(l||[]).find(d=>d&&u(d));if(f)return{kind:i,ref:f}}return null}function $(t=[]){return(t||[]).filter(e=>e&&(e.role==="user"||e.role==="assistant"))}const b=Object.freeze({chat:"message",sideline:"message",note:"section",meeting:"segment",run:"post",text:"part"});function g(t=""){const e=[];let s=null;const n=()=>{s&&s.text.trim()&&e.push({label:s.label,text:s.text.trim()}),s=null};for(const r of String(t||"").split(`
|
|
2
|
+
`)){const a=/^(#{1,6})\s+(.*)$/.exec(r);if(a){n(),s={label:a[2].trim().slice(0,80)||"section",text:""};continue}if(!r.trim()){s&&!s.label?n():s&&(s.text+=`
|
|
3
|
+
`);continue}s||(s={label:"",text:""}),s.text+=(s.text?`
|
|
4
|
+
`:"")+r}return n(),e.map((r,a)=>({n:a+1,label:r.label||`paragraph ${a+1}`,text:r.text}))}function p(t){if(!t)return{kind:"text",title:"",units:[],focus:"",sources:[]};if(Array.isArray(t.units))return{kind:t.kind||"text",title:t.title||"",units:t.units,focus:t.focus||"",sources:t.sources||[]};const e=t.body||t,n=!!(t.sidelineOf||t.meta?.sidelineOf)?"sideline":t.kind||(Array.isArray(e.messages)?"chat":e.markdown!=null?"note":Array.isArray(e.segments)?"meeting":"text"),r=t.title||"",a=(e.attachments||[]).filter(o=>o&&o.kind!=="image"&&(o.title||o.url));if(n==="chat"||n==="sideline"){const o=$(e.messages||[]),c=[...o].reverse().find(l=>l.role==="user"),i=(e.messages||[]).flatMap(l=>(l.attachments||[]).filter(u=>u&&u.kind!=="image"&&u.kind!=="sideline"&&(u.title||u.url)));return{kind:n,title:r,sources:[...a,...i],units:o.map((l,u)=>({n:u+1,label:l.role,text:String(l.content||"")})),focus:String(c?.content||"")}}if(n==="note")return{kind:n,title:r,sources:a,units:g(e.markdown??e.text??""),focus:""};if(n==="meeting"){const o=Array.isArray(e.segments)?e.segments:[],c=o.length?o.map((i,l)=>({n:l+1,label:i.speaker||i.who||"speaker",text:String(i.text||"")})):g(e.summary?`# Summary
|
|
5
5
|
${e.summary}
|
|
6
6
|
|
|
7
|
-
${e.text||e.transcript||""}`:e.text||e.transcript||"");return{kind:n,title:r,sources:a,units:c,focus:String(e.summary||"").slice(0,240)}}if(n==="run"||Array.isArray(e.posts)){const o=e.posts||e.steps||[];return{kind:"run",title:r,sources:a,units:o.map((c,
|
|
8
|
-
`)}const N=Object.freeze({name:h,annotations:{readOnlyHint:!0,idempotentHint:!0},description:"Search or read what this sideline branched from — the main thread, note, meeting or run. Its content is not in this conversation; use this when the question depends on what was said or found there.",parameters:{type:"object",properties:{action:{type:"string",enum:["search","read","latest"],description:"search: parts matching a query (numbered). read: parts from..to by number. latest: the last n parts."},query:{type:"string",description:"For search: what you are looking for."},from:{type:"integer",description:"For read: first part number (1 = oldest)."},to:{type:"integer",description:"For read: last part number (inclusive)."},n:{type:"integer",description:"For latest: how many (default 4)."}},required:["action"],additionalProperties:!1}}),y=320;function A(t,e){const
|
|
7
|
+
${e.text||e.transcript||""}`:e.text||e.transcript||"");return{kind:n,title:r,sources:a,units:c,focus:String(e.summary||"").slice(0,240)}}if(n==="run"||Array.isArray(e.posts)){const o=e.posts||e.steps||[];return{kind:"run",title:r,sources:a,units:o.map((c,i)=>({n:i+1,label:c.actor||c.by||c.role||"post",text:String(c.text||c.content||"")})),focus:String(e.goal||e.request||"")}}return{kind:"text",title:r,sources:a,units:g(e.text||e.markdown||""),focus:""}}function O(t={}){const e=t.units?t:p(t.messages?{kind:"chat",title:t.title,body:{messages:t.messages,attachments:t.sources}}:t),s=b[e.kind]||"part",n=e.kind==="note"?"Main note":e.kind==="meeting"?"Meeting":e.kind==="run"?"Team run":"Main thread",r=String(e.focus||"").replace(/\s+/g," ").trim().slice(0,240),a=(e.sources||[]).map(c=>c?.title||c?.url).filter(Boolean).slice(0,6);return[`${n}${e.title?`: "${e.title}"`:""} — ${e.units.length} ${s}${e.units.length===1?"":"s"}, ~${x(e.units.map(c=>c.text).join(" "))} tokens.`,r?e.kind==="meeting"?`Summary: "${r}${r.length===240?"…":""}"`:`It is currently working on: "${r}${r.length===240?"…":""}"`:"",a.length?`Attached there: ${a.join(" · ")}.`:"",`Its content is NOT in this conversation. Call \`${h}\` to search it or read a range of ${s}s when the question depends on it — and only then.`].filter(Boolean).join(`
|
|
8
|
+
`)}const N=Object.freeze({name:h,annotations:{readOnlyHint:!0,idempotentHint:!0},description:"Search or read what this sideline branched from — the main thread, note, meeting or run. Its content is not in this conversation; use this when the question depends on what was said or found there.",parameters:{type:"object",properties:{action:{type:"string",enum:["search","read","latest"],description:"search: parts matching a query (numbered). read: parts from..to by number. latest: the last n parts."},query:{type:"string",description:"For search: what you are looking for."},from:{type:"integer",description:"For read: first part number (1 = oldest)."},to:{type:"integer",description:"For read: last part number (inclusive)."},n:{type:"integer",description:"For latest: how many (default 4)."}},required:["action"],additionalProperties:!1}}),y=320;function A(t,e){const s=String(t||"").replace(/\s+/g," ").trim();if(s.length<=y)return s;const n=s.toLowerCase();let r=-1;for(const o of e)if(r=n.indexOf(o),r>=0)break;const a=Math.max(0,r-80);return`${a?"…":""}${s.slice(a,a+y)}…`}function q(t={},e={}){const s=t.units?t:p(t.messages?{kind:"chat",body:{messages:t.messages}}:t),n=s.units.map(o=>({n:o.n,role:o.label,text:String(o.text||"")})),r=String(e?.action||"latest");if(r==="search"){const o=S(e?.query);if(!o.length)return{error:"search needs a query."};const c=n.map(i=>({...i,score:o.reduce((l,u)=>l+(i.text.toLowerCase().includes(u)?Math.min(3,u.length/4):0),0)})).filter(i=>i.score>0).sort((i,l)=>l.score-i.score||i.n-l.n).slice(0,6).sort((i,l)=>i.n-l.n).map(i=>({n:i.n,role:i.role,snippet:A(i.text,o)}));return{of:n.length,hits:c,note:c.length?'Read a range with action "read" for the full text.':"Nothing there mentions that."}}if(r==="read"){const o=Math.max(1,Number(e?.from)||1),c=Math.min(n.length,Number(e?.to)||o);if(o>n.length)return{error:`There are ${n.length} ${b[s.kind]||"part"}s.`};const i=n.filter(d=>d.n>=o&&d.n<=c);let l=2e3*4;const u=[];let f=!1;for(const d of i){if(l<=0){f=!0;break}const m=d.text.length>l?`${d.text.slice(0,l)}…`:d.text;m.length<d.text.length&&(f=!0),l-=m.length,u.push({n:d.n,role:d.role,text:m})}return{of:n.length,from:o,to:c,messages:u,truncated:f}}const a=Math.max(1,Math.min(12,Number(e?.n)||4));return{of:n.length,messages:n.slice(-a).map(o=>({n:o.n,role:o.role,text:o.text.length>1600?`${o.text.slice(0,1600)}…`:o.text}))}}function C(t={}){const e=t.units?t:p(t.messages?{kind:"chat",title:t.title,body:{messages:t.messages,attachments:t.sources}}:t),s=O(e);return{specs:[{...N}],system:s,systemParts:{thread:x(s)},async execute(n,r){if(n!==h)return JSON.stringify({error:`Unknown tool: ${n}`});const a=typeof r=="string"?JSON.parse(r||"{}"):r||{};return JSON.stringify(q(e,a))}}}function _({title:t="",turns:e=[]}={}){const s=(e||[]).filter(n=>n&&(n.role==="user"||n.role==="assistant")).map(n=>`${n.role==="user"?"Asked":"Answered"}: ${String(n.content||"").trim()}`).join(`
|
|
9
9
|
|
|
10
|
-
`);return[`This was a side conversation${t?` about "${t}"`:""}, held apart from a main thread that is still being worked on. Write the brief the main thread should receive.`,"Rules: at most 120 words. State what was asked, the answer, any decision or recommendation, and anything still open. Plain prose or up to four short bullets. No preamble, no headings, no restating the main thread.","",
|
|
11
|
-
`)}function
|
|
10
|
+
`);return[`This was a side conversation${t?` about "${t}"`:""}, held apart from a main thread that is still being worked on. Write the brief the main thread should receive.`,"Rules: at most 120 words. State what was asked, the answer, any decision or recommendation, and anything still open. Plain prose or up to four short bullets. No preamble, no headings, no restating the main thread.","",s].join(`
|
|
11
|
+
`)}function P({sideline:t,mode:e="brief",brief:s="",now:n=Date.now,newId:r=()=>`sl_${Math.random().toString(36).slice(2,10)}`}={}){const a=(t?.turns||[]).filter(l=>l&&(l.role==="user"||l.role==="assistant")),o=a.map(l=>`${l.role==="user"?"Asked":"Answered"}: ${String(l.content||"").trim()}`).join(`
|
|
12
12
|
|
|
13
|
-
`),c=e==="full"?o:String(
|
|
13
|
+
`),c=e==="full"?o:String(s||"").trim()||o,i=`From Sideline ${t?.index||1}${t?.model?` · ${t.model}`:""}`;return{id:r(),role:"note",kind:"sideline",ts:n(),content:c,sideline:{id:t?.id||null,index:t?.index||1,model:t?.model||"",turns:a.length,mode:e,broughtBackAt:n()},attachments:[{kind:"sideline",title:i,text:c}]}}function v(t=[]){const e=Array.isArray(t)?t:[];if(!e.some(r=>r?.role==="note"))return e;const s=[];let n=[];for(const r of e){if(r?.role==="note"){n.push(...r.attachments||[]);continue}if(r?.role==="user"&&n.length){s.push({...r,attachments:[...n,...r.attachments||[]]}),n=[];continue}s.push(r)}return s}function B(t=[]){return(t||[]).reduce((e,s)=>Math.max(e,Number(s?.index)||0),0)+1}function D(t,e){const s=[];let n=t,r=0;for(;n&&(n.sideline||n.meta?.sideline)&&r++<16;)s.unshift((n.sideline||n.meta?.sideline)?.index||1),n=e?.(n)||null;return s.join(".")}function J(t,e){if(t==="note"){const s=e.attachments?.[0]?.title||`From Sideline ${e.sideline?.index||1}`,n=String(e.content||"").trim().split(`
|
|
14
14
|
`).map(r=>`> ${r}`).join(`
|
|
15
15
|
`);return{kind:"markdown",markdown:`
|
|
16
16
|
|
|
17
|
-
> **${
|
|
17
|
+
> **${s}**
|
|
18
18
|
${n}
|
|
19
|
-
`}}return{kind:"message",message:e}}const k="sideline",T=Object.freeze({name:k,annotations:{readOnlyHint:!1,idempotentHint:!1},description:"Open a SIDELINE — a separate conversation about one question, apart from this one — and get its brief back. Use it to fork a sub-question to a team, an agent or another model without cluttering this thread; the sideline can search or read this thread with its own `thread` tool. Returns the brief (or the full text) when it is done.",parameters:{type:"object",properties:{question:{type:"string",description:"The question or task for the sideline, self-contained."},target:{type:"string",description:"Optional: who answers — a team name, an agent name, a CLI agent or a model id. Omit for the same model as this conversation."},bring:{type:"string",enum:["brief","full"],description:"What comes back: a brief (default) or the full exchange."}},required:["question"],additionalProperties:!1}});function U({run:t,depth:e=0,maxDepth:
|
|
19
|
+
`}}return{kind:"message",message:e}}const k="sideline",T=Object.freeze({name:k,annotations:{readOnlyHint:!1,idempotentHint:!1},description:"Open a SIDELINE — a separate conversation about one question, apart from this one — and get its brief back. Use it to fork a sub-question to a team, an agent or another model without cluttering this thread; the sideline can search or read this thread with its own `thread` tool. Returns the brief (or the full text) when it is done.",parameters:{type:"object",properties:{question:{type:"string",description:"The question or task for the sideline, self-contained."},target:{type:"string",description:"Optional: who answers — a team name, an agent name, a CLI agent or a model id. Omit for the same model as this conversation."},bring:{type:"string",enum:["brief","full"],description:"What comes back: a brief (default) or the full exchange."}},required:["question"],additionalProperties:!1}});function U({run:t,depth:e=0,maxDepth:s=3}={}){if(typeof t!="function")throw new Error("sidelineToolProvider: run required");return{specs:[{...T}],system:"You may fork a sub-question into a `sideline` (a team, an agent or a model works on it apart from this thread and you get the brief back). Use it for work that would otherwise clutter this thread; do not use it for a question you can answer directly.",async execute(n,r){if(n!==k)return JSON.stringify({error:`Unknown tool: ${n}`});const a=typeof r=="string"?JSON.parse(r||"{}"):r||{},o=String(a.question||"").trim();if(!o)return JSON.stringify({error:"question is required."});if(e>=s)return JSON.stringify({error:`Sidelines nest at most ${s} deep; answer this one here.`});const c=a.target&&w(`/sideline @${/\s/.test(String(a.target))?`"${a.target}"`:a.target} x`)?.target||null;try{const i=await t({question:o,target:c,bring:a.bring==="full"?"full":"brief"});return JSON.stringify({sideline:i?.index!=null?`Sideline ${i.index}`:"sideline",id:i?.id||null,model:i?.model||"",brief:String(i?.brief||"")})}catch(i){return JSON.stringify({error:`The sideline failed: ${i?.message||i}`})}}}}export{I as BRINGBACK_COMMAND,M as SIDELINE_COMMANDS,R as SIDELINE_SLASH_ITEMS,k as SIDELINE_TOOL_NAME,T as SIDELINE_TOOL_SPEC,h as THREAD_TOOL_NAME,N as THREAD_TOOL_SPEC,_ as briefPrompt,J as foldBackFor,P as foldBackNote,v as foldNotes,B as nextSidelineIndex,g as noteUnits,L as parseBringBack,w as parseSideline,q as readThread,j as resolveSidelineTarget,D as sidelinePath,U as sidelineToolProvider,p as sourceOf,O as threadManifest,C as threadToolProvider};
|
package/slash-commands.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function p(e){return String(e||"").toLowerCase().replace(/^\//,"").replace(/\s+/g," ")}function g(e){return{type:"skill",command:e.command||"",icon:e.icon||"🎓",description:e.description||e.name||"",skill:e}}function h(e){return{type:"recipe",command:e.name||"",icon:"🧩",description:e.description||"Saved recipe",recipe:e}}function S(e){const t=!!e.origin?.agent;return{type:"team",command:e.name||"",icon:t?"🧑💻":"🧑🤝🧑",description:e.description||(t?"Agent":"Agent team"),team:e,...t?{agent:e.origin.agent}:{}}}function i(e){return(Array.isArray(e)?e:[]).filter(t=>!!t&&t.enabled!==!1)}function x({builtins:e=[],skills:t=[],recipes:n=[],teams:
|
|
1
|
+
function p(e){return String(e||"").toLowerCase().replace(/^\//,"").replace(/\s+/g," ")}function g(e){return{type:"skill",command:e.command||"",icon:e.icon||"🎓",description:e.description||e.name||"",skill:e}}function h(e){return{type:"recipe",command:e.name||"",icon:"🧩",description:e.description||"Saved recipe",recipe:e}}function S(e){const t=!!e.origin?.agent;return{type:"team",command:e.name||"",icon:t?"🧑💻":"🧑🤝🧑",description:e.description||(t?"Agent":"Agent team"),team:e,...t?{agent:e.origin.agent}:{}}}function i(e){return(Array.isArray(e)?e:[]).filter(t=>!!t&&t.enabled!==!1)}function x({builtins:e=[],skills:t=[],recipes:n=[],teams:a=[],prefix:o="",skillsAllowed:s=!1,features:c={}}={}){const m=p(o),l=(Array.isArray(e)?e:[]).map(r=>({type:"builtin",...r,locked:!!r.feature&&!c[r.feature]})),u=s?i(t).map(g):[],d=(n||[]).filter(r=>r&&r.enabled!==!1&&r.name).map(h),f=(a||[]).filter(r=>r&&r.enabled!==!1&&r.name).map(S);return[...l,...u,...d,...f].filter(r=>r.command&&r.command.toLowerCase().startsWith(m)).slice(0,12)}const $=Object.freeze([{command:"sideline",icon:"⇲",description:"Ask on the side without stopping this thread — @ a team, agent or model to hand it elsewhere"},{command:"bringback",icon:"⇱",description:'Fold the open sideline into this thread as a brief (or "full")'},{command:"breakout",icon:"⇲",description:"Same as /sideline"}]),I=/^\/([a-z0-9_-]*(?:\s+[a-z0-9_-]*)?)$/i;function b(e,t=[]){const n=/^\/([a-z0-9_-]+)\s*([\s\S]*)$/i.exec(String(e||""));if(!n)return null;const a=i(t).find(o=>String(o.command||"").toLowerCase()===n[1].toLowerCase());return a?{skill:a,args:n[2].trim()}:null}function w(e,t=[]){const n=/^\/([a-z0-9_-]+)\s*([\s\S]*)$/i.exec(String(e||""));if(!n)return null;const a=(t||[]).find(o=>o&&o.enabled!==!1&&String(o.name||"").toLowerCase()===n[1].toLowerCase());return a?{recipe:a,args:n[2].trim()}:null}function L(e,t=""){const n=String(t||"").trim();return`Run the saved recipe "${e.name}"${n?` with this input: ${n}`:""}. Use the recipe tool; if a parameter is missing, ask for it.`}function C(e,t=[]){const n=/^\/([a-z0-9_-]+)\s*([\s\S]*)$/i.exec(String(e||""));if(!n)return null;const a=(t||[]).find(o=>o&&o.enabled!==!1&&String(o.name||"").toLowerCase()===n[1].toLowerCase());return a?{team:a,args:n[2].trim()}:null}function A(e,t=""){const n=String(t||"").trim();return e.origin?.agent?`Run the agent "${e.name}" (a one-role team of that name)${n?` on this request: ${n}`:""}. Use the team tool; if the request is unclear, ask first.`:`Run the saved team "${e.name}"${n?` on this request: ${n}`:""}. Use the team tool; if the request is unclear, ask first.`}function _(e){return e?.command?`/${e.command} `:"/"}function y(e,t=""){return e?.command?{command:e.command,args:String(t||"").trim(),name:e.name||"",icon:e.icon||"🎓"}:null}function z(e){return e?.command?`/${e.command}${e.args?` ${e.args}`:""}`:""}export{$ as SIDELINE_SLASH_ITEMS,I as SLASH_TYPING_RE,i as enabledSkills,w as matchSlashRecipe,b as matchSlashSkill,C as matchSlashTeam,L as recipeInvocationText,z as skillInvocationLabel,y as skillInvocationOf,_ as slashCommandInsert,x as slashCommandItems,A as teamInvocationText};
|