shennian 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/native/macos-background-client/Shennian.app/Contents/CodeResources +0 -0
- package/dist/native/macos-background-client/Shennian.app/Contents/Info.plist +17 -0
- package/dist/native/macos-background-client/Shennian.app/Contents/MacOS/ShennianClientLauncher +0 -0
- package/dist/native/macos-background-client/Shennian.app/Contents/Resources/en.lproj/InfoPlist.strings +2 -0
- package/dist/native/macos-background-client/Shennian.app/Contents/Resources/zh-Hans.lproj/InfoPlist.strings +2 -0
- package/dist/native/macos-background-client/Shennian.app/Contents/_CodeSignature/CodeResources +153 -0
- package/dist/publish-build-manifest.json +78 -43
- package/dist/src/agent-env.d.ts +1 -0
- package/dist/src/agent-env.js +4 -4
- package/dist/src/agents/codex.d.ts +3 -2
- package/dist/src/agents/codex.js +8 -8
- package/dist/src/agents/command-spec.js +1 -1
- package/dist/src/agents/config-status.js +1 -1
- package/dist/src/agents/detect.d.ts +1 -0
- package/dist/src/agents/detect.js +1 -1
- package/dist/src/agents/manager.d.ts +3 -3
- package/dist/src/agents/manager.js +9 -9
- package/dist/src/agents/model-registry/cache.d.ts +1 -1
- package/dist/src/agents/model-registry/cache.js +1 -1
- package/dist/src/agents/model-registry/discovery.js +3 -2
- package/dist/src/agents/model-registry/parsers.js +4 -4
- package/dist/src/agents/model-registry/service.js +1 -1
- package/dist/src/agents/model-registry/types.d.ts +1 -0
- package/dist/src/agents/pi-coding-agent-managed-permissions.d.ts +7 -0
- package/dist/src/agents/pi-coding-agent-managed-permissions.js +1 -0
- package/dist/src/agents/pi-coding-agent.d.ts +55 -0
- package/dist/src/agents/pi-coding-agent.js +4 -0
- package/dist/src/agents/pi-managed-extension.d.ts +12 -0
- package/dist/src/agents/pi-managed-extension.js +89 -0
- package/dist/src/agents/pi-managed-model-broker.d.ts +27 -0
- package/dist/src/agents/pi-managed-model-broker.js +1 -0
- package/dist/src/agents/pi-rpc-client.d.ts +31 -0
- package/dist/src/agents/pi-rpc-client.js +3 -0
- package/dist/src/agents/pi-session-ownership.d.ts +2 -0
- package/dist/src/agents/pi-session-ownership.js +2 -0
- package/dist/src/commands/daemon.d.ts +4 -0
- package/dist/src/commands/daemon.js +21 -17
- package/dist/src/commands/pair-browser.js +1 -1
- package/dist/src/manager/prompt.d.ts +1 -1
- package/dist/src/manager/prompt.js +2 -2
- package/dist/src/manager/registry.d.ts +4 -4
- package/dist/src/manager/runtime.d.ts +3 -3
- package/dist/src/room/activation-service.js +4 -4
- package/dist/src/room/device-authorization-client.d.ts +2 -0
- package/dist/src/room/managed-prompt-composer.d.ts +1 -1
- package/dist/src/room/managed-prompt-composer.js +2 -1
- package/dist/src/security/managed-agent-policy.js +1 -1
- package/dist/src/session/handlers/agent-workspace-validation.d.ts +24 -0
- package/dist/src/session/handlers/agent-workspace-validation.js +1 -0
- package/dist/src/session/handlers/chat.js +1 -1
- package/dist/src/session/manager.d.ts +1 -0
- package/dist/src/session/manager.js +1 -1
- package/dist/src/session/native-session-lifecycle.js +6 -6
- package/dist/src/session/queue.d.ts +5 -1
- package/dist/src/session/queue.js +2 -2
- package/dist/src/upgrade/engine.d.ts +1 -0
- package/dist/src/upgrade/engine.js +2 -2
- package/node_modules/@shennian/wire/dist/methods.d.ts +1 -1
- package/node_modules/@shennian/wire/dist/session.d.ts +2 -2
- package/node_modules/@shennian/wire/dist/session.js +1 -0
- package/package.json +3 -3
package/dist/src/agents/codex.js
CHANGED
|
@@ -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
|
|
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}>)`});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
|
|
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=
|
|
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||!
|
|
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(
|
|
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&&
|
|
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&&
|
|
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)}}
|
|
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
|
|
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
|
|
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, nodeVersion?: string): boolean;
|
|
12
13
|
export declare function detectAgents(): DetectedAgent[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AVAILABLE_BUILTIN_AGENT_TYPES as m}from"@shennian/wire";import{loadConfig as
|
|
1
|
+
import{AVAILABLE_BUILTIN_AGENT_TYPES as m}from"@shennian/wire";import{loadConfig as c}from"../config/index.js";import{getBuiltinAgentVersion as l,resolveBuiltinCommand as u}from"./command-spec.js";import{registerCustomRuntimeSecurity as a,resolveCustomRuntimeExecutableFingerprint as f}from"./custom-managed-runtime.js";import{resolveManagedAgentExecutableIdentity as d}from"../security/managed-agent-executable.js";const p=m.filter(t=>t!=="pi");function i(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,r=process.versions.node){return i(r,[22,19,0])&&i(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 p){const e=u(o);if(!e)continue;const n=l(o,e);if(o==="pi-coding-agent"&&!g(n))continue;const s=d(e);t.push({type:o,command:e.command,args:e.args,version:n,runtimePlatform:s.platform,runtimeIsWsl:s.isWsl,executableFingerprint:s.executableFingerprint})}const r=c();for(const[o,e]of Object.entries(r.customAgents??{})){const n=`custom:${o}`;a(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:f(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
|
|
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:
|
|
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>;
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import{AgentAdapter as
|
|
2
|
-
\u9ED8\u8BA4 worker \u6A21\u578B\uFF1A${
|
|
1
|
+
import{AgentAdapter as u,registerAgent as I}from"./adapter.js";import{CodexAdapter as p}from"./codex.js";import{ClaudeAdapter as f}from"./claude.js";import{MANAGER_SYSTEM_PROMPT as y,buildManagerPrompt as l}from"../manager/prompt.js";import{getManagerRuntimeService as o}from"../manager/runtime.js";import d from"node:fs";import c from"node:path";import{PLATFORM_OUTPUT_INSTRUCTIONS as S}from"./platform-instructions.js";function M(r){return r==="claude"?"claude":"codex"}function w(r){return r.replace(/[^a-zA-Z0-9_.-]/g,"_")}function v(r){const e=c.join(r,"AGENTS.md");try{return d.readFileSync(e,"utf8").trim()}catch{return""}}function A(r,e){return c.join(r,".shennian","runtime","manager",w(e),"instructions.md")}function h(r,e){const n=v(r),t=o(),s=t?.getManagerExternalChannelSystemPrompt(e)??"",i=typeof t?.getManagerWorkerDefaults=="function"?t.getManagerWorkerDefaults(e):void 0,a=i?.agentType?`\u9ED8\u8BA4 worker Agent\uFF1A${i.agentType}${i.modelId?`
|
|
2
|
+
\u9ED8\u8BA4 worker \u6A21\u578B\uFF1A${i.modelId}`:""}\u3002\u9664\u975E\u7528\u6237\u660E\u786E\u8981\u6C42\u6216\u4EFB\u52A1\u660E\u663E\u9700\u8981\u5176\u4ED6 Agent/\u6A21\u578B\uFF0C\u521B\u5EFA worker \u65F6\u4F18\u5148\u4F7F\u7528\u8FD9\u4E2A\u9ED8\u8BA4\u7EC4\u5408\u3002`:"";return`${["# Shennian Manager Instructions","This file is generated by Shennian for a Manager Agent substrate session. Do not edit it by hand.",n?`## Project Instructions
|
|
3
3
|
|
|
4
4
|
${n}`:"",`## Manager Instructions
|
|
5
5
|
|
|
6
|
-
${y}`,
|
|
6
|
+
${y}`,a?`## Worker Defaults
|
|
7
7
|
|
|
8
|
-
${
|
|
8
|
+
${a}`:"",s?`## External Message Channel Instructions
|
|
9
9
|
|
|
10
|
-
${
|
|
10
|
+
${s}`:"",S].filter(Boolean).join(`
|
|
11
11
|
|
|
12
12
|
`)}
|
|
13
|
-
`}function k(
|
|
14
|
-
${
|
|
13
|
+
`}function k(r,e){const n=A(r,e),t=h(r,e);d.mkdirSync(c.dirname(n),{recursive:!0});try{if(d.readFileSync(n,"utf8")===t)return n}catch{}return d.writeFileSync(n,t),n}class R extends u{inner;substrate;type;sessionId="";workDir="";agentSessionId=null;configured={};constructor(e,n){super(),this.inner=e,this.substrate=n,this.type=e.type,e.on("agentEvent",t=>{t.agentSessionId&&(this.agentSessionId=t.agentSessionId),this.emit("agentEvent",{...t,source:t.source??n})}),e.on("error",t=>this.emit("error",t))}configure(e){this.configured=e,e.sessionId&&o()?.setManagedAgentPolicy(e.sessionId,e.managedAgentPolicy??null),this.applyEnvironment()}async start(e,n,t,s){this.sessionId=e,this.workDir=n,this.agentSessionId=t??null,this.applyEnvironment(),await this.inner.start(e,n,t,s),o()?.registerManager({sessionId:e,agentSessionId:this.agentSessionId,workDir:n,modelId:this.substrate,agentType:this.type,status:"idle"}),o()?.bindManagerAdapterEvents(e,this.inner)}async send(e,n,t,s,i,a){o()?.registerManager({sessionId:this.sessionId,agentSessionId:this.agentSessionId,workDir:this.workDir,modelId:this.substrate,agentType:this.type,providerModelId:n??null,status:"running"}),await o()?.ready(),this.applyEnvironment();const g=h(this.workDir,this.sessionId),m=E(g,i);return this.inner.send(l(e),n,t,s,m,a)}async resume(e){this.agentSessionId=e,await this.inner.resume(e)}async stop(){o()?.setManagedAgentPolicy(this.sessionId,null),await this.inner.stop()}getStatus(){return this.inner.getStatus?.()??Promise.resolve({active:!1})}setTitle(e,n,t){return this.inner.setTitle?.(e,n,t)??Promise.resolve()}applyEnvironment(){const e=this.sessionId?o()?.getInjectedEnv(this.sessionId,this.agentSessionId,this.workDir,this.substrate)??{}:{};this.inner.configure?.({...this.configured,sessionId:this.configured.sessionId??this.sessionId,env:{...this.configured.env??{},...e},managedAgentPolicy:this.configured.managedAgentPolicy??null})}}function E(r,e){const n=e?.trim()??"";if(!n)return r;const s=["[\u667A\u80FD\u4F53\u79C1\u6709\u7CFB\u7EDF\u63D0\u793A\u8BCD]","[\u667A\u80FD\u4F53\u8EAB\u4EFD]"].map(i=>n.indexOf(i)).filter(i=>i>=0).sort((i,a)=>i-a)[0]??-1;return n.startsWith("[\u795E\u5FF5\u53D7\u7BA1\u4F1A\u8BDD\u89C4\u5219]")&&s>=0?`${n.slice(0,s)}[\u4F1A\u8BDD\u6A21\u5F0F]
|
|
14
|
+
${r.trim()}
|
|
15
15
|
|
|
16
|
-
${n.slice(
|
|
16
|
+
${n.slice(s)}`:`${r.trim()}
|
|
17
17
|
|
|
18
|
-
${n}`}class P extends
|
|
18
|
+
${n}`}class P extends u{type="manager";inner=null;sessionId="";workDir="";agentSessionId=null;modelId="codex";async start(e,n,t){this.sessionId=e,this.workDir=n,this.agentSessionId=t??null,o()?.registerManager({sessionId:e,agentSessionId:this.agentSessionId,workDir:n,modelId:this.modelId,agentType:"manager",status:"idle"})}async send(e,n){const t=M(n);if(!this.inner||t!==this.modelId){await this.inner?.stop().catch(()=>{}),this.inner?.removeAllListeners(),this.modelId=t;const s=k(this.workDir,this.sessionId),i=h(this.workDir,this.sessionId);this.inner=t==="claude"?new f({systemPrompt:i,hidden:!0}):new p({modelInstructionsFile:s,hidden:!0}),this.bindInner(this.inner),await this.inner.start(this.sessionId,this.workDir,this.agentSessionId),o()?.bindManagerAdapterEvents(this.sessionId,this.inner)}o()?.registerManager({sessionId:this.sessionId,agentSessionId:this.agentSessionId,workDir:this.workDir,modelId:this.modelId,agentType:"manager",status:"running"}),await o()?.ready(),await this.withManagerEnv(()=>this.inner.send(l(e)))}async resume(e){this.agentSessionId=e,this.inner&&await this.inner.resume(e)}async stop(){await this.inner?.stop()}bindInner(e){e.on("agentEvent",n=>{n.agentSessionId&&(this.agentSessionId=n.agentSessionId),this.emit("agentEvent",this.wrapEvent(n))}),e.on("error",n=>this.emit("error",n))}wrapEvent(e){return{...e,source:e.source??this.modelId,agentSessionId:e.agentSessionId??this.agentSessionId??void 0}}async withManagerEnv(e){const n=o()?.getInjectedEnv(this.sessionId,this.agentSessionId,this.workDir,this.modelId)??{},t=new Map;for(const[s,i]of Object.entries(n))t.set(s,process.env[s]),process.env[s]=i;try{return await e()}finally{for(const[s,i]of t)i===void 0?delete process.env[s]:process.env[s]=i}}}I("manager",()=>new P);export{P as ManagerAdapter,R as ManagerModeAdapter,E as combineManagerInstructions};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { type CacheEntry, type CacheFile } from './types.js';
|
|
2
2
|
export declare function readCache(): CacheFile;
|
|
3
3
|
export declare function writeCache(cache: CacheFile): void;
|
|
4
|
-
export declare function isCacheFresh(entry: CacheEntry | undefined, version?: string): boolean;
|
|
4
|
+
export declare function isCacheFresh(entry: CacheEntry | undefined, version?: string, sourceRevision?: string): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"node:fs";import o from"node:path";import{CACHE_TTL_MS as
|
|
1
|
+
import e from"node:fs";import o from"node:path";import{CACHE_TTL_MS as f,CACHE_VERSION as n,MODEL_CACHE_PATH as t}from"./types.js";function a(){e.mkdirSync(o.dirname(t),{recursive:!0})}function C(){try{const r=JSON.parse(e.readFileSync(t,"utf-8"));if(r.version===n&&r.agents&&typeof r.agents=="object")return r}catch{}return{version:n,agents:{}}}function h(r){try{a(),e.writeFileSync(t,JSON.stringify(r,null,2))}catch{}}function m(r,s,i){return!r||r.version!==s||i&&r.sourceRevision!==i?!1:Date.now()-r.refreshedAt<f}export{m as isCacheFresh,C as readCache,h as writeCache};
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import{createInterface as
|
|
2
|
-
`,p=>{p&&(clearTimeout(
|
|
1
|
+
import{createInterface as b}from"node:readline";import{resolveBuiltinCommand as l,spawnResolvedCommand as M}from"../command-spec.js";import{fallbackClaudeAliasModels as k,discoverClaudeAliasModelsFromEnv as E,fallbackCodexModels as R,fallbackWorkBuddyModels as x,fallbackGeminiModels as _,parseCodexAppServerModels as O,parseCursorModels as A,parseOpenCodeModels as I}from"./parsers.js";import{runResolvedCommand as m}from"./runner.js";import{DISCOVERY_WORKDIR as w}from"./types.js";import{buildAgentProcessEnv as C,readLatestUserEnv as S}from"../../agent-env.js";import{CODEX_APP_SERVER_CLIENT_INFO as T}from"../codex-utils.js";import{PiRpcClient as P}from"../pi-rpc-client.js";import{loadConfig as $}from"../../config/index.js";function v(r,e,t,s,n,i){return r.stdin?new Promise((o,a)=>{const c=setTimeout(()=>{e.delete(t),a(new Error(`codex app-server request timed out: ${s}`))},i);e.set(t,{resolve:o,reject:a,timer:c}),r.stdin.write(`${JSON.stringify({id:t,method:s,params:n})}
|
|
2
|
+
`,p=>{p&&(clearTimeout(c),e.delete(t),a(p))})}):Promise.reject(new Error("codex app-server stdin unavailable"))}async function D(r){const e=M(r,["app-server","--listen","stdio://"],{cwd:w,stdio:["pipe","pipe","pipe"],env:C({NO_COLOR:"1"})}),t=new Map;let s=1;b({input:e.stdout}).on("line",i=>{if(!i.trim())return;let o;try{o=JSON.parse(i)}catch{return}if(o.id==null)return;const a=t.get(o.id);a&&(clearTimeout(a.timer),t.delete(o.id),o.error?a.reject(new Error(o.error.message||`codex app-server error ${o.error.code??""}`.trim())):a.resolve(o.result))});try{await v(e,t,s++,"initialize",{clientInfo:T,capabilities:{experimentalApi:!0}},1e4);const[i,o]=await Promise.all([v(e,t,s++,"model/list",{},15e3),v(e,t,s++,"config/read",{},15e3).catch(()=>null)]),a=typeof o=="object"&&o!==null&&"config"in o?o.config:void 0;return O({...typeof i=="object"&&i!==null?i:{},config:a})}finally{for(const[i,o]of t)clearTimeout(o.timer),o.reject(new Error("codex app-server stopped")),t.delete(i);e.kill("SIGTERM"),setTimeout(()=>e.kill("SIGKILL"),1e3).unref()}}async function L(){const r=l("cursor");if(!r)return[];const e=await m(r,["--list-models"]);return A(e.stdout)}async function q(){const r=l("opencode");if(!r)return[];const e=await m(r,["models"]);return I(e.stdout)}async function j(){const r={id:"shennian-dashscope/deepseek-v4-flash-0731",name:"DeepSeek V4 Flash",provider:"shennian-dashscope",isDefault:!0,supportedReasoningEfforts:["low","high","max"].map(n=>({id:n,name:n})),defaultReasoningEffort:"high"},e=l("pi-coding-agent");if(!e)return[];if($().machineToken?.trim())return[r];const t=M(e,["--mode","rpc","--no-session","--offline","--no-extensions","--no-skills","--no-prompt-templates","--no-context-files","--no-tools"],{cwd:w,stdio:["pipe","pipe","pipe"],env:C({NO_COLOR:"1"})}),s=new P(t,{requestTimeoutMs:1e4});try{const[n,i]=await Promise.all([s.request("get_available_models"),s.request("get_state")]),o=n.data&&typeof n.data=="object"?n.data:{},a=i.data&&typeof i.data=="object"?i.data:{},c=typeof a.model?.id=="string"&&typeof a.model.provider=="string"?`${a.model.provider}/${a.model.id}`:null;return Array.isArray(o.models)?o.models.flatMap(f=>{if(!f||typeof f!="object")return[];const d=f;if(typeof d.id!="string"||typeof d.provider!="string")return[];const g=`${d.provider}/${d.id}`,h=d.reasoning===!0?["off","minimal","low","medium","high","xhigh","max"].map(y=>({id:y,name:y})):void 0;return[{id:g,name:typeof d.name=="string"&&d.name.trim()?d.name:d.id,provider:d.provider,isDefault:g===c,...h?{supportedReasoningEfforts:h,defaultReasoningEffort:"medium"}:{}}]}):[]}catch{return[]}finally{s.close(),t.kill("SIGTERM"),setTimeout(()=>t.kill("SIGKILL"),1e3).unref()}}async function G(){const r=l("claude");if(!r)return[];const e=S(),t=E(e);if(t.length>0)return t;const s=k(e),n=await m(r,["--help"],3e3).catch(()=>null);return!n||/\bfable\b/i.test(`${n.stdout}
|
|
3
|
+
${n.stderr}`)?s:s.filter(i=>i.id!=="fable")}async function N(){const r=l("codex");if(!r)return[];const e=await D(r).catch(()=>[]);return e.length>0?e:R()}async function B(){return l("gemini")?_():[]}const u=[{id:"qwen3.6-plus",name:"Qwen 3.6 Plus",provider:"dashscope",isDefault:!0}],F=[{id:"codex",name:"Codex",provider:"shennian",isDefault:!0},{id:"claude",name:"Claude Code",provider:"shennian"}];async function V(r){if(!r.serverUrl||!r.authToken)return u;try{const e=await fetch(`${r.serverUrl.replace(/\/$/,"")}/api/models`,{headers:{Authorization:`Bearer ${r.authToken}`}});if(!e.ok)return u;const t=await e.json(),s=(t.models??[]).map(n=>({id:n.id,name:n.name?.trim()||n.id,provider:n.provider,isDefault:n.id===t.default}));return s.length>0?s:u}catch{return u}}async function K(r,e){switch(r){case"claude":return G();case"codex":return N();case"workbuddy":return l("workbuddy")?x():[];case"gemini":return B();case"cursor":return L();case"openclaw":return[];case"opencode":return q();case"pi":return V(e);case"pi-coding-agent":return j();case"manager":return F}}async function ee(r,e){return r.type.startsWith("custom:")?r.models??[]:K(r.type,e)}export{ee as discoverModelsForAgent};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
function g(e){return e.replace(/\u001b\[[0-9;?]*[a-zA-Z]/g,"").replace(/\u001b\][^\u0007]*\u0007/g,"").replace(/[\u0000-\u0008\u000b-\u001f\u007f]/g,"")}function d(e){const n=new Set,t=[];for(const o of e)!o.id||n.has(o.id)||(n.add(o.id),t.push(o));return t}function E(e){return e&&e[0].toUpperCase()+e.slice(1)}function
|
|
2
|
-
`)){const i=o.trim().match(/^(\S+)\s+-\s+(.+?)(?:\s+\(([^)]+)\))?$/);if(!i)continue;const[,s,r,a]=i,u=a?.split(",").map(c=>c.trim().toLowerCase())??[];n.push({id:s,name:r.trim()||
|
|
3
|
-
`).map(t=>t.trim()).filter(Boolean).filter(t=>!t.includes(" ")).map(t=>({id:t,name:t,provider:t.includes("/")?t.split("/")[0]:void 0}));return d(n)}function j(e){const n=g(e).replace(/\s+/g," "),t=[[/\d+\.Default\(recommended\).*?(?:Sonnet|currently\s*Sonnet)\s*([\d.]+)/i,"default","Default (recommended)"],[/\d+\.Best.*?Opus\s*([\d.]+)/i,"best","Best","Most capable available model"],[/\d+\.Opus\(1Mcontext\).*?Opus\s*([\d.]+)/i,"opus[1m]","Opus (1M context)"],[/\d+\.OpusPlan.*?Opus\s*([\d.]+)/i,"opusplan","Opus Plan","Opus for planning \xB7 Sonnet for execution"],[/\d+\.Opus(?!\(1Mcontext\)).*?Opus\s*([\d.]+)/i,"opus","Opus"],[/\d+\.Sonnet\(1Mcontext\).*?Sonnet\s*([\d.]+)/i,"sonnet[1m]","Sonnet (1M context)"],[/\d+\.Sonnet(?!\(1Mcontext\)).*?Sonnet\s*([\d.]+)/i,"sonnet","Sonnet"],[/\d+\.Haiku.*?Haiku\s*([\d.]+)/i,"haiku","Haiku"]],o=[];for(const[a,u,c,l]of t){const p=n.match(a);p&&o.push(h({id:u,name:c,description:l?`${l} \xB7 v${p[1]}`:`v${p[1]}`,provider:"anthropic",isDefault:u==="default"}))}if(o.length>0)return d(o);const i=[],s=n.match(/currently\s*(Sonnet|Opus|Haiku)\s*([34](?:\.\d)?)/i),r={sonnet:"sonnet",opus:"opus",haiku:"haiku"};for(const a of n.matchAll(/\b(Sonnet|Opus|Haiku)\s*([34](?:\.\d)?)\b/gi)){const u=(a[1]??"").toLowerCase(),c=r[u];if(!c)continue;const l=a[2]??"",p=s&&s[1]?.toLowerCase()===u&&s[2]===l;i.push(h({id:c,name:`${E(u)} ${l}`,provider:"anthropic",isDefault:!!p}))}return d(i)}function T(e,n){const t=Math.max(e.length,n.length);for(let o=0;o<t;o++){const i=e[o]??-1,s=n[o]??-1;if(i!==s)return i-s}return 0}function w(e,n){const t=e.match(new RegExp(`^claude-${n}-([0-9]+(?:-[0-9]+)*)$`,"i"));if(!t?.[1])return null;const o=t[1].split("-").map(i=>Number.parseInt(i,10)).filter(i=>Number.isFinite(i));return o.length===0||o.length>2?null:o}function $(e){if(e?.length)return`v${e.join(".")}`}const y={default:"Default (recommended)",sonnet:"Sonnet",opus:"Opus",haiku:"Haiku"},L={default:"ANTHROPIC_MODEL",sonnet:"ANTHROPIC_DEFAULT_SONNET_MODEL",opus:"ANTHROPIC_DEFAULT_OPUS_MODEL",haiku:"ANTHROPIC_DEFAULT_HAIKU_MODEL"},P=[{id:"max",name:"Max"}],
|
|
4
|
-
`)){const i=o.match(/\b(gpt-[a-z0-9][a-z0-9.-]*)\b/i);if(!i)continue;const s=i[1].trim(),r=o.replace(s,"").replace(/^[^\w]+/,"").trim()||void 0;t.push({id:s,name:
|
|
1
|
+
function g(e){return e.replace(/\u001b\[[0-9;?]*[a-zA-Z]/g,"").replace(/\u001b\][^\u0007]*\u0007/g,"").replace(/[\u0000-\u0008\u000b-\u001f\u007f]/g,"")}function d(e){const n=new Set,t=[];for(const o of e)!o.id||n.has(o.id)||(n.add(o.id),t.push(o));return t}function E(e){return e&&e[0].toUpperCase()+e.slice(1)}function x(e){return e.split("-").map(n=>n==="gpt"?"GPT":n==="codex"?"Codex":/^\d/.test(n)?n:E(n)).join("-")}function C(e){switch(e){case"low":return"Low";case"medium":return"Medium";case"high":return"High";case"xhigh":return"Extra High";default:return E(e)}}const O=[{id:"gpt-5.6-sol",name:"GPT-5.6 Sol",description:"Latest GPT-5.6 Codex model.",provider:"openai"},{id:"gpt-5.6-terra",name:"GPT-5.6 Terra",description:"Latest GPT-5.6 Codex model.",provider:"openai"},{id:"gpt-5.6-luna",name:"GPT-5.6 Luna",description:"Latest GPT-5.6 Codex model.",provider:"openai"}];function M(e){const n={...e};return e.supportedReasoningEfforts&&(n.supportedReasoningEfforts=e.supportedReasoningEfforts.map(t=>({...t}))),e.additionalSpeedTiers&&(n.additionalSpeedTiers=[...e.additionalSpeedTiers]),n}function k(e,n){const t=n??e.find(i=>i.isDefault)?.id,o=d([...e.map(M),...O.map(i=>M(i))]);return t?o.map(i=>({...i,isDefault:i.id===t})):o}function N(){return O.map((e,n)=>({...M(e),...n===0?{isDefault:!0}:{}}))}function H(){return[{id:"auto",name:"Auto",provider:"workbuddy",isDefault:!0,supportedReasoningEfforts:["minimal","low","medium","high","xhigh","max"].map(e=>({id:e,name:C(e)})),defaultReasoningEffort:"medium"}]}function R(e){return e.split("-").map(n=>/^\d/.test(n)?n:E(n)).join(" ")}function _(e,n,t=!1){const o=n.toLowerCase().replace(/\s+/g,"-");return`gemini-${e}-${o}${t?"-preview":""}`}function I(e){const n=[],t=g(e);for(const o of t.split(`
|
|
2
|
+
`)){const i=o.trim().match(/^(\S+)\s+-\s+(.+?)(?:\s+\(([^)]+)\))?$/);if(!i)continue;const[,s,r,a]=i,u=a?.split(",").map(c=>c.trim().toLowerCase())??[];n.push({id:s,name:r.trim()||R(s),description:a?.trim(),isDefault:u.includes("default")||u.includes("current")})}return d(n)}function U(e){try{const t=(JSON.parse(e).models??[]).filter(o=>o.available).map(o=>({id:o.key,name:o.name?.trim()||o.key,provider:o.key.split("/")[0],description:o.tags?.join(", "),isDefault:o.tags?.includes("default")??!1}));return d(t)}catch{return[]}}function B(e){const n=g(e).split(`
|
|
3
|
+
`).map(t=>t.trim()).filter(Boolean).filter(t=>!t.includes(" ")).map(t=>({id:t,name:t,provider:t.includes("/")?t.split("/")[0]:void 0}));return d(n)}function j(e){const n=g(e).replace(/\s+/g," "),t=[[/\d+\.Default\(recommended\).*?(?:Sonnet|currently\s*Sonnet)\s*([\d.]+)/i,"default","Default (recommended)"],[/\d+\.Best.*?Opus\s*([\d.]+)/i,"best","Best","Most capable available model"],[/\d+\.Fable.*?Fable\s*([\d.]+)/i,"fable","Fable","Most capable for the hardest, longest-running tasks"],[/\d+\.Opus\(1Mcontext\).*?Opus\s*([\d.]+)/i,"opus[1m]","Opus (1M context)"],[/\d+\.OpusPlan.*?Opus\s*([\d.]+)/i,"opusplan","Opus Plan","Opus for planning \xB7 Sonnet for execution"],[/\d+\.Opus(?!\(1Mcontext\)).*?Opus\s*([\d.]+)/i,"opus","Opus"],[/\d+\.Sonnet\(1Mcontext\).*?Sonnet\s*([\d.]+)/i,"sonnet[1m]","Sonnet (1M context)"],[/\d+\.Sonnet(?!\(1Mcontext\)).*?Sonnet\s*([\d.]+)/i,"sonnet","Sonnet"],[/\d+\.Haiku.*?Haiku\s*([\d.]+)/i,"haiku","Haiku"]],o=[];for(const[a,u,c,l]of t){const p=n.match(a);p&&o.push(h({id:u,name:c,description:l?`${l} \xB7 v${p[1]}`:`v${p[1]}`,provider:"anthropic",isDefault:u==="default"}))}if(o.length>0)return d(o);const i=[],s=n.match(/currently\s*(Sonnet|Opus|Haiku)\s*([34](?:\.\d)?)/i),r={sonnet:"sonnet",opus:"opus",haiku:"haiku"};for(const a of n.matchAll(/\b(Sonnet|Opus|Haiku)\s*([34](?:\.\d)?)\b/gi)){const u=(a[1]??"").toLowerCase(),c=r[u];if(!c)continue;const l=a[2]??"",p=s&&s[1]?.toLowerCase()===u&&s[2]===l;i.push(h({id:c,name:`${E(u)} ${l}`,provider:"anthropic",isDefault:!!p}))}return d(i)}function T(e,n){const t=Math.max(e.length,n.length);for(let o=0;o<t;o++){const i=e[o]??-1,s=n[o]??-1;if(i!==s)return i-s}return 0}function w(e,n){const t=e.match(new RegExp(`^claude-${n}-([0-9]+(?:-[0-9]+)*)$`,"i"));if(!t?.[1])return null;const o=t[1].split("-").map(i=>Number.parseInt(i,10)).filter(i=>Number.isFinite(i));return o.length===0||o.length>2?null:o}function $(e){if(e?.length)return`v${e.join(".")}`}const y={default:"Default (recommended)",sonnet:"Sonnet",opus:"Opus",haiku:"Haiku"},L={default:"ANTHROPIC_MODEL",sonnet:"ANTHROPIC_DEFAULT_SONNET_MODEL",opus:"ANTHROPIC_DEFAULT_OPUS_MODEL",haiku:"ANTHROPIC_DEFAULT_HAIKU_MODEL"},P=[{id:"max",name:"Max"}],F=[{id:"low",name:"Low"},{id:"medium",name:"Medium"},{id:"high",name:"High"},{id:"xhigh",name:"Extra High"},{id:"max",name:"Max"}];function h(e){return{...e,supportedReasoningEfforts:F,defaultReasoningEffort:"medium"}}function b(e,n){return e[n]?.trim()||null}function A(e,n){const t=b(n,"ANTHROPIC_BASE_URL")?.toLowerCase()??"";return t.includes("deepseek.com")||e.toLowerCase().startsWith("deepseek-")?"deepseek":t?"custom":"anthropic"}function D(e){const n=new Set;for(const o of Object.values(L)){const i=b(e,o);i&&n.add(i)}const t=Array.from(n).map((o,i)=>{const s=A(o,e),r={id:o,name:o,provider:s,isDefault:i===0};return s==="deepseek"?{...r,supportedReasoningEfforts:P,defaultReasoningEffort:b(e,"CLAUDE_CODE_EFFORT_LEVEL")??"max"}:h(r)});return d(t)}function V(e=process.env){return D(e)}function G(e,n=process.env){return e.map(t=>{if(!["default","sonnet","opus","haiku"].includes(t.id))return t;const o=t.id,i=b(n,L[o]);if(!i)return t;const r=`Claude Code alias: ${y[o]}`;return{...t,name:i,description:t.description?`${r} \xB7 ${t.description}`:r,provider:A(i,n)}})}function z(e){const n=g(e),t=new Map;for(const i of["sonnet","opus","haiku"])for(const s of n.matchAll(new RegExp(`\\bclaude-${i}-[0-9.-]+\\b`,"gi"))){const r=s[0].trim().toLowerCase().replace(/\./g,"-").replace(/-+$/g,""),a=w(r,i);if(!a)continue;const u=t.get(i);(!u||T(u,a)<0)&&t.set(i,a)}const o=[];for(const i of["default","sonnet","opus","haiku"]){if(!new RegExp(`\\b${i}\\b`,"i").test(n))continue;const s=(i==="default"?t.get("sonnet"):t.get(i))??null;o.push(h({id:i,name:y[i],description:$(s),provider:"anthropic",isDefault:i==="default"}))}return d(o)}function q(e=process.env){const n=D(e);return n.length>0?n:G([{id:"default",name:"Default (recommended)",description:"Recommended model for your account",provider:"anthropic",isDefault:!0},{id:"sonnet",name:"Sonnet",description:"Latest Sonnet \xB7 everyday coding",provider:"anthropic"},{id:"fable",name:"Fable",description:"Most capable for the hardest, longest-running tasks",provider:"anthropic"},{id:"opus",name:"Opus",description:"Latest Opus \xB7 complex reasoning",provider:"anthropic"},{id:"haiku",name:"Haiku",description:"Fast and efficient \xB7 simple tasks",provider:"anthropic"},{id:"best",name:"Best",description:"Most capable available model",provider:"anthropic"},{id:"opus[1m]",name:"Opus (1M context)",description:"Latest Opus \xB7 long sessions",provider:"anthropic"},{id:"sonnet[1m]",name:"Sonnet (1M context)",description:"Latest Sonnet \xB7 long sessions",provider:"anthropic"},{id:"opusplan",name:"Opus Plan",description:"Opus for planning \xB7 Sonnet for execution",provider:"anthropic"}],e).map(t=>t.id==="haiku"?t:h(t))}function K(e){const n=g(e),t=[];for(const o of n.split(`
|
|
4
|
+
`)){const i=o.match(/\b(gpt-[a-z0-9][a-z0-9.-]*)\b/i);if(!i)continue;const s=i[1].trim(),r=o.replace(s,"").replace(/^[^\w]+/,"").trim()||void 0;t.push({id:s,name:x(s),description:r,provider:"openai",isDefault:/\bcurrent\b/i.test(o)||/\bselected\b/i.test(o)})}return d(t)}function W(e){const n=typeof e=="object"&&e!==null?e:{},t=typeof n.config?.model=="string"?n.config.model:void 0,o=typeof n.config?.model_reasoning_effort=="string"?n.config.model_reasoning_effort:void 0,i=[];for(const s of n.data??[]){if(typeof s!="object"||s===null)continue;const r=s,a=typeof r.id=="string"?r.id:typeof r.model=="string"?r.model:"";if(!a)continue;const u=typeof r.displayName=="string"?r.displayName:typeof r.name=="string"?r.name:void 0,c=typeof r.description=="string"?r.description:void 0,l=typeof r.defaultReasoningEffort=="string"?r.defaultReasoningEffort:void 0,p=Array.isArray(r.supportedReasoningEfforts)?r.supportedReasoningEfforts.map(f=>{if(typeof f!="object"||f===null)return null;const m=f,v=typeof m.reasoningEffort=="string"?m.reasoningEffort:typeof m.id=="string"?m.id:"";return v?{id:v,name:C(v),description:typeof m.description=="string"?m.description:void 0}:null}).filter(f=>f!=null):void 0,S=Array.isArray(r.additionalSpeedTiers)?r.additionalSpeedTiers.filter(f=>typeof f=="string"):void 0;i.push({id:a,name:u||x(a),description:c,provider:"openai",isDefault:t?t===a:r.isDefault===!0,supportedReasoningEfforts:p,defaultReasoningEffort:l,additionalSpeedTiers:S})}return t&&!i.some(s=>s.id===t)&&i.unshift({id:t,name:x(t),provider:"openai",isDefault:!0,defaultReasoningEffort:o}),k(d(i),t)}function J(e){const n=g(e),t=[];for(const o of n.matchAll(/\b(?:auto-)?gemini-[a-z0-9.-]+\b/gi)){const i=o[0].trim();t.push({id:i,name:i,provider:"google",isDefault:/\bcurrent\b/i.test(n)&&n.includes(i)})}for(const o of n.matchAll(/\bGemini\s*(\d(?:\.\d)?)\s*(Pro|Flash(?:[- ]Lite)?)\s*(Preview)?\b/gi)){const i=o[1]??"",s=(o[2]??"").replace(/\s+/g,"-"),r=!!o[3],a=_(i,s,r);t.push({id:a,name:`Gemini ${i} ${s.replace(/-/g," ")}`.trim(),provider:"google",isDefault:/\bcurrent\b/i.test(n)&&n.includes(o[0]??"")})}for(const o of n.matchAll(/\bAuto\s*Gemini\s*(\d(?:\.\d)?)\b/gi)){const i=o[1]??"",s=`auto-gemini-${i}`;t.push({id:s,name:`Auto Gemini ${i}`,provider:"google",isDefault:/\bcurrent\b/i.test(n)&&n.includes(o[0]??"")})}return d(t)}function X(){return[{id:"gemini-2.5-pro",name:"Gemini 2.5 Pro",provider:"google",isDefault:!0},{id:"gemini-2.5-flash",name:"Gemini 2.5 Flash",provider:"google"},{id:"auto-gemini-2.5",name:"Auto Gemini 2.5",provider:"google"}]}export{G as applyClaudeModelEnvOverrides,V as discoverClaudeAliasModelsFromEnv,q as fallbackClaudeAliasModels,N as fallbackCodexModels,X as fallbackGeminiModels,H as fallbackWorkBuddyModels,A as inferClaudeOverrideProvider,z as parseClaudeBinaryModels,j as parseClaudeModels,W as parseCodexAppServerModels,K as parseCodexModels,I as parseCursorModels,J as parseGeminiModels,U as parseOpenClawModels,B as parseOpenCodeModels,b as readEnvValue,g as stripAnsi};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getAgentConfigSummary as
|
|
1
|
+
import{getAgentConfigSummary as f}from"../config-status.js";import{isCacheFresh as v,readCache as l,writeCache as y}from"./cache.js";import{discoverModelsForAgent as A}from"./discovery.js";import{getAgentRuntimeSummary as g}from"../runtime-compatibility.js";import{resolveManagedAgentRuntimeProtection as C}from"../../security/managed-agent-runtime.js";const S={claude:"claude-alias-v2"};function x(e){const r=new Set,t=[];for(const n of e)!n.id||r.has(n.id)||(r.add(n.id),t.push(n));return t}function h(e){const t=e.type!=="pi"&&e.type!=="openclaw"?C({agentType:e.type,runtimeVersion:e.version,platform:e.runtimePlatform,isWsl:e.runtimeIsWsl,executableFingerprint:e.executableFingerprint,requireExecutableFingerprint:!0}):null;return{supportsManagedAgent:t?.level==="hard"||t?.level==="partial",supportsWorker:e.type!=="pi"&&e.type!=="openclaw",supportsManagerMode:e.type==="codex"||e.type==="claude"||e.type==="pi-coding-agent",...t?{managedAgentProtection:t}:{}}}function F(e){const r=l();return e.map(t=>{const n=f(t.type),s=g(t);return{type:t.type,models:r.agents[t.type]?.models??t.models??[],...h(t),...n?{config:n}:{},...s?{runtime:s}:{}}})}async function b(e,r){const t=l();for(const n of e)delete t.agents[n.type];return y(t),M(e,r)}async function M(e,r){const t=l();let n=!1;const s=[];for(const o of e){const i=t.agents[o.type],a=S[o.type];let c;if(v(i,o.version,a))c=i.models;else{let p=null;try{p=x(await A(o,r)),c=p.length>0?p:i?.models??o.models??[]}catch{c=i?.models??o.models??[]}if(p&&p.length>0){const m={version:o.version,...a?{sourceRevision:a}:{},refreshedAt:Date.now(),models:c};JSON.stringify(i)!==JSON.stringify(m)&&(t.agents[o.type]=m,n=!0)}}const u=f(o.type),d=g(o);s.push({type:o.type,models:c,...h(o),...u?{config:u}:{},...d?{runtime:d}:{}})}return n&&y(t),s}export{F as getCachedAgentInfos,b as refreshAgentInfos,M as resolveAgentInfos};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ManagedAgentRuntimeSecurityDeclaration } from '../security/managed-agent-runtime.js';
|
|
2
|
+
/** Pi's native tool allowlist is useful but is not a process sandbox. The
|
|
3
|
+
* declaration deliberately reports host-wide reachability because Bash can
|
|
4
|
+
* cross filesystem, network, socket and GUI boundaries on every supported
|
|
5
|
+
* platform. Shennian may still apply a narrower authorization ceiling, but the
|
|
6
|
+
* UI must present the gap as partial protection. */
|
|
7
|
+
export declare const PI_CODING_AGENT_MANAGED_RUNTIME_SECURITY: ManagedAgentRuntimeSecurityDeclaration;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const l={minimumRuntimeVersion:"0.85.0",maximumRuntimeVersionExclusive:"0.86.0",platforms:Object.fromEntries(["darwin","linux","wsl","win32"].map(e=>[e,{level:"partial",fileAccess:{"workspace-read":!1,"workspace-write":!1,"host-full":!0},externalCapabilities:{commandNetwork:{allow:!0,deny:!1},webSearch:{allow:!0,deny:!1},browser:{allow:!0,deny:!1},computerUse:{allow:!0,deny:!1},mcp:{allow:!0,deny:!1}},knownGaps:["sandbox.toolAllowlistOnly","shell.hostFilesystemReachable","shell.networkReachable","shell.localSocketsReachable"]}]))};export{l as PI_CODING_AGENT_MANAGED_RUNTIME_SECURITY};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { ChatAttachmentMeta, ExternalChannelSessionStatus } from '@shennian/wire';
|
|
2
|
+
import { AgentAdapter, type AgentSendContext } from './adapter.js';
|
|
3
|
+
import type { CompiledManagedAgentPolicy } from '../security/managed-agent-policy.js';
|
|
4
|
+
export declare class PiCodingAgentAdapter extends AgentAdapter {
|
|
5
|
+
readonly type: "pi-coding-agent";
|
|
6
|
+
private process;
|
|
7
|
+
private rpc;
|
|
8
|
+
private shennianSessionId;
|
|
9
|
+
private workDir;
|
|
10
|
+
private sessionDir;
|
|
11
|
+
private agentSessionId;
|
|
12
|
+
private externalChannel;
|
|
13
|
+
private extraEnv;
|
|
14
|
+
private managedAgentPolicy;
|
|
15
|
+
private runId;
|
|
16
|
+
private seq;
|
|
17
|
+
private active;
|
|
18
|
+
private terminal;
|
|
19
|
+
private stderr;
|
|
20
|
+
private lastUsage;
|
|
21
|
+
private promptFile;
|
|
22
|
+
private modelBroker;
|
|
23
|
+
private persistNativeSession;
|
|
24
|
+
private validationRoot;
|
|
25
|
+
private runPhase;
|
|
26
|
+
configure(options: {
|
|
27
|
+
sessionId?: string;
|
|
28
|
+
externalChannel?: ExternalChannelSessionStatus | null;
|
|
29
|
+
env?: NodeJS.ProcessEnv;
|
|
30
|
+
managedAgentPolicy?: CompiledManagedAgentPolicy | null;
|
|
31
|
+
}): void;
|
|
32
|
+
start(sessionId: string, workDir: string, agentSessionId?: string | null, options?: import('./adapter.js').AgentStartOptions): Promise<void>;
|
|
33
|
+
send(text: string, modelId?: string, reasoningEffort?: string, attachments?: ChatAttachmentMeta[], agentSystemPrompt?: string | null, context?: AgentSendContext): Promise<void>;
|
|
34
|
+
resume(agentSessionId: string): Promise<void>;
|
|
35
|
+
stop(): Promise<void>;
|
|
36
|
+
getStatus(): Promise<{
|
|
37
|
+
active: boolean;
|
|
38
|
+
runId?: string | null;
|
|
39
|
+
runPhase?: 'thinking' | 'tool_running' | 'streaming_text' | 'waiting_approval' | 'waiting_user_input' | null;
|
|
40
|
+
canStop?: boolean;
|
|
41
|
+
}>;
|
|
42
|
+
setTitle(_agentSessionId: string, title: string): Promise<void>;
|
|
43
|
+
private ensureProcess;
|
|
44
|
+
private managedTools;
|
|
45
|
+
private ownsSessionFile;
|
|
46
|
+
private readState;
|
|
47
|
+
private requireRpc;
|
|
48
|
+
private handleRpcEvent;
|
|
49
|
+
private emitEvent;
|
|
50
|
+
private emitTerminal;
|
|
51
|
+
private emitError;
|
|
52
|
+
private prepareHostedModel;
|
|
53
|
+
private stopModelBroker;
|
|
54
|
+
private stopProcess;
|
|
55
|
+
}
|