shennian 0.4.66 → 0.4.68

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/publish-build-manifest.json +51 -46
  2. package/dist/src/agent-env.js +3 -3
  3. package/dist/src/agents/acp/manifests.d.ts +2 -2
  4. package/dist/src/agents/adapter.d.ts +1 -1
  5. package/dist/src/agents/codex.js +5 -5
  6. package/dist/src/agents/command-spec.d.ts +2 -0
  7. package/dist/src/agents/command-spec.js +3 -3
  8. package/dist/src/agents/runtime-compatibility.js +1 -1
  9. package/dist/src/index.js +3 -3
  10. package/dist/src/manager/registry.d.ts +10 -0
  11. package/dist/src/manager/registry.js +1 -1
  12. package/dist/src/manager/runtime.d.ts +4 -2
  13. package/dist/src/manager/runtime.js +6 -6
  14. package/dist/src/manager/worker-ipc.d.ts +5 -3
  15. package/dist/src/manager/worker-ipc.js +1 -1
  16. package/dist/src/room/activation-service.d.ts +8 -2
  17. package/dist/src/room/activation-service.js +10 -5
  18. package/dist/src/room/managed-context.d.ts +3 -1
  19. package/dist/src/room/managed-context.js +1 -1
  20. package/dist/src/room/managed-prompt-composer.js +1 -1
  21. package/dist/src/room/managed-room-ipc.d.ts +2 -0
  22. package/dist/src/room/managed-room-ipc.js +2 -2
  23. package/dist/src/schedules/personal-context.d.ts +0 -1
  24. package/dist/src/schedules/personal-context.js +1 -1
  25. package/dist/src/session/handlers/chat-adapter-config.js +1 -1
  26. package/dist/src/session/handlers/chat-recovery.js +1 -1
  27. package/dist/src/session/handlers/chat.js +1 -3
  28. package/dist/src/session/manager-event-authority.d.ts +3 -0
  29. package/dist/src/session/manager-event-authority.js +1 -0
  30. package/dist/src/session/manager.d.ts +2 -2
  31. package/dist/src/session/manager.js +2 -2
  32. package/dist/src/session/queue-helpers.d.ts +5 -0
  33. package/dist/src/session/queue-helpers.js +8 -8
  34. package/dist/src/session/queue-message.d.ts +4 -1
  35. package/dist/src/session/queue-message.js +1 -1
  36. package/dist/src/session/queue-storage.d.ts +1 -0
  37. package/dist/src/session/queue-storage.js +2 -2
  38. package/dist/src/session/queue-types.d.ts +8 -0
  39. package/dist/src/session/queue.d.ts +3 -3
  40. package/dist/src/session/queue.js +1 -1
  41. package/dist/src/session/queued-chat-dispatch.js +1 -1
  42. package/dist/src/session/turn-trigger.d.ts +5 -0
  43. package/package.json +1 -1
@@ -2,7 +2,7 @@
2
2
  "schemaVersion": 1,
3
3
  "jsMinified": true,
4
4
  "minifier": "esbuild",
5
- "fileCount": 206,
5
+ "fileCount": 207,
6
6
  "files": [
7
7
  {
8
8
  "file": "bin/shennian.js",
@@ -11,8 +11,8 @@
11
11
  },
12
12
  {
13
13
  "file": "src/agent-env.js",
14
- "beforeBytes": 10485,
15
- "afterBytes": 4709
14
+ "beforeBytes": 10709,
15
+ "afterBytes": 4754
16
16
  },
17
17
  {
18
18
  "file": "src/agents/acp/adapter.js",
@@ -121,13 +121,13 @@
121
121
  },
122
122
  {
123
123
  "file": "src/agents/codex.js",
124
- "beforeBytes": 68764,
125
- "afterBytes": 35246
124
+ "beforeBytes": 69014,
125
+ "afterBytes": 35438
126
126
  },
127
127
  {
128
128
  "file": "src/agents/command-spec.js",
129
- "beforeBytes": 18342,
130
- "afterBytes": 8290
129
+ "beforeBytes": 19263,
130
+ "afterBytes": 8681
131
131
  },
132
132
  {
133
133
  "file": "src/agents/config-status.js",
@@ -271,8 +271,8 @@
271
271
  },
272
272
  {
273
273
  "file": "src/agents/runtime-compatibility.js",
274
- "beforeBytes": 1705,
275
- "afterBytes": 810
274
+ "beforeBytes": 1587,
275
+ "afterBytes": 732
276
276
  },
277
277
  {
278
278
  "file": "src/agents/workbuddy-managed-permissions.js",
@@ -296,7 +296,7 @@
296
296
  },
297
297
  {
298
298
  "file": "src/commands/daemon-process.js",
299
- "beforeBytes": 5337,
299
+ "beforeBytes": 5335,
300
300
  "afterBytes": 2995
301
301
  },
302
302
  {
@@ -446,8 +446,8 @@
446
446
  },
447
447
  {
448
448
  "file": "src/index.js",
449
- "beforeBytes": 38639,
450
- "afterBytes": 19406
449
+ "beforeBytes": 39165,
450
+ "afterBytes": 19567
451
451
  },
452
452
  {
453
453
  "file": "src/log-redaction.js",
@@ -466,8 +466,8 @@
466
466
  },
467
467
  {
468
468
  "file": "src/manager/registry.js",
469
- "beforeBytes": 11428,
470
- "afterBytes": 5407
469
+ "beforeBytes": 12065,
470
+ "afterBytes": 5661
471
471
  },
472
472
  {
473
473
  "file": "src/manager/retired-external-channel-compat.js",
@@ -476,13 +476,13 @@
476
476
  },
477
477
  {
478
478
  "file": "src/manager/runtime.js",
479
- "beforeBytes": 31965,
480
- "afterBytes": 15668
479
+ "beforeBytes": 33902,
480
+ "afterBytes": 16475
481
481
  },
482
482
  {
483
483
  "file": "src/manager/worker-ipc.js",
484
- "beforeBytes": 11319,
485
- "afterBytes": 6180
484
+ "beforeBytes": 11457,
485
+ "afterBytes": 6210
486
486
  },
487
487
  {
488
488
  "file": "src/manager/worker-markdown.js",
@@ -611,8 +611,8 @@
611
611
  },
612
612
  {
613
613
  "file": "src/room/activation-service.js",
614
- "beforeBytes": 24933,
615
- "afterBytes": 12454
614
+ "beforeBytes": 27657,
615
+ "afterBytes": 14988
616
616
  },
617
617
  {
618
618
  "file": "src/room/attachment-cache.js",
@@ -646,13 +646,13 @@
646
646
  },
647
647
  {
648
648
  "file": "src/room/managed-context.js",
649
- "beforeBytes": 4521,
650
- "afterBytes": 2538
649
+ "beforeBytes": 4743,
650
+ "afterBytes": 2662
651
651
  },
652
652
  {
653
653
  "file": "src/room/managed-prompt-composer.js",
654
- "beforeBytes": 10441,
655
- "afterBytes": 11173
654
+ "beforeBytes": 10537,
655
+ "afterBytes": 11365
656
656
  },
657
657
  {
658
658
  "file": "src/room/managed-room-binding.js",
@@ -661,8 +661,8 @@
661
661
  },
662
662
  {
663
663
  "file": "src/room/managed-room-ipc.js",
664
- "beforeBytes": 14052,
665
- "afterBytes": 6859
664
+ "beforeBytes": 14796,
665
+ "afterBytes": 7019
666
666
  },
667
667
  {
668
668
  "file": "src/room/mirror-sync-service.js",
@@ -706,8 +706,8 @@
706
706
  },
707
707
  {
708
708
  "file": "src/schedules/personal-context.js",
709
- "beforeBytes": 1503,
710
- "afterBytes": 1451
709
+ "beforeBytes": 901,
710
+ "afterBytes": 501
711
711
  },
712
712
  {
713
713
  "file": "src/schedules/server-client.js",
@@ -791,8 +791,8 @@
791
791
  },
792
792
  {
793
793
  "file": "src/session/handlers/chat-adapter-config.js",
794
- "beforeBytes": 3042,
795
- "afterBytes": 1288
794
+ "beforeBytes": 2814,
795
+ "afterBytes": 1159
796
796
  },
797
797
  {
798
798
  "file": "src/session/handlers/chat-events.js",
@@ -801,8 +801,8 @@
801
801
  },
802
802
  {
803
803
  "file": "src/session/handlers/chat-recovery.js",
804
- "beforeBytes": 6838,
805
- "afterBytes": 3586
804
+ "beforeBytes": 6525,
805
+ "afterBytes": 3449
806
806
  },
807
807
  {
808
808
  "file": "src/session/handlers/chat-session-lifecycle.js",
@@ -811,8 +811,8 @@
811
811
  },
812
812
  {
813
813
  "file": "src/session/handlers/chat.js",
814
- "beforeBytes": 33859,
815
- "afterBytes": 14585
814
+ "beforeBytes": 35331,
815
+ "afterBytes": 15258
816
816
  },
817
817
  {
818
818
  "file": "src/session/handlers/control.js",
@@ -879,10 +879,15 @@
879
879
  "beforeBytes": 8089,
880
880
  "afterBytes": 3965
881
881
  },
882
+ {
883
+ "file": "src/session/manager-event-authority.js",
884
+ "beforeBytes": 498,
885
+ "afterBytes": 209
886
+ },
882
887
  {
883
888
  "file": "src/session/manager.js",
884
- "beforeBytes": 42639,
885
- "afterBytes": 22478
889
+ "beforeBytes": 42657,
890
+ "afterBytes": 22491
886
891
  },
887
892
  {
888
893
  "file": "src/session/native-cleanup-outbox.js",
@@ -906,13 +911,13 @@
906
911
  },
907
912
  {
908
913
  "file": "src/session/queue-helpers.js",
909
- "beforeBytes": 7920,
910
- "afterBytes": 3969
914
+ "beforeBytes": 8522,
915
+ "afterBytes": 4242
911
916
  },
912
917
  {
913
918
  "file": "src/session/queue-message.js",
914
- "beforeBytes": 2938,
915
- "afterBytes": 1881
919
+ "beforeBytes": 3257,
920
+ "afterBytes": 1987
916
921
  },
917
922
  {
918
923
  "file": "src/session/queue-retry.js",
@@ -921,8 +926,8 @@
921
926
  },
922
927
  {
923
928
  "file": "src/session/queue-storage.js",
924
- "beforeBytes": 1663,
925
- "afterBytes": 909
929
+ "beforeBytes": 2362,
930
+ "afterBytes": 1166
926
931
  },
927
932
  {
928
933
  "file": "src/session/queue-types.js",
@@ -931,13 +936,13 @@
931
936
  },
932
937
  {
933
938
  "file": "src/session/queue.js",
934
- "beforeBytes": 44697,
935
- "afterBytes": 19471
939
+ "beforeBytes": 44695,
940
+ "afterBytes": 19911
936
941
  },
937
942
  {
938
943
  "file": "src/session/queued-chat-dispatch.js",
939
- "beforeBytes": 2902,
940
- "afterBytes": 1626
944
+ "beforeBytes": 3024,
945
+ "afterBytes": 1703
941
946
  },
942
947
  {
943
948
  "file": "src/session/run-recovery/barrier.js",
@@ -1,8 +1,8 @@
1
- import O from"node:os";import E from"node:path";import{spawnSync as p}from"node:child_process";import{buildAugmentedPath as g}from"./env-path.js";import{buildWindowsSystemEnv as A,resolveWindowsPowerShellPath as R}from"./windows-shell.js";const N="__SHENNIAN_AGENT_ENV_START__",f="__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"],d=["SHENNIAN_MANAGED_ROOM_CONTEXT","SHENNIAN_MANAGED_ROOM_IPC_ROOT"],v=["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 T(e){return h[e]??[]}function w(e){return e==="codex"||e==="claude"||e==="pi-coding-agent"?[...d,...v]:d}function j(e=process.platform){return["PATH",...e==="win32"?m:S,...P]}function _(e){return`'${e.replace(/'/g,"'\\''")}'`}function I(e){const n=e.indexOf(N),o=e.indexOf(f,n+N.length);if(n===-1||o===-1)return null;const t=e.slice(n+N.length,o);try{const s=JSON.parse(t),i={};for(const[c,r]of Object.entries(s))typeof r=="string"&&(i[c]=r);return i}catch{return null}}function G(){const e=process.env.SHELL?.trim()||"/bin/sh",n=[`printf ${_(N)}`,`${_(process.execPath)} -e ${_("process.stdout.write(JSON.stringify(process.env))")}`,`printf ${_(f)}`].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"?I(t.stdout):null;if(s)return s}return null}function M(){const e=`
1
+ import O from"node:os";import E from"node:path";import{spawnSync as p}from"node:child_process";import{buildAugmentedPath as g}from"./env-path.js";import{buildWindowsSystemEnv as A,resolveWindowsPowerShellPath as T}from"./windows-shell.js";const N="__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"],v=["NO_COLOR","PI_CODING_AGENT_DIR"],f=["SHENNIAN_MANAGED_ROOM_CONTEXT","SHENNIAN_MANAGED_ROOM_IPC_ROOT"],P=["SHENNIAN_MANAGER_SESSION_ID","SHENNIAN_MANAGER_AGENT_SESSION_ID","SHENNIAN_MANAGER_WORKDIR","SHENNIAN_MANAGER_MODEL","SHENNIAN_MANAGER_IPC_URL","SHENNIAN_MANAGER_IPC_TOKEN"],R={codex:["OPENAI_BASE_URL","OPENAI_API_KEY"],claude:["ANTHROPIC_BASE_URL","ANTHROPIC_API_KEY"],pi:["DASHSCOPE_BASE_URL","DASHSCOPE_API_KEY"]};function h(e){return R[e]??[]}function w(e){return e==="codex"||e==="claude"||e==="pi-coding-agent"?[...f,...P]:f}function j(e=process.platform){return["PATH",...e==="win32"?m:S,...v]}function _(e){return`'${e.replace(/'/g,"'\\''")}'`}function I(e){const n=e.indexOf(N),o=e.indexOf(d,n+N.length);if(n===-1||o===-1)return null;const t=e.slice(n+N.length,o);try{const s=JSON.parse(t),i={};for(const[c,r]of Object.entries(s))typeof r=="string"&&(i[c]=r);return i}catch{return null}}function G(){const e=process.env.SHELL?.trim()||"/bin/sh",n=[`printf ${_(N)}`,`${_(process.execPath)} -e ${_("process.stdout.write(JSON.stringify(process.env))")}`,`printf ${_(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"?I(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 '${N}'
6
6
  $envs | ConvertTo-Json -Compress
7
- Write-Output '${f}'
8
- `,n=p(R(),["-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"?I(n.stdout):null}function y(){return(O.platform()==="win32"?M():G())??{}}function D(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 H(e={}){return D({daemonEnv:process.env,userEnv:y(),extra:e})}function $(e={}){const n=H(e),o=new Set([...d,...v]);for(const t of Object.keys(n))t.startsWith("SHENNIAN_")&&!o.has(t)&&delete n[t];return n}function U(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,T(e.agentType),o),l(t,e.sessionEnv,w(e.agentType),o),l(t,e.runtimeEnv,P,o),o==="win32"&&Object.assign(t,A({...n,...t})),t.PATH=L(n,t,o),delete t.Path,delete t.path,t}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(([a])=>a.toUpperCase()===i.toUpperCase()):s.find(([a])=>a===i))?.[1];typeof r=="string"&&r.length>0&&(e[i]=r)}}function L(e,n,o){const t=o==="win32"?E.win32.delimiter:E.posix.delimiter,s=[],i=(c,r=!1)=>{if(c)for(const a of c.split(t))!a||s.includes(a)||(r?s.unshift(a):s.push(a))};if(i(u(e)),i(E.dirname(process.execPath),!0),o==="win32"){const c=A({...e,...n}),r=c.SystemRoot??c.WINDIR??"C:\\Windows";i(E.win32.join(r,"System32")),i(E.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 c of[u(e),u(n),u(o)])for(const r of(c??"").split(E.delimiter))r&&!s.includes(r)&&s.push(r);if(process.platform==="win32"){const c=t.SystemRoot||t.WINDIR||process.env.SystemRoot||process.env.WINDIR||"C:\\Windows";for(const r of[E.win32.join(c,"System32"),E.win32.join(c,"System32","WindowsPowerShell","v1.0"),E.win32.join(c)])r&&!s.includes(r)&&s.push(r)}const i=E.dirname(process.execPath);return i&&!s.includes(i)&&s.unshift(i),g({pathValue:s.join(E.delimiter),env:t})}export{d as MANAGED_AGENT_SESSION_ENV_KEYS,H as buildAgentProcessEnv,U as buildManagedAgentProcessEnv,$ as buildManagedNativeFullProcessEnv,j as getManagedAgentBaseEnvKeys,T as getManagedAgentProviderEnvKeys,w as getManagedAgentSessionEnvKeys,D as mergeAgentProcessEnv,y as readLatestUserEnv};
7
+ Write-Output '${d}'
8
+ `,n=p(T(),["-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"?I(n.stdout):null}function D(){return(O.platform()==="win32"?M():G())??{}}function y(e){const n={...e.daemonEnv,...e.userEnv,...e.extra};return process.platform==="win32"&&Object.assign(n,A(n)),n.PATH=L(e.daemonEnv,e.userEnv,e.extra,n),delete n.Path,delete n.path,n}function H(e={}){const n=y({daemonEnv:process.env,userEnv:D(),extra:e});return delete n.SHENNIAN_SCHEDULE_CONTEXT,n}function $(e={}){const n=H(e),o=new Set([...f,...P]);for(const t of Object.keys(n))t.startsWith("SHENNIAN_")&&!o.has(t)&&delete n[t];return n}function U(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,h(e.agentType),o),l(t,e.sessionEnv,w(e.agentType),o),l(t,e.runtimeEnv,v,o),o==="win32"&&Object.assign(t,A({...n,...t})),t.PATH=C(n,t,o),delete t.Path,delete t.path,t}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(([a])=>a.toUpperCase()===i.toUpperCase()):s.find(([a])=>a===i))?.[1];typeof r=="string"&&r.length>0&&(e[i]=r)}}function C(e,n,o){const t=o==="win32"?E.win32.delimiter:E.posix.delimiter,s=[],i=(c,r=!1)=>{if(c)for(const a of c.split(t))!a||s.includes(a)||(r?s.unshift(a):s.push(a))};if(i(u(e)),i(E.dirname(process.execPath),!0),o==="win32"){const c=A({...e,...n}),r=c.SystemRoot??c.WINDIR??"C:\\Windows";i(E.win32.join(r,"System32")),i(E.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 L(e,n,o,t){const s=[];for(const c of[u(e),u(n),u(o)])for(const r of(c??"").split(E.delimiter))r&&!s.includes(r)&&s.push(r);if(process.platform==="win32"){const c=t.SystemRoot||t.WINDIR||process.env.SystemRoot||process.env.WINDIR||"C:\\Windows";for(const r of[E.win32.join(c,"System32"),E.win32.join(c,"System32","WindowsPowerShell","v1.0"),E.win32.join(c)])r&&!s.includes(r)&&s.push(r)}const i=E.dirname(process.execPath);return i&&!s.includes(i)&&s.unshift(i),g({pathValue:s.join(E.delimiter),env:t})}export{f as MANAGED_AGENT_SESSION_ENV_KEYS,H as buildAgentProcessEnv,U as buildManagedAgentProcessEnv,$ as buildManagedNativeFullProcessEnv,j as getManagedAgentBaseEnvKeys,h as getManagedAgentProviderEnvKeys,w as getManagedAgentSessionEnvKeys,y as mergeAgentProcessEnv,D as readLatestUserEnv};
@@ -26,8 +26,8 @@ declare const manifestSchema: z.ZodObject<{
26
26
  }>>;
27
27
  }, "strict", z.ZodTypeAny, {
28
28
  id: string;
29
- name: string;
30
29
  schemaVersion: 1;
30
+ name: string;
31
31
  args: string[];
32
32
  command: string;
33
33
  protocol: "acp";
@@ -40,8 +40,8 @@ declare const manifestSchema: z.ZodObject<{
40
40
  } | undefined;
41
41
  }, {
42
42
  id: string;
43
- name: string;
44
43
  schemaVersion: 1;
44
+ name: string;
45
45
  command: string;
46
46
  protocol: "acp";
47
47
  args?: string[] | undefined;
@@ -48,7 +48,7 @@ export type AgentSendResult = {
48
48
  queuedSubmissionId?: string;
49
49
  };
50
50
  export type AgentSendContext = {
51
- source: 'room_activation' | 'upgrade_recovery';
51
+ source: 'room_activation' | 'managed_private' | 'upgrade_recovery';
52
52
  /** Marks internal recovery input; it must never be persisted as user-authored text. */
53
53
  recovery?: 'upgrade';
54
54
  };
@@ -1,8 +1,8 @@
1
- import{spawnSync as q}from"node:child_process";import{createInterface as w}from"node:readline";import{createHash as S,randomUUID as N}from"node:crypto";import p from"node:path";import{AgentAdapter as F,registerAgent as D}from"./adapter.js";import{resolveBuiltinCommand as v,spawnAgentCommand as x}from"./command-spec.js";import{buildAgentProcessEnv as L,buildManagedAgentProcessEnv as $,buildManagedNativeFullProcessEnv as U}from"../agent-env.js";import{ensurePlatformInstructionsFile as W}from"./platform-instructions.js";import{CODEX_DESKTOP_SEND_UNAVAILABLE as E}from"@shennian/wire";import{isCodexThreadTailInterrupted as B}from"../native-fusion/codex-files.js";import{resolveManagedAgentAdapterEnforcement as G,isManagedAgentNativeFull as R}from"../security/managed-agent-policy.js";import{registerManagedAgentRuntimeSecurity as z}from"../security/managed-agent-runtime.js";import{CODEX_MANAGED_MANAGER_DYNAMIC_TOOLS as H,CODEX_MANAGED_ROOM_DYNAMIC_TOOLS as J,CodexManagedRoomToolBinding as V}from"./codex-managed-room-tools.js";import{assertCodexManagedPermissionProfile as C,CODEX_MANAGED_RUNTIME_SECURITY as X,compileCodexManagedPermissions as K,extractCodexMcpServerNames as Q}from"./codex-managed-permissions.js";import{CODEX_APP_SERVER_CLIENT_INFO as Y,extractAppServerErrorMessage as _,formatCodexErrorMessage as j,formatTransientCodexStatus as Z,isCodexCollabAgentItem as ee,isCodexCollabAgentToolName as y,isCodexLegacyCollabAgentItem as te,isCodexUnsupportedEffortError as re,isMissingCodexRolloutError as T,isTransientCodexErrorMessage as ne,looksLikeCodexInteractiveAuthPrompt as se,looksLikeFatalCodexStderr as ie,normalizeCodexModelId as I,normalizeCodexReasoningEffort as oe,normalizeCodexStderr as A,normalizeTerminalText as ae,safeStringify as k,stripGitDirectiveArtifacts as de}from"./codex-utils.js";import{isCodexUnsupportedEffortError as Fe,isMissingCodexRolloutError as De,normalizeCodexModelId as Le,normalizeCodexReasoningEffort as $e}from"./codex-utils.js";z("codex",X);function P(o){const e=o instanceof Error?o.message:String(o);return/already has an active writer|thread-store conflict/i.test(e)}function le(o){const e=o instanceof Error?o.message:String(o);return/paginated(?:_threads|\s+(?:thread\s+)?history)?.*(?:not supported|unsupported|unavailable)/i.test(e)||/(?:not supported|unsupported|unavailable).*paginated(?:_threads|\s+(?:thread\s+)?history)?/i.test(e)}function ce(o){const e=o instanceof Error?o.message:String(o);return/unknown field [`'"]?excludeTurns/i.test(e)||/excludeTurns.*(?:not supported|unsupported|unavailable)/i.test(e)}function ue(o){const e=o instanceof Error?o.message:String(o);return/(?:method not found|unknown method).*(?:project\/list|project\/create)/i.test(e)||/(?:project\/list|project\/create).*(?:not supported|unsupported|unavailable)/i.test(e)}function he(o,e){const t=p.resolve(e);let r;for(const n of o)if(n.id)for(const i of n.roots??[]){if(!i.path)continue;const s=p.resolve(i.path),a=p.relative(s,t);!(a===""||!a.startsWith("..")&&!p.isAbsolute(a))||s.length<=(r?.rootLength??-1)||(r={id:n.id,rootLength:s.length})}return r?.id}function M(o,e){const t=e?.flatMap(n=>pe(n)).filter(n=>!/^https?:\/\//i.test(n.path)).filter(n=>n.path);return{type:"text",text:ge(o,e),text_elements:[],...t?.length?{local_images:t}:{}}}function pe(o){if(o.kind==="image")return o.previewData?[{path:o.path,data:o.previewData,mimeType:o.mimeType}]:[{path:o.path}];if(o.mimeType.startsWith("video/")){const e=me(o.path);return e?[{path:e}]:[]}return[]}function me(o){if(!o||/^https?:\/\//i.test(o))return null;const e=p.extname(o),r=`${e?o.slice(0,-e.length):o}.preview.png`;return q("ffmpeg",["-y","-ss","0","-i",o,"-frames:v","1","-vf","scale=320:-1",r],{stdio:"ignore",timeout:15e3}).status===0?r:null}function ge(o,e){const t=e?.filter(i=>i.kind!=="image").filter(i=>i.path&&!/^https?:\/\//i.test(i.path));if(!t?.length||t.every(i=>o.includes(i.path)))return o;const n=t.map((i,s)=>{const a=i.name||`attachment-${s+1}`,d=i.mimeType?` (${i.mimeType})`:"";return`[${b(a)}${d}](<${i.path}>)`});return[o,"",...n].join(`
1
+ import{spawnSync as q}from"node:child_process";import{createInterface as w}from"node:readline";import{createHash as S,randomUUID as N}from"node:crypto";import p from"node:path";import{AgentAdapter as F,registerAgent as D}from"./adapter.js";import{resolveBuiltinCommand as T,spawnAgentCommand as x}from"./command-spec.js";import{buildAgentProcessEnv as L,buildManagedAgentProcessEnv as $,buildManagedNativeFullProcessEnv as U}from"../agent-env.js";import{ensurePlatformInstructionsFile as W}from"./platform-instructions.js";import{CODEX_DESKTOP_SEND_UNAVAILABLE as E}from"@shennian/wire";import{isCodexThreadTailInterrupted as B}from"../native-fusion/codex-files.js";import{resolveManagedAgentAdapterEnforcement as G,isManagedAgentNativeFull as R}from"../security/managed-agent-policy.js";import{registerManagedAgentRuntimeSecurity as z}from"../security/managed-agent-runtime.js";import{CODEX_MANAGED_MANAGER_DYNAMIC_TOOLS as H,CODEX_MANAGED_ROOM_DYNAMIC_TOOLS as J,CodexManagedRoomToolBinding as V}from"./codex-managed-room-tools.js";import{assertCodexManagedPermissionProfile as C,CODEX_MANAGED_RUNTIME_SECURITY as X,compileCodexManagedPermissions as K,extractCodexMcpServerNames as Q}from"./codex-managed-permissions.js";import{CODEX_APP_SERVER_CLIENT_INFO as Y,extractAppServerErrorMessage as _,formatCodexErrorMessage as j,formatTransientCodexStatus as Z,isCodexCollabAgentItem as ee,isCodexCollabAgentToolName as y,isCodexLegacyCollabAgentItem as te,isCodexUnsupportedEffortError as re,isMissingCodexRolloutError as v,isTransientCodexErrorMessage as ne,looksLikeCodexInteractiveAuthPrompt as se,looksLikeFatalCodexStderr as ie,normalizeCodexModelId as I,normalizeCodexReasoningEffort as oe,normalizeCodexStderr as A,normalizeTerminalText as ae,safeStringify as k,stripGitDirectiveArtifacts as de}from"./codex-utils.js";import{isCodexUnsupportedEffortError as Fe,isMissingCodexRolloutError as De,normalizeCodexModelId as Le,normalizeCodexReasoningEffort as $e}from"./codex-utils.js";z("codex",X);function P(o){const e=o instanceof Error?o.message:String(o);return/already has an active writer|thread-store conflict/i.test(e)}function le(o){const e=o instanceof Error?o.message:String(o);return/paginated(?:_threads|\s+(?:thread\s+)?history)?.*(?:not supported|unsupported|unavailable)/i.test(e)||/(?:not supported|unsupported|unavailable).*paginated(?:_threads|\s+(?:thread\s+)?history)?/i.test(e)}function ce(o){const e=o instanceof Error?o.message:String(o);return/unknown field [`'"]?excludeTurns/i.test(e)||/excludeTurns.*(?:not supported|unsupported|unavailable)/i.test(e)}function ue(o){const e=o instanceof Error?o.message:String(o);return/(?:method not found|unknown method).*(?:project\/list|project\/create)/i.test(e)||/(?:project\/list|project\/create).*(?:not supported|unsupported|unavailable)/i.test(e)}function he(o,e){const t=p.resolve(e);let r;for(const n of o)if(n.id)for(const i of n.roots??[]){if(!i.path)continue;const s=p.resolve(i.path),a=p.relative(s,t);!(a===""||!a.startsWith("..")&&!p.isAbsolute(a))||s.length<=(r?.rootLength??-1)||(r={id:n.id,rootLength:s.length})}return r?.id}function M(o,e){const t=e?.flatMap(n=>pe(n)).filter(n=>!/^https?:\/\//i.test(n.path)).filter(n=>n.path);return{type:"text",text:ge(o,e),text_elements:[],...t?.length?{local_images:t}:{}}}function pe(o){if(o.kind==="image")return o.previewData?[{path:o.path,data:o.previewData,mimeType:o.mimeType}]:[{path:o.path}];if(o.mimeType.startsWith("video/")){const e=me(o.path);return e?[{path:e}]:[]}return[]}function me(o){if(!o||/^https?:\/\//i.test(o))return null;const e=p.extname(o),r=`${e?o.slice(0,-e.length):o}.preview.png`;return q("ffmpeg",["-y","-ss","0","-i",o,"-frames:v","1","-vf","scale=320:-1",r],{stdio:"ignore",timeout:15e3}).status===0?r:null}function ge(o,e){const t=e?.filter(i=>i.kind!=="image").filter(i=>i.path&&!/^https?:\/\//i.test(i.path));if(!t?.length||t.every(i=>o.includes(i.path)))return o;const n=t.map((i,s)=>{const a=i.name||`attachment-${s+1}`,d=i.mimeType?` (${i.mimeType})`:"";return`[${b(a)}${d}](<${i.path}>)`});return[o,"",...n].join(`
2
2
  `)}function fe(o,e){const t=e?.filter(n=>n.path&&!/^https?:\/\//i.test(n.path)&&!o.includes(n.path));if(!t?.length)return o;const r=t.map((n,i)=>{const s=b(n.name||`attachment-${i+1}`);return n.kind==="image"?`![${s}](<${n.path}>)`:`[${s}](<${n.path}>)`});return[o,"",...r].join(`
3
- `)}function ye(o,e,t){return["queue","--thread",o,"--message",fe(e,t)]}function b(o){return o.replace(/[[\]\\]/g,"\\$&")}class Te extends F{options;get supportsActiveInput(){return!0}async injectActiveInput(e){const t=this.agentSessionId,r=this.activeTurnId;if(!t||!r||!this.process)throw new Error("codex_active_turn_unavailable");const n=await this.sendRpc("turn/steer",{threadId:t,expectedTurnId:r,input:[M(e.text,e.attachments)],...e.clientMessageId?{clientUserMessageId:e.clientMessageId}:{}});if(n.turnId&&n.turnId!==r)throw new Error("codex_active_turn_changed")}type="codex";get recoveryCapabilities(){return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!0}}process=null;workDir=null;seq=0;runId="";pendingUsage;agentSessionId=null;hasEmittedText=!1;textTail="";terminalState="open";forceCloseTimer=null;stderrBuf="";rpcSeq=1;pendingRequests=new Map;appServerReady=null;appServerStartupError=null;activeTurnId=null;deltaItemIds=new Set;lastTransientStatus="";agentSystemPrompt="";managedAgentPolicy=null;managedPermissionConfig=null;configurationRestartRequired=!1;managedRoomTools=new V;configuredManagedRoomContextToken=null;configuredManagedRoomExecutor=null;managedRoomToolThreadId=null;managedRoomCapabilityExpectedForTurn=!1;managedRoomTurnBindingFailed=!1;preparedExternalOwnerThreadId=null;managedTurnReplay=null;managedAsyncRecovery=null;persistNativeSession=!0;nativeSessionVisibility="user";constructor(e={}){super(),this.options=e}externalChannel=null;shennianSessionId=null;extraEnv={};configure(e){const t=this.configurationFingerprint();this.shennianSessionId=e.sessionId??null,this.externalChannel=e.externalChannel??null,this.extraEnv=e.env??{},"managedAgentPolicy"in e&&(this.managedAgentPolicy=e.managedAgentPolicy??null),("managedRoomContextToken"in e||"managedRoomExecutor"in e)&&(this.managedRoomTools.deactivateTurn(),this.configuredManagedRoomContextToken=e.managedRoomContextToken?.trim()||null,this.configuredManagedRoomExecutor=e.managedRoomExecutor??null),this.managedAgentPolicy&&(this.workDir=this.managedAgentPolicy.adapterPolicy.workDir);const r=this.configurationFingerprint();t!==r&&this.process&&(this.configurationRestartRequired=!0)}configurationFingerprint(){const e=Object.keys(this.extraEnv).sort().map(t=>[t,this.extraEnv[t]??null]);return S("sha256").update(JSON.stringify({sessionId:this.shennianSessionId,externalChannel:this.externalChannel,env:e,managedAgentPolicy:this.managedAgentPolicy})).digest("hex")}buildProcessEnv(e={}){if(!this.managedAgentPolicy)return L({...e,...this.extraEnv});if(R(this.managedAgentPolicy))return U({...e,...this.extraEnv});const t=Object.fromEntries(Object.entries(this.extraEnv).filter(([r])=>r!=="SHENNIAN_MANAGED_ROOM_CONTEXT"&&r!=="SHENNIAN_MANAGED_ROOM_IPC_ROOT"));return $({agentType:"codex",providerEnv:t,sessionEnv:t,runtimeEnv:e})}async start(e,t,r,n){this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??t,this.seq=0,this.persistNativeSession=n?.persistNativeSession!==!1,this.nativeSessionVisibility=n?.nativeSessionVisibility??"user",r&&(this.agentSessionId=r)}async prepareSend(e,t,r,n,i,s){const a=i?.trim()??"";if(a!==this.agentSystemPrompt&&(this.agentSystemPrompt=a,this.process&&await this.killProcess(!0)),!(!this.agentSessionId||this.activeTurnId)){this.preparedExternalOwnerThreadId=null;try{await this.ensureAppServer(I(t))}catch(d){if(!P(d))throw d;if(s?.source==="room_activation")throw new Error("codex_managed_thread_owned_externally",{cause:d});if(this.isThreadTailInterrupted(this.agentSessionId))throw new Error(E,{cause:d});this.preparedExternalOwnerThreadId=this.agentSessionId}}}async send(e,t,r,n,i,s){if(s?.source==="room_activation"&&!this.managedAgentPolicy)throw new Error("managed_agent_policy_missing");if(s?.source==="room_activation"&&(!this.configuredManagedRoomContextToken||!this.configuredManagedRoomExecutor))throw new Error("codex_managed_room_tool_context_unavailable");const a=s?.source==="room_activation";this.managedRoomCapabilityExpectedForTurn=!1,this.activeTurnId&&(await this.interruptActiveTurn().catch(()=>{}),await this.killProcess(!0)),this.configurationRestartRequired&&this.process&&await this.killProcess(!0),this.configurationRestartRequired=!1;const d=I(t),l=oe(r),c=i?.trim()??"";if(c!==this.agentSystemPrompt&&(this.agentSystemPrompt=c,this.process&&await this.killProcess(!0)),s?.source==="room_activation"&&this.managedRoomTools.configure(this.configuredManagedRoomContextToken,this.configuredManagedRoomExecutor),this.runId=N(),this.seq=0,this.resetRunState(),this.agentSessionId&&this.preparedExternalOwnerThreadId===this.agentSessionId)return this.preparedExternalOwnerThreadId=null,{deliveryMode:"external_owner_queue",queuedSubmissionId:await this.enqueueForExternalOwner(this.agentSessionId,e,n)};this.managedRoomCapabilityExpectedForTurn=a;try{await this.ensureAppServer(d)}catch(u){if(!this.agentSessionId||!P(u))throw u;if(s?.source==="room_activation")throw new Error("codex_managed_thread_owned_externally",{cause:u});if(this.isThreadTailInterrupted(this.agentSessionId))throw new Error(E,{cause:u});return{deliveryMode:"external_owner_queue",queuedSubmissionId:await this.enqueueForExternalOwner(this.agentSessionId,e,n)}}const h=this.agentSessionId;if(!h)throw new Error("codex app-server did not create a thread");this.emitEvent({state:"start",agentSessionId:h}),this.managedTurnReplay=this.managedPermissionConfig?{text:e,modelId:d,reasoningEffort:l,attachments:n,recoveryCount:0}:null;const m=await this.startTurnWithRecovery(h,e,d,l,n),g=this.agentSessionId??h;if(this.activeTurnId=m.turn?.id??null,this.managedRoomTurnBindingFailed)throw await this.killProcess(),new Error("codex_managed_room_turn_binding_failed");if(this.managedRoomCapabilityExpectedForTurn&&this.managedRoomToolThreadId===g&&this.activeTurnId&&!this.managedRoomTools.bindTurn(g,this.activeTurnId))throw await this.killProcess(),new Error("codex_managed_room_turn_binding_failed");return{deliveryMode:"direct"}}isThreadTailInterrupted(e){return this.options.isThreadTailInterrupted?.(e)??B(e)}async enqueueForExternalOwner(e,t,r){const n=v("codex");if(!n)throw new Error('Command "codex" not found. Is OpenAI Codex CLI installed?');const i=ye(e,t,r),s=x(n,i,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:this.buildProcessEnv({NO_COLOR:"1"})});return await new Promise((a,d)=>{let l="",c="",h=!1;const m=(u,f)=>{h||(h=!0,clearTimeout(g),u?d(u):a(f))},g=setTimeout(()=>{s.kill("SIGTERM"),m(new Error("Codex Desktop message queue timed out"))},6e4);g.unref?.(),s.stdout?.on("data",u=>{l+=u.toString()}),s.stderr?.on("data",u=>{c+=u.toString()}),s.once("error",u=>m(u)),s.once("close",u=>{const f=`${l}
4
- ${c}`.trim();if(u!==0){m(new Error(f||`codex queue exited with code ${u??"unknown"}`));return}const O=f.match(/Queued message\s+([^\s]+)\s+for thread/i)?.[1];m(void 0,O)})})}async resume(e){await this.killProcess(),this.agentSessionId=e,this.resetTextState()}async setTitle(e,t,r){const n=e.trim(),i=t.replace(/\s+/g," ").trim();!n||!i||(this.agentSessionId=n,r?.trim()&&(this.workDir=r),await this.ensureAppServer(),await this.sendRpc("thread/name/set",{threadId:n,name:i}))}async stop(){this.managedRoomTools.deactivateTurn(),await this.interruptActiveTurn().catch(()=>{}),await this.killProcess()}async getStatus(){const e=this.agentSessionId,t=this.activeTurnId;if(!e||!this.process)return{active:!1,runId:t,runPhase:null,canStop:!1};let r=null;try{r=(await this.sendRpc("thread/read",{threadId:e,includeTurns:!1},5e3)).thread?.status??null}catch{}const n=r?.type==="active"||!!t;return{active:n,runId:t,runPhase:n?this.mapThreadStatusToRunPhase(r):null,canStop:!!(n&&t&&this.process)}}spawnCodex(e){const t=v("codex");if(!t){this.emit("error",new Error('Command "codex" not found. Is OpenAI Codex CLI installed?'));return}const r=x(t,e,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:this.buildProcessEnv()});this.process=r,w({input:r.stdout}).on("line",s=>{if(s.trim())try{const a=JSON.parse(s);this.handleStreamEvent(a)}catch{this.emitEvent({state:"delta",text:s})}});let i="";r.stderr?.on("data",s=>{i+=s.toString()}),r.on("close",s=>{this.process===r&&(this.process=null,this.clearForceCloseTimer(),this.handleProcessClose(s,i))}),r.on("error",s=>{this.process===r&&(this.process=null,s.code==="ENOENT"?this.emit("error",new Error('Command "codex" not found. Is OpenAI Codex CLI installed?')):this.emit("error",s))})}spawnAppServer(){const e=v("codex");if(!e){this.emit("error",new Error('Command "codex" not found. Is OpenAI Codex CLI installed?'));return}const t=["app-server","--listen","stdio://"],r=this.options.modelInstructionsFile??W(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,this.agentSystemPrompt);r&&t.push("-c",`model_instructions_file=${JSON.stringify(r)}`);const n=x(e,t,{cwd:this.workDir??void 0,stdio:["pipe","pipe","pipe"],env:this.buildProcessEnv({NO_COLOR:"1"})});this.process=n,this.stderrBuf="",this.appServerStartupError=null,w({input:n.stdout}).on("line",s=>{if(!s.trim())return;let a;try{a=JSON.parse(s)}catch{this.handleAppServerNonJsonStdout(s);return}this.handleAppServerMessage(a)}),n.stderr?.on("data",s=>{this.stderrBuf+=s.toString()}),n.on("close",s=>{if(this.process!==n)return;const a=this.activeTurnId!=null;this.process=null,this.appServerReady=null,this.activeTurnId=null,this.managedRoomTools.reset(),this.clearConfiguredManagedRoomContext(),this.rejectAllPending(new Error(A(this.stderrBuf)||`codex app-server exited with code ${s}`)),this.terminalState==="open"&&a&&this.handleProcessClose(s,this.stderrBuf)}),n.on("error",s=>{this.process===n&&(this.process=null,this.managedRoomTools.reset(),this.clearConfiguredManagedRoomContext(),this.rejectAllPending(s),s.code==="ENOENT"?this.emit("error",new Error('Command "codex" not found. Is OpenAI Codex CLI installed?')):this.emit("error",s))})}async ensureAppServer(e){return this.appServerReady?this.appServerReady:(this.spawnAppServer(),this.appServerReady=this.initializeAppServer(e).catch(async t=>{throw this.appServerReady=null,await this.killProcess(),t}),this.appServerReady)}async initializeAppServer(e){const t=I(e);await this.sendRpc("initialize",{clientInfo:Y,capabilities:{experimentalApi:!0}}),this.managedPermissionConfig=this.managedAgentPolicy&&!R(this.managedAgentPolicy)?await this.buildManagedPermissionConfig():null;const r=!!(this.configuredManagedRoomContextToken||this.configuredManagedRoomExecutor);if(this.managedAgentPolicy&&r&&!this.managedRoomTools.isConfigured()&&(this.managedRoomTools.configure(this.configuredManagedRoomContextToken,this.configuredManagedRoomExecutor),!this.managedRoomTools.isConfigured()))throw new Error("codex_managed_room_tool_context_unavailable");if(this.agentSessionId&&this.managedAgentPolicy&&r&&this.agentSessionId!==this.managedRoomToolThreadId){if(!this.managedRoomTools.isConfigured())throw new Error("codex_managed_room_tool_context_unavailable");this.agentSessionId=null}if(this.agentSessionId){const l={threadId:this.agentSessionId,cwd:this.workDir,approvalPolicy:"never",...this.managedPermissionConfig?{config:this.managedPermissionConfig.threadConfig}:{sandbox:"danger-full-access"},persistExtendedHistory:!0,...t?{model:t}:{}};let c;try{c=await this.sendRpc("thread/resume",{...l,excludeTurns:!0})}catch(h){if(!ce(h))throw h;c=await this.sendRpc("thread/resume",l)}this.agentSessionId=c.thread?.id??this.agentSessionId,this.managedPermissionConfig&&C(c,this.managedPermissionConfig.profileId),this.managedAgentPolicy&&r&&(this.managedRoomTools.bindThread(this.agentSessionId),this.managedRoomToolThreadId=this.agentSessionId);return}const n=this.options.hidden||this.nativeSessionVisibility==="internal"||!this.persistNativeSession,i=n?void 0:await this.resolveCodexProjectId(),s={cwd:this.workDir,approvalPolicy:"never",...this.managedPermissionConfig?{config:this.managedPermissionConfig.threadConfig}:{sandbox:"danger-full-access"},serviceName:"Shennian",...n?{}:{threadSource:"user"},experimentalRawEvents:!1,persistExtendedHistory:!0,...this.managedAgentPolicy&&r?{dynamicTools:this.extraEnv.SHENNIAN_MANAGER_SESSION_ID?H:J}:{},...i?{projectId:i}:{},...t?{model:t}:{}};let a;if(n&&!this.managedPermissionConfig)a=await this.sendRpc("thread/start",s);else try{a=await this.sendRpc("thread/start",{...s,historyMode:"paginated"})}catch(l){throw le(l)?new Error("\u5F53\u524D Codex CLI \u4E0D\u652F\u6301\u521B\u5EFA\u53EF\u5728 Codex Desktop \u4E2D\u7EE7\u7EED\u7684\u65B0\u4F1A\u8BDD\uFF0C\u8BF7\u624B\u52A8\u5347\u7EA7 Codex CLI \u540E\u91CD\u8BD5\u3002\u795E\u5FF5\u4E0D\u4F1A\u81EA\u52A8\u5347\u7EA7\uFF0C\u4E5F\u4E0D\u4F1A\u964D\u7EA7\u521B\u5EFA\u4E0D\u53EF\u89C1\u7684 legacy \u4F1A\u8BDD\u3002",{cause:l}):l}const d=a.thread?.id;if(!d)throw new Error("codex app-server thread/start returned no thread id");this.managedPermissionConfig&&C(a,this.managedPermissionConfig.profileId),this.managedAgentPolicy&&r&&(this.managedRoomTools.bindThread(d),this.managedRoomToolThreadId=d),this.agentSessionId=d}async buildManagedPermissionConfig(){const e=this.managedAgentPolicy;if(!e)throw new Error("managed_agent_policy_missing");const t=e.adapterPolicy.externalCapabilities.mcp?[]:Q(await this.sendRpc("config/read",{cwd:e.adapterPolicy.workDir}));return K(G(e),e.adapterPolicy.workDir,{configuredMcpServerNames:t,shellSubprocessPolicy:e.environmentPolicy.shellSubprocess})}async resolveCodexProjectId(){const e=this.workDir?.trim();if(e)try{const t=[];let r;do{const l=await this.sendRpc("project/list",{limit:100,...r?{cursor:r}:{}});t.push(...l.data??[]),r=l.nextCursor}while(r);const n=he(t,e);if(n)return n;const i=p.resolve(e),s=`shennian-project-${S("sha256").update(i).digest("hex")}`,d=(await this.sendRpc("project/create",{idempotencyKey:s,name:p.basename(i)||i,roots:[{path:i}],metadata:{createdBy:"Shennian"}})).project?.id;if(!d)throw new Error("codex app-server project/create returned no project id");return d}catch(t){throw ue(t)?new Error("\u5F53\u524D Codex CLI \u4E0D\u652F\u6301\u521B\u5EFA\u53EF\u5F52\u5C5E\u5230 Codex Desktop \u9879\u76EE\u7684\u65B0\u4F1A\u8BDD\uFF0C\u8BF7\u624B\u52A8\u5347\u7EA7 Codex CLI \u540E\u91CD\u8BD5\u3002\u795E\u5FF5\u4E0D\u4F1A\u81EA\u52A8\u5347\u7EA7\uFF0C\u4E5F\u4E0D\u4F1A\u76F4\u63A5\u4FEE\u6539 Codex Desktop \u7684\u79C1\u6709\u4FA7\u680F\u7D22\u5F15\u3002",{cause:t}):t}}async startTurnWithRecovery(e,t,r,n,i){try{return await this.startTurn(e,t,r,n,i)}catch(s){if(!T(s))throw s;if(this.managedAgentPolicy||this.managedPermissionConfig){this.logManagedThreadLifecycle("rollout.missing",{threadId:e,recovery:"recreate"}),await this.killProcess(!0),this.agentSessionId=null,this.managedRoomToolThreadId=null,await this.ensureAppServer(r);const a=this.agentSessionId;if(!a)throw new Error("codex app-server did not recreate the managed thread",{cause:s});return this.logManagedThreadLifecycle("thread.recreated",{previousThreadId:e,threadId:a}),this.emitEvent({state:"start",agentSessionId:a}),await this.startFreshManagedTurnWithReadinessRetry(a,t,r,n,i)}return await this.killProcess(),await this.ensureAppServer(r),await this.startTurn(e,t,r,n,i)}}async startFreshManagedTurnWithReadinessRetry(e,t,r,n,i){const s=[0,100,300,1e3];let a;for(let d=0;d<s.length;d+=1){const l=s[d];l>0&&await new Promise(c=>setTimeout(c,l));try{const c=await this.startTurn(e,t,r,n,i);return d>0&&this.logManagedThreadLifecycle("rollout.ready",{threadId:e,attempt:d+1}),c}catch(c){if(a=c,!T(c)||d===s.length-1)throw c;this.logManagedThreadLifecycle("rollout.retry",{threadId:e,attempt:d+2,delayMs:s[d+1]})}}throw a}logManagedThreadLifecycle(e,t){console.error(`[codex.managed] ${JSON.stringify({event:e,...t})}`)}async startTurn(e,t,r,n,i){try{return await this.sendRpc("turn/start",{threadId:e,input:[M(t,i)],approvalPolicy:"never",...this.managedPermissionConfig?{}:{sandboxPolicy:{type:"dangerFullAccess"}},...r?{model:r}:{},...n?{effort:n}:{}})}catch(s){throw n&&re(s)?new Error(`Codex app-server does not accept reasoning effort "${n}" for this turn. Refresh models or upgrade Codex CLI, then retry.`,{cause:s}):s}}async interruptActiveTurn(){const e=this.agentSessionId,t=this.activeTurnId;this.activeTurnId=null,this.managedRoomTools.deactivateTurn(),!(!e||!t||!this.process)&&await this.sendRpc("turn/interrupt",{threadId:e,turnId:t},5e3)}sendRpc(e,t,r=6e4){if(this.appServerStartupError)return Promise.reject(this.appServerStartupError);const n=this.process;if(!n?.stdin)return Promise.reject(new Error("codex app-server is not running"));const i=this.rpcSeq++,s=JSON.stringify({id:i,method:e,params:t});return new Promise((a,d)=>{const l=setTimeout(()=>{this.pendingRequests.delete(i),d(new Error(`codex app-server request timed out: ${e}`))},r);this.pendingRequests.set(i,{resolve:a,reject:d,timer:l}),n.stdin.write(`${s}
5
- `,c=>{c&&(clearTimeout(l),this.pendingRequests.delete(i),d(c))})})}handleAppServerMessage(e){if(e.method==="item/tool/call"&&e.id!=null){this.handleManagedRoomToolCall(e.id,e.params??{});return}if(e.id!=null){const r=typeof e.id=="number"?this.pendingRequests.get(e.id):void 0;r&&(clearTimeout(r.timer),this.pendingRequests.delete(e.id),e.error?r.reject(new Error(e.error.message||`codex app-server error ${e.error.code??""}`.trim())):r.resolve(e.result))}if(!e.method)return;const t=e.params??{};switch(e.method){case"turn/started":{const r=typeof t.turn=="object"&&t.turn!==null?t.turn:null,n=typeof r?.id=="string"?r.id:null,i=typeof t.threadId=="string"?t.threadId:"";n&&(this.activeTurnId=n,this.managedRoomCapabilityExpectedForTurn&&this.managedRoomToolThreadId===i&&!this.managedRoomTools.bindTurn(i,n)&&(this.managedRoomTurnBindingFailed=!0,this.emitErrorIfOpen("codex_managed_room_turn_binding_failed")));break}case"thread/status/changed":{const r=typeof t.threadId=="string"?t.threadId:"";if(r&&this.agentSessionId&&r!==this.agentSessionId)break;const n=typeof t.status=="object"&&t.status!==null?t.status:null;n?.type==="active"&&this.emitEvent({state:"heartbeat",runPhase:this.mapThreadStatusToRunPhase(n)});break}case"item/agentMessage/delta":{const r=typeof t.itemId=="string"?t.itemId:"";r&&this.deltaItemIds.add(r),typeof t.delta=="string"&&this.emitText(t.delta);break}case"item/completed":this.handleAppServerCompletedItem(t);break;case"thread/tokenUsage/updated":this.handleAppServerUsage(t);break;case"turn/completed":{const r=typeof t.turn=="object"&&t.turn!==null?t.turn:null,n=typeof r?.id=="string"?r.id:null;(!this.activeTurnId||n===this.activeTurnId)&&(this.activeTurnId=null,this.managedRoomTools.deactivateTurn(),this.emitFinalIfOpen());break}case"turn/failed":{const r=_(t);if(this.scheduleManagedAsyncRolloutRecovery(r))return;this.emitErrorIfOpen(r||"turn failed");break}case"error":{const r=_(t);if(ne(r)){this.emitTransientStatus(r);return}if(this.scheduleManagedAsyncRolloutRecovery(r))return;this.emitErrorIfOpen(r);break}}}scheduleManagedAsyncRolloutRecovery(e){if(!this.managedAgentPolicy&&!this.managedPermissionConfig||!this.managedTurnReplay||!T(new Error(e)))return!1;if(this.managedAsyncRecovery)return!0;if(this.managedTurnReplay.recoveryCount>=2)return!1;this.managedTurnReplay.recoveryCount+=1;const t=this.managedTurnReplay.recoveryCount;return this.logManagedThreadLifecycle("rollout.failed-async",{threadId:this.agentSessionId,recoveryCount:t}),this.managedAsyncRecovery=this.recoverManagedTurnAfterAsyncRolloutFailure().catch(r=>{const n=T(r)?"no rollout found after managed thread recovery":r instanceof Error?r.message:"managed thread recovery failed";this.emitErrorIfOpen(n)}).finally(()=>{this.managedAsyncRecovery=null}),!0}async recoverManagedTurnAfterAsyncRolloutFailure(){const e=this.managedTurnReplay,t=this.agentSessionId;if(!e||!t||this.terminalState!=="open")return;this.activeTurnId=null,this.managedRoomTools.deactivateTurn(),await this.killProcess(!0),this.agentSessionId=null,this.managedRoomToolThreadId=null,await this.ensureAppServer(e.modelId);const r=this.agentSessionId;if(!r)throw new Error("codex app-server did not recreate the managed thread");this.logManagedThreadLifecycle("thread.recreated-async",{previousThreadId:t,threadId:r,recoveryCount:e.recoveryCount}),this.emitEvent({state:"start",agentSessionId:r});const n=await this.startFreshManagedTurnWithReadinessRetry(r,e.text,e.modelId,e.reasoningEffort,e.attachments);if(this.activeTurnId=n.turn?.id??null,this.managedRoomTurnBindingFailed)throw new Error("codex_managed_room_turn_binding_failed");if(this.managedRoomCapabilityExpectedForTurn&&this.managedRoomToolThreadId===r&&this.activeTurnId&&!this.managedRoomTools.bindTurn(r,this.activeTurnId))throw new Error("codex_managed_room_turn_binding_failed")}async handleManagedRoomToolCall(e,t){const r=await this.managedRoomTools.execute(t);if(this.writeAppServerResponse(e,r),r.success&&t.tool==="shennian_room_send"){const n=typeof t.arguments=="object"&&t.arguments!==null?t.arguments:null,i=typeof n?.text=="string"?n.text.trim():"";i&&this.emitText(i,"block")}}writeAppServerResponse(e,t){const r=this.process;r?.stdin&&r.stdin.write(`${JSON.stringify({id:e,result:t})}
3
+ `)}function ye(o,e,t){return["queue","--thread",o,"--message",fe(e,t)]}function b(o){return o.replace(/[[\]\\]/g,"\\$&")}class ve extends F{options;get supportsActiveInput(){return!0}async injectActiveInput(e){const t=this.agentSessionId,r=this.activeTurnId;if(!t||!r||!this.process)throw new Error("codex_active_turn_unavailable");const n=await this.sendRpc("turn/steer",{threadId:t,expectedTurnId:r,input:[M(e.text,e.attachments)],...e.clientMessageId?{clientUserMessageId:e.clientMessageId}:{}});if(n.turnId&&n.turnId!==r)throw new Error("codex_active_turn_changed")}type="codex";get recoveryCapabilities(){return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!0}}process=null;workDir=null;seq=0;runId="";pendingUsage;agentSessionId=null;hasEmittedText=!1;textTail="";terminalState="open";forceCloseTimer=null;stderrBuf="";rpcSeq=1;pendingRequests=new Map;appServerReady=null;appServerStartupError=null;activeTurnId=null;deltaItemIds=new Set;lastTransientStatus="";agentSystemPrompt="";managedAgentPolicy=null;managedPermissionConfig=null;configurationRestartRequired=!1;managedRoomTools=new V;configuredManagedRoomContextToken=null;configuredManagedRoomExecutor=null;managedRoomToolThreadId=null;managedRoomCapabilityExpectedForTurn=!1;managedRoomTurnBindingFailed=!1;preparedExternalOwnerThreadId=null;managedTurnReplay=null;managedAsyncRecovery=null;persistNativeSession=!0;nativeSessionVisibility="user";constructor(e={}){super(),this.options=e}externalChannel=null;shennianSessionId=null;extraEnv={};configure(e){const t=this.configurationFingerprint();this.shennianSessionId=e.sessionId??null,this.externalChannel=e.externalChannel??null,this.extraEnv=e.env??{},"managedAgentPolicy"in e&&(this.managedAgentPolicy=e.managedAgentPolicy??null),("managedRoomContextToken"in e||"managedRoomExecutor"in e)&&(this.managedRoomTools.deactivateTurn(),this.configuredManagedRoomContextToken=e.managedRoomContextToken?.trim()||null,this.configuredManagedRoomExecutor=e.managedRoomExecutor??null),this.managedAgentPolicy&&(this.workDir=this.managedAgentPolicy.adapterPolicy.workDir);const r=this.configurationFingerprint();t!==r&&this.process&&(this.configurationRestartRequired=!0)}configurationFingerprint(){const e=Object.keys(this.extraEnv).sort().map(t=>[t,this.extraEnv[t]??null]);return S("sha256").update(JSON.stringify({sessionId:this.shennianSessionId,externalChannel:this.externalChannel,env:e,managedAgentPolicy:this.managedAgentPolicy})).digest("hex")}buildProcessEnv(e={}){if(!this.managedAgentPolicy)return L({...e,...this.extraEnv});if(R(this.managedAgentPolicy))return U({...e,...this.extraEnv});const t=Object.fromEntries(Object.entries(this.extraEnv).filter(([r])=>r!=="SHENNIAN_MANAGED_ROOM_CONTEXT"&&r!=="SHENNIAN_MANAGED_ROOM_IPC_ROOT"));return $({agentType:"codex",providerEnv:t,sessionEnv:t,runtimeEnv:e})}async start(e,t,r,n){this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??t,this.seq=0,this.persistNativeSession=n?.persistNativeSession!==!1,this.nativeSessionVisibility=n?.nativeSessionVisibility??"user",r&&(this.agentSessionId=r)}async prepareSend(e,t,r,n,i,s){const a=i?.trim()??"";if(a!==this.agentSystemPrompt&&(this.agentSystemPrompt=a,this.process&&await this.killProcess(!0)),!(!this.agentSessionId||this.activeTurnId)){this.preparedExternalOwnerThreadId=null;try{await this.ensureAppServer(I(t))}catch(d){if(!P(d))throw d;if(s?.source==="room_activation"||s?.source==="managed_private")throw new Error("codex_managed_thread_owned_externally",{cause:d});if(this.isThreadTailInterrupted(this.agentSessionId))throw new Error(E,{cause:d});this.preparedExternalOwnerThreadId=this.agentSessionId}}}async send(e,t,r,n,i,s){if((s?.source==="room_activation"||s?.source==="managed_private")&&!this.managedAgentPolicy)throw new Error("managed_agent_policy_missing");if((s?.source==="room_activation"||s?.source==="managed_private")&&(!this.configuredManagedRoomContextToken||!this.configuredManagedRoomExecutor))throw new Error("codex_managed_room_tool_context_unavailable");const a=s?.source==="room_activation"||s?.source==="managed_private";this.managedRoomCapabilityExpectedForTurn=!1,this.activeTurnId&&(await this.interruptActiveTurn().catch(()=>{}),await this.killProcess(!0)),this.configurationRestartRequired&&this.process&&await this.killProcess(!0),this.configurationRestartRequired=!1;const d=I(t),l=oe(r),c=i?.trim()??"";if(c!==this.agentSystemPrompt&&(this.agentSystemPrompt=c,this.process&&await this.killProcess(!0)),(s?.source==="room_activation"||s?.source==="managed_private")&&this.managedRoomTools.configure(this.configuredManagedRoomContextToken,this.configuredManagedRoomExecutor),this.runId=N(),this.seq=0,this.resetRunState(),this.agentSessionId&&this.preparedExternalOwnerThreadId===this.agentSessionId)return this.preparedExternalOwnerThreadId=null,{deliveryMode:"external_owner_queue",queuedSubmissionId:await this.enqueueForExternalOwner(this.agentSessionId,e,n)};this.managedRoomCapabilityExpectedForTurn=a;try{await this.ensureAppServer(d)}catch(u){if(!this.agentSessionId||!P(u))throw u;if(s?.source==="room_activation"||s?.source==="managed_private")throw new Error("codex_managed_thread_owned_externally",{cause:u});if(this.isThreadTailInterrupted(this.agentSessionId))throw new Error(E,{cause:u});return{deliveryMode:"external_owner_queue",queuedSubmissionId:await this.enqueueForExternalOwner(this.agentSessionId,e,n)}}const h=this.agentSessionId;if(!h)throw new Error("codex app-server did not create a thread");this.emitEvent({state:"start",agentSessionId:h}),this.managedTurnReplay=this.managedPermissionConfig?{text:e,modelId:d,reasoningEffort:l,attachments:n,recoveryCount:0}:null;const m=await this.startTurnWithRecovery(h,e,d,l,n),g=this.agentSessionId??h;if(this.activeTurnId=m.turn?.id??null,this.managedRoomTurnBindingFailed)throw await this.killProcess(),new Error("codex_managed_room_turn_binding_failed");if(this.managedRoomCapabilityExpectedForTurn&&this.managedRoomToolThreadId===g&&this.activeTurnId&&!this.managedRoomTools.bindTurn(g,this.activeTurnId))throw await this.killProcess(),new Error("codex_managed_room_turn_binding_failed");return{deliveryMode:"direct"}}isThreadTailInterrupted(e){return this.options.isThreadTailInterrupted?.(e)??B(e)}async enqueueForExternalOwner(e,t,r){const n=T("codex");if(!n)throw new Error('Command "codex" not found. Is OpenAI Codex CLI installed?');const i=ye(e,t,r),s=x(n,i,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:this.buildProcessEnv({NO_COLOR:"1"})});return await new Promise((a,d)=>{let l="",c="",h=!1;const m=(u,f)=>{h||(h=!0,clearTimeout(g),u?d(u):a(f))},g=setTimeout(()=>{s.kill("SIGTERM"),m(new Error("Codex Desktop message queue timed out"))},6e4);g.unref?.(),s.stdout?.on("data",u=>{l+=u.toString()}),s.stderr?.on("data",u=>{c+=u.toString()}),s.once("error",u=>m(u)),s.once("close",u=>{const f=`${l}
4
+ ${c}`.trim();if(u!==0){m(new Error(f||`codex queue exited with code ${u??"unknown"}`));return}const O=f.match(/Queued message\s+([^\s]+)\s+for thread/i)?.[1];m(void 0,O)})})}async resume(e){await this.killProcess(),this.agentSessionId=e,this.resetTextState()}async setTitle(e,t,r){const n=e.trim(),i=t.replace(/\s+/g," ").trim();!n||!i||(this.agentSessionId=n,r?.trim()&&(this.workDir=r),await this.ensureAppServer(),await this.sendRpc("thread/name/set",{threadId:n,name:i}))}async stop(){this.managedRoomTools.deactivateTurn(),await this.interruptActiveTurn().catch(()=>{}),await this.killProcess()}async getStatus(){const e=this.agentSessionId,t=this.activeTurnId;if(!e||!this.process)return{active:!1,runId:t,runPhase:null,canStop:!1};let r=null;try{r=(await this.sendRpc("thread/read",{threadId:e,includeTurns:!1},5e3)).thread?.status??null}catch{}const n=r?.type==="active"||!!t;return{active:n,runId:t,runPhase:n?this.mapThreadStatusToRunPhase(r):null,canStop:!!(n&&t&&this.process)}}spawnCodex(e){const t=T("codex");if(!t){this.emit("error",new Error('Command "codex" not found. Is OpenAI Codex CLI installed?'));return}const r=x(t,e,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:this.buildProcessEnv()});this.process=r,w({input:r.stdout}).on("line",s=>{if(s.trim())try{const a=JSON.parse(s);this.handleStreamEvent(a)}catch{this.emitEvent({state:"delta",text:s})}});let i="";r.stderr?.on("data",s=>{i+=s.toString()}),r.on("close",s=>{this.process===r&&(this.process=null,this.clearForceCloseTimer(),this.handleProcessClose(s,i))}),r.on("error",s=>{this.process===r&&(this.process=null,s.code==="ENOENT"?this.emit("error",new Error('Command "codex" not found. Is OpenAI Codex CLI installed?')):this.emit("error",s))})}spawnAppServer(){const e=T("codex");if(!e){this.emit("error",new Error('Command "codex" not found. Is OpenAI Codex CLI installed?'));return}const t=["app-server","--listen","stdio://"],r=this.options.modelInstructionsFile??W(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,this.agentSystemPrompt);r&&t.push("-c",`model_instructions_file=${JSON.stringify(r)}`);const n=x(e,t,{cwd:this.workDir??void 0,stdio:["pipe","pipe","pipe"],env:this.buildProcessEnv({NO_COLOR:"1"})});this.process=n,this.stderrBuf="",this.appServerStartupError=null,w({input:n.stdout}).on("line",s=>{if(!s.trim())return;let a;try{a=JSON.parse(s)}catch{this.handleAppServerNonJsonStdout(s);return}this.handleAppServerMessage(a)}),n.stderr?.on("data",s=>{this.stderrBuf+=s.toString()}),n.on("close",s=>{if(this.process!==n)return;const a=this.activeTurnId!=null;this.process=null,this.appServerReady=null,this.activeTurnId=null,this.managedRoomTools.reset(),this.clearConfiguredManagedRoomContext(),this.rejectAllPending(new Error(A(this.stderrBuf)||`codex app-server exited with code ${s}`)),this.terminalState==="open"&&a&&this.handleProcessClose(s,this.stderrBuf)}),n.on("error",s=>{this.process===n&&(this.process=null,this.managedRoomTools.reset(),this.clearConfiguredManagedRoomContext(),this.rejectAllPending(s),s.code==="ENOENT"?this.emit("error",new Error('Command "codex" not found. Is OpenAI Codex CLI installed?')):this.emit("error",s))})}async ensureAppServer(e){return this.appServerReady?this.appServerReady:(this.spawnAppServer(),this.appServerReady=this.initializeAppServer(e).catch(async t=>{throw this.appServerReady=null,await this.killProcess(),t}),this.appServerReady)}async initializeAppServer(e){const t=I(e);await this.sendRpc("initialize",{clientInfo:Y,capabilities:{experimentalApi:!0}}),this.managedPermissionConfig=this.managedAgentPolicy&&!R(this.managedAgentPolicy)?await this.buildManagedPermissionConfig():null;const r=!!(this.configuredManagedRoomContextToken||this.configuredManagedRoomExecutor);if(this.managedAgentPolicy&&r&&!this.managedRoomTools.isConfigured()&&(this.managedRoomTools.configure(this.configuredManagedRoomContextToken,this.configuredManagedRoomExecutor),!this.managedRoomTools.isConfigured()))throw new Error("codex_managed_room_tool_context_unavailable");if(this.agentSessionId&&this.managedAgentPolicy&&r&&this.agentSessionId!==this.managedRoomToolThreadId){if(!this.managedRoomTools.isConfigured())throw new Error("codex_managed_room_tool_context_unavailable");this.agentSessionId=null}if(this.agentSessionId){const l={threadId:this.agentSessionId,cwd:this.workDir,approvalPolicy:"never",...this.managedPermissionConfig?{config:this.managedPermissionConfig.threadConfig}:{sandbox:"danger-full-access"},persistExtendedHistory:!0,...t?{model:t}:{}};let c;try{c=await this.sendRpc("thread/resume",{...l,excludeTurns:!0})}catch(h){if(!ce(h))throw h;c=await this.sendRpc("thread/resume",l)}this.agentSessionId=c.thread?.id??this.agentSessionId,this.managedPermissionConfig&&C(c,this.managedPermissionConfig.profileId),this.managedAgentPolicy&&r&&(this.managedRoomTools.bindThread(this.agentSessionId),this.managedRoomToolThreadId=this.agentSessionId);return}const n=this.options.hidden||this.nativeSessionVisibility==="internal"||!this.persistNativeSession,i=n?void 0:await this.resolveCodexProjectId(),s={cwd:this.workDir,approvalPolicy:"never",...this.managedPermissionConfig?{config:this.managedPermissionConfig.threadConfig}:{sandbox:"danger-full-access"},serviceName:"Shennian",...n?{}:{threadSource:"user"},experimentalRawEvents:!1,persistExtendedHistory:!0,...this.managedAgentPolicy&&r?{dynamicTools:this.extraEnv.SHENNIAN_MANAGER_SESSION_ID?H:J}:{},...i?{projectId:i}:{},...t?{model:t}:{}};let a;if(n&&!this.managedPermissionConfig)a=await this.sendRpc("thread/start",s);else try{a=await this.sendRpc("thread/start",{...s,historyMode:"paginated"})}catch(l){throw le(l)?new Error("\u5F53\u524D Codex CLI \u4E0D\u652F\u6301\u521B\u5EFA\u53EF\u5728 Codex Desktop \u4E2D\u7EE7\u7EED\u7684\u65B0\u4F1A\u8BDD\uFF0C\u8BF7\u624B\u52A8\u5347\u7EA7 Codex CLI \u540E\u91CD\u8BD5\u3002\u795E\u5FF5\u4E0D\u4F1A\u81EA\u52A8\u5347\u7EA7\uFF0C\u4E5F\u4E0D\u4F1A\u964D\u7EA7\u521B\u5EFA\u4E0D\u53EF\u89C1\u7684 legacy \u4F1A\u8BDD\u3002",{cause:l}):l}const d=a.thread?.id;if(!d)throw new Error("codex app-server thread/start returned no thread id");this.managedPermissionConfig&&C(a,this.managedPermissionConfig.profileId),this.managedAgentPolicy&&r&&(this.managedRoomTools.bindThread(d),this.managedRoomToolThreadId=d),this.agentSessionId=d}async buildManagedPermissionConfig(){const e=this.managedAgentPolicy;if(!e)throw new Error("managed_agent_policy_missing");const t=e.adapterPolicy.externalCapabilities.mcp?[]:Q(await this.sendRpc("config/read",{cwd:e.adapterPolicy.workDir}));return K(G(e),e.adapterPolicy.workDir,{configuredMcpServerNames:t,shellSubprocessPolicy:e.environmentPolicy.shellSubprocess})}async resolveCodexProjectId(){const e=this.workDir?.trim();if(e)try{const t=[];let r;do{const l=await this.sendRpc("project/list",{limit:100,...r?{cursor:r}:{}});t.push(...l.data??[]),r=l.nextCursor}while(r);const n=he(t,e);if(n)return n;const i=p.resolve(e),s=`shennian-project-${S("sha256").update(i).digest("hex")}`,d=(await this.sendRpc("project/create",{idempotencyKey:s,name:p.basename(i)||i,roots:[{path:i}],metadata:{createdBy:"Shennian"}})).project?.id;if(!d)throw new Error("codex app-server project/create returned no project id");return d}catch(t){throw ue(t)?new Error("\u5F53\u524D Codex CLI \u4E0D\u652F\u6301\u521B\u5EFA\u53EF\u5F52\u5C5E\u5230 Codex Desktop \u9879\u76EE\u7684\u65B0\u4F1A\u8BDD\uFF0C\u8BF7\u624B\u52A8\u5347\u7EA7 Codex CLI \u540E\u91CD\u8BD5\u3002\u795E\u5FF5\u4E0D\u4F1A\u81EA\u52A8\u5347\u7EA7\uFF0C\u4E5F\u4E0D\u4F1A\u76F4\u63A5\u4FEE\u6539 Codex Desktop \u7684\u79C1\u6709\u4FA7\u680F\u7D22\u5F15\u3002",{cause:t}):t}}async startTurnWithRecovery(e,t,r,n,i){try{return await this.startTurn(e,t,r,n,i)}catch(s){if(!v(s))throw s;if(this.managedAgentPolicy||this.managedPermissionConfig){this.logManagedThreadLifecycle("rollout.missing",{threadId:e,recovery:"recreate"}),await this.killProcess(!0),this.agentSessionId=null,this.managedRoomToolThreadId=null,await this.ensureAppServer(r);const a=this.agentSessionId;if(!a)throw new Error("codex app-server did not recreate the managed thread",{cause:s});return this.logManagedThreadLifecycle("thread.recreated",{previousThreadId:e,threadId:a}),this.emitEvent({state:"start",agentSessionId:a}),await this.startFreshManagedTurnWithReadinessRetry(a,t,r,n,i)}return await this.killProcess(),await this.ensureAppServer(r),await this.startTurn(e,t,r,n,i)}}async startFreshManagedTurnWithReadinessRetry(e,t,r,n,i){const s=[0,100,300,1e3];let a;for(let d=0;d<s.length;d+=1){const l=s[d];l>0&&await new Promise(c=>setTimeout(c,l));try{const c=await this.startTurn(e,t,r,n,i);return d>0&&this.logManagedThreadLifecycle("rollout.ready",{threadId:e,attempt:d+1}),c}catch(c){if(a=c,!v(c)||d===s.length-1)throw c;this.logManagedThreadLifecycle("rollout.retry",{threadId:e,attempt:d+2,delayMs:s[d+1]})}}throw a}logManagedThreadLifecycle(e,t){console.error(`[codex.managed] ${JSON.stringify({event:e,...t})}`)}async startTurn(e,t,r,n,i){try{return await this.sendRpc("turn/start",{threadId:e,input:[M(t,i)],approvalPolicy:"never",...this.managedPermissionConfig?{}:{sandboxPolicy:{type:"dangerFullAccess"}},...r?{model:r}:{},...n?{effort:n}:{}})}catch(s){throw n&&re(s)?new Error(`Codex app-server does not accept reasoning effort "${n}" for this turn. Refresh models or upgrade Codex CLI, then retry.`,{cause:s}):s}}async interruptActiveTurn(){const e=this.agentSessionId,t=this.activeTurnId;this.activeTurnId=null,this.managedRoomTools.deactivateTurn(),!(!e||!t||!this.process)&&await this.sendRpc("turn/interrupt",{threadId:e,turnId:t},5e3)}sendRpc(e,t,r=6e4){if(this.appServerStartupError)return Promise.reject(this.appServerStartupError);const n=this.process;if(!n?.stdin)return Promise.reject(new Error("codex app-server is not running"));const i=this.rpcSeq++,s=JSON.stringify({id:i,method:e,params:t});return new Promise((a,d)=>{const l=setTimeout(()=>{this.pendingRequests.delete(i),d(new Error(`codex app-server request timed out: ${e}`))},r);this.pendingRequests.set(i,{resolve:a,reject:d,timer:l}),n.stdin.write(`${s}
5
+ `,c=>{c&&(clearTimeout(l),this.pendingRequests.delete(i),d(c))})})}handleAppServerMessage(e){if(e.method==="item/tool/call"&&e.id!=null){this.handleManagedRoomToolCall(e.id,e.params??{});return}if(e.id!=null){const r=typeof e.id=="number"?this.pendingRequests.get(e.id):void 0;r&&(clearTimeout(r.timer),this.pendingRequests.delete(e.id),e.error?r.reject(new Error(e.error.message||`codex app-server error ${e.error.code??""}`.trim())):r.resolve(e.result))}if(!e.method)return;const t=e.params??{};switch(e.method){case"turn/started":{const r=typeof t.turn=="object"&&t.turn!==null?t.turn:null,n=typeof r?.id=="string"?r.id:null,i=typeof t.threadId=="string"?t.threadId:"";n&&(this.activeTurnId=n,this.managedRoomCapabilityExpectedForTurn&&this.managedRoomToolThreadId===i&&!this.managedRoomTools.bindTurn(i,n)&&(this.managedRoomTurnBindingFailed=!0,this.emitErrorIfOpen("codex_managed_room_turn_binding_failed")));break}case"thread/status/changed":{const r=typeof t.threadId=="string"?t.threadId:"";if(r&&this.agentSessionId&&r!==this.agentSessionId)break;const n=typeof t.status=="object"&&t.status!==null?t.status:null;n?.type==="active"&&this.emitEvent({state:"heartbeat",runPhase:this.mapThreadStatusToRunPhase(n)});break}case"item/agentMessage/delta":{const r=typeof t.itemId=="string"?t.itemId:"";r&&this.deltaItemIds.add(r),typeof t.delta=="string"&&this.emitText(t.delta);break}case"item/completed":this.handleAppServerCompletedItem(t);break;case"thread/tokenUsage/updated":this.handleAppServerUsage(t);break;case"turn/completed":{const r=typeof t.turn=="object"&&t.turn!==null?t.turn:null,n=typeof r?.id=="string"?r.id:null;(!this.activeTurnId||n===this.activeTurnId)&&(this.activeTurnId=null,this.managedRoomTools.deactivateTurn(),this.emitFinalIfOpen());break}case"turn/failed":{const r=_(t);if(this.scheduleManagedAsyncRolloutRecovery(r))return;this.emitErrorIfOpen(r||"turn failed");break}case"error":{const r=_(t);if(ne(r)){this.emitTransientStatus(r);return}if(this.scheduleManagedAsyncRolloutRecovery(r))return;this.emitErrorIfOpen(r);break}}}scheduleManagedAsyncRolloutRecovery(e){if(!this.managedAgentPolicy&&!this.managedPermissionConfig||!this.managedTurnReplay||!v(new Error(e)))return!1;if(this.managedAsyncRecovery)return!0;if(this.managedTurnReplay.recoveryCount>=2)return!1;this.managedTurnReplay.recoveryCount+=1;const t=this.managedTurnReplay.recoveryCount;return this.logManagedThreadLifecycle("rollout.failed-async",{threadId:this.agentSessionId,recoveryCount:t}),this.managedAsyncRecovery=this.recoverManagedTurnAfterAsyncRolloutFailure().catch(r=>{const n=v(r)?"no rollout found after managed thread recovery":r instanceof Error?r.message:"managed thread recovery failed";this.emitErrorIfOpen(n)}).finally(()=>{this.managedAsyncRecovery=null}),!0}async recoverManagedTurnAfterAsyncRolloutFailure(){const e=this.managedTurnReplay,t=this.agentSessionId;if(!e||!t||this.terminalState!=="open")return;this.activeTurnId=null,this.managedRoomTools.deactivateTurn(),await this.killProcess(!0),this.agentSessionId=null,this.managedRoomToolThreadId=null,await this.ensureAppServer(e.modelId);const r=this.agentSessionId;if(!r)throw new Error("codex app-server did not recreate the managed thread");this.logManagedThreadLifecycle("thread.recreated-async",{previousThreadId:t,threadId:r,recoveryCount:e.recoveryCount}),this.emitEvent({state:"start",agentSessionId:r});const n=await this.startFreshManagedTurnWithReadinessRetry(r,e.text,e.modelId,e.reasoningEffort,e.attachments);if(this.activeTurnId=n.turn?.id??null,this.managedRoomTurnBindingFailed)throw new Error("codex_managed_room_turn_binding_failed");if(this.managedRoomCapabilityExpectedForTurn&&this.managedRoomToolThreadId===r&&this.activeTurnId&&!this.managedRoomTools.bindTurn(r,this.activeTurnId))throw new Error("codex_managed_room_turn_binding_failed")}async handleManagedRoomToolCall(e,t){const r=await this.managedRoomTools.execute(t);if(this.writeAppServerResponse(e,r),r.success&&t.tool==="shennian_room_send"){const n=typeof t.arguments=="object"&&t.arguments!==null?t.arguments:null,i=typeof n?.text=="string"?n.text.trim():"";i&&this.emitText(i,"block")}}writeAppServerResponse(e,t){const r=this.process;r?.stdin&&r.stdin.write(`${JSON.stringify({id:e,result:t})}
6
6
  `)}mapThreadStatusToRunPhase(e){const t=e?.type==="active"&&Array.isArray(e.activeFlags)?e.activeFlags:[];return t.includes("waitingOnApproval")?"waiting_approval":t.includes("waitingOnUserInput")?"waiting_user_input":"thinking"}handleAppServerNonJsonStdout(e){const t=ae(e);se(t)&&this.failAppServerStartup(new Error("Codex \u672A\u767B\u5F55\u3002\u8BF7\u5148\u5728\u8FD9\u53F0\u7535\u8111\u7684\u7EC8\u7AEF\u8FD0\u884C `codex`\uFF0C\u6309\u63D0\u793A\u5B8C\u6210 ChatGPT \u767B\u5F55\u6216\u914D\u7F6E API key\uFF0C\u7136\u540E\u518D\u56DE\u5230\u795E\u5FF5\u53D1\u9001\u6D88\u606F\u3002"))}failAppServerStartup(e){this.appServerStartupError||(this.appServerStartupError=e,this.rejectAllPending(e),this.process?.kill("SIGTERM"))}handleAppServerCompletedItem(e){const t=typeof e.item=="object"&&e.item!==null?e.item:null;if(!(!t||typeof t.type!="string")&&!ee(t))switch(t.type){case"agentMessage":{const r=typeof t.id=="string"?t.id:"";if(r&&this.deltaItemIds.has(r))return;typeof t.text=="string"&&this.emitText(t.text,"block");break}case"commandExecution":{const r=typeof t.command=="string"?t.command:"",n=typeof t.aggregatedOutput=="string"?t.aggregatedOutput:"";r&&this.emitEvent({state:"tool-call",name:"command_execution",args:{command:r}}),this.emitEvent({state:"tool-result",name:"command_execution",result:[n,t.exitCode!=null?`
7
7
  (exit ${t.exitCode})`:""].join("").trim()});break}case"mcpToolCall":case"dynamicToolCall":{const r=typeof t.tool=="string"?t.tool:t.type;if(y(r))return;const n=typeof t.arguments=="object"&&t.arguments!==null?t.arguments:{};this.emitEvent({state:"tool-call",name:r,args:n}),this.emitEvent({state:"tool-result",name:r,result:k(t.error??t.result??t.contentItems??"")});break}case"fileChange":break;case"approvalRequest":case"approval_request":case"permissionRequest":case"permission_request":case"userInputRequired":case"user_input_required":{this.emitApprovalPending(t);break}}}handleAppServerUsage(e){const t=typeof e.tokenUsage=="object"&&e.tokenUsage!==null?e.tokenUsage:null,r=typeof t?.last=="object"&&t.last!==null?t.last:null,n=typeof t?.total=="object"&&t.total!==null?t.total:null,i=r??n;if(!i)return;const s=typeof i.inputTokens=="number"?i.inputTokens:void 0,a=typeof i.outputTokens=="number"?i.outputTokens:void 0;(s!=null||a!=null)&&(this.pendingUsage={inputTokens:s??0,outputTokens:a??0})}handleCodexItemLine(e){const t=e.item;if(t?.type&&!te(t))switch(t.type){case"agent_message":case"reasoning":{e.type==="item.completed"&&t.text&&this.emitText(t.text,"block");break}case"command_execution":{if(e.type==="item.started"&&t.command&&this.emitEvent({state:"tool-call",name:"command_execution",args:{command:t.command}}),e.type==="item.completed"){const r=[t.aggregated_output??"",t.exit_code!=null?`
8
8
  (exit ${t.exit_code})`:""];this.emitEvent({state:"tool-result",name:"command_execution",result:r.join("").trim()||String(t.status??"")})}break}case"mcp_tool_call":{if(t.tool&&y(t.tool))return;if(e.type==="item.started"&&this.emitEvent({state:"tool-call",name:t.tool??"mcp_tool",args:{server:t.server,...t.arguments&&typeof t.arguments=="object"?t.arguments:{}}}),e.type==="item.completed"){const r=t.error&&typeof t.error=="object"?t.error.message:void 0;this.emitEvent({state:"tool-result",name:t.tool??"mcp_tool",result:r??k(t.result)})}break}case"file_change":break;case"web_search":{e.type==="item.completed"&&t.query&&this.emitText(`[web_search] ${t.query}`,"block");break}case"todo_list":{if(e.type==="item.completed"&&t.items?.length){const r=t.items.map(n=>`- [${n.completed?"x":" "}] ${n.text}`).join(`
@@ -14,4 +14,4 @@ ${r}`:this.textTail.endsWith(`
14
14
 
15
15
  `)||(r=`
16
16
 
17
- ${r}`)),this.hasEmittedText=!0,this.textTail=(this.textTail+r).slice(-4),this.emitEvent({state:"delta",text:r}))}scheduleProcessClose(){const e=this.process;!e||this.forceCloseTimer||(this.forceCloseTimer=setTimeout(()=>{this.forceCloseTimer=null,this.process===e&&(e.kill("SIGTERM"),setTimeout(()=>{this.process===e&&e.kill("SIGKILL")},1e3))},250))}clearForceCloseTimer(){this.forceCloseTimer&&(clearTimeout(this.forceCloseTimer),this.forceCloseTimer=null)}}D("codex",()=>new Te);export{Te as CodexAdapter,ye as buildCodexQueueArgs,fe as buildCodexQueuedText,P as isCodexActiveWriterError,ce as isCodexExcludeTurnsUnsupportedError,le as isCodexPaginatedHistoryUnsupportedError,ue as isCodexProjectApiUnsupportedError,Fe as isCodexUnsupportedEffortError,De as isMissingCodexRolloutError,Le as normalizeCodexModelId,$e as normalizeCodexReasoningEffort,he as selectCodexProjectIdForWorkDir};
17
+ ${r}`)),this.hasEmittedText=!0,this.textTail=(this.textTail+r).slice(-4),this.emitEvent({state:"delta",text:r}))}scheduleProcessClose(){const e=this.process;!e||this.forceCloseTimer||(this.forceCloseTimer=setTimeout(()=>{this.forceCloseTimer=null,this.process===e&&(e.kill("SIGTERM"),setTimeout(()=>{this.process===e&&e.kill("SIGKILL")},1e3))},250))}clearForceCloseTimer(){this.forceCloseTimer&&(clearTimeout(this.forceCloseTimer),this.forceCloseTimer=null)}}D("codex",()=>new ve);export{ve as CodexAdapter,ye as buildCodexQueueArgs,fe as buildCodexQueuedText,P as isCodexActiveWriterError,ce as isCodexExcludeTurnsUnsupportedError,le as isCodexPaginatedHistoryUnsupportedError,ue as isCodexProjectApiUnsupportedError,Fe as isCodexUnsupportedEffortError,De as isMissingCodexRolloutError,Le as normalizeCodexModelId,$e as normalizeCodexReasoningEffort,he as selectCodexProjectIdForWorkDir};
@@ -17,6 +17,8 @@ type LaunchSpec = {
17
17
  };
18
18
  export declare function resetCommandSpecCache(): void;
19
19
  export declare function getProcessPlatform(): NodeJS.Platform;
20
+ /** macOS Codex desktop ships a directly runnable CLI; Windows Store does not. */
21
+ export declare function getCodexDesktopCommandCandidates(platform?: NodeJS.Platform, home?: string): string[];
20
22
  export declare function windowsPathToWsl(input: string): string | undefined;
21
23
  export declare function commandExists(command: string): boolean;
22
24
  /** Stable, non-secret identity used to invalidate local capability caches. */
@@ -1,3 +1,3 @@
1
- import{spawn as k,spawnSync as C}from"node:child_process";import p from"node:fs";import j from"node:crypto";import E from"node:os";import s from"node:path";const N={claude:[{command:"claude",args:[],display:"claude"}],codex:[{command:"codex",args:[],display:"codex"}],workbuddy:[{command:"codebuddy",args:[],display:"WorkBuddy"}],gemini:[{command:"gemini",args:[],display:"gemini"}],cursor:[{command:"agent",args:[],display:"agent"},{command:"cursor",args:["agent"],display:"cursor agent"}],openclaw:[],opencode:[{command:"opencode",args:[],display:"opencode"}],pi:[{command:"shennian",args:[],display:"shennian"}],"pi-coding-agent":[{command:"pi",args:[],display:"pi"}],manager:[{command:"shennian",args:["manager"],display:"shennian manager"}]},m=new Map,f=new Map,h=new Map,u=new Map;function X(){m.clear(),f.clear(),h.clear(),u.clear()}function c(){return process.platform}function R(n){return n.split(/\r?\n/).map(e=>e.trim()).filter(Boolean)}function b(n){if(s.basename(n)!==n)return[n];const e=E.homedir();if(c()==="win32"){const o=s.win32,r=s.extname(n)?[n]:[n,`${n}.cmd`,`${n}.exe`,`${n}.bat`],a=process.env.APPDATA||o.join(e,"AppData","Roaming"),l=process.env.LOCALAPPDATA||o.join(e,"AppData","Local"),y=[o.join(e,".shennian","node"),o.join("C:\\","nvm4w","nodejs"),o.join(l,"npm-global"),o.join(a,"npm"),o.join(l,"pnpm"),o.join(e,"scoop","shims"),o.join("C:\\","Program Files","nodejs")].flatMap(w=>r.map(g=>o.join(w,g)));if(n==="codebuddy"){const w=[o.join(l,"Programs","WorkBuddy"),o.join(l,"WorkBuddy"),o.join("C:\\","Program Files","WorkBuddy")];for(const g of w)for(const F of["codebuddy.exe","codebuddy.cmd","codebuddy"])y.push(o.join(g,"resources","app.asar.unpacked","cli","bin",F))}return y}const i=[s.join(e,".npm-global","bin"),s.join(e,".local","bin"),s.join(e,".bun","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin"].map(o=>s.join(o,n));return n==="claude"&&c()==="darwin"&&i.push(...V(e)),n==="codebuddy"&&c()==="darwin"&&i.push("/Applications/WorkBuddy.app/Contents/Resources/app.asar.unpacked/cli/bin/codebuddy",s.join(e,"Applications","WorkBuddy.app","Contents","Resources","app.asar.unpacked","cli","bin","codebuddy")),i}function V(n){const e=[s.join(n,"Library","Application Support","Claude","claude-code")],t=[];for(const i of e){let o;try{o=p.readdirSync(i,{withFileTypes:!0}).filter(r=>r.isDirectory()).map(r=>r.name).sort((r,a)=>a.localeCompare(r,void 0,{numeric:!0}))}catch{continue}for(const r of o)t.push(s.join(i,r,"claude.app","Contents","MacOS","claude"))}return t}function P(n,e){const t=n?.split(s.delimiter).filter(Boolean)??[];if(c()==="win32"){if(e&&s.basename(e)!==e){const i=s.win32.dirname(e);t.includes(i)||t.unshift(i)}for(const i of b("shennian")){const o=s.win32.dirname(i);t.includes(o)||t.push(o)}return t.join(s.delimiter)}if(e&&s.basename(e)!==e){const i=s.dirname(e);t.includes(i)||t.unshift(i)}for(const i of b("shennian")){const o=s.dirname(i);t.includes(o)||t.push(o)}return t.join(s.delimiter)}function d(n){if(h.has(n))return h.get(n)??[];const e=c()==="win32",i=C(e?"where":"which",[n],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:3e3,windowsHide:!0,env:{...process.env,PATH:e?process.env.PATH:P(process.env.PATH,n)}}),r=[...i.status===0?R(i.stdout??""):[]];for(const a of b(n))p.existsSync(a)&&!r.includes(a)&&r.push(a);return h.set(n,r),r}function A(){return process.env.ComSpec||"cmd.exe"}function $(n){const e=s.extname(n).toLowerCase();return e===".exe"||e===".com"}function x(n){const e=s.extname(n).toLowerCase();return e===".cmd"||e===".bat"}function S(n){const e=s.extname(n).toLowerCase();return e===".js"||e===".mjs"||e===".cjs"}function W(){return d("node.exe")[0]??d("node")[0]??"node"}function B(n){return`"${n.replace(/"/g,'""')}"`}function v(n){return`'${n.replace(/'/g,"'\\''")}'`}function z(n){if(!n)return;const e=n.replace(/\//g,"\\"),t=e.match(/^([A-Za-z]):\\(.*)$/);if(t){const[,i,o]=t,r=o.replace(/\\/g,"/");return`/mnt/${i.toLowerCase()}/${r}`}if(e.startsWith("\\\\wsl$\\"))return`/${e.replace(/^\\\\wsl\$\\[^\\]+\\?/,"").replace(/\\/g,"/")}`;if(n.startsWith("/"))return n}function H(n){const e=n.trim();if(!e)throw new Error("Command string is empty");if(/[\\/]/.test(e)||/^[A-Za-z]:/.test(e))return x(e)?{kind:"cmd-shim",path:e}:{kind:"direct",path:e};const i=d(e),o=i.find($);if(o)return{kind:"direct",path:o};const r=i.find(x);return r?{kind:"cmd-shim",path:r}:{kind:"direct",path:e}}function L(n){if(u.has(n))return u.get(n)??!1;const e=d("wsl.exe")[0]??d("wsl")[0];if(!e)return u.set(n,!1),!1;const i=C(e,["-e","sh","-lc",`command -v ${v(n)} >/dev/null 2>&1`],{stdio:"ignore",timeout:5e3,windowsHide:!0}).status===0;return u.set(n,i),i}function Y(n){if(m.has(n))return m.get(n)??!1;const e=d(n).length>0||c()==="win32"&&L(n);return m.set(n,e),e}function nn(n){const e=d(n)[0];if(!e)return null;try{const t=p.realpathSync(e),i=p.statSync(t,{bigint:!0}),o=j.createHash("sha256").update(t).digest("hex"),r=j.createHash("sha256").update(`${i.dev}:${i.ino}:${i.size}:${i.mtimeNs}`).digest("hex");return{pathHash:o,fingerprint:r}}catch{return null}}function en(n){return d(n)[0]??null}function I(n){const e=d(n.command),t=e.find($);if(t)return{...n,kind:"native",path:t};const i=e.find(x);if(i)return{...n,kind:"cmd-shim",path:i};if(L(n.command)){const o=d("wsl.exe")[0]??d("wsl")[0];if(o)return{...n,kind:"wsl-bridge",path:o}}return null}function tn(n){if(f.has(n))return f.get(n)??null;const e=N[n].map(t=>{if(c()==="win32")return I(t);const i=d(t.command)[0];return i?{...t,kind:"native",path:i}:null}).find(Boolean)??null;return f.set(n,e),e}function D(n,e,t){if(n.kind==="native")return c()==="win32"&&S(n.path)?{command:W(),args:[n.path,...n.args,...e],cwd:t}:{command:n.path,args:[...n.args,...e],cwd:t};if(n.kind==="cmd-shim"){const r=[n.path,...n.args,...e].map(B).join(" ");return{command:A(),args:["/d","/s","/c",`"${r}"`],cwd:t}}const i=t?z(t):void 0;if(t&&!i)throw new Error(`Cannot map Windows path to WSL workDir: ${t}`);const o=[i?`cd ${v(i)}`:"",`exec ${[n.command,...n.args,...e].map(v).join(" ")}`].filter(Boolean).join(" && ");return{command:n.path,args:["-e","sh","-lc",o],cwd:void 0}}function O(n,e,t={}){const i=D(n,e,t.cwd);return k(i.command,i.args,{...t,cwd:i.cwd,windowsHide:t.windowsHide??!0,...c()==="win32"&&n.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function on(n,e,t={}){return O(n,e,t)}function T(n,e,t={}){const i=D(n,e,t.cwd);return C(i.command,i.args,{...t,cwd:i.cwd,windowsHide:t.windowsHide??!0,...c()==="win32"&&n.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function M(n){const e=[];let t="",i=!1,o=!1;for(const r of n){if(r==="'"&&!o){i=!i;continue}if(r==='"'&&!i){o=!o;continue}if(r===" "&&!i&&!o){t&&(e.push(t),t="");continue}t+=r}return t&&e.push(t),e}function q(n,e,t){const i=M(n),o=i[0];if(!o)throw new Error("Command string is empty");const r=i.slice(1);if(c()!=="win32")return{command:o,args:[...r,...e],cwd:t};const a=H(o);return a.kind==="cmd-shim"?{command:A(),args:["/d","/s","/c",`"${[a.path,...r,...e].map(B).join(" ")}"`],cwd:t}:S(a.path)?{command:W(),args:[a.path,...r,...e],cwd:t}:{command:a.path,args:[...r,...e],cwd:t}}function rn(n,e,t={}){const i=q(n,e,t.cwd),o=M(n),r=c()==="win32"&&o[0]?H(o[0]):null;return k(i.command,i.args,{...t,cwd:i.cwd,windowsHide:t.windowsHide??!0,env:{...t.env,PATH:P(t.env?.PATH??process.env.PATH,o[0])},...c()==="win32"&&r?.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function U(n,e="--version"){const t=T(n,[e],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:5e3});return t.status!==0?void 0:`${t.stdout??""}
2
- ${t.stderr??""}`.trim().match(/\d+\.\d+[\w.-]*/)?.[0]}function sn(n,e){if(n!=="cursor")return U(e);const t=T(e,["about"],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:5e3});return t.status!==0?void 0:`${t.stdout??""}
3
- ${t.stderr??""}`.match(/^\s*CLI Version\s+(\d+\.\d+(?:\.\d+)?[\w.-]*)\s*$/im)?.[1]}export{q as buildCommandStringLaunchSpec,D as buildLaunchSpec,Y as commandExists,sn as getBuiltinAgentVersion,U as getCommandVersion,c as getProcessPlatform,M as parseCommandString,X as resetCommandSpecCache,tn as resolveBuiltinCommand,nn as resolveCommandFileIdentity,en as resolveCommandFilePath,on as spawnAgentCommand,rn as spawnCommandString,O as spawnResolvedCommand,T as spawnResolvedCommandSync,z as windowsPathToWsl};
1
+ import{spawn as k,spawnSync as x}from"node:child_process";import u from"node:fs";import j from"node:crypto";import P from"node:os";import s from"node:path";const A={claude:[{command:"claude",args:[],display:"claude"}],codex:[{command:"codex",args:[],display:"codex"}],workbuddy:[{command:"codebuddy",args:[],display:"WorkBuddy"}],gemini:[{command:"gemini",args:[],display:"gemini"}],cursor:[{command:"agent",args:[],display:"agent"},{command:"cursor",args:["agent"],display:"cursor agent"}],openclaw:[],opencode:[{command:"opencode",args:[],display:"opencode"}],pi:[{command:"shennian",args:[],display:"shennian"}],"pi-coding-agent":[{command:"pi",args:[],display:"pi"}],manager:[{command:"shennian",args:["manager"],display:"shennian manager"}]},m=new Map,f=new Map,h=new Map,l=new Map;function Y(){m.clear(),f.clear(),h.clear(),l.clear()}function a(){return process.platform}function V(n){return n.split(/\r?\n/).map(e=>e.trim()).filter(Boolean)}function C(n){if(s.basename(n)!==n)return[n];const e=P.homedir();if(a()==="win32"){const o=s.win32,r=s.extname(n)?[n]:[n,`${n}.cmd`,`${n}.exe`,`${n}.bat`],d=process.env.APPDATA||o.join(e,"AppData","Roaming"),p=process.env.LOCALAPPDATA||o.join(e,"AppData","Local"),y=[o.join(e,".shennian","node"),o.join("C:\\","nvm4w","nodejs"),o.join(p,"npm-global"),o.join(d,"npm"),o.join(p,"pnpm"),o.join(e,"scoop","shims"),o.join("C:\\","Program Files","nodejs")].flatMap(w=>r.map(g=>o.join(w,g)));if(n==="codebuddy"){const w=[o.join(p,"Programs","WorkBuddy"),o.join(p,"WorkBuddy"),o.join("C:\\","Program Files","WorkBuddy")];for(const g of w)for(const N of["codebuddy.exe","codebuddy.cmd","codebuddy"])y.push(o.join(g,"resources","app.asar.unpacked","cli","bin",N))}return y}const i=[s.join(e,".npm-global","bin"),s.join(e,".local","bin"),s.join(e,".bun","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin"].map(o=>s.join(o,n));return n==="claude"&&a()==="darwin"&&i.push(...I(e)),n==="codebuddy"&&a()==="darwin"&&i.push("/Applications/WorkBuddy.app/Contents/Resources/app.asar.unpacked/cli/bin/codebuddy",s.join(e,"Applications","WorkBuddy.app","Contents","Resources","app.asar.unpacked","cli","bin","codebuddy")),i}function z(n=a(),e=P.homedir()){return n!=="darwin"?[]:["/Applications",s.join(e,"Applications")].flatMap(t=>["ChatGPT.app","Codex.app"].map(i=>s.join(t,i,"Contents","Resources","codex")))}function I(n){const e=[s.join(n,"Library","Application Support","Claude","claude-code")],t=[];for(const i of e){let o;try{o=u.readdirSync(i,{withFileTypes:!0}).filter(r=>r.isDirectory()).map(r=>r.name).sort((r,d)=>d.localeCompare(r,void 0,{numeric:!0}))}catch{continue}for(const r of o)t.push(s.join(i,r,"claude.app","Contents","MacOS","claude"))}return t}function $(n,e){const t=n?.split(s.delimiter).filter(Boolean)??[];if(a()==="win32"){if(e&&s.basename(e)!==e){const i=s.win32.dirname(e);t.includes(i)||t.unshift(i)}for(const i of C("shennian")){const o=s.win32.dirname(i);t.includes(o)||t.push(o)}return t.join(s.delimiter)}if(e&&s.basename(e)!==e){const i=s.dirname(e);t.includes(i)||t.unshift(i)}for(const i of C("shennian")){const o=s.dirname(i);t.includes(o)||t.push(o)}return t.join(s.delimiter)}function c(n){if(h.has(n))return h.get(n)??[];const e=a()==="win32",i=x(e?"where":"which",[n],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:3e3,windowsHide:!0,env:{...process.env,PATH:e?process.env.PATH:$(process.env.PATH,n)}}),r=[...i.status===0?V(i.stdout??""):[]];for(const d of C(n))u.existsSync(d)&&!r.includes(d)&&r.push(d);return h.set(n,r),r}function S(){return process.env.ComSpec||"cmd.exe"}function W(n){const e=s.extname(n).toLowerCase();return e===".exe"||e===".com"}function b(n){const e=s.extname(n).toLowerCase();return e===".cmd"||e===".bat"}function B(n){const e=s.extname(n).toLowerCase();return e===".js"||e===".mjs"||e===".cjs"}function H(){return c("node.exe")[0]??c("node")[0]??"node"}function L(n){return`"${n.replace(/"/g,'""')}"`}function v(n){return`'${n.replace(/'/g,"'\\''")}'`}function O(n){if(!n)return;const e=n.replace(/\//g,"\\"),t=e.match(/^([A-Za-z]):\\(.*)$/);if(t){const[,i,o]=t,r=o.replace(/\\/g,"/");return`/mnt/${i.toLowerCase()}/${r}`}if(e.startsWith("\\\\wsl$\\"))return`/${e.replace(/^\\\\wsl\$\\[^\\]+\\?/,"").replace(/\\/g,"/")}`;if(n.startsWith("/"))return n}function D(n){const e=n.trim();if(!e)throw new Error("Command string is empty");if(/[\\/]/.test(e)||/^[A-Za-z]:/.test(e))return b(e)?{kind:"cmd-shim",path:e}:{kind:"direct",path:e};const i=c(e),o=i.find(W);if(o)return{kind:"direct",path:o};const r=i.find(b);return r?{kind:"cmd-shim",path:r}:{kind:"direct",path:e}}function T(n){if(l.has(n))return l.get(n)??!1;const e=c("wsl.exe")[0]??c("wsl")[0];if(!e)return l.set(n,!1),!1;const i=x(e,["-e","sh","-lc",`command -v ${v(n)} >/dev/null 2>&1`],{stdio:"ignore",timeout:5e3,windowsHide:!0}).status===0;return l.set(n,i),i}function nn(n){if(m.has(n))return m.get(n)??!1;const e=c(n).length>0||a()==="win32"&&T(n);return m.set(n,e),e}function en(n){const e=c(n)[0];if(!e)return null;try{const t=u.realpathSync(e),i=u.statSync(t,{bigint:!0}),o=j.createHash("sha256").update(t).digest("hex"),r=j.createHash("sha256").update(`${i.dev}:${i.ino}:${i.size}:${i.mtimeNs}`).digest("hex");return{pathHash:o,fingerprint:r}}catch{return null}}function tn(n){return c(n)[0]??null}function q(n){const e=c(n.command),t=e.find(W);if(t)return{...n,kind:"native",path:t};const i=e.find(b);if(i)return{...n,kind:"cmd-shim",path:i};if(T(n.command)){const o=c("wsl.exe")[0]??c("wsl")[0];if(o)return{...n,kind:"wsl-bridge",path:o}}return null}function on(n){if(f.has(n))return f.get(n)??null;const e=n==="codex"?z().find(i=>u.existsSync(i)?!!R({command:i,args:[],display:"Codex Desktop",kind:"native",path:i}):!1):void 0,t=e?{...A.codex[0],kind:"native",path:e}:A[n].map(i=>{if(a()==="win32")return q(i);const o=c(i.command)[0];return o?{...i,kind:"native",path:o}:null}).find(Boolean)??null;return f.set(n,t),t}function M(n,e,t){if(n.kind==="native")return a()==="win32"&&B(n.path)?{command:H(),args:[n.path,...n.args,...e],cwd:t}:{command:n.path,args:[...n.args,...e],cwd:t};if(n.kind==="cmd-shim"){const r=[n.path,...n.args,...e].map(L).join(" ");return{command:S(),args:["/d","/s","/c",`"${r}"`],cwd:t}}const i=t?O(t):void 0;if(t&&!i)throw new Error(`Cannot map Windows path to WSL workDir: ${t}`);const o=[i?`cd ${v(i)}`:"",`exec ${[n.command,...n.args,...e].map(v).join(" ")}`].filter(Boolean).join(" && ");return{command:n.path,args:["-e","sh","-lc",o],cwd:void 0}}function U(n,e,t={}){const i=M(n,e,t.cwd);return k(i.command,i.args,{...t,cwd:i.cwd,windowsHide:t.windowsHide??!0,...a()==="win32"&&n.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function rn(n,e,t={}){return U(n,e,t)}function F(n,e,t={}){const i=M(n,e,t.cwd);return x(i.command,i.args,{...t,cwd:i.cwd,windowsHide:t.windowsHide??!0,...a()==="win32"&&n.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function E(n){const e=[];let t="",i=!1,o=!1;for(const r of n){if(r==="'"&&!o){i=!i;continue}if(r==='"'&&!i){o=!o;continue}if(r===" "&&!i&&!o){t&&(e.push(t),t="");continue}t+=r}return t&&e.push(t),e}function Z(n,e,t){const i=E(n),o=i[0];if(!o)throw new Error("Command string is empty");const r=i.slice(1);if(a()!=="win32")return{command:o,args:[...r,...e],cwd:t};const d=D(o);return d.kind==="cmd-shim"?{command:S(),args:["/d","/s","/c",`"${[d.path,...r,...e].map(L).join(" ")}"`],cwd:t}:B(d.path)?{command:H(),args:[d.path,...r,...e],cwd:t}:{command:d.path,args:[...r,...e],cwd:t}}function sn(n,e,t={}){const i=Z(n,e,t.cwd),o=E(n),r=a()==="win32"&&o[0]?D(o[0]):null;return k(i.command,i.args,{...t,cwd:i.cwd,windowsHide:t.windowsHide??!0,env:{...t.env,PATH:$(t.env?.PATH??process.env.PATH,o[0])},...a()==="win32"&&r?.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function R(n,e="--version"){const t=F(n,[e],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:5e3});return t.status!==0?void 0:`${t.stdout??""}
2
+ ${t.stderr??""}`.trim().match(/\d+\.\d+[\w.-]*/)?.[0]}function an(n,e){if(n!=="cursor")return R(e);const t=F(e,["about"],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:5e3});return t.status!==0?void 0:`${t.stdout??""}
3
+ ${t.stderr??""}`.match(/^\s*CLI Version\s+(\d+\.\d+(?:\.\d+)?[\w.-]*)\s*$/im)?.[1]}export{Z as buildCommandStringLaunchSpec,M as buildLaunchSpec,nn as commandExists,an as getBuiltinAgentVersion,z as getCodexDesktopCommandCandidates,R as getCommandVersion,a as getProcessPlatform,E as parseCommandString,Y as resetCommandSpecCache,on as resolveBuiltinCommand,en as resolveCommandFileIdentity,tn as resolveCommandFilePath,rn as spawnAgentCommand,sn as spawnCommandString,U as spawnResolvedCommand,F as spawnResolvedCommandSync,O as windowsPathToWsl};
@@ -1 +1 @@
1
- import r from"node:fs";import c from"node:os";import s from"node:path";import{getCommandVersion as d}from"./command-spec.js";function m(e){const i=s.join("ChatGPT.app","Contents","Resources","codex");return[s.join("/Applications",i),s.join(e,"Applications",i)]}function a(e){if((e.platform??process.platform)!=="darwin")return;const i=e.exists??r.existsSync,t=e.getVersion??d,n=m(e.homeDir??c.homedir()).find(i);if(n)return t({command:n,args:[],display:"Codex Desktop",kind:"native",path:n})}function l(e,i={}){const t=e.version,n=e.type==="codex"?a(i):void 0;if(!t&&!n)return;const o=t&&n?t===n?"compatible":"version_mismatch":void 0;return{...t?{cliVersion:t}:{},...n?{desktopVersion:n}:{},...o?{compatibility:o}:{},...o==="version_mismatch"?{upgradeAction:"manual"}:{}}}export{l as getAgentRuntimeSummary};
1
+ import r from"node:fs";import m from"node:os";import{getCodexDesktopCommandCandidates as d,getCommandVersion as c}from"./command-spec.js";function a(e){const i=e.platform??process.platform;if(i!=="darwin")return;const n=e.exists??r.existsSync,t=e.getVersion??c;for(const o of d(i,e.homeDir??m.homedir())){if(!n(o))continue;const s=t({command:o,args:[],display:"Codex Desktop",kind:"native",path:o});if(s)return s}}function l(e,i={}){const n=e.version,t=e.type==="codex"?a(i):void 0;if(!n&&!t)return;const o=n&&t?n===t?"compatible":"version_mismatch":void 0;return{...n?{cliVersion:n}:{},...t?{desktopVersion:t}:{},...o?{compatibility:o}:{},...o==="version_mismatch"?{upgradeAction:"manual"}:{}}}export{l as getAgentRuntimeSummary};