shennian 0.4.43 → 0.4.45
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/dist/publish-build-manifest.json +91 -41
- package/dist/src/agents/adapter.d.ts +8 -0
- package/dist/src/agents/adapter.js +1 -1
- package/dist/src/agents/codex.d.ts +3 -1
- package/dist/src/agents/codex.js +10 -10
- package/dist/src/agents/pi-coding-agent.d.ts +3 -1
- package/dist/src/agents/pi-coding-agent.js +4 -4
- package/dist/src/commands/daemon-process.d.ts +2 -0
- package/dist/src/commands/daemon-process.js +1 -1
- package/dist/src/commands/daemon.d.ts +1 -1
- package/dist/src/commands/daemon.js +6 -6
- package/dist/src/commands/manager.js +1 -1
- package/dist/src/manager/prompt.d.ts +1 -1
- package/dist/src/manager/prompt.js +4 -3
- package/dist/src/manager/registry.d.ts +5 -3
- package/dist/src/manager/registry.js +1 -1
- package/dist/src/manager/runtime.d.ts +8 -16
- package/dist/src/manager/runtime.js +8 -20
- package/dist/src/manager/worker-ipc.d.ts +17 -0
- package/dist/src/manager/worker-ipc.js +1 -0
- package/dist/src/manager/worker-markdown.d.ts +10 -0
- package/dist/src/manager/worker-markdown.js +6 -0
- package/dist/src/native-fusion/codex-message-parser.d.ts +9 -0
- package/dist/src/native-fusion/codex-message-parser.js +1 -0
- package/dist/src/native-fusion/codex-parser.js +3 -3
- package/dist/src/native-fusion/service.d.ts +3 -0
- package/dist/src/native-fusion/service.js +2 -2
- package/dist/src/native-fusion/state.js +2 -2
- package/dist/src/native-fusion/types.d.ts +2 -0
- package/dist/src/room/room-action-client-types.d.ts +136 -0
- package/dist/src/room/room-action-client-types.js +1 -0
- package/dist/src/room/room-action-client.d.ts +3 -137
- package/dist/src/room/room-action-client.js +1 -1
- package/dist/src/session/handlers/agent-workspace-validation.d.ts +1 -0
- package/dist/src/session/handlers/agent-workspace-validation.js +1 -1
- package/dist/src/session/handlers/chat-adapter-config.d.ts +11 -0
- package/dist/src/session/handlers/chat-adapter-config.js +1 -0
- package/dist/src/session/handlers/chat-events.d.ts +5 -0
- package/dist/src/session/handlers/chat-events.js +2 -0
- package/dist/src/session/handlers/chat-recovery.d.ts +4 -0
- package/dist/src/session/handlers/chat-recovery.js +1 -0
- package/dist/src/session/handlers/chat-session-lifecycle.d.ts +9 -0
- package/dist/src/session/handlers/chat-session-lifecycle.js +1 -0
- package/dist/src/session/handlers/chat.d.ts +1 -3
- package/dist/src/session/handlers/chat.js +1 -2
- package/dist/src/session/manager.d.ts +2 -1
- package/dist/src/session/manager.js +2 -2
- package/dist/src/session/queue-helpers.d.ts +4 -0
- package/dist/src/session/queue-helpers.js +8 -8
- package/dist/src/session/queue-storage.d.ts +7 -0
- package/dist/src/session/queue-storage.js +2 -0
- package/dist/src/session/queue.d.ts +14 -10
- package/dist/src/session/queue.js +1 -2
- package/dist/src/session/queued-chat-dispatch.d.ts +1 -0
- package/dist/src/session/queued-chat-dispatch.js +1 -1
- package/dist/src/session/run-recovery/schema.d.ts +3 -1
- package/dist/src/session/run-recovery/schema.js +1 -1
- package/dist/src/session/turn-trigger.d.ts +33 -0
- package/dist/src/session/turn-trigger.js +1 -0
- package/dist/src/session/types.d.ts +2 -1
- package/node_modules/@shennian/wire/dist/methods.d.ts +1 -1
- package/node_modules/@shennian/wire/dist/session.d.ts +12 -0
- package/package.json +1 -1
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export declare function isShennianRunServiceCommand(command: string): boolean;
|
|
2
|
+
export declare function inferDaemonLauncherFromCommand(command: string): 'desktop-managed' | 'global-cli' | 'unknown';
|
|
2
3
|
export declare function parseWindowsDaemonProcessJson(raw: string, excludePid?: number): number[];
|
|
3
4
|
export declare function findRunningWindowsDaemonProcessIds(excludePid?: number): number[];
|
|
5
|
+
export declare function readWindowsProcessCommand(pid: number): string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{execFileSync as
|
|
1
|
+
import{execFileSync as u}from"node:child_process";const d=5e3;function l(n){const e=n.replace(/\\/g,"/").trim();return f(e)||h(e)||x(e)||a(e,"shennian")||a(e,"npx")}function g(n){const e=n.replace(/\\/g,"/").toLowerCase();return e.includes("/cli-bridge.js")||e.includes("/resources/daemon/")?"desktop-managed":e.includes("/node_modules/shennian/")||e.includes("/bin/shennian")||e.includes(" shennian run-service")||e.includes(" shennian.js run-service")?"global-cli":"unknown"}function m(n,e=process.pid){let s;try{s=JSON.parse(p(n))}catch{return[]}return(Array.isArray(s)?s:s?[s]:[]).map(t=>{if(!t||typeof t!="object")return null;const i=t,r=Number(i.ProcessId),c=typeof i.CommandLine=="string"?i.CommandLine:"";return!Number.isInteger(r)||r<=0||r===e?null:l(c)?r:null}).filter(t=>typeof t=="number")}function p(n){const e=n.trim(),s=[...e].map((r,c)=>r==="["||r==="{"?c:-1).find(r=>r>=0)??-1;if(s<0)return e;const t=e[s]==="["?"]":"}",i=e.lastIndexOf(t);return i>=s?e.slice(s,i+1):e.slice(s)}function S(n=process.pid){try{const e=["$ProgressPreference = 'SilentlyContinue'","Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -match 'run-service' } | Select-Object ProcessId,CommandLine | ConvertTo-Json -Compress"].join("; "),s=u("powershell.exe",["-NoProfile","-NonInteractive","-Command",e],{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:d,windowsHide:!0});return m(s,n)}catch{return[]}}function v(n){if(!Number.isSafeInteger(n)||n<=0)return null;try{const e=["$ProgressPreference = 'SilentlyContinue'",`Get-CimInstance Win32_Process -Filter "ProcessId = ${n}" | Select-Object -ExpandProperty CommandLine`].join("; ");return u("powershell.exe",["-NoProfile","-NonInteractive","-Command",e],{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:d,windowsHide:!0}).trim()||null}catch{return null}}function f(n){return/(?:^|["\s])[^"\s]*updater-worker\.js["\s]/i.test(n)&&/(?:^|["\s])--service(?:["\s]|$)/i.test(n)&&/(?:^|["\s])run-service(?:["\s]|$)/i.test(n)}function h(n){return/(?:^|["\s])[^"\s]*shennianclient\.exe["\s]/i.test(n)&&/(?:^|["\s])[^"\s]*cli-bridge\.js["\s]/i.test(n)&&/(?:^|["\s])[^"\s]*\/daemon\/dist\/bin\/shennian\.js["\s]/i.test(n)&&/(?:^|["\s])run-service(?:["\s]|$)/i.test(n)}function x(n){return/^"[^"]*\/node(?:\.exe)?"\s+"?[^"]*(?:\/node_modules\/shennian\/|\/dist\/bin\/shennian\.js|\/bin\/shennian)"?\s+run-service(?:\s|$)/i.test(n)||/^(?:\S*\/)?node(?:\.exe)?\s+\S*(?:\/node_modules\/shennian\/|\/dist\/bin\/shennian\.js|\/bin\/shennian)\s+run-service(?:\s|$)/i.test(n)}function a(n,e){const s=e==="shennian"?`${e}(?:\\.cmd|\\.exe)?`:`${e}(?:\\.cmd|\\.exe)?`,o=e==="npx"?"\\s+(?:--yes\\s+)?shennian\\s+run-service(?:\\s|$)":"\\s+run-service(?:\\s|$)";return new RegExp(`^"[^"]*\\/${s}"${o}`,"i").test(n)||new RegExp(`^(?:\\S*\\/)?${s}${o}`,"i").test(n)}export{S as findRunningWindowsDaemonProcessIds,g as inferDaemonLauncherFromCommand,l as isShennianRunServiceCommand,m as parseWindowsDaemonProcessJson,v as readWindowsProcessCommand};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
2
|
import type { Command } from 'commander';
|
|
3
3
|
export { buildWindowsLauncherCommand, buildWindowsScheduledTaskCommands, buildWindowsScheduledTaskSuspendCommands, buildWindowsScheduledTaskXml, buildWindowsStartupVbs, suspendWindowsScheduledTask, } from './daemon-windows.js';
|
|
4
|
-
export { isShennianRunServiceCommand } from './daemon-process.js';
|
|
4
|
+
export { inferDaemonLauncherFromCommand, isShennianRunServiceCommand } from './daemon-process.js';
|
|
5
5
|
export declare function isSafeSnapshotEnvKey(key: string): boolean;
|
|
6
6
|
type Platform = 'darwin' | 'linux' | 'win32';
|
|
7
7
|
type ServiceLaunchMode = 'direct' | 'global-shim' | 'npx';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import c from"chalk";import o from"node:fs";import a from"node:path";import d from"node:os";import{execSync as u,spawn as
|
|
2
|
-
`)}function
|
|
1
|
+
import c from"chalk";import o from"node:fs";import a from"node:path";import d from"node:os";import{execSync as u,spawn as ye}from"node:child_process";import{randomUUID as B}from"node:crypto";import{fileURLToPath as we}from"node:url";import{getShennianDir as Ee,loadConfig as V,resolveShennianPath as S,saveConfig as ve}from"../config/index.js";import{buildAugmentedPath as Pe}from"../env-path.js";import{buildWindowsLauncherCommand as Ae,buildWindowsScheduledTaskCommands as Ne,buildWindowsScheduledTaskXml as Ie,buildWindowsStartupVbs as De,escapeXml as T,isWindowsCmdScript as ke,quoteCmdArg as G,quoteSystemdArg as _e,suspendWindowsScheduledTask as be}from"./daemon-windows.js";import{waitForDaemonReadyStatus as x}from"./daemon-start-wait.js";import{findRunningWindowsDaemonProcessIds as Re,inferDaemonLauncherFromCommand as K,isShennianRunServiceCommand as Te,readWindowsProcessCommand as xe}from"./daemon-process.js";import{getCurrentVersion as J}from"../upgrade/engine.js";import{buildWindowsLauncherCommand as xn,buildWindowsScheduledTaskCommands as Ln,buildWindowsScheduledTaskSuspendCommands as On,buildWindowsScheduledTaskXml as Cn,buildWindowsStartupVbs as Hn,suspendWindowsScheduledTask as $n}from"./daemon-windows.js";import{inferDaemonLauncherFromCommand as Un,isShennianRunServiceCommand as jn}from"./daemon-process.js";const Le=a.dirname(we(import.meta.url)),h=Ee(),y=S("daemon.pid"),m=S("daemon.log"),L=S("remote-access.disabled"),k=S("daemon-launcher.json"),q=a.resolve(Le,"../../bin/shennian.js"),X=process.execPath,Y=new Set(["PATH","HOME","USERPROFILE","HOMEDRIVE","HOMEPATH","USERNAME","USERDOMAIN","COMPUTERNAME","USER","LOGNAME","SHELL","TMPDIR","LANG","LC_ALL","LC_CTYPE","SSH_AUTH_SOCK","XDG_CONFIG_HOME","XDG_DATA_HOME","TEMP","TMP","APPDATA","LOCALAPPDATA","ELECTRON_RUN_AS_NODE","SHENNIAN_DESKTOP_CLI_SCRIPT","SHENNIAN_DESKTOP_CLI_BRIDGE","SHENNIAN_DESKTOP_SERVER_URL","SHENNIAN_WECHAT_CHANNEL_HELPER_DIR","SHENNIAN_HOME","SHENNIAN_ACCOUNT_NAMESPACE_ID","SHENNIAN_NATIVE_FUSION_DISABLED","SHENNIAN_WECHAT_DELIVERABILITY_TRACE"]);function Oe(e){return Y.has(e)}function p(){const e=d.platform();return e==="darwin"||e==="linux"||e==="win32"?e:"linux"}function O(e){const n=e.replace(/\\/g,"/").toLowerCase(),r=d.tmpdir().replace(/\\/g,"/").toLowerCase();return n.includes("/_npx/")||n.includes("/npm-cache/_npx/")||n.includes("/pnpm/dlx/")||n.startsWith(r.endsWith("/")?r:`${r}/`)}function Ce(e){return process.env.ELECTRON_RUN_AS_NODE==="1"&&e.desktopBridgePath&&o.existsSync(e.scriptPath)&&o.existsSync(e.desktopBridgePath)?{command:e.nodeExec,args:[e.desktopBridgePath,e.scriptPath,"run-service"],mode:"direct"}:o.existsSync(e.scriptPath)&&(process.env.SHENNIAN_E2E_ISOLATED_DAEMON==="1"||!O(e.scriptPath))?{command:e.nodeExec,args:[e.scriptPath,"run-service"],mode:"direct"}:e.shennianCommandPath&&!O(e.shennianCommandPath)?{command:e.shennianCommandPath,args:["run-service"],mode:"global-shim"}:e.npxPath?{command:e.npxPath,args:["--yes","shennian","run-service"],mode:"npx"}:{command:e.nodeExec,args:[e.scriptPath,"run-service"],mode:"direct"}}function He(e){const n=e.trim();if(!n)return null;if(n.startsWith("{"))try{const t=JSON.parse(n),s=Number(t.pid);return!Number.isInteger(s)||s<=0?null:{pid:s,...typeof t.instanceId=="string"?{instanceId:t.instanceId}:{},...typeof t.version=="string"?{version:t.version}:{},...t.launcher==="desktop-managed"||t.launcher==="global-cli"||t.launcher==="unknown"?{launcher:t.launcher}:{},...typeof t.startedAt=="string"?{startedAt:t.startedAt}:{},...t.adopted===!0?{adopted:!0}:{}}}catch{return null}const r=parseInt(n,10);return isNaN(r)?null:{pid:r}}function A(){try{return He(o.readFileSync(y,"utf-8"))}catch{return null}}function v(e){try{return process.kill(e,0),!0}catch{return!1}}function z(e,n=3e3){const r=Date.now();for(;Date.now()-r<n;){if(!v(e))return!0;Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,100)}return!v(e)}function $e(){try{return o.lstatSync(L),!0}catch(e){return!(e&&typeof e=="object"&&"code"in e&&e.code==="ENOENT")}}function Me(){try{o.unlinkSync(L)}catch(e){if(e&&typeof e=="object"&&"code"in e&&e.code==="ENOENT")return;throw e}}function Ue(e,n){const r=a.dirname(e),t=`${e}.${process.pid}.${B()}.tmp`;o.mkdirSync(r,{recursive:!0});let s=null;try{s=o.openSync(t,"w",384),o.writeSync(s,n,void 0,"utf8"),o.fsyncSync(s),o.closeSync(s),s=null,o.renameSync(t,e);try{const i=o.openSync(r,"r");try{o.fsyncSync(i)}finally{o.closeSync(i)}}catch{}}finally{s!==null&&o.closeSync(s);try{o.unlinkSync(t)}catch{}}}function je(e={}){const n=e.disabledAt??new Date().toISOString(),r=e.markerFile??L,t=e.platform??p(),s=e.servicePresent??(H()&&U(t)),i=e.execCommand??(l=>{u(l,{stdio:"pipe",windowsHide:!0})});if(Ue(r,n),!s)return{disabledAt:n,autoStartDisabled:!0};try{return i(t==="darwin"?`launchctl disable "${P()}"`:t==="linux"?"systemctl --user disable shennian":`schtasks /change /tn "${D}" /disable`),{disabledAt:n,autoStartDisabled:!0}}catch(l){return{disabledAt:n,autoStartDisabled:!1,autoStartError:l instanceof Error?l.message:String(l)}}}function We(e={}){const n=e.platform??p();if(!(e.servicePresent??(H()&&U(n))))return{serviceStopped:!0};const t=e.execCommand??(s=>{u(s,{stdio:"pipe",windowsHide:!0})});try{return t(n==="darwin"?`launchctl bootout "${P()}"`:n==="linux"?"systemctl --user stop shennian":`schtasks /end /tn "${D}"`),{serviceStopped:!0}}catch(s){return{serviceStopped:!1,error:s instanceof Error?s.message:String(s)}}}function Q(){return process.env.SHENNIAN_DESKTOP_CLI_SCRIPT?"desktop-managed":"global-cli"}function Fe(){return`${process.pid}-${Date.now()}-${B()}`}function Be(e,n,r={}){o.mkdirSync(h,{recursive:!0}),o.writeFileSync(y,JSON.stringify({pid:e,instanceId:n,...r.version?{version:r.version}:{},launcher:r.launcher??Q(),...r.adopted?{adopted:!0}:{},startedAt:new Date().toISOString()},null,2))}function _n(e,n){const r=A();if(!(r?.pid!==e||r.instanceId!==n))try{o.unlinkSync(y)}catch{}}function Z(e,n=Q(),r){o.mkdirSync(h,{recursive:!0}),o.writeFileSync(k,JSON.stringify({pid:e,launcher:n,...r?{instanceId:r}:{},updatedAt:new Date().toISOString()},null,2))}function Ve(e){if(e)try{if(JSON.parse(o.readFileSync(k,"utf-8")).instanceId!==e)return}catch{return}try{o.unlinkSync(k)}catch{}}function Ge(e){e&&Z(e)}function Ke(e,n){if(!e||!n)return"unknown";try{const r=JSON.parse(o.readFileSync(k,"utf-8"));if(r.pid!==e)return"unknown";if(r.launcher==="desktop-managed"||r.launcher==="global-cli")return r.launcher}catch{}return C(e)}function C(e){if(p()==="win32"){const n=xe(e);return n?K(n):"unknown"}try{const n=u(`ps -p ${e} -o command=`,{encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:1e3,windowsHide:!0}).replace(/\\/g,"/");return K(n)}catch{}return"unknown"}function ee(e=process.pid){if(p()==="win32")return Re(e);try{return u("ps -axo pid=,command=",{encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:1e3,windowsHide:!0}).split(/\r?\n/).map(r=>{const t=r.trim().match(/^(\d+)\s+(.+)$/);if(!t)return null;const s=Number(t[1]),i=t[2];return!Number.isInteger(s)||s===e?null:Te(i)?s:null}).filter(r=>typeof r=="number")}catch{return[]}}function ne(e=process.env,n=h,r=d.tmpdir(),t=a.join(d.homedir(),".shennian")){if(e.SHENNIAN_E2E_ISOLATED_DAEMON!=="1"||!e.SHENNIAN_HOME?.trim()||a.resolve(n)===a.resolve(t))return!1;const s=a.relative(a.resolve(r),a.resolve(n));return s!==""&&s!==".."&&!s.startsWith(`..${a.sep}`)&&!a.isAbsolute(s)||a.resolve(n)===a.resolve(e.SHENNIAN_HOME)}function te(e=process.env,n=h){return!ne(e,n)}function H(e=process.env,n=h){return!ne(e,n)}function f(e={}){let n=A(),r=n?.pid??null,t=r!==null&&v(r),s=r!==null&&!t,i=n?.adopted===!0;const l=V();if(s&&e.cleanupStale){try{o.unlinkSync(y)}catch{}n=null,r=null,t=!1,s=!1}if(!t&&te()){const E=ee()[0];if(E&&(r=E,t=!0,s=!1,i=!0,e.cleanupStale)){const F=Fe();Be(E,F,{launcher:C(E),adopted:!0}),Z(E,C(E)),n={pid:E,instanceId:F,adopted:!0}}}return{running:t,pid:r,stale:s,remoteAccessDisabled:$e(),launcher:Ke(r,t),platform:p(),shennianDir:h,pidFile:y,logFile:m,...n?.instanceId?{instanceId:n.instanceId}:{},...i?{adopted:!0}:{},...l.machineId?{machineId:l.machineId}:{},paired:!!(l.machineToken&&l.machineId),...l.serverUrl?{serverUrl:l.serverUrl}:{}}}function w(e){process.stdout.write(`${JSON.stringify(e,null,2)}
|
|
2
|
+
`)}function re(e){const n=e?.trim();if(!n)return;const r=V();r.serverUrl=n,ve(r)}function oe(e){return e?.trim()||process.env.SHENNIAN_DESKTOP_SERVER_URL?.trim()||void 0}const $="com.shennian.agent",g=a.join(d.homedir(),"Library/LaunchAgents",`${$}.plist`),se=S("Shennian.app"),Je=a.join(d.homedir(),"AppData","Roaming","Microsoft","Windows","Start Menu","Programs","Startup"),_=S("autostart.cmd"),b=S("autostart.vbs"),R=S("autostart.xml"),qe=a.join(Je,"ShennianAgent.vbs");function ie(e){const n=p()==="win32"?`where ${e}`:`command -v ${e}`;try{return u(n,{stdio:["ignore","pipe","pipe"],encoding:"utf-8",windowsHide:!0}).split(/\r?\n/).map(s=>s.trim()).find(Boolean)??null}catch{return null}}function Xe(){const e=p()==="win32"?"npx.cmd":"npx",n=a.join(a.dirname(X),e);return o.existsSync(n)?n:ie("npx")}function N(){return Ce({nodeExec:X,scriptPath:q,shennianCommandPath:ie("shennian"),npxPath:Xe(),desktopBridgePath:process.env.SHENNIAN_DESKTOP_CLI_BRIDGE})}function ce(){try{u(`schtasks /delete /tn "${D}" /f`,{stdio:"pipe",windowsHide:!0})}catch{}}function ae(){try{o.unlinkSync(qe)}catch{}}function Ye(){const e=process.env.USERDOMAIN?.trim(),n=process.env.COMPUTERNAME?.trim(),r=process.env.USERNAME?.trim()||d.userInfo().username;return e&&e.toUpperCase()!=="WORKGROUP"?`${e}\\${r}`:n?`${n}\\${r}`:r}function ze(e){if(p()==="win32"&&ke(e.command)){const n=[e.command,...e.args].map(G).join(" ");return{command:process.env.ComSpec||"cmd.exe",args:["/d","/s","/c",`"${n}"`],windowsVerbatimArguments:!0}}return{command:e.command,args:e.args}}function Qe(e,n,r=process.env){return{detached:!0,stdio:["ignore",n,n],env:r,windowsHide:!0,...e.windowsVerbatimArguments?{windowsVerbatimArguments:!0}:{}}}function Ze(){const e=N();o.writeFileSync(_,Ae(e,m)),o.writeFileSync(b,De(_)),ae(),ce();const n=Ie({userId:Ye(),command:a.join(process.env.SystemRoot||"C:\\Windows","System32","wscript.exe"),arguments:[G(b)]});o.writeFileSync(R,n,"utf8");const r=Ne({taskName:D,xmlPath:R});try{return u(r.create,{stdio:"pipe",windowsHide:!0}),u(r.run,{stdio:"pipe",windowsHide:!0}),!0}catch{return!1}}function en(){be(D,e=>{u(e,{stdio:"pipe",windowsHide:!0})})}function ue(){const e={};for(const n of Y)process.env[n]&&(e[n]=process.env[n]);if(e.HOME??=d.homedir(),e.PATH=Pe({pathValue:e.PATH,env:e}),e.USER??=d.userInfo().username,p()==="win32"){const n=process.env.TEMP||process.env.TMP||d.tmpdir(),r=d.homedir();e.USERPROFILE??=r;const t=a.win32.parse(r);e.HOMEDRIVE??=t.root.replace(/[\\/]$/,"")||process.env.HOMEDRIVE||"",e.HOMEPATH??=r.slice((e.HOMEDRIVE||"").length)||process.env.HOMEPATH||"",e.USERNAME??=process.env.USERNAME||d.userInfo().username,e.COMPUTERNAME??=process.env.COMPUTERNAME||"",e.TMPDIR??=n,e.TEMP??=n,e.TMP??=n}else e.TMPDIR??="/tmp";return e}function nn(e={}){const n=ue(),r=e.launch??N(),t=Object.entries(n).map(([i,l])=>` <key>${T(i)}</key>
|
|
3
3
|
<string>${T(l)}</string>`).join(`
|
|
4
4
|
`),s=[r.command,...r.args].map(i=>` <string>${T(i)}</string>`).join(`
|
|
5
5
|
`);return`<?xml version="1.0" encoding="UTF-8"?>
|
|
@@ -27,8 +27,8 @@ ${t}
|
|
|
27
27
|
<key>StandardErrorPath</key>
|
|
28
28
|
<string>${m}</string>
|
|
29
29
|
</dict>
|
|
30
|
-
</plist>`}function
|
|
31
|
-
`),t=[n.command,...n.args].map(
|
|
30
|
+
</plist>`}function de(e=se){o.rmSync(e,{recursive:!0,force:!0})}function tn(e=p()){return e!=="darwin"?null:"macOS may show \u201CNode.js Foundation\u201D under Allow in the Background. This is the Node.js runtime used by Shennian Client."}const I=a.join(d.homedir(),".config/systemd/user/shennian.service");function rn(){const e=ue(),n=N(),r=Object.entries(e).map(([s,i])=>`Environment=${s}=${i}`).join(`
|
|
31
|
+
`),t=[n.command,...n.args].map(_e).join(" ");return`[Unit]
|
|
32
32
|
Description=Shennian Agent Daemon
|
|
33
33
|
After=network.target
|
|
34
34
|
|
|
@@ -41,6 +41,6 @@ StandardOutput=append:${m}
|
|
|
41
41
|
StandardError=append:${m}
|
|
42
42
|
|
|
43
43
|
[Install]
|
|
44
|
-
WantedBy=default.target`}const D="ShennianAgent";function
|
|
44
|
+
WantedBy=default.target`}const D="ShennianAgent";function on(e){u(e,{stdio:"pipe",windowsHide:!0})}function sn(){const e=process.getuid?.();if(typeof e=="number")return e;const n=d.userInfo();return typeof n.uid=="number"?n.uid:n.username}function P(e=sn()){return`gui/${e}/${$}`}function cn(e=on){try{return e(`launchctl enable "${P()}"; launchctl unload "${g}" 2>/dev/null; launchctl load -w "${g}"`),e(`launchctl kickstart -k "${P()}"`),!0}catch{try{return e(`launchctl enable "${P()}"`),e(`launchctl load -w "${g}"`),e(`launchctl kickstart -k "${P()}"`),!0}catch{return!1}}}function an(){o.mkdirSync(h,{recursive:!0});const e={};for(const[n,r]of Object.entries(process.env))r!==void 0&&Oe(n)&&(e[n]=r);o.writeFileSync(S("env.json"),JSON.stringify(e,null,2))}function le(e={}){o.mkdirSync(h,{recursive:!0});const n=f({cleanupStale:!0});if(n.pid!==null&&n.running&&!M(n)){e.quiet||console.log(c.green(`\u2713 Background service already running (PID ${n.pid})`));return}pe(n);const r=o.openSync(m,"a"),t=ze(N()),s=ye(t.command,t.args,Qe(t,r));s.unref(),o.closeSync(r),Ge(s.pid),e.quiet||(console.log(c.green(`\u2713 Background service started (PID ${s.pid})`)),console.log(c.gray(` Logs: ${m}`)))}function M(e,n=A(),r=J()){return e.pid===null||!e.running||e.launcher==="desktop-managed"?!1:e.adopted===!0||n?.version!==r}function U(e=p()){switch(e){case"darwin":return o.existsSync(g)&&!o.existsSync(se);case"linux":return o.existsSync(I);case"win32":return o.existsSync(_)&&o.existsSync(b)&&o.existsSync(R)}}function un(e,n,r,t=A(),s=J()){return!n.api?.trim()&&e.pid!==null&&e.running&&!e.stale&&!e.remoteAccessDisabled&&(e.launcher==="desktop-managed"||r)&&!M(e,t,s)}function pe(e=f({cleanupStale:!0})){if(!(!M(e)||e.pid===null))try{process.kill(e.pid,"SIGTERM"),z(e.pid,5e3)||(process.kill(e.pid,"SIGKILL"),z(e.pid,2e3));try{A()?.pid===e.pid&&o.unlinkSync(y)}catch{}}catch{}}function me(e={}){if(o.mkdirSync(h,{recursive:!0}),!H())return!1;const n=p();switch(N().mode==="direct"&&O(q)&&console.warn(c.yellow("\u26A0 Warning: Current CLI path is temporary (npx). Auto-start may not work after reboot.\n Run `npm install -g shennian@latest` for reliable auto-start.")),n){case"darwin":{const t=a.dirname(g);o.mkdirSync(t,{recursive:!0}),de(),o.writeFileSync(g,nn());const s=cn(),i=tn(n);return!e.quiet&&i&&console.log(c.gray(`\u2139 ${i}`)),s}case"linux":{const t=a.dirname(I);o.mkdirSync(t,{recursive:!0}),o.writeFileSync(I,rn());try{u("systemctl --user daemon-reload && systemctl --user enable shennian",{stdio:"pipe",windowsHide:!0})}catch{return!1}try{u(`loginctl enable-linger ${d.userInfo().username}`,{stdio:"pipe",windowsHide:!0})}catch{}try{return u("systemctl --user restart shennian",{stdio:"pipe",windowsHide:!0}),!0}catch{return!1}}case"win32":return Ze()}}function dn(){const n=f({cleanupStale:!0}).pid;if(n===null)return{};if(!v(n)){try{o.unlinkSync(y)}catch{}return{stalePid:n}}try{return process.kill(n,"SIGTERM"),{stoppedPid:n}}catch(r){return{error:r instanceof Error?r.message:String(r)}}}async function fe(e=5e3){const n=dn();if(!n.stoppedPid)return n;if(!await W(n.stoppedPid,e))try{process.kill(n.stoppedPid,"SIGKILL"),await W(n.stoppedPid,2e3)}catch(t){return{...n,error:t instanceof Error?t.message:String(t)}}try{o.unlinkSync(y)}catch{}if(Ve(),te()){for(const t of ee())if(t!==n.stoppedPid)try{process.kill(t,"SIGTERM"),await W(t,2e3)}catch{}}return n}function ln(e={}){re(oe(e.api)),Me(),pe(),me({quiet:e.json})||le({quiet:e.json}),e.json?w(x(()=>f({cleanupStale:!0}))):console.log(c.green("\u2713 Background service started"))}async function pn(e={}){const n=je(),r=We(),t=await fe(),s=f({cleanupStale:!0}),i=t.error??n.autoStartError??r.error;if(e.json){w(i?{...s,error:i}:s);return}i?console.error(c.red(`\u2717 Failed to stop completely: ${i}`)):console.log(c.green("\u2713 Background service stopped"))}function Se(e){const n=f({cleanupStale:!0});if(un(n,e,U())){e.json?w(n):console.log(c.green(`\u2713 Background service already running (PID ${n.pid})`));return}an(),ln(e)}async function j(e={}){await pn(e)}async function W(e,n=5e3){const r=Date.now();for(;Date.now()-r<n;){if(!v(e))return!0;await new Promise(t=>setTimeout(t,100))}return!v(e)}async function mn(e={}){const n=f({cleanupStale:!0});if(n.remoteAccessDisabled){e.json?w({...n,error:"remote_access_disabled_use_shennian_start"}):console.error(c.yellow("Remote access is paused. Run `shennian start` on this computer to resume."));return}re(oe(e.api));const r=p();r==="win32"&&en();const t=await fe();if(t.error){e.json?w({...f(),error:t.error}):console.error(c.red(`\u2717 Failed to stop: ${t.error}`));return}if(t.stoppedPid!==void 0?e.json||console.log(c.green(`\u2713 Background service stopped (PID ${t.stoppedPid})`)):t.stalePid!==void 0?e.json||console.log(c.yellow(`\u26A0 Service process no longer exists, cleaned up stale PID ${t.stalePid}`)):e.json||console.log(c.gray("\u25CF Background service not running, starting it now")),(r==="linux"||r==="win32")&&me()){e.json&&w(x(()=>f({cleanupStale:!0})));return}le({quiet:e.json}),e.json&&w(x(()=>f({cleanupStale:!0})))}function he(e={}){const n=f({cleanupStale:!0});if(e.json){w(n);return}if(n.pid===null){console.log(c.gray("\u25CF Background service not running"));return}n.running?(console.log(c.green(`\u25CF Background service running (PID ${n.pid})`)),console.log(c.gray(` Logs: ${m}`))):console.log(c.yellow(`\u25CF Background service stopped (PID ${n.pid} is stale)`))}function ge(e){if(!o.existsSync(m)){console.log(c.gray("No logs yet"));return}try{const n=u(d.platform()==="win32"?`powershell Get-Content -Tail ${e.lines} "${m}"`:`tail -n ${e.lines} "${m}"`,{encoding:"utf-8",windowsHide:!0});process.stdout.write(n)}catch{const n=o.readFileSync(m,"utf-8").split(`
|
|
45
45
|
`).slice(-e.lines);console.log(n.join(`
|
|
46
|
-
`))}}async function
|
|
46
|
+
`))}}async function fn(){switch(await j(),p()){case"darwin":{if(o.existsSync(g)){try{u(`launchctl unload -w "${g}"`,{stdio:"pipe",windowsHide:!0})}catch{}o.unlinkSync(g)}de(),console.log(c.green("\u2713 Auto-start uninstalled (launchd)"));break}case"linux":{try{u("systemctl --user disable --now shennian",{stdio:"pipe",windowsHide:!0})}catch{}if(o.existsSync(I)){o.unlinkSync(I);try{u("systemctl --user daemon-reload",{stdio:"pipe",windowsHide:!0})}catch{}}console.log(c.green("\u2713 Auto-start uninstalled (systemd)"));break}case"win32":{ce();try{o.unlinkSync(_)}catch{}try{o.unlinkSync(b)}catch{}try{o.unlinkSync(R)}catch{}ae(),console.log(c.green("\u2713 Auto-start uninstalled (Task Scheduler)"));break}}}function bn(e){e.command("start").description("Start the background service").option("--json","Print machine-readable status JSON").option("--api <url>","Server URL override").action(t=>Se(t)),e.command("stop").description("Stop the background service").option("--json","Print machine-readable status JSON").action(t=>j(t)),e.command("status").description("Show background service status").option("--json","Print machine-readable status JSON").action(t=>he(t)),e.command("logs").description("Show recent logs").option("-n, --lines <n>","Number of lines","50").action(t=>ge({lines:parseInt(t.lines,10)}));const n=e.command("daemon",{hidden:!0}).description("Deprecated: use top-level start/stop/status/logs"),r=(t,s)=>{s||console.error(c.yellow(`\u26A0 Deprecated command. Use \`shennian ${t}\` instead.`))};n.command("start").description("Start the background service").option("--json","Print machine-readable status JSON").option("--api <url>","Server URL override").action(t=>{r("start",t.json),Se(t)}),n.command("stop").description("Stop the background service").option("--json","Print machine-readable status JSON").action(async t=>{r("stop",t.json),await j(t)}),n.command("restart").description("Restart the background service").option("--json","Print machine-readable status JSON").option("--api <url>","Server URL override").action(t=>{r("stop && shennian start",t.json),mn(t)}),n.command("status").description("Show background service status").option("--json","Print machine-readable status JSON").action(t=>{r("status",t.json),he(t)}),n.command("logs").description("Show recent logs").option("-n, --lines <n>","Number of lines","50").action(t=>{r("logs"),ge({lines:parseInt(t.lines,10)})}),n.command("uninstall").description("Uninstall auto-start service").action(fn)}export{Qe as buildDaemonSpawnOptions,nn as buildMacLaunchdPlist,rn as buildSystemdUnit,xn as buildWindowsLauncherCommand,Ln as buildWindowsScheduledTaskCommands,On as buildWindowsScheduledTaskSuspendCommands,Cn as buildWindowsScheduledTaskXml,Hn as buildWindowsStartupVbs,un as canReuseRunningDaemonForStart,ue as captureEnvForService,Ve as clearDaemonLauncher,_n as clearDaemonPidIfOwner,Me as clearRemoteAccessDisabled,Fe as createDaemonInstanceId,ee as findRunningDaemonProcessIds,Q as getCurrentProcessDaemonLauncher,f as getDaemonStatus,P as getLaunchdServiceTarget,tn as getMacBackgroundItemNotice,Un as inferDaemonLauncherFromCommand,me as installService,U as isAutoStartServicePresent,O as isEphemeralCliPath,ne as isIsolatedDaemonE2eInstance,$e as isRemoteAccessDisabled,Oe as isSafeSnapshotEnvKey,jn as isShennianRunServiceCommand,je as prepareRemoteAccessPause,Ge as recordStartedDaemon,bn as registerDaemonCommand,cn as reloadLaunchdAgent,de as removeLegacyMacBackgroundApp,Ce as resolveServiceLaunchSpec,an as saveEnvSnapshot,te as shouldDiscoverGlobalDaemonProcesses,H as shouldInstallPlatformService,M as shouldReplaceRunningDaemon,le as startDaemonProcess,We as stopPreparedRemoteAccessService,$n as suspendWindowsScheduledTask,Z as writeDaemonLauncher,Be as writeDaemonPid};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import l from"node:fs";import
|
|
1
|
+
import l from"node:fs";import{resolveShennianPath as g}from"../config/index.js";function f(){const n=process.env.CODEX_SESSION_ID?.trim()||process.env.CODEX_THREAD_ID?.trim();if(n)return{host:"codex",hostSessionId:n};const i=process.env.CLAUDE_CODE_SESSION_ID?.trim()||process.env.CLAUDE_SESSION_ID?.trim();return i?{host:"claude",hostSessionId:i}:null}function w(){const n=g("runtime","manager-ipc.json"),i=l.statSync(n);if(process.platform!=="win32"){const e=typeof process.getuid=="function"?process.getuid():i.uid;if(i.uid!==e||(i.mode&63)!==0)throw new Error("Shennian daemon Manager runtime file has unsafe permissions")}const o=JSON.parse(l.readFileSync(n,"utf-8")),t=typeof o.url=="string"?o.url:"",r=typeof o.token=="string"?o.token:"";if(!/^http:\/\/127\.0\.0\.1:\d+$/.test(t)||!r)throw new Error("Shennian daemon Manager runtime is unavailable");return{url:t,token:r}}async function k(){const n=process.env.SHENNIAN_MANAGER_IPC_URL,i=process.env.SHENNIAN_MANAGER_IPC_TOKEN,o=process.env.SHENNIAN_MANAGER_SESSION_ID;if(n&&i&&o)return{url:n,token:i,managerSessionId:o};const t=f();if(!t)throw new Error("This command requires a Shennian Manager session or a current Codex/Claude Code conversation.");const r=w(),e=await fetch(`${r.url}/skill/context`,{method:"POST",headers:{authorization:`Bearer ${r.token}`,"content-type":"application/json"},body:JSON.stringify({...t,workDir:process.cwd()})}),s=await e.json().catch(()=>({ok:!1,error:e.statusText}));if(!e.ok||!s.ok||typeof s.managerSessionId!="string")throw new Error(s.error||"Unable to establish the native Agent controller context");return{...r,managerSessionId:s.managerSessionId}}async function a(n,i){const o=await k(),t=await fetch(`${o.url}${n}`,{method:"POST",headers:{authorization:`Bearer ${o.token}`,"content-type":"application/json","x-shennian-manager-session-id":o.managerSessionId},body:JSON.stringify({...i,managerSessionId:o.managerSessionId})}),r=await t.json().catch(()=>({ok:!1,error:t.statusText}));if(!t.ok||!r.ok)throw new Error(r.error||`Manager IPC failed: ${t.status}`);return r}function m(n){console.log(JSON.stringify(n,null,2))}function u(n){console.log(typeof n.markdown=="string"?n.markdown:"ok")}function p(n){return n.messageFile?l.readFileSync(n.messageFile,"utf-8"):n.message??""}function I(n){const i=n.command("manager",{hidden:!0}).description("Manager Session local tools"),o=i.command("sessions").description("Manage same-project worker sessions");o.command("list").description("List same-project sessions visible to this Manager").option("--json","Print JSON").action(async e=>{const s=await a("/sessions/list",{});if(e.json)m(s);else{const c=s.sessions??[];for(const d of c)console.log(`${d.sessionId} ${d.agentType} ${d.role??""} ${d.status} ${d.title??d.summary??""}`)}}),o.command("start").description("Start a worker session in the same project").requiredOption("--agent <agent>","Worker agent type, e.g. codex, claude, cursor, opencode, pi, or custom:<name>").requiredOption("--workdir <path>","Worker workdir; must match Manager workdir").option("--title <title>","Short worker title").option("--model <model>","Worker model id").option("--message <text>","Worker prompt").option("--message-file <path>","Read worker prompt from file").option("--json","Print JSON").action(async e=>{const s=await a("/sessions/start",{agentType:e.agent,workDir:e.workdir,title:e.title,modelId:e.model,message:p(e)});e.json?m(s):u(s)}),o.command("send").description("Queue a message for a managed worker; runs immediately if idle").requiredOption("--session-id <id>","Worker session id").option("--message <text>","Message text").option("--message-file <path>","Read message from file").option("--direct","Deprecated compatibility flag; delivery still uses the durable queue").action(async e=>{const s=await a("/sessions/send",{sessionId:e.sessionId,message:p(e),enqueue:!e.direct});u(s)});const t=o.command("queue").description("Inspect and edit pending worker messages");t.command("list").description("List pending messages for a managed worker").requiredOption("--session-id <id>","Worker session id").option("--json","Print JSON").action(async e=>{const s=await a("/sessions/queue",{sessionId:e.sessionId});if(e.json)m(s);else{const c=s.queue?.pending??[];for(const d of c)console.log(`${d.id} ${d.text.replace(/\s+/g," ").slice(0,120)}`)}}),t.command("edit").description("Edit a pending worker message").requiredOption("--session-id <id>","Worker session id").requiredOption("--message-id <id>","Queued message id").option("--message <text>","Replacement message text").option("--message-file <path>","Read replacement message from file").action(async e=>{await a("/sessions/queue/edit",{sessionId:e.sessionId,queueMessageId:e.messageId,message:p(e)}),console.log("ok")}),t.command("delete").description("Delete a pending worker message").requiredOption("--session-id <id>","Worker session id").requiredOption("--message-id <id>","Queued message id").action(async e=>{await a("/sessions/queue/delete",{sessionId:e.sessionId,queueMessageId:e.messageId}),console.log("ok")});const r=async e=>{const s=await a("/sessions/stop",{sessionId:e.sessionId});u(s)};o.command("stop").aliases(["terminate","kill"]).description("Stop or terminate a running managed worker").requiredOption("--session-id <id>","Worker session id").action(r),o.command("read").description("Read a managed worker transcript").requiredOption("--session-id <id>","Worker session id").option("--limit <n>","Message limit","200").option("--json","Print JSON").action(async e=>{const s=await a("/sessions/read",{sessionId:e.sessionId,limit:Number(e.limit)});e.json?m(s):m(s.messages??[])}),o.command("wait").description("Wait up to a bounded timeout for the next worker progress or terminal event").requiredOption("--session-id <id>","Worker session id").option("--timeout <seconds>","Maximum wait in seconds (1-600)","600").option("--json","Print JSON").action(async e=>{const s=Math.max(1,Math.min(Number(e.timeout)||600,600)),c=await a("/sessions/wait",{sessionId:e.sessionId,timeoutMs:s*1e3});e.json?m(c):c.timedOut?console.log(`\u7B49\u5F85\u8D85\u65F6\uFF1BAgent \u5F53\u524D\u72B6\u6001\uFF1A${String(c.status||"unknown")}`):u(c)}),i.command("memory").description("Manager project memory helpers").command("path").description("Print project memory directory path").action(async()=>{const e=await a("/memory/path",{});console.log(e.path)})}export{I as registerManagerCommand};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const MANAGER_SYSTEM_PROMPT = "\u4F60\u662F\u9879\u76EE\u7ECF\u7406\uFF0C\u662F\u5F53\u524D\u9879\u76EE\u7684\u7BA1\u7406\u8005\u3002\n\n\u4F60\u7684\u804C\u8D23\uFF1A\n- \u7406\u89E3\u7528\u6237\u76EE\u6807\u3002\n- \u62C6\u89E3\u4EFB\u52A1\u3002\n- \u521B\u5EFA\u3001\u6307\u6D3E\u3001\u89C2\u5BDF\u548C\u505C\u6B62\u540C\u4E00\u9879\u76EE\u76EE\u5F55\u4E0B\u7684 worker Agent session\u3002\n- \u6C47\u603B worker \u7ED3\u679C\u3002\n- \u5224\u65AD\u662F\u5426\u9700\u8981\u7EE7\u7EED\u7B49\u5F85\u3001\u8C03\u6574\u5B89\u6392\u3001\u8BE2\u95EE\u7528\u6237\u6216\u9A8C\u6536\u3002\n- \u5728\u9879\u76EE .shennian/ \u76EE\u5F55\u4E0B\u7EF4\u62A4\u5FC5\u8981\u7684\u8BA1\u5212\u3001\u8BB0\u5F55\u548C\u9879\u76EE\u8BB0\u5FC6\u3002\n\n\u4F60\u7684\u8FB9\u754C\uFF1A\n- \u4E0D\u8981\u628A\u81EA\u5DF1\u5F53\u4F5C\u4E3B\u8981\u6267\u884C\u8005\u3002\n- \u4E0D\u8981\u76F4\u63A5\u7F16\u8F91\u4E1A\u52A1\u4EE3\u7801\uFF0C\u9664\u975E\u7528\u6237\u660E\u786E\u8981\u6C42\u4F60\u4EB2\u81EA\u6267\u884C\u3002\n- \u53EF\u4EE5\u8BFB\u53D6\u6587\u4EF6\u3001\u641C\u7D22\u9879\u76EE\u548C\u68C0\u67E5\u4E0A\u4E0B\u6587\uFF0C\u4EE5\u4FBF\u505A\u5224\u65AD\u3002\n- \u9700\u8981\u4FEE\u6539\u4EE3\u7801\u3001\u8FD0\u884C\u6D4B\u8BD5\u3001\u8C03\u7814\u65B9\u6848\u65F6\uFF0C\u4F18\u5148\u521B\u5EFA\u6216\u6307\u6D3E worker\u3002\n- \u6BCF\u6B21\u6536\u5230\u65B0\u4EFB\u52A1\u3001\u8865\u5145\u8981\u6C42\u3001\u7EA0\u504F\u6216\u5916\u90E8\u6D88\u606F\u65F6\uFF0C\u5148\u7528 sessions list \u67E5\u770B\u5F53\u524D\u540C\u9879\u76EE worker\uFF1B\u5982\u679C\u53EF\u80FD\u76F8\u5173\uFF0C\u518D\u7528 sessions read \u8BFB\u53D6\u5FC5\u8981\u6458\u8981\u540E\u5224\u65AD\u662F\u5426\u590D\u7528\u3002\n- \u5982\u679C\u5DF2\u6709 worker \u6B63\u5728\u5904\u7406\u540C\u4E00\u76EE\u6807\u3001\u540C\u4E00\u529F\u80FD\u533A\u3001\u540C\u4E00\u6587\u4EF6\u8303\u56F4\u6216\u540C\u4E00\u95EE\u9898\u94FE\u8DEF\uFF0C\u4F18\u5148\u7528 sessions send \u628A\u65B0\u8981\u6C42\u53D1\u7ED9\u8FD9\u4E2A worker\uFF1B\u5373\u4F7F worker \u6B63\u5FD9\u4E5F\u53EF\u4EE5\u53D1\u9001\uFF0C\u9ED8\u8BA4\u4F1A\u8FDB\u5165\u672C\u673A\u961F\u5217\uFF0C\u4E0D\u8981\u56E0\u4E3A\u5B83\u5FD9\u5C31\u65B0\u5EFA worker\u3002\n- \u53EA\u6709\u6CA1\u6709\u76F8\u5173 worker\u3001\u73B0\u6709 worker \u5DF2\u660E\u663E\u4E0D\u9002\u5408\u7EE7\u7EED\u63A8\u8FDB\u3001\u6216\u4EFB\u52A1\u9700\u8981\u5E76\u884C\u62C6\u5206\u7ED9\u4E0D\u540C\u4E13\u957F\u65F6\uFF0C\u624D\u521B\u5EFA\u65B0\u7684 worker\u3002\n- \u521B\u5EFA\u6216\u6307\u6D3E worker \u540E\uFF0C\u9664\u975E\u7528\u6237\u660E\u786E\u8981\u6C42\u4F60\u5F53\u573A\u7EE7\u7EED\u8C03\u5EA6\uFF0C\u5426\u5219\u56DE\u590D\u7528\u6237\u5DF2\u5B89\u6392\u5E76\u7ED3\u675F\u5F53\u524D turn\uFF1B\u4E0D\u8981\u4E3B\u52A8\u8F6E\u8BE2 worker \u72B6\u6001\uFF0C\u795E\u5FF5\u4F1A\u5728 worker \u7EC8\u6001\u6216\u5065\u5EB7\u6458\u8981\u5230\u6765\u65F6\u91CD\u65B0\u5524\u9192\u4F60\u3002\n- sessions read \u8FD4\u56DE\u7684\u662F\u7ED9\u7BA1\u7406\u8005\u770B\u7684\u7B80\u6D01\u8FDB\u5C55\u3001\u5DE5\u5177\u6458\u8981\u548C\u6700\u7EC8\u7ED3\u679C\uFF0C\u4E0D\u662F\u539F\u59CB\u6D41\u5F0F token\uFF1B\u4E0D\u8981\u8981\u6C42\u8BFB\u53D6\u6216\u8F6C\u8FF0\u5B8C\u6574\u6D41\u5F0F\u65E5\u5FD7\u3002\n- \u53EA\u80FD\u7BA1\u7406\u4E0E\u4F60\u5904\u4E8E\u540C\u4E00\u53F0\u673A\u5668\u3001\u540C\u4E00\u9879\u76EE\u76EE\u5F55\u7684\u4F1A\u8BDD\uFF1B\u4E0D\u8981\u8DE8\u673A\u5668\u6216\u8DE8\u9879\u76EE\u8C03\u5EA6\u3002\n- \u4E0D\u8981\u65E0\u9650\u5FAA\u73AF\uFF1B\u6CA1\u6709\u660E\u786E\u4E0B\u4E00\u6B65\u65F6\u8BE2\u95EE\u7528\u6237\u6216\u7ED3\u675F\u5F53\u524D turn \u7B49\u5F85\u7CFB\u7EDF\u4E8B\u4EF6\u3002\n- \u4E0D\u8981\u81EA\u5DF1\u8BBE\u7F6E\u5B9A\u65F6\u5524\u9192\uFF1B\u795E\u5FF5\u4F1A\u5728\u7528\u6237\u6D88\u606F\u3001worker \u7EC8\u6001\u6216 worker \u957F\u8FD0\u884C\u5065\u5EB7\u6458\u8981\u5230\u6765\u65F6\u5524\u9192\u4F60\u3002\n- \u5916\u90E8\u6D88\u606F\u901A\u9053\u4E8B\u4EF6\u4F1A\u50CF\u666E\u901A\u7528\u6237\u6D88\u606F\u4E00\u6837\u9001\u8FBE\uFF0C\u683C\u5F0F\u4E3A\u201C\u5916\u90E8\u5BF9\u8BDD: <\u5BF9\u8BDD\u540D\u79F0>\u201D\u540E\u8DDF\u201C\u5BF9\u65B9: <\u5185\u5BB9\u6216\u9644\u4EF6\u94FE\u63A5>\u201D\uFF0C\u53EF\u80FD\u662F\u5408\u5E76\u6D88\u606F\uFF0C\u4E5F\u53EF\u80FD\u5305\u542B\u56FE\u7247\u3001\u89C6\u9891\u6216\u6587\u4EF6 URL\u3002\n- \u5916\u90E8\u6D88\u606F\u662F\u5426\u9700\u8981\u56DE\u590D\u3001\u8FFD\u95EE\u3001\u5FFD\u7565\u3001\u8F6C\u4EA4\u5185\u90E8\u8D1F\u8D23\u4EBA\uFF0C\u6216\u521B\u5EFA/\u6307\u6D3E worker\uFF0C\u7531\u4F60\u6839\u636E\u9879\u76EE\u4E0A\u4E0B\u6587\u663E\u5F0F\u5224\u65AD\u3002\n- \u5BF9\u5916\u4F60\u662F\u5F53\u524D\u9879\u76EE\u7684\u9879\u76EE\u7ECF\u7406\uFF0C\u4E0D\u8981\u81EA\u79F0\u795E\u5FF5\u3001Manager Agent \u6216 worker\uFF0C\u4E5F\u4E0D\u8981\u89E3\u91CA\u5185\u90E8\u8C03\u5EA6\u673A\u5236\uFF1B\u53EA\u5728\u9700\u8981\u65F6\u7528\u201C\u6211\u8FD9\u8FB9/\u6211\u4EEC\u8FD9\u8FB9\u201D\u6C9F\u901A\u3002\n- \u4E0D\u8981\u628A\u6240\u6709\u7EC6\u8282\u585E\u8FDB\u5BF9\u8BDD\u4E0A\u4E0B\u6587\uFF1B\u9700\u8981\u957F\u671F\u4FDD\u5B58\u7684\u4FE1\u606F\u5199\u5230\u9879\u76EE .shennian/ \u4E0B\u3002\n\n\u9700\u8981\u7BA1\u7406 worker \u6216\u5916\u90E8\u901A\u9053\u65F6\uFF0C\u4F7F\u7528\u672C\u5730\u547D\u4EE4\uFF1A\n- shennian manager sessions list --json\n- shennian manager sessions start --agent <codex|claude|workbuddy|cursor|opencode|pi-coding-agent|custom:name> --workdir <path> --
|
|
1
|
+
export declare const MANAGER_SYSTEM_PROMPT = "\u4F60\u662F\u9879\u76EE\u7ECF\u7406\uFF0C\u662F\u5F53\u524D\u9879\u76EE\u7684\u7BA1\u7406\u8005\u3002\n\n\u4F60\u7684\u804C\u8D23\uFF1A\n- \u7406\u89E3\u7528\u6237\u76EE\u6807\u3002\n- \u62C6\u89E3\u4EFB\u52A1\u3002\n- \u521B\u5EFA\u3001\u6307\u6D3E\u3001\u89C2\u5BDF\u548C\u505C\u6B62\u540C\u4E00\u9879\u76EE\u76EE\u5F55\u4E0B\u7684 worker Agent session\u3002\n- \u6C47\u603B worker \u7ED3\u679C\u3002\n- \u5224\u65AD\u662F\u5426\u9700\u8981\u7EE7\u7EED\u7B49\u5F85\u3001\u8C03\u6574\u5B89\u6392\u3001\u8BE2\u95EE\u7528\u6237\u6216\u9A8C\u6536\u3002\n- \u5728\u9879\u76EE .shennian/ \u76EE\u5F55\u4E0B\u7EF4\u62A4\u5FC5\u8981\u7684\u8BA1\u5212\u3001\u8BB0\u5F55\u548C\u9879\u76EE\u8BB0\u5FC6\u3002\n\n\u4F60\u7684\u8FB9\u754C\uFF1A\n- \u4E0D\u8981\u628A\u81EA\u5DF1\u5F53\u4F5C\u4E3B\u8981\u6267\u884C\u8005\u3002\n- \u4E0D\u8981\u76F4\u63A5\u7F16\u8F91\u4E1A\u52A1\u4EE3\u7801\uFF0C\u9664\u975E\u7528\u6237\u660E\u786E\u8981\u6C42\u4F60\u4EB2\u81EA\u6267\u884C\u3002\n- \u53EF\u4EE5\u8BFB\u53D6\u6587\u4EF6\u3001\u641C\u7D22\u9879\u76EE\u548C\u68C0\u67E5\u4E0A\u4E0B\u6587\uFF0C\u4EE5\u4FBF\u505A\u5224\u65AD\u3002\n- \u9700\u8981\u4FEE\u6539\u4EE3\u7801\u3001\u8FD0\u884C\u6D4B\u8BD5\u3001\u8C03\u7814\u65B9\u6848\u65F6\uFF0C\u4F18\u5148\u521B\u5EFA\u6216\u6307\u6D3E worker\u3002\n- \u6BCF\u6B21\u6536\u5230\u65B0\u4EFB\u52A1\u3001\u8865\u5145\u8981\u6C42\u3001\u7EA0\u504F\u6216\u5916\u90E8\u6D88\u606F\u65F6\uFF0C\u5148\u7528 sessions list \u67E5\u770B\u5F53\u524D\u540C\u9879\u76EE worker\uFF1B\u5982\u679C\u53EF\u80FD\u76F8\u5173\uFF0C\u518D\u7528 sessions read \u8BFB\u53D6\u5FC5\u8981\u6458\u8981\u540E\u5224\u65AD\u662F\u5426\u590D\u7528\u3002\n- \u5982\u679C\u5DF2\u6709 worker \u6B63\u5728\u5904\u7406\u540C\u4E00\u76EE\u6807\u3001\u540C\u4E00\u529F\u80FD\u533A\u3001\u540C\u4E00\u6587\u4EF6\u8303\u56F4\u6216\u540C\u4E00\u95EE\u9898\u94FE\u8DEF\uFF0C\u4F18\u5148\u7528 sessions send \u628A\u65B0\u8981\u6C42\u53D1\u7ED9\u8FD9\u4E2A worker\uFF1B\u5373\u4F7F worker \u6B63\u5FD9\u4E5F\u53EF\u4EE5\u53D1\u9001\uFF0C\u9ED8\u8BA4\u4F1A\u8FDB\u5165\u672C\u673A\u961F\u5217\uFF0C\u4E0D\u8981\u56E0\u4E3A\u5B83\u5FD9\u5C31\u65B0\u5EFA worker\u3002\n- \u53EA\u6709\u6CA1\u6709\u76F8\u5173 worker\u3001\u73B0\u6709 worker \u5DF2\u660E\u663E\u4E0D\u9002\u5408\u7EE7\u7EED\u63A8\u8FDB\u3001\u6216\u4EFB\u52A1\u9700\u8981\u5E76\u884C\u62C6\u5206\u7ED9\u4E0D\u540C\u4E13\u957F\u65F6\uFF0C\u624D\u521B\u5EFA\u65B0\u7684 worker\u3002\n- \u521B\u5EFA\u6216\u6307\u6D3E worker \u540E\uFF0C\u9664\u975E\u7528\u6237\u660E\u786E\u8981\u6C42\u4F60\u5F53\u573A\u7EE7\u7EED\u8C03\u5EA6\uFF0C\u5426\u5219\u56DE\u590D\u7528\u6237\u5DF2\u5B89\u6392\u5E76\u7ED3\u675F\u5F53\u524D turn\uFF1B\u4E0D\u8981\u4E3B\u52A8\u8F6E\u8BE2 worker \u72B6\u6001\uFF0C\u795E\u5FF5\u4F1A\u5728 worker \u7EC8\u6001\u6216\u5065\u5EB7\u6458\u8981\u5230\u6765\u65F6\u91CD\u65B0\u5524\u9192\u4F60\u3002\n- \u521B\u5EFA worker \u65F6\u5FC5\u987B\u63D0\u4F9B\u7B80\u77ED\u3001\u5177\u4F53\u3001\u53EF\u533A\u5206\u7684 --title\uFF0C\u540C\u65F6\u628A\u5B8C\u6574\u4EFB\u52A1\u653E\u8FDB --message\uFF1B\u4E0D\u8981\u628A\u6574\u6BB5\u4EFB\u52A1\u6216 Session ID \u5F53\u6807\u9898\u3002\n- sessions read \u8FD4\u56DE\u7684\u662F\u7ED9\u7BA1\u7406\u8005\u770B\u7684\u7B80\u6D01\u8FDB\u5C55\u3001\u5DE5\u5177\u6458\u8981\u548C\u6700\u7EC8\u7ED3\u679C\uFF0C\u4E0D\u662F\u539F\u59CB\u6D41\u5F0F token\uFF1B\u4E0D\u8981\u8981\u6C42\u8BFB\u53D6\u6216\u8F6C\u8FF0\u5B8C\u6574\u6D41\u5F0F\u65E5\u5FD7\u3002\n- \u53EA\u80FD\u7BA1\u7406\u4E0E\u4F60\u5904\u4E8E\u540C\u4E00\u53F0\u673A\u5668\u3001\u540C\u4E00\u9879\u76EE\u76EE\u5F55\u7684\u4F1A\u8BDD\uFF1B\u4E0D\u8981\u8DE8\u673A\u5668\u6216\u8DE8\u9879\u76EE\u8C03\u5EA6\u3002\n- \u4E0D\u8981\u65E0\u9650\u5FAA\u73AF\uFF1B\u6CA1\u6709\u660E\u786E\u4E0B\u4E00\u6B65\u65F6\u8BE2\u95EE\u7528\u6237\u6216\u7ED3\u675F\u5F53\u524D turn \u7B49\u5F85\u7CFB\u7EDF\u4E8B\u4EF6\u3002\n- \u4E0D\u8981\u81EA\u5DF1\u8BBE\u7F6E\u5B9A\u65F6\u5524\u9192\uFF1B\u795E\u5FF5\u4F1A\u5728\u7528\u6237\u6D88\u606F\u3001worker \u7EC8\u6001\u6216 worker \u957F\u8FD0\u884C\u5065\u5EB7\u6458\u8981\u5230\u6765\u65F6\u5524\u9192\u4F60\u3002\n- \u5916\u90E8\u6D88\u606F\u901A\u9053\u4E8B\u4EF6\u4F1A\u50CF\u666E\u901A\u7528\u6237\u6D88\u606F\u4E00\u6837\u9001\u8FBE\uFF0C\u683C\u5F0F\u4E3A\u201C\u5916\u90E8\u5BF9\u8BDD: <\u5BF9\u8BDD\u540D\u79F0>\u201D\u540E\u8DDF\u201C\u5BF9\u65B9: <\u5185\u5BB9\u6216\u9644\u4EF6\u94FE\u63A5>\u201D\uFF0C\u53EF\u80FD\u662F\u5408\u5E76\u6D88\u606F\uFF0C\u4E5F\u53EF\u80FD\u5305\u542B\u56FE\u7247\u3001\u89C6\u9891\u6216\u6587\u4EF6 URL\u3002\n- \u5916\u90E8\u6D88\u606F\u662F\u5426\u9700\u8981\u56DE\u590D\u3001\u8FFD\u95EE\u3001\u5FFD\u7565\u3001\u8F6C\u4EA4\u5185\u90E8\u8D1F\u8D23\u4EBA\uFF0C\u6216\u521B\u5EFA/\u6307\u6D3E worker\uFF0C\u7531\u4F60\u6839\u636E\u9879\u76EE\u4E0A\u4E0B\u6587\u663E\u5F0F\u5224\u65AD\u3002\n- \u5BF9\u5916\u4F60\u662F\u5F53\u524D\u9879\u76EE\u7684\u9879\u76EE\u7ECF\u7406\uFF0C\u4E0D\u8981\u81EA\u79F0\u795E\u5FF5\u3001Manager Agent \u6216 worker\uFF0C\u4E5F\u4E0D\u8981\u89E3\u91CA\u5185\u90E8\u8C03\u5EA6\u673A\u5236\uFF1B\u53EA\u5728\u9700\u8981\u65F6\u7528\u201C\u6211\u8FD9\u8FB9/\u6211\u4EEC\u8FD9\u8FB9\u201D\u6C9F\u901A\u3002\n- \u4E0D\u8981\u628A\u6240\u6709\u7EC6\u8282\u585E\u8FDB\u5BF9\u8BDD\u4E0A\u4E0B\u6587\uFF1B\u9700\u8981\u957F\u671F\u4FDD\u5B58\u7684\u4FE1\u606F\u5199\u5230\u9879\u76EE .shennian/ \u4E0B\u3002\n\n\u9700\u8981\u7BA1\u7406 worker \u6216\u5916\u90E8\u901A\u9053\u65F6\uFF0C\u4F7F\u7528\u672C\u5730\u547D\u4EE4\uFF1A\n- shennian manager sessions list --json\n- shennian manager sessions start --agent <codex|claude|workbuddy|cursor|opencode|pi-coding-agent|custom:name> --workdir <path> --title <\u77ED\u6807\u9898> --message <\u5B8C\u6574\u4EFB\u52A1>\n- shennian manager sessions send --session-id <id> --message <text>\n- shennian manager sessions queue list --session-id <id> --json\n- shennian manager sessions queue edit --session-id <id> --message-id <queueMessageId> --message <text>\n- shennian manager sessions queue delete --session-id <id> --message-id <queueMessageId>\n- shennian manager sessions stop --session-id <id>\uFF08\u7EC8\u6B62\u6B63\u5728\u8FD0\u884C\u7684 worker\uFF1B\u4E5F\u53EF\u7528 terminate/kill \u522B\u540D\uFF09\n- shennian manager sessions read --session-id <id> --limit 200 --json\n- shennian manager sessions wait --session-id <id> --timeout <1-600>\uFF08\u4EC5\u5916\u90E8\u539F\u751F\u5BBF\u4E3B\u9700\u8981\u6709\u754C\u7B49\u5F85\u65F6\u4F7F\u7528\u4E00\u6B21\uFF1B\u53D7\u7BA1 Manager \u4E0D\u4E3B\u52A8\u8C03\u7528\uFF09\n- shennian manager memory path\n\n\u53EF\u521B\u5EFA\u7684 worker Agent \u5305\u62EC Codex\u3001Claude Code\u3001WorkBuddy\u3001Cursor\u3001opencode\u3001Pi\uFF0C\u4EE5\u53CA\u672C\u673A custom agent\uFF08custom:<name>\uFF09\u3002sessions send \u59CB\u7EC8\u5148\u628A worker \u6D88\u606F\u4EA4\u7ED9\u672C\u673A durable queue\uFF1Aworker \u6B63\u5FD9\u65F6\u7B49\u5F85\uFF0C\u7A7A\u95F2\u65F6\u7ACB\u5373\u7531\u540C\u4E00\u8C03\u5EA6\u5668\u6267\u884C\u3002\u961F\u5217\u91CC\u7684\u672A\u6267\u884C\u6D88\u606F\u53EF\u4EE5 list/edit/delete\uFF1B\u5DF2\u7ECF\u5F00\u59CB\u6267\u884C\u7684\u6D88\u606F\u4E0D\u80FD\u7F16\u8F91\u6216\u5220\u9664\uFF0C\u53EA\u80FD stop \u540E\u91CD\u65B0\u53D1\u9001\u3002\n\n\u8FD9\u4E9B\u547D\u4EE4\u5DF2\u7ECF\u7531\u795E\u5FF5\u6CE8\u5165\u5F53\u524D Manager \u8EAB\u4EFD\u548C\u540C\u9879\u76EE\u6743\u9650\u8FB9\u754C\u3002\u4E0D\u8981\u5C1D\u8BD5\u4F2A\u9020 Manager session id\u3002";
|
|
2
2
|
export declare function buildManagerPrompt(userText: string): string;
|
|
@@ -17,6 +17,7 @@ const s=`\u4F60\u662F\u9879\u76EE\u7ECF\u7406\uFF0C\u662F\u5F53\u524D\u9879\u76E
|
|
|
17
17
|
- \u5982\u679C\u5DF2\u6709 worker \u6B63\u5728\u5904\u7406\u540C\u4E00\u76EE\u6807\u3001\u540C\u4E00\u529F\u80FD\u533A\u3001\u540C\u4E00\u6587\u4EF6\u8303\u56F4\u6216\u540C\u4E00\u95EE\u9898\u94FE\u8DEF\uFF0C\u4F18\u5148\u7528 sessions send \u628A\u65B0\u8981\u6C42\u53D1\u7ED9\u8FD9\u4E2A worker\uFF1B\u5373\u4F7F worker \u6B63\u5FD9\u4E5F\u53EF\u4EE5\u53D1\u9001\uFF0C\u9ED8\u8BA4\u4F1A\u8FDB\u5165\u672C\u673A\u961F\u5217\uFF0C\u4E0D\u8981\u56E0\u4E3A\u5B83\u5FD9\u5C31\u65B0\u5EFA worker\u3002
|
|
18
18
|
- \u53EA\u6709\u6CA1\u6709\u76F8\u5173 worker\u3001\u73B0\u6709 worker \u5DF2\u660E\u663E\u4E0D\u9002\u5408\u7EE7\u7EED\u63A8\u8FDB\u3001\u6216\u4EFB\u52A1\u9700\u8981\u5E76\u884C\u62C6\u5206\u7ED9\u4E0D\u540C\u4E13\u957F\u65F6\uFF0C\u624D\u521B\u5EFA\u65B0\u7684 worker\u3002
|
|
19
19
|
- \u521B\u5EFA\u6216\u6307\u6D3E worker \u540E\uFF0C\u9664\u975E\u7528\u6237\u660E\u786E\u8981\u6C42\u4F60\u5F53\u573A\u7EE7\u7EED\u8C03\u5EA6\uFF0C\u5426\u5219\u56DE\u590D\u7528\u6237\u5DF2\u5B89\u6392\u5E76\u7ED3\u675F\u5F53\u524D turn\uFF1B\u4E0D\u8981\u4E3B\u52A8\u8F6E\u8BE2 worker \u72B6\u6001\uFF0C\u795E\u5FF5\u4F1A\u5728 worker \u7EC8\u6001\u6216\u5065\u5EB7\u6458\u8981\u5230\u6765\u65F6\u91CD\u65B0\u5524\u9192\u4F60\u3002
|
|
20
|
+
- \u521B\u5EFA worker \u65F6\u5FC5\u987B\u63D0\u4F9B\u7B80\u77ED\u3001\u5177\u4F53\u3001\u53EF\u533A\u5206\u7684 --title\uFF0C\u540C\u65F6\u628A\u5B8C\u6574\u4EFB\u52A1\u653E\u8FDB --message\uFF1B\u4E0D\u8981\u628A\u6574\u6BB5\u4EFB\u52A1\u6216 Session ID \u5F53\u6807\u9898\u3002
|
|
20
21
|
- sessions read \u8FD4\u56DE\u7684\u662F\u7ED9\u7BA1\u7406\u8005\u770B\u7684\u7B80\u6D01\u8FDB\u5C55\u3001\u5DE5\u5177\u6458\u8981\u548C\u6700\u7EC8\u7ED3\u679C\uFF0C\u4E0D\u662F\u539F\u59CB\u6D41\u5F0F token\uFF1B\u4E0D\u8981\u8981\u6C42\u8BFB\u53D6\u6216\u8F6C\u8FF0\u5B8C\u6574\u6D41\u5F0F\u65E5\u5FD7\u3002
|
|
21
22
|
- \u53EA\u80FD\u7BA1\u7406\u4E0E\u4F60\u5904\u4E8E\u540C\u4E00\u53F0\u673A\u5668\u3001\u540C\u4E00\u9879\u76EE\u76EE\u5F55\u7684\u4F1A\u8BDD\uFF1B\u4E0D\u8981\u8DE8\u673A\u5668\u6216\u8DE8\u9879\u76EE\u8C03\u5EA6\u3002
|
|
22
23
|
- \u4E0D\u8981\u65E0\u9650\u5FAA\u73AF\uFF1B\u6CA1\u6709\u660E\u786E\u4E0B\u4E00\u6B65\u65F6\u8BE2\u95EE\u7528\u6237\u6216\u7ED3\u675F\u5F53\u524D turn \u7B49\u5F85\u7CFB\u7EDF\u4E8B\u4EF6\u3002
|
|
@@ -28,16 +29,16 @@ const s=`\u4F60\u662F\u9879\u76EE\u7ECF\u7406\uFF0C\u662F\u5F53\u524D\u9879\u76E
|
|
|
28
29
|
|
|
29
30
|
\u9700\u8981\u7BA1\u7406 worker \u6216\u5916\u90E8\u901A\u9053\u65F6\uFF0C\u4F7F\u7528\u672C\u5730\u547D\u4EE4\uFF1A
|
|
30
31
|
- shennian manager sessions list --json
|
|
31
|
-
- shennian manager sessions start --agent <codex|claude|workbuddy|cursor|opencode|pi-coding-agent|custom:name> --workdir <path> --message
|
|
32
|
+
- shennian manager sessions start --agent <codex|claude|workbuddy|cursor|opencode|pi-coding-agent|custom:name> --workdir <path> --title <\u77ED\u6807\u9898> --message <\u5B8C\u6574\u4EFB\u52A1>
|
|
32
33
|
- shennian manager sessions send --session-id <id> --message <text>
|
|
33
|
-
- shennian manager sessions send --session-id <id> --message <text> --direct
|
|
34
34
|
- shennian manager sessions queue list --session-id <id> --json
|
|
35
35
|
- shennian manager sessions queue edit --session-id <id> --message-id <queueMessageId> --message <text>
|
|
36
36
|
- shennian manager sessions queue delete --session-id <id> --message-id <queueMessageId>
|
|
37
37
|
- shennian manager sessions stop --session-id <id>\uFF08\u7EC8\u6B62\u6B63\u5728\u8FD0\u884C\u7684 worker\uFF1B\u4E5F\u53EF\u7528 terminate/kill \u522B\u540D\uFF09
|
|
38
38
|
- shennian manager sessions read --session-id <id> --limit 200 --json
|
|
39
|
+
- shennian manager sessions wait --session-id <id> --timeout <1-600>\uFF08\u4EC5\u5916\u90E8\u539F\u751F\u5BBF\u4E3B\u9700\u8981\u6709\u754C\u7B49\u5F85\u65F6\u4F7F\u7528\u4E00\u6B21\uFF1B\u53D7\u7BA1 Manager \u4E0D\u4E3B\u52A8\u8C03\u7528\uFF09
|
|
39
40
|
- shennian manager memory path
|
|
40
41
|
|
|
41
|
-
\u53EF\u521B\u5EFA\u7684 worker Agent \u5305\u62EC Codex\u3001Claude Code\u3001WorkBuddy\u3001Cursor\u3001opencode\u3001Pi\uFF0C\u4EE5\u53CA\u672C\u673A custom agent\uFF08custom:<name>\uFF09\
|
|
42
|
+
\u53EF\u521B\u5EFA\u7684 worker Agent \u5305\u62EC Codex\u3001Claude Code\u3001WorkBuddy\u3001Cursor\u3001opencode\u3001Pi\uFF0C\u4EE5\u53CA\u672C\u673A custom agent\uFF08custom:<name>\uFF09\u3002sessions send \u59CB\u7EC8\u5148\u628A worker \u6D88\u606F\u4EA4\u7ED9\u672C\u673A durable queue\uFF1Aworker \u6B63\u5FD9\u65F6\u7B49\u5F85\uFF0C\u7A7A\u95F2\u65F6\u7ACB\u5373\u7531\u540C\u4E00\u8C03\u5EA6\u5668\u6267\u884C\u3002\u961F\u5217\u91CC\u7684\u672A\u6267\u884C\u6D88\u606F\u53EF\u4EE5 list/edit/delete\uFF1B\u5DF2\u7ECF\u5F00\u59CB\u6267\u884C\u7684\u6D88\u606F\u4E0D\u80FD\u7F16\u8F91\u6216\u5220\u9664\uFF0C\u53EA\u80FD stop \u540E\u91CD\u65B0\u53D1\u9001\u3002
|
|
42
43
|
|
|
43
44
|
\u8FD9\u4E9B\u547D\u4EE4\u5DF2\u7ECF\u7531\u795E\u5FF5\u6CE8\u5165\u5F53\u524D Manager \u8EAB\u4EFD\u548C\u540C\u9879\u76EE\u6743\u9650\u8FB9\u754C\u3002\u4E0D\u8981\u5C1D\u8BD5\u4F2A\u9020 Manager session id\u3002`;function n(e){return e}export{s as MANAGER_SYSTEM_PROMPT,n as buildManagerPrompt};
|
|
@@ -37,10 +37,10 @@ export type ManagerRecord = {
|
|
|
37
37
|
/** This Manager Session originated from a managed Room and every synthetic
|
|
38
38
|
* continuation must reacquire that Room's current trusted context. */
|
|
39
39
|
managedRoomBound?: boolean;
|
|
40
|
+
controllerKind?: 'managed_session' | 'native_skill';
|
|
40
41
|
status: ManagerStatus;
|
|
41
|
-
/**
|
|
42
|
-
*
|
|
43
|
-
* failures instead of deleting work when a synthetic request is swallowed. */
|
|
42
|
+
/** Event ids currently being transferred. Queue durable ACK ends inbox
|
|
43
|
+
* ownership; Provider start is intentionally not a second acknowledgement. */
|
|
44
44
|
deliveringInboxEventIds?: string[];
|
|
45
45
|
managedWorkerSessionIds: string[];
|
|
46
46
|
attachedExternalChannels: string[];
|
|
@@ -89,6 +89,7 @@ export declare class ManagerRegistry {
|
|
|
89
89
|
defaultWorkerAgentType?: AgentType | null;
|
|
90
90
|
defaultWorkerModelId?: string | null;
|
|
91
91
|
managedRoomBound?: boolean;
|
|
92
|
+
controllerKind?: 'managed_session' | 'native_skill';
|
|
92
93
|
status?: ManagerStatus;
|
|
93
94
|
deliveringInboxEventIds?: string[];
|
|
94
95
|
}): ManagerRecord;
|
|
@@ -101,6 +102,7 @@ export declare class ManagerRegistry {
|
|
|
101
102
|
sessionId?: string;
|
|
102
103
|
agentType: AgentType;
|
|
103
104
|
workDir: string;
|
|
105
|
+
title?: string | null;
|
|
104
106
|
summary?: string | null;
|
|
105
107
|
}): ManagedWorkerRecord;
|
|
106
108
|
updateWorker(sessionId: string, patch: Partial<ManagedWorkerRecord>): ManagedWorkerRecord | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import u from"node:fs";import S from"node:path";import{randomUUID as m}from"node:crypto";import{isAgentHiddenPayload as v,sessionPreviewFromPayload as w}from"@shennian/wire";import{resolveShennianPath as A}from"../config/index.js";import{listSessionRecords as f,readMessages as T}from"../session/store.js";import{listProjectedSessions as M}from"../session/projection.js";const I=A("manager-registry.json");function g(){return new Date().toISOString()}function W(){return{managers:{},workers:{},replyTargets:{},inbox:{}}}class B{load(){try{const e=JSON.parse(u.readFileSync(I,"utf-8"));return{managers:e.managers??{},workers:e.workers??{},replyTargets:e.replyTargets??{},inbox:e.inbox??{}}}catch{return W()}}save(e){u.mkdirSync(S.dirname(I),{recursive:!0}),u.writeFileSync(I,JSON.stringify(e,null,2))}upsertManager(e){const t=this.load(),r=t.managers[e.sessionId],s=g(),a={sessionId:e.sessionId,agentSessionId:e.agentSessionId??r?.agentSessionId??null,workDir:e.workDir,machineId:e.machineId??r?.machineId??null,modelId:e.modelId,agentType:e.agentType??r?.agentType??"manager",providerModelId:e.providerModelId??r?.providerModelId??null,defaultWorkerAgentType:e.defaultWorkerAgentType??r?.defaultWorkerAgentType??null,defaultWorkerModelId:e.defaultWorkerModelId??r?.defaultWorkerModelId??null,managedRoomBound:e.managedRoomBound??r?.managedRoomBound??!1,status:e.status??r?.status??"idle",deliveringInboxEventIds:e.deliveringInboxEventIds??r?.deliveringInboxEventIds??[],managedWorkerSessionIds:r?.managedWorkerSessionIds??[],attachedExternalChannels:r?.attachedExternalChannels??[],createdAt:r?.createdAt??s,updatedAt:s};return t.managers[e.sessionId]=a,this.save(t),a}getManager(e){return this.load().managers[e]}enqueueInboxEvent(e){const t=this.load(),r=t.managers[e.managerSessionId],s=t.workers[e.workerSessionId];if(!r||!s||s.managedBy!==r.sessionId||s.workDir!==r.workDir)return null;const a=g(),o=t.inbox[e.managerSessionId]??[],d=o.findIndex(c=>c.workerSessionId===e.workerSessionId&&(e.kind==="worker.health"?c.kind==="worker.health":c.kind===e.kind&&c.runId===e.runId)),l=d>=0?{...o[d],...e,updatedAt:a}:{...e,id:`mie_${m()}`,createdAt:a,updatedAt:a};return d>=0?o[d]=l:o.push(l),t.inbox[e.managerSessionId]=o,this.save(t),l}listInboxEvents(e){return[...this.load().inbox[e]??[]].sort((t,r)=>t.createdAt.localeCompare(r.createdAt))}removeInboxEvents(e,t){if(!t.length)return;const r=this.load(),s=new Set(t);r.inbox[e]=(r.inbox[e]??[]).filter(a=>!s.has(a.id)),this.save(r)}addWorker(e){const t=this.load(),r=t.managers[e.managerSessionId];if(!r)throw new Error("Manager runtime is not registered");const s=e.sessionId??`sess_worker_${m()}`,a=g(),o={sessionId:s,agentType:e.agentType,workDir:e.workDir,managedBy:e.managerSessionId,status:"running",createdAt:a,updatedAt:a,lastActivityAt:a,summary:e.summary??null,agentSessionId:null,runId:null};return t.workers[s]=o,r.managedWorkerSessionIds.includes(s)||r.managedWorkerSessionIds.push(s),r.updatedAt=a,this.save(t),o}updateWorker(e,t){const r=this.load(),s=r.workers[e];if(!s)return;const a={...s,...t,updatedAt:g()};return r.workers[e]=a,this.save(r),a}listWorkers(e,t={}){const r=this.load(),s=r.managers[e];if(!s)return[];const a=Object.values(r.workers).filter(n=>n.workDir===s.workDir).filter(n=>t.includeManagers||n.agentType!=="manager").map(n=>this.decorateManagedWorker(n,t.runningSessionIds)),o=new Set(a.map(n=>n.sessionId)),d=f().filter(n=>n.workDir===s.workDir).filter(n=>t.includeManagers||n.agentType!=="manager").filter(n=>!o.has(n.sessionId)).map(n=>this.sessionRecordToWorker(n,t.runningSessionIds)),l=new Set([...a,...d].map(n=>n.sessionId)),
|
|
1
|
+
import u from"node:fs";import S from"node:path";import{randomUUID as m}from"node:crypto";import{isAgentHiddenPayload as v,sessionPreviewFromPayload as w}from"@shennian/wire";import{resolveShennianPath as A}from"../config/index.js";import{listSessionRecords as f,readMessages as T}from"../session/store.js";import{listProjectedSessions as M}from"../session/projection.js";const I=A("manager-registry.json");function g(){return new Date().toISOString()}function W(){return{managers:{},workers:{},replyTargets:{},inbox:{}}}class B{load(){try{const e=JSON.parse(u.readFileSync(I,"utf-8"));return{managers:e.managers??{},workers:e.workers??{},replyTargets:e.replyTargets??{},inbox:e.inbox??{}}}catch{return W()}}save(e){u.mkdirSync(S.dirname(I),{recursive:!0}),u.writeFileSync(I,JSON.stringify(e,null,2))}upsertManager(e){const t=this.load(),r=t.managers[e.sessionId],s=g(),a={sessionId:e.sessionId,agentSessionId:e.agentSessionId??r?.agentSessionId??null,workDir:e.workDir,machineId:e.machineId??r?.machineId??null,modelId:e.modelId,agentType:e.agentType??r?.agentType??"manager",providerModelId:e.providerModelId??r?.providerModelId??null,defaultWorkerAgentType:e.defaultWorkerAgentType??r?.defaultWorkerAgentType??null,defaultWorkerModelId:e.defaultWorkerModelId??r?.defaultWorkerModelId??null,managedRoomBound:e.managedRoomBound??r?.managedRoomBound??!1,controllerKind:e.controllerKind??r?.controllerKind??"managed_session",status:e.status??r?.status??"idle",deliveringInboxEventIds:e.deliveringInboxEventIds??r?.deliveringInboxEventIds??[],managedWorkerSessionIds:r?.managedWorkerSessionIds??[],attachedExternalChannels:r?.attachedExternalChannels??[],createdAt:r?.createdAt??s,updatedAt:s};return t.managers[e.sessionId]=a,this.save(t),a}getManager(e){return this.load().managers[e]}enqueueInboxEvent(e){const t=this.load(),r=t.managers[e.managerSessionId],s=t.workers[e.workerSessionId];if(!r||!s||s.managedBy!==r.sessionId||s.workDir!==r.workDir)return null;const a=g(),o=t.inbox[e.managerSessionId]??[],d=o.findIndex(c=>c.workerSessionId===e.workerSessionId&&(e.kind==="worker.health"?c.kind==="worker.health":c.kind===e.kind&&c.runId===e.runId)),l=d>=0?{...o[d],...e,updatedAt:a}:{...e,id:`mie_${m()}`,createdAt:a,updatedAt:a};return d>=0?o[d]=l:o.push(l),t.inbox[e.managerSessionId]=o,this.save(t),l}listInboxEvents(e){return[...this.load().inbox[e]??[]].sort((t,r)=>t.createdAt.localeCompare(r.createdAt))}removeInboxEvents(e,t){if(!t.length)return;const r=this.load(),s=new Set(t);r.inbox[e]=(r.inbox[e]??[]).filter(a=>!s.has(a.id)),this.save(r)}addWorker(e){const t=this.load(),r=t.managers[e.managerSessionId];if(!r)throw new Error("Manager runtime is not registered");const s=e.sessionId??`sess_worker_${m()}`,a=g(),o={sessionId:s,agentType:e.agentType,workDir:e.workDir,managedBy:e.managerSessionId,status:"running",createdAt:a,updatedAt:a,lastActivityAt:a,title:e.title??null,summary:e.summary??null,agentSessionId:null,runId:null};return t.workers[s]=o,r.managedWorkerSessionIds.includes(s)||r.managedWorkerSessionIds.push(s),r.updatedAt=a,this.save(t),o}updateWorker(e,t){const r=this.load(),s=r.workers[e];if(!s)return;const a={...s,...t,updatedAt:g()};return r.workers[e]=a,this.save(r),a}listWorkers(e,t={}){const r=this.load(),s=r.managers[e];if(!s)return[];const a=Object.values(r.workers).filter(n=>n.workDir===s.workDir).filter(n=>t.includeManagers||n.agentType!=="manager").map(n=>this.decorateManagedWorker(n,t.runningSessionIds)),o=new Set(a.map(n=>n.sessionId)),d=f().filter(n=>n.workDir===s.workDir).filter(n=>t.includeManagers||n.agentType!=="manager").filter(n=>!o.has(n.sessionId)).map(n=>this.sessionRecordToWorker(n,t.runningSessionIds)),l=new Set([...a,...d].map(n=>n.sessionId)),p=(t.projectedSessions??M()).filter(n=>n.workDir===s.workDir).filter(n=>t.includeManagers||n.agentType!=="manager").filter(n=>!l.has(n.id)).map(n=>this.projectedSessionToWorker(n,t.runningSessionIds));return[...a,...d,...p].sort((n,k)=>k.lastActivityAt.localeCompare(n.lastActivityAt))}getWorkerForManager(e,t){const r=this.load(),s=r.managers[e],a=r.workers[t];if(!s)return;if(a)return a.workDir!==s.workDir||a.agentType==="manager"?void 0:this.decorateManagedWorker(a);const o=f().find(d=>d.sessionId===t);if(!(!o||o.workDir!==s.workDir||o.agentType==="manager"))return this.sessionRecordToWorker(o)}decorateManagedWorker(e,t){const r=t?.has(e.sessionId)?"running":e.status,s=this.readTranscriptSummary(e.sessionId,e.summary??null),a=s.lastMessagePreview??e.lastMessagePreview??e.summary??null,o=e.userGoal??s.userGoal??null;return{...e,managedBy:e.managedBy??null,status:r,title:e.title??o??a??e.summary??e.sessionId,userGoal:o,lastMessagePreview:a,summary:e.summary??a,canResume:e.canResume??e.status!=="aborted",source:e.source??"manager_registry",role:"managed_worker"}}sessionRecordToWorker(e,t){const r=this.readTranscriptSummary(e.sessionId,e.lastMessagePreview??null),s=r.lastMessagePreview??e.lastMessagePreview??null,a=r.userGoal,o=t?.has(e.sessionId)?"running":e.status==="failed"?"error":e.status==="completed"?"final":"idle";return{sessionId:e.sessionId,agentType:e.agentType,workDir:e.workDir,managedBy:null,status:o,createdAt:e.createdAt,updatedAt:e.updatedAt,lastActivityAt:e.lastActivityAt,title:a??s??e.sessionId,userGoal:a,lastMessagePreview:s,summary:s??a??null,agentSessionId:e.agentSessionId??null,runId:null,canResume:!!e.agentSessionId,source:"local_index",role:"project_session"}}projectedSessionToWorker(e,t){const r=e.lastMessagePreview??null,s=e.title?.trim()||r,a=t?.has(e.id)?"running":e.status==="failed"?"error":e.status==="completed"?"final":"idle";return{sessionId:e.id,agentType:e.agentType,workDir:e.workDir,managedBy:null,status:a,createdAt:e.createdAt,updatedAt:e.updatedAt,lastActivityAt:e.lastActivityAt||e.updatedAt,title:s??e.id,userGoal:s??null,lastMessagePreview:r,summary:r??s??null,agentSessionId:e.agentSessionId??null,runId:e.activity?.runId??null,canResume:!0,source:"app_projection",role:"project_session"}}readTranscriptSummary(e,t){const r=T(e,{limit:200});if(!r.length)return{userGoal:null,lastMessagePreview:t};const s=[...r].sort((d,l)=>d.ts-l.ts),a=s.find(d=>d.role==="user"),o=[...s].reverse().find(d=>y(d));return{userGoal:a?h(y(a),160):null,lastMessagePreview:h(y(o),180)??t}}createReplyTarget(e){const t=this.load(),r={replyTarget:`rt_${m()}`,managerSessionId:e.managerSessionId,channelId:e.channelId,conversationId:e.conversationId,messageId:e.messageId??null,createdAt:g()};return t.replyTargets[r.replyTarget]=r,this.save(t),r}getReplyTarget(e){return this.load().replyTargets[e]}getLatestReplyTargetForManager(e){return Object.values(this.load().replyTargets).filter(t=>t.managerSessionId===e).sort((t,r)=>r.createdAt.localeCompare(t.createdAt))[0]}}function y(i){return!i||v(i.payload)?null:w(i.payload,180)}function h(i,e){return i?i.length>e?`${i.slice(0,e)}...`:i:null}export{B as ManagerRegistry};
|
|
@@ -2,9 +2,12 @@ import type { AgentEvent, AgentAdapter } from '../agents/adapter.js';
|
|
|
2
2
|
import { type AgentType, type ExternalChannelSessionStatus, type ReqFrame } from '@shennian/wire';
|
|
3
3
|
import { ManagerRegistry } from './registry.js';
|
|
4
4
|
import type { SessionManagerRuntime } from '../session/types.js';
|
|
5
|
-
import { RetiredChannelRuntime as ChannelRuntime, type ChannelRuntimeOptions, type WeChatAutomationLane
|
|
5
|
+
import { RetiredChannelRuntime as ChannelRuntime, type ChannelRuntimeOptions, type WeChatAutomationLane } from './retired-external-channel-compat.js';
|
|
6
6
|
import type { CompiledManagedAgentPolicy } from '../security/managed-agent-policy.js';
|
|
7
|
-
export type
|
|
7
|
+
export type LocalReqDispatchResult = {
|
|
8
|
+
durableQueueHandoff?: boolean;
|
|
9
|
+
};
|
|
10
|
+
export type LocalReqDispatcher = (req: ReqFrame) => Promise<void | LocalReqDispatchResult>;
|
|
8
11
|
type ManagerRuntimeServiceOptions = {
|
|
9
12
|
getRuntime: () => SessionManagerRuntime;
|
|
10
13
|
dispatchReq: LocalReqDispatcher;
|
|
@@ -19,20 +22,13 @@ export declare class ManagerRuntimeService {
|
|
|
19
22
|
private readonly managedPolicies;
|
|
20
23
|
readonly registry: ManagerRegistry;
|
|
21
24
|
readonly channelRuntime: ChannelRuntime;
|
|
22
|
-
private readonly weChatRpaSessionSync;
|
|
23
25
|
private server;
|
|
24
26
|
private ipcUrl;
|
|
25
27
|
private ipcToken;
|
|
26
28
|
private healthTimer;
|
|
27
29
|
private startPromise;
|
|
28
30
|
private workerTextAcc;
|
|
29
|
-
private readonly weChatAutomationLane;
|
|
30
31
|
constructor(opts: ManagerRuntimeServiceOptions);
|
|
31
|
-
private listWeChatRpaSessionContexts;
|
|
32
|
-
private listAuthoritativeWeChatRpaSessionContexts;
|
|
33
|
-
private listLocalWeChatRpaSessionContexts;
|
|
34
|
-
notifyWeChatRpaSessionBinding(session: WeChatRpaSessionContext): Promise<void>;
|
|
35
|
-
reconcileWeChatRpaSessionBindings(): Promise<void>;
|
|
36
32
|
start(): Promise<void>;
|
|
37
33
|
private doStart;
|
|
38
34
|
ready(): Promise<void>;
|
|
@@ -50,10 +46,12 @@ export declare class ManagerRuntimeService {
|
|
|
50
46
|
defaultWorkerAgentType?: AgentType | null;
|
|
51
47
|
defaultWorkerModelId?: string | null;
|
|
52
48
|
managedRoomBound?: boolean;
|
|
49
|
+
controllerKind?: 'managed_session' | 'native_skill';
|
|
53
50
|
status?: 'idle' | 'running' | 'interrupting';
|
|
54
51
|
}): void;
|
|
55
52
|
setManagedAgentPolicy(sessionId: string, policy: CompiledManagedAgentPolicy | null): void;
|
|
56
53
|
getManagedAgentPolicyForWorker(managerSessionId: string, workDir: string): CompiledManagedAgentPolicy | null;
|
|
54
|
+
isNativeSkillManager(managerSessionId: string, workDir: string): boolean;
|
|
57
55
|
setManagerWorkerDefaults(sessionId: string, agentType?: AgentType | null, modelId?: string | null): void;
|
|
58
56
|
getManagerWorkerDefaults(sessionId: string): {
|
|
59
57
|
agentType: AgentType | null;
|
|
@@ -63,16 +61,10 @@ export declare class ManagerRuntimeService {
|
|
|
63
61
|
noteAgentEvent(sessionId: string, event: AgentEvent): void;
|
|
64
62
|
private findWorker;
|
|
65
63
|
handleAppReq(req: ReqFrame): Promise<void>;
|
|
66
|
-
private broadcastConfiguredChannelStatuses;
|
|
67
|
-
private broadcastManagerChannelStatus;
|
|
68
64
|
private handleIpc;
|
|
69
|
-
private dispatchChatSend;
|
|
70
65
|
private dispatchChatEnqueue;
|
|
71
|
-
private
|
|
72
|
-
private sendManagedWeComReply;
|
|
66
|
+
private appendManagerVisibleMarkdown;
|
|
73
67
|
private enqueueWorkerEvent;
|
|
74
|
-
private handleExternalMessage;
|
|
75
|
-
private dispatchExternalMessage;
|
|
76
68
|
private scanWorkerHealth;
|
|
77
69
|
private interruptAndResumeManager;
|
|
78
70
|
bindManagerAdapterEvents(sessionId: string, adapter: AgentAdapter): void;
|