chainlesschain 0.47.5 → 0.47.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/package.json +2 -1
  2. package/src/assets/web-panel/.build-hash +1 -1
  3. package/src/assets/web-panel/assets/Analytics-BFI7jbwM.css +1 -0
  4. package/src/assets/web-panel/assets/Analytics-DQ135mAd.js +3 -0
  5. package/src/assets/web-panel/assets/AppLayout-6SPt_8Y_.js +1 -0
  6. package/src/assets/web-panel/assets/AppLayout-BFJ-Fofn.css +1 -0
  7. package/src/assets/web-panel/assets/{Backup-Ba9UybpT.js → Backup-DbVRG5vE.js} +1 -1
  8. package/src/assets/web-panel/assets/{Chat-BwXskT21.js → Chat-wVhrFK9C.js} +1 -1
  9. package/src/assets/web-panel/assets/{Cowork-UmOe7qvE.js → Cowork-lOC25IW2.js} +1 -1
  10. package/src/assets/web-panel/assets/{Cron-JHS-rc-4.js → Cron-3P0eVLTV.js} +1 -1
  11. package/src/assets/web-panel/assets/{Dashboard-B95cMCO7.js → Dashboard-Br7kCwKJ.js} +1 -1
  12. package/src/assets/web-panel/assets/{Git-CSYO0_zk.js → Git-CrDCcBig.js} +2 -2
  13. package/src/assets/web-panel/assets/{Logs-Hxw_K0km.js → Logs-BfTE8urP.js} +1 -1
  14. package/src/assets/web-panel/assets/{McpTools-DIE75TrB.js → McpTools-CsGIijNe.js} +1 -1
  15. package/src/assets/web-panel/assets/{Memory-C4KVnLlp.js → Memory-BXX_yMKJ.js} +1 -1
  16. package/src/assets/web-panel/assets/{Notes-DuzrHMAk.js → Notes-DU6Vf2cL.js} +1 -1
  17. package/src/assets/web-panel/assets/{Organization-DTq6uF82.js → Organization-Bny6yOPV.js} +4 -4
  18. package/src/assets/web-panel/assets/{P2P-C0hjlhsR.js → P2P-BxFZ1Bit.js} +2 -2
  19. package/src/assets/web-panel/assets/{Permissions-Ec0NH-xC.js → Permissions-B1j3Mtms.js} +3 -3
  20. package/src/assets/web-panel/assets/{Projects-U8D0asCS.js → Projects-D-CGscDu.js} +1 -1
  21. package/src/assets/web-panel/assets/{Providers-BngtTLvJ.js → Providers-r6NaBYMf.js} +1 -1
  22. package/src/assets/web-panel/assets/{RssFeed-B9NbwCKM.js → RssFeed-D7b68C5q.js} +1 -1
  23. package/src/assets/web-panel/assets/{Security-BL5Rkr1T.js → Security-MJfKv0EJ.js} +3 -3
  24. package/src/assets/web-panel/assets/{Services-D4MJzLld.js → Services-Yb_Q1V3d.js} +1 -1
  25. package/src/assets/web-panel/assets/{Skills-CQTOMDwF.js → Skills-DLTHcH5T.js} +1 -1
  26. package/src/assets/web-panel/assets/{Tasks-DepbJMnL.js → Tasks-CqycpPjS.js} +1 -1
  27. package/src/assets/web-panel/assets/{Templates-C24PVZPu.js → Templates-y01u2Zis.js} +1 -1
  28. package/src/assets/web-panel/assets/VideoEditing-BA1N-5kq.css +1 -0
  29. package/src/assets/web-panel/assets/VideoEditing-B_nPKw6B.js +1 -0
  30. package/src/assets/web-panel/assets/{Wallet-PQoSpN_P.js → Wallet-CsRgnjJY.js} +1 -1
  31. package/src/assets/web-panel/assets/{WebAuthn-BcuyQ4Lr.js → WebAuthn-DWoR5ADp.js} +1 -1
  32. package/src/assets/web-panel/assets/{WorkflowEditor-C-SvXbHW.js → WorkflowEditor-DBJhFPMN.js} +1 -1
  33. package/src/assets/web-panel/assets/{antd-DEjZPGMj.js → antd-Dh2t0vGq.js} +84 -84
  34. package/src/assets/web-panel/assets/index-tN-8TosE.js +2 -0
  35. package/src/assets/web-panel/assets/{markdown-CusdXFxb.js → markdown-CBnGGMzE.js} +1 -1
  36. package/src/assets/web-panel/index.html +2 -2
  37. package/src/commands/agent.js +20 -0
  38. package/src/commands/config.js +67 -0
  39. package/src/commands/mcp.js +86 -4
  40. package/src/commands/memory.js +175 -0
  41. package/src/commands/sandbox.js +80 -6
  42. package/src/commands/serve.js +10 -0
  43. package/src/commands/session.js +284 -0
  44. package/src/commands/stream.js +75 -0
  45. package/src/commands/video.js +363 -0
  46. package/src/gateways/http/envelope-http-server.js +194 -0
  47. package/src/gateways/ws/message-dispatcher.js +123 -0
  48. package/src/gateways/ws/session-core-protocol.js +427 -0
  49. package/src/gateways/ws/session-protocol.js +42 -1
  50. package/src/gateways/ws/video-protocol.js +230 -0
  51. package/src/gateways/ws/ws-server.js +72 -0
  52. package/src/gateways/ws/ws-session-gateway.js +7 -3
  53. package/src/harness/jsonl-session-store.js +17 -9
  54. package/src/index.js +8 -0
  55. package/src/lib/agent-stream.js +63 -0
  56. package/src/lib/chat-core.js +183 -6
  57. package/src/lib/cowork/ab-comparator-cli.js +44 -23
  58. package/src/lib/cowork/agent-group-runner.js +145 -0
  59. package/src/lib/cowork/debate-review-cli.js +47 -25
  60. package/src/lib/cowork/project-style-analyzer-cli.js +34 -7
  61. package/src/lib/interaction-adapter.js +59 -1
  62. package/src/lib/jsonl-session-store.js +2 -0
  63. package/src/lib/memory-injection.js +90 -0
  64. package/src/lib/provider-stream.js +120 -0
  65. package/src/lib/sandbox-v2.js +198 -3
  66. package/src/lib/session-consolidator.js +125 -0
  67. package/src/lib/session-core-singletons.js +126 -0
  68. package/src/lib/session-tail.js +128 -0
  69. package/src/lib/session-usage.js +166 -0
  70. package/src/lib/shell-approval.js +96 -0
  71. package/src/lib/ws-chat-handler.js +3 -0
  72. package/src/repl/agent-repl.js +271 -6
  73. package/src/repl/chat-repl.js +87 -100
  74. package/src/runtime/agent-core.js +98 -15
  75. package/src/runtime/agent-runtime.js +105 -3
  76. package/src/runtime/policies/agent-policy.js +10 -0
  77. package/src/session/index.js +7 -0
  78. package/src/skills/video-editing/SKILL.md +46 -0
  79. package/src/skills/video-editing/beat-snap.js +127 -0
  80. package/src/skills/video-editing/extractors/audio-extractor.js +212 -0
  81. package/src/skills/video-editing/extractors/subtitle-extractor.js +90 -0
  82. package/src/skills/video-editing/extractors/video-extractor.js +137 -0
  83. package/src/skills/video-editing/parallel-orchestrator.js +212 -0
  84. package/src/skills/video-editing/pipeline.js +480 -0
  85. package/src/skills/video-editing/prompts/aesthetic-analysis.md +21 -0
  86. package/src/skills/video-editing/prompts/audio-segment.md +15 -0
  87. package/src/skills/video-editing/prompts/character-identify.md +19 -0
  88. package/src/skills/video-editing/prompts/dense-caption.md +20 -0
  89. package/src/skills/video-editing/prompts/editor-system.md +29 -0
  90. package/src/skills/video-editing/prompts/hook-dialogue.md +17 -0
  91. package/src/skills/video-editing/prompts/protagonist-detect.md +20 -0
  92. package/src/skills/video-editing/prompts/scene-caption.md +16 -0
  93. package/src/skills/video-editing/prompts/shot-caption.md +25 -0
  94. package/src/skills/video-editing/prompts/shot-plan.md +28 -0
  95. package/src/skills/video-editing/prompts/structure-proposal.md +16 -0
  96. package/src/skills/video-editing/prompts/vlog-scene-caption.md +18 -0
  97. package/src/skills/video-editing/render/audio-mix.js +128 -0
  98. package/src/skills/video-editing/render/ffmpeg-concat.js +45 -0
  99. package/src/skills/video-editing/render/ffmpeg-extract.js +67 -0
  100. package/src/skills/video-editing/reviewer.js +161 -0
  101. package/src/skills/video-editing/tools/commit.js +108 -0
  102. package/src/skills/video-editing/tools/review-clip.js +46 -0
  103. package/src/skills/video-editing/tools/semantic-retrieval.js +56 -0
  104. package/src/skills/video-editing/tools/shot-trimming.js +73 -0
  105. package/src/assets/web-panel/assets/Analytics-B4OM8S8X.css +0 -1
  106. package/src/assets/web-panel/assets/Analytics-DgypYeUB.js +0 -3
  107. package/src/assets/web-panel/assets/AppLayout-Bzf3mSZI.js +0 -1
  108. package/src/assets/web-panel/assets/AppLayout-DQyDwGut.css +0 -1
  109. package/src/assets/web-panel/assets/index-CwvzTTw_.js +0 -2
@@ -0,0 +1,2 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./AppLayout-6SPt_8Y_.js","./vendor-CN0Iv_qZ.js","./ws-Dma34ig_.js","./_plugin-vue_export-helper-DlAUqK2U.js","./antd-Dh2t0vGq.js","./AppLayout-BFJ-Fofn.css","./Dashboard-Br7kCwKJ.js","./chat-BYmuDvol.js","./Dashboard-CKeMmCoT.css","./Chat-wVhrFK9C.js","./markdown-CBnGGMzE.js","./Chat-DfR76jyX.css","./github-dark-Dfs9RUU9.css","./Cowork-lOC25IW2.js","./Cowork-CXuhlHew.css","./Services-Yb_Q1V3d.js","./Services-C8Qs6KXv.css","./Logs-BfTE8urP.js","./Logs-Gf_Mv9Nx.css","./Skills-DLTHcH5T.js","./parsers-DftYMnlk.js","./Skills-BdjRyorN.css","./Providers-r6NaBYMf.js","./Providers-BEakqcO5.css","./McpTools-CsGIijNe.js","./McpTools-CyhSLDwf.css","./Notes-DU6Vf2cL.js","./Notes-BG69sJKi.css","./Memory-BXX_yMKJ.js","./Memory-DRghrGJr.css","./Cron-3P0eVLTV.js","./WorkflowEditor-DBJhFPMN.js","./WorkflowEditor-D5bX6woe.css","./Tasks-CqycpPjS.js","./Tasks-BJjN_YEm.css","./Security-MJfKv0EJ.js","./Security-Dwxw7rfP.css","./Permissions-B1j3Mtms.js","./Permissions-C9WlkGl-.css","./P2P-BxFZ1Bit.js","./P2P-OEzOeMZX.css","./Git-CrDCcBig.js","./Git-DGcuBXST.css","./Projects-D-CGscDu.js","./Projects-DxKelI5h.css","./Wallet-CsRgnjJY.js","./Wallet-DnIumafl.css","./Organization-Bny6yOPV.js","./Organization-DdOOM4ic.css","./Analytics-DQ135mAd.js","./Analytics-BFI7jbwM.css","./Templates-y01u2Zis.js","./Templates-DOY_oZnm.css","./Backup-DbVRG5vE.js","./Backup-fZqtfC1m.css","./RssFeed-D7b68C5q.js","./RssFeed-BlFC20eg.css","./WebAuthn-DWoR5ADp.js","./WebAuthn-CNPl2VQR.css","./VideoEditing-B_nPKw6B.js","./VideoEditing-BA1N-5kq.css"])))=>i.map(i=>d[i]);
2
+ import{S as L,U as I,V as B,f as T,c as E,o as R,W as O,u as k,X as y,Y as V,Z as D,k as x,R as S,_ as w}from"./vendor-CN0Iv_qZ.js";import{a as g,A as M}from"./antd-Dh2t0vGq.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"]'))c(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"&&c(n)}).observe(document,{childList:!0,subtree:!0});function m(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 c(t){if(t.ep)return;t.ep=!0;const o=m(t);fetch(t.href,o)}})();const C="modulepreload",N=function(s,a){return new URL(s,a).href},P={},e=function(a,m,c){let t=Promise.resolve();if(m&&m.length>0){let b=function(i){return Promise.all(i.map(d=>Promise.resolve(d).then(u=>({status:"fulfilled",value:u}),u=>({status:"rejected",reason:u}))))};const n=document.getElementsByTagName("link"),r=document.querySelector("meta[property=csp-nonce]"),p=r?.nonce||r?.getAttribute("nonce");t=b(m.map(i=>{if(i=N(i,c),i in P)return;P[i]=!0;const d=i.endsWith(".css"),u=d?'[rel="stylesheet"]':"";if(c)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}"]${u}`))return;const l=document.createElement("link");if(l.rel=d?"stylesheet":C,d||(l.as="script"),l.crossOrigin="",l.href=i,p&&l.setAttribute("nonce",p),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-6SPt_8Y_.js"),__vite__mapDeps([0,1,2,3,4,5]),import.meta.url),children:[{path:"",redirect:"/dashboard"},{path:"dashboard",name:"Dashboard",component:()=>e(()=>import("./Dashboard-Br7kCwKJ.js"),__vite__mapDeps([6,1,2,7,3,4,8]),import.meta.url)},{path:"chat",name:"Chat",component:()=>e(()=>import("./Chat-wVhrFK9C.js"),__vite__mapDeps([9,1,10,4,7,2,3,11,12]),import.meta.url)},{path:"cowork",name:"Cowork",component:()=>e(()=>import("./Cowork-lOC25IW2.js"),__vite__mapDeps([13,1,10,4,2,7,3,14,12]),import.meta.url)},{path:"services",name:"Services",component:()=>e(()=>import("./Services-Yb_Q1V3d.js"),__vite__mapDeps([15,2,1,3,4,16]),import.meta.url)},{path:"logs",name:"Logs",component:()=>e(()=>import("./Logs-BfTE8urP.js"),__vite__mapDeps([17,2,1,3,4,18]),import.meta.url)},{path:"skills",name:"Skills",component:()=>e(()=>import("./Skills-DLTHcH5T.js"),__vite__mapDeps([19,1,2,20,7,3,4,21]),import.meta.url)},{path:"providers",name:"Providers",component:()=>e(()=>import("./Providers-r6NaBYMf.js"),__vite__mapDeps([22,1,2,20,3,4,23]),import.meta.url)},{path:"mcp",name:"McpTools",component:()=>e(()=>import("./McpTools-CsGIijNe.js"),__vite__mapDeps([24,2,1,3,4,25]),import.meta.url)},{path:"notes",name:"Notes",component:()=>e(()=>import("./Notes-DU6Vf2cL.js"),__vite__mapDeps([26,2,1,3,4,27]),import.meta.url)},{path:"memory",name:"Memory",component:()=>e(()=>import("./Memory-BXX_yMKJ.js"),__vite__mapDeps([28,2,1,3,4,29]),import.meta.url)},{path:"cron",name:"Cron",component:()=>e(()=>import("./Cron-3P0eVLTV.js"),__vite__mapDeps([30,2,1,4]),import.meta.url)},{path:"workflow",name:"Workflow",component:()=>e(()=>import("./WorkflowEditor-DBJhFPMN.js"),__vite__mapDeps([31,1,2,3,4,32]),import.meta.url)},{path:"tasks",name:"Tasks",component:()=>e(()=>import("./Tasks-CqycpPjS.js"),__vite__mapDeps([33,1,2,3,4,34]),import.meta.url)},{path:"security",name:"Security",component:()=>e(()=>import("./Security-MJfKv0EJ.js"),__vite__mapDeps([35,2,1,3,4,36]),import.meta.url)},{path:"permissions",name:"Permissions",component:()=>e(()=>import("./Permissions-B1j3Mtms.js"),__vite__mapDeps([37,2,1,3,4,38]),import.meta.url)},{path:"p2p",name:"P2P",component:()=>e(()=>import("./P2P-BxFZ1Bit.js"),__vite__mapDeps([39,2,1,3,4,40]),import.meta.url)},{path:"git",name:"Git",component:()=>e(()=>import("./Git-CrDCcBig.js"),__vite__mapDeps([41,2,1,3,4,42]),import.meta.url)},{path:"projects",name:"Projects",component:()=>e(()=>import("./Projects-D-CGscDu.js"),__vite__mapDeps([43,2,1,3,4,44]),import.meta.url)},{path:"wallet",name:"Wallet",component:()=>e(()=>import("./Wallet-CsRgnjJY.js"),__vite__mapDeps([45,2,1,3,4,46]),import.meta.url)},{path:"organization",name:"Organization",component:()=>e(()=>import("./Organization-Bny6yOPV.js"),__vite__mapDeps([47,1,2,3,4,48]),import.meta.url)},{path:"analytics",name:"Analytics",component:()=>e(()=>import("./Analytics-DQ135mAd.js"),__vite__mapDeps([49,2,1,3,4,50]),import.meta.url)},{path:"templates",name:"Templates",component:()=>e(()=>import("./Templates-y01u2Zis.js"),__vite__mapDeps([51,1,2,3,4,52]),import.meta.url)},{path:"backup",name:"Backup",component:()=>e(()=>import("./Backup-DbVRG5vE.js"),__vite__mapDeps([53,2,1,3,4,54]),import.meta.url)},{path:"rssfeed",name:"RssFeed",component:()=>e(()=>import("./RssFeed-D7b68C5q.js"),__vite__mapDeps([55,1,2,3,4,56]),import.meta.url)},{path:"webauthn",name:"WebAuthn",component:()=>e(()=>import("./WebAuthn-DWoR5ADp.js"),__vite__mapDeps([57,2,1,3,4,58]),import.meta.url)},{path:"video",name:"VideoEditing",component:()=>e(()=>import("./VideoEditing-B_nPKw6B.js"),__vite__mapDeps([59,2,1,3,4,60]),import.meta.url)}]}],F=L({history:I(),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"}}},W=B("theme",()=>{const s=T(localStorage.getItem(A)||"light"),a=E(()=>v[s.value]||v.dark),m=E(()=>a.value.antd),c=E(()=>s.value!=="light");function t(){const r=a.value.vars,p=document.documentElement;for(const[b,i]of Object.entries(r))p.style.setProperty(b,i);p.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:m,isDark:c,setTheme:o,init:n}}),j={__name:"App",setup(s){const a=W();return R(()=>a.init()),(m,c)=>{const t=y("router-view"),o=y("a-config-provider");return V(),O(o,{theme:k(a).antdTheme},{default:D(()=>[x(t)]),_:1},8,["theme"])}}},h=S(j);h.use(w());h.use(F);h.use(M);h.mount("#app");export{v as T,W as u};
@@ -1,4 +1,4 @@
1
- import{g as Yc}from"./antd-DEjZPGMj.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={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},$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(`
1
+ import{g as Yc}from"./antd-Dh2t0vGq.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={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},$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,`
@@ -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-CwvzTTw_.js"></script>
11
+ <script type="module" crossorigin src="./assets/index-tN-8TosE.js"></script>
12
12
  <link rel="modulepreload" crossorigin href="./assets/vendor-CN0Iv_qZ.js">
13
- <link rel="modulepreload" crossorigin href="./assets/antd-DEjZPGMj.js">
13
+ <link rel="modulepreload" crossorigin href="./assets/antd-Dh2t0vGq.js">
14
14
  <link rel="stylesheet" crossorigin href="./assets/index-CyGyEIVX.css">
15
15
  </head>
16
16
  <body>
@@ -23,6 +23,19 @@ export function registerAgentCommand(program) {
23
23
  .option("--base-url <url>", "API base URL")
24
24
  .option("--api-key <key>", "API key")
25
25
  .option("--session <id>", "Resume a previous agent session")
26
+ .option("--agent-id <id>", "Agent id for scoped memory recall")
27
+ .option("--recall-limit <n>", "Top-K memories to inject into system prompt")
28
+ .option("--recall-query <q>", "Query string for startup memory recall")
29
+ .option("--no-recall-memory", "Disable startup memory recall")
30
+ .option("--no-stream", "Disable streamed response rendering")
31
+ .option(
32
+ "--no-park-on-exit",
33
+ "Close the session-core handle on exit instead of parking it",
34
+ )
35
+ .option(
36
+ "--bundle <path>",
37
+ "Agent bundle directory (chainless-agent.toml + AGENTS.md + skills/ + mcp.json + USER.md)",
38
+ )
26
39
  .action(async (options) => {
27
40
  const runtime = createAgentRuntimeFactory().createAgentRuntime({
28
41
  model: options.model,
@@ -30,6 +43,13 @@ export function registerAgentCommand(program) {
30
43
  baseUrl: options.baseUrl,
31
44
  apiKey: options.apiKey,
32
45
  sessionId: options.session,
46
+ agentId: options.agentId,
47
+ recallLimit: options.recallLimit,
48
+ recallQuery: options.recallQuery,
49
+ recallMemory: options.recallMemory, // false when --no-recall-memory
50
+ noStream: options.stream === false, // true when --no-stream
51
+ parkOnExit: options.parkOnExit, // false when --no-park-on-exit
52
+ bundlePath: options.bundle || null,
33
53
  });
34
54
  await runtime.startAgentSession();
35
55
  });
@@ -129,6 +129,73 @@ export function registerConfigCommand(program) {
129
129
  logger.info("Reset cancelled");
130
130
  }
131
131
  });
132
+
133
+ // config beta — Managed Agents parity Phase E2 beta flags
134
+ const beta = cmd
135
+ .command("beta")
136
+ .description("Manage beta / experimental feature flags");
137
+
138
+ beta
139
+ .command("list", { isDefault: true })
140
+ .description("List enabled and known beta flags")
141
+ .option("--json", "Output as JSON")
142
+ .action(async (options) => {
143
+ try {
144
+ const { getBetaFlags } =
145
+ await import("../lib/session-core-singletons.js");
146
+ const flags = await getBetaFlags();
147
+ const out = flags.list();
148
+ if (options.json) {
149
+ console.log(JSON.stringify(out, null, 2));
150
+ return;
151
+ }
152
+ logger.log(chalk.bold("Enabled beta flags:"));
153
+ if (out.enabled.length === 0) logger.log(chalk.gray(" (none)"));
154
+ for (const f of out.enabled) logger.log(` ${chalk.green("✓")} ${f}`);
155
+ if (out.known.length > out.enabled.length) {
156
+ const disabled = out.known.filter((f) => !out.enabled.includes(f));
157
+ logger.log(chalk.bold("\nKnown (disabled):"));
158
+ for (const f of disabled) logger.log(` ${chalk.gray("·")} ${f}`);
159
+ }
160
+ } catch (err) {
161
+ logger.error(`Failed: ${err.message}`);
162
+ process.exit(1);
163
+ }
164
+ });
165
+
166
+ beta
167
+ .command("enable")
168
+ .description("Enable a beta flag (format: <feature>-<YYYY-MM-DD>)")
169
+ .argument("<flag>")
170
+ .action(async (flag) => {
171
+ try {
172
+ const { getBetaFlags } =
173
+ await import("../lib/session-core-singletons.js");
174
+ const flags = await getBetaFlags();
175
+ flags.enable(flag);
176
+ logger.success(`Enabled: ${chalk.cyan(flag)}`);
177
+ } catch (err) {
178
+ logger.error(`Failed: ${err.message}`);
179
+ process.exit(1);
180
+ }
181
+ });
182
+
183
+ beta
184
+ .command("disable")
185
+ .description("Disable a beta flag")
186
+ .argument("<flag>")
187
+ .action(async (flag) => {
188
+ try {
189
+ const { getBetaFlags } =
190
+ await import("../lib/session-core-singletons.js");
191
+ const flags = await getBetaFlags();
192
+ flags.disable(flag);
193
+ logger.success(`Disabled: ${chalk.cyan(flag)}`);
194
+ } catch (err) {
195
+ logger.error(`Failed: ${err.message}`);
196
+ process.exit(1);
197
+ }
198
+ });
132
199
  }
133
200
 
134
201
  function printConfig(obj, indent = "") {
@@ -8,6 +8,10 @@ import ora from "ora";
8
8
  import { logger } from "../lib/logger.js";
9
9
  import { bootstrap, shutdown } from "../runtime/bootstrap.js";
10
10
  import { MCPClient, MCPServerConfig } from "../harness/mcp-client.js";
11
+ import {
12
+ validateMcpServer,
13
+ annotateMcpCompatibility,
14
+ } from "@chainlesschain/session-core";
11
15
 
12
16
  // Singleton MCP client for session reuse
13
17
  let mcpClient = null;
@@ -17,6 +21,28 @@ function getClient() {
17
21
  return mcpClient;
18
22
  }
19
23
 
24
+ // Phase 3 (Hosted MCP Policy): resolve runtime mode from --mode > env > local.
25
+ function resolveMode(options) {
26
+ return (
27
+ options?.mode ||
28
+ process.env.CHAINLESSCHAIN_MODE ||
29
+ "local"
30
+ ).toLowerCase();
31
+ }
32
+
33
+ // Normalize a stored server row to mcp-policy's server shape.
34
+ function toPolicyServer(row) {
35
+ return {
36
+ name: row.name,
37
+ command: row.command,
38
+ args: row.args,
39
+ env: row.env,
40
+ transport: row.transport,
41
+ url: row.url,
42
+ modeCompatibility: row.modeCompatibility,
43
+ };
44
+ }
45
+
20
46
  export function registerMcpCommand(program) {
21
47
  const mcp = program
22
48
  .command("mcp")
@@ -27,6 +53,7 @@ export function registerMcpCommand(program) {
27
53
  .command("servers")
28
54
  .description("List configured MCP servers")
29
55
  .option("--json", "Output as JSON")
56
+ .option("--mode <mode>", "Runtime mode (local | lan | hosted)")
30
57
  .action(async (options) => {
31
58
  try {
32
59
  const ctx = await bootstrap({ verbose: program.opts().verbose });
@@ -38,19 +65,45 @@ export function registerMcpCommand(program) {
38
65
  const db = ctx.db.getDatabase();
39
66
  const config = new MCPServerConfig(db);
40
67
  const servers = config.list();
68
+ const mode = resolveMode(options);
69
+ const annotated = servers.map((s) => {
70
+ const { allowed, reason, transport } = validateMcpServer(
71
+ toPolicyServer(s),
72
+ mode,
73
+ );
74
+ const modes = annotateMcpCompatibility(
75
+ toPolicyServer(s),
76
+ )._modeCompatibility;
77
+ return {
78
+ ...s,
79
+ _mode: mode,
80
+ _allowed: allowed,
81
+ _reason: reason,
82
+ _transport: transport,
83
+ _modeCompatibility: modes,
84
+ };
85
+ });
41
86
 
42
87
  if (options.json) {
43
- console.log(JSON.stringify(servers, null, 2));
88
+ console.log(JSON.stringify(annotated, null, 2));
44
89
  } else if (servers.length === 0) {
45
90
  logger.info("No MCP servers configured. Use 'mcp add' to add one.");
46
91
  } else {
47
- logger.log(chalk.bold(`MCP Servers (${servers.length}):\n`));
48
- for (const s of servers) {
92
+ logger.log(
93
+ chalk.bold(`MCP Servers (${servers.length}) — mode: ${mode}\n`),
94
+ );
95
+ for (const s of annotated) {
49
96
  const auto = s.autoConnect ? chalk.green(" [auto]") : "";
50
- logger.log(` ${chalk.cyan(s.name)}${auto}`);
97
+ const flag = s._allowed
98
+ ? chalk.green(" [ok]")
99
+ : chalk.yellow(` [blocked: ${s._reason}]`);
100
+ logger.log(` ${chalk.cyan(s.name)}${auto}${flag}`);
51
101
  logger.log(
52
102
  ` ${chalk.gray("Command:")} ${s.command} ${s.args.join(" ")}`,
53
103
  );
104
+ logger.log(
105
+ ` ${chalk.gray("Compatible:")} ${s._modeCompatibility.join(", ") || "(none)"}`,
106
+ );
54
107
  }
55
108
  }
56
109
 
@@ -69,6 +122,10 @@ export function registerMcpCommand(program) {
69
122
  .requiredOption("-c, --command <cmd>", "Server command to run")
70
123
  .option("-a, --args <args>", "Command arguments (comma-separated)")
71
124
  .option("--auto-connect", "Auto-connect on startup")
125
+ .option(
126
+ "--mode <mode>",
127
+ "Runtime mode to validate against (local | lan | hosted)",
128
+ )
72
129
  .option("--json", "Output as JSON")
73
130
  .action(async (name, options) => {
74
131
  try {
@@ -84,6 +141,17 @@ export function registerMcpCommand(program) {
84
141
  ? options.args.split(",").map((a) => a.trim())
85
142
  : [];
86
143
 
144
+ const mode = resolveMode(options);
145
+ const check = validateMcpServer(
146
+ { name, command: options.command, args },
147
+ mode,
148
+ );
149
+ if (!check.allowed) {
150
+ logger.warn(
151
+ `Server "${name}" is not compatible with mode "${mode}": ${check.reason}`,
152
+ );
153
+ }
154
+
87
155
  config.add(name, {
88
156
  command: options.command,
89
157
  args,
@@ -148,6 +216,8 @@ export function registerMcpCommand(program) {
148
216
  .command("connect")
149
217
  .description("Connect to an MCP server")
150
218
  .argument("<name>", "Server name (configured or command)")
219
+ .option("--mode <mode>", "Runtime mode (local | lan | hosted)")
220
+ .option("--force", "Bypass mode compatibility check")
151
221
  .option("--json", "Output as JSON")
152
222
  .action(async (name, options) => {
153
223
  try {
@@ -166,6 +236,18 @@ export function registerMcpCommand(program) {
166
236
  process.exit(1);
167
237
  }
168
238
 
239
+ const mode = resolveMode(options);
240
+ const check = validateMcpServer(
241
+ toPolicyServer({ name, ...serverConfig }),
242
+ mode,
243
+ );
244
+ if (!check.allowed && !options.force) {
245
+ logger.error(
246
+ `Server "${name}" blocked in mode "${mode}": ${check.reason}. Use --force to override.`,
247
+ );
248
+ process.exit(1);
249
+ }
250
+
169
251
  const spinner = ora(`Connecting to ${name}...`).start();
170
252
  const client = getClient();
171
253
 
@@ -239,6 +239,181 @@ export function registerMemoryCommand(program) {
239
239
  }
240
240
  });
241
241
 
242
+ // memory recall — Managed Agents parity Phase D2 (session-core MemoryStore)
243
+ memory
244
+ .command("recall")
245
+ .description("Recall scoped memory (session-core MemoryStore)")
246
+ .argument("[query]", "Query string")
247
+ .option("--scope <scope>", "session | agent | user | global")
248
+ .option(
249
+ "--scope-id <id>",
250
+ "Session/agent/user id (required for non-global scopes)",
251
+ )
252
+ .option("--category <cat>", "Filter by category")
253
+ .option("--tags <tags>", "Comma-separated tags")
254
+ .option("-n, --limit <n>", "Max results", "10")
255
+ .option("--json", "Output as JSON")
256
+ .action(async (query, options) => {
257
+ try {
258
+ const { getMemoryStore } =
259
+ await import("../lib/session-core-singletons.js");
260
+ const store = getMemoryStore();
261
+ const tags = options.tags
262
+ ? options.tags
263
+ .split(",")
264
+ .map((t) => t.trim())
265
+ .filter(Boolean)
266
+ : null;
267
+ const results = store.recall({
268
+ query: query || "",
269
+ scope: options.scope,
270
+ scopeId: options.scopeId,
271
+ category: options.category,
272
+ tags,
273
+ limit: Math.max(1, parseInt(options.limit) || 10),
274
+ });
275
+
276
+ if (options.json) {
277
+ console.log(JSON.stringify(results, null, 2));
278
+ } else if (results.length === 0) {
279
+ logger.info("No scoped memory entries matched.");
280
+ } else {
281
+ logger.log(
282
+ chalk.bold(`Scoped memory (${results.length} results):\n`),
283
+ );
284
+ for (const m of results) {
285
+ logger.log(
286
+ ` ${chalk.gray(m.id.slice(0, 12))} ${chalk.cyan(m.scope)}${m.scopeId ? ":" + m.scopeId.slice(0, 12) : ""} ${chalk.yellow(m.category)} rel=${m.relevance?.toFixed(2) ?? "?"}`,
287
+ );
288
+ logger.log(` ${chalk.white(m.content.substring(0, 160))}`);
289
+ }
290
+ }
291
+ } catch (err) {
292
+ logger.error(`Failed: ${err.message}`);
293
+ process.exit(1);
294
+ }
295
+ });
296
+
297
+ // memory store — add to session-core MemoryStore (separate from DB-backed memory add)
298
+ memory
299
+ .command("store")
300
+ .description("Write a scoped memory (session-core MemoryStore)")
301
+ .argument("<content>")
302
+ .requiredOption("--scope <scope>", "session | agent | user | global")
303
+ .option("--scope-id <id>", "Required for session/agent/user scope")
304
+ .option("--category <cat>", "Category", "general")
305
+ .option("--tags <tags>", "Comma-separated tags")
306
+ .option("--json", "Output as JSON")
307
+ .action(async (content, options) => {
308
+ try {
309
+ const { getMemoryStore } =
310
+ await import("../lib/session-core-singletons.js");
311
+ const store = getMemoryStore();
312
+ const tags = options.tags
313
+ ? options.tags
314
+ .split(",")
315
+ .map((t) => t.trim())
316
+ .filter(Boolean)
317
+ : [];
318
+ const m = store.add({
319
+ scope: options.scope,
320
+ scopeId: options.scopeId || null,
321
+ category: options.category,
322
+ content,
323
+ tags,
324
+ });
325
+ if (options.json) console.log(JSON.stringify(m, null, 2));
326
+ else
327
+ logger.success(
328
+ `Stored ${chalk.gray(m.id.slice(0, 12))} [${chalk.cyan(m.scope)}/${m.category}]`,
329
+ );
330
+ } catch (err) {
331
+ logger.error(`Failed: ${err.message}`);
332
+ process.exit(1);
333
+ }
334
+ });
335
+
336
+ // memory consolidate — Managed Agents parity Phase G
337
+ // Reads a JSONL session and writes extracted facts into session-core MemoryStore
338
+ memory
339
+ .command("consolidate")
340
+ .description("Consolidate a session's trace into scoped memory")
341
+ .requiredOption("--session <id>", "Session ID (JSONL)")
342
+ .option("--scope <scope>", "session | agent | global", "agent")
343
+ .option("--scope-id <id>", "Override scope id (default: agent/session id)")
344
+ .option("--agent-id <id>", "Attach consolidated memories to this agent id")
345
+ .option("--dry-run", "Extract facts without writing to MemoryStore")
346
+ .option("--json", "Output as JSON")
347
+ .action(async (options) => {
348
+ try {
349
+ const { consolidateJsonlSession, buildTraceStoreFromJsonl } =
350
+ await import("../lib/session-consolidator.js");
351
+
352
+ if (options.dryRun) {
353
+ const { readEvents, sessionExists } =
354
+ await import("../harness/jsonl-session-store.js");
355
+ if (!sessionExists(options.session)) {
356
+ logger.error(`Session not found: ${options.session}`);
357
+ process.exit(1);
358
+ }
359
+ const events = readEvents(options.session);
360
+ const trace = buildTraceStoreFromJsonl(options.session, events);
361
+ const traceEvents = trace.query(options.session, {
362
+ limit: Number.MAX_SAFE_INTEGER,
363
+ });
364
+ const { defaultMemoryExtractor } =
365
+ await import("@chainlesschain/session-core");
366
+ const facts = defaultMemoryExtractor(traceEvents);
367
+ if (options.json) {
368
+ console.log(
369
+ JSON.stringify(
370
+ { dryRun: true, factCount: facts.length, facts },
371
+ null,
372
+ 2,
373
+ ),
374
+ );
375
+ } else {
376
+ logger.log(
377
+ chalk.bold(
378
+ `Dry run: ${facts.length} facts would be written (no memory modified).\n`,
379
+ ),
380
+ );
381
+ for (const f of facts) {
382
+ logger.log(
383
+ ` ${chalk.cyan(f.category)} ${chalk.gray((f.tags || []).join(","))}`,
384
+ );
385
+ logger.log(` ${chalk.white(String(f.content).slice(0, 160))}`);
386
+ }
387
+ }
388
+ return;
389
+ }
390
+
391
+ const result = await consolidateJsonlSession(options.session, {
392
+ scope: options.scope,
393
+ scopeId: options.scopeId || null,
394
+ agentId: options.agentId || null,
395
+ });
396
+ await new Promise((r) => setImmediate(r)); // let adapter flush
397
+
398
+ if (options.json) {
399
+ console.log(JSON.stringify(result, null, 2));
400
+ } else {
401
+ logger.success(
402
+ `Consolidated ${chalk.cyan(result.writtenCount)} memory entries ` +
403
+ `(${result.eventCount} trace events, scope=${chalk.yellow(result.scope)}).`,
404
+ );
405
+ for (const m of result.written.slice(0, 10)) {
406
+ logger.log(
407
+ ` ${chalk.gray(m.id.slice(0, 12))} ${chalk.cyan(m.category)} ${chalk.white(String(m.content).slice(0, 120))}`,
408
+ );
409
+ }
410
+ }
411
+ } catch (err) {
412
+ logger.error(`Failed: ${err.message}`);
413
+ process.exit(1);
414
+ }
415
+ });
416
+
242
417
  // memory file
243
418
  memory
244
419
  .command("file")
@@ -9,6 +9,8 @@ import { logger } from "../lib/logger.js";
9
9
  import { bootstrap, shutdown } from "../runtime/bootstrap.js";
10
10
  import {
11
11
  createSandbox,
12
+ acquireSandbox,
13
+ pruneExpired,
12
14
  executeSandbox,
13
15
  destroySandbox,
14
16
  listSandboxes,
@@ -31,6 +33,11 @@ export function registerSandboxCommand(program) {
31
33
  .option("--allow-read <paths>", "Comma-separated allowed read paths")
32
34
  .option("--allow-write <paths>", "Comma-separated allowed write paths")
33
35
  .option("--allowed-hosts <hosts>", "Comma-separated allowed network hosts")
36
+ .option(
37
+ "--bundle <path>",
38
+ "Agent bundle path — applies bundle sandbox policy, enables scope-aware reuse",
39
+ )
40
+ .option("--scope <scope>", "Sandbox scope override (thread|assistant)")
34
41
  .option("--json", "Output as JSON")
35
42
  .action(async (agentId, options) => {
36
43
  try {
@@ -64,18 +71,47 @@ export function registerSandboxCommand(program) {
64
71
 
65
72
  const sandboxOpts =
66
73
  Object.keys(perms).length > 0 ? { permissions: perms } : {};
67
- const result = createSandbox(db, agentId, sandboxOpts);
68
- spinner.succeed("Sandbox created");
74
+
75
+ let bundle = null;
76
+ if (options.bundle) {
77
+ try {
78
+ const { loadAgentBundle } =
79
+ await import("@chainlesschain/session-core/agent-bundle-loader");
80
+ bundle = loadAgentBundle(options.bundle);
81
+ } catch (err) {
82
+ spinner.fail(`Failed to load bundle: ${err.message}`);
83
+ process.exit(1);
84
+ }
85
+ }
86
+ if (options.scope) {
87
+ sandboxOpts.policy = {
88
+ ...(sandboxOpts.policy || {}),
89
+ scope: options.scope,
90
+ };
91
+ }
92
+
93
+ const result =
94
+ bundle || options.scope
95
+ ? acquireSandbox(db, agentId, { ...sandboxOpts, bundle })
96
+ : createSandbox(db, agentId, sandboxOpts);
97
+ spinner.succeed(result.reused ? "Sandbox reused" : "Sandbox created");
69
98
 
70
99
  if (options.json) {
71
100
  console.log(JSON.stringify(result, null, 2));
72
101
  } else {
73
- logger.log(chalk.bold("Sandbox Created:"));
74
- logger.log(` ID: ${chalk.cyan(result.id)}`);
75
- logger.log(` Status: ${chalk.green(result.status)}`);
76
102
  logger.log(
77
- ` Quota: CPU=${result.quota.cpu}, Memory=${(result.quota.memory / 1024 / 1024).toFixed(0)}MB`,
103
+ chalk.bold(result.reused ? "Sandbox Reused:" : "Sandbox Created:"),
78
104
  );
105
+ logger.log(` ID: ${chalk.cyan(result.id)}`);
106
+ if (result.scope) {
107
+ logger.log(` Scope: ${chalk.cyan(result.scope)}`);
108
+ }
109
+ logger.log(` Status: ${chalk.green(result.status)}`);
110
+ if (result.quota) {
111
+ logger.log(
112
+ ` Quota: CPU=${result.quota.cpu}, Memory=${(result.quota.memory / 1024 / 1024).toFixed(0)}MB`,
113
+ );
114
+ }
79
115
  }
80
116
 
81
117
  await shutdown();
@@ -357,6 +393,44 @@ export function registerSandboxCommand(program) {
357
393
  }
358
394
  }
359
395
 
396
+ await shutdown();
397
+ } catch (err) {
398
+ logger.error(`Failed: ${err.message}`);
399
+ process.exit(1);
400
+ }
401
+ });
402
+
403
+ // sandbox prune — Phase 4 TTL / idle sweep
404
+ sandbox
405
+ .command("prune")
406
+ .description(
407
+ "Destroy sandboxes whose ttl or idle-ttl has expired (Phase 4)",
408
+ )
409
+ .option("--json", "Output as JSON")
410
+ .action(async (options) => {
411
+ try {
412
+ const ctx = await bootstrap({ verbose: program.opts().verbose });
413
+ if (!ctx.db) {
414
+ logger.error("Database not available");
415
+ process.exit(1);
416
+ }
417
+ const db = ctx.db.getDatabase();
418
+
419
+ const destroyed = pruneExpired(db);
420
+
421
+ if (options.json) {
422
+ console.log(JSON.stringify({ destroyed }, null, 2));
423
+ } else if (destroyed.length === 0) {
424
+ logger.info("No expired sandboxes.");
425
+ } else {
426
+ logger.log(chalk.bold(`Pruned ${destroyed.length} sandbox(es):`));
427
+ for (const d of destroyed) {
428
+ logger.log(
429
+ ` ${chalk.cyan(d.id)} reason=${chalk.yellow(d.reason)}`,
430
+ );
431
+ }
432
+ }
433
+
360
434
  await shutdown();
361
435
  } catch (err) {
362
436
  logger.error(`Failed: ${err.message}`);
@@ -27,6 +27,14 @@ export function registerServeCommand(program) {
27
27
  "Allow non-localhost connections (requires --token)",
28
28
  )
29
29
  .option("--project <path>", "Default project root for sessions")
30
+ .option(
31
+ "--http-port <port>",
32
+ "Hosted HTTP port for Phase 5 envelope SSE (disabled if unset)",
33
+ )
34
+ .option(
35
+ "--bundle <path>",
36
+ "Agent bundle directory — applies AGENTS.md, MCP, and approval policy to all sessions",
37
+ )
30
38
  .action(async (opts) => {
31
39
  try {
32
40
  const runtime = createAgentRuntimeFactory().createServerRuntime({
@@ -37,6 +45,8 @@ export function registerServeCommand(program) {
37
45
  timeout: parseInt(opts.timeout, 10),
38
46
  allowRemote: opts.allowRemote,
39
47
  project: opts.project,
48
+ httpPort: opts.httpPort ? parseInt(opts.httpPort, 10) : null,
49
+ bundlePath: opts.bundle || null,
40
50
  });
41
51
  await runtime.startServer();
42
52
  } catch (err) {