shennian 0.3.29 → 0.3.30

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.
@@ -136,8 +136,8 @@
136
136
  },
137
137
  {
138
138
  "file": "src/agents/workbuddy.js",
139
- "beforeBytes": 12451,
140
- "afterBytes": 6549
139
+ "beforeBytes": 13410,
140
+ "afterBytes": 6941
141
141
  },
142
142
  {
143
143
  "file": "src/commands/agent.js",
@@ -2,6 +2,7 @@ import type { ChatAttachmentMeta, ExternalChannelSessionStatus, SessionRunPhase
2
2
  import { AgentAdapter, type AgentSendContext } from './adapter.js';
3
3
  export declare function normalizeWorkBuddyModelId(modelId?: string | null): string | undefined;
4
4
  export declare function normalizeWorkBuddyReasoningEffort(value?: string | null): string | undefined;
5
+ export declare function workBuddySystemPromptArgs(systemPrompt: string | null, platform: NodeJS.Platform, promptFile?: string): string[];
5
6
  export declare class WorkBuddyAdapter extends AgentAdapter {
6
7
  readonly type: "workbuddy";
7
8
  private process;
@@ -1,3 +1,3 @@
1
- import{createInterface as g}from"node:readline";import{randomUUID as y}from"node:crypto";import{AgentAdapter as I,registerAgent as S}from"./adapter.js";import{resolveBuiltinCommand as k,spawnAgentCommand as _}from"./command-spec.js";import{buildAgentProcessEnv as x}from"../agent-env.js";import{buildPlatformInstructions as w}from"./platform-instructions.js";import{ensureWorkBuddyRoomPluginBundle as E}from"../integrations/workbuddy-plugin-bundle.js";import{roomMcpHostToolName as P}from"../integrations/room-plugin-shared.js";const B=new Set(["minimal","low","medium","high","xhigh","max"]);function T(i){const t=i?.trim();return t&&t!=="auto"?t:void 0}function W(i){const t=i?.trim();if(t){if(B.has(t))return t;throw new Error(`Unsupported WorkBuddy reasoning effort "${t}". Supported values: minimal, low, medium, high, xhigh, max.`)}}class C extends I{type="workbuddy";process=null;agentSessionId=null;workDir=null;seq=0;runId="";terminalState="open";hasEmittedText=!1;runPhase=null;externalChannel=null;shennianSessionId=null;extraEnv={};configure(t){this.shennianSessionId=t.sessionId??null,this.externalChannel=t.externalChannel??null,this.extraEnv=t.env??{}}async start(t,s,e){this.workDir=s,this.seq=0,e&&(this.agentSessionId=e)}async send(t,s,e,o,a,n){await this.killProcess(),this.runId=y(),this.resetRunState();const u=n?.source==="room_activation",r=["-p",t,"--output-format","stream-json","--verbose","--permission-mode",u?"dontAsk":"auto","--setting-sources","user,project,local"],h=T(s);h&&r.push("--model",h);const m=E(),l=P("workbuddy");u?r.push("--allowedTools",l,"--tools",`NoDefer(${l})`,"--mcp-config",m.mcpFile,"--strict-mcp-config","--disallowedTools","mcp__shennian_room__shennian_agent","--max-turns","2"):r.push("--allowedTools",l,"--tools",`*,NoDefer(${l})`),r.push("--plugin-dir",m.pluginRoot);const p=this.shennianSessionId?.startsWith("room-managed-")&&!this.agentSessionId&&!u?null:w(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,a);p&&r.push("--append-system-prompt",p);const f=W(e);f&&r.push("--effort",f),this.agentSessionId&&r.push("--resume",this.agentSessionId),this.spawnAndParse(r)}async resume(t){await this.killProcess(),this.agentSessionId=t,this.resetRunState()}async stop(){await this.killProcess()}async getStatus(){return{active:this.process!=null&&this.terminalState==="open",runId:this.runId||null,runPhase:this.runPhase,canStop:this.process!=null&&this.terminalState==="open"}}spawnAndParse(t){const s=k("workbuddy");if(!s){this.emit("error",new Error("WorkBuddy was not found. Install WorkBuddy Desktop or the CodeBuddy CLI, then retry."));return}const e=_(s,t,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:x(this.extraEnv)});this.process=e,g({input:e.stdout}).on("line",n=>{if(n.trim())try{this.handleStreamEvent(JSON.parse(n))}catch{}});let a="";e.stderr?.on("data",n=>{a=`${a}${n.toString()}`.slice(-8e3)}),e.on("close",n=>{this.process===e&&(this.process=null,this.runPhase=null,this.handleProcessClose(n,a))}),e.on("error",n=>{if(this.process!==e)return;this.process=null,this.runPhase=null;const u=n.code==="ENOENT";this.emitErrorIfOpen({state:"error",message:u?"WorkBuddy was not found. Install WorkBuddy Desktop or the CodeBuddy CLI, then retry.":d(n.message)})})}handleStreamEvent(t){if(t.type==="system"&&t.subtype==="init"&&t.session_id){this.agentSessionId=t.session_id,this.runPhase="thinking",this.emitEvent({state:"start",agentSessionId:t.session_id});return}if(t.type==="control_request"&&t.request?.subtype==="can_use_tool"){this.runPhase="waiting_approval",this.emitEvent({state:"approval-pending",name:t.request.tool_name,args:t.request.input,approval:{title:`WorkBuddy \u8BF7\u6C42\u4F7F\u7528 ${t.request.tool_name||"\u5DE5\u5177"}`,source:"workbuddy",actionHint:"\u8BF7\u5728 WorkBuddy \u6216\u795E\u5FF5\u4E2D\u786E\u8BA4\u540E\u7EE7\u7EED\u3002"}});return}if(t.type==="assistant"){const e=t.message?.content;if(e?.length)for(const o of e)this.handleContentBlock(o);else t.text&&this.emitText(t.text,!!t.thinking);return}if(t.type!=="result")return;if(t.subtype==="tool_result"){this.runPhase="tool_running",this.emitEvent({state:"tool-result",name:t.name,result:c(t.content)});return}if(t.subtype==="error"||t.error){this.emitErrorIfOpen({state:"error",message:d(t.error||t.result||"WorkBuddy failed.")});return}!this.hasEmittedText&&t.result&&this.emitText(t.result,!1),t.session_id&&(this.agentSessionId=t.session_id);const s=t.usage??t.message?.usage;this.emitFinalIfOpen({state:"final",agentSessionId:this.agentSessionId??void 0,usage:s?{inputTokens:s.input_tokens??0,outputTokens:s.output_tokens??0}:void 0})}handleContentBlock(t){t.type==="text"&&t.text?this.emitText(t.text,!1):t.type==="thinking"&&t.thinking?this.emitText(t.thinking,!0):t.type==="tool_use"?(this.runPhase="tool_running",this.emitEvent({state:"tool-call",name:t.name,args:t.input})):t.type==="tool_result"&&this.emitEvent({state:"tool-result",name:t.name,result:c(t.content)})}emitText(t,s){this.runPhase=s?"thinking":"streaming_text";const e=!s&&this.hasEmittedText?`
1
+ import{createInterface as y}from"node:readline";import{randomUUID as I}from"node:crypto";import{AgentAdapter as k,registerAgent as w}from"./adapter.js";import{resolveBuiltinCommand as S,spawnAgentCommand as x}from"./command-spec.js";import{buildAgentProcessEnv as _}from"../agent-env.js";import{buildPlatformInstructions as E,ensurePlatformInstructionsFile as B}from"./platform-instructions.js";import{ensureWorkBuddyRoomPluginBundle as P}from"../integrations/workbuddy-plugin-bundle.js";import{roomMcpHostToolName as T}from"../integrations/room-plugin-shared.js";const W=new Set(["minimal","low","medium","high","xhigh","max"]);function C(n){const t=n?.trim();return t&&t!=="auto"?t:void 0}function A(n){const t=n?.trim();if(t){if(W.has(t))return t;throw new Error(`Unsupported WorkBuddy reasoning effort "${t}". Supported values: minimal, low, medium, high, xhigh, max.`)}}function D(n,t,e){if(!n)return[];if(t==="win32"){if(!e)throw new Error("WorkBuddy system prompt file is required on Windows.");return["--system-prompt-file",e]}return["--append-system-prompt",n]}class O extends k{type="workbuddy";process=null;agentSessionId=null;workDir=null;seq=0;runId="";terminalState="open";hasEmittedText=!1;runPhase=null;externalChannel=null;shennianSessionId=null;extraEnv={};configure(t){this.shennianSessionId=t.sessionId??null,this.externalChannel=t.externalChannel??null,this.extraEnv=t.env??{}}async start(t,e,s){this.workDir=e,this.seq=0,s&&(this.agentSessionId=s)}async send(t,e,s,o,a,i){await this.killProcess(),this.runId=I(),this.resetRunState();const u=i?.source==="room_activation",r=["-p",t,"--output-format","stream-json","--verbose","--permission-mode",u?"dontAsk":"auto","--setting-sources","user,project,local"],h=C(e);h&&r.push("--model",h);const m=P(),l=T("workbuddy");u?r.push("--allowedTools",l,"--tools",`NoDefer(${l})`,"--mcp-config",m.mcpFile,"--strict-mcp-config","--disallowedTools","mcp__shennian_room__shennian_agent","--max-turns","2"):r.push("--allowedTools",l,"--tools",`*,NoDefer(${l})`),r.push("--plugin-dir",m.pluginRoot);const p=this.shennianSessionId?.startsWith("room-managed-")&&!this.agentSessionId&&!u?null:E(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,a);if(p){const g=process.platform==="win32"?B(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,a):void 0;r.push(...D(p,process.platform,g))}const f=A(s);f&&r.push("--effort",f),this.agentSessionId&&r.push("--resume",this.agentSessionId),this.spawnAndParse(r)}async resume(t){await this.killProcess(),this.agentSessionId=t,this.resetRunState()}async stop(){await this.killProcess()}async getStatus(){return{active:this.process!=null&&this.terminalState==="open",runId:this.runId||null,runPhase:this.runPhase,canStop:this.process!=null&&this.terminalState==="open"}}spawnAndParse(t){const e=S("workbuddy");if(!e){this.emit("error",new Error("WorkBuddy was not found. Install WorkBuddy Desktop or the CodeBuddy CLI, then retry."));return}const s=x(e,t,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:_(this.extraEnv)});this.process=s,y({input:s.stdout}).on("line",i=>{if(i.trim())try{this.handleStreamEvent(JSON.parse(i))}catch{}});let a="";s.stderr?.on("data",i=>{a=`${a}${i.toString()}`.slice(-8e3)}),s.on("close",i=>{this.process===s&&(this.process=null,this.runPhase=null,this.handleProcessClose(i,a))}),s.on("error",i=>{if(this.process!==s)return;this.process=null,this.runPhase=null;const u=i.code==="ENOENT";this.emitErrorIfOpen({state:"error",message:u?"WorkBuddy was not found. Install WorkBuddy Desktop or the CodeBuddy CLI, then retry.":d(i.message)})})}handleStreamEvent(t){if(t.type==="system"&&t.subtype==="init"&&t.session_id){this.agentSessionId=t.session_id,this.runPhase="thinking",this.emitEvent({state:"start",agentSessionId:t.session_id});return}if(t.type==="control_request"&&t.request?.subtype==="can_use_tool"){this.runPhase="waiting_approval",this.emitEvent({state:"approval-pending",name:t.request.tool_name,args:t.request.input,approval:{title:`WorkBuddy \u8BF7\u6C42\u4F7F\u7528 ${t.request.tool_name||"\u5DE5\u5177"}`,source:"workbuddy",actionHint:"\u8BF7\u5728 WorkBuddy \u6216\u795E\u5FF5\u4E2D\u786E\u8BA4\u540E\u7EE7\u7EED\u3002"}});return}if(t.type==="assistant"){const s=t.message?.content;if(s?.length)for(const o of s)this.handleContentBlock(o);else t.text&&this.emitText(t.text,!!t.thinking);return}if(t.type!=="result")return;if(t.subtype==="tool_result"){this.runPhase="tool_running",this.emitEvent({state:"tool-result",name:t.name,result:c(t.content)});return}if(t.subtype==="error"||t.error){this.emitErrorIfOpen({state:"error",message:d(t.error||t.result||"WorkBuddy failed.")});return}!this.hasEmittedText&&t.result&&this.emitText(t.result,!1),t.session_id&&(this.agentSessionId=t.session_id);const e=t.usage??t.message?.usage;this.emitFinalIfOpen({state:"final",agentSessionId:this.agentSessionId??void 0,usage:e?{inputTokens:e.input_tokens??0,outputTokens:e.output_tokens??0}:void 0})}handleContentBlock(t){t.type==="text"&&t.text?this.emitText(t.text,!1):t.type==="thinking"&&t.thinking?this.emitText(t.thinking,!0):t.type==="tool_use"?(this.runPhase="tool_running",this.emitEvent({state:"tool-call",name:t.name,args:t.input})):t.type==="tool_result"&&this.emitEvent({state:"tool-result",name:t.name,result:c(t.content)})}emitText(t,e){this.runPhase=e?"thinking":"streaming_text";const s=!e&&this.hasEmittedText?`
2
2
 
3
- `:"";this.emitEvent({state:"delta",text:e+t,thinking:s||void 0}),s||(this.hasEmittedText=!0)}handleProcessClose(t,s){if(t!==0&&t!==null){this.emitErrorIfOpen({state:"error",message:d(s)||`WorkBuddy exited with code ${t}.`});return}this.emitFinalIfOpen({state:"final",agentSessionId:this.agentSessionId??void 0})}emitFinalIfOpen(t){this.terminalState==="open"&&(this.terminalState="final",this.runPhase=null,this.emitEvent(t))}emitErrorIfOpen(t){this.terminalState==="open"&&(this.terminalState="error",this.runPhase=null,this.emitEvent(t))}emitEvent(t){this.emit("agentEvent",{...t,runId:this.runId,seq:this.seq++})}resetRunState(){this.seq=0,this.terminalState="open",this.hasEmittedText=!1,this.runPhase=null}async killProcess(){const t=this.process;t&&(this.process=null,this.runPhase=null,t.kill("SIGTERM"),await new Promise(s=>{let e=!1;const o=()=>{e||(e=!0,s())};t.once("close",o),setTimeout(()=>{t.kill("SIGKILL"),o()},3e3).unref?.()}))}}function c(i){if(typeof i=="string")return i;try{return JSON.stringify(i)}catch{return"[unserializable WorkBuddy tool result]"}}function d(i){return i.replace(/(Authorization\s*:\s*)Bearer\s+[A-Za-z0-9._~+/-]+/gi,"$1Bearer [redacted]").replace(/(api[-_ ]?key|access[-_ ]?token|refresh[-_ ]?token|connector[-_ ]?token)(\s*[:=]\s*)[^\s,;]+/gi,"$1$2[redacted]").trim().slice(0,2e3)}S("workbuddy",()=>new C);export{C as WorkBuddyAdapter,T as normalizeWorkBuddyModelId,W as normalizeWorkBuddyReasoningEffort,d as sanitizeWorkBuddyError};
3
+ `:"";this.emitEvent({state:"delta",text:s+t,thinking:e||void 0}),e||(this.hasEmittedText=!0)}handleProcessClose(t,e){if(t!==0&&t!==null){this.emitErrorIfOpen({state:"error",message:d(e)||`WorkBuddy exited with code ${t}.`});return}this.emitFinalIfOpen({state:"final",agentSessionId:this.agentSessionId??void 0})}emitFinalIfOpen(t){this.terminalState==="open"&&(this.terminalState="final",this.runPhase=null,this.emitEvent(t))}emitErrorIfOpen(t){this.terminalState==="open"&&(this.terminalState="error",this.runPhase=null,this.emitEvent(t))}emitEvent(t){this.emit("agentEvent",{...t,runId:this.runId,seq:this.seq++})}resetRunState(){this.seq=0,this.terminalState="open",this.hasEmittedText=!1,this.runPhase=null}async killProcess(){const t=this.process;t&&(this.process=null,this.runPhase=null,t.kill("SIGTERM"),await new Promise(e=>{let s=!1;const o=()=>{s||(s=!0,e())};t.once("close",o),setTimeout(()=>{t.kill("SIGKILL"),o()},3e3).unref?.()}))}}function c(n){if(typeof n=="string")return n;try{return JSON.stringify(n)}catch{return"[unserializable WorkBuddy tool result]"}}function d(n){return n.replace(/(Authorization\s*:\s*)Bearer\s+[A-Za-z0-9._~+/-]+/gi,"$1Bearer [redacted]").replace(/(api[-_ ]?key|access[-_ ]?token|refresh[-_ ]?token|connector[-_ ]?token)(\s*[:=]\s*)[^\s,;]+/gi,"$1$2[redacted]").trim().slice(0,2e3)}w("workbuddy",()=>new O);export{O as WorkBuddyAdapter,C as normalizeWorkBuddyModelId,A as normalizeWorkBuddyReasoningEffort,d as sanitizeWorkBuddyError,D as workBuddySystemPromptArgs};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shennian",
3
- "version": "0.3.29",
3
+ "version": "0.3.30",
4
4
  "description": "Shennian — AI Agent Control Plane CLI",
5
5
  "type": "module",
6
6
  "bin": {