shennian 0.4.1 → 0.4.3

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 (47) hide show
  1. package/dist/publish-build-manifest.json +70 -35
  2. package/dist/src/agent-env.d.ts +1 -0
  3. package/dist/src/agent-env.js +4 -4
  4. package/dist/src/agents/codex.d.ts +3 -2
  5. package/dist/src/agents/codex.js +8 -8
  6. package/dist/src/agents/command-spec.js +1 -1
  7. package/dist/src/agents/config-status.js +1 -1
  8. package/dist/src/agents/detect.d.ts +1 -0
  9. package/dist/src/agents/detect.js +1 -1
  10. package/dist/src/agents/manager.d.ts +3 -3
  11. package/dist/src/agents/manager.js +9 -9
  12. package/dist/src/agents/model-registry/cache.d.ts +1 -1
  13. package/dist/src/agents/model-registry/cache.js +1 -1
  14. package/dist/src/agents/model-registry/discovery.js +3 -2
  15. package/dist/src/agents/model-registry/parsers.js +4 -4
  16. package/dist/src/agents/model-registry/service.js +1 -1
  17. package/dist/src/agents/model-registry/types.d.ts +1 -0
  18. package/dist/src/agents/pi-coding-agent-managed-permissions.d.ts +7 -0
  19. package/dist/src/agents/pi-coding-agent-managed-permissions.js +1 -0
  20. package/dist/src/agents/pi-coding-agent.d.ts +55 -0
  21. package/dist/src/agents/pi-coding-agent.js +4 -0
  22. package/dist/src/agents/pi-managed-extension.d.ts +12 -0
  23. package/dist/src/agents/pi-managed-extension.js +89 -0
  24. package/dist/src/agents/pi-managed-model-broker.d.ts +27 -0
  25. package/dist/src/agents/pi-managed-model-broker.js +1 -0
  26. package/dist/src/agents/pi-rpc-client.d.ts +31 -0
  27. package/dist/src/agents/pi-rpc-client.js +3 -0
  28. package/dist/src/agents/pi-session-ownership.d.ts +2 -0
  29. package/dist/src/agents/pi-session-ownership.js +2 -0
  30. package/dist/src/manager/prompt.d.ts +1 -1
  31. package/dist/src/manager/prompt.js +2 -2
  32. package/dist/src/manager/registry.d.ts +4 -4
  33. package/dist/src/manager/runtime.d.ts +3 -3
  34. package/dist/src/room/activation-service.js +4 -4
  35. package/dist/src/security/managed-agent-policy.js +1 -1
  36. package/dist/src/session/handlers/agent-workspace-validation.d.ts +24 -0
  37. package/dist/src/session/handlers/agent-workspace-validation.js +1 -0
  38. package/dist/src/session/handlers/chat.js +1 -1
  39. package/dist/src/session/manager.d.ts +1 -0
  40. package/dist/src/session/manager.js +1 -1
  41. package/dist/src/session/native-session-lifecycle.js +6 -6
  42. package/dist/src/session/queue.d.ts +5 -1
  43. package/dist/src/session/queue.js +2 -2
  44. package/node_modules/@shennian/wire/dist/methods.d.ts +1 -1
  45. package/node_modules/@shennian/wire/dist/session.d.ts +2 -2
  46. package/node_modules/@shennian/wire/dist/session.js +1 -0
  47. package/package.json +1 -1
@@ -2,7 +2,7 @@
2
2
  "schemaVersion": 1,
3
3
  "jsMinified": true,
4
4
  "minifier": "esbuild",
5
- "fileCount": 145,
5
+ "fileCount": 152,
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": 9273,
15
- "afterBytes": 4197
14
+ "beforeBytes": 9854,
15
+ "afterBytes": 4529
16
16
  },
17
17
  {
18
18
  "file": "src/agents/adapter.js",
@@ -46,18 +46,18 @@
46
46
  },
47
47
  {
48
48
  "file": "src/agents/codex.js",
49
- "beforeBytes": 64672,
50
- "afterBytes": 33374
49
+ "beforeBytes": 64856,
50
+ "afterBytes": 33479
51
51
  },
52
52
  {
53
53
  "file": "src/agents/command-spec.js",
54
- "beforeBytes": 17437,
55
- "afterBytes": 7807
54
+ "beforeBytes": 17521,
55
+ "afterBytes": 7863
56
56
  },
57
57
  {
58
58
  "file": "src/agents/config-status.js",
59
- "beforeBytes": 7583,
60
- "afterBytes": 3900
59
+ "beforeBytes": 7976,
60
+ "afterBytes": 4126
61
61
  },
62
62
  {
63
63
  "file": "src/agents/cursor-managed-permissions.js",
@@ -81,8 +81,8 @@
81
81
  },
82
82
  {
83
83
  "file": "src/agents/detect.js",
84
- "beforeBytes": 2358,
85
- "afterBytes": 1204
84
+ "beforeBytes": 3366,
85
+ "afterBytes": 1504
86
86
  },
87
87
  {
88
88
  "file": "src/agents/external-channel-instructions.js",
@@ -96,23 +96,23 @@
96
96
  },
97
97
  {
98
98
  "file": "src/agents/manager.js",
99
- "beforeBytes": 10725,
100
- "afterBytes": 5801
99
+ "beforeBytes": 10675,
100
+ "afterBytes": 5749
101
101
  },
102
102
  {
103
103
  "file": "src/agents/model-registry/cache.js",
104
- "beforeBytes": 1216,
105
- "afterBytes": 548
104
+ "beforeBytes": 1321,
105
+ "afterBytes": 575
106
106
  },
107
107
  {
108
108
  "file": "src/agents/model-registry/discovery.js",
109
- "beforeBytes": 7085,
110
- "afterBytes": 3340
109
+ "beforeBytes": 10881,
110
+ "afterBytes": 5056
111
111
  },
112
112
  {
113
113
  "file": "src/agents/model-registry/parsers.js",
114
- "beforeBytes": 19646,
115
- "afterBytes": 10067
114
+ "beforeBytes": 19925,
115
+ "afterBytes": 10288
116
116
  },
117
117
  {
118
118
  "file": "src/agents/model-registry/runner.js",
@@ -121,8 +121,8 @@
121
121
  },
122
122
  {
123
123
  "file": "src/agents/model-registry/service.js",
124
- "beforeBytes": 4344,
125
- "afterBytes": 1743
124
+ "beforeBytes": 4571,
125
+ "afterBytes": 1869
126
126
  },
127
127
  {
128
128
  "file": "src/agents/model-registry/types.js",
@@ -154,6 +154,36 @@
154
154
  "beforeBytes": 11310,
155
155
  "afterBytes": 6249
156
156
  },
157
+ {
158
+ "file": "src/agents/pi-coding-agent-managed-permissions.js",
159
+ "beforeBytes": 1534,
160
+ "afterBytes": 592
161
+ },
162
+ {
163
+ "file": "src/agents/pi-coding-agent.js",
164
+ "beforeBytes": 24240,
165
+ "afterBytes": 13052
166
+ },
167
+ {
168
+ "file": "src/agents/pi-managed-extension.js",
169
+ "beforeBytes": 8913,
170
+ "afterBytes": 8208
171
+ },
172
+ {
173
+ "file": "src/agents/pi-managed-model-broker.js",
174
+ "beforeBytes": 8338,
175
+ "afterBytes": 4484
176
+ },
177
+ {
178
+ "file": "src/agents/pi-rpc-client.js",
179
+ "beforeBytes": 5326,
180
+ "afterBytes": 2807
181
+ },
182
+ {
183
+ "file": "src/agents/pi-session-ownership.js",
184
+ "beforeBytes": 2329,
185
+ "afterBytes": 1278
186
+ },
157
187
  {
158
188
  "file": "src/agents/platform-instructions.js",
159
189
  "beforeBytes": 2829,
@@ -331,8 +361,8 @@
331
361
  },
332
362
  {
333
363
  "file": "src/manager/prompt.js",
334
- "beforeBytes": 4350,
335
- "afterBytes": 7113
364
+ "beforeBytes": 4370,
365
+ "afterBytes": 7133
336
366
  },
337
367
  {
338
368
  "file": "src/manager/registry.js",
@@ -466,8 +496,8 @@
466
496
  },
467
497
  {
468
498
  "file": "src/room/activation-service.js",
469
- "beforeBytes": 21713,
470
- "afterBytes": 10792
499
+ "beforeBytes": 22403,
500
+ "afterBytes": 11182
471
501
  },
472
502
  {
473
503
  "file": "src/room/attachment-cache.js",
@@ -561,8 +591,8 @@
561
591
  },
562
592
  {
563
593
  "file": "src/security/managed-agent-policy.js",
564
- "beforeBytes": 6728,
565
- "afterBytes": 3141
594
+ "beforeBytes": 6759,
595
+ "afterBytes": 3166
566
596
  },
567
597
  {
568
598
  "file": "src/security/managed-agent-runtime.js",
@@ -604,6 +634,11 @@
604
634
  "beforeBytes": 5590,
605
635
  "afterBytes": 2803
606
636
  },
637
+ {
638
+ "file": "src/session/handlers/agent-workspace-validation.js",
639
+ "beforeBytes": 7952,
640
+ "afterBytes": 4110
641
+ },
607
642
  {
608
643
  "file": "src/session/handlers/agents.js",
609
644
  "beforeBytes": 1853,
@@ -611,8 +646,8 @@
611
646
  },
612
647
  {
613
648
  "file": "src/session/handlers/chat.js",
614
- "beforeBytes": 43645,
615
- "afterBytes": 18275
649
+ "beforeBytes": 43663,
650
+ "afterBytes": 18270
616
651
  },
617
652
  {
618
653
  "file": "src/session/handlers/control.js",
@@ -671,8 +706,8 @@
671
706
  },
672
707
  {
673
708
  "file": "src/session/manager.js",
674
- "beforeBytes": 31103,
675
- "afterBytes": 16179
709
+ "beforeBytes": 31381,
710
+ "afterBytes": 16358
676
711
  },
677
712
  {
678
713
  "file": "src/session/native-cleanup-outbox.js",
@@ -681,8 +716,8 @@
681
716
  },
682
717
  {
683
718
  "file": "src/session/native-session-lifecycle.js",
684
- "beforeBytes": 14160,
685
- "afterBytes": 6446
719
+ "beforeBytes": 14829,
720
+ "afterBytes": 6738
686
721
  },
687
722
  {
688
723
  "file": "src/session/projection.js",
@@ -691,8 +726,8 @@
691
726
  },
692
727
  {
693
728
  "file": "src/session/queue.js",
694
- "beforeBytes": 33159,
695
- "afterBytes": 14816
729
+ "beforeBytes": 33537,
730
+ "afterBytes": 14902
696
731
  },
697
732
  {
698
733
  "file": "src/session/store.js",
@@ -6,6 +6,7 @@ import type { AgentType } from '@shennian/wire';
6
6
  */
7
7
  export declare const MANAGED_AGENT_SESSION_ENV_KEYS: readonly ["SHENNIAN_MANAGED_ROOM_CONTEXT", "SHENNIAN_MANAGED_ROOM_IPC_ROOT"];
8
8
  export declare function getManagedAgentProviderEnvKeys(agentType: AgentType): readonly string[];
9
+ export declare function getManagedAgentSessionEnvKeys(agentType: AgentType): readonly string[];
9
10
  export declare function getManagedAgentBaseEnvKeys(platform?: NodeJS.Platform): readonly string[];
10
11
  export type ManagedAgentProcessEnvInput = {
11
12
  agentType: AgentType;
@@ -1,8 +1,8 @@
1
- import S from"node:os";import a from"node:path";import{spawnSync as _}from"node:child_process";import{buildAugmentedPath as g}from"./env-path.js";import{buildWindowsSystemEnv as u,resolveWindowsPowerShellPath as h}from"./windows-shell.js";const l="__SHENNIAN_AGENT_ENV_START__",A="__SHENNIAN_AGENT_ENV_END__",m=["HOME","USER","LOGNAME","LANG","LANGUAGE","LC_ALL","LC_CTYPE","TMPDIR","TMP","TEMP","TZ"],N=["SystemRoot","WINDIR","ComSpec","PATHEXT","USERPROFILE","APPDATA","LOCALAPPDATA","ProgramData","ProgramFiles","ProgramFiles(x86)","TEMP","TMP","TZ"],P=["NO_COLOR"],O=["SHENNIAN_MANAGED_ROOM_CONTEXT","SHENNIAN_MANAGED_ROOM_IPC_ROOT"],T={codex:["OPENAI_BASE_URL","OPENAI_API_KEY"],claude:["ANTHROPIC_BASE_URL","ANTHROPIC_API_KEY"],pi:["DASHSCOPE_BASE_URL","DASHSCOPE_API_KEY"]};function w(e){return T[e]??[]}function V(e=process.platform){return["PATH",...e==="win32"?N:m,...P]}function p(e){return`'${e.replace(/'/g,"'\\''")}'`}function v(e){const n=e.indexOf(l),r=e.indexOf(A,n+l.length);if(n===-1||r===-1)return null;const t=e.slice(n+l.length,r);try{const o=JSON.parse(t),i={};for(const[c,s]of Object.entries(o))typeof s=="string"&&(i[c]=s);return i}catch{return null}}function R(){const e=process.env.SHELL?.trim()||"/bin/sh",n=[`printf ${p(l)}`,`${p(process.execPath)} -e ${p("process.stdout.write(JSON.stringify(process.env))")}`,`printf ${p(A)}`].join("; ");for(const r of[["-ilc",n],["-lc",n]]){const t=_(e,r,{env:process.env,encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:1500,windowsHide:!0}),o=typeof t.stdout=="string"?v(t.stdout):null;if(o)return o}return null}function y(){const e=`
1
+ import I from"node:os";import E from"node:path";import{spawnSync as p}from"node:child_process";import{buildAugmentedPath as O}from"./env-path.js";import{buildWindowsSystemEnv as A,resolveWindowsPowerShellPath as g}from"./windows-shell.js";const N="__SHENNIAN_AGENT_ENV_START__",f="__SHENNIAN_AGENT_ENV_END__",d=["HOME","USER","LOGNAME","LANG","LANGUAGE","LC_ALL","LC_CTYPE","TMPDIR","TMP","TEMP","TZ"],S=["SystemRoot","WINDIR","ComSpec","PATHEXT","USERPROFILE","APPDATA","LOCALAPPDATA","ProgramData","ProgramFiles","ProgramFiles(x86)","TEMP","TMP","TZ"],m=["NO_COLOR","PI_CODING_AGENT_DIR"],P=["SHENNIAN_MANAGED_ROOM_CONTEXT","SHENNIAN_MANAGED_ROOM_IPC_ROOT"],R=["SHENNIAN_MANAGER_SESSION_ID","SHENNIAN_MANAGER_AGENT_SESSION_ID","SHENNIAN_MANAGER_WORKDIR","SHENNIAN_MANAGER_MODEL","SHENNIAN_MANAGER_IPC_URL","SHENNIAN_MANAGER_IPC_TOKEN"],T={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 T[e]??[]}function G(e){return e==="codex"||e==="claude"||e==="pi-coding-agent"?[...P,...R]:P}function W(e=process.platform){return["PATH",...e==="win32"?S:d,...m]}function _(e){return`'${e.replace(/'/g,"'\\''")}'`}function v(e){const n=e.indexOf(N),r=e.indexOf(f,n+N.length);if(n===-1||r===-1)return null;const t=e.slice(n+N.length,r);try{const o=JSON.parse(t),i={};for(const[c,s]of Object.entries(o))typeof s=="string"&&(i[c]=s);return i}catch{return null}}function w(){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 r of[["-ilc",n],["-lc",n]]){const t=p(e,r,{env:process.env,encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:1500,windowsHide:!0}),o=typeof t.stdout=="string"?v(t.stdout):null;if(o)return o}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
- Write-Output '${l}'
5
+ Write-Output '${N}'
6
6
  $envs | ConvertTo-Json -Compress
7
- Write-Output '${A}'
8
- `,n=_(h(),["-NoProfile","-Command",e],{env:{...process.env,...u(process.env)},encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:1500,windowsHide:!0});return typeof n.stdout=="string"?v(n.stdout):null}function I(){return(S.platform()==="win32"?y():R())??{}}function G(e){const n={...e.daemonEnv,...e.userEnv,...e.extra};return process.platform==="win32"&&Object.assign(n,u(n)),n.PATH=M(e.daemonEnv,e.userEnv,e.extra,n),delete n.Path,delete n.path,n}function j(e={}){return G({daemonEnv:process.env,userEnv:I(),extra:e})}function W(e){const n=e.daemonEnv??process.env,r=e.platform??process.platform,t={};return f(t,n,r==="win32"?N:m,r),f(t,e.providerEnv,w(e.agentType),r),f(t,e.sessionEnv,O,r),f(t,e.runtimeEnv,P,r),r==="win32"&&Object.assign(t,u({...n,...t})),t.PATH=D(n,t,r),delete t.Path,delete t.path,t}function f(e,n,r,t){if(!n)return;const o=Object.entries(n);for(const i of r){const s=(t==="win32"?o.find(([E])=>E.toUpperCase()===i.toUpperCase()):o.find(([E])=>E===i))?.[1];typeof s=="string"&&s.length>0&&(e[i]=s)}}function D(e,n,r){const t=r==="win32"?a.win32.delimiter:a.posix.delimiter,o=[],i=(c,s=!1)=>{if(c)for(const E of c.split(t))!E||o.includes(E)||(s?o.unshift(E):o.push(E))};if(i(d(e)),i(a.dirname(process.execPath),!0),r==="win32"){const c=u({...e,...n}),s=c.SystemRoot??c.WINDIR??"C:\\Windows";i(a.win32.join(s,"System32")),i(a.win32.join(s,"System32","WindowsPowerShell","v1.0")),i(s)}else i("/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin");return o.join(t)}function d(e){return e?.PATH??e?.Path??e?.path}function M(e,n,r,t){const o=[];for(const c of[d(e),d(n),d(r)])for(const s of(c??"").split(a.delimiter))s&&!o.includes(s)&&o.push(s);if(process.platform==="win32"){const c=t.SystemRoot||t.WINDIR||process.env.SystemRoot||process.env.WINDIR||"C:\\Windows";for(const s of[a.win32.join(c,"System32"),a.win32.join(c,"System32","WindowsPowerShell","v1.0"),a.win32.join(c)])s&&!o.includes(s)&&o.push(s)}const i=a.dirname(process.execPath);return i&&!o.includes(i)&&o.unshift(i),g({pathValue:o.join(a.delimiter),env:t})}export{O as MANAGED_AGENT_SESSION_ENV_KEYS,j as buildAgentProcessEnv,W as buildManagedAgentProcessEnv,V as getManagedAgentBaseEnvKeys,w as getManagedAgentProviderEnvKeys,G as mergeAgentProcessEnv,I as readLatestUserEnv};
7
+ Write-Output '${f}'
8
+ `,n=p(g(),["-NoProfile","-Command",e],{env:{...process.env,...A(process.env)},encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:1500,windowsHide:!0});return typeof n.stdout=="string"?v(n.stdout):null}function D(){return(I.platform()==="win32"?M():w())??{}}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 j(e={}){return y({daemonEnv:process.env,userEnv:D(),extra:e})}function $(e){const n=e.daemonEnv??process.env,r=e.platform??process.platform,t={};return l(t,n,r==="win32"?S:d,r),l(t,e.providerEnv,h(e.agentType),r),l(t,e.sessionEnv,G(e.agentType),r),l(t,e.runtimeEnv,m,r),r==="win32"&&Object.assign(t,A({...n,...t})),t.PATH=H(n,t,r),delete t.Path,delete t.path,t}function l(e,n,r,t){if(!n)return;const o=Object.entries(n);for(const i of r){const s=(t==="win32"?o.find(([a])=>a.toUpperCase()===i.toUpperCase()):o.find(([a])=>a===i))?.[1];typeof s=="string"&&s.length>0&&(e[i]=s)}}function H(e,n,r){const t=r==="win32"?E.win32.delimiter:E.posix.delimiter,o=[],i=(c,s=!1)=>{if(c)for(const a of c.split(t))!a||o.includes(a)||(s?o.unshift(a):o.push(a))};if(i(u(e)),i(E.dirname(process.execPath),!0),r==="win32"){const c=A({...e,...n}),s=c.SystemRoot??c.WINDIR??"C:\\Windows";i(E.win32.join(s,"System32")),i(E.win32.join(s,"System32","WindowsPowerShell","v1.0")),i(s)}else i("/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin");return o.join(t)}function u(e){return e?.PATH??e?.Path??e?.path}function L(e,n,r,t){const o=[];for(const c of[u(e),u(n),u(r)])for(const s of(c??"").split(E.delimiter))s&&!o.includes(s)&&o.push(s);if(process.platform==="win32"){const c=t.SystemRoot||t.WINDIR||process.env.SystemRoot||process.env.WINDIR||"C:\\Windows";for(const s of[E.win32.join(c,"System32"),E.win32.join(c,"System32","WindowsPowerShell","v1.0"),E.win32.join(c)])s&&!o.includes(s)&&o.push(s)}const i=E.dirname(process.execPath);return i&&!o.includes(i)&&o.unshift(i),O({pathValue:o.join(E.delimiter),env:t})}export{P as MANAGED_AGENT_SESSION_ENV_KEYS,j as buildAgentProcessEnv,$ as buildManagedAgentProcessEnv,W as getManagedAgentBaseEnvKeys,h as getManagedAgentProviderEnvKeys,G as getManagedAgentSessionEnvKeys,y as mergeAgentProcessEnv,D as readLatestUserEnv};
@@ -1,4 +1,4 @@
1
- import { AgentAdapter, type AgentSendContext, type AgentSendResult } from './adapter.js';
1
+ import { AgentAdapter, type AgentSendContext, type AgentSendResult, type AgentStartOptions } from './adapter.js';
2
2
  import { type ChatAttachmentMeta, type ExternalChannelSessionStatus } from '@shennian/wire';
3
3
  import type { SessionRunPhase } from '@shennian/wire';
4
4
  import { type CompiledManagedAgentPolicy } from '../security/managed-agent-policy.js';
@@ -49,6 +49,7 @@ export declare class CodexAdapter extends AgentAdapter {
49
49
  private preparedExternalOwnerThreadId;
50
50
  private managedTurnReplay;
51
51
  private managedAsyncRecovery;
52
+ private persistNativeSession;
52
53
  constructor(options?: {
53
54
  modelInstructionsFile?: string;
54
55
  hidden?: boolean;
@@ -67,7 +68,7 @@ export declare class CodexAdapter extends AgentAdapter {
67
68
  }): void;
68
69
  private configurationFingerprint;
69
70
  private buildProcessEnv;
70
- start(_sessionId: string, workDir: string, agentSessionId?: string | null): Promise<void>;
71
+ start(_sessionId: string, workDir: string, agentSessionId?: string | null, options?: AgentStartOptions): Promise<void>;
71
72
  prepareSend(_text: string, modelId?: string, _reasoningEffort?: string, _attachments?: ChatAttachmentMeta[], agentSystemPrompt?: string | null, context?: AgentSendContext): Promise<void>;
72
73
  send(text: string, modelId?: string, reasoningEffort?: string, attachments?: ChatAttachmentMeta[], agentSystemPrompt?: string | null, context?: AgentSendContext): Promise<void | AgentSendResult>;
73
74
  private isThreadTailInterrupted;
@@ -1,12 +1,12 @@
1
- import{spawnSync as O}from"node:child_process";import{createInterface as w}from"node:readline";import{createHash as S,randomUUID as b}from"node:crypto";import p from"node:path";import{AgentAdapter as q,registerAgent as D}from"./adapter.js";import{resolveBuiltinCommand as v,spawnAgentCommand as x}from"./command-spec.js";import{buildAgentProcessEnv as L,buildManagedAgentProcessEnv as N}from"../agent-env.js";import{ensurePlatformInstructionsFile as F}from"./platform-instructions.js";import{CODEX_DESKTOP_SEND_UNAVAILABLE as C}from"@shennian/wire";import{isCodexThreadTailInterrupted as $}from"../native-fusion/codex-files.js";import{resolveManagedAgentAdapterEnforcement as U}from"../security/managed-agent-policy.js";import{registerManagedAgentRuntimeSecurity as W}from"../security/managed-agent-runtime.js";import{CODEX_MANAGED_ROOM_DYNAMIC_TOOLS as z,CodexManagedRoomToolBinding as B}from"./codex-managed-room-tools.js";import{assertCodexManagedPermissionProfile as E,CODEX_MANAGED_RUNTIME_SECURITY as G,compileCodexManagedPermissions as J,extractCodexMcpServerNames as H}from"./codex-managed-permissions.js";import{CODEX_APP_SERVER_CLIENT_INFO as V,extractAppServerErrorMessage as R,formatCodexErrorMessage as X,formatTransientCodexStatus as K,isCodexCollabAgentItem as Q,isCodexCollabAgentToolName as y,isCodexLegacyCollabAgentItem as Y,isCodexUnsupportedEffortError as j,isMissingCodexRolloutError as T,isTransientCodexErrorMessage as Z,looksLikeCodexInteractiveAuthPrompt as ee,looksLikeFatalCodexStderr as te,normalizeCodexModelId as I,normalizeCodexReasoningEffort as re,normalizeCodexStderr as _,normalizeTerminalText as se,safeStringify as k,stripGitDirectiveArtifacts as ne}from"./codex-utils.js";import{isCodexUnsupportedEffortError as be,isMissingCodexRolloutError as qe,normalizeCodexModelId as De,normalizeCodexReasoningEffort as Le}from"./codex-utils.js";W("codex",G);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 ie(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 oe(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 ae(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 de(o,e){const t=p.resolve(e);let r;for(const s of o)if(s.id)for(const i of s.roots??[]){if(!i.path)continue;const n=p.resolve(i.path),a=p.relative(n,t);!(a===""||!a.startsWith("..")&&!p.isAbsolute(a))||n.length<=(r?.rootLength??-1)||(r={id:s.id,rootLength:n.length})}return r?.id}function le(o,e){const t=e?.flatMap(s=>ce(s)).filter(s=>!/^https?:\/\//i.test(s.path)).filter(s=>s.path);return{type:"text",text:he(o,e),text_elements:[],...t?.length?{local_images:t}:{}}}function ce(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=ue(o.path);return e?[{path:e}]:[]}return[]}function ue(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 O("ffmpeg",["-y","-ss","0","-i",o,"-frames:v","1","-vf","scale=320:-1",r],{stdio:"ignore",timeout:15e3}).status===0?r:null}function he(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 s=t.map((i,n)=>{const a=i.name||`attachment-${n+1}`,d=i.mimeType?` (${i.mimeType})`:"";return`[${A(a)}${d}](<${i.path}>)`});return[o,"",...s].join(`
1
+ import{spawnSync as O}from"node:child_process";import{createInterface as w}from"node:readline";import{createHash as S,randomUUID as b}from"node:crypto";import p from"node:path";import{AgentAdapter as q,registerAgent as N}from"./adapter.js";import{resolveBuiltinCommand as T,spawnAgentCommand as x}from"./command-spec.js";import{buildAgentProcessEnv as D,buildManagedAgentProcessEnv as L}from"../agent-env.js";import{ensurePlatformInstructionsFile as F}from"./platform-instructions.js";import{CODEX_DESKTOP_SEND_UNAVAILABLE as C}from"@shennian/wire";import{isCodexThreadTailInterrupted as $}from"../native-fusion/codex-files.js";import{resolveManagedAgentAdapterEnforcement as U}from"../security/managed-agent-policy.js";import{registerManagedAgentRuntimeSecurity as W}from"../security/managed-agent-runtime.js";import{CODEX_MANAGED_ROOM_DYNAMIC_TOOLS as z,CodexManagedRoomToolBinding as B}from"./codex-managed-room-tools.js";import{assertCodexManagedPermissionProfile as E,CODEX_MANAGED_RUNTIME_SECURITY as G,compileCodexManagedPermissions as J,extractCodexMcpServerNames as H}from"./codex-managed-permissions.js";import{CODEX_APP_SERVER_CLIENT_INFO as V,extractAppServerErrorMessage as R,formatCodexErrorMessage as X,formatTransientCodexStatus as K,isCodexCollabAgentItem as Q,isCodexCollabAgentToolName as v,isCodexLegacyCollabAgentItem as Y,isCodexUnsupportedEffortError as j,isMissingCodexRolloutError as y,isTransientCodexErrorMessage as Z,looksLikeCodexInteractiveAuthPrompt as ee,looksLikeFatalCodexStderr as te,normalizeCodexModelId as I,normalizeCodexReasoningEffort as re,normalizeCodexStderr as _,normalizeTerminalText as se,safeStringify as k,stripGitDirectiveArtifacts as ne}from"./codex-utils.js";import{isCodexUnsupportedEffortError as be,isMissingCodexRolloutError as qe,normalizeCodexModelId as Ne,normalizeCodexReasoningEffort as De}from"./codex-utils.js";W("codex",G);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 ie(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 oe(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 ae(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 de(o,e){const t=p.resolve(e);let r;for(const s of o)if(s.id)for(const i of s.roots??[]){if(!i.path)continue;const n=p.resolve(i.path),a=p.relative(n,t);!(a===""||!a.startsWith("..")&&!p.isAbsolute(a))||n.length<=(r?.rootLength??-1)||(r={id:s.id,rootLength:n.length})}return r?.id}function le(o,e){const t=e?.flatMap(s=>ce(s)).filter(s=>!/^https?:\/\//i.test(s.path)).filter(s=>s.path);return{type:"text",text:he(o,e),text_elements:[],...t?.length?{local_images:t}:{}}}function ce(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=ue(o.path);return e?[{path:e}]:[]}return[]}function ue(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 O("ffmpeg",["-y","-ss","0","-i",o,"-frames:v","1","-vf","scale=320:-1",r],{stdio:"ignore",timeout:15e3}).status===0?r:null}function he(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 s=t.map((i,n)=>{const a=i.name||`attachment-${n+1}`,d=i.mimeType?` (${i.mimeType})`:"";return`[${A(a)}${d}](<${i.path}>)`});return[o,"",...s].join(`
2
2
  `)}function pe(o,e){const t=e?.filter(s=>s.path&&!/^https?:\/\//i.test(s.path)&&!o.includes(s.path));if(!t?.length)return o;const r=t.map((s,i)=>{const n=A(s.name||`attachment-${i+1}`);return s.kind==="image"?`![${n}](<${s.path}>)`:`[${n}](<${s.path}>)`});return[o,"",...r].join(`
3
- `)}function me(o,e,t){return["queue","--thread",o,"--message",pe(e,t)]}function A(o){return o.replace(/[[\]\\]/g,"\\$&")}class ge extends q{options;type="codex";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 B;configuredManagedRoomContextToken=null;configuredManagedRoomExecutor=null;managedRoomToolThreadId=null;preparedExternalOwnerThreadId=null;managedTurnReplay=null;managedAsyncRecovery=null;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});const t=Object.fromEntries(Object.entries(this.extraEnv).filter(([r])=>r!=="SHENNIAN_MANAGED_ROOM_CONTEXT"&&r!=="SHENNIAN_MANAGED_ROOM_IPC_ROOT"));return N({agentType:"codex",providerEnv:t,sessionEnv:t,runtimeEnv:e})}async start(e,t,r){this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??t,this.seq=0,r&&(this.agentSessionId=r)}async prepareSend(e,t,r,s,i,n){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(n?.source==="room_activation")throw new Error("codex_managed_thread_owned_externally",{cause:d});if(this.isThreadTailInterrupted(this.agentSessionId))throw new Error(C,{cause:d});this.preparedExternalOwnerThreadId=this.agentSessionId}}}async send(e,t,r,s,i,n){if(n?.source==="room_activation"&&!this.managedAgentPolicy)throw new Error("managed_agent_policy_missing");if(n?.source==="room_activation"&&(!this.configuredManagedRoomContextToken||!this.configuredManagedRoomExecutor))throw new Error("codex_managed_room_tool_context_unavailable");this.activeTurnId&&(await this.interruptActiveTurn().catch(()=>{}),await this.killProcess(!0)),this.configurationRestartRequired&&this.process&&await this.killProcess(!0),this.configurationRestartRequired=!1;const a=I(t),d=re(r),c=i?.trim()??"";if(c!==this.agentSystemPrompt&&(this.agentSystemPrompt=c,this.process&&await this.killProcess(!0)),n?.source==="room_activation"&&this.managedRoomTools.configure(this.configuredManagedRoomContextToken,this.configuredManagedRoomExecutor),this.runId=b(),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,s)};try{await this.ensureAppServer(a)}catch(h){if(!this.agentSessionId||!P(h))throw h;if(n?.source==="room_activation")throw new Error("codex_managed_thread_owned_externally",{cause:h});if(this.isThreadTailInterrupted(this.agentSessionId))throw new Error(C,{cause:h});return{deliveryMode:"external_owner_queue",queuedSubmissionId:await this.enqueueForExternalOwner(this.agentSessionId,e,s)}}const l=this.agentSessionId;if(!l)throw new Error("codex app-server did not create a thread");this.emitEvent({state:"start",agentSessionId:l}),this.managedTurnReplay=this.managedPermissionConfig?{text:e,modelId:a,reasoningEffort:d,attachments:s,recoveryCount:0}:null;const g=await this.startTurnWithRecovery(l,e,a,d,s),m=this.agentSessionId??l;if(this.activeTurnId=g.turn?.id??null,this.managedPermissionConfig&&this.activeTurnId&&!this.managedRoomTools.bindTurn(m,this.activeTurnId))throw await this.killProcess(),new Error("codex_managed_room_turn_binding_failed");return{deliveryMode:"direct"}}isThreadTailInterrupted(e){return this.options.isThreadTailInterrupted?.(e)??$(e)}async enqueueForExternalOwner(e,t,r){const s=v("codex");if(!s)throw new Error('Command "codex" not found. Is OpenAI Codex CLI installed?');const i=me(e,t,r),n=x(s,i,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:this.buildProcessEnv({NO_COLOR:"1"})});return await new Promise((a,d)=>{let c="",l="",g=!1;const m=(u,f)=>{g||(g=!0,clearTimeout(h),u?d(u):a(f))},h=setTimeout(()=>{n.kill("SIGTERM"),m(new Error("Codex Desktop message queue timed out"))},6e4);h.unref?.(),n.stdout?.on("data",u=>{c+=u.toString()}),n.stderr?.on("data",u=>{l+=u.toString()}),n.once("error",u=>m(u)),n.once("close",u=>{const f=`${c}
4
- ${l}`.trim();if(u!==0){m(new Error(f||`codex queue exited with code ${u??"unknown"}`));return}const M=f.match(/Queued message\s+([^\s]+)\s+for thread/i)?.[1];m(void 0,M)})})}async resume(e){await this.killProcess(),this.agentSessionId=e,this.resetTextState()}async setTitle(e,t,r){const s=e.trim(),i=t.replace(/\s+/g," ").trim();!s||!i||(this.agentSessionId=s,r?.trim()&&(this.workDir=r),await this.ensureAppServer(),await this.sendRpc("thread/name/set",{threadId:s,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 s=r?.type==="active"||!!t;return{active:s,runId:t,runPhase:s?this.mapThreadStatusToRunPhase(r):null,canStop:!!(s&&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",n=>{if(n.trim())try{const a=JSON.parse(n);this.handleStreamEvent(a)}catch{this.emitEvent({state:"delta",text:n})}});let i="";r.stderr?.on("data",n=>{i+=n.toString()}),r.on("close",n=>{this.process===r&&(this.process=null,this.clearForceCloseTimer(),this.handleProcessClose(n,i))}),r.on("error",n=>{this.process===r&&(this.process=null,n.code==="ENOENT"?this.emit("error",new Error('Command "codex" not found. Is OpenAI Codex CLI installed?')):this.emit("error",n))})}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??F(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,this.agentSystemPrompt);r&&t.push("-c",`model_instructions_file=${JSON.stringify(r)}`);const s=x(e,t,{cwd:this.workDir??void 0,stdio:["pipe","pipe","pipe"],env:this.buildProcessEnv({NO_COLOR:"1"})});this.process=s,this.stderrBuf="",this.appServerStartupError=null,w({input:s.stdout}).on("line",n=>{if(!n.trim())return;let a;try{a=JSON.parse(n)}catch{this.handleAppServerNonJsonStdout(n);return}this.handleAppServerMessage(a)}),s.stderr?.on("data",n=>{this.stderrBuf+=n.toString()}),s.on("close",n=>{if(this.process!==s)return;const a=this.activeTurnId!=null;this.process=null,this.appServerReady=null,this.activeTurnId=null,this.managedRoomTools.reset(),this.clearConfiguredManagedRoomContext(),this.rejectAllPending(new Error(_(this.stderrBuf)||`codex app-server exited with code ${n}`)),this.terminalState==="open"&&a&&this.handleProcessClose(n,this.stderrBuf)}),s.on("error",n=>{this.process===s&&(this.process=null,this.managedRoomTools.reset(),this.clearConfiguredManagedRoomContext(),this.rejectAllPending(n),n.code==="ENOENT"?this.emit("error",new Error('Command "codex" not found. Is OpenAI Codex CLI installed?')):this.emit("error",n))})}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);if(await this.sendRpc("initialize",{clientInfo:V,capabilities:{experimentalApi:!0}}),this.managedPermissionConfig=this.managedAgentPolicy?await this.buildManagedPermissionConfig():null,this.managedPermissionConfig&&!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.managedPermissionConfig&&this.agentSessionId!==this.managedRoomToolThreadId){if(!this.managedRoomTools.isConfigured())throw new Error("codex_managed_room_tool_context_unavailable");this.agentSessionId=null}if(this.agentSessionId){const a={threadId:this.agentSessionId,cwd:this.workDir,approvalPolicy:"never",...this.managedPermissionConfig?{config:this.managedPermissionConfig.threadConfig}:{sandbox:"danger-full-access"},persistExtendedHistory:!0,...this.options.hidden?{threadSource:"subagent"}:{},...t?{model:t}:{}};let d;try{d=await this.sendRpc("thread/resume",{...a,excludeTurns:!0})}catch(c){if(!oe(c))throw c;d=await this.sendRpc("thread/resume",a)}this.agentSessionId=d.thread?.id??this.agentSessionId,this.managedPermissionConfig&&(E(d,this.managedPermissionConfig.profileId),this.managedRoomTools.bindThread(this.agentSessionId),this.managedRoomToolThreadId=this.agentSessionId);return}const r=this.options.hidden?void 0:await this.resolveCodexProjectId(),s={cwd:this.workDir,approvalPolicy:"never",...this.managedPermissionConfig?{config:this.managedPermissionConfig.threadConfig}:{sandbox:"danger-full-access"},serviceName:"Shennian",threadSource:this.options.hidden?"subagent":"user",experimentalRawEvents:!1,persistExtendedHistory:!0,...this.managedPermissionConfig?{dynamicTools:z}:{},...r?{projectId:r}:{},...t?{model:t}:{}};let i;if(this.options.hidden&&!this.managedPermissionConfig)i=await this.sendRpc("thread/start",s);else try{i=await this.sendRpc("thread/start",{...s,historyMode:"paginated"})}catch(a){throw ie(a)?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:a}):a}const n=i.thread?.id;if(!n)throw new Error("codex app-server thread/start returned no thread id");this.managedPermissionConfig&&(E(i,this.managedPermissionConfig.profileId),this.managedRoomTools.bindThread(n),this.managedRoomToolThreadId=n),this.agentSessionId=n}async buildManagedPermissionConfig(){const e=this.managedAgentPolicy;if(!e)throw new Error("managed_agent_policy_missing");const t=e.adapterPolicy.externalCapabilities.mcp?[]:H(await this.sendRpc("config/read",{cwd:e.adapterPolicy.workDir}));return J(U(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 c=await this.sendRpc("project/list",{limit:100,...r?{cursor:r}:{}});t.push(...c.data??[]),r=c.nextCursor}while(r);const s=de(t,e);if(s)return s;const i=p.resolve(e),n=`shennian-project-${S("sha256").update(i).digest("hex")}`,d=(await this.sendRpc("project/create",{idempotencyKey:n,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 ae(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,s,i){try{return await this.startTurn(e,t,r,s,i)}catch(n){if(!T(n))throw n;if(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:n});return this.logManagedThreadLifecycle("thread.recreated",{previousThreadId:e,threadId:a}),this.emitEvent({state:"start",agentSessionId:a}),await this.startFreshManagedTurnWithReadinessRetry(a,t,r,s,i)}return await this.killProcess(),await this.ensureAppServer(r),await this.startTurn(e,t,r,s,i)}}async startFreshManagedTurnWithReadinessRetry(e,t,r,s,i){const n=[0,100,300,1e3];let a;for(let d=0;d<n.length;d+=1){const c=n[d];c>0&&await new Promise(l=>setTimeout(l,c));try{const l=await this.startTurn(e,t,r,s,i);return d>0&&this.logManagedThreadLifecycle("rollout.ready",{threadId:e,attempt:d+1}),l}catch(l){if(a=l,!T(l)||d===n.length-1)throw l;this.logManagedThreadLifecycle("rollout.retry",{threadId:e,attempt:d+2,delayMs:n[d+1]})}}throw a}logManagedThreadLifecycle(e,t){console.error(`[codex.managed] ${JSON.stringify({event:e,...t})}`)}async startTurn(e,t,r,s,i){try{return await this.sendRpc("turn/start",{threadId:e,input:[le(t,i)],approvalPolicy:"never",...this.managedPermissionConfig?{}:{sandboxPolicy:{type:"dangerFullAccess"}},...r?{model:r}:{},...s?{effort:s}:{}})}catch(n){throw s&&j(n)?new Error(`Codex app-server does not accept reasoning effort "${s}" for this turn. Refresh models or upgrade Codex CLI, then retry.`,{cause:n}):n}}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 s=this.process;if(!s?.stdin)return Promise.reject(new Error("codex app-server is not running"));const i=this.rpcSeq++,n=JSON.stringify({id:i,method:e,params:t});return new Promise((a,d)=>{const c=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:c}),s.stdin.write(`${n}
5
- `,l=>{l&&(clearTimeout(c),this.pendingRequests.delete(i),d(l))})})}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,s=typeof r?.id=="string"?r.id:null,i=typeof t.threadId=="string"?t.threadId:"";s&&(this.activeTurnId=s,this.managedPermissionConfig&&!this.managedRoomTools.bindTurn(i,s)&&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 s=typeof t.status=="object"&&t.status!==null?t.status:null;s?.type==="active"&&this.emitEvent({state:"heartbeat",runPhase:this.mapThreadStatusToRunPhase(s)});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,s=typeof r?.id=="string"?r.id:null;(!this.activeTurnId||s===this.activeTurnId)&&(this.activeTurnId=null,this.managedRoomTools.deactivateTurn(),this.emitFinalIfOpen());break}case"turn/failed":{const r=R(t);if(this.scheduleManagedAsyncRolloutRecovery(r))return;this.emitErrorIfOpen(r||"turn failed");break}case"error":{const r=R(t);if(Z(r)){this.emitTransientStatus(r);return}if(this.scheduleManagedAsyncRolloutRecovery(r))return;this.emitErrorIfOpen(r);break}}}scheduleManagedAsyncRolloutRecovery(e){if(!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 s=T(r)?"no rollout found after managed thread recovery":r instanceof Error?r.message:"managed thread recovery failed";this.emitErrorIfOpen(s)}).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 s=await this.startFreshManagedTurnWithReadinessRetry(r,e.text,e.modelId,e.reasoningEffort,e.attachments);if(this.activeTurnId=s.turn?.id??null,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 s=typeof t.arguments=="object"&&t.arguments!==null?t.arguments:null,i=typeof s?.text=="string"?s.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 me(o,e,t){return["queue","--thread",o,"--message",pe(e,t)]}function A(o){return o.replace(/[[\]\\]/g,"\\$&")}class ge extends q{options;type="codex";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 B;configuredManagedRoomContextToken=null;configuredManagedRoomExecutor=null;managedRoomToolThreadId=null;preparedExternalOwnerThreadId=null;managedTurnReplay=null;managedAsyncRecovery=null;persistNativeSession=!0;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 D({...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 L({agentType:"codex",providerEnv:t,sessionEnv:t,runtimeEnv:e})}async start(e,t,r,s){this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??t,this.seq=0,this.persistNativeSession=s?.persistNativeSession!==!1,r&&(this.agentSessionId=r)}async prepareSend(e,t,r,s,i,n){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(n?.source==="room_activation")throw new Error("codex_managed_thread_owned_externally",{cause:d});if(this.isThreadTailInterrupted(this.agentSessionId))throw new Error(C,{cause:d});this.preparedExternalOwnerThreadId=this.agentSessionId}}}async send(e,t,r,s,i,n){if(n?.source==="room_activation"&&!this.managedAgentPolicy)throw new Error("managed_agent_policy_missing");if(n?.source==="room_activation"&&(!this.configuredManagedRoomContextToken||!this.configuredManagedRoomExecutor))throw new Error("codex_managed_room_tool_context_unavailable");this.activeTurnId&&(await this.interruptActiveTurn().catch(()=>{}),await this.killProcess(!0)),this.configurationRestartRequired&&this.process&&await this.killProcess(!0),this.configurationRestartRequired=!1;const a=I(t),d=re(r),c=i?.trim()??"";if(c!==this.agentSystemPrompt&&(this.agentSystemPrompt=c,this.process&&await this.killProcess(!0)),n?.source==="room_activation"&&this.managedRoomTools.configure(this.configuredManagedRoomContextToken,this.configuredManagedRoomExecutor),this.runId=b(),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,s)};try{await this.ensureAppServer(a)}catch(h){if(!this.agentSessionId||!P(h))throw h;if(n?.source==="room_activation")throw new Error("codex_managed_thread_owned_externally",{cause:h});if(this.isThreadTailInterrupted(this.agentSessionId))throw new Error(C,{cause:h});return{deliveryMode:"external_owner_queue",queuedSubmissionId:await this.enqueueForExternalOwner(this.agentSessionId,e,s)}}const l=this.agentSessionId;if(!l)throw new Error("codex app-server did not create a thread");this.emitEvent({state:"start",agentSessionId:l}),this.managedTurnReplay=this.managedPermissionConfig?{text:e,modelId:a,reasoningEffort:d,attachments:s,recoveryCount:0}:null;const g=await this.startTurnWithRecovery(l,e,a,d,s),m=this.agentSessionId??l;if(this.activeTurnId=g.turn?.id??null,this.managedPermissionConfig&&this.activeTurnId&&!this.managedRoomTools.bindTurn(m,this.activeTurnId))throw await this.killProcess(),new Error("codex_managed_room_turn_binding_failed");return{deliveryMode:"direct"}}isThreadTailInterrupted(e){return this.options.isThreadTailInterrupted?.(e)??$(e)}async enqueueForExternalOwner(e,t,r){const s=T("codex");if(!s)throw new Error('Command "codex" not found. Is OpenAI Codex CLI installed?');const i=me(e,t,r),n=x(s,i,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:this.buildProcessEnv({NO_COLOR:"1"})});return await new Promise((a,d)=>{let c="",l="",g=!1;const m=(u,f)=>{g||(g=!0,clearTimeout(h),u?d(u):a(f))},h=setTimeout(()=>{n.kill("SIGTERM"),m(new Error("Codex Desktop message queue timed out"))},6e4);h.unref?.(),n.stdout?.on("data",u=>{c+=u.toString()}),n.stderr?.on("data",u=>{l+=u.toString()}),n.once("error",u=>m(u)),n.once("close",u=>{const f=`${c}
4
+ ${l}`.trim();if(u!==0){m(new Error(f||`codex queue exited with code ${u??"unknown"}`));return}const M=f.match(/Queued message\s+([^\s]+)\s+for thread/i)?.[1];m(void 0,M)})})}async resume(e){await this.killProcess(),this.agentSessionId=e,this.resetTextState()}async setTitle(e,t,r){const s=e.trim(),i=t.replace(/\s+/g," ").trim();!s||!i||(this.agentSessionId=s,r?.trim()&&(this.workDir=r),await this.ensureAppServer(),await this.sendRpc("thread/name/set",{threadId:s,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 s=r?.type==="active"||!!t;return{active:s,runId:t,runPhase:s?this.mapThreadStatusToRunPhase(r):null,canStop:!!(s&&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",n=>{if(n.trim())try{const a=JSON.parse(n);this.handleStreamEvent(a)}catch{this.emitEvent({state:"delta",text:n})}});let i="";r.stderr?.on("data",n=>{i+=n.toString()}),r.on("close",n=>{this.process===r&&(this.process=null,this.clearForceCloseTimer(),this.handleProcessClose(n,i))}),r.on("error",n=>{this.process===r&&(this.process=null,n.code==="ENOENT"?this.emit("error",new Error('Command "codex" not found. Is OpenAI Codex CLI installed?')):this.emit("error",n))})}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??F(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,this.agentSystemPrompt);r&&t.push("-c",`model_instructions_file=${JSON.stringify(r)}`);const s=x(e,t,{cwd:this.workDir??void 0,stdio:["pipe","pipe","pipe"],env:this.buildProcessEnv({NO_COLOR:"1"})});this.process=s,this.stderrBuf="",this.appServerStartupError=null,w({input:s.stdout}).on("line",n=>{if(!n.trim())return;let a;try{a=JSON.parse(n)}catch{this.handleAppServerNonJsonStdout(n);return}this.handleAppServerMessage(a)}),s.stderr?.on("data",n=>{this.stderrBuf+=n.toString()}),s.on("close",n=>{if(this.process!==s)return;const a=this.activeTurnId!=null;this.process=null,this.appServerReady=null,this.activeTurnId=null,this.managedRoomTools.reset(),this.clearConfiguredManagedRoomContext(),this.rejectAllPending(new Error(_(this.stderrBuf)||`codex app-server exited with code ${n}`)),this.terminalState==="open"&&a&&this.handleProcessClose(n,this.stderrBuf)}),s.on("error",n=>{this.process===s&&(this.process=null,this.managedRoomTools.reset(),this.clearConfiguredManagedRoomContext(),this.rejectAllPending(n),n.code==="ENOENT"?this.emit("error",new Error('Command "codex" not found. Is OpenAI Codex CLI installed?')):this.emit("error",n))})}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);if(await this.sendRpc("initialize",{clientInfo:V,capabilities:{experimentalApi:!0}}),this.managedPermissionConfig=this.managedAgentPolicy?await this.buildManagedPermissionConfig():null,this.managedPermissionConfig&&!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.managedPermissionConfig&&this.agentSessionId!==this.managedRoomToolThreadId){if(!this.managedRoomTools.isConfigured())throw new Error("codex_managed_room_tool_context_unavailable");this.agentSessionId=null}if(this.agentSessionId){const d={threadId:this.agentSessionId,cwd:this.workDir,approvalPolicy:"never",...this.managedPermissionConfig?{config:this.managedPermissionConfig.threadConfig}:{sandbox:"danger-full-access"},persistExtendedHistory:!0,...this.options.hidden||!this.persistNativeSession?{threadSource:"subagent"}:{},...t?{model:t}:{}};let c;try{c=await this.sendRpc("thread/resume",{...d,excludeTurns:!0})}catch(l){if(!oe(l))throw l;c=await this.sendRpc("thread/resume",d)}this.agentSessionId=c.thread?.id??this.agentSessionId,this.managedPermissionConfig&&(E(c,this.managedPermissionConfig.profileId),this.managedRoomTools.bindThread(this.agentSessionId),this.managedRoomToolThreadId=this.agentSessionId);return}const r=this.options.hidden||!this.persistNativeSession,s=r?void 0:await this.resolveCodexProjectId(),i={cwd:this.workDir,approvalPolicy:"never",...this.managedPermissionConfig?{config:this.managedPermissionConfig.threadConfig}:{sandbox:"danger-full-access"},serviceName:"Shennian",threadSource:r?"subagent":"user",experimentalRawEvents:!1,persistExtendedHistory:!0,...this.managedPermissionConfig?{dynamicTools:z}:{},...s?{projectId:s}:{},...t?{model:t}:{}};let n;if(r&&!this.managedPermissionConfig)n=await this.sendRpc("thread/start",i);else try{n=await this.sendRpc("thread/start",{...i,historyMode:"paginated"})}catch(d){throw ie(d)?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:d}):d}const a=n.thread?.id;if(!a)throw new Error("codex app-server thread/start returned no thread id");this.managedPermissionConfig&&(E(n,this.managedPermissionConfig.profileId),this.managedRoomTools.bindThread(a),this.managedRoomToolThreadId=a),this.agentSessionId=a}async buildManagedPermissionConfig(){const e=this.managedAgentPolicy;if(!e)throw new Error("managed_agent_policy_missing");const t=e.adapterPolicy.externalCapabilities.mcp?[]:H(await this.sendRpc("config/read",{cwd:e.adapterPolicy.workDir}));return J(U(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 c=await this.sendRpc("project/list",{limit:100,...r?{cursor:r}:{}});t.push(...c.data??[]),r=c.nextCursor}while(r);const s=de(t,e);if(s)return s;const i=p.resolve(e),n=`shennian-project-${S("sha256").update(i).digest("hex")}`,d=(await this.sendRpc("project/create",{idempotencyKey:n,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 ae(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,s,i){try{return await this.startTurn(e,t,r,s,i)}catch(n){if(!y(n))throw n;if(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:n});return this.logManagedThreadLifecycle("thread.recreated",{previousThreadId:e,threadId:a}),this.emitEvent({state:"start",agentSessionId:a}),await this.startFreshManagedTurnWithReadinessRetry(a,t,r,s,i)}return await this.killProcess(),await this.ensureAppServer(r),await this.startTurn(e,t,r,s,i)}}async startFreshManagedTurnWithReadinessRetry(e,t,r,s,i){const n=[0,100,300,1e3];let a;for(let d=0;d<n.length;d+=1){const c=n[d];c>0&&await new Promise(l=>setTimeout(l,c));try{const l=await this.startTurn(e,t,r,s,i);return d>0&&this.logManagedThreadLifecycle("rollout.ready",{threadId:e,attempt:d+1}),l}catch(l){if(a=l,!y(l)||d===n.length-1)throw l;this.logManagedThreadLifecycle("rollout.retry",{threadId:e,attempt:d+2,delayMs:n[d+1]})}}throw a}logManagedThreadLifecycle(e,t){console.error(`[codex.managed] ${JSON.stringify({event:e,...t})}`)}async startTurn(e,t,r,s,i){try{return await this.sendRpc("turn/start",{threadId:e,input:[le(t,i)],approvalPolicy:"never",...this.managedPermissionConfig?{}:{sandboxPolicy:{type:"dangerFullAccess"}},...r?{model:r}:{},...s?{effort:s}:{}})}catch(n){throw s&&j(n)?new Error(`Codex app-server does not accept reasoning effort "${s}" for this turn. Refresh models or upgrade Codex CLI, then retry.`,{cause:n}):n}}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 s=this.process;if(!s?.stdin)return Promise.reject(new Error("codex app-server is not running"));const i=this.rpcSeq++,n=JSON.stringify({id:i,method:e,params:t});return new Promise((a,d)=>{const c=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:c}),s.stdin.write(`${n}
5
+ `,l=>{l&&(clearTimeout(c),this.pendingRequests.delete(i),d(l))})})}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,s=typeof r?.id=="string"?r.id:null,i=typeof t.threadId=="string"?t.threadId:"";s&&(this.activeTurnId=s,this.managedPermissionConfig&&!this.managedRoomTools.bindTurn(i,s)&&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 s=typeof t.status=="object"&&t.status!==null?t.status:null;s?.type==="active"&&this.emitEvent({state:"heartbeat",runPhase:this.mapThreadStatusToRunPhase(s)});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,s=typeof r?.id=="string"?r.id:null;(!this.activeTurnId||s===this.activeTurnId)&&(this.activeTurnId=null,this.managedRoomTools.deactivateTurn(),this.emitFinalIfOpen());break}case"turn/failed":{const r=R(t);if(this.scheduleManagedAsyncRolloutRecovery(r))return;this.emitErrorIfOpen(r||"turn failed");break}case"error":{const r=R(t);if(Z(r)){this.emitTransientStatus(r);return}if(this.scheduleManagedAsyncRolloutRecovery(r))return;this.emitErrorIfOpen(r);break}}}scheduleManagedAsyncRolloutRecovery(e){if(!this.managedPermissionConfig||!this.managedTurnReplay||!y(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 s=y(r)?"no rollout found after managed thread recovery":r instanceof Error?r.message:"managed thread recovery failed";this.emitErrorIfOpen(s)}).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 s=await this.startFreshManagedTurnWithReadinessRetry(r,e.text,e.modelId,e.reasoningEffort,e.attachments);if(this.activeTurnId=s.turn?.id??null,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 s=typeof t.arguments=="object"&&t.arguments!==null?t.arguments:null,i=typeof s?.text=="string"?s.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=se(e);ee(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")&&!Q(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:"",s=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:[s,t.exitCode!=null?`
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 s=typeof t.arguments=="object"&&t.arguments!==null?t.arguments:{};this.emitEvent({state:"tool-call",name:r,args:s}),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,s=typeof t?.total=="object"&&t.total!==null?t.total:null,i=r??s;if(!i)return;const n=typeof i.inputTokens=="number"?i.inputTokens:void 0,a=typeof i.outputTokens=="number"?i.outputTokens:void 0;(n!=null||a!=null)&&(this.pendingUsage={inputTokens:n??0,outputTokens:a??0})}handleCodexItemLine(e){const t=e.item;if(t?.type&&!Y(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
- (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(s=>`- [${s.completed?"x":" "}] ${s.text}`).join(`
9
- `);this.emitText(r,"block")}break}case"approval_request":case"approvalRequest":case"permission_request":case"permissionRequest":case"user_input_required":case"userInputRequired":{(e.type==="item.started"||e.type==="item.completed")&&this.emitApprovalPending(t);break}case"error":{e.type==="item.completed"&&t.message&&this.emitEvent({state:"error",message:t.message});break}default:break}}handleStreamEvent(e){const t=e.type??e.event;switch(t?.startsWith("item.")&&this.handleCodexItemLine(e),t){case"turn.completed":{const s=e.usage;if(s){const i=s.input_tokens??s.prompt_tokens,n=s.output_tokens??s.completion_tokens;(i!=null||n!=null)&&(this.pendingUsage={inputTokens:i??0,outputTokens:n??0})}this.emitFinalIfOpen();return}case"turn.failed":{const s=typeof e.error=="object"&&e.error?.message?e.error.message:typeof e.error=="string"?e.error:"turn failed";this.emitErrorIfOpen(s);return}case"error":{const s=typeof e.message=="string"?e.message:"";if(s.includes("Reconnecting"))return;this.emitErrorIfOpen(s||(typeof e.error=="string"?e.error:"stream error"));return}case"thread.started":{const s=e.thread_id??e.session_id??e.id;typeof s=="string"&&s&&(this.agentSessionId=s,this.emitEvent({state:"start",agentSessionId:this.agentSessionId}));return}case"turn.started":return}if(t?.startsWith("item."))return;switch(e.type??e.event){case"message":case"text":case"content":{const s=e.content??e.text;s&&this.emitText(s);break}case"function_call":case"tool_call":{if(this.isApprovalLikeName(e.name)){this.emitApprovalPending(e);break}if(e.name&&y(e.name))return;this.emitEvent({state:"tool-call",name:e.name,args:e.arguments??e.input});break}case"function_call_output":case"tool_result":{if(e.name&&y(e.name))return;this.emitEvent({state:"tool-result",name:e.name,result:e.output??e.result});break}case"approval_request":case"approvalRequest":case"permission_request":case"permissionRequest":case"user_input_required":case"userInputRequired":{this.emitApprovalPending(e);break}case"error":break;case"done":case"completed":{e.usage&&(this.pendingUsage={inputTokens:e.usage.prompt_tokens??e.usage.input_tokens??0,outputTokens:e.usage.completion_tokens??e.usage.output_tokens??0}),this.emitFinalIfOpen();break}}}emitEvent(e){if(this.terminalState!=="open"&&e.state!=="final"&&e.state!=="error"&&e.state!=="aborted")return;const t={...e,runId:this.runId,seq:this.seq++};this.emit("agentEvent",t)}isApprovalLikeName(e){return typeof e!="string"?!1:/approval|permission|confirm|user[_-]?input|request[_-]?user/i.test(e)}emitApprovalPending(e){const t=typeof e.command=="string"?e.command:"",r=typeof e.title=="string"&&e.title.trim()?e.title:"\u9700\u8981\u7528\u6237\u786E\u8BA4",s=typeof e.prompt=="string"?e.prompt:typeof e.reason=="string"?e.reason:typeof e.message=="string"?e.message:t?`Codex \u8BF7\u6C42\u6267\u884C\u547D\u4EE4\uFF1A${t}`:"Codex \u6B63\u5728\u7B49\u5F85\u7528\u6237\u786E\u8BA4\u540E\u7EE7\u7EED\u3002";this.emitEvent({state:"approval-pending",approval:{title:r,content:s,source:"codex",actionHint:"\u5F53\u524D\u795E\u5FF5\u6682\u4E0D\u652F\u6301\u8FDC\u7A0B\u786E\u8BA4\uFF0C\u8BF7\u56DE\u5230\u8FD0\u884C Codex \u7684\u7535\u8111/\u7EC8\u7AEF\u5B8C\u6210\u786E\u8BA4\u3002"}})}async killProcess(e=!1){const t=this.process;if(this.appServerReady=null,this.activeTurnId=null,this.managedRoomTools.reset(),e||this.clearConfiguredManagedRoomContext(),!t){this.rejectAllPending(new Error("codex app-server stopped"));return}this.process=null,this.clearForceCloseTimer(),t.kill("SIGTERM"),await new Promise(r=>{t.on("close",r),setTimeout(()=>{t.kill("SIGKILL"),r()},3e3)}),this.rejectAllPending(new Error("codex app-server stopped"))}rejectAllPending(e){for(const[t,r]of this.pendingRequests.entries())clearTimeout(r.timer),r.reject(e),this.pendingRequests.delete(t)}handleProcessClose(e,t){const r=_(t);if(e!==0&&e!==null){const s=r||`codex exited with code ${e}`;this.emitErrorIfOpen(s)}else te(r)?this.emitErrorIfOpen(r):this.emitFinalIfOpen();this.pendingUsage=void 0}emitFinalIfOpen(){this.terminalState==="open"&&(this.terminalState="final",this.managedTurnReplay=null,this.managedRoomTools.deactivateTurn(),this.clearConfiguredManagedRoomContext(),this.emitEvent({state:"final",usage:this.pendingUsage,agentSessionId:this.agentSessionId??void 0}),this.killProcess().catch(()=>{}))}emitErrorIfOpen(e){this.terminalState==="open"&&(this.terminalState="error",this.managedTurnReplay=null,this.managedRoomTools.deactivateTurn(),this.clearConfiguredManagedRoomContext(),this.emitEvent({state:"error",message:X(e)}),this.scheduleProcessClose())}resetRunState(){this.pendingUsage=void 0,this.terminalState="open",this.deltaItemIds.clear(),this.lastTransientStatus="",this.clearForceCloseTimer(),this.resetTextState()}clearConfiguredManagedRoomContext(){this.configuredManagedRoomContextToken=null,this.configuredManagedRoomExecutor=null}emitTransientStatus(e){const t=K(e);!t||t===this.lastTransientStatus||this.terminalState!=="open"||(this.lastTransientStatus=t,this.emitEvent({state:"delta",text:`${t}
7
+ (exit ${t.exitCode})`:""].join("").trim()});break}case"mcpToolCall":case"dynamicToolCall":{const r=typeof t.tool=="string"?t.tool:t.type;if(v(r))return;const s=typeof t.arguments=="object"&&t.arguments!==null?t.arguments:{};this.emitEvent({state:"tool-call",name:r,args:s}),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,s=typeof t?.total=="object"&&t.total!==null?t.total:null,i=r??s;if(!i)return;const n=typeof i.inputTokens=="number"?i.inputTokens:void 0,a=typeof i.outputTokens=="number"?i.outputTokens:void 0;(n!=null||a!=null)&&(this.pendingUsage={inputTokens:n??0,outputTokens:a??0})}handleCodexItemLine(e){const t=e.item;if(t?.type&&!Y(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
+ (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&&v(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(s=>`- [${s.completed?"x":" "}] ${s.text}`).join(`
9
+ `);this.emitText(r,"block")}break}case"approval_request":case"approvalRequest":case"permission_request":case"permissionRequest":case"user_input_required":case"userInputRequired":{(e.type==="item.started"||e.type==="item.completed")&&this.emitApprovalPending(t);break}case"error":{e.type==="item.completed"&&t.message&&this.emitEvent({state:"error",message:t.message});break}default:break}}handleStreamEvent(e){const t=e.type??e.event;switch(t?.startsWith("item.")&&this.handleCodexItemLine(e),t){case"turn.completed":{const s=e.usage;if(s){const i=s.input_tokens??s.prompt_tokens,n=s.output_tokens??s.completion_tokens;(i!=null||n!=null)&&(this.pendingUsage={inputTokens:i??0,outputTokens:n??0})}this.emitFinalIfOpen();return}case"turn.failed":{const s=typeof e.error=="object"&&e.error?.message?e.error.message:typeof e.error=="string"?e.error:"turn failed";this.emitErrorIfOpen(s);return}case"error":{const s=typeof e.message=="string"?e.message:"";if(s.includes("Reconnecting"))return;this.emitErrorIfOpen(s||(typeof e.error=="string"?e.error:"stream error"));return}case"thread.started":{const s=e.thread_id??e.session_id??e.id;typeof s=="string"&&s&&(this.agentSessionId=s,this.emitEvent({state:"start",agentSessionId:this.agentSessionId}));return}case"turn.started":return}if(t?.startsWith("item."))return;switch(e.type??e.event){case"message":case"text":case"content":{const s=e.content??e.text;s&&this.emitText(s);break}case"function_call":case"tool_call":{if(this.isApprovalLikeName(e.name)){this.emitApprovalPending(e);break}if(e.name&&v(e.name))return;this.emitEvent({state:"tool-call",name:e.name,args:e.arguments??e.input});break}case"function_call_output":case"tool_result":{if(e.name&&v(e.name))return;this.emitEvent({state:"tool-result",name:e.name,result:e.output??e.result});break}case"approval_request":case"approvalRequest":case"permission_request":case"permissionRequest":case"user_input_required":case"userInputRequired":{this.emitApprovalPending(e);break}case"error":break;case"done":case"completed":{e.usage&&(this.pendingUsage={inputTokens:e.usage.prompt_tokens??e.usage.input_tokens??0,outputTokens:e.usage.completion_tokens??e.usage.output_tokens??0}),this.emitFinalIfOpen();break}}}emitEvent(e){if(this.terminalState!=="open"&&e.state!=="final"&&e.state!=="error"&&e.state!=="aborted")return;const t={...e,runId:this.runId,seq:this.seq++};this.emit("agentEvent",t)}isApprovalLikeName(e){return typeof e!="string"?!1:/approval|permission|confirm|user[_-]?input|request[_-]?user/i.test(e)}emitApprovalPending(e){const t=typeof e.command=="string"?e.command:"",r=typeof e.title=="string"&&e.title.trim()?e.title:"\u9700\u8981\u7528\u6237\u786E\u8BA4",s=typeof e.prompt=="string"?e.prompt:typeof e.reason=="string"?e.reason:typeof e.message=="string"?e.message:t?`Codex \u8BF7\u6C42\u6267\u884C\u547D\u4EE4\uFF1A${t}`:"Codex \u6B63\u5728\u7B49\u5F85\u7528\u6237\u786E\u8BA4\u540E\u7EE7\u7EED\u3002";this.emitEvent({state:"approval-pending",approval:{title:r,content:s,source:"codex",actionHint:"\u5F53\u524D\u795E\u5FF5\u6682\u4E0D\u652F\u6301\u8FDC\u7A0B\u786E\u8BA4\uFF0C\u8BF7\u56DE\u5230\u8FD0\u884C Codex \u7684\u7535\u8111/\u7EC8\u7AEF\u5B8C\u6210\u786E\u8BA4\u3002"}})}async killProcess(e=!1){const t=this.process;if(this.appServerReady=null,this.activeTurnId=null,this.managedRoomTools.reset(),e||this.clearConfiguredManagedRoomContext(),!t){this.rejectAllPending(new Error("codex app-server stopped"));return}this.process=null,this.clearForceCloseTimer(),t.kill("SIGTERM"),await new Promise(r=>{t.on("close",r),setTimeout(()=>{t.kill("SIGKILL"),r()},3e3)}),this.rejectAllPending(new Error("codex app-server stopped"))}rejectAllPending(e){for(const[t,r]of this.pendingRequests.entries())clearTimeout(r.timer),r.reject(e),this.pendingRequests.delete(t)}handleProcessClose(e,t){const r=_(t);if(e!==0&&e!==null){const s=r||`codex exited with code ${e}`;this.emitErrorIfOpen(s)}else te(r)?this.emitErrorIfOpen(r):this.emitFinalIfOpen();this.pendingUsage=void 0}emitFinalIfOpen(){this.terminalState==="open"&&(this.terminalState="final",this.managedTurnReplay=null,this.managedRoomTools.deactivateTurn(),this.clearConfiguredManagedRoomContext(),this.emitEvent({state:"final",usage:this.pendingUsage,agentSessionId:this.agentSessionId??void 0}),this.killProcess().catch(()=>{}))}emitErrorIfOpen(e){this.terminalState==="open"&&(this.terminalState="error",this.managedTurnReplay=null,this.managedRoomTools.deactivateTurn(),this.clearConfiguredManagedRoomContext(),this.emitEvent({state:"error",message:X(e)}),this.scheduleProcessClose())}resetRunState(){this.pendingUsage=void 0,this.terminalState="open",this.deltaItemIds.clear(),this.lastTransientStatus="",this.clearForceCloseTimer(),this.resetTextState()}clearConfiguredManagedRoomContext(){this.configuredManagedRoomContextToken=null,this.configuredManagedRoomExecutor=null}emitTransientStatus(e){const t=K(e);!t||t===this.lastTransientStatus||this.terminalState!=="open"||(this.lastTransientStatus=t,this.emitEvent({state:"delta",text:`${t}
10
10
  `,thinking:!0}))}resetTextState(){this.hasEmittedText=!1,this.textTail=""}emitText(e,t="delta"){if(!e)return;let r=ne(e);r&&(t==="block"&&this.hasEmittedText&&!r.startsWith(`
11
11
  `)&&(this.textTail.endsWith(`
12
12
  `)?r=`
@@ -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 ge);export{ge as CodexAdapter,me as buildCodexQueueArgs,pe as buildCodexQueuedText,P as isCodexActiveWriterError,oe as isCodexExcludeTurnsUnsupportedError,ie as isCodexPaginatedHistoryUnsupportedError,ae as isCodexProjectApiUnsupportedError,be as isCodexUnsupportedEffortError,qe as isMissingCodexRolloutError,De as normalizeCodexModelId,Le as normalizeCodexReasoningEffort,de 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)}}N("codex",()=>new ge);export{ge as CodexAdapter,me as buildCodexQueueArgs,pe as buildCodexQueuedText,P as isCodexActiveWriterError,oe as isCodexExcludeTurnsUnsupportedError,ie as isCodexPaginatedHistoryUnsupportedError,ae as isCodexProjectApiUnsupportedError,be as isCodexUnsupportedEffortError,qe as isMissingCodexRolloutError,Ne as normalizeCodexModelId,De as normalizeCodexReasoningEffort,de as selectCodexProjectIdForWorkDir};
@@ -1,3 +1,3 @@
1
- import{spawn as k,spawnSync as g}from"node:child_process";import y from"node:fs";import E from"node:os";import s from"node:path";const F={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"}],manager:[{command:"shennian",args:["manager"],display:"shennian manager"}]},p=new Map,m=new Map,f=new Map,u=new Map;function K(){p.clear(),m.clear(),f.clear(),u.clear()}function d(){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(d()==="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"),v=[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(h=>r.map(w=>o.join(h,w)));if(n==="codebuddy"){const h=[o.join(l,"Programs","WorkBuddy"),o.join(l,"WorkBuddy"),o.join("C:\\","Program Files","WorkBuddy")];for(const w of h)for(const M of["codebuddy.exe","codebuddy.cmd","codebuddy"])v.push(o.join(w,"resources","app.asar.unpacked","cli","bin",M))}return v}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"&&d()==="darwin"&&i.push(...V(e)),n==="codebuddy"&&d()==="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=y.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 j(n,e){const t=n?.split(s.delimiter).filter(Boolean)??[];if(d()==="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 c(n){if(f.has(n))return f.get(n)??[];const e=d()==="win32",i=g(e?"where":"which",[n],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:3e3,windowsHide:!0,env:{...process.env,PATH:e?process.env.PATH:j(process.env.PATH,n)}}),r=[...i.status===0?R(i.stdout??""):[]];for(const a of b(n))y.existsSync(a)&&!r.includes(a)&&r.push(a);return f.set(n,r),r}function A(){return process.env.ComSpec||"cmd.exe"}function P(n){const e=s.extname(n).toLowerCase();return e===".exe"||e===".com"}function C(n){const e=s.extname(n).toLowerCase();return e===".cmd"||e===".bat"}function $(n){const e=s.extname(n).toLowerCase();return e===".js"||e===".mjs"||e===".cjs"}function W(){return c("node.exe")[0]??c("node")[0]??"node"}function S(n){return`"${n.replace(/"/g,'""')}"`}function x(n){return`'${n.replace(/'/g,"'\\''")}'`}function N(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 B(n){const e=n.trim();if(!e)throw new Error("Command string is empty");if(/[\\/]/.test(e)||/^[A-Za-z]:/.test(e))return C(e)?{kind:"cmd-shim",path:e}:{kind:"direct",path:e};const i=c(e),o=i.find(P);if(o)return{kind:"direct",path:o};const r=i.find(C);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=c("wsl.exe")[0]??c("wsl")[0];if(!e)return u.set(n,!1),!1;const i=g(e,["-e","sh","-lc",`command -v ${x(n)} >/dev/null 2>&1`],{stdio:"ignore",timeout:5e3,windowsHide:!0}).status===0;return u.set(n,i),i}function Q(n){if(p.has(n))return p.get(n)??!1;const e=c(n).length>0||d()==="win32"&&L(n);return p.set(n,e),e}function z(n){const e=c(n.command),t=e.find(P);if(t)return{...n,kind:"native",path:t};const i=e.find(C);if(i)return{...n,kind:"cmd-shim",path:i};if(L(n.command)){const o=c("wsl.exe")[0]??c("wsl")[0];if(o)return{...n,kind:"wsl-bridge",path:o}}return null}function X(n){if(m.has(n))return m.get(n)??null;const e=F[n].map(t=>{if(d()==="win32")return z(t);const i=c(t.command)[0];return i?{...t,kind:"native",path:i}:null}).find(Boolean)??null;return m.set(n,e),e}function H(n,e,t){if(n.kind==="native")return d()==="win32"&&$(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(S).join(" ");return{command:A(),args:["/d","/s","/c",`"${r}"`],cwd:t}}const i=t?N(t):void 0;if(t&&!i)throw new Error(`Cannot map Windows path to WSL workDir: ${t}`);const o=[i?`cd ${x(i)}`:"",`exec ${[n.command,...n.args,...e].map(x).join(" ")}`].filter(Boolean).join(" && ");return{command:n.path,args:["-e","sh","-lc",o],cwd:void 0}}function I(n,e,t={}){const i=H(n,e,t.cwd);return k(i.command,i.args,{...t,cwd:i.cwd,windowsHide:t.windowsHide??!0,...d()==="win32"&&n.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function Y(n,e,t={}){return I(n,e,t)}function D(n,e,t={}){const i=H(n,e,t.cwd);return g(i.command,i.args,{...t,cwd:i.cwd,windowsHide:t.windowsHide??!0,...d()==="win32"&&n.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function T(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 O(n,e,t){const i=T(n),o=i[0];if(!o)throw new Error("Command string is empty");const r=i.slice(1);if(d()!=="win32")return{command:o,args:[...r,...e],cwd:t};const a=B(o);return a.kind==="cmd-shim"?{command:A(),args:["/d","/s","/c",`"${[a.path,...r,...e].map(S).join(" ")}"`],cwd:t}:$(a.path)?{command:W(),args:[a.path,...r,...e],cwd:t}:{command:a.path,args:[...r,...e],cwd:t}}function nn(n,e,t={}){const i=O(n,e,t.cwd),o=T(n),r=d()==="win32"&&o[0]?B(o[0]):null;return k(i.command,i.args,{...t,cwd:i.cwd,windowsHide:t.windowsHide??!0,env:{...t.env,PATH:j(t.env?.PATH??process.env.PATH,o[0])},...d()==="win32"&&r?.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function q(n,e="--version"){const t=D(n,[e],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:5e3});return t.status!==0?void 0:`${t.stdout??""}
1
+ import{spawn as y,spawnSync as g}from"node:child_process";import k from"node:fs";import E from"node:os";import s from"node:path";const F={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"}]},p=new Map,m=new Map,f=new Map,u=new Map;function K(){p.clear(),m.clear(),f.clear(),u.clear()}function d(){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(d()==="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"),v=[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(h=>r.map(w=>o.join(h,w)));if(n==="codebuddy"){const h=[o.join(l,"Programs","WorkBuddy"),o.join(l,"WorkBuddy"),o.join("C:\\","Program Files","WorkBuddy")];for(const w of h)for(const M of["codebuddy.exe","codebuddy.cmd","codebuddy"])v.push(o.join(w,"resources","app.asar.unpacked","cli","bin",M))}return v}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"&&d()==="darwin"&&i.push(...V(e)),n==="codebuddy"&&d()==="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=k.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 j(n,e){const t=n?.split(s.delimiter).filter(Boolean)??[];if(d()==="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 c(n){if(f.has(n))return f.get(n)??[];const e=d()==="win32",i=g(e?"where":"which",[n],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:3e3,windowsHide:!0,env:{...process.env,PATH:e?process.env.PATH:j(process.env.PATH,n)}}),r=[...i.status===0?R(i.stdout??""):[]];for(const a of b(n))k.existsSync(a)&&!r.includes(a)&&r.push(a);return f.set(n,r),r}function A(){return process.env.ComSpec||"cmd.exe"}function P(n){const e=s.extname(n).toLowerCase();return e===".exe"||e===".com"}function C(n){const e=s.extname(n).toLowerCase();return e===".cmd"||e===".bat"}function $(n){const e=s.extname(n).toLowerCase();return e===".js"||e===".mjs"||e===".cjs"}function W(){return c("node.exe")[0]??c("node")[0]??"node"}function S(n){return`"${n.replace(/"/g,'""')}"`}function x(n){return`'${n.replace(/'/g,"'\\''")}'`}function N(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 B(n){const e=n.trim();if(!e)throw new Error("Command string is empty");if(/[\\/]/.test(e)||/^[A-Za-z]:/.test(e))return C(e)?{kind:"cmd-shim",path:e}:{kind:"direct",path:e};const i=c(e),o=i.find(P);if(o)return{kind:"direct",path:o};const r=i.find(C);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=c("wsl.exe")[0]??c("wsl")[0];if(!e)return u.set(n,!1),!1;const i=g(e,["-e","sh","-lc",`command -v ${x(n)} >/dev/null 2>&1`],{stdio:"ignore",timeout:5e3,windowsHide:!0}).status===0;return u.set(n,i),i}function Q(n){if(p.has(n))return p.get(n)??!1;const e=c(n).length>0||d()==="win32"&&L(n);return p.set(n,e),e}function z(n){const e=c(n.command),t=e.find(P);if(t)return{...n,kind:"native",path:t};const i=e.find(C);if(i)return{...n,kind:"cmd-shim",path:i};if(L(n.command)){const o=c("wsl.exe")[0]??c("wsl")[0];if(o)return{...n,kind:"wsl-bridge",path:o}}return null}function X(n){if(m.has(n))return m.get(n)??null;const e=F[n].map(t=>{if(d()==="win32")return z(t);const i=c(t.command)[0];return i?{...t,kind:"native",path:i}:null}).find(Boolean)??null;return m.set(n,e),e}function H(n,e,t){if(n.kind==="native")return d()==="win32"&&$(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(S).join(" ");return{command:A(),args:["/d","/s","/c",`"${r}"`],cwd:t}}const i=t?N(t):void 0;if(t&&!i)throw new Error(`Cannot map Windows path to WSL workDir: ${t}`);const o=[i?`cd ${x(i)}`:"",`exec ${[n.command,...n.args,...e].map(x).join(" ")}`].filter(Boolean).join(" && ");return{command:n.path,args:["-e","sh","-lc",o],cwd:void 0}}function I(n,e,t={}){const i=H(n,e,t.cwd);return y(i.command,i.args,{...t,cwd:i.cwd,windowsHide:t.windowsHide??!0,...d()==="win32"&&n.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function Y(n,e,t={}){return I(n,e,t)}function D(n,e,t={}){const i=H(n,e,t.cwd);return g(i.command,i.args,{...t,cwd:i.cwd,windowsHide:t.windowsHide??!0,...d()==="win32"&&n.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function T(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 O(n,e,t){const i=T(n),o=i[0];if(!o)throw new Error("Command string is empty");const r=i.slice(1);if(d()!=="win32")return{command:o,args:[...r,...e],cwd:t};const a=B(o);return a.kind==="cmd-shim"?{command:A(),args:["/d","/s","/c",`"${[a.path,...r,...e].map(S).join(" ")}"`],cwd:t}:$(a.path)?{command:W(),args:[a.path,...r,...e],cwd:t}:{command:a.path,args:[...r,...e],cwd:t}}function nn(n,e,t={}){const i=O(n,e,t.cwd),o=T(n),r=d()==="win32"&&o[0]?B(o[0]):null;return y(i.command,i.args,{...t,cwd:i.cwd,windowsHide:t.windowsHide??!0,env:{...t.env,PATH:j(t.env?.PATH??process.env.PATH,o[0])},...d()==="win32"&&r?.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function q(n,e="--version"){const t=D(n,[e],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:5e3});return t.status!==0?void 0:`${t.stdout??""}
2
2
  ${t.stderr??""}`.trim().match(/\d+\.\d+[\w.-]*/)?.[0]}function en(n,e){if(n!=="cursor")return q(e);const t=D(e,["about"],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:5e3});return t.status!==0?void 0:`${t.stdout??""}
3
3
  ${t.stderr??""}`.match(/^\s*CLI Version\s+(\d+\.\d+(?:\.\d+)?[\w.-]*)\s*$/im)?.[1]}export{O as buildCommandStringLaunchSpec,H as buildLaunchSpec,Q as commandExists,en as getBuiltinAgentVersion,q as getCommandVersion,d as getProcessPlatform,T as parseCommandString,K as resetCommandSpecCache,X as resolveBuiltinCommand,Y as spawnAgentCommand,nn as spawnCommandString,I as spawnResolvedCommand,D as spawnResolvedCommandSync,N as windowsPathToWsl};
@@ -1 +1 @@
1
- import s from"node:fs";import m from"node:os";import i from"node:path";import{readLatestUserEnv as E}from"../agent-env.js";import{loadConfig as S,resolveShennianPath as g}from"../config/index.js";const c=g("agent-provider-config.json"),U=4;function A(e){return e==="codex"||e==="claude"||e==="pi"}const O={codex:{baseUrl:["OPENAI_BASE_URL","OPENAI_API_BASE","OPENAI_API_URL"],token:["OPENAI_API_KEY","OPENAI_TOKEN"]},claude:{baseUrl:["ANTHROPIC_BASE_URL","ANTHROPIC_API_URL"],token:["ANTHROPIC_API_KEY","ANTHROPIC_AUTH_TOKEN"]},pi:{baseUrl:["DASHSCOPE_BASE_URL","DASHSCOPE_API_BASE","DASHSCOPE_API_URL"],token:["DASHSCOPE_API_KEY","DASHSCOPE_TOKEN"]}};function k(e){return u().configs[e]}function v(e){const n=u(),o=n.configs[e.agent],t={agent:e.agent,baseUrl:e.baseUrl?.trim()||o?.baseUrl,token:e.token?.trim()||o?.token,updatedAt:new Date().toISOString()};return n.configs[e.agent]=t,_(n),t}function B(e){const n=u();delete n.configs[e],_(n)}function K(e){if(!A(e))return{};const n=k(e);return n?l(e==="codex"?{OPENAI_BASE_URL:n.baseUrl,OPENAI_API_KEY:n.token}:e==="claude"?{ANTHROPIC_BASE_URL:n.baseUrl,ANTHROPIC_API_KEY:n.token}:{DASHSCOPE_BASE_URL:n.baseUrl,DASHSCOPE_API_KEY:n.token}):{}}function j(e,n=E()){if(!A(e))return;const o=k(e);if(o?.token||o?.baseUrl)return a({agent:e,source:"shennian",status:o.token?"managed":"missing",baseUrl:o.baseUrl,token:o.token,tokenPresent:!!o.token});const t=I(e,n);if(t.tokenPresent||t.baseUrl)return a({agent:e,source:"env",status:t.tokenPresent?"detected":"missing",baseUrl:t.baseUrl,token:t.token,tokenPresent:t.tokenPresent});const r=p(e);return r.tokenPresent||r.baseUrl?a({agent:e,source:"config-file",status:r.tokenPresent?"detected":"missing",baseUrl:r.baseUrl,token:r.token,tokenPresent:r.tokenPresent}):a({agent:e,source:"unknown",status:"missing",tokenPresent:!1})}function u(){try{return{configs:JSON.parse(s.readFileSync(c,"utf-8")).configs??{}}}catch{return{configs:{}}}}function _(e){s.mkdirSync(i.dirname(c),{recursive:!0}),s.writeFileSync(c,JSON.stringify(e,null,2),{mode:384});try{s.chmodSync(c,384)}catch{}}function l(e){const n={};for(const[o,t]of Object.entries(e))t&&(n[o]=t);return n}function I(e,n){const o=O[e],t=P(n,o.baseUrl),r=P(n,o.token);return{baseUrl:t,token:r,tokenPresent:!!r}}function P(e,n){for(const o of n){const t=e[o]?.trim();if(t)return t}}function p(e){const n=m.homedir();if(e==="pi"){const r=S().apiKeys?.dashscope?.trim();if(r)return{token:r,tokenPresent:!0}}const o=e==="codex"?[i.join(n,".codex","config.toml"),i.join(n,".codex","auth.json")]:e==="claude"?[i.join(n,".claude","settings.json"),i.join(n,".claude.json")]:[i.join(n,".dashscope","config.json")];for(const t of o){const r=C(t);if(!r)continue;const f=N(r,e),d=b(r);if(f||d)return{token:f,baseUrl:d,tokenPresent:!!f}}return{tokenPresent:!1}}function C(e){try{const n=s.statSync(e);return!n.isFile()||n.size>1024*1024?null:s.readFileSync(e,"utf-8")}catch{return null}}function b(e){return e.match(/(?:base_url|baseURL|api_url|apiUrl|ANTHROPIC_BASE_URL|OPENAI_BASE_URL|DASHSCOPE_BASE_URL)["'\s:=]+([^"'\s,}]+)/i)?.[1]?.trim()}function N(e,n){const o=n==="claude"?"sk-ant-":"sk-",t=e.match(new RegExp(`${o.replace(/-/g,"\\-")}[A-Za-z0-9_\\-]{8,}`));return t?.[0]?t[0]:e.match(/(?:api[_-]?key|auth[_-]?token|token|dashscope)["'\s:=]+([A-Za-z0-9_\-.]{12,})/i)?.[1]?.trim()}function a(e){return{status:e.status,source:e.source,tokenPresent:e.tokenPresent,...e.baseUrl?{baseUrlHost:R(e.baseUrl)}:{},...e.token?{tokenHint:h(e.token)}:{},updatedAt:new Date().toISOString()}}function h(e){const n=e.trim();return n?`\u2022\u2022\u2022\u2022${n.slice(-U)}`:""}function R(e){try{return new URL(e).host||e}catch{return e.replace(/^https?:\/\//i,"").replace(/\/.*$/,"")||e}}export{K as buildManagedAgentEnv,B as deleteManagedAgentProviderConfig,j as getAgentConfigSummary,k as getManagedAgentProviderConfig,h as maskToken,v as upsertManagedAgentProviderConfig};
1
+ import i from"node:fs";import E from"node:os";import c from"node:path";import{readLatestUserEnv as g}from"../agent-env.js";import{loadConfig as k,resolveShennianPath as S}from"../config/index.js";const a=S("agent-provider-config.json"),U=4;function A(e){return e==="codex"||e==="claude"||e==="pi"}const O={codex:{baseUrl:["OPENAI_BASE_URL","OPENAI_API_BASE","OPENAI_API_URL"],token:["OPENAI_API_KEY","OPENAI_TOKEN"]},claude:{baseUrl:["ANTHROPIC_BASE_URL","ANTHROPIC_API_URL"],token:["ANTHROPIC_API_KEY","ANTHROPIC_AUTH_TOKEN"]},pi:{baseUrl:["DASHSCOPE_BASE_URL","DASHSCOPE_API_BASE","DASHSCOPE_API_URL"],token:["DASHSCOPE_API_KEY","DASHSCOPE_TOKEN"]}};function P(e){return u().configs[e]}function v(e){const n=u(),o=n.configs[e.agent],t={agent:e.agent,baseUrl:e.baseUrl?.trim()||o?.baseUrl,token:e.token?.trim()||o?.token,updatedAt:new Date().toISOString()};return n.configs[e.agent]=t,_(n),t}function B(e){const n=u();delete n.configs[e],_(n)}function K(e){if(!A(e))return{};const n=P(e);return n?l(e==="codex"?{OPENAI_BASE_URL:n.baseUrl,OPENAI_API_KEY:n.token}:e==="claude"?{ANTHROPIC_BASE_URL:n.baseUrl,ANTHROPIC_API_KEY:n.token}:{DASHSCOPE_BASE_URL:n.baseUrl,DASHSCOPE_API_KEY:n.token}):{}}function j(e,n=g()){if(e==="pi-coding-agent"){const s=!!k().machineToken?.trim();return{status:s?"managed":"missing",source:"shennian",tokenPresent:!1,baseUrlHost:"shennian.net",...s?{}:{error:"Pair Shennian before using the managed Pi model."}}}if(!A(e))return;const o=P(e);if(o?.token||o?.baseUrl)return f({agent:e,source:"shennian",status:o.token?"managed":"missing",baseUrl:o.baseUrl,token:o.token,tokenPresent:!!o.token});const t=h(e,n);if(t.tokenPresent||t.baseUrl)return f({agent:e,source:"env",status:t.tokenPresent?"detected":"missing",baseUrl:t.baseUrl,token:t.token,tokenPresent:t.tokenPresent});const r=p(e);return r.tokenPresent||r.baseUrl?f({agent:e,source:"config-file",status:r.tokenPresent?"detected":"missing",baseUrl:r.baseUrl,token:r.token,tokenPresent:r.tokenPresent}):f({agent:e,source:"unknown",status:"missing",tokenPresent:!1})}function u(){try{return{configs:JSON.parse(i.readFileSync(a,"utf-8")).configs??{}}}catch{return{configs:{}}}}function _(e){i.mkdirSync(c.dirname(a),{recursive:!0}),i.writeFileSync(a,JSON.stringify(e,null,2),{mode:384});try{i.chmodSync(a,384)}catch{}}function l(e){const n={};for(const[o,t]of Object.entries(e))t&&(n[o]=t);return n}function h(e,n){const o=O[e],t=m(n,o.baseUrl),r=m(n,o.token);return{baseUrl:t,token:r,tokenPresent:!!r}}function m(e,n){for(const o of n){const t=e[o]?.trim();if(t)return t}}function p(e){const n=E.homedir();if(e==="pi"){const r=k().apiKeys?.dashscope?.trim();if(r)return{token:r,tokenPresent:!0}}const o=e==="codex"?[c.join(n,".codex","config.toml"),c.join(n,".codex","auth.json")]:e==="claude"?[c.join(n,".claude","settings.json"),c.join(n,".claude.json")]:[c.join(n,".dashscope","config.json")];for(const t of o){const r=I(t);if(!r)continue;const s=C(r,e),d=b(r);if(s||d)return{token:s,baseUrl:d,tokenPresent:!!s}}return{tokenPresent:!1}}function I(e){try{const n=i.statSync(e);return!n.isFile()||n.size>1024*1024?null:i.readFileSync(e,"utf-8")}catch{return null}}function b(e){return e.match(/(?:base_url|baseURL|api_url|apiUrl|ANTHROPIC_BASE_URL|OPENAI_BASE_URL|DASHSCOPE_BASE_URL)["'\s:=]+([^"'\s,}]+)/i)?.[1]?.trim()}function C(e,n){const o=n==="claude"?"sk-ant-":"sk-",t=e.match(new RegExp(`${o.replace(/-/g,"\\-")}[A-Za-z0-9_\\-]{8,}`));return t?.[0]?t[0]:e.match(/(?:api[_-]?key|auth[_-]?token|token|dashscope)["'\s:=]+([A-Za-z0-9_\-.]{12,})/i)?.[1]?.trim()}function f(e){return{status:e.status,source:e.source,tokenPresent:e.tokenPresent,...e.baseUrl?{baseUrlHost:H(e.baseUrl)}:{},...e.token?{tokenHint:N(e.token)}:{},updatedAt:new Date().toISOString()}}function N(e){const n=e.trim();return n?`\u2022\u2022\u2022\u2022${n.slice(-U)}`:""}function H(e){try{return new URL(e).host||e}catch{return e.replace(/^https?:\/\//i,"").replace(/\/.*$/,"")||e}}export{K as buildManagedAgentEnv,B as deleteManagedAgentProviderConfig,j as getAgentConfigSummary,P as getManagedAgentProviderConfig,N as maskToken,v as upsertManagedAgentProviderConfig};
@@ -9,4 +9,5 @@ export type DetectedAgent = {
9
9
  executableFingerprint?: string;
10
10
  models?: ModelInfo[];
11
11
  };
12
+ export declare function isPiCodingAgentRuntimeCompatible(piVersion: string | undefined): boolean;
12
13
  export declare function detectAgents(): DetectedAgent[];
@@ -1 +1 @@
1
- import{AVAILABLE_BUILTIN_AGENT_TYPES as m}from"@shennian/wire";import{loadConfig as i}from"../config/index.js";import{getBuiltinAgentVersion as l,resolveBuiltinCommand as c}from"./command-spec.js";import{registerCustomRuntimeSecurity as u,resolveCustomRuntimeExecutableFingerprint as a}from"./custom-managed-runtime.js";import{resolveManagedAgentExecutableIdentity as f}from"../security/managed-agent-executable.js";const d=m.filter(t=>t!=="pi");function p(t){const r=t.models?.length?t.models:t.model?[t.model]:[],o=t.defaultModel??t.model;return r.map(e=>({id:e,name:e,isDefault:e===o}))}function E(){const t=[];for(const o of d){const e=c(o);if(!e)continue;const n=l(o,e),s=f(e);t.push({type:o,command:e.command,args:e.args,version:n,runtimePlatform:s.platform,runtimeIsWsl:s.isWsl,executableFingerprint:s.executableFingerprint})}const r=i();for(const[o,e]of Object.entries(r.customAgents??{})){const n=`custom:${o}`;u(n,e),t.push({type:n,command:e.command,args:[],version:e.caps.version,runtimePlatform:process.platform,runtimeIsWsl:process.platform==="linux"&&!!(process.env.WSL_DISTRO_NAME||process.env.WSL_INTEROP),executableFingerprint:a(e),models:p(e.caps)})}return t}export{E as detectAgents};
1
+ import{AVAILABLE_BUILTIN_AGENT_TYPES as i}from"@shennian/wire";import{loadConfig as m}from"../config/index.js";import{getBuiltinAgentVersion as c,resolveBuiltinCommand as l}from"./command-spec.js";import{registerCustomRuntimeSecurity as u,resolveCustomRuntimeExecutableFingerprint as a}from"./custom-managed-runtime.js";import{resolveManagedAgentExecutableIdentity as f}from"../security/managed-agent-executable.js";const d=i.filter(t=>t!=="pi");function p(t,r){const o=t?.match(/(?:^|v)(\d+)\.(\d+)\.(\d+)/);if(!o)return!1;const e=o.slice(1,4).map(Number);for(let n=0;n<r.length;n+=1)if(e[n]!==r[n])return e[n]>r[n];return!0}function g(t){return p(t,[0,85,0])}function A(t){const r=t.models?.length?t.models:t.model?[t.model]:[],o=t.defaultModel??t.model;return r.map(e=>({id:e,name:e,isDefault:e===o}))}function y(){const t=[];for(const o of d){const e=l(o);if(!e)continue;const n=c(o,e);if(o==="pi-coding-agent"&&!g(n))continue;const s=f(e);t.push({type:o,command:e.command,args:e.args,version:n,runtimePlatform:s.platform,runtimeIsWsl:s.isWsl,executableFingerprint:s.executableFingerprint})}const r=m();for(const[o,e]of Object.entries(r.customAgents??{})){const n=`custom:${o}`;u(n,e),t.push({type:n,command:e.command,args:[],version:e.caps.version,runtimePlatform:process.platform,runtimeIsWsl:process.platform==="linux"&&!!(process.env.WSL_DISTRO_NAME||process.env.WSL_INTEROP),executableFingerprint:a(e),models:A(e.caps)})}return t}export{y as detectAgents,g as isPiCodingAgentRuntimeCompatible};
@@ -2,7 +2,7 @@ import type { AgentSendContext, AgentSendResult } from './adapter.js';
2
2
  import { AgentAdapter } from './adapter.js';
3
3
  import type { ChatAttachmentMeta, ExternalChannelSessionStatus } from '@shennian/wire';
4
4
  import type { CompiledManagedAgentPolicy } from '../security/managed-agent-policy.js';
5
- type ManagerModelId = 'codex' | 'claude';
5
+ type ManagerSubstrate = Exclude<import('@shennian/wire').AgentType, 'manager' | 'pi' | 'openclaw'>;
6
6
  /** Decorates a real provider Adapter with Manager session capabilities. New
7
7
  * sessions use this class and keep their real agentType/modelId. */
8
8
  export declare class ManagerModeAdapter extends AgentAdapter {
@@ -13,14 +13,14 @@ export declare class ManagerModeAdapter extends AgentAdapter {
13
13
  private workDir;
14
14
  private agentSessionId;
15
15
  private configured;
16
- constructor(inner: AgentAdapter, substrate: ManagerModelId);
16
+ constructor(inner: AgentAdapter, substrate: ManagerSubstrate);
17
17
  configure(options: {
18
18
  sessionId?: string;
19
19
  externalChannel?: ExternalChannelSessionStatus | null;
20
20
  env?: NodeJS.ProcessEnv;
21
21
  managedAgentPolicy?: CompiledManagedAgentPolicy | null;
22
22
  }): void;
23
- start(sessionId: string, workDir: string, agentSessionId?: string | null): Promise<void>;
23
+ start(sessionId: string, workDir: string, agentSessionId?: string | null, options?: import('./adapter.js').AgentStartOptions): Promise<void>;
24
24
  send(text: string, modelId?: string, reasoningEffort?: string, attachments?: ChatAttachmentMeta[], agentSystemPrompt?: string | null, context?: AgentSendContext): Promise<void | AgentSendResult>;
25
25
  resume(agentSessionId: string): Promise<void>;
26
26
  stop(): Promise<void>;