chainlesschain 0.45.79 → 0.45.81
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/bin/chainlesschain.js +0 -0
- package/package.json +1 -1
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{Analytics-CoH0P1ux.js → Analytics-C1AnPdMx.js} +2 -2
- package/src/assets/web-panel/assets/{AppLayout-Dk1eV3Xp.js → AppLayout-YdvJBMHH.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-Cv97eAjW.js → Backup-D31iZX3l.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-DSbYaPuD.js → Chat-DiXJ3TuK.js} +1 -1
- package/src/assets/web-panel/assets/Cowork-BnrHWwZw.js +7 -0
- package/src/assets/web-panel/assets/Cowork-CcSoS3eX.css +1 -0
- package/src/assets/web-panel/assets/{Cron-BcH0ckxq.js → Cron-DBt1ueXh.js} +2 -2
- package/src/assets/web-panel/assets/Dashboard-BS-tzGNj.css +1 -0
- package/src/assets/web-panel/assets/{Dashboard-DSOE-azo.js → Dashboard-HPh9FcPt.js} +2 -2
- package/src/assets/web-panel/assets/{Git-zd3CuuXJ.js → Git-hwQ1oZHj.js} +2 -2
- package/src/assets/web-panel/assets/{Logs-BUKXg48N.js → Logs-4D9p6PRM.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-WVxDlw0C.js → McpTools-CyAUjbbs.js} +1 -1
- package/src/assets/web-panel/assets/{Memory-BLFTgTpY.js → Memory-BMqOR7S-.js} +2 -2
- package/src/assets/web-panel/assets/{Notes-CFypT876.js → Notes-Cmas8i4E.js} +2 -2
- package/src/assets/web-panel/assets/{Organization-BOOqeyu_.js → Organization-DnSa58Tl.js} +4 -4
- package/src/assets/web-panel/assets/{P2P-D9xrbb8q.js → P2P-BxksIBWs.js} +2 -2
- package/src/assets/web-panel/assets/{Permissions-CidrpFWd.js → Permissions-Bq5Qn2s3.js} +4 -4
- package/src/assets/web-panel/assets/{Projects-D3Ycn8xG.js → Projects-B7EM0uPg.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-D0kMUvHz.js → Providers-DAwgG5KV.js} +2 -2
- package/src/assets/web-panel/assets/{RssFeed-OQLesJxb.js → RssFeed-HSZoRXvS.js} +2 -2
- package/src/assets/web-panel/assets/{Security-BR4hAAkF.js → Security-Cz17qBny.js} +3 -3
- package/src/assets/web-panel/assets/{Services-BFMDfXE5.js → Services-D2EsLq-v.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-BAf_mFKw.js → Skills-C9v-f3vZ.js} +1 -1
- package/src/assets/web-panel/assets/{Tasks-DuNOWfjU.js → Tasks-yMEcU0n7.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-buh__Yll.js → Templates-l7SvlKuB.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-vgS5USvW.js → Wallet-BHWhLWn9.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-BoL2UJ5Z.js → WebAuthn-kWhFYaUK.js} +4 -4
- package/src/assets/web-panel/assets/{antd-BQNxIyr-.js → antd-D6h4fDFf.js} +82 -82
- package/src/assets/web-panel/assets/{chat-BwUxWn7i.js → chat-BYmuDvol.js} +1 -1
- package/src/assets/web-panel/assets/{index-CCRLEutJ.js → index-ByUk2Wmr.js} +2 -2
- package/src/assets/web-panel/assets/{markdown-BeVIhIzs.js → markdown-BZsB-Dsv.js} +1 -1
- package/src/assets/web-panel/assets/ws-Dma34ig_.js +1 -0
- package/src/assets/web-panel/index.html +2 -2
- package/src/gateways/ws/action-protocol.js +101 -0
- package/src/gateways/ws/message-dispatcher.js +3 -0
- package/src/gateways/ws/session-protocol.js +2 -0
- package/src/gateways/ws/ws-agent-handler.js +1 -0
- package/src/gateways/ws/ws-server.js +18 -0
- package/src/gateways/ws/ws-session-gateway.js +1 -0
- package/src/lib/cowork-task-runner.js +55 -3
- package/src/lib/cowork-task-templates.js +105 -0
- package/src/lib/sub-agent-context.js +26 -0
- package/src/runtime/agent-core.js +6 -1
- package/src/runtime/coding-agent-shell-policy.cjs +16 -1
- package/src/assets/web-panel/assets/Cowork-CPqYhoMI.css +0 -1
- package/src/assets/web-panel/assets/Cowork-DY0Jcql7.js +0 -48
- package/src/assets/web-panel/assets/Dashboard-CKeMmCoT.css +0 -1
- package/src/assets/web-panel/assets/ws-B4fo9ew1.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{V as M,f as g,r as w}from"./vendor-CN0Iv_qZ.js";import{u as f}from"./ws-
|
|
1
|
+
import{V as M,f as g,r as w}from"./vendor-CN0Iv_qZ.js";import{u as f}from"./ws-Dma34ig_.js";const S="新对话",T="新 Agent",b={"assistant.delta":"response-token","assistant.final":"response-complete","assistant.message":"response-complete","tool.call.started":"tool-executing","tool.call.completed":"tool-result","tool.call.failed":"tool-result","slot.filling":"question","approval.requested":"question",error:"error"},U=M("chat",()=>{const c=g([]),p=g(null),i=w({}),a=w({}),m=w({}),d=g(!1);let q=null;const A=new Set;function h(t){return i[t]||(i[t]=[]),i[t]}function y(t){if(!t?.id)return;const e=c.value.find(n=>n.id===t.id);if(e){Object.assign(e,t);return}c.value.unshift(t)}function C(t,e=f()){i[t]||(i[t]=[]),a[t]||(a[t]={content:"",active:!1}),!A.has(t)&&(A.add(t),e.onSession(t,n=>_(t,n)))}function v(t=f()){q||(q=t.onRuntimeEvent(e=>{const n=e.payload||{},s=n.record||{};if(e.type==="session:start"){const o=n.sessionType||s.type||"chat";y({id:n.sessionId,type:o,provider:s.provider||null,model:s.model||null,projectRoot:s.projectRoot||null,status:s.status||"created",title:o==="chat"?S:T,createdAt:Date.now(),messageCount:s.messageCount??0})}else if(e.type==="session:resume"){const o=n.sessionId;if(!o)return;Array.isArray(n.history)&&(i[o]=n.history.map(r=>({role:r.role,content:r.content,timestamp:r.timestamp||Date.now()}))),a[o]||(a[o]={content:"",active:!1}),y({id:o,type:s.type||null,provider:s.provider||null,model:s.model||null,projectRoot:s.projectRoot||null,status:s.status||"resumed",messageCount:s.messageCount??(Array.isArray(n.history)?n.history.length:0)})}else if(e.type==="session:end"){const o=n.sessionId;c.value=c.value.filter(r=>r.id!==o),p.value===o&&(p.value=c.value[0]?.id||null)}}))}async function D(){const t=f();v(t),c.value=await t.listSessions()}async function E(t="chat",e={}){const n=f();v(n);const s=await n.createSession(t,null,e);return y({id:s,type:t,title:t==="chat"?S:T,createdAt:Date.now(),messageCount:0}),C(s,n),p.value=s,s}function _(t,e){const n=h(t),s=b[e.type]||e.type,o=e.payload||{};if(s==="response-token"){a[t]||(a[t]={content:"",active:!0});const r=e.token||o.token||o.delta||o.content||"";a[t].content+=r,a[t].active=!0}else if(s==="response-complete"){const r=e.content||o.content||a[t]?.content||"";n.push({role:"assistant",content:r,timestamp:Date.now()}),a[t]&&(a[t].content="",a[t].active=!1);const l=c.value.find(u=>u.id===t);if(l&&(l.title===S||l.title===T)){const u=n.find(j=>j.role==="user");u&&(l.title=u.content.slice(0,30))}l&&(l.messageCount=n.filter(u=>u.role!=="tool").length),d.value=!1}else if(s==="tool-executing")n.push({role:"tool",tool:e.tool||o.tool||o.toolName||"unknown",input:e.input||o.input||o.args||null,status:"running",timestamp:Date.now()});else if(s==="tool-result"){const r=e.tool||o.tool||o.toolName||"unknown",l=[...n].reverse().find(u=>u.role==="tool"&&u.tool===r);l&&(l.result=e.result||o.result||o.output||null,l.status="done")}else if(s==="question")m[t]={requestId:e.requestId||o.requestId||e.id,question:e.question||o.question||o.message||"",choices:e.choices||o.choices||o.options||[]};else if(s==="error"){const r=e.message||o.message||"Unknown error";n.push({role:"assistant",content:`Error: ${r}`,timestamp:Date.now()}),d.value=!1,a[t]&&(a[t].active=!1)}}async function k(t,e){const n=f();v(n),h(t).push({role:"user",content:e,timestamp:Date.now()}),a[t]||(a[t]={content:"",active:!1}),a[t].active=!0,d.value=!0,n.sendSessionMessage(t,e)}function R(t,e){const n=f(),s=m[t];s&&(n.answerQuestion(t,s.requestId,e),delete m[t])}async function L(t){const e=f();if(v(e),p.value=t,C(t,e),!i[t]||i[t].length===0)try{await e.resumeSession(t)}catch{}}return{sessions:c,currentSessionId:p,messages:i,streaming:a,pendingQuestion:m,isLoading:d,loadSessions:D,createSession:E,sendMessage:k,answerQuestion:R,switchSession:L,getMessages:h}});export{U as u};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./AppLayout-
|
|
2
|
-
import{S as B,U as L,V as I,f as T,c as E,o as R,W as O,u as k,X as y,Y as V,Z as x,k as D,R as S,_ as w}from"./vendor-CN0Iv_qZ.js";import{a as g,A as M}from"./antd-
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./AppLayout-YdvJBMHH.js","./vendor-CN0Iv_qZ.js","./ws-Dma34ig_.js","./_plugin-vue_export-helper-DlAUqK2U.js","./antd-D6h4fDFf.js","./AppLayout-cxfKLu-m.css","./Dashboard-HPh9FcPt.js","./chat-BYmuDvol.js","./Dashboard-BS-tzGNj.css","./Chat-DiXJ3TuK.js","./markdown-BZsB-Dsv.js","./Chat-DfR76jyX.css","./github-dark-Dfs9RUU9.css","./Cowork-BnrHWwZw.js","./Cowork-CcSoS3eX.css","./Services-D2EsLq-v.js","./Services-C8Qs6KXv.css","./Logs-4D9p6PRM.js","./Logs-Gf_Mv9Nx.css","./Skills-C9v-f3vZ.js","./parsers-DftYMnlk.js","./Skills-BdjRyorN.css","./Providers-DAwgG5KV.js","./Providers-BEakqcO5.css","./McpTools-CyAUjbbs.js","./McpTools-CyhSLDwf.css","./Notes-Cmas8i4E.js","./Notes-BG69sJKi.css","./Memory-BMqOR7S-.js","./Memory-DRghrGJr.css","./Cron-DBt1ueXh.js","./Tasks-yMEcU0n7.js","./Tasks-BJjN_YEm.css","./Security-Cz17qBny.js","./Security-Dwxw7rfP.css","./Permissions-Bq5Qn2s3.js","./Permissions-C9WlkGl-.css","./P2P-BxksIBWs.js","./P2P-OEzOeMZX.css","./Git-hwQ1oZHj.js","./Git-DGcuBXST.css","./Projects-B7EM0uPg.js","./Projects-DxKelI5h.css","./Wallet-BHWhLWn9.js","./Wallet-DnIumafl.css","./Organization-DnSa58Tl.js","./Organization-DdOOM4ic.css","./Analytics-C1AnPdMx.js","./Analytics-B4OM8S8X.css","./Templates-l7SvlKuB.js","./Templates-DOY_oZnm.css","./Backup-D31iZX3l.js","./Backup-fZqtfC1m.css","./RssFeed-HSZoRXvS.js","./RssFeed-BlFC20eg.css","./WebAuthn-kWhFYaUK.js","./WebAuthn-CNPl2VQR.css"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{S as B,U as L,V as I,f as T,c as E,o as R,W as O,u as k,X as y,Y as V,Z as x,k as D,R as S,_ as w}from"./vendor-CN0Iv_qZ.js";import{a as g,A as M}from"./antd-D6h4fDFf.js";(function(){const a=document.createElement("link").relList;if(a&&a.supports&&a.supports("modulepreload"))return;for(const t of document.querySelectorAll('link[rel="modulepreload"]'))m(t);new MutationObserver(t=>{for(const o of t)if(o.type==="childList")for(const n of o.addedNodes)n.tagName==="LINK"&&n.rel==="modulepreload"&&m(n)}).observe(document,{childList:!0,subtree:!0});function c(t){const o={};return t.integrity&&(o.integrity=t.integrity),t.referrerPolicy&&(o.referrerPolicy=t.referrerPolicy),t.crossOrigin==="use-credentials"?o.credentials="include":t.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function m(t){if(t.ep)return;t.ep=!0;const o=c(t);fetch(t.href,o)}})();const C="modulepreload",N=function(s,a){return new URL(s,a).href},P={},e=function(a,c,m){let t=Promise.resolve();if(c&&c.length>0){let b=function(i){return Promise.all(i.map(d=>Promise.resolve(d).then(p=>({status:"fulfilled",value:p}),p=>({status:"rejected",reason:p}))))};const n=document.getElementsByTagName("link"),r=document.querySelector("meta[property=csp-nonce]"),u=r?.nonce||r?.getAttribute("nonce");t=b(c.map(i=>{if(i=N(i,m),i in P)return;P[i]=!0;const d=i.endsWith(".css"),p=d?'[rel="stylesheet"]':"";if(m)for(let f=n.length-1;f>=0;f--){const _=n[f];if(_.href===i&&(!d||_.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${i}"]${p}`))return;const l=document.createElement("link");if(l.rel=d?"stylesheet":C,d||(l.as="script"),l.crossOrigin="",l.href=i,u&&l.setAttribute("nonce",u),document.head.appendChild(l),d)return new Promise((f,_)=>{l.addEventListener("load",f),l.addEventListener("error",()=>_(new Error(`Unable to preload CSS for ${i}`)))})}))}function o(n){const r=new Event("vite:preloadError",{cancelable:!0});if(r.payload=n,window.dispatchEvent(r),!r.defaultPrevented)throw n}return t.then(n=>{for(const r of n||[])r.status==="rejected"&&o(r.reason);return a().catch(o)})},U=[{path:"/",component:()=>e(()=>import("./AppLayout-YdvJBMHH.js"),__vite__mapDeps([0,1,2,3,4,5]),import.meta.url),children:[{path:"",redirect:"/dashboard"},{path:"dashboard",name:"Dashboard",component:()=>e(()=>import("./Dashboard-HPh9FcPt.js"),__vite__mapDeps([6,1,2,7,3,4,8]),import.meta.url)},{path:"chat",name:"Chat",component:()=>e(()=>import("./Chat-DiXJ3TuK.js"),__vite__mapDeps([9,1,10,4,7,2,3,11,12]),import.meta.url)},{path:"cowork",name:"Cowork",component:()=>e(()=>import("./Cowork-BnrHWwZw.js"),__vite__mapDeps([13,1,10,4,2,7,3,14,12]),import.meta.url)},{path:"services",name:"Services",component:()=>e(()=>import("./Services-D2EsLq-v.js"),__vite__mapDeps([15,2,1,3,4,16]),import.meta.url)},{path:"logs",name:"Logs",component:()=>e(()=>import("./Logs-4D9p6PRM.js"),__vite__mapDeps([17,2,1,3,4,18]),import.meta.url)},{path:"skills",name:"Skills",component:()=>e(()=>import("./Skills-C9v-f3vZ.js"),__vite__mapDeps([19,1,2,20,7,3,4,21]),import.meta.url)},{path:"providers",name:"Providers",component:()=>e(()=>import("./Providers-DAwgG5KV.js"),__vite__mapDeps([22,1,2,20,3,4,23]),import.meta.url)},{path:"mcp",name:"McpTools",component:()=>e(()=>import("./McpTools-CyAUjbbs.js"),__vite__mapDeps([24,2,1,3,4,25]),import.meta.url)},{path:"notes",name:"Notes",component:()=>e(()=>import("./Notes-Cmas8i4E.js"),__vite__mapDeps([26,2,1,3,4,27]),import.meta.url)},{path:"memory",name:"Memory",component:()=>e(()=>import("./Memory-BMqOR7S-.js"),__vite__mapDeps([28,2,1,3,4,29]),import.meta.url)},{path:"cron",name:"Cron",component:()=>e(()=>import("./Cron-DBt1ueXh.js"),__vite__mapDeps([30,2,1,4]),import.meta.url)},{path:"tasks",name:"Tasks",component:()=>e(()=>import("./Tasks-yMEcU0n7.js"),__vite__mapDeps([31,1,2,3,4,32]),import.meta.url)},{path:"security",name:"Security",component:()=>e(()=>import("./Security-Cz17qBny.js"),__vite__mapDeps([33,2,1,3,4,34]),import.meta.url)},{path:"permissions",name:"Permissions",component:()=>e(()=>import("./Permissions-Bq5Qn2s3.js"),__vite__mapDeps([35,2,1,3,4,36]),import.meta.url)},{path:"p2p",name:"P2P",component:()=>e(()=>import("./P2P-BxksIBWs.js"),__vite__mapDeps([37,2,1,3,4,38]),import.meta.url)},{path:"git",name:"Git",component:()=>e(()=>import("./Git-hwQ1oZHj.js"),__vite__mapDeps([39,2,1,3,4,40]),import.meta.url)},{path:"projects",name:"Projects",component:()=>e(()=>import("./Projects-B7EM0uPg.js"),__vite__mapDeps([41,2,1,3,4,42]),import.meta.url)},{path:"wallet",name:"Wallet",component:()=>e(()=>import("./Wallet-BHWhLWn9.js"),__vite__mapDeps([43,2,1,3,4,44]),import.meta.url)},{path:"organization",name:"Organization",component:()=>e(()=>import("./Organization-DnSa58Tl.js"),__vite__mapDeps([45,1,2,3,4,46]),import.meta.url)},{path:"analytics",name:"Analytics",component:()=>e(()=>import("./Analytics-C1AnPdMx.js"),__vite__mapDeps([47,2,1,3,4,48]),import.meta.url)},{path:"templates",name:"Templates",component:()=>e(()=>import("./Templates-l7SvlKuB.js"),__vite__mapDeps([49,1,2,3,4,50]),import.meta.url)},{path:"backup",name:"Backup",component:()=>e(()=>import("./Backup-D31iZX3l.js"),__vite__mapDeps([51,2,1,3,4,52]),import.meta.url)},{path:"rssfeed",name:"RssFeed",component:()=>e(()=>import("./RssFeed-HSZoRXvS.js"),__vite__mapDeps([53,1,2,3,4,54]),import.meta.url)},{path:"webauthn",name:"WebAuthn",component:()=>e(()=>import("./WebAuthn-kWhFYaUK.js"),__vite__mapDeps([55,2,1,3,4,56]),import.meta.url)}]}],F=B({history:L(),routes:U}),A="cc_theme",v={dark:{label:"暗黑",icon:"🌑",antd:{algorithm:g.darkAlgorithm,token:{colorPrimary:"#1677ff",colorBgBase:"#141414",colorBgContainer:"#1f1f1f",colorBgElevated:"#2a2a2a",borderRadius:8,fontFamily:'system-ui, -apple-system, "Segoe UI", sans-serif'},components:{Layout:{siderBg:"#1c1c1c",headerBg:"#1c1c1c",bodyBg:"#141414"},Menu:{darkItemBg:"#1c1c1c",darkSubMenuItemBg:"#171717"}}},vars:{"--bg-base":"#141414","--bg-sidebar":"#1c1c1c","--bg-header":"#1c1c1c","--bg-card":"#1f1f1f","--bg-card-hover":"#262626","--border-color":"#252525","--border-subtle":"#1e1e1e","--text-primary":"#e0e0e0","--text-secondary":"#888","--text-muted":"#444","--logo-text":"#ffffff","--menu-mode":"dark","--shadow-card":"0 2px 8px rgba(0,0,0,.45)","--group-title":"#3a3a3a"}},light:{label:"亮白",icon:"☀️",antd:{algorithm:g.defaultAlgorithm,token:{colorPrimary:"#1677ff",colorBgBase:"#ffffff",colorBgContainer:"#ffffff",colorBgElevated:"#ffffff",borderRadius:8,fontFamily:'system-ui, -apple-system, "Segoe UI", sans-serif'},components:{Layout:{siderBg:"#ffffff",headerBg:"#ffffff",bodyBg:"#f4f6fb"},Menu:{itemBg:"#ffffff"}}},vars:{"--bg-base":"#f4f6fb","--bg-sidebar":"#ffffff","--bg-header":"#ffffff","--bg-card":"#ffffff","--bg-card-hover":"#f0f4ff","--border-color":"#e8edf5","--border-subtle":"#f0f0f0","--text-primary":"#1a1a2e","--text-secondary":"#5a6474","--text-muted":"#b0b8c8","--logo-text":"#1a1a2e","--menu-mode":"light","--shadow-card":"0 2px 12px rgba(0,0,0,.07)","--group-title":"#aab0bc"}},blue:{label:"深蓝",icon:"🌊",antd:{algorithm:g.darkAlgorithm,token:{colorPrimary:"#2f80ed",colorBgBase:"#0d1117",colorBgContainer:"#161b22",colorBgElevated:"#1c2230",borderRadius:8,fontFamily:'system-ui, -apple-system, "Segoe UI", sans-serif'},components:{Layout:{siderBg:"#0f1923",headerBg:"#0f1923",bodyBg:"#0d1117"},Menu:{darkItemBg:"#0f1923",darkSubMenuItemBg:"#0b1520"}}},vars:{"--bg-base":"#0d1117","--bg-sidebar":"#0f1923","--bg-header":"#0f1923","--bg-card":"#161b22","--bg-card-hover":"#1c2230","--border-color":"#21303f","--border-subtle":"#182030","--text-primary":"#c9d8ef","--text-secondary":"#6e8caa","--text-muted":"#2d4060","--logo-text":"#e0eeff","--menu-mode":"dark","--shadow-card":"0 2px 8px rgba(0,40,80,.5)","--group-title":"#2d4060"}},green:{label:"翠绿",icon:"🌿",antd:{algorithm:g.darkAlgorithm,token:{colorPrimary:"#29a270",colorBgBase:"#0a1a12",colorBgContainer:"#0f2318",colorBgElevated:"#152e20",borderRadius:8,fontFamily:'system-ui, -apple-system, "Segoe UI", sans-serif'},components:{Layout:{siderBg:"#0c1e14",headerBg:"#0c1e14",bodyBg:"#0a1a12"},Menu:{darkItemBg:"#0c1e14",darkSubMenuItemBg:"#091810"}}},vars:{"--bg-base":"#0a1a12","--bg-sidebar":"#0c1e14","--bg-header":"#0c1e14","--bg-card":"#0f2318","--bg-card-hover":"#152e20","--border-color":"#1a3828","--border-subtle":"#122a1c","--text-primary":"#c0e8c8","--text-secondary":"#5a9a6a","--text-muted":"#1e4028","--logo-text":"#d8f0e0","--menu-mode":"dark","--shadow-card":"0 2px 8px rgba(0,40,20,.5)","--group-title":"#1e4028"}}},j=I("theme",()=>{const s=T(localStorage.getItem(A)||"light"),a=E(()=>v[s.value]||v.dark),c=E(()=>a.value.antd),m=E(()=>s.value!=="light");function t(){const r=a.value.vars,u=document.documentElement;for(const[b,i]of Object.entries(r))u.style.setProperty(b,i);u.setAttribute("data-theme",s.value)}function o(r){v[r]&&(s.value=r,localStorage.setItem(A,r),t())}function n(){t()}return{current:s,config:a,antdTheme:c,isDark:m,setTheme:o,init:n}}),W={__name:"App",setup(s){const a=j();return R(()=>a.init()),(c,m)=>{const t=y("router-view"),o=y("a-config-provider");return V(),O(o,{theme:k(a).antdTheme},{default:x(()=>[D(t)]),_:1},8,["theme"])}}},h=S(W);h.use(w());h.use(F);h.use(M);h.mount("#app");export{v as T,j as u};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{g as Yc}from"./antd-
|
|
1
|
+
import{g as Yc}from"./antd-D6h4fDFf.js";function Ni(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}let He=Ni();function Mc(a){He=a}const Lc=/[&<>"']/,qc=new RegExp(Lc.source,"g"),xc=/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,Hc=new RegExp(xc.source,"g"),Vc={"&":"&","<":"<",">":">",'"':""","'":"'"},$i=a=>Vc[a];function Ne(a,e){if(e){if(Lc.test(a))return a.replace(qc,$i)}else if(xc.test(a))return a.replace(Hc,$i);return a}const zc=/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig;function Wc(a){return a.replace(zc,(e,t)=>(t=t.toLowerCase(),t==="colon"?":":t.charAt(0)==="#"?t.charAt(1)==="x"?String.fromCharCode(parseInt(t.substring(2),16)):String.fromCharCode(+t.substring(1)):""))}const $c=/(^|[^\[])\^/g;function Z(a,e){let t=typeof a=="string"?a:a.source;e=e||"";const n={replace:(r,i)=>{let o=typeof i=="string"?i:i.source;return o=o.replace($c,"$1"),t=t.replace(r,o),n},getRegex:()=>new RegExp(t,e)};return n}function Ki(a){try{a=encodeURI(a).replace(/%25/g,"%")}catch{return null}return a}const pt={exec:()=>null};function Qi(a,e){const t=a.replace(/\|/g,(i,o,s)=>{let l=!1,_=o;for(;--_>=0&&s[_]==="\\";)l=!l;return l?"|":" |"}),n=t.split(/ \|/);let r=0;if(n[0].trim()||n.shift(),n.length>0&&!n[n.length-1].trim()&&n.pop(),e)if(n.length>e)n.splice(e);else for(;n.length<e;)n.push("");for(;r<n.length;r++)n[r]=n[r].trim().replace(/\\\|/g,"|");return n}function yt(a,e,t){const n=a.length;if(n===0)return"";let r=0;for(;r<n&&a.charAt(n-r-1)===e;)r++;return a.slice(0,n-r)}function Kc(a,e){if(a.indexOf(e[1])===-1)return-1;let t=0;for(let n=0;n<a.length;n++)if(a[n]==="\\")n++;else if(a[n]===e[0])t++;else if(a[n]===e[1]&&(t--,t<0))return n;return-1}function Xi(a,e,t,n){const r=e.href,i=e.title?Ne(e.title):null,o=a[1].replace(/\\([\[\]])/g,"$1");if(a[0].charAt(0)!=="!"){n.state.inLink=!0;const s={type:"link",raw:t,href:r,title:i,text:o,tokens:n.inlineTokens(o)};return n.state.inLink=!1,s}return{type:"image",raw:t,href:r,title:i,text:Ne(o)}}function Qc(a,e){const t=a.match(/^(\s+)(?:```)/);if(t===null)return e;const n=t[1];return e.split(`
|
|
2
2
|
`).map(r=>{const i=r.match(/^\s+/);if(i===null)return r;const[o]=i;return o.length>=n.length?r.slice(n.length):r}).join(`
|
|
3
3
|
`)}class Lt{options;rules;lexer;constructor(e){this.options=e||He}space(e){const t=this.rules.block.newline.exec(e);if(t&&t[0].length>0)return{type:"space",raw:t[0]}}code(e){const t=this.rules.block.code.exec(e);if(t){const n=t[0].replace(/^ {1,4}/gm,"");return{type:"code",raw:t[0],codeBlockStyle:"indented",text:this.options.pedantic?n:yt(n,`
|
|
4
4
|
`)}}}fences(e){const t=this.rules.block.fences.exec(e);if(t){const n=t[0],r=Qc(n,t[3]||"");return{type:"code",raw:n,lang:t[2]?t[2].trim().replace(this.rules.inline.anyPunctuation,"$1"):t[2],text:r}}}heading(e){const t=this.rules.block.heading.exec(e);if(t){let n=t[2].trim();if(/#$/.test(n)){const r=yt(n,"#");(this.options.pedantic||!r||/ $/.test(r))&&(n=r.trim())}return{type:"heading",raw:t[0],depth:t[1].length,text:n,tokens:this.lexer.inline(n)}}}hr(e){const t=this.rules.block.hr.exec(e);if(t)return{type:"hr",raw:t[0]}}blockquote(e){const t=this.rules.block.blockquote.exec(e);if(t){let n=t[0].replace(/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{V as U,f as I,c as B}from"./vendor-CN0Iv_qZ.js";let F=0;const v=()=>`wp-${++F}`,b=new Set;function d(e,n={},r={}){return{type:e,kind:r.kind||"server",sessionId:r.sessionId||n.sessionId||null,timestamp:r.timestamp||Date.now(),payload:n}}function G(e){const n=e?.type,r=e?.payload||{};switch(n){case"task:notification":return d("task:notification",{task:e.task||r.task},{kind:"server"});case"session-created":case"session.started":return d("session:start",{sessionId:e.sessionId||r.sessionId,sessionType:e.sessionType||r.sessionType||null,record:e.record||r.record||{id:e.sessionId||r.sessionId,type:e.sessionType||r.sessionType||null,status:"created",history:[],messageCount:0}},{kind:"server",sessionId:e.sessionId||r.sessionId});case"session-resumed":case"session.resumed":{const u=e.sessionId||r.sessionId,i=e.history||r.history||[];return d("session:resume",{sessionId:u,history:i,historyCount:Array.isArray(i)?i.length:0,record:e.record||r.record||{id:u,type:null,status:"resumed",history:i,messageCount:Array.isArray(i)?i.length:0}},{kind:"server",sessionId:u})}case"worktree-diff":case"worktree.diff":return d("worktree:diff:ready",{requestId:e.requestId||e.id||null,record:e.record||r.record||{branch:e.branch||r.branch||null,summary:e.summary||r.summary||null,previewEntrypoints:[{type:"worktree-diff",branch:e.branch||r.branch||null}]}},{kind:"server"});case"worktree-merged":case"worktree.merged":return d("worktree:merge:completed",{requestId:e.requestId||e.id||null,record:e.record||r.record||{branch:e.branch||r.branch||null,summary:e.summary||r.summary||null,conflicts:e.conflicts||r.conflicts||[],previewEntrypoints:e.previewEntrypoints||r.previewEntrypoints||[]}},{kind:"server"});case"compression-stats":case"context.compaction.completed":return d("compression:summary",{requestId:e.requestId||e.id||null,summary:e.summary||r.summary||{}},{kind:"server"});default:return null}}function N(e,n=null){b.forEach(r=>r(e,n||e))}function Q(e){if(!e)return null;const n=e.record||{id:e.id||null,type:e.type||null,provider:e.provider||null,model:e.model||null,projectRoot:e.projectRoot||null,messageCount:e.messageCount??0,history:e.history||[],status:e.status||null};return{...e,id:e.id||n.id,type:e.type||n.type,provider:e.provider||n.provider,model:e.model||n.model,projectRoot:e.projectRoot||n.projectRoot,messageCount:e.messageCount??n.messageCount??0,status:e.status||n.status||null,record:n}}const K=U("ws",()=>{const e=I(null),n=I("disconnected"),r=I(null),u=new Map,i=new Map;let C=null,m=1e3;const y=window.__CC_CONFIG__||{},O=B(()=>`ws://${y.wsHost||"127.0.0.1"}:${y.wsPort||18800}`);function h(){if(e.value?.readyState!==WebSocket.OPEN){n.value="connecting",r.value=null;try{const t=new WebSocket(O.value);e.value=t,t.onopen=()=>{m=1e3,y.wsToken?l({type:"auth",id:v(),token:y.wsToken}).then(()=>{n.value="connected"}).catch(()=>{n.value="connected"}):n.value="connected"},t.onmessage=s=>{let o;try{o=JSON.parse(s.data)}catch{return}x(o)},t.onerror=()=>{r.value="WebSocket error",n.value="error"},t.onclose=()=>{n.value="disconnected",e.value=null,u.forEach(({reject:s})=>s(new Error("WebSocket closed"))),u.clear(),C=setTimeout(()=>{m=Math.min(m*2,3e4),h()},m)}}catch(t){n.value="error",r.value=t.message}}}function W(){clearTimeout(C),e.value?.close(),e.value=null,n.value="disconnected"}function P(t){if(!t.version&&!t.payload)return t;const s=t.payload||{};return{...t,...s,type:t.type,sessionId:t.sessionId||s.sessionId||null}}function x(t){const{type:s}=t,o=t.requestId||t.id;let c=!1;if(o&&u.has(o)){const{resolve:w,reject:T,timeout:S}=u.get(o);clearTimeout(S),u.delete(o),c=!0;const E=P(t);E.id=o,s==="error"?T(new Error(E.message||"Unknown error")):w(E)}const a=t.sessionId||t.payload&&t.payload.sessionId||null;if(a&&i.has(a)){const w=P(t);i.get(a).forEach(S=>S(w))}k.forEach(w=>w(t));const f=G(t);return f&&N(f,t),c}const k=new Set;function q(t){return k.add(t),()=>k.delete(t)}function J(t){return b.add(t),()=>b.delete(t)}function j(t,s){return i.has(t)||i.set(t,new Set),i.get(t).add(s),()=>{i.get(t)?.delete(s),i.get(t)?.size===0&&i.delete(t)}}function l(t,s=15e3){return new Promise((o,c)=>{if(e.value?.readyState!==WebSocket.OPEN){c(new Error("WebSocket not connected"));return}const a=t.id||v(),f=setTimeout(()=>{u.delete(a),c(new Error("Request timeout"))},s);u.set(a,{resolve:o,reject:c,timeout:f}),e.value.send(JSON.stringify({...t,id:a}))})}function p(t=8e3){return n.value==="connected"?Promise.resolve():new Promise((s,o)=>{const c=Date.now()+t,a=()=>{if(n.value==="connected")return s();if(n.value==="error"||Date.now()>=c)return o(new Error(`WS not ready: ${n.value}`));setTimeout(a,150)};n.value==="disconnected"&&h(),a()})}async function R(t,s=3e4){await p(8e3);const o=await l({type:"execute",command:t},s),c=o.output??o.stdout??"",a=o.stderr??"";return{output:c||a,exitCode:o.exitCode??0}}async function A(t,s=3e4){const{output:o,exitCode:c}=await R(t,s);if(c!==0)throw new Error(`Command failed: ${o}`);try{return JSON.parse(o.trim())}catch{const a=o.match(/\{[\s\S]*\}|\[[\s\S]*\]/);if(a)return JSON.parse(a[0]);throw new Error(`Invalid JSON output: ${o.slice(0,200)}`)}}async function M(t="chat",s=null,o={}){await p(8e3);const a={type:"session-create",id:v(),sessionType:t,projectRoot:s||y.projectRoot||null};return o.systemPromptExtension&&(a.systemPromptExtension=o.systemPromptExtension),Array.isArray(o.shellPolicyOverrides)&&o.shellPolicyOverrides.length&&(a.shellPolicyOverrides=o.shellPolicyOverrides),(await l(a)).sessionId}function _(t,s){e.value?.readyState===WebSocket.OPEN&&e.value.send(JSON.stringify({type:"session-message",id:v(),sessionId:t,content:s}))}function $(t,s,o){e.value?.readyState===WebSocket.OPEN&&e.value.send(JSON.stringify({type:"session-answer",id:v(),sessionId:t,requestId:s,answer:o}))}async function D(){return await p(8e3),((await l({type:"session-list"},1e4)).sessions||[]).map(Q).filter(Boolean)}async function H(t){try{await l({type:"session-close",sessionId:t},5e3),N(d("session:end",{sessionId:t},{kind:"server",sessionId:t}),{type:"result",sessionId:t,success:!0})}catch{}}async function z(t){return await p(8e3),await l({type:"session-resume",sessionId:t},1e4)}return{status:n,error:r,wsUrl:O,connect:h,disconnect:W,waitConnected:p,onMessage:q,onRuntimeEvent:J,onSession:j,sendRaw:l,execute:R,executeJson:A,createSession:M,resumeSession:z,sendSessionMessage:_,answerQuestion:$,listSessions:D,closeSession:H}});export{K as u};
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
// Injected by web-ui-server.js at serve time
|
|
9
9
|
window.__CC_CONFIG__ = __CC_CONFIG_PLACEHOLDER__;
|
|
10
10
|
</script>
|
|
11
|
-
<script type="module" crossorigin src="./assets/index-
|
|
11
|
+
<script type="module" crossorigin src="./assets/index-ByUk2Wmr.js"></script>
|
|
12
12
|
<link rel="modulepreload" crossorigin href="./assets/vendor-CN0Iv_qZ.js">
|
|
13
|
-
<link rel="modulepreload" crossorigin href="./assets/antd-
|
|
13
|
+
<link rel="modulepreload" crossorigin href="./assets/antd-D6h4fDFf.js">
|
|
14
14
|
<link rel="stylesheet" crossorigin href="./assets/index-CyGyEIVX.css">
|
|
15
15
|
</head>
|
|
16
16
|
<body>
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// Track running cowork tasks for cancellation
|
|
2
|
+
const _runningTasks = new Map();
|
|
3
|
+
|
|
1
4
|
export async function handleCoworkTask(server, id, ws, message) {
|
|
2
5
|
const { templateId = null, userMessage, files = [] } = message;
|
|
3
6
|
|
|
@@ -11,6 +14,10 @@ export async function handleCoworkTask(server, id, ws, message) {
|
|
|
11
14
|
return;
|
|
12
15
|
}
|
|
13
16
|
|
|
17
|
+
const ac = new AbortController();
|
|
18
|
+
const trackingId = `cowork-${id}`;
|
|
19
|
+
_runningTasks.set(trackingId, ac);
|
|
20
|
+
|
|
14
21
|
try {
|
|
15
22
|
const { runCoworkTask } = await import("../../lib/cowork-task-runner.js");
|
|
16
23
|
|
|
@@ -18,6 +25,7 @@ export async function handleCoworkTask(server, id, ws, message) {
|
|
|
18
25
|
id,
|
|
19
26
|
type: "cowork:started",
|
|
20
27
|
templateId,
|
|
28
|
+
trackingId,
|
|
21
29
|
});
|
|
22
30
|
|
|
23
31
|
const result = await runCoworkTask({
|
|
@@ -26,6 +34,17 @@ export async function handleCoworkTask(server, id, ws, message) {
|
|
|
26
34
|
files,
|
|
27
35
|
cwd: server.projectRoot || process.cwd(),
|
|
28
36
|
llmOptions: {},
|
|
37
|
+
signal: ac.signal,
|
|
38
|
+
onProgress: (progress) => {
|
|
39
|
+
server._send(ws, {
|
|
40
|
+
id,
|
|
41
|
+
type: "cowork:progress",
|
|
42
|
+
event: progress.type,
|
|
43
|
+
tool: progress.tool,
|
|
44
|
+
iterationCount: progress.iterationCount,
|
|
45
|
+
tokenCount: progress.tokenCount,
|
|
46
|
+
});
|
|
47
|
+
},
|
|
29
48
|
});
|
|
30
49
|
|
|
31
50
|
server._send(ws, {
|
|
@@ -39,6 +58,7 @@ export async function handleCoworkTask(server, id, ws, message) {
|
|
|
39
58
|
artifacts: result.result?.artifacts || [],
|
|
40
59
|
toolsUsed: result.result?.toolsUsed || [],
|
|
41
60
|
iterationCount: result.result?.iterationCount || 0,
|
|
61
|
+
tokenCount: result.result?.tokenCount || 0,
|
|
42
62
|
});
|
|
43
63
|
} catch (err) {
|
|
44
64
|
server._send(ws, {
|
|
@@ -47,6 +67,36 @@ export async function handleCoworkTask(server, id, ws, message) {
|
|
|
47
67
|
code: "COWORK_FAILED",
|
|
48
68
|
message: err.message,
|
|
49
69
|
});
|
|
70
|
+
} finally {
|
|
71
|
+
_runningTasks.delete(trackingId);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function handleCoworkCancel(server, id, ws, message) {
|
|
76
|
+
const { trackingId } = message;
|
|
77
|
+
|
|
78
|
+
if (!trackingId) {
|
|
79
|
+
server._send(ws, {
|
|
80
|
+
id,
|
|
81
|
+
type: "error",
|
|
82
|
+
code: "INVALID_MESSAGE",
|
|
83
|
+
message: "trackingId field required",
|
|
84
|
+
});
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const ac = _runningTasks.get(trackingId);
|
|
89
|
+
if (ac) {
|
|
90
|
+
ac.abort();
|
|
91
|
+
_runningTasks.delete(trackingId);
|
|
92
|
+
server._send(ws, { id, type: "cowork:cancelled", trackingId });
|
|
93
|
+
} else {
|
|
94
|
+
server._send(ws, {
|
|
95
|
+
id,
|
|
96
|
+
type: "error",
|
|
97
|
+
code: "TASK_NOT_FOUND",
|
|
98
|
+
message: `No running cowork task: ${trackingId}`,
|
|
99
|
+
});
|
|
50
100
|
}
|
|
51
101
|
}
|
|
52
102
|
|
|
@@ -67,6 +117,57 @@ export function handleSlashCommand(server, id, ws, message) {
|
|
|
67
117
|
handler.handleSlashCommand(command, id);
|
|
68
118
|
}
|
|
69
119
|
|
|
120
|
+
export async function handleCoworkHistory(server, id, ws, message) {
|
|
121
|
+
const { limit = 50 } = message;
|
|
122
|
+
const cwd = server.projectRoot || process.cwd();
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
const { readFileSync, existsSync } = await import("node:fs");
|
|
126
|
+
const { join } = await import("node:path");
|
|
127
|
+
const histPath = join(cwd, ".chainlesschain", "cowork", "history.jsonl");
|
|
128
|
+
|
|
129
|
+
if (!existsSync(histPath)) {
|
|
130
|
+
server._send(ws, { id, type: "cowork:history", entries: [] });
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const lines = readFileSync(histPath, "utf-8").split("\n").filter(Boolean);
|
|
135
|
+
const entries = [];
|
|
136
|
+
for (const line of lines.slice(-limit)) {
|
|
137
|
+
try {
|
|
138
|
+
entries.push(JSON.parse(line));
|
|
139
|
+
} catch (_e) {
|
|
140
|
+
// skip malformed lines
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
server._send(ws, { id, type: "cowork:history", entries });
|
|
145
|
+
} catch (err) {
|
|
146
|
+
server._send(ws, {
|
|
147
|
+
id,
|
|
148
|
+
type: "error",
|
|
149
|
+
code: "HISTORY_FAILED",
|
|
150
|
+
message: err.message,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export async function handleCoworkTemplates(server, id, ws) {
|
|
156
|
+
try {
|
|
157
|
+
const { getTemplatesForUI } =
|
|
158
|
+
await import("../../lib/cowork-task-templates.js");
|
|
159
|
+
const templates = getTemplatesForUI();
|
|
160
|
+
server._send(ws, { id, type: "cowork:templates", templates });
|
|
161
|
+
} catch (err) {
|
|
162
|
+
server._send(ws, {
|
|
163
|
+
id,
|
|
164
|
+
type: "error",
|
|
165
|
+
code: "TEMPLATES_FAILED",
|
|
166
|
+
message: err.message,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
70
171
|
export async function handleOrchestrate(server, id, ws, message) {
|
|
71
172
|
const {
|
|
72
173
|
task,
|
|
@@ -44,6 +44,9 @@ export function createWsMessageDispatcher(server) {
|
|
|
44
44
|
"host-tool-result": () => server._handleHostToolResult(id, ws, message),
|
|
45
45
|
orchestrate: () => server._handleOrchestrate(id, ws, message),
|
|
46
46
|
"cowork-task": () => server._handleCoworkTask(id, ws, message),
|
|
47
|
+
"cowork-cancel": () => server._handleCoworkCancel(id, ws, message),
|
|
48
|
+
"cowork-templates": () => server._handleCoworkTemplates(id, ws),
|
|
49
|
+
"cowork-history": () => server._handleCoworkHistory(id, ws, message),
|
|
47
50
|
"tasks-list": () => server._handleTasksList(id, ws),
|
|
48
51
|
"tasks-stop": () => server._handleTasksStop(id, ws, message),
|
|
49
52
|
"tasks-detail": () => server._handleTaskDetail(id, ws, message),
|
|
@@ -82,6 +82,7 @@ export async function handleSessionCreate(server, id, ws, message) {
|
|
|
82
82
|
hostManagedToolPolicy,
|
|
83
83
|
worktreeIsolation,
|
|
84
84
|
systemPromptExtension,
|
|
85
|
+
shellPolicyOverrides,
|
|
85
86
|
} = message;
|
|
86
87
|
|
|
87
88
|
try {
|
|
@@ -96,6 +97,7 @@ export async function handleSessionCreate(server, id, ws, message) {
|
|
|
96
97
|
hostManagedToolPolicy,
|
|
97
98
|
worktreeIsolation,
|
|
98
99
|
systemPromptExtension,
|
|
100
|
+
shellPolicyOverrides,
|
|
99
101
|
});
|
|
100
102
|
|
|
101
103
|
const session = server.sessionManager.getSession(sessionId);
|
|
@@ -105,6 +105,7 @@ export class WSAgentHandler {
|
|
|
105
105
|
externalToolDescriptors: session.externalToolDescriptors || {},
|
|
106
106
|
externalToolExecutors: session.externalToolExecutors || {},
|
|
107
107
|
mcpClient: session.mcpClient || null,
|
|
108
|
+
shellPolicyOverrides: session.shellPolicyOverrides || null,
|
|
108
109
|
slotFiller,
|
|
109
110
|
interaction: this.interaction,
|
|
110
111
|
signal: abortController.signal,
|
|
@@ -52,6 +52,9 @@ import {
|
|
|
52
52
|
handleSlashCommand,
|
|
53
53
|
handleOrchestrate,
|
|
54
54
|
handleCoworkTask,
|
|
55
|
+
handleCoworkCancel,
|
|
56
|
+
handleCoworkTemplates,
|
|
57
|
+
handleCoworkHistory,
|
|
55
58
|
} from "./action-protocol.js";
|
|
56
59
|
import {
|
|
57
60
|
handleWorktreeDiff,
|
|
@@ -303,6 +306,21 @@ export class ChainlessChainWSServer extends EventEmitter {
|
|
|
303
306
|
return handleCoworkTask(this, id, ws, message);
|
|
304
307
|
}
|
|
305
308
|
|
|
309
|
+
/** @private — cancel a running cowork task */
|
|
310
|
+
_handleCoworkCancel(id, ws, message) {
|
|
311
|
+
return handleCoworkCancel(this, id, ws, message);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/** @private — return cowork templates for UI */
|
|
315
|
+
_handleCoworkTemplates(id, ws) {
|
|
316
|
+
return handleCoworkTemplates(this, id, ws);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/** @private — return cowork task history */
|
|
320
|
+
_handleCoworkHistory(id, ws, message) {
|
|
321
|
+
return handleCoworkHistory(this, id, ws, message);
|
|
322
|
+
}
|
|
323
|
+
|
|
306
324
|
/** @private – list background tasks */
|
|
307
325
|
async _handleTasksList(id, ws) {
|
|
308
326
|
try {
|
|
@@ -369,6 +369,7 @@ export class WSSessionManager {
|
|
|
369
369
|
pendingPatches: new Map(),
|
|
370
370
|
patchHistory: [],
|
|
371
371
|
taskGraph: null,
|
|
372
|
+
shellPolicyOverrides: options.shellPolicyOverrides || null,
|
|
372
373
|
interaction: null, // Set by ws-server after creation
|
|
373
374
|
createdAt: new Date().toISOString(),
|
|
374
375
|
lastActivity: new Date().toISOString(),
|
|
@@ -7,9 +7,15 @@
|
|
|
7
7
|
* @module cowork-task-runner
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
import { existsSync, mkdirSync, appendFileSync } from "node:fs";
|
|
11
|
+
import { join } from "node:path";
|
|
10
12
|
import { SubAgentContext } from "./sub-agent-context.js";
|
|
11
13
|
import { getTemplate } from "./cowork-task-templates.js";
|
|
12
14
|
|
|
15
|
+
// ─── Dependencies (overridable for testing) ──────────────────────────────────
|
|
16
|
+
|
|
17
|
+
export const _deps = { existsSync, mkdirSync, appendFileSync };
|
|
18
|
+
|
|
13
19
|
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
14
20
|
|
|
15
21
|
const DEFAULT_MAX_ITERATIONS = 50;
|
|
@@ -41,12 +47,22 @@ export async function runCoworkTask(options = {}) {
|
|
|
41
47
|
llmOptions = {},
|
|
42
48
|
maxIterations = DEFAULT_MAX_ITERATIONS,
|
|
43
49
|
tokenBudget = DEFAULT_TOKEN_BUDGET,
|
|
50
|
+
onProgress = null,
|
|
51
|
+
signal = null,
|
|
44
52
|
} = options;
|
|
45
53
|
|
|
46
54
|
if (!userMessage || typeof userMessage !== "string") {
|
|
47
55
|
throw new Error("userMessage is required");
|
|
48
56
|
}
|
|
49
57
|
|
|
58
|
+
// Validate file paths before starting
|
|
59
|
+
if (files.length > 0) {
|
|
60
|
+
const missing = files.filter((f) => !_deps.existsSync(f));
|
|
61
|
+
if (missing.length > 0) {
|
|
62
|
+
throw new Error(`File(s) not found: ${missing.join(", ")}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
50
66
|
// Resolve template
|
|
51
67
|
const template = getTemplate(templateId);
|
|
52
68
|
|
|
@@ -69,22 +85,35 @@ export async function runCoworkTask(options = {}) {
|
|
|
69
85
|
db,
|
|
70
86
|
llmOptions,
|
|
71
87
|
cwd,
|
|
88
|
+
onProgress,
|
|
89
|
+
signal,
|
|
72
90
|
});
|
|
73
91
|
|
|
74
92
|
const taskId = subAgent.id;
|
|
75
93
|
|
|
94
|
+
// Build loop options — pass shell policy overrides if template declares them
|
|
95
|
+
const loopOptions = {};
|
|
96
|
+
if (
|
|
97
|
+
Array.isArray(template.shellPolicyOverrides) &&
|
|
98
|
+
template.shellPolicyOverrides.length
|
|
99
|
+
) {
|
|
100
|
+
loopOptions.shellPolicyOverrides = template.shellPolicyOverrides;
|
|
101
|
+
}
|
|
102
|
+
|
|
76
103
|
// Run the agent with the user's message
|
|
77
104
|
try {
|
|
78
|
-
const result = await subAgent.run(userMessage);
|
|
79
|
-
|
|
105
|
+
const result = await subAgent.run(userMessage, loopOptions);
|
|
106
|
+
const entry = {
|
|
80
107
|
taskId,
|
|
81
108
|
status: subAgent.status,
|
|
82
109
|
templateId: template.id,
|
|
83
110
|
templateName: template.name,
|
|
84
111
|
result,
|
|
85
112
|
};
|
|
113
|
+
_appendHistory(cwd, entry, userMessage);
|
|
114
|
+
return entry;
|
|
86
115
|
} catch (err) {
|
|
87
|
-
|
|
116
|
+
const entry = {
|
|
88
117
|
taskId,
|
|
89
118
|
status: "failed",
|
|
90
119
|
templateId: template.id,
|
|
@@ -97,5 +126,28 @@ export async function runCoworkTask(options = {}) {
|
|
|
97
126
|
iterationCount: 0,
|
|
98
127
|
},
|
|
99
128
|
};
|
|
129
|
+
_appendHistory(cwd, entry, userMessage);
|
|
130
|
+
return entry;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// ─── History Persistence ─────────────────────────────────────────────────────
|
|
135
|
+
|
|
136
|
+
function _appendHistory(cwd, entry, userMessage) {
|
|
137
|
+
try {
|
|
138
|
+
const histDir = join(cwd, ".chainlesschain", "cowork");
|
|
139
|
+
_deps.mkdirSync(histDir, { recursive: true });
|
|
140
|
+
const record = {
|
|
141
|
+
...entry,
|
|
142
|
+
userMessage,
|
|
143
|
+
timestamp: new Date().toISOString(),
|
|
144
|
+
};
|
|
145
|
+
_deps.appendFileSync(
|
|
146
|
+
join(histDir, "history.jsonl"),
|
|
147
|
+
JSON.stringify(record) + "\n",
|
|
148
|
+
"utf-8",
|
|
149
|
+
);
|
|
150
|
+
} catch (_e) {
|
|
151
|
+
// Best-effort — don't fail the task for history write errors
|
|
100
152
|
}
|
|
101
153
|
}
|
|
@@ -194,6 +194,7 @@ ${ERROR_RECOVERY_PROMPT}`,
|
|
|
194
194
|
category: "research",
|
|
195
195
|
acceptsFiles: false,
|
|
196
196
|
fileTypes: [],
|
|
197
|
+
shellPolicyOverrides: ["network-download"],
|
|
197
198
|
systemPromptExtension: `你是信息检索与调研专家。
|
|
198
199
|
|
|
199
200
|
## 核心能力
|
|
@@ -394,6 +395,7 @@ ${ERROR_RECOVERY_PROMPT}`,
|
|
|
394
395
|
category: "network",
|
|
395
396
|
acceptsFiles: false,
|
|
396
397
|
fileTypes: [],
|
|
398
|
+
shellPolicyOverrides: ["network-download"],
|
|
397
399
|
systemPromptExtension: `你是网络诊断与工具专家。
|
|
398
400
|
|
|
399
401
|
## 核心能力
|
|
@@ -491,3 +493,106 @@ ${ERROR_RECOVERY_PROMPT}`,
|
|
|
491
493
|
export function listTemplateIds() {
|
|
492
494
|
return Object.keys(TASK_TEMPLATES);
|
|
493
495
|
}
|
|
496
|
+
|
|
497
|
+
// ─── UI Metadata ─────────────────────────────────────────────────────────────
|
|
498
|
+
|
|
499
|
+
const UI_METADATA = {
|
|
500
|
+
"doc-convert": {
|
|
501
|
+
icon: "FileTextOutlined",
|
|
502
|
+
description: "Word、Markdown、HTML、PDF 之间的格式互转",
|
|
503
|
+
examples: [
|
|
504
|
+
"把 report.docx 转成 PDF",
|
|
505
|
+
"合并多个 Markdown 为一个文档",
|
|
506
|
+
"把 Excel 导出为 PDF",
|
|
507
|
+
],
|
|
508
|
+
},
|
|
509
|
+
"media-process": {
|
|
510
|
+
icon: "PlayCircleOutlined",
|
|
511
|
+
description: "视频压缩、音频提取、格式转换、剪辑",
|
|
512
|
+
examples: [
|
|
513
|
+
"提取 MP4 的音频",
|
|
514
|
+
"压缩视频到 50MB 以内",
|
|
515
|
+
"剪辑 10:30 到 25:00 的片段",
|
|
516
|
+
],
|
|
517
|
+
},
|
|
518
|
+
"data-analysis": {
|
|
519
|
+
icon: "BarChartOutlined",
|
|
520
|
+
description: "CSV/Excel 分析、统计、可视化图表",
|
|
521
|
+
examples: [
|
|
522
|
+
"分析 sales.csv 的月度趋势",
|
|
523
|
+
"清洗数据去重修复格式",
|
|
524
|
+
"比较两个 CSV 的差异",
|
|
525
|
+
],
|
|
526
|
+
},
|
|
527
|
+
"web-research": {
|
|
528
|
+
icon: "SearchOutlined",
|
|
529
|
+
description: "网页抓取、API 调用、多源信息汇总",
|
|
530
|
+
examples: ["调研 AI Agent 框架对比", "查询实时汇率", "抓取网页内容并翻译"],
|
|
531
|
+
},
|
|
532
|
+
"image-process": {
|
|
533
|
+
icon: "PictureOutlined",
|
|
534
|
+
description: "批量压缩、格式转换、加水印、OCR",
|
|
535
|
+
examples: ["批量压缩到 500KB", "加水印文字", "识别图上的文字 (OCR)"],
|
|
536
|
+
},
|
|
537
|
+
"code-helper": {
|
|
538
|
+
icon: "CodeOutlined",
|
|
539
|
+
description: "生成脚本、调试代码、自动化任务",
|
|
540
|
+
examples: [
|
|
541
|
+
"写一个批量重命名脚本",
|
|
542
|
+
"调试这段报错代码",
|
|
543
|
+
"生成 REST API 脚手架",
|
|
544
|
+
],
|
|
545
|
+
},
|
|
546
|
+
"system-admin": {
|
|
547
|
+
icon: "DesktopOutlined",
|
|
548
|
+
description: "磁盘分析、进程管理、日志分析",
|
|
549
|
+
examples: [
|
|
550
|
+
"查看磁盘使用情况",
|
|
551
|
+
"找出最大的 10 个文件",
|
|
552
|
+
"列出占用端口的进程",
|
|
553
|
+
],
|
|
554
|
+
},
|
|
555
|
+
"file-organize": {
|
|
556
|
+
icon: "FolderOpenOutlined",
|
|
557
|
+
description: "批量重命名、分类整理、查找重复",
|
|
558
|
+
examples: [
|
|
559
|
+
"按文件类型分类整理",
|
|
560
|
+
"批量重命名去空格",
|
|
561
|
+
"打包排除 node_modules",
|
|
562
|
+
],
|
|
563
|
+
},
|
|
564
|
+
"network-tools": {
|
|
565
|
+
icon: "GlobalOutlined",
|
|
566
|
+
description: "API 调试、网页抓取、网络诊断",
|
|
567
|
+
examples: ["测试 API 接口", "抓取网页图片链接", "ping 测试网络延迟"],
|
|
568
|
+
},
|
|
569
|
+
"learning-assist": {
|
|
570
|
+
icon: "ReadOutlined",
|
|
571
|
+
description: "文档翻译、内容总结、论文分析",
|
|
572
|
+
examples: ["翻译 PDF 摘要", "总结长文档要点", "解释代码工作原理"],
|
|
573
|
+
},
|
|
574
|
+
};
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* Get all templates formatted for UI consumption.
|
|
578
|
+
* Returns an array of template objects with id, name, icon, category,
|
|
579
|
+
* description, examples, acceptsFiles, and optional shellPolicyOverrides.
|
|
580
|
+
* @returns {object[]}
|
|
581
|
+
*/
|
|
582
|
+
export function getTemplatesForUI() {
|
|
583
|
+
return Object.values(TASK_TEMPLATES).map((tpl) => {
|
|
584
|
+
const ui = UI_METADATA[tpl.id] || {};
|
|
585
|
+
return {
|
|
586
|
+
id: tpl.id,
|
|
587
|
+
name: tpl.name,
|
|
588
|
+
icon: ui.icon || "AppstoreOutlined",
|
|
589
|
+
category: tpl.category,
|
|
590
|
+
description: ui.description || "",
|
|
591
|
+
examples: ui.examples || [],
|
|
592
|
+
acceptsFiles: tpl.acceptsFiles,
|
|
593
|
+
...(tpl.shellPolicyOverrides
|
|
594
|
+
? { shellPolicyOverrides: tpl.shellPolicyOverrides }
|
|
595
|
+
: {}),
|
|
596
|
+
};
|
|
597
|
+
});
|
|
598
|
+
}
|
|
@@ -101,6 +101,12 @@ export class SubAgentContext {
|
|
|
101
101
|
// LLM options for chatWithTools
|
|
102
102
|
this._llmOptions = options.llmOptions || {};
|
|
103
103
|
|
|
104
|
+
// Optional progress callback for streaming events to consumers
|
|
105
|
+
this._onProgress = options.onProgress || null;
|
|
106
|
+
|
|
107
|
+
// Optional abort signal for cancellation
|
|
108
|
+
this._signal = options.signal || null;
|
|
109
|
+
|
|
104
110
|
// Build isolated system prompt
|
|
105
111
|
const basePrompt = buildSystemPrompt(this.cwd);
|
|
106
112
|
const rolePrompt = `\n\n## Sub-Agent Role: ${this.role}\nYou are a focused sub-agent with the role "${this.role}". Your task is:\n${this.task}\n\nStay focused on this specific task. Be concise and return results directly.`;
|
|
@@ -253,6 +259,26 @@ export class SubAgentContext {
|
|
|
253
259
|
this._tokenCount += Math.ceil((lastContent.length || 0) / 4);
|
|
254
260
|
}
|
|
255
261
|
|
|
262
|
+
// Emit progress to consumer if callback provided
|
|
263
|
+
if (this._onProgress) {
|
|
264
|
+
try {
|
|
265
|
+
this._onProgress({
|
|
266
|
+
type: event.type,
|
|
267
|
+
tool: event.tool || null,
|
|
268
|
+
iterationCount: this._iterationCount,
|
|
269
|
+
tokenCount: this._tokenCount,
|
|
270
|
+
});
|
|
271
|
+
} catch (_e) {
|
|
272
|
+
// Never let progress callback failures break the agent loop
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Check abort signal
|
|
277
|
+
if (this._signal?.aborted) {
|
|
278
|
+
this.forceComplete("cancelled");
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
|
|
256
282
|
// Enforce token budget
|
|
257
283
|
if (this.tokenBudget && this._tokenCount >= this.tokenBudget) {
|
|
258
284
|
this.forceComplete("token-budget-exceeded");
|