shennian 0.5.20 → 0.5.22

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.
@@ -46,8 +46,8 @@
46
46
  },
47
47
  {
48
48
  "file": "src/agent-env.js",
49
- "beforeBytes": 11128,
50
- "afterBytes": 4946
49
+ "beforeBytes": 11186,
50
+ "afterBytes": 4975
51
51
  },
52
52
  {
53
53
  "file": "src/agents/acp/adapter.js",
@@ -466,8 +466,8 @@
466
466
  },
467
467
  {
468
468
  "file": "src/commands/daemon-state.js",
469
- "beforeBytes": 10219,
470
- "afterBytes": 4981
469
+ "beforeBytes": 10460,
470
+ "afterBytes": 5023
471
471
  },
472
472
  {
473
473
  "file": "src/commands/daemon-stop-ipc.js",
@@ -481,8 +481,8 @@
481
481
  },
482
482
  {
483
483
  "file": "src/commands/daemon.js",
484
- "beforeBytes": 38777,
485
- "afterBytes": 19473
484
+ "beforeBytes": 38859,
485
+ "afterBytes": 19483
486
486
  },
487
487
  {
488
488
  "file": "src/commands/integration.js",
@@ -666,8 +666,8 @@
666
666
  },
667
667
  {
668
668
  "file": "src/index.js",
669
- "beforeBytes": 46996,
670
- "afterBytes": 23133
669
+ "beforeBytes": 47391,
670
+ "afterBytes": 23200
671
671
  },
672
672
  {
673
673
  "file": "src/log-redaction.js",
@@ -861,8 +861,8 @@
861
861
  },
862
862
  {
863
863
  "file": "src/room/activation-service.js",
864
- "beforeBytes": 28830,
865
- "afterBytes": 15852
864
+ "beforeBytes": 29557,
865
+ "afterBytes": 16983
866
866
  },
867
867
  {
868
868
  "file": "src/room/attachment-cache.js",
@@ -981,8 +981,8 @@
981
981
  },
982
982
  {
983
983
  "file": "src/schedules/personal-context.js",
984
- "beforeBytes": 901,
985
- "afterBytes": 501
984
+ "beforeBytes": 1776,
985
+ "afterBytes": 1787
986
986
  },
987
987
  {
988
988
  "file": "src/schedules/server-client.js",
@@ -1226,8 +1226,8 @@
1226
1226
  },
1227
1227
  {
1228
1228
  "file": "src/session/queue-helpers.js",
1229
- "beforeBytes": 9503,
1230
- "afterBytes": 4628
1229
+ "beforeBytes": 9648,
1230
+ "afterBytes": 4739
1231
1231
  },
1232
1232
  {
1233
1233
  "file": "src/session/queue-message.js",
@@ -1251,8 +1251,8 @@
1251
1251
  },
1252
1252
  {
1253
1253
  "file": "src/session/queue.js",
1254
- "beforeBytes": 43664,
1255
- "afterBytes": 19298
1254
+ "beforeBytes": 43859,
1255
+ "afterBytes": 19352
1256
1256
  },
1257
1257
  {
1258
1258
  "file": "src/session/queued-chat-dispatch.js",
@@ -1331,8 +1331,8 @@
1331
1331
  },
1332
1332
  {
1333
1333
  "file": "src/steward/session.js",
1334
- "beforeBytes": 2984,
1335
- "afterBytes": 2185
1334
+ "beforeBytes": 3215,
1335
+ "afterBytes": 2333
1336
1336
  },
1337
1337
  {
1338
1338
  "file": "src/steward/templates.js",
@@ -1,8 +1,8 @@
1
- import T from"node:os";import c from"node:path";import{spawnSync as p}from"node:child_process";import{buildAugmentedPath as R}from"./env-path.js";import{buildWindowsSystemEnv as a,resolveWindowsPowerShellPath as g}from"./windows-shell.js";const _="__SHENNIAN_AGENT_ENV_START__",d="__SHENNIAN_AGENT_ENV_END__",S=["HOME","USER","LOGNAME","LANG","LANGUAGE","LC_ALL","LC_CTYPE","TMPDIR","TMP","TEMP","TZ"],m=["SystemRoot","WINDIR","ComSpec","PATHEXT","USERPROFILE","APPDATA","LOCALAPPDATA","ProgramData","ProgramFiles","ProgramFiles(x86)","TEMP","TMP","TZ"],P=["NO_COLOR","PI_CODING_AGENT_DIR"],f=["SHENNIAN_MANAGED_ROOM_CONTEXT","SHENNIAN_MANAGED_ROOM_IPC_ROOT"],I=["SHENNIAN_MANAGER_SESSION_ID","SHENNIAN_MANAGER_AGENT_SESSION_ID","SHENNIAN_MANAGER_WORKDIR","SHENNIAN_MANAGER_MODEL","SHENNIAN_MANAGER_IPC_URL","SHENNIAN_MANAGER_IPC_TOKEN"],h={codex:["OPENAI_BASE_URL","OPENAI_API_KEY"],claude:["ANTHROPIC_BASE_URL","ANTHROPIC_API_KEY"],pi:["DASHSCOPE_BASE_URL","DASHSCOPE_API_KEY"]};function D(e){return h[e]??[]}function G(e){return e==="codex"||e==="claude"||e==="pi-coding-agent"?[...f,...I]:f}function $(e=process.platform){return["PATH",...e==="win32"?m:S,...P]}function A(e){return`'${e.replace(/'/g,"'\\''")}'`}function v(e){const n=e.indexOf(_),o=e.indexOf(d,n+_.length);if(n===-1||o===-1)return null;const t=e.slice(n+_.length,o);try{const s=JSON.parse(t),i={};for(const[E,r]of Object.entries(s))typeof r=="string"&&(i[E]=r);return i}catch{return null}}function w(){const e=process.env.SHELL?.trim()||"/bin/sh",n=[`printf ${A(_)}`,`${A(process.execPath)} -e ${A("process.stdout.write(JSON.stringify(process.env))")}`,`printf ${A(d)}`].join("; ");for(const o of[["-ilc",n],["-lc",n]]){const t=p(e,o,{env:process.env,encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:1500,windowsHide:!0}),s=typeof t.stdout=="string"?v(t.stdout):null;if(s)return s}return null}function M(){const e=`
1
+ import T from"node:os";import c from"node:path";import{spawnSync as S}from"node:child_process";import{buildAugmentedPath as R}from"./env-path.js";import{buildWindowsSystemEnv as a,resolveWindowsPowerShellPath as g}from"./windows-shell.js";const _="__SHENNIAN_AGENT_ENV_START__",d="__SHENNIAN_AGENT_ENV_END__",p=["HOME","USER","LOGNAME","LANG","LANGUAGE","LC_ALL","LC_CTYPE","TMPDIR","TMP","TEMP","TZ"],m=["SystemRoot","WINDIR","ComSpec","PATHEXT","USERPROFILE","APPDATA","LOCALAPPDATA","ProgramData","ProgramFiles","ProgramFiles(x86)","TEMP","TMP","TZ"],P=["NO_COLOR","PI_CODING_AGENT_DIR"],f=["SHENNIAN_MANAGED_ROOM_CONTEXT","SHENNIAN_MANAGED_ROOM_IPC_ROOT"],I=["SHENNIAN_MANAGER_SESSION_ID","SHENNIAN_MANAGER_AGENT_SESSION_ID","SHENNIAN_MANAGER_WORKDIR","SHENNIAN_MANAGER_MODEL","SHENNIAN_MANAGER_IPC_URL","SHENNIAN_MANAGER_IPC_TOKEN"],h={codex:["OPENAI_BASE_URL","OPENAI_API_KEY"],claude:["ANTHROPIC_BASE_URL","ANTHROPIC_API_KEY"],pi:["DASHSCOPE_BASE_URL","DASHSCOPE_API_KEY"]};function D(e){return h[e]??[]}function G(e){return e==="codex"||e==="claude"||e==="pi-coding-agent"?[...f,...I]:f}function U(e=process.platform){return["PATH",...e==="win32"?m:p,...P]}function A(e){return`'${e.replace(/'/g,"'\\''")}'`}function O(e){const n=e.indexOf(_),o=e.indexOf(d,n+_.length);if(n===-1||o===-1)return null;const t=e.slice(n+_.length,o);try{const s=JSON.parse(t),i={};for(const[E,r]of Object.entries(s))typeof r=="string"&&(i[E]=r);return i}catch{return null}}function w(){const e=process.env.SHELL?.trim()||"/bin/sh",n=[`printf ${A(_)}`,`${A(process.execPath)} -e ${A("process.stdout.write(JSON.stringify(process.env))")}`,`printf ${A(d)}`].join("; ");for(const o of[["-ilc",n],["-lc",n]]){const t=S(e,o,{env:process.env,encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:1500,windowsHide:!0}),s=typeof t.stdout=="string"?O(t.stdout):null;if(s)return s}return null}function M(){const e=`
2
2
  $envs = @{}
3
3
  [Environment]::GetEnvironmentVariables('Machine').GetEnumerator() | ForEach-Object { $envs[$_.Key] = [string]$_.Value }
4
4
  [Environment]::GetEnvironmentVariables('User').GetEnumerator() | ForEach-Object { $envs[$_.Key] = [string]$_.Value }
5
5
  Write-Output '${_}'
6
6
  $envs | ConvertTo-Json -Compress
7
7
  Write-Output '${d}'
8
- `,n=p(g(),["-NoProfile","-Command",e],{env:{...process.env,...a(process.env)},encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:1500,windowsHide:!0});return typeof n.stdout=="string"?v(n.stdout):null}function C(){return(T.platform()==="win32"?M():w())??{}}function H(e){const n={...e.daemonEnv,...e.userEnv,...e.extra};return process.platform==="win32"&&Object.assign(n,a(n)),n.PATH=b(e.daemonEnv,e.userEnv,e.extra,n),delete n.Path,delete n.path,n}function y(e={}){const n=H({daemonEnv:process.env,userEnv:C(),extra:e});return delete n.SHENNIAN_SCHEDULE_CONTEXT,O(n),n}function U(e={}){const n=y(e),o=new Set([...f,...I]);for(const t of Object.keys(n))t.startsWith("SHENNIAN_")&&!o.has(t)&&delete n[t];return n}function Y(e){const n=e.daemonEnv??process.env,o=e.platform??process.platform,t={};return l(t,n,o==="win32"?m:S,o),l(t,e.providerEnv,D(e.agentType),o),l(t,e.sessionEnv,G(e.agentType),o),l(t,e.runtimeEnv,P,o),o==="win32"&&Object.assign(t,a({...n,...t})),t.PATH=L(n,t,o),O(t),delete t.Path,delete t.path,t}function O(e){delete e.ELECTRON_RUN_AS_NODE,delete e.ELECTRON_NO_ASAR,delete e.SHENNIAN_DESKTOP_CLI_SCRIPT,delete e.SHENNIAN_DESKTOP_CLI_BRIDGE,delete e.SHENNIAN_DESKTOP_CLI_COMMAND}function l(e,n,o,t){if(!n)return;const s=Object.entries(n);for(const i of o){const r=(t==="win32"?s.find(([N])=>N.toUpperCase()===i.toUpperCase()):s.find(([N])=>N===i))?.[1];typeof r=="string"&&r.length>0&&(e[i]=r)}}function L(e,n,o){const t=o==="win32"?c.win32.delimiter:c.posix.delimiter,s=[],i=(E,r=!1)=>{if(E)for(const N of E.split(t))!N||s.includes(N)||(r?s.unshift(N):s.push(N))};if(i(u(e)),i(c.dirname(process.execPath),!0),o==="win32"){const E=a({...e,...n}),r=E.SystemRoot??E.WINDIR??"C:\\Windows";i(c.win32.join(r,"System32")),i(c.win32.join(r,"System32","WindowsPowerShell","v1.0")),i(r)}else i("/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin");return s.join(t)}function u(e){return e?.PATH??e?.Path??e?.path}function b(e,n,o,t){const s=[];for(const E of[u(e),u(n),u(o)])for(const r of(E??"").split(c.delimiter))r&&!s.includes(r)&&s.push(r);if(process.platform==="win32"){const E=t.SystemRoot||t.WINDIR||process.env.SystemRoot||process.env.WINDIR||"C:\\Windows";for(const r of[c.win32.join(E,"System32"),c.win32.join(E,"System32","WindowsPowerShell","v1.0"),c.win32.join(E)])r&&!s.includes(r)&&s.push(r)}const i=c.dirname(process.execPath);return i&&!s.includes(i)&&s.unshift(i),R({pathValue:s.join(c.delimiter),env:t})}export{f as MANAGED_AGENT_SESSION_ENV_KEYS,y as buildAgentProcessEnv,Y as buildManagedAgentProcessEnv,U as buildManagedNativeFullProcessEnv,$ as getManagedAgentBaseEnvKeys,D as getManagedAgentProviderEnvKeys,G as getManagedAgentSessionEnvKeys,H as mergeAgentProcessEnv,C as readLatestUserEnv};
8
+ `,n=S(g(),["-NoProfile","-Command",e],{env:{...process.env,...a(process.env)},encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:1500,windowsHide:!0});return typeof n.stdout=="string"?O(n.stdout):null}function C(){return(T.platform()==="win32"?M():w())??{}}function H(e){const n={...e.daemonEnv,...e.userEnv,...e.extra};return process.platform==="win32"&&Object.assign(n,a(n)),n.PATH=b(e.daemonEnv,e.userEnv,e.extra,n),delete n.Path,delete n.path,n}function L(e={}){const n=H({daemonEnv:process.env,userEnv:C(),extra:e});return e.SHENNIAN_SCHEDULE_CONTEXT||delete n.SHENNIAN_SCHEDULE_CONTEXT,v(n),n}function $(e={}){const n=L(e),o=new Set([...f,...I]);for(const t of Object.keys(n))t.startsWith("SHENNIAN_")&&!o.has(t)&&delete n[t];return n}function Y(e){const n=e.daemonEnv??process.env,o=e.platform??process.platform,t={};return l(t,n,o==="win32"?m:p,o),l(t,e.providerEnv,D(e.agentType),o),l(t,e.sessionEnv,G(e.agentType),o),l(t,e.runtimeEnv,P,o),o==="win32"&&Object.assign(t,a({...n,...t})),t.PATH=y(n,t,o),v(t),delete t.Path,delete t.path,t}function v(e){delete e.ELECTRON_RUN_AS_NODE,delete e.ELECTRON_NO_ASAR,delete e.SHENNIAN_DESKTOP_CLI_SCRIPT,delete e.SHENNIAN_DESKTOP_CLI_BRIDGE,delete e.SHENNIAN_DESKTOP_CLI_COMMAND}function l(e,n,o,t){if(!n)return;const s=Object.entries(n);for(const i of o){const r=(t==="win32"?s.find(([N])=>N.toUpperCase()===i.toUpperCase()):s.find(([N])=>N===i))?.[1];typeof r=="string"&&r.length>0&&(e[i]=r)}}function y(e,n,o){const t=o==="win32"?c.win32.delimiter:c.posix.delimiter,s=[],i=(E,r=!1)=>{if(E)for(const N of E.split(t))!N||s.includes(N)||(r?s.unshift(N):s.push(N))};if(i(u(e)),i(c.dirname(process.execPath),!0),o==="win32"){const E=a({...e,...n}),r=E.SystemRoot??E.WINDIR??"C:\\Windows";i(c.win32.join(r,"System32")),i(c.win32.join(r,"System32","WindowsPowerShell","v1.0")),i(r)}else i("/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin");return s.join(t)}function u(e){return e?.PATH??e?.Path??e?.path}function b(e,n,o,t){const s=[];for(const E of[u(e),u(n),u(o)])for(const r of(E??"").split(c.delimiter))r&&!s.includes(r)&&s.push(r);if(process.platform==="win32"){const E=t.SystemRoot||t.WINDIR||process.env.SystemRoot||process.env.WINDIR||"C:\\Windows";for(const r of[c.win32.join(E,"System32"),c.win32.join(E,"System32","WindowsPowerShell","v1.0"),c.win32.join(E)])r&&!s.includes(r)&&s.push(r)}const i=c.dirname(process.execPath);return i&&!s.includes(i)&&s.unshift(i),R({pathValue:s.join(c.delimiter),env:t})}export{f as MANAGED_AGENT_SESSION_ENV_KEYS,L as buildAgentProcessEnv,Y as buildManagedAgentProcessEnv,$ as buildManagedNativeFullProcessEnv,U as getManagedAgentBaseEnvKeys,D as getManagedAgentProviderEnvKeys,G as getManagedAgentSessionEnvKeys,H as mergeAgentProcessEnv,C as readLatestUserEnv};
@@ -1 +1 @@
1
- import i from"node:fs";import c from"node:path";import f from"node:os";import{execSync as g}from"node:child_process";import{randomUUID as A}from"node:crypto";import{getShennianDir as b,loadConfig as O,resolveShennianPath as p}from"../config/index.js";import{findRunningWindowsDaemonProcessIds as P,inferDaemonLauncherFromCommand as w,isDaemonProcessRunning as k,isShennianRunServiceCommand as F,readWindowsProcessCommand as L}from"./daemon-process.js";const u=b(),l=p("daemon.pid"),R=p("daemon.log"),D=p("remote-access.disabled"),m=p("daemon-launcher.json");function h(){const e=f.platform();return e==="darwin"||e==="linux"||e==="win32"?e:"linux"}function _(e){const n=e.trim();if(!n)return null;if(n.startsWith("{"))try{const t=JSON.parse(n),o=Number(t.pid);return!Number.isInteger(o)||o<=0?null:{pid:o,...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 N(){try{return _(i.readFileSync(l,"utf-8"))}catch{return null}}function S(e){return k(e)}function z(e,n=3e3){const r=Date.now();for(;Date.now()-r<n;){if(!S(e))return!0;Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,100)}return!S(e)}function H(){try{return i.lstatSync(D),!0}catch(e){return!(e&&typeof e=="object"&&"code"in e&&e.code==="ENOENT")}}function K(){try{i.unlinkSync(D)}catch(e){if(e&&typeof e=="object"&&"code"in e&&e.code==="ENOENT")return;throw e}}function v(){return"global-cli"}function C(){return`${process.pid}-${Date.now()}-${A()}`}function T(e,n,r={}){i.mkdirSync(u,{recursive:!0}),i.writeFileSync(l,JSON.stringify({pid:e,instanceId:n,...r.version?{version:r.version}:{},launcher:r.launcher??v(),...r.adopted?{adopted:!0}:{},startedAt:new Date().toISOString()},null,2))}function Q(e,n){const r=N();if(!(r?.pid!==e||r.instanceId!==n))try{i.unlinkSync(l)}catch{}}function x(e,n=v(),r){i.mkdirSync(u,{recursive:!0}),i.writeFileSync(m,JSON.stringify({pid:e,launcher:n,...r?{instanceId:r}:{},updatedAt:new Date().toISOString()},null,2))}function X(e){if(e)try{if(JSON.parse(i.readFileSync(m,"utf-8")).instanceId!==e)return}catch{return}try{i.unlinkSync(m)}catch{}}function Y(e){e&&x(e)}function U(e,n){if(!e||!n)return"unknown";try{const r=JSON.parse(i.readFileSync(m,"utf-8"));if(r.pid!==e)return"unknown";if(r.launcher==="desktop-managed"||r.launcher==="global-cli")return r.launcher}catch{}return I(e)}function I(e){if(h()==="win32"){const n=L(e);return n?w(n):"unknown"}try{const n=g(`ps -p ${e} -o command=`,{encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:1e3,windowsHide:!0}).replace(/\\/g,"/");return w(n)}catch{}return"unknown"}function $(e=process.pid){if(h()==="win32")return P(e);try{return g("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 o=Number(t[1]),d=t[2];return!Number.isInteger(o)||o===e?null:F(d)?o:null}).filter(r=>typeof r=="number")}catch{return[]}}function E(e=process.env,n=u,r=f.tmpdir(),t=c.join(f.homedir(),".shennian")){if(e.SHENNIAN_E2E_ISOLATED_DAEMON!=="1"||!e.SHENNIAN_HOME?.trim()||c.resolve(n)===c.resolve(t))return!1;const o=c.relative(c.resolve(r),c.resolve(n));return o!==""&&o!==".."&&!o.startsWith(`..${c.sep}`)&&!c.isAbsolute(o)||c.resolve(n)===c.resolve(e.SHENNIAN_HOME)}function J(e=process.env,n=u){return!E(e,n)}function Z(e=process.env,n=u){return!E(e,n)}function ee(e={}){let n=N(),r=n?.pid??null,t=r!==null&&S(r),o=r!==null&&!t,d=n?.adopted===!0;const s=O();if(o&&e.cleanupStale){try{i.unlinkSync(l)}catch{}n=null,r=null,t=!1,o=!1}if(!t&&J()){const a=$()[0];if(a&&(r=a,t=!0,o=!1,d=!0,e.cleanupStale)){const y=C();T(a,y,{launcher:I(a),adopted:!0}),x(a,I(a)),n={pid:a,instanceId:y,adopted:!0}}}return{running:t,pid:r,stale:o,remoteAccessDisabled:H(),launcher:U(r,t),...t&&n?.pid===r&&n.version?{daemonVersion:n.version}:{},platform:h(),shennianDir:u,pidFile:l,logFile:R,...n?.instanceId?{instanceId:n.instanceId}:{},...d?{adopted:!0}:{},...s.machineId?{machineId:s.machineId}:{},paired:!!(s.machineToken&&s.machineId),...s.serverUrl?{serverUrl:s.serverUrl}:{}}}export{m as LAUNCHER_FILE,R as LOG_FILE,l as PID_FILE,D as REMOTE_ACCESS_DISABLED_FILE,u as SHENNIAN_DIR,X as clearDaemonLauncher,Q as clearDaemonPidIfOwner,K as clearRemoteAccessDisabled,C as createDaemonInstanceId,$ as findRunningDaemonProcessIds,v as getCurrentProcessDaemonLauncher,ee as getDaemonStatus,h as getPlatform,E as isIsolatedDaemonE2eInstance,H as isRemoteAccessDisabled,S as isRunning,N as readPidRecord,Y as recordStartedDaemon,J as shouldDiscoverGlobalDaemonProcesses,Z as shouldInstallPlatformService,z as waitForPidExitSync,x as writeDaemonLauncher,T as writeDaemonPid};
1
+ import i from"node:fs";import c from"node:path";import f from"node:os";import{execSync as g}from"node:child_process";import{randomUUID as A}from"node:crypto";import{getShennianDir as O,loadConfig as b,resolveShennianPath as p}from"../config/index.js";import{findRunningWindowsDaemonProcessIds as P,inferDaemonLauncherFromCommand as w,isDaemonProcessRunning as k,isShennianRunServiceCommand as F,readWindowsProcessCommand as L}from"./daemon-process.js";const u=O(),l=p("daemon.pid"),R=p("daemon.log"),D=p("remote-access.disabled"),m=p("daemon-launcher.json");function h(){const e=f.platform();return e==="darwin"||e==="linux"||e==="win32"?e:"linux"}function _(e){const n=e.trim();if(!n)return null;if(n.startsWith("{"))try{const t=JSON.parse(n),o=Number(t.pid);return!Number.isInteger(o)||o<=0?null:{pid:o,...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 N(){try{return _(i.readFileSync(l,"utf-8"))}catch{return null}}function S(e){return k(e)}function z(e,n=3e3){const r=Date.now();for(;Date.now()-r<n;){if(!S(e))return!0;Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,100)}return!S(e)}function H(){try{return i.lstatSync(D),!0}catch(e){return!(e&&typeof e=="object"&&"code"in e&&e.code==="ENOENT")}}function K(){try{i.unlinkSync(D)}catch(e){if(e&&typeof e=="object"&&"code"in e&&e.code==="ENOENT")return;throw e}}function E(){return"global-cli"}function C(){return`${process.pid}-${Date.now()}-${A()}`}function T(e,n,r={}){i.mkdirSync(u,{recursive:!0}),i.writeFileSync(l,JSON.stringify({pid:e,instanceId:n,...r.version?{version:r.version}:{},launcher:r.launcher??E(),...r.adopted?{adopted:!0}:{},startedAt:new Date().toISOString()},null,2))}function Q(e,n){const r=N();if(!(r?.pid!==e||r.instanceId!==n))try{i.unlinkSync(l)}catch{}}function x(e,n=E(),r){i.mkdirSync(u,{recursive:!0}),i.writeFileSync(m,JSON.stringify({pid:e,launcher:n,...r?{instanceId:r}:{},updatedAt:new Date().toISOString()},null,2))}function X(e){if(e)try{if(JSON.parse(i.readFileSync(m,"utf-8")).instanceId!==e)return}catch{return}try{i.unlinkSync(m)}catch{}}function Y(e){e&&x(e)}function U(e,n){if(!e||!n)return"unknown";try{const r=JSON.parse(i.readFileSync(m,"utf-8"));if(r.pid!==e)return"unknown";if(r.launcher==="desktop-managed"||r.launcher==="global-cli")return r.launcher}catch{}return I(e)}function I(e){if(h()==="win32"){const n=L(e);return n?w(n):"unknown"}try{const n=g(`ps -p ${e} -o command=`,{encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:1e3,windowsHide:!0}).replace(/\\/g,"/");return w(n)}catch{}return"unknown"}function $(e=process.pid){if(h()==="win32")return P(e);try{return g("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 o=Number(t[1]),d=t[2];return!Number.isInteger(o)||o===e?null:F(d)?o:null}).filter(r=>typeof r=="number")}catch{return[]}}function v(e=process.env,n=u,r=f.tmpdir(),t=c.join(f.homedir(),".shennian")){if(e.SHENNIAN_E2E_ISOLATED_DAEMON!=="1"||!e.SHENNIAN_HOME?.trim()||c.resolve(n)===c.resolve(t))return!1;const o=c.relative(c.resolve(r),c.resolve(n));return o!==""&&o!==".."&&!o.startsWith(`..${c.sep}`)&&!c.isAbsolute(o)||c.resolve(n)===c.resolve(e.SHENNIAN_HOME)}function J(e=process.env,n=u){return!v(e,n)}function Z(e=process.env,n=u){return e.SHENNIAN_DAEMON_SUPERVISOR!=="docker"&&!v(e,n)}function ee(e={}){let n=N(),r=n?.pid??null,t=r!==null&&S(r),o=r!==null&&!t,d=n?.adopted===!0;const s=b();if(o&&e.cleanupStale){try{i.unlinkSync(l)}catch{}n=null,r=null,t=!1,o=!1}if(!t&&J()){const a=$()[0];if(a&&(r=a,t=!0,o=!1,d=!0,e.cleanupStale)){const y=C();T(a,y,{launcher:I(a),adopted:!0}),x(a,I(a)),n={pid:a,instanceId:y,adopted:!0}}}return{running:t,pid:r,stale:o,remoteAccessDisabled:H(),launcher:U(r,t),...t&&n?.pid===r&&n.version?{daemonVersion:n.version}:{},platform:h(),shennianDir:u,pidFile:l,logFile:R,...n?.instanceId?{instanceId:n.instanceId}:{},...d?{adopted:!0}:{},...s.machineId?{machineId:s.machineId}:{},paired:!!(s.machineToken&&s.machineId),...s.serverUrl?{serverUrl:s.serverUrl}:{}}}export{m as LAUNCHER_FILE,R as LOG_FILE,l as PID_FILE,D as REMOTE_ACCESS_DISABLED_FILE,u as SHENNIAN_DIR,X as clearDaemonLauncher,Q as clearDaemonPidIfOwner,K as clearRemoteAccessDisabled,C as createDaemonInstanceId,$ as findRunningDaemonProcessIds,E as getCurrentProcessDaemonLauncher,ee as getDaemonStatus,h as getPlatform,v as isIsolatedDaemonE2eInstance,H as isRemoteAccessDisabled,S as isRunning,N as readPidRecord,Y as recordStartedDaemon,J as shouldDiscoverGlobalDaemonProcesses,Z as shouldInstallPlatformService,z as waitForPidExitSync,x as writeDaemonLauncher,T as writeDaemonPid};
@@ -1,7 +1,7 @@
1
- import a from"chalk";import{readCliDistribution as de}from"../runtime-distribution.js";import s from"node:fs";import{renameSyncWithRetry as le}from"../fs/atomic-rename.js";import d from"node:path";import g from"node:os";import{execSync as u,spawn as pe}from"node:child_process";import{randomUUID as me}from"node:crypto";import{fileURLToPath as fe}from"node:url";import{loadConfig as Se,resolveShennianPath as k,saveConfig as ge}from"../config/index.js";import{buildWindowsLauncherCommand as he,buildWindowsScheduledTaskXml as ye,buildWindowsStartupVbs as we,escapeXml as $,isWindowsCmdScript as ve,quoteCmdArg as F,quoteSystemdArg as ke,registerWindowsScheduledTask as De,suspendWindowsScheduledTask as Pe}from"./daemon-windows.js";import{isDaemonReadyStatus as A,waitForDaemonReadyStatus as D}from"./daemon-start-wait.js";import{checkDaemonIpcHealth as be}from"./daemon-ipc-health.js";import{requestWindowsDaemonSelfStop as Ee}from"./daemon-stop-ipc.js";import{compareVersions as Ie,getCurrentVersion as H}from"../upgrade/engine.js";import{buildWindowsLauncherCommand as bn,buildWindowsScheduledTaskCommands as En,buildWindowsScheduledTaskSuspendCommands as In,buildWindowsScheduledTaskXml as $n,buildWindowsStartupVbs as An,suspendWindowsScheduledTask as Rn}from"./daemon-windows.js";import{inferDaemonLauncherFromCommand as xn,isShennianRunServiceCommand as Ln}from"./daemon-process.js";import{SHENNIAN_DIR as M,PID_FILE as R,LOG_FILE as l,REMOTE_ACCESS_DISABLED_FILE as V,readPidRecord as _,clearDaemonLauncher as $e,shouldDiscoverGlobalDaemonProcesses as Ae,getPlatform as p,isRunning as P,waitForPidExitSync as q,isRemoteAccessDisabled as Re,clearRemoteAccessDisabled as G,recordStartedDaemon as _e,findRunningDaemonProcessIds as xe,shouldInstallPlatformService as x,getDaemonStatus as c}from"./daemon-state.js";import{isEphemeralCliPath as Le,resolveServiceLaunchSpec as Ce,captureEnvForService as J,saveEnvSnapshot as K}from"./daemon-service-spec.js";import{isRemoteAccessDisabled as jn,clearRemoteAccessDisabled as Nn,getCurrentProcessDaemonLauncher as Tn,createDaemonInstanceId as Wn,writeDaemonPid as On,clearDaemonPidIfOwner as Un,writeDaemonLauncher as Bn,clearDaemonLauncher as Fn,recordStartedDaemon as Hn,findRunningDaemonProcessIds as Mn,isIsolatedDaemonE2eInstance as Vn,shouldDiscoverGlobalDaemonProcesses as qn,shouldInstallPlatformService as Gn,getDaemonStatus as Jn}from"./daemon-state.js";import{isSafeSnapshotEnvKey as Xn,isEphemeralCliPath as Yn,resolveServiceLaunchSpec as zn,captureEnvForService as Qn,saveEnvSnapshot as Zn}from"./daemon-service-spec.js";const je=d.dirname(fe(import.meta.url)),X=d.resolve(je,"../../bin/shennian.js"),Y=process.execPath;function z(e,n){const r=d.dirname(e),t=`${e}.${process.pid}.${me()}.tmp`;s.mkdirSync(r,{recursive:!0});let o=null;try{o=s.openSync(t,"w",384),s.writeSync(o,n,void 0,"utf8"),s.fsyncSync(o),s.closeSync(o),o=null,le(t,e);try{const i=s.openSync(r,"r");try{s.fsyncSync(i)}finally{s.closeSync(i)}}catch{}}finally{o!==null&&s.closeSync(o);try{s.unlinkSync(t)}catch{}}}function Ne(e={}){const n=e.disabledAt??new Date().toISOString(),r=e.markerFile??V,t=e.platform??p(),o=e.servicePresent??(x()&&T(t)),i=e.execCommand??(f=>{u(f,{stdio:"pipe",windowsHide:!0})});if(z(r,n),!o)return{disabledAt:n,autoStartDisabled:!0};try{return i(t==="darwin"?`launchctl disable "${C()}"`:t==="linux"?"systemctl --user disable shennian":`schtasks /change /tn "${w}" /disable`),{disabledAt:n,autoStartDisabled:!0}}catch(f){return{disabledAt:n,autoStartDisabled:!1,autoStartError:f instanceof Error?f.message:String(f)}}}function Te(e={}){const n=e.platform??p();if(!(e.servicePresent??(x()&&T(n))))return{serviceStopped:!0};const t=e.execCommand??(o=>{u(o,{stdio:"pipe",windowsHide:!0})});try{return t(n==="darwin"?`launchctl bootout "${C()}"`:n==="linux"?"systemctl --user stop shennian":`schtasks /end /tn "${w}"`),{serviceStopped:!0}}catch(o){return{serviceStopped:!1,error:o instanceof Error?o.message:String(o)}}}function m(e){process.stdout.write(`${JSON.stringify(e,null,2)}
2
- `)}function Q(e){const n=e?.trim();if(!n)return;const r=Se();r.serverUrl=n,ge(r)}function Z(e){return e?.trim()||process.env.SHENNIAN_DESKTOP_SERVER_URL?.trim()||void 0}const L="com.shennian.agent",S=d.join(g.homedir(),"Library/LaunchAgents",`${L}.plist`),ee=k("Shennian.app"),We=d.join(g.homedir(),"AppData","Roaming","Microsoft","Windows","Start Menu","Programs","Startup"),b=k("autostart.cmd"),E=k("autostart.vbs"),I=k("autostart.xml"),Oe=d.join(We,"ShennianAgent.vbs");function ne(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(o=>o.trim()).find(Boolean)??null}catch{return null}}function Ue(){const e=p()==="win32"?"npx.cmd":"npx",n=d.join(d.dirname(Y),e);return s.existsSync(n)?n:ne("npx")}function h(){return Ce({nodeExec:Y,scriptPath:X,shennianCommandPath:ne("shennian"),npxPath:Ue()})}function re(){try{u(`schtasks /delete /tn "${w}" /f`,{stdio:"pipe",windowsHide:!0})}catch{}}function te(){try{s.unlinkSync(Oe)}catch{}}function Be(){const e=process.env.USERDOMAIN?.trim(),n=process.env.COMPUTERNAME?.trim(),r=process.env.USERNAME?.trim()||g.userInfo().username;return e&&e.toUpperCase()!=="WORKGROUP"?`${e}\\${r}`:n?`${n}\\${r}`:r}function Fe(e){if(p()==="win32"&&ve(e.command)){const n=[e.command,...e.args].map(F).join(" ");return{command:process.env.ComSpec||"cmd.exe",args:["/d","/s","/c",`"${n}"`],windowsVerbatimArguments:!0}}return{command:e.command,args:e.args}}function He(e,n,r=process.env){return{detached:!0,stdio:["ignore",n,n],env:r,windowsHide:!0,...e.windowsVerbatimArguments?{windowsVerbatimArguments:!0}:{}}}function Me(){const e=h();s.writeFileSync(b,he(e,l)),s.writeFileSync(E,we(b)),te(),re();const n=ye({userId:Be(),command:d.join(process.env.SystemRoot||"C:\\Windows","System32","wscript.exe"),arguments:[F(E)]});return s.writeFileSync(I,`\uFEFF${n}`,"utf16le"),De({taskName:w,xmlPath:I},r=>{u(r,{stdio:"pipe",windowsHide:!0})})}function Ve(){Pe(w,e=>{u(e,{stdio:"pipe",windowsHide:!0})})}function qe(e={}){const n=J(),r=e.launch??h(),t=Object.entries(n).map(([i,f])=>` <key>${$(i)}</key>
3
- <string>${$(f)}</string>`).join(`
4
- `),o=[r.command,...r.args].map(i=>` <string>${$(i)}</string>`).join(`
1
+ import a from"chalk";import{readCliDistribution as de}from"../runtime-distribution.js";import s from"node:fs";import{renameSyncWithRetry as le}from"../fs/atomic-rename.js";import d from"node:path";import g from"node:os";import{execSync as u,spawn as pe}from"node:child_process";import{randomUUID as me}from"node:crypto";import{fileURLToPath as fe}from"node:url";import{loadConfig as Se,resolveShennianPath as k,saveConfig as ge}from"../config/index.js";import{buildWindowsLauncherCommand as he,buildWindowsScheduledTaskXml as ye,buildWindowsStartupVbs as we,escapeXml as A,isWindowsCmdScript as ve,quoteCmdArg as F,quoteSystemdArg as ke,registerWindowsScheduledTask as De,suspendWindowsScheduledTask as Pe}from"./daemon-windows.js";import{isDaemonReadyStatus as R,waitForDaemonReadyStatus as D}from"./daemon-start-wait.js";import{checkDaemonIpcHealth as be}from"./daemon-ipc-health.js";import{requestWindowsDaemonSelfStop as Ee}from"./daemon-stop-ipc.js";import{compareVersions as Ie,getCurrentVersion as H}from"../upgrade/engine.js";import{buildWindowsLauncherCommand as bn,buildWindowsScheduledTaskCommands as En,buildWindowsScheduledTaskSuspendCommands as In,buildWindowsScheduledTaskXml as $n,buildWindowsStartupVbs as An,suspendWindowsScheduledTask as Rn}from"./daemon-windows.js";import{inferDaemonLauncherFromCommand as xn,isShennianRunServiceCommand as Ln}from"./daemon-process.js";import{SHENNIAN_DIR as M,PID_FILE as _,LOG_FILE as l,REMOTE_ACCESS_DISABLED_FILE as V,readPidRecord as x,clearDaemonLauncher as $e,shouldDiscoverGlobalDaemonProcesses as Ae,getPlatform as p,isRunning as P,waitForPidExitSync as q,isRemoteAccessDisabled as Re,clearRemoteAccessDisabled as G,recordStartedDaemon as _e,findRunningDaemonProcessIds as xe,shouldInstallPlatformService as b,getDaemonStatus as c}from"./daemon-state.js";import{isEphemeralCliPath as Le,resolveServiceLaunchSpec as Ce,captureEnvForService as J,saveEnvSnapshot as K}from"./daemon-service-spec.js";import{isRemoteAccessDisabled as jn,clearRemoteAccessDisabled as Nn,getCurrentProcessDaemonLauncher as Tn,createDaemonInstanceId as Wn,writeDaemonPid as On,clearDaemonPidIfOwner as Un,writeDaemonLauncher as Bn,clearDaemonLauncher as Fn,recordStartedDaemon as Hn,findRunningDaemonProcessIds as Mn,isIsolatedDaemonE2eInstance as Vn,shouldDiscoverGlobalDaemonProcesses as qn,shouldInstallPlatformService as Gn,getDaemonStatus as Jn}from"./daemon-state.js";import{isSafeSnapshotEnvKey as Xn,isEphemeralCliPath as Yn,resolveServiceLaunchSpec as zn,captureEnvForService as Qn,saveEnvSnapshot as Zn}from"./daemon-service-spec.js";const je=d.dirname(fe(import.meta.url)),X=d.resolve(je,"../../bin/shennian.js"),Y=process.execPath;function z(e,n){const r=d.dirname(e),t=`${e}.${process.pid}.${me()}.tmp`;s.mkdirSync(r,{recursive:!0});let o=null;try{o=s.openSync(t,"w",384),s.writeSync(o,n,void 0,"utf8"),s.fsyncSync(o),s.closeSync(o),o=null,le(t,e);try{const i=s.openSync(r,"r");try{s.fsyncSync(i)}finally{s.closeSync(i)}}catch{}}finally{o!==null&&s.closeSync(o);try{s.unlinkSync(t)}catch{}}}function Ne(e={}){const n=e.disabledAt??new Date().toISOString(),r=e.markerFile??V,t=e.platform??p(),o=e.servicePresent??(b()&&T(t)),i=e.execCommand??(f=>{u(f,{stdio:"pipe",windowsHide:!0})});if(z(r,n),!o)return{disabledAt:n,autoStartDisabled:!0};try{return i(t==="darwin"?`launchctl disable "${C()}"`:t==="linux"?"systemctl --user disable shennian":`schtasks /change /tn "${w}" /disable`),{disabledAt:n,autoStartDisabled:!0}}catch(f){return{disabledAt:n,autoStartDisabled:!1,autoStartError:f instanceof Error?f.message:String(f)}}}function Te(e={}){const n=e.platform??p();if(!(e.servicePresent??(b()&&T(n))))return{serviceStopped:!0};const t=e.execCommand??(o=>{u(o,{stdio:"pipe",windowsHide:!0})});try{return t(n==="darwin"?`launchctl bootout "${C()}"`:n==="linux"?"systemctl --user stop shennian":`schtasks /end /tn "${w}"`),{serviceStopped:!0}}catch(o){return{serviceStopped:!1,error:o instanceof Error?o.message:String(o)}}}function m(e){process.stdout.write(`${JSON.stringify(e,null,2)}
2
+ `)}function Q(e){const n=e?.trim();if(!n)return;const r=Se();r.serverUrl=n,ge(r)}function Z(e){return e?.trim()||process.env.SHENNIAN_DESKTOP_SERVER_URL?.trim()||void 0}const L="com.shennian.agent",S=d.join(g.homedir(),"Library/LaunchAgents",`${L}.plist`),ee=k("Shennian.app"),We=d.join(g.homedir(),"AppData","Roaming","Microsoft","Windows","Start Menu","Programs","Startup"),E=k("autostart.cmd"),I=k("autostart.vbs"),$=k("autostart.xml"),Oe=d.join(We,"ShennianAgent.vbs");function ne(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(o=>o.trim()).find(Boolean)??null}catch{return null}}function Ue(){const e=p()==="win32"?"npx.cmd":"npx",n=d.join(d.dirname(Y),e);return s.existsSync(n)?n:ne("npx")}function h(){return Ce({nodeExec:Y,scriptPath:X,shennianCommandPath:ne("shennian"),npxPath:Ue()})}function re(){try{u(`schtasks /delete /tn "${w}" /f`,{stdio:"pipe",windowsHide:!0})}catch{}}function te(){try{s.unlinkSync(Oe)}catch{}}function Be(){const e=process.env.USERDOMAIN?.trim(),n=process.env.COMPUTERNAME?.trim(),r=process.env.USERNAME?.trim()||g.userInfo().username;return e&&e.toUpperCase()!=="WORKGROUP"?`${e}\\${r}`:n?`${n}\\${r}`:r}function Fe(e){if(p()==="win32"&&ve(e.command)){const n=[e.command,...e.args].map(F).join(" ");return{command:process.env.ComSpec||"cmd.exe",args:["/d","/s","/c",`"${n}"`],windowsVerbatimArguments:!0}}return{command:e.command,args:e.args}}function He(e,n,r=process.env){return{detached:!0,stdio:["ignore",n,n],env:r,windowsHide:!0,...e.windowsVerbatimArguments?{windowsVerbatimArguments:!0}:{}}}function Me(){const e=h();s.writeFileSync(E,he(e,l)),s.writeFileSync(I,we(E)),te(),re();const n=ye({userId:Be(),command:d.join(process.env.SystemRoot||"C:\\Windows","System32","wscript.exe"),arguments:[F(I)]});return s.writeFileSync($,`\uFEFF${n}`,"utf16le"),De({taskName:w,xmlPath:$},r=>{u(r,{stdio:"pipe",windowsHide:!0})})}function Ve(){Pe(w,e=>{u(e,{stdio:"pipe",windowsHide:!0})})}function qe(e={}){const n=J(),r=e.launch??h(),t=Object.entries(n).map(([i,f])=>` <key>${A(i)}</key>
3
+ <string>${A(f)}</string>`).join(`
4
+ `),o=[r.command,...r.args].map(i=>` <string>${A(i)}</string>`).join(`
5
5
  `);return`<?xml version="1.0" encoding="UTF-8"?>
6
6
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
7
7
  <plist version="1.0">
@@ -41,6 +41,6 @@ StandardOutput=append:${l}
41
41
  StandardError=append:${l}
42
42
 
43
43
  [Install]
44
- WantedBy=default.target`}const w="ShennianAgent";function Ke(e){u(e,{stdio:"pipe",windowsHide:!0})}function se(){const e=process.getuid?.();if(typeof e=="number")return e;const n=g.userInfo();return typeof n.uid=="number"?n.uid:n.username}function C(e=se()){return`gui/${e}/${L}`}function Xe(e=Ke){const n=`gui/${se()}`,r=C();try{return e(`launchctl enable "${r}"`),e(`launchctl bootout "${r}" 2>/dev/null || true`),e(`launchctl bootstrap "${n}" "${S}"`),e(`launchctl kickstart -k "${r}"`),e(`launchctl print "${r}"`),!0}catch{try{return e(`launchctl enable "${r}"`),e(`launchctl unload "${S}" 2>/dev/null || true`),e(`launchctl load -w "${S}"`),e(`launchctl kickstart -k "${r}"`),e(`launchctl print "${r}"`),!0}catch{return!1}}}function j(e={}){s.mkdirSync(M,{recursive:!0});const n=c({cleanupStale:!0}),r=v(n);if(r)throw new Error(r);if(n.pid!==null&&n.running&&!N(n)){e.quiet||console.log(a.green(`\u2713 Background service already running (PID ${n.pid})`));return}W(n);const t=s.openSync(l,"a"),o=Fe(h()),i=pe(o.command,o.args,He(o,t));i.unref(),s.closeSync(t),_e(i.pid),e.quiet||(console.log(a.green(`\u2713 Background service started (PID ${i.pid})`)),console.log(a.gray(` Logs: ${l}`)))}function N(e,n=_(),r=H()){return e.pid===null||!e.running||e.launcher!=="global-cli"?!1:e.adopted===!0||n?.version!==r}function v(e){return e.pid===null||!e.running||e.launcher==="global-cli"?null:`unsupported_daemon_source:${e.launcher}`}function T(e=p()){switch(e){case"darwin":return s.existsSync(S)&&!s.existsSync(ee);case"linux":return s.existsSync(y);case"win32":return s.existsSync(b)&&s.existsSync(E)&&s.existsSync(I)}}function Ye(e,n,r,t=_(),o=H()){return!n.api?.trim()&&e.pid!==null&&e.running&&e.launcher==="global-cli"&&!e.stale&&!e.remoteAccessDisabled&&r&&!N(e,t,o)}function W(e=c({cleanupStale:!0})){if(!N(e)||e.pid===null)return;let n;try{process.kill(e.pid,"SIGTERM"),q(e.pid,5e3)||(process.kill(e.pid,"SIGKILL"),q(e.pid,2e3))}catch(r){n=r}if(P(e.pid)){const r=n instanceof Error?n.message:"daemon_stop_timeout",t=n&&typeof n=="object"&&"code"in n?n.code:null;throw process.platform==="win32"&&(t==="EPERM"||t==="EACCES")&&e.daemonVersion&&Ie(e.daemonVersion,"0.5.12")!=="none"?new Error("legacy_s4u_migration_required"):new Error(`daemon_replacement_failed: ${r}`)}try{_()?.pid===e.pid&&s.unlinkSync(R)}catch{}}function O(e={}){if(s.mkdirSync(M,{recursive:!0}),!x())return!1;const n=p();switch(h().mode==="direct"&&Le(X)&&console.warn(a.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=d.dirname(S);s.mkdirSync(t,{recursive:!0}),oe(),s.writeFileSync(S,qe());const o=Xe(),i=Ge(n);return!e.quiet&&i&&console.log(a.gray(`\u2139 ${i}`)),o}case"linux":{const t=d.dirname(y);s.mkdirSync(t,{recursive:!0}),s.writeFileSync(y,Je());try{u("systemctl --user daemon-reload && systemctl --user enable shennian",{stdio:"pipe",windowsHide:!0})}catch{return!1}try{u(`loginctl enable-linger ${g.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 Me()}}function ze(){const n=c({cleanupStale:!0}).pid;if(n===null)return{};if(!P(n)){try{s.unlinkSync(R)}catch{}return{stalePid:n}}try{return process.kill(n,"SIGTERM"),{stoppedPid:n}}catch(r){const t=r&&typeof r=="object"&&"code"in r&&typeof r.code=="string"?r.code:void 0;return{refusedPid:n,error:r instanceof Error?r.message:String(r),errorCode:t}}}async function ie(e=5e3){let n=ze(),r=!1;if(n.refusedPid&&(n.errorCode==="EPERM"||n.errorCode==="EACCES")&&p()==="win32"){const o=await Ee(n.refusedPid);if(!o.accepted)return{error:o.error};n={stoppedPid:n.refusedPid},r=!0}if(!n.stoppedPid)return n;const t=await B(n.stoppedPid,e);if(!t&&r)return{...n,error:"daemon_stop_timeout"};if(!t)try{if(process.kill(n.stoppedPid,"SIGKILL"),!await B(n.stoppedPid,2e3))return{...n,error:"daemon_stop_timeout"}}catch(o){return{...n,error:o instanceof Error?o.message:String(o)}}try{s.unlinkSync(R)}catch{}if($e(),Ae()){for(const o of xe())if(o!==n.stoppedPid)try{process.kill(o,"SIGTERM"),await B(o,2e3)}catch{}}return n}function vn(e={}){const n=c({cleanupStale:!0});if(n.remoteAccessDisabled&&!e.resumePaused)return{status:"paused"};if(A(n)&&!n.remoteAccessDisabled)return{status:"running"};const r=v(n);if(r)throw new Error(r);K(),G(),W(n),O({quiet:!0})||j({quiet:!0});const o=n.running?n.instanceId:void 0,i=D(()=>c({cleanupStale:!0}),{excludedInstanceId:o});if(!A(i,o))throw new Error("daemon_start_failed");return{status:"started"}}function Qe(e={}){const n=Re();try{const r=c({cleanupStale:!0}),t=v(r);if(t)throw new Error(t);Q(Z(e.api)),G(),W(r),O({quiet:e.json})||j({quiet:e.json});const i=r.running?r.instanceId:void 0,f=D(()=>c({cleanupStale:!0}),{excludedInstanceId:i});if(!A(f,i))throw new Error("daemon_start_failed");e.json?m(f):console.log(a.green("\u2713 Background service started"))}catch(r){n&&z(V,new Date().toISOString()),process.exitCode=1;const t=r instanceof Error?r.message:String(r);e.json?m({...c(),error:t}):console.error(a.red(`Background service did not start: ${t}`))}}async function Ze(e={}){const n=Ne(),r=Te(),t=await ie(),o=c({cleanupStale:!0}),i=t.error??n.autoStartError??r.error??(o.running?"daemon_stop_failed":o.remoteAccessDisabled?void 0:"remote_access_pause_failed");if(i&&(process.exitCode=1),e.json){m(i?{...o,error:i}:o);return}i?console.error(a.red(`\u2717 Failed to stop completely: ${i}`)):console.log(a.green("\u2713 Background service stopped"))}function ae(e){const n=c({cleanupStale:!0});if(Ye(n,e,T())){e.json?m(n):console.log(a.green(`\u2713 Background service already running (PID ${n.pid})`));return}K(),Qe(e)}async function U(e={}){const n=c({cleanupStale:!0}),r=v(n);if(r){process.exitCode=1,e.json?m({...n,error:r}):console.error(a.red(`Background service was not stopped: ${r}`));return}await Ze(e)}async function B(e,n=5e3){const r=Date.now();for(;Date.now()-r<n;){if(!P(e))return!0;await new Promise(t=>setTimeout(t,100))}return!P(e)}async function en(e={}){const n=c({cleanupStale:!0}),r=v(n);if(r){process.exitCode=1,e.json?m({...n,error:r}):console.error(a.red(`Background service was not restarted: ${r}`));return}if(n.remoteAccessDisabled){e.json?m({...n,error:"remote_access_disabled_use_shennian_start"}):console.error(a.yellow("Remote access is paused. Run `shennian start` on this computer to resume."));return}Q(Z(e.api));const t=p();t==="win32"&&Ve();const o=await ie();if(o.error){e.json?m({...c(),error:o.error}):console.error(a.red(`\u2717 Failed to stop: ${o.error}`));return}if(o.stoppedPid!==void 0?e.json||console.log(a.green(`\u2713 Background service stopped (PID ${o.stoppedPid})`)):o.stalePid!==void 0?e.json||console.log(a.yellow(`\u26A0 Service process no longer exists, cleaned up stale PID ${o.stalePid}`)):e.json||console.log(a.gray("\u25CF Background service not running, starting it now")),(t==="linux"||t==="win32")&&O()){e.json&&m(D(()=>c({cleanupStale:!0})));return}j({quiet:e.json}),e.json&&m(D(()=>c({cleanupStale:!0})))}async function ce(e={}){const n=c(),r={...n,client:de(),ipc:await be(n.running)};if(e.json){m(r);return}if(r.pid===null){console.log(a.gray("\u25CF Background service not running"));return}r.running?(console.log(a.green(`\u25CF Background service running (PID ${r.pid})`)),(r.ipc.state==="unavailable"||r.ipc.state==="unsupported")&&(console.log(a.yellow(` Local control IPC: ${r.ipc.state} (${r.ipc.error})`)),console.log(a.gray(" PID and pairing alone do not prove local commands work; check the Client version, service account, and logs."))),console.log(a.gray(` Logs: ${l}`))):console.log(a.yellow(`\u25CF Background service stopped (PID ${r.pid} is stale)`))}function ue(e){if(!s.existsSync(l)){console.log(a.gray("No logs yet"));return}try{const n=u(g.platform()==="win32"?`powershell Get-Content -Tail ${e.lines} "${l}"`:`tail -n ${e.lines} "${l}"`,{encoding:"utf-8",windowsHide:!0});process.stdout.write(n)}catch{const n=s.readFileSync(l,"utf-8").split(`
44
+ WantedBy=default.target`}const w="ShennianAgent";function Ke(e){u(e,{stdio:"pipe",windowsHide:!0})}function se(){const e=process.getuid?.();if(typeof e=="number")return e;const n=g.userInfo();return typeof n.uid=="number"?n.uid:n.username}function C(e=se()){return`gui/${e}/${L}`}function Xe(e=Ke){const n=`gui/${se()}`,r=C();try{return e(`launchctl enable "${r}"`),e(`launchctl bootout "${r}" 2>/dev/null || true`),e(`launchctl bootstrap "${n}" "${S}"`),e(`launchctl kickstart -k "${r}"`),e(`launchctl print "${r}"`),!0}catch{try{return e(`launchctl enable "${r}"`),e(`launchctl unload "${S}" 2>/dev/null || true`),e(`launchctl load -w "${S}"`),e(`launchctl kickstart -k "${r}"`),e(`launchctl print "${r}"`),!0}catch{return!1}}}function j(e={}){s.mkdirSync(M,{recursive:!0});const n=c({cleanupStale:!0}),r=v(n);if(r)throw new Error(r);if(n.pid!==null&&n.running&&!N(n)){e.quiet||console.log(a.green(`\u2713 Background service already running (PID ${n.pid})`));return}W(n);const t=s.openSync(l,"a"),o=Fe(h()),i=pe(o.command,o.args,He(o,t));i.unref(),s.closeSync(t),_e(i.pid),e.quiet||(console.log(a.green(`\u2713 Background service started (PID ${i.pid})`)),console.log(a.gray(` Logs: ${l}`)))}function N(e,n=x(),r=H()){return e.pid===null||!e.running||e.launcher!=="global-cli"?!1:e.adopted===!0||n?.version!==r}function v(e){return e.pid===null||!e.running||e.launcher==="global-cli"?null:`unsupported_daemon_source:${e.launcher}`}function T(e=p()){switch(e){case"darwin":return s.existsSync(S)&&!s.existsSync(ee);case"linux":return s.existsSync(y);case"win32":return s.existsSync(E)&&s.existsSync(I)&&s.existsSync($)}}function Ye(e,n,r,t=x(),o=H()){return!n.api?.trim()&&e.pid!==null&&e.running&&e.launcher==="global-cli"&&!e.stale&&!e.remoteAccessDisabled&&r&&!N(e,t,o)}function W(e=c({cleanupStale:!0})){if(!N(e)||e.pid===null)return;let n;try{process.kill(e.pid,"SIGTERM"),q(e.pid,5e3)||(process.kill(e.pid,"SIGKILL"),q(e.pid,2e3))}catch(r){n=r}if(P(e.pid)){const r=n instanceof Error?n.message:"daemon_stop_timeout",t=n&&typeof n=="object"&&"code"in n?n.code:null;throw process.platform==="win32"&&(t==="EPERM"||t==="EACCES")&&e.daemonVersion&&Ie(e.daemonVersion,"0.5.12")!=="none"?new Error("legacy_s4u_migration_required"):new Error(`daemon_replacement_failed: ${r}`)}try{x()?.pid===e.pid&&s.unlinkSync(_)}catch{}}function O(e={}){if(s.mkdirSync(M,{recursive:!0}),!b())return!1;const n=p();switch(h().mode==="direct"&&Le(X)&&console.warn(a.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=d.dirname(S);s.mkdirSync(t,{recursive:!0}),oe(),s.writeFileSync(S,qe());const o=Xe(),i=Ge(n);return!e.quiet&&i&&console.log(a.gray(`\u2139 ${i}`)),o}case"linux":{const t=d.dirname(y);s.mkdirSync(t,{recursive:!0}),s.writeFileSync(y,Je());try{u("systemctl --user daemon-reload && systemctl --user enable shennian",{stdio:"pipe",windowsHide:!0})}catch{return!1}try{u(`loginctl enable-linger ${g.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 Me()}}function ze(){const n=c({cleanupStale:!0}).pid;if(n===null)return{};if(!P(n)){try{s.unlinkSync(_)}catch{}return{stalePid:n}}try{return process.kill(n,"SIGTERM"),{stoppedPid:n}}catch(r){const t=r&&typeof r=="object"&&"code"in r&&typeof r.code=="string"?r.code:void 0;return{refusedPid:n,error:r instanceof Error?r.message:String(r),errorCode:t}}}async function ie(e=5e3){let n=ze(),r=!1;if(n.refusedPid&&(n.errorCode==="EPERM"||n.errorCode==="EACCES")&&p()==="win32"){const o=await Ee(n.refusedPid);if(!o.accepted)return{error:o.error};n={stoppedPid:n.refusedPid},r=!0}if(!n.stoppedPid)return n;const t=await B(n.stoppedPid,e);if(!t&&r)return{...n,error:"daemon_stop_timeout"};if(!t)try{if(process.kill(n.stoppedPid,"SIGKILL"),!await B(n.stoppedPid,2e3))return{...n,error:"daemon_stop_timeout"}}catch(o){return{...n,error:o instanceof Error?o.message:String(o)}}try{s.unlinkSync(_)}catch{}if($e(),Ae()){for(const o of xe())if(o!==n.stoppedPid)try{process.kill(o,"SIGTERM"),await B(o,2e3)}catch{}}return n}function vn(e={}){const n=c({cleanupStale:!0});if(n.remoteAccessDisabled&&!e.resumePaused)return{status:"paused"};if(R(n)&&!n.remoteAccessDisabled)return{status:"running"};const r=v(n);if(r)throw new Error(r);K(),G(),W(n),O({quiet:!0})||j({quiet:!0});const o=n.running?n.instanceId:void 0,i=D(()=>c({cleanupStale:!0}),{excludedInstanceId:o});if(!R(i,o))throw new Error("daemon_start_failed");return{status:"started"}}function Qe(e={}){const n=Re();try{const r=c({cleanupStale:!0}),t=v(r);if(t)throw new Error(t);Q(Z(e.api)),G(),W(r),O({quiet:e.json})||j({quiet:e.json});const i=r.running?r.instanceId:void 0,f=D(()=>c({cleanupStale:!0}),{excludedInstanceId:i});if(!R(f,i))throw new Error("daemon_start_failed");e.json?m(f):console.log(a.green("\u2713 Background service started"))}catch(r){n&&z(V,new Date().toISOString()),process.exitCode=1;const t=r instanceof Error?r.message:String(r);e.json?m({...c(),error:t}):console.error(a.red(`Background service did not start: ${t}`))}}async function Ze(e={}){const n=Ne(),r=Te(),t=await ie(),o=c({cleanupStale:!0}),i=t.error??n.autoStartError??r.error??(o.running?"daemon_stop_failed":o.remoteAccessDisabled?void 0:"remote_access_pause_failed");if(i&&(process.exitCode=1),e.json){m(i?{...o,error:i}:o);return}i?console.error(a.red(`\u2717 Failed to stop completely: ${i}`)):console.log(a.green("\u2713 Background service stopped"))}function ae(e){const n=c({cleanupStale:!0}),r=!b()||T();if(Ye(n,e,r)){e.json?m(n):console.log(a.green(`\u2713 Background service already running (PID ${n.pid})`));return}K(),Qe(e)}async function U(e={}){const n=c({cleanupStale:!0}),r=v(n);if(r){process.exitCode=1,e.json?m({...n,error:r}):console.error(a.red(`Background service was not stopped: ${r}`));return}await Ze(e)}async function B(e,n=5e3){const r=Date.now();for(;Date.now()-r<n;){if(!P(e))return!0;await new Promise(t=>setTimeout(t,100))}return!P(e)}async function en(e={}){const n=c({cleanupStale:!0}),r=v(n);if(r){process.exitCode=1,e.json?m({...n,error:r}):console.error(a.red(`Background service was not restarted: ${r}`));return}if(n.remoteAccessDisabled){e.json?m({...n,error:"remote_access_disabled_use_shennian_start"}):console.error(a.yellow("Remote access is paused. Run `shennian start` on this computer to resume."));return}Q(Z(e.api));const t=p();t==="win32"&&Ve();const o=await ie();if(o.error){e.json?m({...c(),error:o.error}):console.error(a.red(`\u2717 Failed to stop: ${o.error}`));return}if(o.stoppedPid!==void 0?e.json||console.log(a.green(`\u2713 Background service stopped (PID ${o.stoppedPid})`)):o.stalePid!==void 0?e.json||console.log(a.yellow(`\u26A0 Service process no longer exists, cleaned up stale PID ${o.stalePid}`)):e.json||console.log(a.gray("\u25CF Background service not running, starting it now")),(t==="linux"||t==="win32")&&O()){e.json&&m(D(()=>c({cleanupStale:!0})));return}j({quiet:e.json}),e.json&&m(D(()=>c({cleanupStale:!0})))}async function ce(e={}){const n=c(),r={...n,client:de(),ipc:await be(n.running)};if(e.json){m(r);return}if(r.pid===null){console.log(a.gray("\u25CF Background service not running"));return}r.running?(console.log(a.green(`\u25CF Background service running (PID ${r.pid})`)),(r.ipc.state==="unavailable"||r.ipc.state==="unsupported")&&(console.log(a.yellow(` Local control IPC: ${r.ipc.state} (${r.ipc.error})`)),console.log(a.gray(" PID and pairing alone do not prove local commands work; check the Client version, service account, and logs."))),console.log(a.gray(` Logs: ${l}`))):console.log(a.yellow(`\u25CF Background service stopped (PID ${r.pid} is stale)`))}function ue(e){if(!s.existsSync(l)){console.log(a.gray("No logs yet"));return}try{const n=u(g.platform()==="win32"?`powershell Get-Content -Tail ${e.lines} "${l}"`:`tail -n ${e.lines} "${l}"`,{encoding:"utf-8",windowsHide:!0});process.stdout.write(n)}catch{const n=s.readFileSync(l,"utf-8").split(`
45
45
  `).slice(-e.lines);console.log(n.join(`
46
- `))}}async function nn(){switch(await U(),p()){case"darwin":{if(s.existsSync(S)){try{u(`launchctl unload -w "${S}"`,{stdio:"pipe",windowsHide:!0})}catch{}s.unlinkSync(S)}oe(),console.log(a.green("\u2713 Auto-start uninstalled (launchd)"));break}case"linux":{try{u("systemctl --user disable --now shennian",{stdio:"pipe",windowsHide:!0})}catch{}if(s.existsSync(y)){s.unlinkSync(y);try{u("systemctl --user daemon-reload",{stdio:"pipe",windowsHide:!0})}catch{}}console.log(a.green("\u2713 Auto-start uninstalled (systemd)"));break}case"win32":{re();try{s.unlinkSync(b)}catch{}try{s.unlinkSync(E)}catch{}try{s.unlinkSync(I)}catch{}te(),console.log(a.green("\u2713 Auto-start uninstalled (Task Scheduler)"));break}}}function kn(e){e.command("start").description("Start the background service").option("--json","Print machine-readable status JSON").option("--api <url>","Server URL override").action(t=>ae(t)),e.command("stop").description("Stop the background service").option("--json","Print machine-readable status JSON").action(t=>U(t)),e.command("status").description("Show background service status").option("--json","Print machine-readable status JSON").action(t=>ce(t)),e.command("logs").description("Show recent logs").option("-n, --lines <n>","Number of lines","50").action(t=>ue({lines:parseInt(t.lines,10)}));const n=e.command("daemon",{hidden:!0}).description("Deprecated: use top-level start/stop/status/logs"),r=(t,o)=>{o||console.error(a.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),ae(t)}),n.command("stop").description("Stop the background service").option("--json","Print machine-readable status JSON").action(async t=>{r("stop",t.json),await U(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),en(t)}),n.command("status").description("Show background service status").option("--json","Print machine-readable status JSON").action(t=>{r("status",t.json),ce(t)}),n.command("logs").description("Show recent logs").option("-n, --lines <n>","Number of lines","50").action(t=>{r("logs"),ue({lines:parseInt(t.lines,10)})}),n.command("uninstall").description("Uninstall auto-start service").action(nn)}export{He as buildDaemonSpawnOptions,qe as buildMacLaunchdPlist,Je as buildSystemdUnit,bn as buildWindowsLauncherCommand,En as buildWindowsScheduledTaskCommands,In as buildWindowsScheduledTaskSuspendCommands,$n as buildWindowsScheduledTaskXml,An as buildWindowsStartupVbs,Ye as canReuseRunningDaemonForStart,Qn as captureEnvForService,Fn as clearDaemonLauncher,Un as clearDaemonPidIfOwner,Nn as clearRemoteAccessDisabled,Wn as createDaemonInstanceId,vn as ensureDaemonStarted,Mn as findRunningDaemonProcessIds,Tn as getCurrentProcessDaemonLauncher,Jn as getDaemonStatus,C as getLaunchdServiceTarget,Ge as getMacBackgroundItemNotice,v as getUnsupportedDaemonSourceError,xn as inferDaemonLauncherFromCommand,O as installService,T as isAutoStartServicePresent,Yn as isEphemeralCliPath,Vn as isIsolatedDaemonE2eInstance,jn as isRemoteAccessDisabled,Xn as isSafeSnapshotEnvKey,Ln as isShennianRunServiceCommand,Ne as prepareRemoteAccessPause,Hn as recordStartedDaemon,kn as registerDaemonCommand,Xe as reloadLaunchdAgent,oe as removeLegacyMacBackgroundApp,zn as resolveServiceLaunchSpec,Zn as saveEnvSnapshot,qn as shouldDiscoverGlobalDaemonProcesses,Gn as shouldInstallPlatformService,N as shouldReplaceRunningDaemon,j as startDaemonProcess,Te as stopPreparedRemoteAccessService,Rn as suspendWindowsScheduledTask,Bn as writeDaemonLauncher,On as writeDaemonPid};
46
+ `))}}async function nn(){switch(await U(),p()){case"darwin":{if(s.existsSync(S)){try{u(`launchctl unload -w "${S}"`,{stdio:"pipe",windowsHide:!0})}catch{}s.unlinkSync(S)}oe(),console.log(a.green("\u2713 Auto-start uninstalled (launchd)"));break}case"linux":{try{u("systemctl --user disable --now shennian",{stdio:"pipe",windowsHide:!0})}catch{}if(s.existsSync(y)){s.unlinkSync(y);try{u("systemctl --user daemon-reload",{stdio:"pipe",windowsHide:!0})}catch{}}console.log(a.green("\u2713 Auto-start uninstalled (systemd)"));break}case"win32":{re();try{s.unlinkSync(E)}catch{}try{s.unlinkSync(I)}catch{}try{s.unlinkSync($)}catch{}te(),console.log(a.green("\u2713 Auto-start uninstalled (Task Scheduler)"));break}}}function kn(e){e.command("start").description("Start the background service").option("--json","Print machine-readable status JSON").option("--api <url>","Server URL override").action(t=>ae(t)),e.command("stop").description("Stop the background service").option("--json","Print machine-readable status JSON").action(t=>U(t)),e.command("status").description("Show background service status").option("--json","Print machine-readable status JSON").action(t=>ce(t)),e.command("logs").description("Show recent logs").option("-n, --lines <n>","Number of lines","50").action(t=>ue({lines:parseInt(t.lines,10)}));const n=e.command("daemon",{hidden:!0}).description("Deprecated: use top-level start/stop/status/logs"),r=(t,o)=>{o||console.error(a.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),ae(t)}),n.command("stop").description("Stop the background service").option("--json","Print machine-readable status JSON").action(async t=>{r("stop",t.json),await U(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),en(t)}),n.command("status").description("Show background service status").option("--json","Print machine-readable status JSON").action(t=>{r("status",t.json),ce(t)}),n.command("logs").description("Show recent logs").option("-n, --lines <n>","Number of lines","50").action(t=>{r("logs"),ue({lines:parseInt(t.lines,10)})}),n.command("uninstall").description("Uninstall auto-start service").action(nn)}export{He as buildDaemonSpawnOptions,qe as buildMacLaunchdPlist,Je as buildSystemdUnit,bn as buildWindowsLauncherCommand,En as buildWindowsScheduledTaskCommands,In as buildWindowsScheduledTaskSuspendCommands,$n as buildWindowsScheduledTaskXml,An as buildWindowsStartupVbs,Ye as canReuseRunningDaemonForStart,Qn as captureEnvForService,Fn as clearDaemonLauncher,Un as clearDaemonPidIfOwner,Nn as clearRemoteAccessDisabled,Wn as createDaemonInstanceId,vn as ensureDaemonStarted,Mn as findRunningDaemonProcessIds,Tn as getCurrentProcessDaemonLauncher,Jn as getDaemonStatus,C as getLaunchdServiceTarget,Ge as getMacBackgroundItemNotice,v as getUnsupportedDaemonSourceError,xn as inferDaemonLauncherFromCommand,O as installService,T as isAutoStartServicePresent,Yn as isEphemeralCliPath,Vn as isIsolatedDaemonE2eInstance,jn as isRemoteAccessDisabled,Xn as isSafeSnapshotEnvKey,Ln as isShennianRunServiceCommand,Ne as prepareRemoteAccessPause,Hn as recordStartedDaemon,kn as registerDaemonCommand,Xe as reloadLaunchdAgent,oe as removeLegacyMacBackgroundApp,zn as resolveServiceLaunchSpec,Zn as saveEnvSnapshot,qn as shouldDiscoverGlobalDaemonProcesses,Gn as shouldInstallPlatformService,N as shouldReplaceRunningDaemon,j as startDaemonProcess,Te as stopPreparedRemoteAccessService,Rn as suspendWindowsScheduledTask,Bn as writeDaemonLauncher,On as writeDaemonPid};
package/dist/src/index.js CHANGED
@@ -1,3 +1,3 @@
1
- import{registerScheduleCommand as be}from"./commands/schedule.js";import{resolvePersonalScheduleContext as Ae}from"./schedules/personal-context.js";import{executeServerSchedule as ae,deliverServerSchedule as Pe}from"./schedules/server-client.js";import{Command as Ee}from"commander";import T from"chalk";import Te from"node:os";import{randomUUID as Ue}from"node:crypto";import J from"node:fs";import{loadConfig as p,saveConfig as De,getConfigPath as Me,getShennianDir as _e,resolveShennianPath as K,normalizeAutoUpgradePolicy as Ne}from"./config/index.js";import{CliRelayClient as xe}from"./relay/client.js";import{collectKnownLogSecrets as ie,installCliLogRedaction as Oe,sanitizeCliLogValue as $e}from"./log-redaction.js";import{registerPairCommand as Le,runSmartStart as Ve}from"./commands/pair.js";import{registerLogoutCommand as je}from"./commands/logout.js";import{clearDaemonPidIfOwner as se,createDaemonInstanceId as Fe,clearDaemonLauncher as ce,findRunningDaemonProcessIds as He,isRemoteAccessDisabled as de,prepareRemoteAccessPause as Be,stopPreparedRemoteAccessService as We,isIsolatedDaemonE2eInstance as Ge,getDaemonStatus as le,registerDaemonCommand as qe,writeDaemonPid as me,writeDaemonLauncher as pe}from"./commands/daemon.js";import{registerRuntimeCommand as ze}from"./commands/runtime.js";import{registerAdapterCommand as Je}from"./commands/adapter.js";import{registerAgentCommand as Ke}from"./commands/agent.js";import{registerManagerCommand as Qe}from"./commands/manager.js";import{registerWorkerCommand as Ye}from"./commands/worker.js";import{registerProjectCommand as Ze}from"./commands/project.js";import{registerStewardCommand as Xe}from"./commands/steward.js";import{handleUpgradeStart as eo,registerUpgradeCommand as oo}from"./commands/upgrade.js";import{registerToolsCommand as no}from"./commands/tools.js";import{registerQueueCommand as to}from"./commands/queue.js";import{registerSkillCommand as ro}from"./commands/skill.js";import{refreshExistingSkillForHosts as ao}from"./skill/hosts.js";import{registerSetupCommand as io}from"./commands/setup.js";import{getUnavailableAcpAgents as so}from"./agents/acp/discovery.js";import{registerCommandReference as co}from"./commands/command-reference.js";import{registerIntegrationCommand as lo}from"./commands/integration.js";import{registerRoomCommand as mo}from"./commands/room.js";import{registerContactCommand as po}from"./commands/contact.js";import{registerSupportCommand as go}from"./commands/support.js";import{SessionManager as uo}from"./session/manager.js";import{createTrustedProjectFsRequestResolver as fo}from"./session/handlers/project-fs.js";import{SERVERS as Q,regionToUrl as ho,urlToRegion as vo}from"./region.js";import{clearUpgradeAttempt as Io,getCurrentVersion as ge,handleStartupCrashCheck as So,readUpgradeAttempt as yo}from"./upgrade/engine.js";import{AutoUpgradeScheduler as wo}from"./upgrade/scheduler.js";import{ensureUpdaterInstalled as Co}from"./upgrade/updater-bootstrap.js";import{launchUpdater as ko,markUpdaterHealthy as Ro}from"./upgrade/updater-launcher.js";import{detectAgents as ue}from"./agents/detect.js";import{PublicAgentDeliveryWorker as bo}from"./agents/public-delivery-worker.js";import{augmentProcessPath as fe}from"./env-path.js";import{acquireDaemonInstanceLock as Ao}from"./commands/daemon-instance-lock.js";fe();const U=ge();import{getCachedAgentInfos as V,resolveAgentInfos as Po}from"./agents/model-registry.js";import{initCliLogReporter as Eo,reportLog as D,reportUpgradeAggregateMetric as To}from"./log-reporter.js";import{isNativeFusionEnabled as Uo}from"./native-fusion/config.js";import{NativeSessionFusionService as Do}from"./native-fusion/service.js";import{startDaemonLogRetention as Mo}from"./daemon-log.js";import{startDaemonIpcServer as he}from"./daemon-ipc/server.js";import{resolveDaemonIpcPaths as _o,resolveManagedRoomIpcPaths as No}from"./daemon-ipc/paths.js";import{createDaemonControlHandlers as xo}from"./daemon-ipc/control.js";import{createAgentReadinessHandlers as Oo}from"./daemon-ipc/agent-readiness.js";import{scanMachineAgents as ve}from"./session/handlers/agents.js";import{validateAgentWorkspaceConfiguration as $o}from"./session/handlers/agent-workspace-validation.js";import{DAEMON_IPC_VERSION as Lo}from"./daemon-ipc/protocol.js";import{RoomSessionRegistry as Vo}from"./room/session-registry.js";import{HttpRoomBindingClient as jo}from"./room/room-binding-client.js";import{TrustedManagedRoomBinder as Fo}from"./room/managed-room-binding.js";import{RoomHostSessionObservationStore as Ho}from"./room/host-session-observations.js";import{RoomMirrorSyncService as Bo}from"./room/mirror-sync-service.js";import{handleLiveRoomDelivery as Wo}from"./room/live-delivery.js";import{NativeSourceDeletionStore as Go}from"./native-fusion/native-source-deletions.js";import{matchesRoomOwner as qo,isCurrentRegistration as zo}from"./room/registration-authority.js";import{RoomActivationService as Jo,resolveManagedAgentPolicy as Ko}from"./room/activation-service.js";import{RoomActivationAudit as Qo}from"./room/activation-audit.js";import{RoomAttachmentCache as Yo}from"./room/attachment-cache.js";import{RoomAttachmentUploader as Zo}from"./room/attachment-upload.js";import{ManagedRoomContextAuthority as Xo}from"./room/managed-context.js";import{createManagedRoomExecutor as en}from"./room/managed-room-ipc.js";import{SESSION_SYNC_PROTOCOL_VERSION as Ie,SESSION_SYNC_ADVERTISED_CAPABILITIES as Se}from"@shennian/wire";import{getDaemonInstallationId as on}from"./session/store.js";import{OWNER_DIRECT_TURN_OPTIONS as nn}from"./session/queue-helpers.js";import{synchronizeMachinePersonalAuthority as tn}from"./personal-sync/machine-authority.js";import{CLI_SESSION_SYNC_DATA_EPOCH as ye,ensurePersonalDataEpoch as rn}from"./personal-sync/epoch.js";import{DeletionSyncRetryWaitError as an,DeletionSyncTerminalError as sn}from"./session/deletion-sync-state.js";const we=_e(),cn=K("daemon.pid"),dn=K("daemon.instance.lock");function ln(){try{const i=J.readFileSync(cn,"utf-8").trim();if(i.startsWith("{")){const g=JSON.parse(i),d=Number(g.pid);return Number.isInteger(d)&&d>0?d:null}const c=parseInt(i,10);return Number.isInteger(c)&&c>0?c:null}catch{return null}}function mn(i){return i.replace(/^https:\/\//,"wss://").replace(/^http:\/\//,"ws://")}function Y(){process.stdout.write(`${JSON.stringify({ok:!1,error:"integration_command_retired",message:"Room MCP and Hooks were retired. Use the Shennian Skill and CLI.",nextAction:{type:"open_install_guide",url:"https://shennian.net/install.md"}})}
2
- `),process.exitCode=1}function pn(i){const c=[`trigger=${i.trigger??"unknown"}`,`phase=${i.phase}`,`code=${i.code??"unknown"}`,`attempt=${i.reconnectAttempt}`];return i.reason&&c.push(`reason=${i.reason}`),i.error&&c.push(`error=${i.error}`),c.join(" ")}const a=new Ee;a.name("shennian").description("Shennian \u2014 AI Agent Control Plane").version(U),a.enablePositionalOptions(),lo(a),mo(a),po(a),go(a),be(a),a.option("--api <url>","Server URL override").option("--name <name>","Machine name",Te.hostname()).action(async i=>{const c=p(),g=i.api??process.env.SHENNIAN_DESKTOP_SERVER_URL??c.serverUrl??void 0;await Ve(g,i.name)}),a.command("run-service",{hidden:!0}).description("(internal) Connect to relay server, called by the background service").option("--api <url>","Server URL override").action(async i=>{const c=K("env.json");try{const e=JSON.parse(J.readFileSync(c,"utf-8"));for(const[n,o]of Object.entries(e))process.env[n]||(process.env[n]=o);fe()}catch{}Oe(ie(process.env,p()));const g=Mo();de()&&(console.log(`[${new Date().toISOString()}] remote access disabled, service start skipped`),clearInterval(g),process.exit(0));const d=Fe(),C=Ao({lockPath:dn,instanceId:d});C.acquired||(console.log(`[${new Date().toISOString()}] daemon already running`+(C.ownerPid?` (PID ${C.ownerPid})`:"")+", skipping duplicate start"),clearInterval(g),process.exit(0));try{const e=ln();if(e&&e!==process.pid)try{process.kill(e,0),console.log(`[${new Date().toISOString()}] daemon already running (PID ${e}), skipping duplicate start`),C.release(),process.exit(0)}catch{}}catch{}const Z=Ge(process.env,we)?[]:He(process.pid);Z.length>0&&(console.log(`[${new Date().toISOString()}] daemon already running (PID ${Z[0]}), skipping duplicate start`),C.release(),process.exit(0)),me(process.pid,d,{version:U}),pe(process.pid,void 0,d),process.on("exit",()=>{se(process.pid,d),ce(d)}),process.on("exit",C.release);let j=null;try{j=Co()}catch(e){console.error(`[upgrade] updater bootstrap unavailable: ${e instanceof Error?e.message:String(e)}`)}const M=await So();if(M){j||(console.error("[upgrade] Crash-loop rollback blocked: updater bootstrap unavailable"),process.exit(1));try{ko({fromVersion:U,targetVersion:M.from,oldDaemonPid:process.pid,operation:"rollback",rollbackJobId:M.jobId},{readiness:j}),console.error(`[upgrade] New version crashed ${M.attemptCount} times; external rollback scheduled.`),process.stdin.resume();return}catch(e){console.error(`[upgrade] Crash-loop rollback could not start: ${e instanceof Error?e.message:String(e)}`),process.exit(1)}}try{rn()}catch(e){console.error(`[personal-sync] data epoch initialization failed: ${e instanceof Error?e.message:String(e)}`),process.exitCode=1;return}const m=p(),u=i.api??process.env.SHENNIAN_DESKTOP_SERVER_URL??m.serverUrl??Q.cn.url,h=ge(),l=await ue({serverUrl:u,authToken:m.machineToken??m.accessToken}),S=l.map(e=>e.type);let F=V(l);const v=new Vo,_=new Ho,R=new Xo(v),y=new jo(u),ke=new Yo({actionClient:y}),Re=new Zo({actionClient:y});let w=null,r;const X=en({authority:R,actionClient:y,attachmentCache:ke,attachmentUploader:Re,observations:_,getMachineCredentials:()=>({machineToken:p().machineToken}),managerExecutor:e=>r.executeManagedManagerAction(e),onSendOutcome:e=>r.noteManagedRoomSendOutcome(e),getActiveRunId:(e,n)=>r.getManagedRoomActiveRunId(e,n),scheduleExecutor:(e,n,o)=>ae({serverUrl:u,machineToken:p().machineToken,sessionId:e,action:n,args:o}),onPaused:({registryKey:e,sessionId:n})=>{const t=v.getByRegistryKey(e)?.binding;t&&v.setBinding({registryKey:e,bindingId:t.bindingId,roomId:t.roomId,agentIdentityId:t.agentIdentityId,agentMembershipId:t.agentMembershipId,status:"paused",activationMode:"paused"}),R.revokeSession(e),r?.discardPendingManagedRoomMessages(n)}});let H=null,B=null,W=null,G=null,ee=!1;const b=await he({paths:_o(),handlers:{...xo({daemonVersion:h,protocolVersion:Lo,getStatus:()=>le(),getAgents:()=>l,requestShutdown:()=>{G?G():ee=!0},completeAgentAuthentication:e=>r.resumePendingAcpAuthentication(e),bindManagedRoom:e=>r.bindManagedRoomFromLocal(e),stewardSay:e=>r.stewardSayFromLocal(e),startUpgrade:async e=>{if(!H)throw new Error("upgrade_unavailable");return H(e)},prepareExternalUpgrade:e=>{if(!B)throw new Error("external_upgrade_unavailable");return B(e)},cancelExternalUpgrade:()=>{if(!W)throw new Error("external_upgrade_unavailable");return W()}}),...Oo({getStatus:()=>le(),getSnapshot:()=>V(l).map(e=>{const n=l.find(o=>o.type===e.type);return{...e,runtimePlatform:n?.runtimePlatform,runtimeIsWsl:n?.runtimeIsWsl}}),getUnavailable:so,discover:async e=>{if(!r)throw new Error("daemon_starting");const n=await ve(!0,e);if(e){const t=l.filter(f=>f.type!==e);l.splice(0,l.length,...t,...n.detectedAgents)}else l.splice(0,l.length,...n.detectedAgents);const o=V(l);return s.sendEvent({type:"event",event:"machine.agents",payload:{agentList:l.map(t=>t.type),agents:o}}),n.agents.map(t=>{const f=n.detectedAgents.find(z=>z.type===t.type);return{...t,runtimePlatform:f?.runtimePlatform,runtimeIsWsl:f?.runtimeIsWsl}})},validate:async e=>{if(!r)throw new Error("daemon_starting");return $o(e,{ignoreNativeSession:(n,o)=>P?.ignoreNativeSource(n,o)})}})}});let A;try{A=await he({paths:No(),handlers:{"managed-room.execute":e=>X(e),"schedule.personal":async e=>{const n=e,o=Ae(n?.context);if(v.getByNianSessionId(o)?.binding)throw new Error("schedule_personal_context_required");return await ae({serverUrl:u,machineToken:p().machineToken,sessionId:o,action:n.operation,args:n})}}})}catch(e){throw await b.close(),e}let oe=!1;const N=()=>{oe||(oe=!0,Promise.allSettled([b.close(),A.close()]).finally(()=>process.exit(0)))};if(process.once("SIGINT",N),process.once("SIGTERM",N),!m.machineToken){console.error('Shennian CLI is not paired. Run "shennian pair --browser" or "shennian pair --token" first.'),await Promise.allSettled([b.close(),A.close()]),process.exitCode=1;return}process.removeListener("SIGINT",N),process.removeListener("SIGTERM",N);const ne=`${mn(u)}/relay/machine`,x=m.machineToken;if(!x)return;try{await tn({serverUrl:u,machineToken:x,machineId:m.machineId})}catch(e){console.error(`[personal-sync] machine authority verification failed: ${e instanceof Error?e.message:String(e)}`),await Promise.allSettled([b.close(),A.close()]),process.exit(1)}m.machineId&&Eo(u,m.machineId),console.log(`[${new Date().toISOString()}] Connecting to ${ne}... (v${h}) agents: ${S.join(",")}`),D({level:"info",wsEvent:"daemon.start",metadata:{version:h,agents:S}});let P=null,E=null,k=0,q=!1,I=yo();const te=Ne(m.autoUpgrade),O=m.machineId?new bo({serverUrl:u,machineId:m.machineId,getMachineToken:()=>p().machineToken,getDetectedAgents:()=>ue({serverUrl:u,authToken:p().machineToken}),onRuntimeChanged:async()=>{const e=k,n=await ve(!0);if(l.splice(0,l.length,...n.detectedAgents),S.splice(0,S.length,...n.agentList),F=n.agents,!(await s.sendReq({type:"req",id:Ue(),method:"machine.agents.report",params:{agents:n.agents}},2e4)).ok)throw new Error("machine_capability_report_rejected");e===k&&s.getState()==="connected"&&O?.start()},onError:()=>console.warn("[public-agent] delivery attempt failed")}):null,s=new xe({serverUrl:ne,machineToken:x,cliVersion:h,agentList:S,autoUpgradePolicy:te,sessionSyncProtocolVersion:Ie,sessionSyncCapabilities:Se,daemonInstallationId:on(),dataEpoch:ye,updaterProtocolVersion:1,onConnected:()=>{console.log(`[${new Date().toISOString()}] \u2713 Connected`),D({level:"info",wsEvent:"daemon.connected"}),s.sendEvent({type:"event",event:"machine.agents",payload:{agentList:S,agents:F}}),Po(l,{serverUrl:m.serverUrl??u,authToken:m.machineToken??m.accessToken}).then(o=>{JSON.stringify(o)!==JSON.stringify(F)&&s.sendEvent({type:"event",event:"machine.agents",payload:{agentList:S,agents:o}})}).catch(()=>{}),I&&s.sendEvent({type:"event",event:"upgrade",payload:{state:"recovering",machineId:"self",from:I.from,to:I.to,...I.jobId?{jobId:I.jobId}:{},activeRunCount:r.getPendingRecoveryCount()}}),$.start(),E?.start();const e=++k,n=async()=>{try{if(await r.synchronizeSessionDeletions(),await r.recoverInterruptedRuns(),I){const o=I;I=null,o.jobId&&Ro(o.jobId,o.to),Io(),console.log(`[${new Date().toISOString()}] [upgrade] ${o.operation==="rollback"?"Rolled back":"Healthy"}: ${o.from} \u2192 ${o.to}`),To({kind:"upgrade",result:o.operation==="rollback"?"rolled_back":"healthy",stage:"terminal"}),s.sendEvent({type:"event",event:"upgrade",payload:{state:o.operation==="rollback"?"rolled_back":"healthy",machineId:"self",from:o.from,to:o.to,...o.jobId?{jobId:o.jobId}:{}}}),o.operation!=="rollback"&&s.sendEvent({type:"event",event:"upgrade",payload:{state:"success",machineId:"self",from:o.from,to:o.to}})}q||(q=!0,ao({clientVersion:h}).then(o=>{const t=o.filter(f=>!f.ok||!["current","registered","updated"].includes(f.result.status));t.length>0&&console.warn(`[skill] ${t.length} installed Skill copies need attention; run shennian setup for details`)}).catch(()=>console.warn("[skill] Official Skill refresh failed; Client remains available")).finally(()=>{q=!1})),e===k&&s.getState()==="connected"&&(P?.handleConnected(),O?.start())}catch(o){if(console.error("[session.deletions] startup catch-up failed",o),e===k&&s.getState()==="connected"){if(o instanceof sn)return;const t=o instanceof an?Math.max(1e3,o.retryAfterMs):5e3;setTimeout(()=>{n()},t).unref?.()}}};n()},onDisconnected:e=>{k+=1,r?.revokeProjectFsHandles(),O?.stop(),E?.stop(),console.log(`[${new Date().toISOString()}] \u26A0 Disconnected, reconnecting... ${pn(e)}`),D({level:"warn",wsEvent:"daemon.disconnected",metadata:{code:e.code,reason:e.reason,error:e.error,phase:e.phase,trigger:e.trigger,reconnectAttempt:e.reconnectAttempt}})},onProjectFsCapabilityChanged:e=>{e||r?.revokeProjectFsHandles()},onReq:e=>{if(console.log(`[${new Date().toISOString()}] [req] ${e.method}`),D({level:"info",type:"ws",wsEvent:e.method,wsDirection:"in",traceId:e.traceId}),e.method==="room.message.deliver"){Wo(s,E,e);return}r.handleReq(e)}});P=Uo()?new Do(s):null,E=new Bo({registry:v,observations:_,actionClient:y,getMachineCredentials:()=>({machineToken:p().machineToken}),isSessionDeleted:e=>new Go().hasSession(e),onMessages:async(e,n,o,t)=>{await w?.processMessages(e,n,o,t)},onBindingPaused:e=>{e.lifecycleState==="closed"?(R.revokeSession(e.registryKey),r?.retireManagedRoomSession(e.nianSessionId).catch(()=>{console.warn("[room.sync] retired session cleanup failed")})):r?.discardPendingManagedRoomMessages(e.nianSessionId)}});const $=new wo({currentVersion:h,machineId:m.machineId??"unknown-machine",serverUrl:m.serverUrl??u,getIdleState:()=>r.getUpgradeIdleState(),sessionSyncProtocolVersion:Ie,dataEpoch:ye,advertisedCapabilities:Se,updaterProtocolVersion:1,startUpgrade:async(e,n)=>{const{handleUpgradeStart:o}=await import("./commands/upgrade.js");await o(s,"auto-upgrade",e,{currentVersion:h,prepareForUpgrade:t=>r.prepareForUpgrade(t),cancelUpgradePreparation:()=>r.cancelUpgradePreparation(),shutdownAfterHandoff:()=>{setTimeout(()=>process.kill(process.pid,"SIGTERM"),100).unref?.()},suppressResponse:!0,waitForCompletion:!0,canHandoff:n?void 0:()=>r.getUpgradeIdleState().idle})}});$.setPolicy(te),r=new uo(s,P,h,$,new Fo({registry:v,observations:_,bindingClient:y,getMachineCredentials:()=>{const e=p();return{machineId:e.machineId,machineToken:e.machineToken}},hostProcessIdentity:()=>`daemon:${d}`}),{prepare:()=>Be(),isDisabled:()=>de(),shutdownAfterResponse:()=>{setTimeout(()=>{We(),process.kill(process.pid,"SIGTERM")},100).unref?.()}},e=>R.revokeToken(e),X,null,fo(x),()=>V(l)),H=async e=>{const n=e&&typeof e=="object"&&!Array.isArray(e)?e:{},o=typeof n.targetVersion=="string"?n.targetVersion:void 0,t=n.confirmedMajor===!0;return await eo(s,`local-upgrade-${Date.now()}`,o,{currentVersion:h,confirmedMajor:t,prepareForUpgrade:z=>r.prepareForUpgrade(z),cancelUpgradePreparation:()=>r.cancelUpgradePreparation(),shutdownAfterHandoff:()=>{setTimeout(()=>process.kill(process.pid,"SIGTERM"),100).unref?.()},suppressResponse:!0})},B=e=>{const n=e&&typeof e=="object"&&!Array.isArray(e)?e:{},t=`desktop-${(typeof n.targetVersion=="string"?n.targetVersion:"unknown").replace(/[^A-Za-z0-9._-]/g,"_")}-${Date.now()}`;return{jobId:t,...r.prepareForUpgrade(t)}},W=()=>(r.cancelUpgradePreparation(),{cancelled:!0}),w=new Jo({registry:v,observations:_,enqueueConversationBatch:e=>r.enqueueManagedRoomBatch(e),loadContext:async e=>{const n=p().machineToken?.trim(),o=e.binding;if(!n||!o)throw new Error("managed_room_context_unavailable");const t=await y.status({machineToken:n,roomId:o.roomId,bindingId:o.bindingId});if(!zo(v,e)||!qo(e,t))throw new Error("managed_room_binding_unavailable");return{roomName:t.room.name,memberCount:t.room.memberCount,members:t.room.members,agentsByIdentityId:t.agent?{[t.agentIdentityId]:t.agent}:{},effectiveModelsBySessionId:t.effectiveModelId!==void 0?{[e.nianSessionId]:t.effectiveModelId}:void 0,agentSystemPromptsByIdentityId:t.agent?{[t.agentIdentityId]:t.agent.systemPrompt??""}:{}}},issueManagedRoomContext:(e,n,o,t)=>{const f=p().machineToken;if(!f)throw new Error("machine_not_authorized");return R.issue({registryKey:e,machineCredential:f,activationCauseMessageId:n,allowedActions:o,propagateWorkerRoomOrigin:t})},audit:new Qo,resolveManagedAgentPolicy:e=>Ko({...e,runtime:l.find(n=>n.type===e.registration.runtimeAdapter)})}),r.scheduleHandler=e=>Pe({serverUrl:u,machineToken:p().machineToken,req:e,client:s,queue:r.getScheduleQueue(),registry:v}),r.getScheduleQueue().validateScheduledTarget=async e=>{if(!e.bindingId||!e.roomId)return"ready";if(v.getByNianSessionId(e.sessionId)?.binding?.bindingId!==e.bindingId)return"ended";const o=await y.status({machineToken:p().machineToken,roomId:e.roomId,bindingId:e.bindingId});return o.status==="active"&&o.room.status==="active"?"ready":"ended"},r.setManagedRoomTurnPreparer(e=>w.prepareConversationTurn(e)),r.setManagedAgentDirectTurnPreparer((e,n)=>w.prepareDirectConversationTurn(e,n)),r.setManagedRecoveryPreparer(async e=>e.source==="managed_direct"?w.prepareDirectConversationTurn(e.sessionId,nn):e.source==="manager_event"?w.prepareDirectConversationTurn(e.sessionId,{allowedRoomActions:[],managerEvent:!0}):e.source!=="managed_room"||!e.roomContextRegistryKey||!e.activationCauseMessageId||!e.rootCauseMessageId||!e.activationSequence||e.activationHopCount===null?null:w.prepareConversationTurn([{registryKey:e.roomContextRegistryKey,causeMessageId:e.activationCauseMessageId,rootCauseMessageId:e.rootCauseMessageId,sequence:e.activationSequence,hopCount:e.activationHopCount}])),J.mkdirSync(we,{recursive:!0}),me(process.pid,d,{version:h}),pe(process.pid,void 0,d),s.connect(),process.stdin.resume();let re=!1;const L=async()=>{if(!re){re=!0,console.log(T.gray(`
3
- Disconnecting...`)),D({level:"info",wsEvent:"daemon.stop"}),clearInterval(g),O?.stop();try{await r.cleanup(),$.stop(),P?.stop(),E?.stop(),s.disconnect(),await Promise.allSettled([b.close(),A.close()]),se(process.pid,d),ce(d)}finally{process.exit(0)}}};G=L,ee&&L(),process.on("SIGINT",()=>{L()}),process.on("SIGTERM",()=>{L()})}),a.command("workbuddy-session-hook",{hidden:!0}).description("(retired) WorkBuddy Room Hook").allowUnknownOption(!0).action(()=>Y()),a.command("room-session-hook",{hidden:!0}).description("(internal) Authorize the official Room tool for one trusted Agent Session").argument("<runtime>","Trusted runtime adapter").allowUnknownOption(!0).action(()=>Y()),a.command("room-tool-server",{hidden:!0}).description("(internal) Run the official Shennian Room MCP tool").allowUnknownOption(!0).action(()=>Y());const Ce=a.command("config").description("View or modify configuration");Ce.command("show",{isDefault:!0}).description("Show current configuration").action(()=>{console.log(`Config file: ${Me()}`);const i=p(),c=$e(i,ie(process.env,i));if(i.serverUrl){const g=vo(i.serverUrl);console.log(`Region: ${g} (${Q[g].label})`)}console.log(JSON.stringify(c,null,2))}),Ce.command("set").description("Update a config value").argument("<key>",'Config key (e.g. "server")').argument("<value>",'Config value (e.g. "cn" or "global")').action((i,c)=>{const g=p();if(i==="server"){c!=="cn"&&c!=="global"&&(console.error(T.red('\u2717 Value must be "cn" or "global"')),process.exit(1));const d=c;g.serverUrl=ho(d),De(g),console.log(T.green(`\u2713 Server set to ${Q[d].label}`)),console.log(T.yellow(" Restart the background service for this to take effect: shennian stop && shennian start"));return}console.error(T.red(`\u2717 Unknown config key: ${i}. Supported: server`)),process.exit(1)}),io(a),Le(a),je(a),qe(a),ze(a),Je(a,{clientVersion:U}),Ke(a),Qe(a),Ye(a),Ze(a),Xe(a),oo(a),no(a),to(a),ro(a),co(a,U),a.parse();
1
+ import{registerScheduleCommand as be}from"./commands/schedule.js";import{resolvePersonalScheduleContext as Ae}from"./schedules/personal-context.js";import{isStewardSessionId as Pe}from"./steward/session.js";import{executeServerSchedule as ae,deliverServerSchedule as Ee}from"./schedules/server-client.js";import{Command as Te}from"commander";import T from"chalk";import Ue from"node:os";import{randomUUID as De}from"node:crypto";import J from"node:fs";import{loadConfig as p,saveConfig as Me,getConfigPath as _e,getShennianDir as Ne,resolveShennianPath as K,normalizeAutoUpgradePolicy as xe}from"./config/index.js";import{CliRelayClient as Oe}from"./relay/client.js";import{collectKnownLogSecrets as ie,installCliLogRedaction as $e,sanitizeCliLogValue as Le}from"./log-redaction.js";import{registerPairCommand as Ve,runSmartStart as je}from"./commands/pair.js";import{registerLogoutCommand as Fe}from"./commands/logout.js";import{clearDaemonPidIfOwner as se,createDaemonInstanceId as He,clearDaemonLauncher as ce,findRunningDaemonProcessIds as Be,isRemoteAccessDisabled as de,prepareRemoteAccessPause as We,stopPreparedRemoteAccessService as Ge,isIsolatedDaemonE2eInstance as qe,getDaemonStatus as le,registerDaemonCommand as ze,writeDaemonPid as me,writeDaemonLauncher as pe}from"./commands/daemon.js";import{registerRuntimeCommand as Je}from"./commands/runtime.js";import{registerAdapterCommand as Ke}from"./commands/adapter.js";import{registerAgentCommand as Qe}from"./commands/agent.js";import{registerManagerCommand as Ye}from"./commands/manager.js";import{registerWorkerCommand as Ze}from"./commands/worker.js";import{registerProjectCommand as Xe}from"./commands/project.js";import{registerStewardCommand as eo}from"./commands/steward.js";import{handleUpgradeStart as oo,registerUpgradeCommand as no}from"./commands/upgrade.js";import{registerToolsCommand as to}from"./commands/tools.js";import{registerQueueCommand as ro}from"./commands/queue.js";import{registerSkillCommand as ao}from"./commands/skill.js";import{refreshExistingSkillForHosts as io}from"./skill/hosts.js";import{registerSetupCommand as so}from"./commands/setup.js";import{getUnavailableAcpAgents as co}from"./agents/acp/discovery.js";import{registerCommandReference as lo}from"./commands/command-reference.js";import{registerIntegrationCommand as mo}from"./commands/integration.js";import{registerRoomCommand as po}from"./commands/room.js";import{registerContactCommand as go}from"./commands/contact.js";import{registerSupportCommand as uo}from"./commands/support.js";import{SessionManager as fo}from"./session/manager.js";import{createTrustedProjectFsRequestResolver as ho}from"./session/handlers/project-fs.js";import{SERVERS as Q,regionToUrl as vo,urlToRegion as Io}from"./region.js";import{clearUpgradeAttempt as So,getCurrentVersion as ge,handleStartupCrashCheck as yo,readUpgradeAttempt as wo}from"./upgrade/engine.js";import{AutoUpgradeScheduler as Co}from"./upgrade/scheduler.js";import{ensureUpdaterInstalled as ko}from"./upgrade/updater-bootstrap.js";import{launchUpdater as Ro,markUpdaterHealthy as bo}from"./upgrade/updater-launcher.js";import{detectAgents as ue}from"./agents/detect.js";import{PublicAgentDeliveryWorker as Ao}from"./agents/public-delivery-worker.js";import{augmentProcessPath as fe}from"./env-path.js";import{acquireDaemonInstanceLock as Po}from"./commands/daemon-instance-lock.js";fe();const U=ge();import{getCachedAgentInfos as V,resolveAgentInfos as Eo}from"./agents/model-registry.js";import{initCliLogReporter as To,reportLog as D,reportUpgradeAggregateMetric as Uo}from"./log-reporter.js";import{isNativeFusionEnabled as Do}from"./native-fusion/config.js";import{NativeSessionFusionService as Mo}from"./native-fusion/service.js";import{startDaemonLogRetention as _o}from"./daemon-log.js";import{startDaemonIpcServer as he}from"./daemon-ipc/server.js";import{resolveDaemonIpcPaths as No,resolveManagedRoomIpcPaths as xo}from"./daemon-ipc/paths.js";import{createDaemonControlHandlers as Oo}from"./daemon-ipc/control.js";import{createAgentReadinessHandlers as $o}from"./daemon-ipc/agent-readiness.js";import{scanMachineAgents as ve}from"./session/handlers/agents.js";import{validateAgentWorkspaceConfiguration as Lo}from"./session/handlers/agent-workspace-validation.js";import{DAEMON_IPC_VERSION as Vo}from"./daemon-ipc/protocol.js";import{RoomSessionRegistry as jo}from"./room/session-registry.js";import{HttpRoomBindingClient as Fo}from"./room/room-binding-client.js";import{TrustedManagedRoomBinder as Ho}from"./room/managed-room-binding.js";import{RoomHostSessionObservationStore as Bo}from"./room/host-session-observations.js";import{RoomMirrorSyncService as Wo}from"./room/mirror-sync-service.js";import{handleLiveRoomDelivery as Go}from"./room/live-delivery.js";import{NativeSourceDeletionStore as qo}from"./native-fusion/native-source-deletions.js";import{matchesRoomOwner as zo,isCurrentRegistration as Jo}from"./room/registration-authority.js";import{RoomActivationService as Ko,resolveManagedAgentPolicy as Qo}from"./room/activation-service.js";import{RoomActivationAudit as Yo}from"./room/activation-audit.js";import{RoomAttachmentCache as Zo}from"./room/attachment-cache.js";import{RoomAttachmentUploader as Xo}from"./room/attachment-upload.js";import{ManagedRoomContextAuthority as en}from"./room/managed-context.js";import{createManagedRoomExecutor as on}from"./room/managed-room-ipc.js";import{SESSION_SYNC_PROTOCOL_VERSION as Ie,SESSION_SYNC_ADVERTISED_CAPABILITIES as Se}from"@shennian/wire";import{getDaemonInstallationId as nn}from"./session/store.js";import{OWNER_DIRECT_TURN_OPTIONS as tn}from"./session/queue-helpers.js";import{synchronizeMachinePersonalAuthority as rn}from"./personal-sync/machine-authority.js";import{CLI_SESSION_SYNC_DATA_EPOCH as ye,ensurePersonalDataEpoch as an}from"./personal-sync/epoch.js";import{DeletionSyncRetryWaitError as sn,DeletionSyncTerminalError as cn}from"./session/deletion-sync-state.js";const we=Ne(),dn=K("daemon.pid"),ln=K("daemon.instance.lock");function mn(){try{const i=J.readFileSync(dn,"utf-8").trim();if(i.startsWith("{")){const g=JSON.parse(i),d=Number(g.pid);return Number.isInteger(d)&&d>0?d:null}const c=parseInt(i,10);return Number.isInteger(c)&&c>0?c:null}catch{return null}}function pn(i){return i.replace(/^https:\/\//,"wss://").replace(/^http:\/\//,"ws://")}function Y(){process.stdout.write(`${JSON.stringify({ok:!1,error:"integration_command_retired",message:"Room MCP and Hooks were retired. Use the Shennian Skill and CLI.",nextAction:{type:"open_install_guide",url:"https://shennian.net/install.md"}})}
2
+ `),process.exitCode=1}function gn(i){const c=[`trigger=${i.trigger??"unknown"}`,`phase=${i.phase}`,`code=${i.code??"unknown"}`,`attempt=${i.reconnectAttempt}`];return i.reason&&c.push(`reason=${i.reason}`),i.error&&c.push(`error=${i.error}`),c.join(" ")}const a=new Te;a.name("shennian").description("Shennian \u2014 AI Agent Control Plane").version(U),a.enablePositionalOptions(),mo(a),po(a),go(a),uo(a),be(a),a.option("--api <url>","Server URL override").option("--name <name>","Machine name",Ue.hostname()).action(async i=>{const c=p(),g=i.api??process.env.SHENNIAN_DESKTOP_SERVER_URL??c.serverUrl??void 0;await je(g,i.name)}),a.command("run-service",{hidden:!0}).description("(internal) Connect to relay server, called by the background service").option("--api <url>","Server URL override").action(async i=>{const c=K("env.json");try{const e=JSON.parse(J.readFileSync(c,"utf-8"));for(const[n,o]of Object.entries(e))process.env[n]||(process.env[n]=o);fe()}catch{}$e(ie(process.env,p()));const g=_o();de()&&(console.log(`[${new Date().toISOString()}] remote access disabled, service start skipped`),clearInterval(g),process.exit(0));const d=He(),C=Po({lockPath:ln,instanceId:d});C.acquired||(console.log(`[${new Date().toISOString()}] daemon already running`+(C.ownerPid?` (PID ${C.ownerPid})`:"")+", skipping duplicate start"),clearInterval(g),process.exit(0));try{const e=mn();if(e&&e!==process.pid)try{process.kill(e,0),console.log(`[${new Date().toISOString()}] daemon already running (PID ${e}), skipping duplicate start`),C.release(),process.exit(0)}catch{}}catch{}const Z=qe(process.env,we)?[]:Be(process.pid);Z.length>0&&(console.log(`[${new Date().toISOString()}] daemon already running (PID ${Z[0]}), skipping duplicate start`),C.release(),process.exit(0)),me(process.pid,d,{version:U}),pe(process.pid,void 0,d),process.on("exit",()=>{se(process.pid,d),ce(d)}),process.on("exit",C.release);let j=null;try{j=ko()}catch(e){console.error(`[upgrade] updater bootstrap unavailable: ${e instanceof Error?e.message:String(e)}`)}const M=await yo();if(M){j||(console.error("[upgrade] Crash-loop rollback blocked: updater bootstrap unavailable"),process.exit(1));try{Ro({fromVersion:U,targetVersion:M.from,oldDaemonPid:process.pid,operation:"rollback",rollbackJobId:M.jobId},{readiness:j}),console.error(`[upgrade] New version crashed ${M.attemptCount} times; external rollback scheduled.`),process.stdin.resume();return}catch(e){console.error(`[upgrade] Crash-loop rollback could not start: ${e instanceof Error?e.message:String(e)}`),process.exit(1)}}try{an()}catch(e){console.error(`[personal-sync] data epoch initialization failed: ${e instanceof Error?e.message:String(e)}`),process.exitCode=1;return}const m=p(),u=i.api??process.env.SHENNIAN_DESKTOP_SERVER_URL??m.serverUrl??Q.cn.url,h=ge(),l=await ue({serverUrl:u,authToken:m.machineToken??m.accessToken}),S=l.map(e=>e.type);let F=V(l);const v=new jo,_=new Bo,R=new en(v),y=new Fo(u),ke=new Zo({actionClient:y}),Re=new Xo({actionClient:y});let w=null,r;const X=on({authority:R,actionClient:y,attachmentCache:ke,attachmentUploader:Re,observations:_,getMachineCredentials:()=>({machineToken:p().machineToken}),managerExecutor:e=>r.executeManagedManagerAction(e),onSendOutcome:e=>r.noteManagedRoomSendOutcome(e),getActiveRunId:(e,n)=>r.getManagedRoomActiveRunId(e,n),scheduleExecutor:(e,n,o)=>ae({serverUrl:u,machineToken:p().machineToken,sessionId:e,action:n,args:o}),onPaused:({registryKey:e,sessionId:n})=>{const t=v.getByRegistryKey(e)?.binding;t&&v.setBinding({registryKey:e,bindingId:t.bindingId,roomId:t.roomId,agentIdentityId:t.agentIdentityId,agentMembershipId:t.agentMembershipId,status:"paused",activationMode:"paused"}),R.revokeSession(e),r?.discardPendingManagedRoomMessages(n)}});let H=null,B=null,W=null,G=null,ee=!1;const b=await he({paths:No(),handlers:{...Oo({daemonVersion:h,protocolVersion:Vo,getStatus:()=>le(),getAgents:()=>l,requestShutdown:()=>{G?G():ee=!0},completeAgentAuthentication:e=>r.resumePendingAcpAuthentication(e),bindManagedRoom:e=>r.bindManagedRoomFromLocal(e),stewardSay:e=>r.stewardSayFromLocal(e),startUpgrade:async e=>{if(!H)throw new Error("upgrade_unavailable");return H(e)},prepareExternalUpgrade:e=>{if(!B)throw new Error("external_upgrade_unavailable");return B(e)},cancelExternalUpgrade:()=>{if(!W)throw new Error("external_upgrade_unavailable");return W()}}),...$o({getStatus:()=>le(),getSnapshot:()=>V(l).map(e=>{const n=l.find(o=>o.type===e.type);return{...e,runtimePlatform:n?.runtimePlatform,runtimeIsWsl:n?.runtimeIsWsl}}),getUnavailable:co,discover:async e=>{if(!r)throw new Error("daemon_starting");const n=await ve(!0,e);if(e){const t=l.filter(f=>f.type!==e);l.splice(0,l.length,...t,...n.detectedAgents)}else l.splice(0,l.length,...n.detectedAgents);const o=V(l);return s.sendEvent({type:"event",event:"machine.agents",payload:{agentList:l.map(t=>t.type),agents:o}}),n.agents.map(t=>{const f=n.detectedAgents.find(z=>z.type===t.type);return{...t,runtimePlatform:f?.runtimePlatform,runtimeIsWsl:f?.runtimeIsWsl}})},validate:async e=>{if(!r)throw new Error("daemon_starting");return Lo(e,{ignoreNativeSession:(n,o)=>P?.ignoreNativeSource(n,o)})}})}});let A;try{A=await he({paths:xo(),handlers:{"managed-room.execute":e=>X(e),"schedule.personal":async e=>{const n=e,o=Ae(n?.context);if(v.getByNianSessionId(o)?.binding||!Pe(o))throw new Error("schedule_personal_context_required");return await ae({serverUrl:u,machineToken:p().machineToken,sessionId:o,action:n.operation,args:n})}}})}catch(e){throw await b.close(),e}let oe=!1;const N=()=>{oe||(oe=!0,Promise.allSettled([b.close(),A.close()]).finally(()=>process.exit(0)))};if(process.once("SIGINT",N),process.once("SIGTERM",N),!m.machineToken){console.error('Shennian CLI is not paired. Run "shennian pair --browser" or "shennian pair --token" first.'),await Promise.allSettled([b.close(),A.close()]),process.exitCode=1;return}process.removeListener("SIGINT",N),process.removeListener("SIGTERM",N);const ne=`${pn(u)}/relay/machine`,x=m.machineToken;if(!x)return;try{await rn({serverUrl:u,machineToken:x,machineId:m.machineId})}catch(e){console.error(`[personal-sync] machine authority verification failed: ${e instanceof Error?e.message:String(e)}`),await Promise.allSettled([b.close(),A.close()]),process.exit(1)}m.machineId&&To(u,m.machineId),console.log(`[${new Date().toISOString()}] Connecting to ${ne}... (v${h}) agents: ${S.join(",")}`),D({level:"info",wsEvent:"daemon.start",metadata:{version:h,agents:S}});let P=null,E=null,k=0,q=!1,I=wo();const te=xe(m.autoUpgrade),O=m.machineId?new Ao({serverUrl:u,machineId:m.machineId,getMachineToken:()=>p().machineToken,getDetectedAgents:()=>ue({serverUrl:u,authToken:p().machineToken}),onRuntimeChanged:async()=>{const e=k,n=await ve(!0);if(l.splice(0,l.length,...n.detectedAgents),S.splice(0,S.length,...n.agentList),F=n.agents,!(await s.sendReq({type:"req",id:De(),method:"machine.agents.report",params:{agents:n.agents}},2e4)).ok)throw new Error("machine_capability_report_rejected");e===k&&s.getState()==="connected"&&O?.start()},onError:()=>console.warn("[public-agent] delivery attempt failed")}):null,s=new Oe({serverUrl:ne,machineToken:x,cliVersion:h,agentList:S,autoUpgradePolicy:te,sessionSyncProtocolVersion:Ie,sessionSyncCapabilities:Se,daemonInstallationId:nn(),dataEpoch:ye,updaterProtocolVersion:1,onConnected:()=>{console.log(`[${new Date().toISOString()}] \u2713 Connected`),D({level:"info",wsEvent:"daemon.connected"}),s.sendEvent({type:"event",event:"machine.agents",payload:{agentList:S,agents:F}}),Eo(l,{serverUrl:m.serverUrl??u,authToken:m.machineToken??m.accessToken}).then(o=>{JSON.stringify(o)!==JSON.stringify(F)&&s.sendEvent({type:"event",event:"machine.agents",payload:{agentList:S,agents:o}})}).catch(()=>{}),I&&s.sendEvent({type:"event",event:"upgrade",payload:{state:"recovering",machineId:"self",from:I.from,to:I.to,...I.jobId?{jobId:I.jobId}:{},activeRunCount:r.getPendingRecoveryCount()}}),$.start(),E?.start();const e=++k,n=async()=>{try{if(await r.synchronizeSessionDeletions(),await r.recoverInterruptedRuns(),I){const o=I;I=null,o.jobId&&bo(o.jobId,o.to),So(),console.log(`[${new Date().toISOString()}] [upgrade] ${o.operation==="rollback"?"Rolled back":"Healthy"}: ${o.from} \u2192 ${o.to}`),Uo({kind:"upgrade",result:o.operation==="rollback"?"rolled_back":"healthy",stage:"terminal"}),s.sendEvent({type:"event",event:"upgrade",payload:{state:o.operation==="rollback"?"rolled_back":"healthy",machineId:"self",from:o.from,to:o.to,...o.jobId?{jobId:o.jobId}:{}}}),o.operation!=="rollback"&&s.sendEvent({type:"event",event:"upgrade",payload:{state:"success",machineId:"self",from:o.from,to:o.to}})}q||(q=!0,io({clientVersion:h}).then(o=>{const t=o.filter(f=>!f.ok||!["current","registered","updated"].includes(f.result.status));t.length>0&&console.warn(`[skill] ${t.length} installed Skill copies need attention; run shennian setup for details`)}).catch(()=>console.warn("[skill] Official Skill refresh failed; Client remains available")).finally(()=>{q=!1})),e===k&&s.getState()==="connected"&&(P?.handleConnected(),O?.start())}catch(o){if(console.error("[session.deletions] startup catch-up failed",o),e===k&&s.getState()==="connected"){if(o instanceof cn)return;const t=o instanceof sn?Math.max(1e3,o.retryAfterMs):5e3;setTimeout(()=>{n()},t).unref?.()}}};n()},onDisconnected:e=>{k+=1,r?.revokeProjectFsHandles(),O?.stop(),E?.stop(),console.log(`[${new Date().toISOString()}] \u26A0 Disconnected, reconnecting... ${gn(e)}`),D({level:"warn",wsEvent:"daemon.disconnected",metadata:{code:e.code,reason:e.reason,error:e.error,phase:e.phase,trigger:e.trigger,reconnectAttempt:e.reconnectAttempt}})},onProjectFsCapabilityChanged:e=>{e||r?.revokeProjectFsHandles()},onReq:e=>{if(console.log(`[${new Date().toISOString()}] [req] ${e.method}`),D({level:"info",type:"ws",wsEvent:e.method,wsDirection:"in",traceId:e.traceId}),e.method==="room.message.deliver"){Go(s,E,e);return}r.handleReq(e)}});P=Do()?new Mo(s):null,E=new Wo({registry:v,observations:_,actionClient:y,getMachineCredentials:()=>({machineToken:p().machineToken}),isSessionDeleted:e=>new qo().hasSession(e),onMessages:async(e,n,o,t)=>{await w?.processMessages(e,n,o,t)},onBindingPaused:e=>{e.lifecycleState==="closed"?(R.revokeSession(e.registryKey),r?.retireManagedRoomSession(e.nianSessionId).catch(()=>{console.warn("[room.sync] retired session cleanup failed")})):r?.discardPendingManagedRoomMessages(e.nianSessionId)}});const $=new Co({currentVersion:h,machineId:m.machineId??"unknown-machine",serverUrl:m.serverUrl??u,getIdleState:()=>r.getUpgradeIdleState(),sessionSyncProtocolVersion:Ie,dataEpoch:ye,advertisedCapabilities:Se,updaterProtocolVersion:1,startUpgrade:async(e,n)=>{const{handleUpgradeStart:o}=await import("./commands/upgrade.js");await o(s,"auto-upgrade",e,{currentVersion:h,prepareForUpgrade:t=>r.prepareForUpgrade(t),cancelUpgradePreparation:()=>r.cancelUpgradePreparation(),shutdownAfterHandoff:()=>{setTimeout(()=>process.kill(process.pid,"SIGTERM"),100).unref?.()},suppressResponse:!0,waitForCompletion:!0,canHandoff:n?void 0:()=>r.getUpgradeIdleState().idle})}});$.setPolicy(te),r=new fo(s,P,h,$,new Ho({registry:v,observations:_,bindingClient:y,getMachineCredentials:()=>{const e=p();return{machineId:e.machineId,machineToken:e.machineToken}},hostProcessIdentity:()=>`daemon:${d}`}),{prepare:()=>We(),isDisabled:()=>de(),shutdownAfterResponse:()=>{setTimeout(()=>{Ge(),process.kill(process.pid,"SIGTERM")},100).unref?.()}},e=>R.revokeToken(e),X,null,ho(x),()=>V(l)),H=async e=>{const n=e&&typeof e=="object"&&!Array.isArray(e)?e:{},o=typeof n.targetVersion=="string"?n.targetVersion:void 0,t=n.confirmedMajor===!0;return await oo(s,`local-upgrade-${Date.now()}`,o,{currentVersion:h,confirmedMajor:t,prepareForUpgrade:z=>r.prepareForUpgrade(z),cancelUpgradePreparation:()=>r.cancelUpgradePreparation(),shutdownAfterHandoff:()=>{setTimeout(()=>process.kill(process.pid,"SIGTERM"),100).unref?.()},suppressResponse:!0})},B=e=>{const n=e&&typeof e=="object"&&!Array.isArray(e)?e:{},t=`desktop-${(typeof n.targetVersion=="string"?n.targetVersion:"unknown").replace(/[^A-Za-z0-9._-]/g,"_")}-${Date.now()}`;return{jobId:t,...r.prepareForUpgrade(t)}},W=()=>(r.cancelUpgradePreparation(),{cancelled:!0}),w=new Ko({registry:v,observations:_,enqueueConversationBatch:e=>r.enqueueManagedRoomBatch(e),loadContext:async e=>{const n=p().machineToken?.trim(),o=e.binding;if(!n||!o)throw new Error("managed_room_context_unavailable");const t=await y.status({machineToken:n,roomId:o.roomId,bindingId:o.bindingId});if(!Jo(v,e)||!zo(e,t))throw new Error("managed_room_binding_unavailable");return{roomName:t.room.name,memberCount:t.room.memberCount,members:t.room.members,agentsByIdentityId:t.agent?{[t.agentIdentityId]:t.agent}:{},effectiveModelsBySessionId:t.effectiveModelId!==void 0?{[e.nianSessionId]:t.effectiveModelId}:void 0,agentSystemPromptsByIdentityId:t.agent?{[t.agentIdentityId]:t.agent.systemPrompt??""}:{}}},issueManagedRoomContext:(e,n,o,t)=>{const f=p().machineToken;if(!f)throw new Error("machine_not_authorized");return R.issue({registryKey:e,machineCredential:f,activationCauseMessageId:n,allowedActions:o,propagateWorkerRoomOrigin:t})},audit:new Yo,resolveManagedAgentPolicy:e=>Qo({...e,runtime:l.find(n=>n.type===e.registration.runtimeAdapter)})}),r.scheduleHandler=e=>Ee({serverUrl:u,machineToken:p().machineToken,req:e,client:s,queue:r.getScheduleQueue(),registry:v}),r.getScheduleQueue().validateScheduledTarget=async e=>{if(!e.bindingId||!e.roomId)return"ready";if(v.getByNianSessionId(e.sessionId)?.binding?.bindingId!==e.bindingId)return"ended";const o=await y.status({machineToken:p().machineToken,roomId:e.roomId,bindingId:e.bindingId});return o.status==="active"&&o.room.status==="active"?"ready":"ended"},r.setManagedRoomTurnPreparer(e=>w.prepareConversationTurn(e)),r.setManagedAgentDirectTurnPreparer((e,n)=>w.prepareDirectConversationTurn(e,n)),r.setManagedRecoveryPreparer(async e=>e.source==="managed_direct"?w.prepareDirectConversationTurn(e.sessionId,tn):e.source==="manager_event"?w.prepareDirectConversationTurn(e.sessionId,{allowedRoomActions:[],managerEvent:!0}):e.source!=="managed_room"||!e.roomContextRegistryKey||!e.activationCauseMessageId||!e.rootCauseMessageId||!e.activationSequence||e.activationHopCount===null?null:w.prepareConversationTurn([{registryKey:e.roomContextRegistryKey,causeMessageId:e.activationCauseMessageId,rootCauseMessageId:e.rootCauseMessageId,sequence:e.activationSequence,hopCount:e.activationHopCount}])),J.mkdirSync(we,{recursive:!0}),me(process.pid,d,{version:h}),pe(process.pid,void 0,d),s.connect(),process.stdin.resume();let re=!1;const L=async()=>{if(!re){re=!0,console.log(T.gray(`
3
+ Disconnecting...`)),D({level:"info",wsEvent:"daemon.stop"}),clearInterval(g),O?.stop();try{await r.cleanup(),$.stop(),P?.stop(),E?.stop(),s.disconnect(),await Promise.allSettled([b.close(),A.close()]),se(process.pid,d),ce(d)}finally{process.exit(0)}}};G=L,ee&&L(),process.on("SIGINT",()=>{L()}),process.on("SIGTERM",()=>{L()})}),a.command("workbuddy-session-hook",{hidden:!0}).description("(retired) WorkBuddy Room Hook").allowUnknownOption(!0).action(()=>Y()),a.command("room-session-hook",{hidden:!0}).description("(internal) Authorize the official Room tool for one trusted Agent Session").argument("<runtime>","Trusted runtime adapter").allowUnknownOption(!0).action(()=>Y()),a.command("room-tool-server",{hidden:!0}).description("(internal) Run the official Shennian Room MCP tool").allowUnknownOption(!0).action(()=>Y());const Ce=a.command("config").description("View or modify configuration");Ce.command("show",{isDefault:!0}).description("Show current configuration").action(()=>{console.log(`Config file: ${_e()}`);const i=p(),c=Le(i,ie(process.env,i));if(i.serverUrl){const g=Io(i.serverUrl);console.log(`Region: ${g} (${Q[g].label})`)}console.log(JSON.stringify(c,null,2))}),Ce.command("set").description("Update a config value").argument("<key>",'Config key (e.g. "server")').argument("<value>",'Config value (e.g. "cn" or "global")').action((i,c)=>{const g=p();if(i==="server"){c!=="cn"&&c!=="global"&&(console.error(T.red('\u2717 Value must be "cn" or "global"')),process.exit(1));const d=c;g.serverUrl=vo(d),Me(g),console.log(T.green(`\u2713 Server set to ${Q[d].label}`)),console.log(T.yellow(" Restart the background service for this to take effect: shennian stop && shennian start"));return}console.error(T.red(`\u2717 Unknown config key: ${i}. Supported: server`)),process.exit(1)}),so(a),Ve(a),Fe(a),ze(a),Je(a),Ke(a,{clientVersion:U}),Qe(a),Ye(a),Ze(a),Xe(a),eo(a),no(a),to(a),ro(a),ao(a),lo(a,U),a.parse();
@@ -1,14 +1,14 @@
1
- import{isAvailableBuiltinAgentType as k,managedAgentExecutionMode as P}from"@shennian/wire";import{getBuiltinAgentVersion as S,resolveBuiltinCommand as B}from"../agents/command-spec.js";import{registerCustomRuntimeSecurity as K,resolveCustomRuntimeExecutableFingerprint as $}from"../agents/custom-managed-runtime.js";import{loadConfig as x}from"../config/index.js";import{resolveManagedAgentExecutableIdentity as W}from"../security/managed-agent-executable.js";import{compileManagedAgentPolicy as T}from"../security/managed-agent-policy.js";import{resolveManagedAgentRuntimeProtection as R}from"../security/managed-agent-runtime.js";import{selectRoomActivationTargets as q}from"./activation-policy.js";import{buildManagedAgentPermissionPrompt as E,composeManagedRoomPrompt as D}from"./managed-prompt-composer.js";import{isCurrentRegistration as f}from"./registration-authority.js";const N=4,O=6e4,F=6,V=5*6e4;class ce{deps;latestContexts=new Map;constructor(e){this.deps=e}async processMessages(e,o,t,a={roomName:"\u5F53\u524D\u7FA4\u804A"}){const d=[],m=[],c=new Map,u=new Set,g=[...o].sort((i,s)=>J(i.sequence,s.sequence));for(const i of t){const s=this.deps.registry.getByRegistryKey(i.registryKey);!s?.binding||!f(this.deps.registry,i)||s.binding.roomId!==e||s.binding.status!=="active"&&s.binding.status!=="paused"&&s.binding.activationQueue.length}for(const i of t){const s=this.deps.registry.getByRegistryKey(i.registryKey);if(!s?.binding||!f(this.deps.registry,i)||s.binding.roomId!==e||s.binding.activationQueue.length===0&&!s.binding.activeActivation||(u.add(s.registryKey),s.binding.status!=="active"||s.binding.activationMode==="paused")||s.binding.activationQueue.length===0)continue;const l=this.deps.observations.getBySource(s);if(!l?.workspacePath||l.lifecycleState==="closed")throw new Error("managed_room_workspace_unavailable");this.latestContexts.set(s.registryKey,a);for(const r of s.binding.activationQueue)d.push({registration:s,input:{params:{sessionId:s.nianSessionId,text:r.deliveryText??"\u7FA4\u804A\u4E2D\u6709\u4E00\u6761\u5F85\u5904\u7406\u6D88\u606F\uFF0C\u8BF7\u7ED3\u5408\u5F53\u524D\u7FA4\u804A\u4E0A\u4E0B\u6587\u5904\u7406\u3002",agentType:y(s.runtimeAdapter),sessionMode:a.agentsByIdentityId?.[s.binding.agentIdentityId]?.sessionMode??"standard",managerConfig:a.agentsByIdentityId?.[s.binding.agentIdentityId]?.managerConfig??null,managerDefaultWorkerAgentType:a.agentsByIdentityId?.[s.binding.agentIdentityId]?.managerConfig?.defaultWorkerAgentType??null,managerDefaultWorkerModelId:a.agentsByIdentityId?.[s.binding.agentIdentityId]?.managerConfig?.defaultWorkerModelId??null,workDir:l.workspacePath,agentSessionId:s.sourceSessionKey,queueMessageId:`room-activation-${s.binding.bindingId}-${r.causeMessageId}`,clientMessageId:`room-activation-${s.binding.bindingId}-${r.causeMessageId}`},context:{registryKey:s.registryKey,causeMessageId:r.causeMessageId,rootCauseMessageId:r.rootCauseMessageId,sequence:r.sequence,hopCount:r.hopCount}}})}for(const i of g){const s=new Set(q(i,t).map(l=>l.registration.registryKey));for(const l of t){const r=this.deps.registry.getByRegistryKey(l.registryKey);if(!r?.binding||!f(this.deps.registry,l)||r.binding.roomId!==e||r.binding.status!=="active"&&r.binding.status!=="paused"||a.agentsByIdentityId?.[r.binding.agentIdentityId]?.configurationPending||BigInt(i.sequence)<=BigInt(r.binding.lastActivatedSequence))continue;const I=c.get(r.registryKey)??[...r.binding.mentionContext??[]];if(c.set(r.registryKey,I),s.has(r.registryKey)){const p=(i.activationCause?.hopCount??0)+(i.author.principalType==="agent"?1:0),h=i.activationCause?.rootCauseMessageId??i.id;if(p>N)this.audit(r,i.id,h,p,"suppressed","max_hops");else{const w=this.deps.registry.claimActivation({registryKey:r.registryKey,causeMessageId:i.id,windowMs:O,maxActivations:F,pauseMs:V,now:this.deps.now?.()});if(!w.allowed){w.newlyPaused&&this.audit(r,i.id,h,p,"suppressed","rate_limited"),m.push({registryKey:r.registryKey,sequence:i.sequence});continue}const b=this.deps.observations.getBySource(r);if(!b?.workspacePath||b.lifecycleState==="closed")throw new Error("managed_room_workspace_unavailable");const M=v([i]),C=r.binding.activationMode==="mention_only"?Q([...I.map(_=>_.deliveryText),M]):M;this.latestContexts.set(r.registryKey,a),d.push({registration:r,input:{params:{sessionId:r.nianSessionId,text:C,agentType:y(r.runtimeAdapter),sessionMode:a.agentsByIdentityId?.[r.binding.agentIdentityId]?.sessionMode??"standard",managerConfig:a.agentsByIdentityId?.[r.binding.agentIdentityId]?.managerConfig??null,managerDefaultWorkerAgentType:a.agentsByIdentityId?.[r.binding.agentIdentityId]?.managerConfig?.defaultWorkerAgentType??null,managerDefaultWorkerModelId:a.agentsByIdentityId?.[r.binding.agentIdentityId]?.managerConfig?.defaultWorkerModelId??null,workDir:b.workspacePath,agentSessionId:r.sourceSessionKey,queueMessageId:`room-activation-${r.binding.bindingId}-${i.id}`,clientMessageId:`room-activation-${r.binding.bindingId}-${i.id}`,roomMessageCreatedAt:i.createdAt},context:{registryKey:r.registryKey,causeMessageId:i.id,rootCauseMessageId:h,sequence:i.sequence,hopCount:p}}}),r.binding.activationMode==="mention_only"&&c.set(r.registryKey,[])}}else r.binding.activationMode==="mention_only"&&i.kind!=="system"&&i.author.membershipId!==r.binding.agentMembershipId&&(I.some(p=>p.sequence===i.sequence)||I.push({sequence:i.sequence,deliveryText:v([i])}));m.push({registryKey:r.registryKey,sequence:i.sequence})}}await this.deps.enqueueConversationBatch(d.map(i=>i.input));for(const i of u)this.deps.registry.retireLegacyActivationState(i,this.deps.now?.()??new Date);for(const[i,s]of c)this.deps.registry.getByRegistryKey(i)?.lifecycleState!=="closed"&&this.deps.registry.replaceMentionContext(i,s,this.deps.now?.()??new Date);for(const i of d)this.audit(i.registration,i.input.context.causeMessageId,i.input.context.rootCauseMessageId,i.input.context.hopCount,"queued","conversation_queue");for(const i of m)this.deps.registry.getByRegistryKey(i.registryKey)?.lifecycleState!=="closed"&&this.deps.registry.advanceCursor({registryKey:i.registryKey,cursor:"activated",sequence:i.sequence})}async prepareConversationTurn(e){const o=e.at(-1);if(!o)throw new Error("managed_room_queue_context_missing");const t=this.deps.registry.getByRegistryKey(o.registryKey);if(!t)throw new Error("managed_room_binding_unavailable");const a=await this.prepareManagedTurn(t,o.causeMessageId);return this.audit(t,o.causeMessageId,o.rootCauseMessageId,o.hopCount,"activated","conversation_queue_dispatch"),a}async prepareDirectConversationTurn(e,o={}){const t=o.roomOrigin?this.deps.registry.getByRegistryKey(o.roomOrigin.registryKey):this.deps.registry.getByNianSessionId(e);return t?.nianSessionId!==e||!t||o.roomOrigin&&(t.registrationEpoch!==o.roomOrigin.registrationEpoch||t.binding?.bindingId!==o.roomOrigin.bindingId||t.binding.roomId!==o.roomOrigin.roomId)?null:this.prepareManagedTurn(t,void 0,o)}async prepareManagedTurn(e,o,t){if(!f(this.deps.registry,e)||!e.binding||e.binding.status!=="active")throw new Error("managed_room_binding_unavailable");const a=this.deps.loadContext?await this.deps.loadContext(e):this.latestContexts.get(e.registryKey);if(!a)throw new Error("managed_room_prompt_context_unavailable");const d=a.agentsByIdentityId?.[e.binding.agentIdentityId];if(d?.configurationPending)throw new Error("managed_agent_configuration_pending");if(!d?.permissionPolicy)throw new Error("managed_agent_policy_missing");const m=d.sessionMode==="manager"?"manager":"standard",c=m==="manager"?{...d.managerConfig,defaultWorkerAgentType:d.managerConfig?.defaultWorkerAgentType??y(e.runtimeAdapter),defaultWorkerModelId:d.managerConfig?.defaultWorkerModelId??null}:null,u=this.deps.observations.getBySource(e);if(!u?.workspacePath||u.lifecycleState==="closed")throw new Error("managed_room_workspace_unavailable");const g=this.deps.resolveManagedAgentPolicy?await this.deps.resolveManagedAgentPolicy({registration:e,permissionPolicy:d.permissionPolicy,permissionConfirmation:d.permissionConfirmation,workDir:u.workspacePath}):await U({registration:e,permissionPolicy:d.permissionPolicy,permissionConfirmation:d.permissionConfirmation,workDir:u.workspacePath});if(!f(this.deps.registry,e))throw new Error("managed_room_binding_unavailable");const i=H(a,e,g),s=this.deps.issueManagedRoomContext(e.registryKey,o,t?.allowedRoomActions,t?.propagateWorkerRoomOrigin);if(!/^mrc_[A-Za-z0-9_-]{43}$/.test(s))throw new Error("managed_room_context_unavailable");return{agentType:y(e.runtimeAdapter),effectiveModelId:a.effectiveModelsBySessionId?.[e.nianSessionId],workDir:g.adapterPolicy.workDir,agentSessionId:e.sourceSessionKey,systemPrompt:t?G({managerEvent:t.managerEvent===!0,roomSendAllowed:t.allowedRoomActions?.includes("send")===!0,agentSystemPrompt:a.agentSystemPromptsByIdentityId?.[e.binding.agentIdentityId],managedAgentPolicy:g,runtimeAdapter:y(e.runtimeAdapter)}):i.systemPrompt,sessionMode:m,managerConfig:c,managerDefaultWorkerAgentType:c?.defaultWorkerAgentType??null,managerDefaultWorkerModelId:c?.defaultWorkerModelId??null,roomContextRegistryKey:e.registryKey,managedRoomContextToken:s,managedAgentPolicy:g,managedRoomPromptSnapshot:i.snapshot}}audit(e,o,t,a,d,m){e.binding&&this.deps.audit?.record({roomId:e.binding.roomId,bindingId:e.binding.bindingId,causeMessageId:o,rootCauseMessageId:t,hopCount:a,outcome:d,reason:m,at:this.deps.now?.()})}}function v(n){if(n.length===1&&n[0].kind==="system")return`[\u7FA4\u4E8B\u4EF6]
1
+ import{isAvailableBuiltinAgentType as k,managedAgentExecutionMode as P}from"@shennian/wire";import{getBuiltinAgentVersion as S,resolveBuiltinCommand as B}from"../agents/command-spec.js";import{registerCustomRuntimeSecurity as K,resolveCustomRuntimeExecutableFingerprint as $}from"../agents/custom-managed-runtime.js";import{loadConfig as x}from"../config/index.js";import{resolveManagedAgentExecutableIdentity as T}from"../security/managed-agent-executable.js";import{compileManagedAgentPolicy as W}from"../security/managed-agent-policy.js";import{resolveManagedAgentRuntimeProtection as R}from"../security/managed-agent-runtime.js";import{selectRoomActivationTargets as q}from"./activation-policy.js";import{buildManagedAgentPermissionPrompt as E,composeManagedRoomPrompt as D}from"./managed-prompt-composer.js";import{isCurrentRegistration as f}from"./registration-authority.js";const N=4,F=6e4,O=6,V=5*6e4;class ce{deps;latestContexts=new Map;constructor(e){this.deps=e}async processMessages(e,o,t,a={roomName:"\u5F53\u524D\u7FA4\u804A"}){const d=[],m=[],c=new Map,u=new Set,g=[...o].sort((i,s)=>J(i.sequence,s.sequence));for(const i of t){const s=this.deps.registry.getByRegistryKey(i.registryKey);!s?.binding||!f(this.deps.registry,i)||s.binding.roomId!==e||s.binding.status!=="active"&&s.binding.status!=="paused"&&s.binding.activationQueue.length}for(const i of t){const s=this.deps.registry.getByRegistryKey(i.registryKey);if(!s?.binding||!f(this.deps.registry,i)||s.binding.roomId!==e||s.binding.activationQueue.length===0&&!s.binding.activeActivation||(u.add(s.registryKey),s.binding.status!=="active"||s.binding.activationMode==="paused")||s.binding.activationQueue.length===0)continue;const l=this.deps.observations.getBySource(s);if(!l?.workspacePath||l.lifecycleState==="closed")throw new Error("managed_room_workspace_unavailable");this.latestContexts.set(s.registryKey,a);for(const r of s.binding.activationQueue)d.push({registration:s,input:{params:{sessionId:s.nianSessionId,text:r.deliveryText??"\u7FA4\u804A\u4E2D\u6709\u4E00\u6761\u5F85\u5904\u7406\u6D88\u606F\uFF0C\u8BF7\u7ED3\u5408\u5F53\u524D\u7FA4\u804A\u4E0A\u4E0B\u6587\u5904\u7406\u3002",agentType:y(s.runtimeAdapter),sessionMode:a.agentsByIdentityId?.[s.binding.agentIdentityId]?.sessionMode??"standard",managerConfig:a.agentsByIdentityId?.[s.binding.agentIdentityId]?.managerConfig??null,managerDefaultWorkerAgentType:a.agentsByIdentityId?.[s.binding.agentIdentityId]?.managerConfig?.defaultWorkerAgentType??null,managerDefaultWorkerModelId:a.agentsByIdentityId?.[s.binding.agentIdentityId]?.managerConfig?.defaultWorkerModelId??null,workDir:l.workspacePath,agentSessionId:s.sourceSessionKey,queueMessageId:`room-activation-${s.binding.bindingId}-${r.causeMessageId}`,clientMessageId:`room-activation-${s.binding.bindingId}-${r.causeMessageId}`},context:{registryKey:s.registryKey,causeMessageId:r.causeMessageId,rootCauseMessageId:r.rootCauseMessageId,sequence:r.sequence,hopCount:r.hopCount}}})}for(const i of g){const s=new Set(q(i,t).map(l=>l.registration.registryKey));for(const l of t){const r=this.deps.registry.getByRegistryKey(l.registryKey);if(!r?.binding||!f(this.deps.registry,l)||r.binding.roomId!==e||r.binding.status!=="active"&&r.binding.status!=="paused"||a.agentsByIdentityId?.[r.binding.agentIdentityId]?.configurationPending||BigInt(i.sequence)<=BigInt(r.binding.lastActivatedSequence))continue;const h=c.get(r.registryKey)??[...r.binding.mentionContext??[]];if(c.set(r.registryKey,h),s.has(r.registryKey)){const p=(i.activationCause?.hopCount??0)+(i.author.principalType==="agent"?1:0),I=i.activationCause?.rootCauseMessageId??i.id;if(p>N)this.audit(r,i.id,I,p,"suppressed","max_hops");else{const w=this.deps.registry.claimActivation({registryKey:r.registryKey,causeMessageId:i.id,windowMs:F,maxActivations:O,pauseMs:V,now:this.deps.now?.()});if(!w.allowed){w.newlyPaused&&this.audit(r,i.id,I,p,"suppressed","rate_limited"),m.push({registryKey:r.registryKey,sequence:i.sequence});continue}const b=this.deps.observations.getBySource(r);if(!b?.workspacePath||b.lifecycleState==="closed")throw new Error("managed_room_workspace_unavailable");const M=v([i]),A=r.binding.activationMode==="mention_only"?Q([...h.map(C=>C.deliveryText),M]):M;this.latestContexts.set(r.registryKey,a),d.push({registration:r,input:{params:{sessionId:r.nianSessionId,text:A,agentType:y(r.runtimeAdapter),sessionMode:a.agentsByIdentityId?.[r.binding.agentIdentityId]?.sessionMode??"standard",managerConfig:a.agentsByIdentityId?.[r.binding.agentIdentityId]?.managerConfig??null,managerDefaultWorkerAgentType:a.agentsByIdentityId?.[r.binding.agentIdentityId]?.managerConfig?.defaultWorkerAgentType??null,managerDefaultWorkerModelId:a.agentsByIdentityId?.[r.binding.agentIdentityId]?.managerConfig?.defaultWorkerModelId??null,workDir:b.workspacePath,agentSessionId:r.sourceSessionKey,queueMessageId:`room-activation-${r.binding.bindingId}-${i.id}`,clientMessageId:`room-activation-${r.binding.bindingId}-${i.id}`,roomMessageCreatedAt:i.createdAt},context:{registryKey:r.registryKey,causeMessageId:i.id,rootCauseMessageId:I,sequence:i.sequence,hopCount:p}}}),r.binding.activationMode==="mention_only"&&c.set(r.registryKey,[])}}else r.binding.activationMode==="mention_only"&&i.kind!=="system"&&i.author.membershipId!==r.binding.agentMembershipId&&(h.some(p=>p.sequence===i.sequence)||h.push({sequence:i.sequence,deliveryText:v([i])}));m.push({registryKey:r.registryKey,sequence:i.sequence})}}await this.deps.enqueueConversationBatch(d.map(i=>i.input));for(const i of u)this.deps.registry.retireLegacyActivationState(i,this.deps.now?.()??new Date);for(const[i,s]of c)this.deps.registry.getByRegistryKey(i)?.lifecycleState!=="closed"&&this.deps.registry.replaceMentionContext(i,s,this.deps.now?.()??new Date);for(const i of d)this.audit(i.registration,i.input.context.causeMessageId,i.input.context.rootCauseMessageId,i.input.context.hopCount,"queued","conversation_queue");for(const i of m)this.deps.registry.getByRegistryKey(i.registryKey)?.lifecycleState!=="closed"&&this.deps.registry.advanceCursor({registryKey:i.registryKey,cursor:"activated",sequence:i.sequence})}async prepareConversationTurn(e){const o=e.at(-1);if(!o)throw new Error("managed_room_queue_context_missing");const t=this.deps.registry.getByRegistryKey(o.registryKey);if(!t)throw new Error("managed_room_binding_unavailable");const a=await this.prepareManagedTurn(t,o.causeMessageId);return this.audit(t,o.causeMessageId,o.rootCauseMessageId,o.hopCount,"activated","conversation_queue_dispatch"),a}async prepareDirectConversationTurn(e,o={}){const t=o.roomOrigin?this.deps.registry.getByRegistryKey(o.roomOrigin.registryKey):this.deps.registry.getByNianSessionId(e);return t?.nianSessionId!==e||!t||o.roomOrigin&&(t.registrationEpoch!==o.roomOrigin.registrationEpoch||t.binding?.bindingId!==o.roomOrigin.bindingId||t.binding.roomId!==o.roomOrigin.roomId)?null:this.prepareManagedTurn(t,void 0,o)}async prepareManagedTurn(e,o,t){if(!f(this.deps.registry,e)||!e.binding||e.binding.status!=="active")throw new Error("managed_room_binding_unavailable");const a=this.deps.loadContext?await this.deps.loadContext(e):this.latestContexts.get(e.registryKey);if(!a)throw new Error("managed_room_prompt_context_unavailable");const d=a.agentsByIdentityId?.[e.binding.agentIdentityId];if(d?.configurationPending)throw new Error("managed_agent_configuration_pending");if(!d?.permissionPolicy)throw new Error("managed_agent_policy_missing");const m=d.sessionMode==="manager"?"manager":"standard",c=m==="manager"?{...d.managerConfig,defaultWorkerAgentType:d.managerConfig?.defaultWorkerAgentType??y(e.runtimeAdapter),defaultWorkerModelId:d.managerConfig?.defaultWorkerModelId??null}:null,u=this.deps.observations.getBySource(e);if(!u?.workspacePath||u.lifecycleState==="closed")throw new Error("managed_room_workspace_unavailable");const g=this.deps.resolveManagedAgentPolicy?await this.deps.resolveManagedAgentPolicy({registration:e,permissionPolicy:d.permissionPolicy,permissionConfirmation:d.permissionConfirmation,workDir:u.workspacePath}):await U({registration:e,permissionPolicy:d.permissionPolicy,permissionConfirmation:d.permissionConfirmation,workDir:u.workspacePath});if(!f(this.deps.registry,e))throw new Error("managed_room_binding_unavailable");const i=H(a,e,g),s=this.deps.issueManagedRoomContext(e.registryKey,o,t?.allowedRoomActions,t?.propagateWorkerRoomOrigin);if(!/^mrc_[A-Za-z0-9_-]{43}$/.test(s))throw new Error("managed_room_context_unavailable");return{agentType:y(e.runtimeAdapter),effectiveModelId:a.effectiveModelsBySessionId?.[e.nianSessionId],workDir:g.adapterPolicy.workDir,agentSessionId:e.sourceSessionKey,systemPrompt:t?G({managerEvent:t.managerEvent===!0,scheduledTask:t.scheduledTask===!0,roomSendAllowed:t.allowedRoomActions?.includes("send")===!0,agentSystemPrompt:a.agentSystemPromptsByIdentityId?.[e.binding.agentIdentityId],managedAgentPolicy:g,runtimeAdapter:y(e.runtimeAdapter)}):i.systemPrompt,sessionMode:m,managerConfig:c,managerDefaultWorkerAgentType:c?.defaultWorkerAgentType??null,managerDefaultWorkerModelId:c?.defaultWorkerModelId??null,roomContextRegistryKey:e.registryKey,managedRoomContextToken:s,managedAgentPolicy:g,managedRoomPromptSnapshot:i.snapshot}}audit(e,o,t,a,d,m){e.binding&&this.deps.audit?.record({roomId:e.binding.roomId,bindingId:e.binding.bindingId,causeMessageId:o,rootCauseMessageId:t,hopCount:a,outcome:d,reason:m,at:this.deps.now?.()})}}function v(n){if(n.length===1&&n[0].kind==="system")return`[\u7FA4\u4E8B\u4EF6]
2
2
  ${n[0].text?.trim()||"\u7FA4\u804A\u72B6\u6001\u53D1\u751F\u53D8\u5316\u3002"}`;const e=n.map(o=>{const t=o.text?.trim()||"\u53D1\u9001\u4E86\u4E00\u6761\u6D88\u606F",a=o.attachments.length>0?`
3
3
  ${o.attachments.map(L).join(`
4
- `)}`:"";return{speaker:o.author.displayName,body:`${t}${a}`}});return A(e)}function L(n){return`\u9644\u4EF6\uFF1A${`${j(n.name)} \xB7 ${z(n.byteSize)}`}\uFF5C${n.mimeType}\uFF5CattachmentId=${n.attachmentId}`}function j(n){return String(n||"\u9644\u4EF6").replace(/[[\]\\]/g,"\\$&").replace(/[\r\n]+/g," ")}function z(n){const e=Number(n);if(!Number.isFinite(e)||e<0)return`${n} B`;if(e<1024)return`${e} B`;const o=["KB","MB","GB","TB"];let t=e,a=-1;do t/=1024,a+=1;while(t>=1024&&a<o.length-1);const d=t>=100?0:t>=10?1:2;return`${t.toFixed(d).replace(/\.0+$|(?<=\.[0-9])0+$/,"")} ${o[a]}`}function Q(n){return A(n.map(X))}function X(n){const e=n.match(/^\[群消息\][ \t]+<([^>\n]+)>\n([\s\S]*)$/);if(e)return{speaker:e[1],body:e[2]};const o=n.match(/^\[群消息\]\n<([^>\n]+)>\n([\s\S]*)$/);if(o)return{speaker:o[1],body:o[2]};const t=n.match(/^群消息\n([^\n]+)\n([\s\S]*)$/);if(t)return{speaker:t[1],body:t[2]};const a=n.match(/^([^\n]+)\n([\s\S]*)$/);return a?{speaker:a[1],body:a[2]}:{speaker:"\u7FA4\u6210\u5458",body:n.trim()}}function A(n){if(n.length===1){const[e]=n;return`[\u7FA4\u6D88\u606F] <${e.speaker}>
4
+ `)}`:"";return{speaker:o.author.displayName,body:`${t}${a}`}});return _(e)}function L(n){return`\u9644\u4EF6\uFF1A${`${j(n.name)} \xB7 ${z(n.byteSize)}`}\uFF5C${n.mimeType}\uFF5CattachmentId=${n.attachmentId}`}function j(n){return String(n||"\u9644\u4EF6").replace(/[[\]\\]/g,"\\$&").replace(/[\r\n]+/g," ")}function z(n){const e=Number(n);if(!Number.isFinite(e)||e<0)return`${n} B`;if(e<1024)return`${e} B`;const o=["KB","MB","GB","TB"];let t=e,a=-1;do t/=1024,a+=1;while(t>=1024&&a<o.length-1);const d=t>=100?0:t>=10?1:2;return`${t.toFixed(d).replace(/\.0+$|(?<=\.[0-9])0+$/,"")} ${o[a]}`}function Q(n){return _(n.map(X))}function X(n){const e=n.match(/^\[群消息\][ \t]+<([^>\n]+)>\n([\s\S]*)$/);if(e)return{speaker:e[1],body:e[2]};const o=n.match(/^\[群消息\]\n<([^>\n]+)>\n([\s\S]*)$/);if(o)return{speaker:o[1],body:o[2]};const t=n.match(/^群消息\n([^\n]+)\n([\s\S]*)$/);if(t)return{speaker:t[1],body:t[2]};const a=n.match(/^([^\n]+)\n([\s\S]*)$/);return a?{speaker:a[1],body:a[2]}:{speaker:"\u7FA4\u6210\u5458",body:n.trim()}}function _(n){if(n.length===1){const[e]=n;return`[\u7FA4\u6D88\u606F] <${e.speaker}>
5
5
  ${e.body}`}return`[\u7FA4\u6D88\u606F]
6
6
  ${n.map(e=>`<${e.speaker}>
7
7
  ${e.body}`).join(`
8
8
 
9
- `)}`}function G(n){const e=E({requestedPolicy:n.managedAgentPolicy.requestedPolicy,enforcement:n.managedAgentPolicy.enforcement,resolvedWorkDir:n.managedAgentPolicy.adapterPolicy.workDir}),o=n.managerEvent&&n.roomSendAllowed?`\u8FD9\u662F\u7531\u5F53\u524D\u7FA4\u804A\u4EFB\u52A1\u521B\u5EFA\u7684 Worker \u89E6\u53D1\u7684\u79C1\u6709 Manager \u7EED\u8F6E\u3002\u5148\u4F7F\u7528 Manager \u5DE5\u5177\u8BFB\u53D6\u5E76\u6838\u9A8C Worker \u7ED3\u679C\u3002\u53EA\u628A\u9762\u5411\u7528\u6237\u7684\u6700\u7EC8\u8FDB\u5C55\u6216\u7ED3\u8BBA\u53D1\u9001\u5230\u8BE5\u4EFB\u52A1\u539F\u59CB\u7FA4\u804A\uFF0C\u4E0D\u53D1\u9001 Worker \u539F\u59CB\u6D3B\u52A8\u3001\u5DE5\u5177\u65E5\u5FD7\u3001\u5185\u90E8\u6807\u8BC6\u6216\u8C03\u5EA6\u7EC6\u8282\u3002\u9700\u8981\u53D1\u5E03\u65F6\u5FC5\u987B\u663E\u5F0F\u4F7F\u7528${n.runtimeAdapter==="codex"?" shennian_room_send \u5DE5\u5177":" shennian room send \u547D\u4EE4"}\uFF1B\u53EA\u5728\u5F53\u524D\u5185\u90E8\u5BF9\u8BDD\u4E2D\u751F\u6210\u6587\u5B57\u4E0D\u4F1A\u53D1\u9001\u5230\u7FA4\u804A\u3002`:!n.managerEvent&&n.roomSendAllowed?`\u8FD9\u662F Owner \u4E0E Manager \u7684\u79C1\u6709\u5BF9\u8BDD\u3002\u4F60\u4ECD\u53EF\u4EE3\u8868\u5F53\u524D\u7ED1\u5B9A\u7684\u667A\u80FD\u4F53\uFF0C\u6309 Owner \u660E\u786E\u8981\u6C42\u5C06\u8FDB\u5C55\u6216\u7ED3\u8BBA\u663E\u5F0F\u53D1\u9001\u5230\u5B83\u6240\u5C5E\u7684 Room\uFF1B\u9700\u8981\u53D1\u5E03\u65F6\u5FC5\u987B\u4F7F\u7528${n.runtimeAdapter==="codex"?" shennian_room_send \u5DE5\u5177":" shennian room send \u547D\u4EE4"}\u3002\u4F60\u4E0D\u80FD\u8BFB\u53D6 Room \u5386\u53F2\u6216\u5411\u5176\u4ED6 Room \u53D1\u9001\u3002`:n.managerEvent?"\u8FD9\u662F Worker \u89E6\u53D1\u7684\u79C1\u6709 Manager \u7EED\u8F6E\u3002\u53EF\u4EE5\u4F7F\u7528 Manager \u5DE5\u5177\u8BFB\u53D6\u5E76\u6838\u9A8C Worker \u7ED3\u679C\uFF0C\u4F46\u4E0D\u5F97\u8BFB\u53D6\u3001\u53D1\u9001\u6216\u56DE\u590D\u4EFB\u4F55 Room \u5185\u5BB9\u3002":"\u8FD9\u662F Owner \u4E0E Manager \u7684\u79C1\u6709\u5BF9\u8BDD\u3002\u53EF\u4EE5\u4F7F\u7528 Manager \u5DE5\u5177\u7BA1\u7406 Worker\uFF0C\u4F46\u5F53\u524D\u6CA1\u6709 Room \u53D1\u5E03\u6743\u9650\u3002",t=n.agentSystemPrompt?.trim();return[`[\u795E\u5FF5\u53D7\u7BA1\u79C1\u6709\u7EED\u8F6E\u89C4\u5219]
9
+ `)}`}function G(n){const e=E({requestedPolicy:n.managedAgentPolicy.requestedPolicy,enforcement:n.managedAgentPolicy.enforcement,resolvedWorkDir:n.managedAgentPolicy.adapterPolicy.workDir}),o=n.scheduledTask?`\u8FD9\u662F\u670D\u52A1\u5668\u5DF2\u4FDD\u5B58\u7684\u5B9A\u65F6\u4EFB\u52A1\u73B0\u5728\u89E6\u53D1\uFF0C\u4E0D\u662F\u8981\u6C42\u4F60\u521B\u5EFA\u6216\u4FEE\u6539\u5B9A\u65F6\u4EFB\u52A1\u3002\u7ACB\u5373\u6267\u884C\u672C\u8F6E\u6536\u5230\u7684\u5DE5\u4F5C\u5185\u5BB9\uFF1B\u5176\u4E2D\u7684\u5468\u671F\u548C\u65F6\u95F4\u53EA\u662F\u539F\u5B89\u6392\u80CC\u666F\uFF0C\u4E0D\u8981\u518D\u6B21\u8C03\u7528\u5B9A\u65F6\u4EFB\u52A1\u521B\u5EFA\u5DE5\u5177\u3002\u9700\u8981\u5411\u5F53\u524D\u7ED1\u5B9A\u7FA4\u804A\u6C47\u62A5\u65F6\uFF0C\u5FC5\u987B\u663E\u5F0F\u4F7F\u7528${n.runtimeAdapter==="codex"?" shennian_room_send \u5DE5\u5177":" shennian room send \u547D\u4EE4"}\uFF1B\u53EA\u5728\u5185\u90E8\u5BF9\u8BDD\u56DE\u590D\u4E0D\u4F1A\u53D1\u5E03\u5230\u7FA4\u804A\u3002\u53EA\u80FD\u5411\u5F53\u524D\u7ED1\u5B9A\u7FA4\u804A\u53D1\u9001\uFF0C\u4E0D\u80FD\u8BFB\u53D6\u7FA4\u5386\u53F2\u6216\u64CD\u4F5C\u5176\u4ED6\u7FA4\u804A\u3002\u82E5\u6267\u884C\u6216\u53D1\u9001\u5931\u8D25\uFF0C\u5982\u5B9E\u62A5\u544A\uFF0C\u4E0D\u5F97\u58F0\u79F0\u5DF2\u64AD\u62A5\u3002`:n.managerEvent&&n.roomSendAllowed?`\u8FD9\u662F\u7531\u5F53\u524D\u7FA4\u804A\u4EFB\u52A1\u521B\u5EFA\u7684 Worker \u89E6\u53D1\u7684\u79C1\u6709 Manager \u7EED\u8F6E\u3002\u5148\u4F7F\u7528 Manager \u5DE5\u5177\u8BFB\u53D6\u5E76\u6838\u9A8C Worker \u7ED3\u679C\u3002\u53EA\u628A\u9762\u5411\u7528\u6237\u7684\u6700\u7EC8\u8FDB\u5C55\u6216\u7ED3\u8BBA\u53D1\u9001\u5230\u8BE5\u4EFB\u52A1\u539F\u59CB\u7FA4\u804A\uFF0C\u4E0D\u53D1\u9001 Worker \u539F\u59CB\u6D3B\u52A8\u3001\u5DE5\u5177\u65E5\u5FD7\u3001\u5185\u90E8\u6807\u8BC6\u6216\u8C03\u5EA6\u7EC6\u8282\u3002\u9700\u8981\u53D1\u5E03\u65F6\u5FC5\u987B\u663E\u5F0F\u4F7F\u7528${n.runtimeAdapter==="codex"?" shennian_room_send \u5DE5\u5177":" shennian room send \u547D\u4EE4"}\uFF1B\u53EA\u5728\u5F53\u524D\u5185\u90E8\u5BF9\u8BDD\u4E2D\u751F\u6210\u6587\u5B57\u4E0D\u4F1A\u53D1\u9001\u5230\u7FA4\u804A\u3002`:!n.managerEvent&&n.roomSendAllowed?`\u8FD9\u662F Owner \u4E0E Manager \u7684\u79C1\u6709\u5BF9\u8BDD\u3002\u4F60\u4ECD\u53EF\u4EE3\u8868\u5F53\u524D\u7ED1\u5B9A\u7684\u667A\u80FD\u4F53\uFF0C\u6309 Owner \u660E\u786E\u8981\u6C42\u5C06\u8FDB\u5C55\u6216\u7ED3\u8BBA\u663E\u5F0F\u53D1\u9001\u5230\u5B83\u6240\u5C5E\u7684 Room\uFF1B\u9700\u8981\u53D1\u5E03\u65F6\u5FC5\u987B\u4F7F\u7528${n.runtimeAdapter==="codex"?" shennian_room_send \u5DE5\u5177":" shennian room send \u547D\u4EE4"}\u3002\u4F60\u4E0D\u80FD\u8BFB\u53D6 Room \u5386\u53F2\u6216\u5411\u5176\u4ED6 Room \u53D1\u9001\u3002`:n.managerEvent?"\u8FD9\u662F Worker \u89E6\u53D1\u7684\u79C1\u6709 Manager \u7EED\u8F6E\u3002\u53EF\u4EE5\u4F7F\u7528 Manager \u5DE5\u5177\u8BFB\u53D6\u5E76\u6838\u9A8C Worker \u7ED3\u679C\uFF0C\u4F46\u4E0D\u5F97\u8BFB\u53D6\u3001\u53D1\u9001\u6216\u56DE\u590D\u4EFB\u4F55 Room \u5185\u5BB9\u3002":"\u8FD9\u662F Owner \u4E0E Manager \u7684\u79C1\u6709\u5BF9\u8BDD\u3002\u53EF\u4EE5\u4F7F\u7528 Manager \u5DE5\u5177\u7BA1\u7406 Worker\uFF0C\u4F46\u5F53\u524D\u6CA1\u6709 Room \u53D1\u5E03\u6743\u9650\u3002",t=n.agentSystemPrompt?.trim();return[`[\u795E\u5FF5\u53D7\u7BA1\u79C1\u6709\u7EED\u8F6E\u89C4\u5219]
10
10
  ${o}
11
11
  \u4E0D\u5F97\u731C\u6D4B\u6216\u5C55\u793A Room\u3001Agent\u3001Session\u3001Binding\u3001Membership\u3001Machine \u6807\u8BC6\u6216\u4EFB\u4F55\u51ED\u636E\u3002`,e,t?`[\u667A\u80FD\u4F53\u79C1\u6709\u7CFB\u7EDF\u63D0\u793A\u8BCD]
12
12
  ${t}`:""].filter(Boolean).join(`
13
13
 
14
- `)}function H(n,e,o){const t=e.binding?n.agentsByIdentityId?.[e.binding.agentIdentityId]:void 0;if(!e.binding||!t)throw new Error("managed_room_prompt_incomplete");return D({runtimeAdapter:y(e.runtimeAdapter),agent:{displayName:t.displayName,description:t.description,systemPrompt:n.agentSystemPromptsByIdentityId?.[e.binding.agentIdentityId],configurationVersion:t.configurationVersion},room:{name:n.roomName,activationMode:e.binding.activationMode,members:n.members},runtimePermissions:{requestedPolicy:o.requestedPolicy,enforcement:o.enforcement,resolvedWorkDir:o.adapterPolicy.workDir}})}async function U(n){const e=y(n.registration.runtimeAdapter),o=k(e)?B(e):null,t=e.startsWith("custom:")?x().customAgents?.[e.slice(7)]:void 0;t&&K(e,t);const a=n.runtime?.version??(o?S(e,o):t?.caps.version),d=n.runtime?{platform:n.runtime.runtimePlatform??process.platform,isWsl:n.runtime.runtimeIsWsl??!1,executableFingerprint:n.runtime.executableFingerprint}:o?W(o):{platform:process.platform,isWsl:process.platform==="linux"&&!!(process.env.WSL_DISTRO_NAME||process.env.WSL_INTEROP),executableFingerprint:t?$(t):void 0},m={agentType:e,runtimeVersion:a,platform:d.platform,isWsl:d.isWsl,executableFingerprint:d.executableFingerprint,requireExecutableFingerprint:!0},c=R(m);if(e==="codex"&&n.permissionConfirmation&&(n.permissionConfirmation.platform==="win32"&&c.platform==="wsl"||n.permissionConfirmation.platform==="wsl"&&c.platform==="win32"))throw new Error("managed_agent_runtime_changed");const u=Z({confirmation:n.permissionConfirmation,policy:n.permissionPolicy,runtimeAdapter:e,protection:c}),g=await T({...m,policy:n.permissionPolicy,workDir:n.workDir,hostFullAccessConfirmed:u&&n.permissionConfirmation?.hostFullAccess,limitedProtectionConfirmed:u&&n.permissionConfirmation?.limitedProtection});if(!g.ok){const i=g.unsupportedCapabilities?.length?`:${g.unsupportedCapabilities.join(",")}`:"";throw new Error(`${g.errorCode}${i}`)}return g.value}function Z(n){const{confirmation:e,policy:o,runtimeAdapter:t}=n,a=P(o);return!!(e&&e.policyVersion===o.version&&e.runtimeAdapter===t&&(e.executionMode??"restricted")===a&&e.hostFullAccess===(a==="native-full"||o.fileAccess==="host-full"))}function y(n){return n==="claude_code"?"claude":n}function J(n,e){const o=BigInt(n),t=BigInt(e);return o<t?-1:o>t?1:0}export{ce as RoomActivationService,Z as managedAgentPermissionConfirmationMatches,U as resolveManagedAgentPolicy};
14
+ `)}function H(n,e,o){const t=e.binding?n.agentsByIdentityId?.[e.binding.agentIdentityId]:void 0;if(!e.binding||!t)throw new Error("managed_room_prompt_incomplete");return D({runtimeAdapter:y(e.runtimeAdapter),agent:{displayName:t.displayName,description:t.description,systemPrompt:n.agentSystemPromptsByIdentityId?.[e.binding.agentIdentityId],configurationVersion:t.configurationVersion},room:{name:n.roomName,activationMode:e.binding.activationMode,members:n.members},runtimePermissions:{requestedPolicy:o.requestedPolicy,enforcement:o.enforcement,resolvedWorkDir:o.adapterPolicy.workDir}})}async function U(n){const e=y(n.registration.runtimeAdapter),o=k(e)?B(e):null,t=e.startsWith("custom:")?x().customAgents?.[e.slice(7)]:void 0;t&&K(e,t);const a=n.runtime?.version??(o?S(e,o):t?.caps.version),d=n.runtime?{platform:n.runtime.runtimePlatform??process.platform,isWsl:n.runtime.runtimeIsWsl??!1,executableFingerprint:n.runtime.executableFingerprint}:o?T(o):{platform:process.platform,isWsl:process.platform==="linux"&&!!(process.env.WSL_DISTRO_NAME||process.env.WSL_INTEROP),executableFingerprint:t?$(t):void 0},m={agentType:e,runtimeVersion:a,platform:d.platform,isWsl:d.isWsl,executableFingerprint:d.executableFingerprint,requireExecutableFingerprint:!0},c=R(m);if(e==="codex"&&n.permissionConfirmation&&(n.permissionConfirmation.platform==="win32"&&c.platform==="wsl"||n.permissionConfirmation.platform==="wsl"&&c.platform==="win32"))throw new Error("managed_agent_runtime_changed");const u=Z({confirmation:n.permissionConfirmation,policy:n.permissionPolicy,runtimeAdapter:e,protection:c}),g=await W({...m,policy:n.permissionPolicy,workDir:n.workDir,hostFullAccessConfirmed:u&&n.permissionConfirmation?.hostFullAccess,limitedProtectionConfirmed:u&&n.permissionConfirmation?.limitedProtection});if(!g.ok){const i=g.unsupportedCapabilities?.length?`:${g.unsupportedCapabilities.join(",")}`:"";throw new Error(`${g.errorCode}${i}`)}return g.value}function Z(n){const{confirmation:e,policy:o,runtimeAdapter:t}=n,a=P(o);return!!(e&&e.policyVersion===o.version&&e.runtimeAdapter===t&&(e.executionMode??"restricted")===a&&e.hostFullAccess===(a==="native-full"||o.fileAccess==="host-full"))}function y(n){return n==="claude_code"?"claude":n}function J(n,e){const o=BigInt(n),t=BigInt(e);return o<t?-1:o>t?1:0}export{ce as RoomActivationService,Z as managedAgentPermissionConfirmationMatches,U as resolveManagedAgentPolicy};
@@ -1 +1 @@
1
- import{randomBytes as i}from"node:crypto";const n=new Map;function l(t){const e=Date.now();for(const[s,r]of n)if(r.expires<=e)n.delete(s);else if(r.sessionId===t)return r.expires=e+30*6e4,s;const o=i(32).toString("base64url");return n.set(o,{sessionId:t,expires:e+30*6e4}),o}function p(t){const e=typeof t=="string"?n.get(t):null;if(!e||e.expires<=Date.now())throw new Error("schedule_context_expired");return e.sessionId}export{l as issuePersonalScheduleContext,p as resolvePersonalScheduleContext};
1
+ import{randomBytes as i}from"node:crypto";const o=new Map;function a(t){const e=Date.now();for(const[s,n]of o)if(n.expires<=e)o.delete(s);else if(n.sessionId===t)return n.expires=e+30*6e4,s;const r=i(32).toString("base64url");return o.set(r,{sessionId:t,expires:e+30*6e4}),r}function c(t){const e=typeof t=="string"?o.get(t):null;if(!e||e.expires<=Date.now())throw new Error("schedule_context_expired");return e.sessionId}const u="\u5982\u7528\u6237\u8981\u6C42\u5B89\u6392\u7A0D\u540E\u6216\u5B9A\u671F\u5DE5\u4F5C\uFF0C\u4F7F\u7528 shennian schedule --operation create --operation-id <\u7A33\u5B9AID> --time-description <\u65F6\u95F4\u63CF\u8FF0> --timezone <IANA\u65F6\u533A> --prompt <\u5DE5\u4F5C\u5185\u5BB9>\u3002\u652F\u6301\u6BCF\u592909:00\u3001\u6BCF\u5468\u4E0009:00\u3001\u6BCF\u67081\u65E509:00\u3001\u6BCF\u969424\u5C0F\u65F6\u300130\u5206\u949F\u540E\u6216ISO\u65F6\u95F4\u3002\u67E5\u8BE2\u7528 --operation list\uFF1B\u4FEE\u6539/\u6682\u505C/\u6062\u590D/\u5220\u9664\u7528 update/pause/resume/delete\uFF0C\u5E76\u5E26\u67E5\u8BE2\u5F97\u5230\u7684 --id \u548C --version\u3002\u53EA\u5728\u771F\u5B9E\u4FDD\u5B58\u6210\u529F\u540E\u7528 say \u505A\u7B80\u77ED\u786E\u8BA4\uFF0C\u4E0D\u5F97\u53E3\u5934\u627F\u8BFA\u5C1A\u672A\u4FDD\u5B58\u6210\u529F\u7684\u5B89\u6392\u3002\u8BE5\u4EFB\u52A1\u7ED1\u5B9A\u5728\u8FD9\u53F0\u673A\u5668\uFF0C\u4E0D\u662F\u8FD9\u4E00\u6B21\u5BF9\u8BDD\uFF1B\u673A\u5668\u79BB\u7EBF\u65F6\u5230\u70B9\u4F1A\u8DF3\u8FC7\u800C\u4E0D\u662F\u7B49\u5F85\u6216\u8865\u8DD1\u3002\u65F6\u95F4\u548C\u5DE5\u4F5C\u5185\u5BB9\u5206\u5F00\uFF0C\u4E0D\u5728\u5DE5\u4F5C Prompt \u91CC\u91CD\u590D\u521B\u5EFA\u5B9A\u65F6\u4EFB\u52A1\u3002";export{u as STEWARD_SCHEDULE_INSTRUCTIONS,a as issuePersonalScheduleContext,c as resolvePersonalScheduleContext};
@@ -1,16 +1,16 @@
1
- import{listSessionRecords as p}from"./store.js";const _={allowedRoomActions:["send"],propagateWorkerRoomOrigin:!1};function I(n,r){return n?{roomOrigin:n.roomOrigin,allowedRoomActions:n.roomOrigin?["send"]:[],managerEvent:!0}:r?_:void 0}function R(n,r){const e=l(r);if(e)return n.find(i=>l(i)===e)??null;if(r.origin!=="external")return null;const t=g(r);return n.find(i=>g(i)===t)??null}function b(n){const{dispatchBlock:r,origin:e,managedRoom:t,managedAgentDirect:i,trigger:a,externalQueuedSubmissionId:o,...u}=n;return u}function S(n){const r=n.reduce((o,u)=>{const d=c(u);return o===null||d<o?d:o},null);if(r===null)return[];const e=n.filter(o=>c(o)===r),t=e[0];if(!t)return[];if(s(t))return[t];if(t.trigger?.kind==="manager_worker"||t.trigger?.kind==="scheduled")return[t];const i=f(t),a=[];for(const o of e){if(f(o)!==i)break;a.push(o)}return a}function s(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 y(n){return n?.trim()||void 0}function D(n,r){const e=n.find(t=>t.id===r&&s(t));return e?[e]:[]}function c(n){const r=m(n).kind;return r==="personal"||r==="managed_direct"?0:r==="manager_event"||r==="manager_worker"?1:2}function m(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,roomOrigin:r.roomOrigin??null}:r.kind==="manager_event"?{kind:r.kind,roomOrigin:r.roomOrigin??null}:{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:y(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,roomInputKind:n.managedRoom?n.text.trimStart().startsWith(`[\u7FA4\u4E8B\u4EF6]
2
- `)?"event":"message":null,trigger:m(n)})}function M(n){return n.every(r=>r.managedRoom)?n.every(r=>r.text.trimStart().startsWith(`[\u7FA4\u4E8B\u4EF6]
1
+ import{listSessionRecords as p}from"./store.js";const _={allowedRoomActions:["send"],propagateWorkerRoomOrigin:!1},I={allowedRoomActions:["send"],propagateWorkerRoomOrigin:!1,scheduledTask:!0};function R(n,e){return n?{roomOrigin:n.roomOrigin,allowedRoomActions:n.roomOrigin?["send"]:[],managerEvent:!0}:e?_:void 0}function S(n,e){const r=l(e);if(r)return n.find(i=>l(i)===r)??null;if(e.origin!=="external")return null;const t=g(e);return n.find(i=>g(i)===t)??null}function O(n){const{dispatchBlock:e,origin:r,managedRoom:t,managedAgentDirect:i,trigger:a,externalQueuedSubmissionId:o,...u}=n;return u}function b(n){const e=n.reduce((o,u)=>{const d=c(u);return o===null||d<o?d:o},null);if(e===null)return[];const r=n.filter(o=>c(o)===e),t=r[0];if(!t)return[];if(s(t))return[t];if(t.trigger?.kind==="manager_worker"||t.trigger?.kind==="scheduled")return[t];const i=f(t),a=[];for(const o of r){if(f(o)!==i)break;a.push(o)}return a}function s(n){if(n.origin==="external"||n.origin==="room"||n.managedRoom)return!1;const e=n.trigger?.kind;return e==null||e==="personal"||e==="managed_direct"}function y(n){return n?.trim()||void 0}function D(n,e){const r=n.find(t=>t.id===e&&s(t));return r?[r]:[]}function c(n){const e=m(n).kind;return e==="personal"||e==="managed_direct"?0:e==="manager_event"||e==="manager_worker"?1:2}function m(n){const e=n.trigger;return e?e.kind==="room_activation"?{kind:e.kind,registryKey:e.registryKey}:e.kind==="manager_worker"?{kind:e.kind,parentSessionId:e.parentSessionId,roomOrigin:e.roomOrigin??null}:e.kind==="manager_event"?{kind:e.kind,roomOrigin:e.roomOrigin??null}:{kind:e.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:y(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,roomInputKind:n.managedRoom?n.text.trimStart().startsWith(`[\u7FA4\u4E8B\u4EF6]
2
+ `)?"event":"message":null,trigger:m(n)})}function T(n){return n.every(e=>e.managedRoom)?n.every(e=>e.text.trimStart().startsWith(`[\u7FA4\u4E8B\u4EF6]
3
3
  `))?`[\u7FA4\u4E8B\u4EF6]
4
- ${n.map(r=>r.text.trim().slice(6)).filter(Boolean).join(`
4
+ ${n.map(e=>e.text.trim().slice(6)).filter(Boolean).join(`
5
5
 
6
6
  `)}`:`[\u7FA4\u6D88\u606F]
7
- ${n.map(r=>k(r.text)).filter(Boolean).join(`
7
+ ${n.map(e=>k(e.text)).filter(Boolean).join(`
8
8
 
9
9
  `)}`:`[\u8FDE\u7EED\u7528\u6237\u6D88\u606F]
10
- ${n.map((r,e)=>`<\u6D88\u606F ${e+1}>
11
- ${r.text.trim()}`).join(`
10
+ ${n.map((e,r)=>`<\u6D88\u606F ${r+1}>
11
+ ${e.text.trim()}`).join(`
12
12
 
13
- `)}`}function k(n){const r=n.trim(),e=r.match(/^\[群消息\][ \t]+<([^>\n]+)>\n([\s\S]*)$/);return e?`<${e[1]}>
14
- ${e[2]}`:r.startsWith(`[\u7FA4\u6D88\u606F]
15
- `)?r.slice(6):r}function g(n){const r=l(n);return r?`id:${r}`:["body",h(n.text),...(n.attachments??[]).map(e=>e.path||`${e.name}:${e.mimeType}`)].join(`
16
- `)}function l(n){const r=typeof n.clientMessageId=="string"?n.clientMessageId.trim():"";if(r)return r;const e=typeof n.id=="string"?n.id.trim():"";return e&&!e.startsWith("queue-")?e:""}function v(n){const r=new Set,e=[];for(const t of n){const i=t.path||`${t.name}:${t.mimeType}`;r.has(i)||(r.add(i),e.push(t))}return e.length?e:void 0}function h(n){return String(n||"").replace(/\s+/g," ").trim()}function O(n,r){const e=n.toLowerCase();if(e.includes("managed claim session conflicts with source binding"))return"managed_claim_source_binding_conflict";const t=e.match(/\b(?:managed_(?:agent|room)|agent_validation|acp|native|codex)_[a-z0-9_]+\b/)?.[0];return t||(e.includes("no rollout found")?"missing_rollout":e.includes("managed_room_permission_snapshot_mismatch")?"managed_room_permission_snapshot_mismatch":e.includes("managed_room_prompt_snapshot_mismatch")?"managed_room_prompt_snapshot_mismatch":e.includes("managed_room_turn_preparer_unavailable")?"managed_room_turn_preparer_unavailable":e.includes("timeout")?"timeout":e.includes("connection")?"connection_error":r)}function T(n,r){if(n.sessions.has(r.sessionId))return null;const e=p().find(t=>t.sessionId===r.sessionId)?.agentSessionId?.trim();return!e||e.startsWith("managed:")?null:e}export{_ as OWNER_DIRECT_TURN_OPTIONS,O as classifyQueueError,v as dedupeQueuedAttachments,R as findDuplicateQueuedMessage,M as formatQueuedBatch,s as isControllableQueueMessage,I as managedDirectTurnOptions,y as normalizeQueuedModelId,T as resolveManagedRoomNativeSessionId,b as stripLocalQueueFields,S as takeCompatibleBatch,D as takeControllableMessage};
13
+ `)}`}function k(n){const e=n.trim(),r=e.match(/^\[群消息\][ \t]+<([^>\n]+)>\n([\s\S]*)$/);return r?`<${r[1]}>
14
+ ${r[2]}`:e.startsWith(`[\u7FA4\u6D88\u606F]
15
+ `)?e.slice(6):e}function g(n){const e=l(n);return e?`id:${e}`:["body",h(n.text),...(n.attachments??[]).map(r=>r.path||`${r.name}:${r.mimeType}`)].join(`
16
+ `)}function l(n){const e=typeof n.clientMessageId=="string"?n.clientMessageId.trim():"";if(e)return e;const r=typeof n.id=="string"?n.id.trim():"";return r&&!r.startsWith("queue-")?r:""}function M(n){const e=new Set,r=[];for(const t of n){const i=t.path||`${t.name}:${t.mimeType}`;e.has(i)||(e.add(i),r.push(t))}return r.length?r:void 0}function h(n){return String(n||"").replace(/\s+/g," ").trim()}function v(n,e){const r=n.toLowerCase();if(r.includes("managed claim session conflicts with source binding"))return"managed_claim_source_binding_conflict";const t=r.match(/\b(?:managed_(?:agent|room)|agent_validation|acp|native|codex)_[a-z0-9_]+\b/)?.[0];return t||(r.includes("no rollout found")?"missing_rollout":r.includes("managed_room_permission_snapshot_mismatch")?"managed_room_permission_snapshot_mismatch":r.includes("managed_room_prompt_snapshot_mismatch")?"managed_room_prompt_snapshot_mismatch":r.includes("managed_room_turn_preparer_unavailable")?"managed_room_turn_preparer_unavailable":r.includes("timeout")?"timeout":r.includes("connection")?"connection_error":e)}function C(n,e){if(n.sessions.has(e.sessionId))return null;const r=p().find(t=>t.sessionId===e.sessionId)?.agentSessionId?.trim();return!r||r.startsWith("managed:")?null:r}export{_ as OWNER_DIRECT_TURN_OPTIONS,I as SCHEDULED_ROOM_TURN_OPTIONS,v as classifyQueueError,M as dedupeQueuedAttachments,S as findDuplicateQueuedMessage,T as formatQueuedBatch,s as isControllableQueueMessage,R as managedDirectTurnOptions,y as normalizeQueuedModelId,C as resolveManagedRoomNativeSessionId,O as stripLocalQueueFields,b as takeCompatibleBatch,D as takeControllableMessage};
@@ -1 +1 @@
1
- import{NativeSourceDeletionStore as K}from"../native-fusion/native-source-deletions.js";import{QueueRetryScheduler as G}from"./queue-retry.js";import{findDuplicateQueuedMessage as P,stripLocalQueueFields as H,takeCompatibleBatch as b,formatQueuedBatch as V,dedupeQueuedAttachments as X,classifyQueueError as Y,normalizeQueuedModelId as k,resolveManagedRoomNativeSessionId as E,managedDirectTurnOptions as W}from"./queue-helpers.js";import{CODEX_DESKTOP_SEND_UNAVAILABLE as Z}from"@shennian/wire";import{isCodexThreadTailInterrupted as ee}from"../native-fusion/codex-files.js";import{mergeProjectedSessions as te}from"./projection.js";import{assertFinishedAttachmentReferences as ne,markAttachmentReferences as se}from"./attachment-transfer-store.js";import{appendMessage as F,getMessageDeliveryStatus as x,listSessionRecords as A,recordSession as L,tombstoneMessage as ie,upsertMessage as re}from"./store.js";import{handleQueueDispatchFailure as ae,queueBlockedUntil as O,resolveQueueRecoveryNotice as j}from"./queue-dispatch-failure.js";import{resetCommandSpecCache as oe}from"../agents/command-spec.js";import{requestSessionIndexPublish as y}from"./index-publisher.js";import{clearPersistedManagerRoomOrigins as de,purgeQueuedSessionData as ue,readQueue as h,writeQueue as w}from"./queue-storage.js";import{parsePersonalAttachmentReferences as le}from"./attachment-reference.js";import{getPersonalSyncIdentity as N}from"../personal-sync/epoch.js";import{getDaemonInstallationId as z}from"../personal-sync/identity.js";import{isStewardSessionId as B,pinStewardWorkDir as ge}from"../steward/session.js";import{classifyStewardFailure as ce}from"../steward/failover.js";import{tryStewardFailover as me}from"./handlers/steward.js";import{isTrustedManagerEvent as he}from"./manager-event-authority.js";import{getQueueSnapshot as pe,handleQueueDelete as fe,handleQueueEdit as Ie,handleQueueGet as Se,handleQueuePromote as we}from"./queue-control.js";import{TerminalQueuedChatDispatchError as $,nowIso as J,queueEnvelope as Q,queueMessageFromParams as U}from"./queue-message.js";import{purgeQueuedSessionData as Je}from"./queue-storage.js";import{TerminalQueuedChatDispatchError as Ke}from"./queue-message.js";class Ne{opts;validateScheduledTarget;async enqueueScheduled(e){return this.handleEnqueue(e,!0)}draining=new Set;promoting=new Set;disposed=!1;retries=new G(e=>{this.wakeSession(e)});deletions=new K;inFlightMessageIds=new Map;deferredLogState=new Map;prepareManagedRoomTurn=null;prepareManagedAgentDirectTurn=null;constructor(e){this.opts=e,de(),setTimeout(()=>this.drainIdleQueues(),0).unref?.()}stop(){this.disposed=!0,this.retries.stop()}getSnapshot(e){return pe({getRuntime:this.opts.getRuntime,inFlightMessageIds:this.inFlightMessageIds,broadcast:t=>this.broadcast(t)},e)}async switchUnavailableSteward(e,t,n){const i=n instanceof Error?n.message:String(n);return ce(i)==="crashed"||!t.text?!1:me(this.opts.getRuntime(),e,{agentType:t.agentType},{state:"error",runId:"",message:i},t.text).catch(()=>!1)}isImmediateSendAvailable(e){const t=this.opts.getRuntime(),n=t.sessions.get(e);return n?.currentRunId?n.journalRunId?t.runJournal?.get(e,n.journalRunId)?.deliveryMode==="direct":!1:!0}setManagedRoomTurnPreparer(e){this.prepareManagedRoomTurn=e}setManagedAgentDirectTurnPreparer(e){this.prepareManagedAgentDirectTurn=e}async enqueueManagedRoomBatch(e){if(e.length===0)return;const t=this.opts.getRuntime(),n=h(),i=new Set,r=new Map;let d=!1;for(const s of e){const a=s.params;if(this.deletions.hasSession(a.sessionId)){delete n.sessions[a.sessionId],d=!0;continue}if(!a.sessionId||!a.text||!a.agentType||!a.workDir)throw new Error("sessionId, text, agentType and workDir are required");const l=U({...N(z()),...a});typeof a.roomMessageCreatedAt=="string"&&Number.isFinite(Date.parse(a.roomMessageCreatedAt))&&(l.createdAt=new Date(a.roomMessageCreatedAt).toISOString()),l.origin="room",l.managedRoom=s.context,l.trigger={kind:"room_activation",...s.context};const o=n.sessions[a.sessionId]??[],m=P(o,l),c=l.clientMessageId??l.id,S=x(a.sessionId,c);if(!m&&S.state==="not_found")o.push(l),n.sessions[a.sessionId]=o,r.set(`${l.sessionId}\0${c}`,l),i.add(a.sessionId),d=!0;else if(m&&S.state==="not_found")r.set(`${m.sessionId}\0${c}`,m),i.add(a.sessionId);else if(m&&S.state==="queued")i.add(a.sessionId);else if(m){const I=o.filter(f=>f.id!==m.id);I.length?n.sessions[a.sessionId]=I:delete n.sessions[a.sessionId],d=!0}}d&&w(n);let u;for(const s of i)try{for(const a of r.values())a.sessionId===s&&(F(s,Q(a),"queued"),L({sessionId:s,agentType:a.agentType,sessionMode:a.sessionMode,managerConfig:a.managerConfig,workDir:a.workDir,agentSessionId:E(t,a),modelId:a.modelId}));this.logLifecycle("enqueue.persisted",s,{origin:"room",pendingCount:h().sessions[s]?.length??0}),this.broadcast(s),this.wakeSession(s)}catch(a){u=a,this.logLifecycle("enqueue.commit-failed",s,{failureClass:Y(a instanceof Error?a.message:"","canonical_commit_failed")},"error"),this.retries.schedule(s,!0)}if(i.size&&y(t.client),u)throw u}async handleEnqueue(e,t=!1){const n=this.opts.getRuntime(),i=e.params;if(i.scheduledTask&&!t)throw new Error("schedule_source_untrusted");if((i.managerEventId||i.managerEventRoomOrigin||i.managedWorkerParentSessionId||i.managerWorkerRoomOrigin||e.params.managerWorkerNativeFull||e.params.managedRecoverySource)&&!he(e))throw new Error("manager_event_source_untrusted");const r=!t&&!i.managedWorkerParentSessionId?n.managerRuntime?.getWorkerControllerSessionId?.(String(i.sessionId??""),String(i.workDir??"")):null,d=r?{...i,managedWorkerParentSessionId:r}:i,u=!t&&(B(String(d.sessionId??""))||d.sessionScope==="steward");if(u){if((d.sessionMode??"standard")!=="standard")throw new Error("steward_session_mode_invalid");if(!B(d.sessionId)&&A().some(q=>q.sessionId===d.sessionId))throw new Error("steward_scope_conflict")}const s=u?{...d,workDir:ge(),sessionMode:"standard"}:d,a=!!(t&&s.scheduledTask?.bindingId);if(te(s.sessionListProjection),!s.sessionId||!s.text||!s.agentType||!s.workDir)return n.client.sendRes({type:"res",id:e.id,ok:!1,error:"sessionId, text, agentType and workDir are required"}),!1;const l=W(s.managerEventId?{roomOrigin:s.managerEventRoomOrigin}:null,!!s.managedAgentDirect),o=s.managedAgentDirect||a?await this.prepareManagedAgentDirectTurn?.(s.sessionId,l):null;if((s.managedAgentDirect||a)&&!o)throw new Error("managed_agent_context_unavailable");const m=o?A().find(q=>q.sessionId===s.sessionId):null,c=o?{...s,...o,agentType:o.agentType,sessionMode:o.sessionMode,managerConfig:o.managerConfig,workDir:o.workDir,agentSessionId:o.agentSessionId?.startsWith("managed:")?m?.agentSessionId&&!m.agentSessionId.startsWith("managed:")?m.agentSessionId:null:o.agentSessionId,modelId:o.effectiveModelId!==void 0?k(o.effectiveModelId):m?.modelId??void 0,systemPrompt:o.systemPrompt,externalChannel:s.managedAgentDirect?null:s.externalChannel,replyTarget:s.managedAgentDirect?null:s.replyTarget,managerDefaultWorkerAgentType:o.managerDefaultWorkerAgentType,managerDefaultWorkerModelId:o.managerDefaultWorkerModelId}:s,S=n.resolvePath(c.workDir),I=le(c.attachments);I?.length&&ne(S,I);const f={text:c.text,attachments:I,localized:!1},T=n.sessions.get(c.sessionId);if(c.agentType==="codex"&&c.agentSessionId&&T?.currentRunId?.startsWith("dispatch:")&&ee(c.agentSessionId))return n.client.sendRes({type:"res",id:e.id,ok:!1,error:Z}),!1;o?.managedRoomContextToken&&n.revokeManagedRoomContextToken?.(o.managedRoomContextToken);const C=await this.isSessionBusy(c.sessionId),M=h(),_=M.sessions[c.sessionId]??[],g=U({...c,text:f.text,attachments:f.attachments,systemPrompt:o?null:c.systemPrompt});o&&(s.managedAgentDirect&&(g.managedAgentDirect=!0),g.trigger?.kind!=="manager_event"&&g.trigger?.kind!=="scheduled"&&(g.trigger={kind:"managed_direct"}));const v=g.clientMessageId??g.id,R=x(c.sessionId,v);if(R.state!=="not_found")return n.client.sendRes({type:"res",id:e.id,ok:!0,payload:{queued:R.state==="queued",queueMessageId:g.id,...R,queue:this.getSnapshot(c.sessionId)}}),!0;const D=P(_,g);D||(M.sessions[c.sessionId]=[..._,g],w(M));const p=D??g;return L({sessionId:p.sessionId,agentType:p.agentType,sessionMode:p.sessionMode,managerConfig:p.managerConfig,workDir:p.workDir,agentSessionId:p.agentSessionId,modelId:p.modelId,...u?{sessionScope:"steward"}:{}}),F(p.sessionId,Q(p),"queued"),se(n.resolvePath(p.workDir),p.attachments??[]),y(n.client),this.logLifecycle("enqueue.persisted",c.sessionId,{origin:c.origin??"app",queueMessageId:p.id,pendingCount:(h().sessions[c.sessionId]??[]).length}),this.broadcast(c.sessionId),n.client.sendRes({type:"res",id:e.id,ok:!0,payload:{queued:!0,queueMessageId:D?.id??g.id,...x(c.sessionId,D?.clientMessageId??D?.id??g.clientMessageId??g.id),queue:this.getSnapshot(c.sessionId),...f.localized?{localizedAttachments:!0}:{}}}),C?this.retries.schedule(c.sessionId):this.wakeSession(c.sessionId),!0}async handleGet(e){await Se(this.queueControlContext(),e)}async handleEdit(e){await Ie(this.queueControlContext(),e)}async handleDelete(e){await fe(this.queueControlContext(),e)}queueControlContext(){return{getRuntime:this.opts.getRuntime,inFlightMessageIds:this.inFlightMessageIds,broadcast:e=>this.broadcast(e)}}async handlePromote(e){await we({...this.queueControlContext(),promoting:this.promoting,draining:this.draining,isImmediateSendAvailable:t=>this.isImmediateSendAvailable(t),canInjectActiveBatch:(t,n)=>this.canInjectActiveBatch(t,n),interruptQueuedSession:this.opts.interruptQueuedSession,dispatchQueuedMessages:t=>this.dispatchQueuedMessages(t),markExternalQueued:(t,n)=>this.markExternalQueued(t,n),removeBatch:(t,n)=>this.removeBatch(t,n),wakeSession:t=>this.wakeSession(t)},e)}isDispatching(e){return this.inFlightMessageIds.has(e)}noteTerminal(e){const t=h().sessions[e]?.find(n=>!!n.externalQueuedSubmissionId);t&&this.noteExternalClaim(e,t.clientMessageId??t.id),this.wakeSession(e)}purgeSession(e){ue(e),this.retries.cancel(e)}discardPendingManagedRoomMessages(e){if(this.deletions.hasSession(e)){const u=h().sessions[e]?.length??0;return this.purgeSession(e),u}const t=h(),n=t.sessions[e]??[],i=this.inFlightMessageIds.get(e)??new Set,r=n.filter(u=>u.managedRoom&&!i.has(u.id));if(r.length===0)return 0;const d=n.filter(u=>!r.includes(u));d.length?t.sessions[e]=d:delete t.sessions[e],w(t);for(const u of r)ie(e,u.clientMessageId??u.id);return y(this.opts.getRuntime().client),this.logLifecycle("managed-room.discarded-paused",e,{discardedCount:r.length,pendingCount:d.length}),this.broadcast(e),r.length}wakeSession(e){this.drainNext(e).catch(()=>{this.logLifecycle("drain.retry-required",e,{},"error"),this.retries.schedule(e,!0)})}drainIdleQueues(){if(this.disposed)return;const e=h();for(const t of Object.keys(e.sessions))this.wakeSession(t)}async drainNext(e){if(this.disposed||this.draining.has(e)||this.promoting.has(e))return;this.draining.add(e);let t=!1,n=!1,i=[];try{if(this.deletions.hasSession(e)){this.purgeSession(e);return}if(await this.isSessionBusy(e)){const o=h().sessions[e]?.length??0,m=this.deferredLogState.get(e),c=Date.now();(!m||m.pendingCount!==o||c-m.at>=3e4)&&(this.logLifecycle("drain.deferred",e,{pendingCount:o}),this.deferredLogState.set(e,{at:c,pendingCount:o}));return}this.deferredLogState.delete(e);const r=h(),d=r.sessions[e]??[],u=d.filter(o=>{const m=o.clientMessageId??o.id,c=x(e,m).state;return c==="queued"||c==="not_found"});if(u.length!==d.length&&(u.length?r.sessions[e]=u:delete r.sessions[e],w(r),this.logLifecycle("drain.pruned-terminal",e,{prunedCount:d.length-u.length,pendingCount:u.length})),u.some(o=>!!o.externalQueuedSubmissionId)){this.broadcast(e);return}const s=b(u);if(s.length===0){this.broadcast(e);return}if(O(s))return;s.some(o=>(o.dispatchBlock?.retryAt??0)>0)&&oe(),i=s,this.inFlightMessageIds.set(e,new Set(s.map(o=>o.id))),this.logLifecycle("dispatch.start",e,{batchCount:s.length,queueMessageId:s[0].id,origin:s[0].origin??"app"}),this.broadcast(e);for(const o of s)re(e,Q(o),"queued");const a=await this.dispatchQueuedMessages(s);if(a.deliveryMode==="external_owner_queue"){this.markExternalQueued(s,a.queuedSubmissionId),j(s),s.some(o=>o.dispatchBlock)&&y(this.opts.getRuntime().client),this.logLifecycle("dispatch.external-queued",e,{batchCount:s.length,queueMessageId:s[0].id}),this.broadcast(e);return}const l=this.removeBatch(e,s);j(s),s.some(o=>o.dispatchBlock)&&y(this.opts.getRuntime().client),this.logLifecycle("dispatch.accepted",e,{batchCount:s.length,queueMessageId:s[0].id,pendingCount:l}),this.deferredLogState.delete(e),t=l>0,this.broadcast(e)}catch(r){const d=i[0];if(d&&B(e)&&await this.switchUnavailableSteward(e,d,r)){this.removeBatch(e,i),this.broadcast(e);return}const u=ae({error:r,sessionId:e,batch:i,publish:()=>y(this.opts.getRuntime().client),isManagedWorker:!!this.opts.getRuntime().managerRuntime?.isManagedWorkerSession(e),removeBatch:()=>this.removeBatch(e,i),log:(s,a)=>this.logLifecycle(s,e,a,"error")});t=u.drainAgain,n=u.transientFailure,this.broadcast(e)}finally{this.inFlightMessageIds.delete(e),this.draining.delete(e);const r=h().sessions[e]??[];r.length?(this.broadcast(e),r.some(d=>!!d.externalQueuedSubmissionId)?this.retries.cancel(e):t?queueMicrotask(()=>this.wakeSession(e)):this.retries.schedule(e,n,O(b(r)))):this.retries.cancel(e)}}noteExternalClaim(e,t){const n=h(),i=n.sessions[e]??[],r=i.filter(d=>(d.clientMessageId??d.id)!==t);r.length!==i.length&&(r.length?n.sessions[e]=r:delete n.sessions[e],w(n),this.broadcast(e))}canInjectActiveBatch(e,t){if(!e.adapter.supportsActiveInput||!e.adapter.injectActiveInput||!e.journalRunId)return!1;const n=this.opts.getRuntime().runJournal?.get(t[0].sessionId,e.journalRunId),i=t[0].trigger?.kind==="managed_direct"||t[0].managedAgentDirect?null:"personal";return!!(i&&t[0].systemPrompt==null&&n&&n.source===i&&n.deliveryMode==="direct"&&n.agentType===t[0].agentType&&n.workDir===e.workDir&&n.agentSessionId===e.agentSessionId&&n.modelId===(t[0].modelId??null)&&n.reasoningEffort===(t[0].reasoningEffort??null))}removeBatch(e,t){if(t.length===0)return h().sessions[e]?.length??0;const n=h(),i=new Set(t.map(d=>d.id)),r=(n.sessions[e]??[]).filter(d=>!i.has(d.id));return r.length?n.sessions[e]=r:delete n.sessions[e],w(n),r.length}logLifecycle(e,t,n,i="info"){const r=`[chat.queue] ${JSON.stringify({at:J(),event:e,sessionId:t,...n})}`;i==="error"?console.error(r):console.info(r)}async dispatchQueuedMessages(e){const t=e[0],n=t.trigger?.kind==="scheduled"?t.trigger:null;if(n&&await this.validateScheduledTarget?.({sessionId:t.sessionId,...n})!=="ready")throw new $("schedule_target_unavailable");const i=e.flatMap(g=>{if(g.trigger?.kind==="room_activation"){const{kind:v,...R}=g.trigger;return[R]}return!g.trigger&&g.managedRoom?[g.managedRoom]:[]}),r=e.find(g=>g.trigger?.kind==="manager_event")?.trigger,d=e.some(g=>g.trigger?.kind==="managed_direct"||!!g.managedAgentDirect),u=d||!!n?.bindingId,s=e.find(g=>g.trigger?.kind==="manager_worker")?.trigger,a=r?.kind==="manager_event"||d,l=i.length>0?await this.prepareManagedRoomTurn?.(i):u||r?.kind==="manager_event"?await this.prepareManagedAgentDirectTurn?.(t.sessionId,W(r?.kind==="manager_event"?r:null,d)):void 0;if(i.length>0&&!l)throw new Error("managed_room_turn_preparer_unavailable");if(u&&!l)throw new Error("managed_agent_context_unavailable");if(r?.kind==="manager_event"&&this.opts.getRuntime().managerRuntime?.isManagedRoomBoundManager(t.sessionId)&&!l)throw new Error("managed_agent_context_unavailable");const o=new Set((h().sessions[t.sessionId]??[]).map(g=>g.id));if(this.disposed||this.deletions.hasSession(t.sessionId)||e.some(g=>!o.has(g.id)))throw l?.managedRoomContextToken&&this.opts.getRuntime().revokeManagedRoomContextToken?.(l.managedRoomContextToken),this.disposed?new Error("queue_stopped"):new $("queued_dispatch_cancelled");const m=l??null,c=m?.sessionMode==="manager"?m.managerConfig:null,S=e.length===1?t.text:V(e),I=X(e.flatMap(g=>g.attachments??[])),f=u||r?.kind==="manager_event"&&!!l,T=f?l.agentSessionId?.startsWith("managed:")?E(this.opts.getRuntime(),t):l.agentSessionId:i.length>0?E(this.opts.getRuntime(),t):t.agentSessionId??null,C=l?A().find(g=>g.sessionId===t.sessionId):null,M=l?.effectiveModelId!==void 0?k(l.effectiveModelId):k(C?.modelId)??k(t.modelId),_=l?.effectiveModelId!==void 0?"room_effective_model":k(C?.modelId)?"persisted_session_model":k(t.modelId)?"queued_message_model":"pi_default_model";return await this.opts.dispatchQueuedReq({type:"req",id:`queue-send-${t.id}-${Date.now()}`,method:"chat.send",params:{...N(z()),sessionId:t.sessionId,text:S,agentType:f?l.agentType:t.agentType,sessionMode:m?.sessionMode??t.sessionMode,managerConfig:m?c:t.managerConfig,workDir:f?l.workDir:t.workDir,agentSessionId:T,modelId:M,modelSelectionSource:_,systemPrompt:l?.systemPrompt??t.systemPrompt??null,managerDefaultWorkerAgentType:m?m.managerDefaultWorkerAgentType:t.managerDefaultWorkerAgentType,managerDefaultWorkerModelId:m?m.managerDefaultWorkerModelId:t.managerDefaultWorkerModelId,reasoningEffort:t.reasoningEffort??void 0,clientMessageId:t.clientMessageId??t.id,attachments:I,externalChannel:a?void 0:t.externalChannel,replyTarget:a?void 0:t.replyTarget,roomContextRegistryKey:a?void 0:l?.roomContextRegistryKey,activationCauseMessageId:a?void 0:i.at(-1)?.causeMessageId,rootCauseMessageId:a?void 0:i.at(-1)?.rootCauseMessageId,activationSequence:a?void 0:i.at(-1)?.sequence,activationHopCount:a?void 0:i.at(-1)?.hopCount,managedRecoverySource:r?.kind==="manager_event"?"manager_event":u?"managed_direct":i.length>0?"managed_room":void 0,managerEventId:r?.kind==="manager_event"?r.eventId:void 0,managedWorkerParentSessionId:s?.kind==="manager_worker"?s.parentSessionId:void 0,managerWorkerRoomOrigin:s?.kind==="manager_worker"?s.roomOrigin:void 0,managerWorkerNativeFull:s?.kind==="manager_worker"&&this.opts.getRuntime().managerRuntime?.isExternalWorkerController(s.parentSessionId,t.workDir)||void 0,managedRoomContextToken:l?.managedRoomContextToken,scheduledDelivery:!!n,suppressExternalOwnerEcho:i.length>0||!!n||void 0,queuedBatchItems:e.map(g=>{const v=H(g);return a?{...v,systemPrompt:l?.systemPrompt??null,externalChannel:null,replyTarget:null}:v}),waitForDispatch:!0}},l??void 0)??{}}markExternalQueued(e,t){const n=h(),i=new Set(e.map(u=>u.id)),r=n.sessions[e[0].sessionId]??[];let d=!1;for(const u of r)i.has(u.id)&&(u.externalQueuedSubmissionId=t||u.id,u.updatedAt=J(),d=!0);d&&w(n)}async isSessionBusy(e){const t=this.opts.getRuntime().recoveryBarrier;if(t?.isDispatchFrozen()||t?.isRecovering(e))return!0;const n=this.opts.getRuntime().sessions.get(e);if(!n)return!1;if(n.currentRunId){if(!(n.currentRunId.startsWith("dispatch:")&&!!this.opts.getRuntime().runJournal&&!n.journalRunId)||(n.adapter.getStatus?await n.adapter.getStatus().catch(()=>null):null)?.active)return!0;this.logLifecycle("drain.recovered-stale-dispatch",e,{staleRunId:n.currentRunId}),n.currentRunId=null,n.currentRunPhase=null}if(!n.adapter.getStatus)return!1;const i=await n.adapter.getStatus().catch(()=>null);return i?.active?(i.runId&&(n.currentRunId=i.runId,n.currentRunPhase=i.runPhase??n.currentRunPhase),!0):!1}broadcast(e){this.opts.getRuntime().client.sendEvent({type:"event",event:"session.queue.update",payload:{queue:this.getSnapshot(e)}})}}export{Ne as ChatQueueManager,Ke as TerminalQueuedChatDispatchError,Je as purgeQueuedSessionData};
1
+ import{NativeSourceDeletionStore as G}from"../native-fusion/native-source-deletions.js";import{QueueRetryScheduler as H}from"./queue-retry.js";import{findDuplicateQueuedMessage as P,stripLocalQueueFields as V,takeCompatibleBatch as b,formatQueuedBatch as X,dedupeQueuedAttachments as Y,classifyQueueError as Z,normalizeQueuedModelId as k,resolveManagedRoomNativeSessionId as E,managedDirectTurnOptions as W,SCHEDULED_ROOM_TURN_OPTIONS as F}from"./queue-helpers.js";import{CODEX_DESKTOP_SEND_UNAVAILABLE as ee}from"@shennian/wire";import{isCodexThreadTailInterrupted as te}from"../native-fusion/codex-files.js";import{mergeProjectedSessions as ne}from"./projection.js";import{assertFinishedAttachmentReferences as se,markAttachmentReferences as ie}from"./attachment-transfer-store.js";import{appendMessage as L,getMessageDeliveryStatus as x,listSessionRecords as A,recordSession as O,tombstoneMessage as re,upsertMessage as ae}from"./store.js";import{handleQueueDispatchFailure as oe,queueBlockedUntil as j,resolveQueueRecoveryNotice as N}from"./queue-dispatch-failure.js";import{resetCommandSpecCache as de}from"../agents/command-spec.js";import{requestSessionIndexPublish as y}from"./index-publisher.js";import{clearPersistedManagerRoomOrigins as ue,purgeQueuedSessionData as le,readQueue as h,writeQueue as w}from"./queue-storage.js";import{parsePersonalAttachmentReferences as ge}from"./attachment-reference.js";import{getPersonalSyncIdentity as z}from"../personal-sync/epoch.js";import{getDaemonInstallationId as $}from"../personal-sync/identity.js";import{isStewardSessionId as B,pinStewardWorkDir as ce}from"../steward/session.js";import{classifyStewardFailure as me}from"../steward/failover.js";import{tryStewardFailover as he}from"./handlers/steward.js";import{isTrustedManagerEvent as pe}from"./manager-event-authority.js";import{getQueueSnapshot as fe,handleQueueDelete as Ie,handleQueueEdit as Se,handleQueueGet as we,handleQueuePromote as ke}from"./queue-control.js";import{TerminalQueuedChatDispatchError as U,nowIso as J,queueEnvelope as Q,queueMessageFromParams as K}from"./queue-message.js";import{purgeQueuedSessionData as Je}from"./queue-storage.js";import{TerminalQueuedChatDispatchError as Ge}from"./queue-message.js";class ze{opts;validateScheduledTarget;async enqueueScheduled(e){return this.handleEnqueue(e,!0)}draining=new Set;promoting=new Set;disposed=!1;retries=new H(e=>{this.wakeSession(e)});deletions=new G;inFlightMessageIds=new Map;deferredLogState=new Map;prepareManagedRoomTurn=null;prepareManagedAgentDirectTurn=null;constructor(e){this.opts=e,ue(),setTimeout(()=>this.drainIdleQueues(),0).unref?.()}stop(){this.disposed=!0,this.retries.stop()}getSnapshot(e){return fe({getRuntime:this.opts.getRuntime,inFlightMessageIds:this.inFlightMessageIds,broadcast:t=>this.broadcast(t)},e)}async switchUnavailableSteward(e,t,n){const i=n instanceof Error?n.message:String(n);return me(i)==="crashed"||!t.text?!1:he(this.opts.getRuntime(),e,{agentType:t.agentType},{state:"error",runId:"",message:i},t.text).catch(()=>!1)}isImmediateSendAvailable(e){const t=this.opts.getRuntime(),n=t.sessions.get(e);return n?.currentRunId?n.journalRunId?t.runJournal?.get(e,n.journalRunId)?.deliveryMode==="direct":!1:!0}setManagedRoomTurnPreparer(e){this.prepareManagedRoomTurn=e}setManagedAgentDirectTurnPreparer(e){this.prepareManagedAgentDirectTurn=e}async enqueueManagedRoomBatch(e){if(e.length===0)return;const t=this.opts.getRuntime(),n=h(),i=new Set,a=new Map;let d=!1;for(const s of e){const r=s.params;if(this.deletions.hasSession(r.sessionId)){delete n.sessions[r.sessionId],d=!0;continue}if(!r.sessionId||!r.text||!r.agentType||!r.workDir)throw new Error("sessionId, text, agentType and workDir are required");const l=K({...z($()),...r});typeof r.roomMessageCreatedAt=="string"&&Number.isFinite(Date.parse(r.roomMessageCreatedAt))&&(l.createdAt=new Date(r.roomMessageCreatedAt).toISOString()),l.origin="room",l.managedRoom=s.context,l.trigger={kind:"room_activation",...s.context};const o=n.sessions[r.sessionId]??[],m=P(o,l),c=l.clientMessageId??l.id,S=x(r.sessionId,c);if(!m&&S.state==="not_found")o.push(l),n.sessions[r.sessionId]=o,a.set(`${l.sessionId}\0${c}`,l),i.add(r.sessionId),d=!0;else if(m&&S.state==="not_found")a.set(`${m.sessionId}\0${c}`,m),i.add(r.sessionId);else if(m&&S.state==="queued")i.add(r.sessionId);else if(m){const I=o.filter(f=>f.id!==m.id);I.length?n.sessions[r.sessionId]=I:delete n.sessions[r.sessionId],d=!0}}d&&w(n);let u;for(const s of i)try{for(const r of a.values())r.sessionId===s&&(L(s,Q(r),"queued"),O({sessionId:s,agentType:r.agentType,sessionMode:r.sessionMode,managerConfig:r.managerConfig,workDir:r.workDir,agentSessionId:E(t,r),modelId:r.modelId}));this.logLifecycle("enqueue.persisted",s,{origin:"room",pendingCount:h().sessions[s]?.length??0}),this.broadcast(s),this.wakeSession(s)}catch(r){u=r,this.logLifecycle("enqueue.commit-failed",s,{failureClass:Z(r instanceof Error?r.message:"","canonical_commit_failed")},"error"),this.retries.schedule(s,!0)}if(i.size&&y(t.client),u)throw u}async handleEnqueue(e,t=!1){const n=this.opts.getRuntime(),i=e.params;if(i.scheduledTask&&!t)throw new Error("schedule_source_untrusted");if((i.managerEventId||i.managerEventRoomOrigin||i.managedWorkerParentSessionId||i.managerWorkerRoomOrigin||e.params.managerWorkerNativeFull||e.params.managedRecoverySource)&&!pe(e))throw new Error("manager_event_source_untrusted");const a=!t&&!i.managedWorkerParentSessionId?n.managerRuntime?.getWorkerControllerSessionId?.(String(i.sessionId??""),String(i.workDir??"")):null,d=a?{...i,managedWorkerParentSessionId:a}:i,u=!t&&(B(String(d.sessionId??""))||d.sessionScope==="steward");if(u){if((d.sessionMode??"standard")!=="standard")throw new Error("steward_session_mode_invalid");if(!B(d.sessionId)&&A().some(q=>q.sessionId===d.sessionId))throw new Error("steward_scope_conflict")}const s=u?{...d,workDir:ce(),sessionMode:"standard"}:d,r=!!(t&&s.scheduledTask?.bindingId);if(ne(s.sessionListProjection),!s.sessionId||!s.text||!s.agentType||!s.workDir)return n.client.sendRes({type:"res",id:e.id,ok:!1,error:"sessionId, text, agentType and workDir are required"}),!1;const l=r?F:W(s.managerEventId?{roomOrigin:s.managerEventRoomOrigin}:null,!!s.managedAgentDirect),o=s.managedAgentDirect||r?await this.prepareManagedAgentDirectTurn?.(s.sessionId,l):null;if((s.managedAgentDirect||r)&&!o)throw new Error("managed_agent_context_unavailable");const m=o?A().find(q=>q.sessionId===s.sessionId):null,c=o?{...s,...o,agentType:o.agentType,sessionMode:o.sessionMode,managerConfig:o.managerConfig,workDir:o.workDir,agentSessionId:o.agentSessionId?.startsWith("managed:")?m?.agentSessionId&&!m.agentSessionId.startsWith("managed:")?m.agentSessionId:null:o.agentSessionId,modelId:o.effectiveModelId!==void 0?k(o.effectiveModelId):m?.modelId??void 0,systemPrompt:o.systemPrompt,externalChannel:s.managedAgentDirect?null:s.externalChannel,replyTarget:s.managedAgentDirect?null:s.replyTarget,managerDefaultWorkerAgentType:o.managerDefaultWorkerAgentType,managerDefaultWorkerModelId:o.managerDefaultWorkerModelId}:s,S=n.resolvePath(c.workDir),I=ge(c.attachments);I?.length&&se(S,I);const f={text:c.text,attachments:I,localized:!1},T=n.sessions.get(c.sessionId);if(c.agentType==="codex"&&c.agentSessionId&&T?.currentRunId?.startsWith("dispatch:")&&te(c.agentSessionId))return n.client.sendRes({type:"res",id:e.id,ok:!1,error:ee}),!1;o?.managedRoomContextToken&&n.revokeManagedRoomContextToken?.(o.managedRoomContextToken);const C=await this.isSessionBusy(c.sessionId),M=h(),_=M.sessions[c.sessionId]??[],g=K({...c,text:f.text,attachments:f.attachments,systemPrompt:o?null:c.systemPrompt});o&&(s.managedAgentDirect&&(g.managedAgentDirect=!0),g.trigger?.kind!=="manager_event"&&g.trigger?.kind!=="scheduled"&&(g.trigger={kind:"managed_direct"}));const v=g.clientMessageId??g.id,R=x(c.sessionId,v);if(R.state!=="not_found")return n.client.sendRes({type:"res",id:e.id,ok:!0,payload:{queued:R.state==="queued",queueMessageId:g.id,...R,queue:this.getSnapshot(c.sessionId)}}),!0;const D=P(_,g);D||(M.sessions[c.sessionId]=[..._,g],w(M));const p=D??g;return O({sessionId:p.sessionId,agentType:p.agentType,sessionMode:p.sessionMode,managerConfig:p.managerConfig,workDir:p.workDir,agentSessionId:p.agentSessionId,modelId:p.modelId,...u?{sessionScope:"steward"}:{}}),L(p.sessionId,Q(p),"queued"),ie(n.resolvePath(p.workDir),p.attachments??[]),y(n.client),this.logLifecycle("enqueue.persisted",c.sessionId,{origin:c.origin??"app",queueMessageId:p.id,pendingCount:(h().sessions[c.sessionId]??[]).length}),this.broadcast(c.sessionId),n.client.sendRes({type:"res",id:e.id,ok:!0,payload:{queued:!0,queueMessageId:D?.id??g.id,...x(c.sessionId,D?.clientMessageId??D?.id??g.clientMessageId??g.id),queue:this.getSnapshot(c.sessionId),...f.localized?{localizedAttachments:!0}:{}}}),C?this.retries.schedule(c.sessionId):this.wakeSession(c.sessionId),!0}async handleGet(e){await we(this.queueControlContext(),e)}async handleEdit(e){await Se(this.queueControlContext(),e)}async handleDelete(e){await Ie(this.queueControlContext(),e)}queueControlContext(){return{getRuntime:this.opts.getRuntime,inFlightMessageIds:this.inFlightMessageIds,broadcast:e=>this.broadcast(e)}}async handlePromote(e){await ke({...this.queueControlContext(),promoting:this.promoting,draining:this.draining,isImmediateSendAvailable:t=>this.isImmediateSendAvailable(t),canInjectActiveBatch:(t,n)=>this.canInjectActiveBatch(t,n),interruptQueuedSession:this.opts.interruptQueuedSession,dispatchQueuedMessages:t=>this.dispatchQueuedMessages(t),markExternalQueued:(t,n)=>this.markExternalQueued(t,n),removeBatch:(t,n)=>this.removeBatch(t,n),wakeSession:t=>this.wakeSession(t)},e)}isDispatching(e){return this.inFlightMessageIds.has(e)}noteTerminal(e){const t=h().sessions[e]?.find(n=>!!n.externalQueuedSubmissionId);t&&this.noteExternalClaim(e,t.clientMessageId??t.id),this.wakeSession(e)}purgeSession(e){le(e),this.retries.cancel(e)}discardPendingManagedRoomMessages(e){if(this.deletions.hasSession(e)){const u=h().sessions[e]?.length??0;return this.purgeSession(e),u}const t=h(),n=t.sessions[e]??[],i=this.inFlightMessageIds.get(e)??new Set,a=n.filter(u=>u.managedRoom&&!i.has(u.id));if(a.length===0)return 0;const d=n.filter(u=>!a.includes(u));d.length?t.sessions[e]=d:delete t.sessions[e],w(t);for(const u of a)re(e,u.clientMessageId??u.id);return y(this.opts.getRuntime().client),this.logLifecycle("managed-room.discarded-paused",e,{discardedCount:a.length,pendingCount:d.length}),this.broadcast(e),a.length}wakeSession(e){this.drainNext(e).catch(()=>{this.logLifecycle("drain.retry-required",e,{},"error"),this.retries.schedule(e,!0)})}drainIdleQueues(){if(this.disposed)return;const e=h();for(const t of Object.keys(e.sessions))this.wakeSession(t)}async drainNext(e){if(this.disposed||this.draining.has(e)||this.promoting.has(e))return;this.draining.add(e);let t=!1,n=!1,i=[];try{if(this.deletions.hasSession(e)){this.purgeSession(e);return}if(await this.isSessionBusy(e)){const o=h().sessions[e]?.length??0,m=this.deferredLogState.get(e),c=Date.now();(!m||m.pendingCount!==o||c-m.at>=3e4)&&(this.logLifecycle("drain.deferred",e,{pendingCount:o}),this.deferredLogState.set(e,{at:c,pendingCount:o}));return}this.deferredLogState.delete(e);const a=h(),d=a.sessions[e]??[],u=d.filter(o=>{const m=o.clientMessageId??o.id,c=x(e,m).state;return c==="queued"||c==="not_found"});if(u.length!==d.length&&(u.length?a.sessions[e]=u:delete a.sessions[e],w(a),this.logLifecycle("drain.pruned-terminal",e,{prunedCount:d.length-u.length,pendingCount:u.length})),u.some(o=>!!o.externalQueuedSubmissionId)){this.broadcast(e);return}const s=b(u);if(s.length===0){this.broadcast(e);return}if(j(s))return;s.some(o=>(o.dispatchBlock?.retryAt??0)>0)&&de(),i=s,this.inFlightMessageIds.set(e,new Set(s.map(o=>o.id))),this.logLifecycle("dispatch.start",e,{batchCount:s.length,queueMessageId:s[0].id,origin:s[0].origin??"app"}),this.broadcast(e);for(const o of s)ae(e,Q(o),"queued");const r=await this.dispatchQueuedMessages(s);if(r.deliveryMode==="external_owner_queue"){this.markExternalQueued(s,r.queuedSubmissionId),N(s),s.some(o=>o.dispatchBlock)&&y(this.opts.getRuntime().client),this.logLifecycle("dispatch.external-queued",e,{batchCount:s.length,queueMessageId:s[0].id}),this.broadcast(e);return}const l=this.removeBatch(e,s);N(s),s.some(o=>o.dispatchBlock)&&y(this.opts.getRuntime().client),this.logLifecycle("dispatch.accepted",e,{batchCount:s.length,queueMessageId:s[0].id,pendingCount:l}),this.deferredLogState.delete(e),t=l>0,this.broadcast(e)}catch(a){const d=i[0];if(d&&B(e)&&await this.switchUnavailableSteward(e,d,a)){this.removeBatch(e,i),this.broadcast(e);return}const u=oe({error:a,sessionId:e,batch:i,publish:()=>y(this.opts.getRuntime().client),isManagedWorker:!!this.opts.getRuntime().managerRuntime?.isManagedWorkerSession(e),removeBatch:()=>this.removeBatch(e,i),log:(s,r)=>this.logLifecycle(s,e,r,"error")});t=u.drainAgain,n=u.transientFailure,this.broadcast(e)}finally{this.inFlightMessageIds.delete(e),this.draining.delete(e);const a=h().sessions[e]??[];a.length?(this.broadcast(e),a.some(d=>!!d.externalQueuedSubmissionId)?this.retries.cancel(e):t?queueMicrotask(()=>this.wakeSession(e)):this.retries.schedule(e,n,j(b(a)))):this.retries.cancel(e)}}noteExternalClaim(e,t){const n=h(),i=n.sessions[e]??[],a=i.filter(d=>(d.clientMessageId??d.id)!==t);a.length!==i.length&&(a.length?n.sessions[e]=a:delete n.sessions[e],w(n),this.broadcast(e))}canInjectActiveBatch(e,t){if(!e.adapter.supportsActiveInput||!e.adapter.injectActiveInput||!e.journalRunId)return!1;const n=this.opts.getRuntime().runJournal?.get(t[0].sessionId,e.journalRunId),i=t[0].trigger?.kind==="managed_direct"||t[0].managedAgentDirect?null:"personal";return!!(i&&t[0].systemPrompt==null&&n&&n.source===i&&n.deliveryMode==="direct"&&n.agentType===t[0].agentType&&n.workDir===e.workDir&&n.agentSessionId===e.agentSessionId&&n.modelId===(t[0].modelId??null)&&n.reasoningEffort===(t[0].reasoningEffort??null))}removeBatch(e,t){if(t.length===0)return h().sessions[e]?.length??0;const n=h(),i=new Set(t.map(d=>d.id)),a=(n.sessions[e]??[]).filter(d=>!i.has(d.id));return a.length?n.sessions[e]=a:delete n.sessions[e],w(n),a.length}logLifecycle(e,t,n,i="info"){const a=`[chat.queue] ${JSON.stringify({at:J(),event:e,sessionId:t,...n})}`;i==="error"?console.error(a):console.info(a)}async dispatchQueuedMessages(e){const t=e[0],n=t.trigger?.kind==="scheduled"?t.trigger:null;if(n&&await this.validateScheduledTarget?.({sessionId:t.sessionId,...n})!=="ready")throw new U("schedule_target_unavailable");const i=e.flatMap(g=>{if(g.trigger?.kind==="room_activation"){const{kind:v,...R}=g.trigger;return[R]}return!g.trigger&&g.managedRoom?[g.managedRoom]:[]}),a=e.find(g=>g.trigger?.kind==="manager_event")?.trigger,d=e.some(g=>g.trigger?.kind==="managed_direct"||!!g.managedAgentDirect),u=d||!!n?.bindingId,s=e.find(g=>g.trigger?.kind==="manager_worker")?.trigger,r=a?.kind==="manager_event"||d,l=i.length>0?await this.prepareManagedRoomTurn?.(i):u||a?.kind==="manager_event"?await this.prepareManagedAgentDirectTurn?.(t.sessionId,n?.bindingId?F:W(a?.kind==="manager_event"?a:null,d)):void 0;if(i.length>0&&!l)throw new Error("managed_room_turn_preparer_unavailable");if(u&&!l)throw new Error("managed_agent_context_unavailable");if(a?.kind==="manager_event"&&this.opts.getRuntime().managerRuntime?.isManagedRoomBoundManager(t.sessionId)&&!l)throw new Error("managed_agent_context_unavailable");const o=new Set((h().sessions[t.sessionId]??[]).map(g=>g.id));if(this.disposed||this.deletions.hasSession(t.sessionId)||e.some(g=>!o.has(g.id)))throw l?.managedRoomContextToken&&this.opts.getRuntime().revokeManagedRoomContextToken?.(l.managedRoomContextToken),this.disposed?new Error("queue_stopped"):new U("queued_dispatch_cancelled");const m=l??null,c=m?.sessionMode==="manager"?m.managerConfig:null,S=e.length===1?t.text:X(e),I=Y(e.flatMap(g=>g.attachments??[])),f=u||a?.kind==="manager_event"&&!!l,T=f?l.agentSessionId?.startsWith("managed:")?E(this.opts.getRuntime(),t):l.agentSessionId:i.length>0?E(this.opts.getRuntime(),t):t.agentSessionId??null,C=l?A().find(g=>g.sessionId===t.sessionId):null,M=l?.effectiveModelId!==void 0?k(l.effectiveModelId):k(C?.modelId)??k(t.modelId),_=l?.effectiveModelId!==void 0?"room_effective_model":k(C?.modelId)?"persisted_session_model":k(t.modelId)?"queued_message_model":"pi_default_model";return await this.opts.dispatchQueuedReq({type:"req",id:`queue-send-${t.id}-${Date.now()}`,method:"chat.send",params:{...z($()),sessionId:t.sessionId,text:S,agentType:f?l.agentType:t.agentType,sessionMode:m?.sessionMode??t.sessionMode,managerConfig:m?c:t.managerConfig,workDir:f?l.workDir:t.workDir,agentSessionId:T,modelId:M,modelSelectionSource:_,systemPrompt:l?.systemPrompt??t.systemPrompt??null,managerDefaultWorkerAgentType:m?m.managerDefaultWorkerAgentType:t.managerDefaultWorkerAgentType,managerDefaultWorkerModelId:m?m.managerDefaultWorkerModelId:t.managerDefaultWorkerModelId,reasoningEffort:t.reasoningEffort??void 0,clientMessageId:t.clientMessageId??t.id,attachments:I,externalChannel:r?void 0:t.externalChannel,replyTarget:r?void 0:t.replyTarget,roomContextRegistryKey:r?void 0:l?.roomContextRegistryKey,activationCauseMessageId:r?void 0:i.at(-1)?.causeMessageId,rootCauseMessageId:r?void 0:i.at(-1)?.rootCauseMessageId,activationSequence:r?void 0:i.at(-1)?.sequence,activationHopCount:r?void 0:i.at(-1)?.hopCount,managedRecoverySource:a?.kind==="manager_event"?"manager_event":u?"managed_direct":i.length>0?"managed_room":void 0,managerEventId:a?.kind==="manager_event"?a.eventId:void 0,managedWorkerParentSessionId:s?.kind==="manager_worker"?s.parentSessionId:void 0,managerWorkerRoomOrigin:s?.kind==="manager_worker"?s.roomOrigin:void 0,managerWorkerNativeFull:s?.kind==="manager_worker"&&this.opts.getRuntime().managerRuntime?.isExternalWorkerController(s.parentSessionId,t.workDir)||void 0,managedRoomContextToken:l?.managedRoomContextToken,scheduledDelivery:!!n,suppressExternalOwnerEcho:i.length>0||!!n||void 0,queuedBatchItems:e.map(g=>{const v=V(g);return r?{...v,systemPrompt:l?.systemPrompt??null,externalChannel:null,replyTarget:null}:v}),waitForDispatch:!0}},l??void 0)??{}}markExternalQueued(e,t){const n=h(),i=new Set(e.map(u=>u.id)),a=n.sessions[e[0].sessionId]??[];let d=!1;for(const u of a)i.has(u.id)&&(u.externalQueuedSubmissionId=t||u.id,u.updatedAt=J(),d=!0);d&&w(n)}async isSessionBusy(e){const t=this.opts.getRuntime().recoveryBarrier;if(t?.isDispatchFrozen()||t?.isRecovering(e))return!0;const n=this.opts.getRuntime().sessions.get(e);if(!n)return!1;if(n.currentRunId){if(!(n.currentRunId.startsWith("dispatch:")&&!!this.opts.getRuntime().runJournal&&!n.journalRunId)||(n.adapter.getStatus?await n.adapter.getStatus().catch(()=>null):null)?.active)return!0;this.logLifecycle("drain.recovered-stale-dispatch",e,{staleRunId:n.currentRunId}),n.currentRunId=null,n.currentRunPhase=null}if(!n.adapter.getStatus)return!1;const i=await n.adapter.getStatus().catch(()=>null);return i?.active?(i.runId&&(n.currentRunId=i.runId,n.currentRunPhase=i.runPhase??n.currentRunPhase),!0):!1}broadcast(e){this.opts.getRuntime().client.sendEvent({type:"event",event:"session.queue.update",payload:{queue:this.getSnapshot(e)}})}}export{ze as ChatQueueManager,Ge as TerminalQueuedChatDispatchError,Je as purgeQueuedSessionData};
@@ -1,2 +1,2 @@
1
- import a from"node:fs";import i from"node:path";import{listSessionRecords as p}from"../session/store.js";import{StewardWorkspaceError as o,ensureStewardWorkspace as s}from"./workspace.js";import{STEWARD_INDEX_ONBOARDING as S}from"./onboarding.js";const d="SHENNIAN_STEWARD_SESSION_ID",E=2e4,A=["\u4F60\u662F\u795E\u5FF5\u7BA1\u5BB6\uFF0C\u5728\u7528\u6237\u9009\u5B9A\u7684\u8FD9\u53F0\u7535\u8111\u4E0A\u5DE5\u4F5C\u3002\u5148\u8BFB\u5F53\u524D\u76EE\u5F55\u7684 AGENTS.md\uFF0C\u518D\u6309\u9700\u8BFB index.md\u3002",'\u7528\u6237\u53EA\u770B\u5230\u4F60\u7528 shennian steward say "\u8981\u7ED9\u7528\u6237\u770B\u7684\u8BDD" \u53D1\u51FA\u7684\u6D88\u606F\uFF0C\u5176\u4F59\u8F93\u51FA\u7528\u6237\u90FD\u770B\u4E0D\u5230\u3002\u6536\u5230\u8BF7\u6C42\u5148\u7528 say \u56DE\u5E94\u4E00\u53E5\uFF0C\u5904\u7406\u5B8C\u518D say \u7ED3\u679C\u3002',"\u82E5\u672C\u8F6E\u5E94\u9996\u6B21\u9080\u8BF7\u5EFA\u7ACB\u8D44\u6599\u7D22\u5F15\uFF0C\u628A\u9080\u8BF7\u9644\u5728\u9996\u6B21\u6B63\u5E38\u56DE\u5E94\u7684\u540C\u4E00\u6B21 say \u672B\u5C3E\uFF1B\u4E0D\u8981\u7B49\u7B2C\u4E8C\u6B21 say\u3002\u7528\u6237\u5DF2\u7ECF\u660E\u786E\u62D2\u7EDD\u5219\u53EA\u8BB0\u5F55\u8DF3\u8FC7\uFF0C\u4E0D\u9080\u8BF7\u3002","\u8017\u65F6\u3001\u590D\u6742\u6216\u9700\u8981\u4FEE\u6539\u9879\u76EE\u6587\u4EF6\u7684\u5DE5\u4F5C\uFF0C\u7528 shennian project task create \u8F6C\u6210\u9879\u76EE\u4EFB\u52A1\uFF0C\u4E0D\u8981\u81EA\u5DF1\u5728\u8FD9\u91CC\u505A\u5B8C\u3002",S].join(`
2
- `);function c(r){return p().some(e=>e.sessionId===r&&e.sessionScope==="steward")}function D(r){return c(r)?{[d]:r}:{}}function n(r){return process.platform==="win32"||process.platform==="darwin"?r.toLowerCase():r}function k(){return s().dir}function x(r){const e=s().dir;let t;try{t=a.realpathSync.native(i.resolve(r))}catch{throw new o("steward_workdir_invalid","The steward must run in its fixed workspace.")}if(n(t)!==n(e))throw new o("steward_workdir_invalid","The steward must run in its fixed workspace.");return e}export{E as STEWARD_SAY_MAX_CHARS,d as STEWARD_SESSION_ID_ENV,A as STEWARD_SYSTEM_PROMPT,x as assertStewardWorkDir,c as isStewardSessionId,k as pinStewardWorkDir,D as stewardSessionEnv};
1
+ import a from"node:fs";import i from"node:path";import{listSessionRecords as S}from"../session/store.js";import{StewardWorkspaceError as o,ensureStewardWorkspace as s}from"./workspace.js";import{STEWARD_INDEX_ONBOARDING as p}from"./onboarding.js";import{issuePersonalScheduleContext as c,STEWARD_SCHEDULE_INSTRUCTIONS as d}from"../schedules/personal-context.js";const w="SHENNIAN_STEWARD_SESSION_ID",D=2e4,A=["\u4F60\u662F\u795E\u5FF5\u7BA1\u5BB6\uFF0C\u5728\u7528\u6237\u9009\u5B9A\u7684\u8FD9\u53F0\u7535\u8111\u4E0A\u5DE5\u4F5C\u3002\u5148\u8BFB\u5F53\u524D\u76EE\u5F55\u7684 AGENTS.md\uFF0C\u518D\u6309\u9700\u8BFB index.md\u3002",'\u7528\u6237\u53EA\u770B\u5230\u4F60\u7528 shennian steward say "\u8981\u7ED9\u7528\u6237\u770B\u7684\u8BDD" \u53D1\u51FA\u7684\u6D88\u606F\uFF0C\u5176\u4F59\u8F93\u51FA\u7528\u6237\u90FD\u770B\u4E0D\u5230\u3002\u6536\u5230\u8BF7\u6C42\u5148\u7528 say \u56DE\u5E94\u4E00\u53E5\uFF0C\u5904\u7406\u5B8C\u518D say \u7ED3\u679C\u3002',"\u82E5\u672C\u8F6E\u5E94\u9996\u6B21\u9080\u8BF7\u5EFA\u7ACB\u8D44\u6599\u7D22\u5F15\uFF0C\u628A\u9080\u8BF7\u9644\u5728\u9996\u6B21\u6B63\u5E38\u56DE\u5E94\u7684\u540C\u4E00\u6B21 say \u672B\u5C3E\uFF1B\u4E0D\u8981\u7B49\u7B2C\u4E8C\u6B21 say\u3002\u7528\u6237\u5DF2\u7ECF\u660E\u786E\u62D2\u7EDD\u5219\u53EA\u8BB0\u5F55\u8DF3\u8FC7\uFF0C\u4E0D\u9080\u8BF7\u3002","\u8017\u65F6\u3001\u590D\u6742\u6216\u9700\u8981\u4FEE\u6539\u9879\u76EE\u6587\u4EF6\u7684\u5DE5\u4F5C\uFF0C\u7528 shennian project task create \u8F6C\u6210\u9879\u76EE\u4EFB\u52A1\uFF0C\u4E0D\u8981\u81EA\u5DF1\u5728\u8FD9\u91CC\u505A\u5B8C\u3002",d,p].join(`
2
+ `);function _(r){return S().some(e=>e.sessionId===r&&e.sessionScope==="steward")}function l(r){return _(r)?{[w]:r,SHENNIAN_SCHEDULE_CONTEXT:c(r)}:{}}function n(r){return process.platform==="win32"||process.platform==="darwin"?r.toLowerCase():r}function x(){return s().dir}function R(r){const e=s().dir;let t;try{t=a.realpathSync.native(i.resolve(r))}catch{throw new o("steward_workdir_invalid","The steward must run in its fixed workspace.")}if(n(t)!==n(e))throw new o("steward_workdir_invalid","The steward must run in its fixed workspace.");return e}export{D as STEWARD_SAY_MAX_CHARS,w as STEWARD_SESSION_ID_ENV,A as STEWARD_SYSTEM_PROMPT,R as assertStewardWorkDir,_ as isStewardSessionId,x as pinStewardWorkDir,l as stewardSessionEnv};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shennian",
3
- "version": "0.5.20",
3
+ "version": "0.5.22",
4
4
  "description": "Shennian \u2014 AI Agent Control Plane CLI",
5
5
  "type": "module",
6
6
  "bin": {