shennian 0.4.50 → 0.4.52

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.
@@ -476,8 +476,8 @@
476
476
  },
477
477
  {
478
478
  "file": "src/manager/worker-ipc.js",
479
- "beforeBytes": 10872,
480
- "afterBytes": 5983
479
+ "beforeBytes": 11490,
480
+ "afterBytes": 6256
481
481
  },
482
482
  {
483
483
  "file": "src/manager/worker-markdown.js",
@@ -891,8 +891,8 @@
891
891
  },
892
892
  {
893
893
  "file": "src/session/queue-helpers.js",
894
- "beforeBytes": 7328,
895
- "afterBytes": 3699
894
+ "beforeBytes": 7587,
895
+ "afterBytes": 3747
896
896
  },
897
897
  {
898
898
  "file": "src/session/queue-retry.js",
@@ -1 +1 @@
1
- import w from"node:path";import{createHash as S,randomUUID as f}from"node:crypto";import{AVAILABLE_BUILTIN_AGENT_TYPES as h,extractPayloadText as M,isAgentHiddenPayload as q,isToolPayload as W}from"@shennian/wire";import{loadConfig as E}from"../config/index.js";import{readMessages as T,recordSession as _}from"../session/store.js";import{deriveWorkerTitle as c,formatWorkerMarkdown as k,normalizeWorkerTitle as x}from"./worker-markdown.js";function y(e){return w.resolve(e||process.cwd())}function D(e){return e==="manager"||e==="pi"?!1:e.startsWith("custom:")?!0:h.includes(e)}function b(e){return e==="worker.final"?"completed":e==="worker.error"?"failed":e==="worker.aborted"?"stopped":"progress"}function v(e,o){const t=[];for(const g of e)if(!q(g.payload))if(W(g.payload)){let a="tool",d="completed";try{const u=JSON.parse(g.payload);a=u.name||a,d=u.status||d}catch{}t.push({...g,payload:`[\u5DE5\u5177] ${a} \xB7 ${d}`})}else t.push({...g,payload:M(g.payload)});return t.slice(-Math.max(1,Math.min(o,500)))}async function P(e,o,t,g){if(o==="/skill/context"){const r=E(),i=String(t.host||""),n=String(t.hostSessionId||""),l=y(String(t.workDir||""));if(!r.machineId||!r.machineToken&&!r.accessToken)throw new Error("Shennian CLI must be paired and logged in");if(i!=="codex"&&i!=="claude")throw new Error("unsupported_native_agent_host");if(!n)throw new Error("native_agent_session_unavailable");if(!l||!w.isAbsolute(l))throw new Error("workDir is required");const m=`skill_manager_${S("sha256").update(r.machineId).update("\0").update(i).update("\0").update(n).update("\0").update(l).digest("hex").slice(0,32)}`;return e.registry.upsertManager({sessionId:m,agentSessionId:null,workDir:l,machineId:r.machineId,modelId:i,agentType:i,controllerKind:"native_skill",status:"idle"}),{status:200,body:{ok:!0,managerSessionId:m}}}if(!o.startsWith("/sessions/")&&o!=="/memory/path")return null;const a=String(t.managerSessionId||g||"");if(!a)throw new Error("managerSessionId is required");const d=e.registry.getManager(a);if(!d)throw new Error("Manager runtime is not registered");if(o==="/sessions/list"){const r=new Set(e.getRuntime().sessions.keys());return{status:200,body:{ok:!0,sessions:e.registry.listWorkers(a,{runningSessionIds:r})}}}if(o==="/memory/path")return{status:200,body:{ok:!0,path:w.join(d.workDir,".shennian")}};if(o==="/sessions/start"){const r=String(t.agentType||t.agent||d.defaultWorkerAgentType||"codex");if(!D(r))throw new Error(`Unsupported manager worker agent: ${r}`);const i=y(String(t.workDir||d.workDir));if(i!==d.workDir)throw new Error("Manager can only start workers in the same workDir");const n=String(t.message||"");if(!n)throw new Error("message is required");const l=t.title?x(String(t.title)):c(n),m=e.registry.addWorker({managerSessionId:a,agentType:r,workDir:i,title:l,summary:n.slice(0,120)}),p=String(t.modelId||(r===d.defaultWorkerAgentType?d.defaultWorkerModelId??"":""));_({sessionId:m.sessionId,agentType:r,workDir:i,agentSessionId:null,modelId:p||null,title:l,titleSource:"shennian_generated"}),await e.dispatchChatEnqueue(m.sessionId,r,i,n,null,p,a);const I=k({kind:"created",sessionId:m.sessionId,title:l,body:n});return e.appendManagerVisibleMarkdown(a,I,`worker-created:${m.sessionId}`),{status:200,body:{ok:!0,session:m,markdown:I}}}const u=String(t.sessionId||""),s=e.registry.getWorkerForManager(a,u);if(!s)throw new Error("Worker not found in this manager scope");if(o==="/sessions/send"){const r=String(t.message||"");if(!r.trim())throw new Error("message is required");const i=t.enqueue===void 0?!0:!!t.enqueue,n=String(t.modelId||(s.agentType===d.defaultWorkerAgentType?d.defaultWorkerModelId??"":""));await e.dispatchChatEnqueue(s.sessionId,s.agentType,s.workDir,r,s.agentSessionId??null,n,a);const l=k({kind:"message",sessionId:u,title:s.title||c(s.userGoal||s.summary||r),body:r});return e.appendManagerVisibleMarkdown(a,l,`worker-message:${f()}`),{status:200,body:{ok:!0,markdown:l,queued:!0,directRequested:!i}}}if(o==="/sessions/queue")return{status:200,body:{ok:!0,queue:e.getRuntime().chatQueue?.getSnapshot(u)}};if(o==="/sessions/queue/edit"||o==="/sessions/queue/delete"){const r=o.endsWith("/edit");return await e.dispatchReq({type:"req",id:`manager-queue-${r?"edit":"delete"}-${f()}`,method:r?"chat.queue.edit":"chat.queue.delete",params:{sessionId:u,queueMessageId:String(t.queueMessageId||t.messageId||""),...r?{text:String(t.message||t.text||"")}:{}}}),{status:200,body:{ok:!0,queue:e.getRuntime().chatQueue?.getSnapshot(u)}}}if(o==="/sessions/stop"||o==="/sessions/terminate"){if(s.status==="final"||s.status==="error"||s.status==="aborted"){const r=s.status==="final"?"completed":s.status==="error"?"failed":"stopped";return{status:200,body:{ok:!0,alreadyTerminal:!0,status:s.status,markdown:k({kind:r,sessionId:u,title:s.title||c(s.userGoal||s.summary||""),body:s.summary||"\u672C\u6B21\u6267\u884C\u5DF2\u7ECF\u7ED3\u675F\u3002"})}}}return await e.dispatchReq({type:"req",id:`manager-abort-${f()}`,method:"chat.abort",params:{sessionId:u}}),e.registry.updateWorker(u,{status:"aborted"}),{status:200,body:{ok:!0,markdown:k({kind:"stopped",sessionId:u,title:s.title||c(s.userGoal||s.summary||""),body:"\u5DF2\u505C\u6B62\u672C\u6B21\u6267\u884C\u3002"})}}}if(o==="/sessions/read"){const r=Number(t.limit||200),i=T(u,{limit:Math.max(r*20,r)});return{status:200,body:{ok:!0,messages:v(i,r),rawMessageCount:i.length}}}if(o==="/sessions/wait"){const r=Math.max(1e3,Math.min(Number(t.timeoutMs||6e5),6e5)),i=Date.now()+r;let n;for(;Date.now()<i&&(n=e.registry.listInboxEvents(a).find(m=>m.workerSessionId===u),!n);)await new Promise(m=>setTimeout(m,1e3));if(!n)return{status:200,body:{ok:!0,timedOut:!0,status:e.registry.getWorkerForManager(a,u)?.status}};const l=k({kind:b(n.kind),sessionId:u,title:s.title||c(s.userGoal||s.summary||n.summary),body:n.summary});return e.registry.removeInboxEvents(a,[n.id]),{status:200,body:{ok:!0,timedOut:!1,markdown:l,event:n}}}return null}export{P as handleWorkerIpcRoute};
1
+ import w from"node:path";import{createHash as h,randomUUID as f}from"node:crypto";import{AVAILABLE_BUILTIN_AGENT_TYPES as M,extractPayloadText as q,isAgentHiddenPayload as W,isToolPayload as _}from"@shennian/wire";import{loadConfig as E}from"../config/index.js";import{getPersonalSyncIdentity as y}from"../personal-sync/epoch.js";import{readMessages as T,recordSession as v}from"../session/store.js";import{deriveWorkerTitle as c,formatWorkerMarkdown as k,normalizeWorkerTitle as x}from"./worker-markdown.js";function S(e){return w.resolve(e||process.cwd())}function b(e){return e==="manager"||e==="pi"?!1:e.startsWith("custom:")?!0:M.includes(e)}function D(e){return e==="worker.final"?"completed":e==="worker.error"?"failed":e==="worker.aborted"?"stopped":"progress"}function A(e,a){const s=[];for(const g of e)if(!W(g.payload))if(_(g.payload)){let o="tool",l="completed";try{const u=JSON.parse(g.payload);o=u.name||o,l=u.status||l}catch{}s.push({...g,payload:`[\u5DE5\u5177] ${o} \xB7 ${l}`})}else s.push({...g,payload:q(g.payload)});return s.slice(-Math.max(1,Math.min(a,500)))}async function K(e,a,s,g){if(a==="/skill/context"){const r=E(),n=String(s.host||""),i=String(s.hostSessionId||""),d=S(String(s.workDir||""));if(!r.machineId||!r.machineToken&&!r.accessToken)throw new Error("Shennian CLI must be paired and logged in");if(n!=="codex"&&n!=="claude")throw new Error("unsupported_native_agent_host");if(!i)throw new Error("native_agent_session_unavailable");if(!d||!w.isAbsolute(d))throw new Error("workDir is required");const m=`skill_manager_${h("sha256").update(r.machineId).update("\0").update(n).update("\0").update(i).update("\0").update(d).digest("hex").slice(0,32)}`;return e.registry.upsertManager({sessionId:m,agentSessionId:null,workDir:d,machineId:r.machineId,modelId:n,agentType:n,controllerKind:"native_skill",status:"idle"}),{status:200,body:{ok:!0,managerSessionId:m}}}if(!a.startsWith("/sessions/")&&a!=="/memory/path")return null;const o=String(s.managerSessionId||g||"");if(!o)throw new Error("managerSessionId is required");const l=e.registry.getManager(o);if(!l)throw new Error("Manager runtime is not registered");if(a==="/sessions/list"){const r=new Set(e.getRuntime().sessions.keys()),n=e.registry.listWorkers(o,{runningSessionIds:r});return{status:200,body:{ok:!0,sessions:l.controllerKind==="native_skill"?n.filter(d=>d.role==="managed_worker"&&d.managedBy===o):n}}}if(a==="/memory/path")return{status:200,body:{ok:!0,path:w.join(l.workDir,".shennian")}};if(a==="/sessions/start"){const r=String(s.agentType||s.agent||l.defaultWorkerAgentType||"codex");if(!b(r))throw new Error(`Unsupported manager worker agent: ${r}`);const n=S(String(s.workDir||l.workDir));if(n!==l.workDir)throw new Error("Manager can only start workers in the same workDir");const i=String(s.message||"");if(!i)throw new Error("message is required");const d=s.title?x(String(s.title)):c(i),m=e.registry.addWorker({managerSessionId:o,agentType:r,workDir:n,title:d,summary:i.slice(0,120)}),p=String(s.modelId||(r===l.defaultWorkerAgentType?l.defaultWorkerModelId??"":""));v({sessionId:m.sessionId,agentType:r,workDir:n,agentSessionId:null,modelId:p||null,title:d,titleSource:"shennian_generated"}),await e.dispatchChatEnqueue(m.sessionId,r,n,i,null,p||void 0,o);const I=k({kind:"created",sessionId:m.sessionId,title:d,body:i});return e.appendManagerVisibleMarkdown(o,I,`worker-created:${m.sessionId}`),{status:200,body:{ok:!0,session:m,markdown:I}}}const u=String(s.sessionId||""),t=e.registry.getWorkerForManager(o,u);if(!t||l.controllerKind==="native_skill"&&(t.role!=="managed_worker"||t.managedBy!==o))throw new Error("Worker not found in this manager scope");if(a==="/sessions/send"){const r=String(s.message||"");if(!r.trim())throw new Error("message is required");const n=s.enqueue===void 0?!0:!!s.enqueue,i=String(s.modelId||(t.agentType===l.defaultWorkerAgentType?l.defaultWorkerModelId??"":""));await e.dispatchChatEnqueue(t.sessionId,t.agentType,t.workDir,r,t.agentSessionId??null,i||void 0,o);const d=k({kind:"message",sessionId:u,title:t.title||c(t.userGoal||t.summary||r),body:r});return e.appendManagerVisibleMarkdown(o,d,`worker-message:${f()}`),{status:200,body:{ok:!0,markdown:d,queued:!0,directRequested:!n}}}if(a==="/sessions/queue")return{status:200,body:{ok:!0,queue:e.getRuntime().chatQueue?.getSnapshot(u)}};if(a==="/sessions/queue/edit"||a==="/sessions/queue/delete"){const r=a.endsWith("/edit");return await e.dispatchReq({type:"req",id:`manager-queue-${r?"edit":"delete"}-${f()}`,method:r?"chat.queue.edit":"chat.queue.delete",params:{...y(),sessionId:u,queueMessageId:String(s.queueMessageId||s.messageId||""),...r?{text:String(s.message||s.text||"")}:{}}}),{status:200,body:{ok:!0,queue:e.getRuntime().chatQueue?.getSnapshot(u)}}}if(a==="/sessions/stop"||a==="/sessions/terminate"){if(t.status==="final"||t.status==="error"||t.status==="aborted"){const r=t.status==="final"?"completed":t.status==="error"?"failed":"stopped";return{status:200,body:{ok:!0,alreadyTerminal:!0,status:t.status,markdown:k({kind:r,sessionId:u,title:t.title||c(t.userGoal||t.summary||""),body:t.summary||"\u672C\u6B21\u6267\u884C\u5DF2\u7ECF\u7ED3\u675F\u3002"})}}}return await e.dispatchReq({type:"req",id:`manager-abort-${f()}`,method:"chat.abort",params:{...y(),sessionId:u}}),e.registry.updateWorker(u,{status:"aborted"}),{status:200,body:{ok:!0,markdown:k({kind:"stopped",sessionId:u,title:t.title||c(t.userGoal||t.summary||""),body:"\u5DF2\u505C\u6B62\u672C\u6B21\u6267\u884C\u3002"})}}}if(a==="/sessions/read"){const r=Number(s.limit||200),n=T(u,{limit:Math.max(r*20,r)});return{status:200,body:{ok:!0,messages:A(n,r),rawMessageCount:n.length}}}if(a==="/sessions/wait"){const r=Math.max(1e3,Math.min(Number(s.timeoutMs||6e5),6e5)),n=Date.now()+r;let i;for(;Date.now()<n&&(i=e.registry.listInboxEvents(o).find(m=>m.workerSessionId===u),!i);)await new Promise(m=>setTimeout(m,1e3));if(!i)return{status:200,body:{ok:!0,timedOut:!0,status:e.registry.getWorkerForManager(o,u)?.status}};const d=k({kind:D(i.kind),sessionId:u,title:t.title||c(t.userGoal||t.summary||i.summary),body:i.summary});return e.registry.removeInboxEvents(o,[i.id]),{status:200,body:{ok:!0,timedOut:!1,markdown:d,event:i}}}return null}export{K as handleWorkerIpcRoute};
@@ -1,4 +1,4 @@
1
- import{listSessionRecords as p}from"./store.js";function h(n,r){const e=u(r);if(e)return n.find(i=>u(i)===e)??null;if(r.origin!=="external")return null;const t=m(r);return n.find(i=>m(i)===t)??null}function I(n){const{origin:r,managedRoom:e,managedAgentDirect:t,trigger:i,...a}=n;return a}function x(n){const r=n.reduce((o,g)=>{const l=s(g);return o===null||l<o?l:o},null);if(r===null)return[];const e=n.filter(o=>s(o)===r),t=e[0];if(!t)return[];if(d(t))return[t];const i=f(t),a=[];for(const o of e){if(f(o)!==i)break;a.push(o)}return a}function d(n){if(n.origin==="external"||n.origin==="room"||n.managedRoom)return!1;const r=n.trigger?.kind;return r==null||r==="personal"||r==="managed_direct"}function b(n,r){const e=n.find(t=>t.id===r&&d(t));return e?[e]:[]}function s(n){const r=c(n).kind;return r==="personal"||r==="managed_direct"?0:r==="manager_event"||r==="manager_worker"?1:2}function c(n){const r=n.trigger;return r?r.kind==="room_activation"?{kind:r.kind,registryKey:r.registryKey}:r.kind==="manager_worker"?{kind:r.kind,parentSessionId:r.parentSessionId}:{kind:r.kind}:n.managedRoom?{kind:"room_activation",registryKey:n.managedRoom.registryKey}:n.managedAgentDirect?{kind:"managed_direct"}:{kind:"personal"}}function f(n){return JSON.stringify({agentType:n.agentType,sessionMode:n.sessionMode??null,workDir:n.workDir,agentSessionId:n.agentSessionId??null,modelId:n.modelId??null,systemPrompt:n.systemPrompt??null,reasoningEffort:n.reasoningEffort??null,managerConfig:n.managerConfig??null,managerDefaultWorkerAgentType:n.managerDefaultWorkerAgentType??null,managerDefaultWorkerModelId:n.managerDefaultWorkerModelId??null,externalChannel:n.externalChannel??null,replyTarget:n.replyTarget??null,roomRegistryKey:n.managedRoom?.registryKey??null,trigger:c(n)})}function M(n){return n.every(r=>r.managedRoom)?`[\u7FA4\u6D88\u606F]
1
+ import{listSessionRecords as p}from"./store.js";function h(n,r){const e=u(r);if(e)return n.find(i=>u(i)===e)??null;if(r.origin!=="external")return null;const t=m(r);return n.find(i=>m(i)===t)??null}function I(n){const{origin:r,managedRoom:e,managedAgentDirect:t,trigger:i,...a}=n;return a}function x(n){const r=n.reduce((o,g)=>{const l=s(g);return o===null||l<o?l:o},null);if(r===null)return[];const e=n.filter(o=>s(o)===r),t=e[0];if(!t)return[];if(d(t))return[t];if(t.trigger?.kind==="manager_worker")return[t];const i=f(t),a=[];for(const o of e){if(f(o)!==i)break;a.push(o)}return a}function d(n){if(n.origin==="external"||n.origin==="room"||n.managedRoom)return!1;const r=n.trigger?.kind;return r==null||r==="personal"||r==="managed_direct"}function b(n,r){const e=n.find(t=>t.id===r&&d(t));return e?[e]:[]}function s(n){const r=c(n).kind;return r==="personal"||r==="managed_direct"?0:r==="manager_event"||r==="manager_worker"?1:2}function c(n){const r=n.trigger;return r?r.kind==="room_activation"?{kind:r.kind,registryKey:r.registryKey}:r.kind==="manager_worker"?{kind:r.kind,parentSessionId:r.parentSessionId}:{kind:r.kind}:n.managedRoom?{kind:"room_activation",registryKey:n.managedRoom.registryKey}:n.managedAgentDirect?{kind:"managed_direct"}:{kind:"personal"}}function f(n){return JSON.stringify({agentType:n.agentType,sessionMode:n.sessionMode??null,workDir:n.workDir,agentSessionId:n.agentSessionId??null,modelId:n.modelId??null,systemPrompt:n.systemPrompt??null,reasoningEffort:n.reasoningEffort??null,managerConfig:n.managerConfig??null,managerDefaultWorkerAgentType:n.managerDefaultWorkerAgentType??null,managerDefaultWorkerModelId:n.managerDefaultWorkerModelId??null,externalChannel:n.externalChannel??null,replyTarget:n.replyTarget??null,roomRegistryKey:n.managedRoom?.registryKey??null,trigger:c(n)})}function M(n){return n.every(r=>r.managedRoom)?`[\u7FA4\u6D88\u606F]
2
2
  ${n.map(r=>_(r.text)).filter(Boolean).join(`
3
3
 
4
4
  `)}`:`[\u8FDE\u7EED\u7528\u6237\u6D88\u606F]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shennian",
3
- "version": "0.4.50",
3
+ "version": "0.4.52",
4
4
  "description": "Shennian — AI Agent Control Plane CLI",
5
5
  "type": "module",
6
6
  "bin": {