shennian 0.4.69 → 0.4.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/publish-build-manifest.json +125 -70
- package/dist/src/agent-env.js +4 -4
- package/dist/src/agents/adapter.d.ts +7 -3
- package/dist/src/agents/auth-status.d.ts +4 -0
- package/dist/src/agents/auth-status.js +2 -0
- package/dist/src/agents/codex-protocol.d.ts +103 -0
- package/dist/src/agents/codex-protocol.js +3 -0
- package/dist/src/agents/codex-runtime.d.ts +91 -0
- package/dist/src/agents/codex-runtime.js +14 -0
- package/dist/src/agents/codex.d.ts +15 -91
- package/dist/src/agents/codex.js +2 -17
- package/dist/src/agents/command-spec.js +4 -3
- package/dist/src/agents/detect.js +1 -1
- package/dist/src/agents/manager.d.ts +4 -3
- package/dist/src/agents/manager.js +4 -4
- package/dist/src/agents/opencode.d.ts +4 -0
- package/dist/src/agents/opencode.js +1 -1
- package/dist/src/commands/agent-readiness.d.ts +17 -0
- package/dist/src/commands/agent-readiness.js +2 -0
- package/dist/src/commands/agent.js +2 -2
- package/dist/src/commands/daemon-instance-lock.js +1 -1
- package/dist/src/commands/daemon-process.d.ts +1 -0
- package/dist/src/commands/daemon-process.js +1 -1
- package/dist/src/commands/daemon-service-spec.d.ts +28 -0
- package/dist/src/commands/daemon-service-spec.js +1 -0
- package/dist/src/commands/daemon-start-wait.d.ts +1 -1
- package/dist/src/commands/daemon-start-wait.js +1 -1
- package/dist/src/commands/daemon-state.d.ts +57 -0
- package/dist/src/commands/daemon-state.js +1 -0
- package/dist/src/commands/daemon-windows.d.ts +8 -0
- package/dist/src/commands/daemon-windows.js +10 -10
- package/dist/src/commands/daemon.d.ts +4 -64
- package/dist/src/commands/daemon.js +13 -13
- package/dist/src/commands/upgrade.js +1 -1
- package/dist/src/daemon-ipc/agent-readiness.d.ts +14 -0
- package/dist/src/daemon-ipc/agent-readiness.js +1 -0
- package/dist/src/daemon-ipc/control.d.ts +1 -1
- package/dist/src/daemon-ipc/control.js +1 -1
- package/dist/src/index.js +3 -3
- package/dist/src/native-fusion/local-repository.d.ts +6 -1
- package/dist/src/native-fusion/local-repository.js +2 -2
- package/dist/src/native-fusion/service.d.ts +2 -0
- package/dist/src/native-fusion/service.js +2 -2
- package/dist/src/native-fusion/source-visibility-audit.d.ts +16 -0
- package/dist/src/native-fusion/source-visibility-audit.js +1 -0
- package/dist/src/native-fusion/source-visibility.d.ts +25 -0
- package/dist/src/native-fusion/source-visibility.js +1 -0
- package/dist/src/native-fusion/state.d.ts +1 -0
- package/dist/src/native-fusion/state.js +2 -2
- package/dist/src/native-fusion/types.d.ts +5 -0
- package/dist/src/room/managed-room-binding.d.ts +2 -0
- package/dist/src/room/managed-room-binding.js +1 -1
- package/dist/src/room/room-binding-client.d.ts +1 -0
- package/dist/src/room/room-binding-client.js +1 -1
- package/dist/src/runtime-distribution.d.ts +13 -0
- package/dist/src/runtime-distribution.js +1 -0
- package/dist/src/security/managed-agent-policy.d.ts +7 -0
- package/dist/src/security/managed-agent-policy.js +1 -1
- package/dist/src/session/handlers/agent-workspace-validation.d.ts +1 -0
- package/dist/src/session/handlers/agent-workspace-validation.js +1 -1
- package/dist/src/session/handlers/agents.d.ts +7 -1
- package/dist/src/session/handlers/agents.js +1 -1
- package/dist/src/session/handlers/chat-context.d.ts +31 -0
- package/dist/src/session/handlers/chat-context.js +1 -0
- package/dist/src/session/handlers/chat-events.d.ts +1 -1
- package/dist/src/session/handlers/chat-events.js +2 -2
- package/dist/src/session/handlers/chat-session-lifecycle.d.ts +2 -2
- package/dist/src/session/handlers/chat-session-lifecycle.js +1 -1
- package/dist/src/session/handlers/chat.d.ts +3 -29
- package/dist/src/session/handlers/chat.js +1 -1
- package/dist/src/session/manager.js +2 -2
- package/dist/src/session/queue-helpers.js +2 -2
- package/dist/src/session/queue-message.d.ts +2 -0
- package/dist/src/session/queue.d.ts +7 -1
- package/dist/src/session/queue.js +1 -1
- package/dist/src/session/queued-chat-dispatch.d.ts +4 -1
- package/dist/src/session/queued-chat-dispatch.js +1 -1
- package/dist/src/session/store.d.ts +4 -2
- package/dist/src/session/store.js +2 -2
- package/dist/src/session/types.d.ts +1 -0
- package/dist/src/upgrade/engine.js +2 -2
- package/dist/src/upgrade/scheduler.js +1 -1
- package/dist/src/upgrade/updater-launcher.js +3 -3
- package/node_modules/@shennian/wire/dist/room.d.ts +2 -0
- package/node_modules/@shennian/wire/dist/session-sync.d.ts +2 -1
- package/node_modules/@shennian/wire/dist/session.d.ts +19 -1
- package/node_modules/@shennian/wire/dist/session.js +8 -0
- package/package.json +1 -1
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { ChatAttachmentMeta, ExternalChannelSessionStatus } from '@shennian/wire';
|
|
2
|
+
import type { ChildProcess } from 'node:child_process';
|
|
3
|
+
import type { ManagedRoomExecutor } from '../room/managed-room-ipc.js';
|
|
4
|
+
import type { CompiledManagedAgentPolicy } from '../security/managed-agent-policy.js';
|
|
5
|
+
import { AgentAdapter, type AgentEvent } from './adapter.js';
|
|
6
|
+
import type { CodexManagedPermissionConfig } from './codex-managed-permissions.js';
|
|
7
|
+
import { CodexManagedRoomToolBinding } from './codex-managed-room-tools.js';
|
|
8
|
+
import type { CodexItem, CodexStreamEvent, CodexThreadStatus, JsonRpcMessage, ManagedTurnReplay, PendingRequest } from './codex-protocol.js';
|
|
9
|
+
export declare abstract class CodexRuntime extends AgentAdapter {
|
|
10
|
+
protected readonly options: {
|
|
11
|
+
modelInstructionsFile?: string;
|
|
12
|
+
hidden?: boolean;
|
|
13
|
+
isThreadTailInterrupted?: (threadId: string) => boolean;
|
|
14
|
+
};
|
|
15
|
+
protected process: ChildProcess | null;
|
|
16
|
+
protected workDir: string | null;
|
|
17
|
+
protected seq: number;
|
|
18
|
+
protected runId: string;
|
|
19
|
+
protected pendingUsage: AgentEvent['usage'] | undefined;
|
|
20
|
+
protected agentSessionId: string | null;
|
|
21
|
+
protected hasEmittedText: boolean;
|
|
22
|
+
protected textTail: string;
|
|
23
|
+
protected terminalState: 'open' | 'final' | 'error';
|
|
24
|
+
protected forceCloseTimer: NodeJS.Timeout | null;
|
|
25
|
+
protected stderrBuf: string;
|
|
26
|
+
protected rpcSeq: number;
|
|
27
|
+
protected pendingRequests: Map<number, PendingRequest>;
|
|
28
|
+
protected appServerReady: Promise<void> | null;
|
|
29
|
+
protected appServerStartupError: Error | null;
|
|
30
|
+
protected activeTurnId: string | null;
|
|
31
|
+
protected deltaItemIds: Set<string>;
|
|
32
|
+
protected lastTransientStatus: string;
|
|
33
|
+
protected agentSystemPrompt: string;
|
|
34
|
+
protected managedAgentPolicy: CompiledManagedAgentPolicy | null;
|
|
35
|
+
protected managedPermissionConfig: CodexManagedPermissionConfig | null;
|
|
36
|
+
protected configurationRestartRequired: boolean;
|
|
37
|
+
protected readonly managedRoomTools: CodexManagedRoomToolBinding;
|
|
38
|
+
protected configuredManagedRoomContextToken: string | null;
|
|
39
|
+
protected configuredManagedRoomExecutor: ManagedRoomExecutor | null;
|
|
40
|
+
protected managedRoomToolThreadId: string | null;
|
|
41
|
+
protected managedRoomCapabilityExpectedForTurn: boolean;
|
|
42
|
+
protected managedRoomTurnBindingFailed: boolean;
|
|
43
|
+
protected preparedExternalOwnerThreadId: string | null;
|
|
44
|
+
protected managedTurnReplay: ManagedTurnReplay | null;
|
|
45
|
+
protected managedAsyncRecovery: Promise<void> | null;
|
|
46
|
+
protected persistNativeSession: boolean;
|
|
47
|
+
protected nativeSessionVisibility: 'user' | 'internal';
|
|
48
|
+
constructor(options?: {
|
|
49
|
+
modelInstructionsFile?: string;
|
|
50
|
+
hidden?: boolean;
|
|
51
|
+
isThreadTailInterrupted?: (threadId: string) => boolean;
|
|
52
|
+
});
|
|
53
|
+
protected externalChannel: ExternalChannelSessionStatus | null;
|
|
54
|
+
protected shennianSessionId: string | null;
|
|
55
|
+
protected extraEnv: NodeJS.ProcessEnv;
|
|
56
|
+
protected abstract ensureAppServer(modelId?: string): Promise<void>;
|
|
57
|
+
protected abstract logManagedThreadLifecycle(event: string, details: Record<string, unknown>): void;
|
|
58
|
+
protected abstract startFreshManagedTurnWithReadinessRetry(threadId: string, text: string, modelId?: string, reasoningEffort?: string, attachments?: ChatAttachmentMeta[]): Promise<{
|
|
59
|
+
turn?: {
|
|
60
|
+
id?: string;
|
|
61
|
+
};
|
|
62
|
+
}>;
|
|
63
|
+
protected sendRpc(method: string, params: unknown, timeoutMs?: number): Promise<unknown>;
|
|
64
|
+
protected handleAppServerMessage(msg: JsonRpcMessage): void;
|
|
65
|
+
protected scheduleManagedAsyncRolloutRecovery(message: string): boolean;
|
|
66
|
+
protected recoverManagedTurnAfterAsyncRolloutFailure(): Promise<void>;
|
|
67
|
+
protected handleManagedRoomToolCall(id: number | string, params: Record<string, unknown>): Promise<void>;
|
|
68
|
+
protected writeAppServerResponse(id: number | string, result: unknown): void;
|
|
69
|
+
protected mapThreadStatusToRunPhase(status: CodexThreadStatus | null): 'thinking' | 'waiting_approval' | 'waiting_user_input';
|
|
70
|
+
protected handleAppServerNonJsonStdout(line: string): void;
|
|
71
|
+
protected failAppServerStartup(error: Error): void;
|
|
72
|
+
protected handleAppServerCompletedItem(params: Record<string, unknown>): void;
|
|
73
|
+
protected handleAppServerUsage(params: Record<string, unknown>): void;
|
|
74
|
+
protected handleCodexItemLine(obj: CodexStreamEvent): void;
|
|
75
|
+
protected handleStreamEvent(obj: CodexStreamEvent): void;
|
|
76
|
+
protected emitEvent(partial: Omit<AgentEvent, 'runId' | 'seq'>): void;
|
|
77
|
+
protected isApprovalLikeName(name: unknown): boolean;
|
|
78
|
+
protected emitApprovalPending(source: Record<string, unknown> | CodexItem): void;
|
|
79
|
+
protected killProcess(preserveConfiguredManagedRoomContext?: boolean): Promise<void>;
|
|
80
|
+
protected rejectAllPending(error: Error): void;
|
|
81
|
+
protected handleProcessClose(code: number | null, stderrBuf: string): void;
|
|
82
|
+
protected emitFinalIfOpen(): void;
|
|
83
|
+
protected emitErrorIfOpen(message: string): void;
|
|
84
|
+
protected resetRunState(): void;
|
|
85
|
+
protected clearConfiguredManagedRoomContext(): void;
|
|
86
|
+
protected emitTransientStatus(message: string): void;
|
|
87
|
+
protected resetTextState(): void;
|
|
88
|
+
protected emitText(text: string, mode?: 'delta' | 'block'): void;
|
|
89
|
+
protected scheduleProcessClose(): void;
|
|
90
|
+
protected clearForceCloseTimer(): void;
|
|
91
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import{AgentAdapter as h}from"./adapter.js";import{CodexManagedRoomToolBinding as g}from"./codex-managed-room-tools.js";import{extractAppServerErrorMessage as c,formatCodexErrorMessage as f,formatTransientCodexStatus as T,isCodexCollabAgentItem as y,isCodexCollabAgentToolName as o,isCodexLegacyCollabAgentItem as v,isMissingCodexRolloutError as m,isTransientCodexErrorMessage as x,looksLikeCodexInteractiveAuthPrompt as I,looksLikeFatalCodexStderr as R,normalizeCodexStderr as S,normalizeTerminalText as k,safeStringify as p,stripGitDirectiveArtifacts as C}from"./codex-utils.js";class q extends h{options;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 g;configuredManagedRoomContextToken=null;configuredManagedRoomExecutor=null;managedRoomToolThreadId=null;managedRoomCapabilityExpectedForTurn=!1;managedRoomTurnBindingFailed=!1;preparedExternalOwnerThreadId=null;managedTurnReplay=null;managedAsyncRecovery=null;persistNativeSession=!0;nativeSessionVisibility="user";constructor(e={}){super(),this.options=e}externalChannel=null;shennianSessionId=null;extraEnv={};sendRpc(e,t,n=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 r=this.rpcSeq++,i=JSON.stringify({id:r,method:e,params:t});return new Promise((a,l)=>{const d=setTimeout(()=>{this.pendingRequests.delete(r),l(new Error(`codex app-server request timed out: ${e}`))},n);this.pendingRequests.set(r,{resolve:a,reject:l,timer:d}),s.stdin.write(`${i}
|
|
2
|
+
`,u=>{u&&(clearTimeout(d),this.pendingRequests.delete(r),l(u))})})}handleAppServerMessage(e){if(e.method==="item/tool/call"&&e.id!=null){this.handleManagedRoomToolCall(e.id,e.params??{});return}if(e.id!=null){const n=typeof e.id=="number"?this.pendingRequests.get(e.id):void 0;n&&(clearTimeout(n.timer),this.pendingRequests.delete(e.id),e.error?n.reject(new Error(e.error.message||`codex app-server error ${e.error.code??""}`.trim())):n.resolve(e.result))}if(!e.method)return;const t=e.params??{};switch(e.method){case"turn/started":{const n=typeof t.turn=="object"&&t.turn!==null?t.turn:null,s=typeof n?.id=="string"?n.id:null,r=typeof t.threadId=="string"?t.threadId:"";s&&(this.activeTurnId=s,this.managedRoomCapabilityExpectedForTurn&&this.managedRoomToolThreadId===r&&!this.managedRoomTools.bindTurn(r,s)&&(this.managedRoomTurnBindingFailed=!0,this.emitErrorIfOpen("codex_managed_room_turn_binding_failed")));break}case"thread/status/changed":{const n=typeof t.threadId=="string"?t.threadId:"";if(n&&this.agentSessionId&&n!==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 n=typeof t.itemId=="string"?t.itemId:"";n&&this.deltaItemIds.add(n),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 n=typeof t.turn=="object"&&t.turn!==null?t.turn:null,s=typeof n?.id=="string"?n.id:null;(!this.activeTurnId||s===this.activeTurnId)&&(this.activeTurnId=null,this.managedRoomTools.deactivateTurn(),this.emitFinalIfOpen());break}case"turn/failed":{const n=c(t);if(this.scheduleManagedAsyncRolloutRecovery(n))return;this.emitErrorIfOpen(n||"turn failed");break}case"error":{const n=c(t);if(x(n)){this.emitTransientStatus(n);return}if(this.scheduleManagedAsyncRolloutRecovery(n))return;this.emitErrorIfOpen(n);break}}}scheduleManagedAsyncRolloutRecovery(e){if(!this.managedAgentPolicy&&!this.managedPermissionConfig||!this.managedTurnReplay||!m(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(n=>{const s=m(n)?"no rollout found after managed thread recovery":n instanceof Error?n.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 n=this.agentSessionId;if(!n)throw new Error("codex app-server did not recreate the managed thread");this.logManagedThreadLifecycle("thread.recreated-async",{previousThreadId:t,threadId:n,recoveryCount:e.recoveryCount}),this.emitEvent({state:"start",agentSessionId:n});const s=await this.startFreshManagedTurnWithReadinessRetry(n,e.text,e.modelId,e.reasoningEffort,e.attachments);if(this.activeTurnId=s.turn?.id??null,this.managedRoomTurnBindingFailed)throw new Error("codex_managed_room_turn_binding_failed");if(this.managedRoomCapabilityExpectedForTurn&&this.managedRoomToolThreadId===n&&this.activeTurnId&&!this.managedRoomTools.bindTurn(n,this.activeTurnId))throw new Error("codex_managed_room_turn_binding_failed")}async handleManagedRoomToolCall(e,t){const n=await this.managedRoomTools.execute(t);if(this.writeAppServerResponse(e,n),n.success&&t.tool==="shennian_room_send"){const s=typeof t.arguments=="object"&&t.arguments!==null?t.arguments:null,r=typeof s?.text=="string"?s.text.trim():"";r&&this.emitText(r,"block")}}writeAppServerResponse(e,t){const n=this.process;n?.stdin&&n.stdin.write(`${JSON.stringify({id:e,result:t})}
|
|
3
|
+
`)}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=k(e);I(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")&&!y(t))switch(t.type){case"agentMessage":{const n=typeof t.id=="string"?t.id:"";if(n&&this.deltaItemIds.has(n))return;typeof t.text=="string"&&this.emitText(t.text,"block");break}case"commandExecution":{const n=typeof t.command=="string"?t.command:"",s=typeof t.aggregatedOutput=="string"?t.aggregatedOutput:"";n&&this.emitEvent({state:"tool-call",name:"command_execution",args:{command:n}}),this.emitEvent({state:"tool-result",name:"command_execution",result:[s,t.exitCode!=null?`
|
|
4
|
+
(exit ${t.exitCode})`:""].join("").trim()});break}case"mcpToolCall":case"dynamicToolCall":{const n=typeof t.tool=="string"?t.tool:t.type;if(o(n))return;const s=typeof t.arguments=="object"&&t.arguments!==null?t.arguments:{};this.emitEvent({state:"tool-call",name:n,args:s}),this.emitEvent({state:"tool-result",name:n,result:p(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,n=typeof t?.last=="object"&&t.last!==null?t.last:null,s=typeof t?.total=="object"&&t.total!==null?t.total:null,r=n??s;if(!r)return;const i=typeof r.inputTokens=="number"?r.inputTokens:void 0,a=typeof r.outputTokens=="number"?r.outputTokens:void 0;(i!=null||a!=null)&&(this.pendingUsage={inputTokens:i??0,outputTokens:a??0})}handleCodexItemLine(e){const t=e.item;if(t?.type&&!v(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 n=[t.aggregated_output??"",t.exit_code!=null?`
|
|
5
|
+
(exit ${t.exit_code})`:""];this.emitEvent({state:"tool-result",name:"command_execution",result:n.join("").trim()||String(t.status??"")})}break}case"mcp_tool_call":{if(t.tool&&o(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 n=t.error&&typeof t.error=="object"?t.error.message:void 0;this.emitEvent({state:"tool-result",name:t.tool??"mcp_tool",result:n??p(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 n=t.items.map(s=>`- [${s.completed?"x":" "}] ${s.text}`).join(`
|
|
6
|
+
`);this.emitText(n,"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 r=s.input_tokens??s.prompt_tokens,i=s.output_tokens??s.completion_tokens;(r!=null||i!=null)&&(this.pendingUsage={inputTokens:r??0,outputTokens:i??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&&o(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&&o(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:"",n=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:n,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(n=>{t.on("close",n),setTimeout(()=>{t.kill("SIGKILL"),n()},3e3)}),this.rejectAllPending(new Error("codex app-server stopped"))}rejectAllPending(e){for(const[t,n]of this.pendingRequests.entries())clearTimeout(n.timer),n.reject(e),this.pendingRequests.delete(t)}handleProcessClose(e,t){const n=S(t);if(e!==0&&e!==null){const s=n||`codex exited with code ${e}`;this.emitErrorIfOpen(s)}else R(n)?this.emitErrorIfOpen(n):this.emitFinalIfOpen();this.pendingUsage=void 0}emitFinalIfOpen(){this.terminalState==="open"&&(this.terminalState="final",this.managedTurnReplay=null,this.managedRoomCapabilityExpectedForTurn=!1,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.managedRoomCapabilityExpectedForTurn=!1,this.managedRoomTools.deactivateTurn(),this.clearConfiguredManagedRoomContext(),this.emitEvent({state:"error",message:f(e)}),this.scheduleProcessClose())}resetRunState(){this.pendingUsage=void 0,this.terminalState="open",this.managedRoomTurnBindingFailed=!1,this.deltaItemIds.clear(),this.lastTransientStatus="",this.clearForceCloseTimer(),this.resetTextState()}clearConfiguredManagedRoomContext(){this.configuredManagedRoomContextToken=null,this.configuredManagedRoomExecutor=null}emitTransientStatus(e){const t=T(e);!t||t===this.lastTransientStatus||this.terminalState!=="open"||(this.lastTransientStatus=t,this.emitEvent({state:"delta",text:`${t}
|
|
7
|
+
`,thinking:!0}))}resetTextState(){this.hasEmittedText=!1,this.textTail=""}emitText(e,t="delta"){if(!e)return;let n=C(e);n&&(t==="block"&&this.hasEmittedText&&!n.startsWith(`
|
|
8
|
+
`)&&(this.textTail.endsWith(`
|
|
9
|
+
`)?n=`
|
|
10
|
+
${n}`:this.textTail.endsWith(`
|
|
11
|
+
|
|
12
|
+
`)||(n=`
|
|
13
|
+
|
|
14
|
+
${n}`)),this.hasEmittedText=!0,this.textTail=(this.textTail+n).slice(-4),this.emitEvent({state:"delta",text:n}))}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)}}export{q as CodexRuntime};
|
|
@@ -1,24 +1,12 @@
|
|
|
1
|
-
import { AgentAdapter, type AgentActiveInput, type AgentSendContext, type AgentSendResult, type AgentStartOptions } from './adapter.js';
|
|
2
|
-
import { type ChatAttachmentMeta, type ExternalChannelSessionStatus } from '@shennian/wire';
|
|
3
1
|
import type { SessionRunPhase } from '@shennian/wire';
|
|
4
|
-
import { type
|
|
2
|
+
import { type ChatAttachmentMeta, type ExternalChannelSessionStatus } from '@shennian/wire';
|
|
5
3
|
import type { ManagedRoomExecutor } from '../room/managed-room-ipc.js';
|
|
4
|
+
import { type CompiledManagedAgentPolicy } from '../security/managed-agent-policy.js';
|
|
5
|
+
import { type AgentActiveInput, type AgentSendContext, type AgentSendResult, type AgentStartOptions } from './adapter.js';
|
|
6
|
+
export { buildCodexQueueArgs, buildCodexQueuedText, isCodexActiveWriterError, isCodexExcludeTurnsUnsupportedError, isCodexPaginatedHistoryUnsupportedError, isCodexProjectApiUnsupportedError, selectCodexProjectIdForWorkDir, } from './codex-protocol.js';
|
|
6
7
|
export { isCodexUnsupportedEffortError, isMissingCodexRolloutError, normalizeCodexModelId, normalizeCodexReasoningEffort, } from './codex-utils.js';
|
|
7
|
-
|
|
8
|
-
export declare
|
|
9
|
-
export declare function isCodexExcludeTurnsUnsupportedError(error: unknown): boolean;
|
|
10
|
-
export declare function isCodexProjectApiUnsupportedError(error: unknown): boolean;
|
|
11
|
-
type CodexProject = {
|
|
12
|
-
id?: string;
|
|
13
|
-
roots?: Array<{
|
|
14
|
-
path?: string;
|
|
15
|
-
}>;
|
|
16
|
-
};
|
|
17
|
-
export declare function selectCodexProjectIdForWorkDir(projects: CodexProject[], workDir: string): string | undefined;
|
|
18
|
-
export declare function buildCodexQueuedText(text: string, attachments?: ChatAttachmentMeta[]): string;
|
|
19
|
-
export declare function buildCodexQueueArgs(threadId: string, text: string, attachments?: ChatAttachmentMeta[]): string[];
|
|
20
|
-
export declare class CodexAdapter extends AgentAdapter {
|
|
21
|
-
private readonly options;
|
|
8
|
+
import { CodexRuntime } from './codex-runtime.js';
|
|
9
|
+
export declare class CodexAdapter extends CodexRuntime {
|
|
22
10
|
get supportsActiveInput(): boolean;
|
|
23
11
|
injectActiveInput(input: AgentActiveInput): Promise<void>;
|
|
24
12
|
readonly type: "codex";
|
|
@@ -28,47 +16,6 @@ export declare class CodexAdapter extends AgentAdapter {
|
|
|
28
16
|
resumeRun: boolean;
|
|
29
17
|
resumeSession: boolean;
|
|
30
18
|
};
|
|
31
|
-
private process;
|
|
32
|
-
private workDir;
|
|
33
|
-
private seq;
|
|
34
|
-
private runId;
|
|
35
|
-
private pendingUsage;
|
|
36
|
-
private agentSessionId;
|
|
37
|
-
private hasEmittedText;
|
|
38
|
-
private textTail;
|
|
39
|
-
private terminalState;
|
|
40
|
-
private forceCloseTimer;
|
|
41
|
-
private stderrBuf;
|
|
42
|
-
private rpcSeq;
|
|
43
|
-
private pendingRequests;
|
|
44
|
-
private appServerReady;
|
|
45
|
-
private appServerStartupError;
|
|
46
|
-
private activeTurnId;
|
|
47
|
-
private deltaItemIds;
|
|
48
|
-
private lastTransientStatus;
|
|
49
|
-
private agentSystemPrompt;
|
|
50
|
-
private managedAgentPolicy;
|
|
51
|
-
private managedPermissionConfig;
|
|
52
|
-
private configurationRestartRequired;
|
|
53
|
-
private readonly managedRoomTools;
|
|
54
|
-
private configuredManagedRoomContextToken;
|
|
55
|
-
private configuredManagedRoomExecutor;
|
|
56
|
-
private managedRoomToolThreadId;
|
|
57
|
-
private managedRoomCapabilityExpectedForTurn;
|
|
58
|
-
private managedRoomTurnBindingFailed;
|
|
59
|
-
private preparedExternalOwnerThreadId;
|
|
60
|
-
private managedTurnReplay;
|
|
61
|
-
private managedAsyncRecovery;
|
|
62
|
-
private persistNativeSession;
|
|
63
|
-
private nativeSessionVisibility;
|
|
64
|
-
constructor(options?: {
|
|
65
|
-
modelInstructionsFile?: string;
|
|
66
|
-
hidden?: boolean;
|
|
67
|
-
isThreadTailInterrupted?: (threadId: string) => boolean;
|
|
68
|
-
});
|
|
69
|
-
private externalChannel;
|
|
70
|
-
private shennianSessionId;
|
|
71
|
-
private extraEnv;
|
|
72
19
|
configure(options: {
|
|
73
20
|
sessionId?: string;
|
|
74
21
|
externalChannel?: ExternalChannelSessionStatus | null;
|
|
@@ -79,7 +26,7 @@ export declare class CodexAdapter extends AgentAdapter {
|
|
|
79
26
|
}): void;
|
|
80
27
|
private configurationFingerprint;
|
|
81
28
|
private buildProcessEnv;
|
|
82
|
-
start(
|
|
29
|
+
start(sessionId: string, workDir: string, agentSessionId?: string | null, options?: AgentStartOptions): Promise<void>;
|
|
83
30
|
prepareSend(_text: string, modelId?: string, _reasoningEffort?: string, _attachments?: ChatAttachmentMeta[], agentSystemPrompt?: string | null, context?: AgentSendContext): Promise<void>;
|
|
84
31
|
send(text: string, modelId?: string, reasoningEffort?: string, attachments?: ChatAttachmentMeta[], agentSystemPrompt?: string | null, context?: AgentSendContext): Promise<void | AgentSendResult>;
|
|
85
32
|
private isThreadTailInterrupted;
|
|
@@ -95,41 +42,18 @@ export declare class CodexAdapter extends AgentAdapter {
|
|
|
95
42
|
}>;
|
|
96
43
|
private spawnCodex;
|
|
97
44
|
private spawnAppServer;
|
|
98
|
-
|
|
45
|
+
protected ensureAppServer(modelId?: string): Promise<void>;
|
|
99
46
|
private initializeAppServer;
|
|
47
|
+
private notifyNativeSession;
|
|
100
48
|
private buildManagedPermissionConfig;
|
|
101
49
|
private resolveCodexProjectId;
|
|
102
50
|
private startTurnWithRecovery;
|
|
103
|
-
|
|
104
|
-
|
|
51
|
+
protected startFreshManagedTurnWithReadinessRetry(threadId: string, text: string, codexModelId?: string, reasoningEffort?: string, attachments?: ChatAttachmentMeta[]): Promise<{
|
|
52
|
+
turn?: {
|
|
53
|
+
id?: string;
|
|
54
|
+
};
|
|
55
|
+
}>;
|
|
56
|
+
protected logManagedThreadLifecycle(event: string, details: Record<string, unknown>): void;
|
|
105
57
|
private startTurn;
|
|
106
58
|
private interruptActiveTurn;
|
|
107
|
-
private sendRpc;
|
|
108
|
-
private handleAppServerMessage;
|
|
109
|
-
private scheduleManagedAsyncRolloutRecovery;
|
|
110
|
-
private recoverManagedTurnAfterAsyncRolloutFailure;
|
|
111
|
-
private handleManagedRoomToolCall;
|
|
112
|
-
private writeAppServerResponse;
|
|
113
|
-
private mapThreadStatusToRunPhase;
|
|
114
|
-
private handleAppServerNonJsonStdout;
|
|
115
|
-
private failAppServerStartup;
|
|
116
|
-
private handleAppServerCompletedItem;
|
|
117
|
-
private handleAppServerUsage;
|
|
118
|
-
private handleCodexItemLine;
|
|
119
|
-
private handleStreamEvent;
|
|
120
|
-
private emitEvent;
|
|
121
|
-
private isApprovalLikeName;
|
|
122
|
-
private emitApprovalPending;
|
|
123
|
-
private killProcess;
|
|
124
|
-
private rejectAllPending;
|
|
125
|
-
private handleProcessClose;
|
|
126
|
-
private emitFinalIfOpen;
|
|
127
|
-
private emitErrorIfOpen;
|
|
128
|
-
private resetRunState;
|
|
129
|
-
private clearConfiguredManagedRoomContext;
|
|
130
|
-
private emitTransientStatus;
|
|
131
|
-
private resetTextState;
|
|
132
|
-
private emitText;
|
|
133
|
-
private scheduleProcessClose;
|
|
134
|
-
private clearForceCloseTimer;
|
|
135
59
|
}
|
package/dist/src/agents/codex.js
CHANGED
|
@@ -1,17 +1,2 @@
|
|
|
1
|
-
import{
|
|
2
|
-
`)}function fe(o,e){const t=e?.filter(n=>n.path&&!/^https?:\/\//i.test(n.path)&&!o.includes(n.path));if(!t?.length)return o;const r=t.map((n,i)=>{const s=b(n.name||`attachment-${i+1}`);return n.kind==="image"?``:`[${s}](<${n.path}>)`});return[o,"",...r].join(`
|
|
3
|
-
`)}function ye(o,e,t){return["queue","--thread",o,"--message",fe(e,t)]}function b(o){return o.replace(/[[\]\\]/g,"\\$&")}class ve extends F{options;get supportsActiveInput(){return!0}async injectActiveInput(e){const t=this.agentSessionId,r=this.activeTurnId;if(!t||!r||!this.process)throw new Error("codex_active_turn_unavailable");const n=await this.sendRpc("turn/steer",{threadId:t,expectedTurnId:r,input:[M(e.text,e.attachments)],...e.clientMessageId?{clientUserMessageId:e.clientMessageId}:{}});if(n.turnId&&n.turnId!==r)throw new Error("codex_active_turn_changed")}type="codex";get recoveryCapabilities(){return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!0}}process=null;workDir=null;seq=0;runId="";pendingUsage;agentSessionId=null;hasEmittedText=!1;textTail="";terminalState="open";forceCloseTimer=null;stderrBuf="";rpcSeq=1;pendingRequests=new Map;appServerReady=null;appServerStartupError=null;activeTurnId=null;deltaItemIds=new Set;lastTransientStatus="";agentSystemPrompt="";managedAgentPolicy=null;managedPermissionConfig=null;configurationRestartRequired=!1;managedRoomTools=new V;configuredManagedRoomContextToken=null;configuredManagedRoomExecutor=null;managedRoomToolThreadId=null;managedRoomCapabilityExpectedForTurn=!1;managedRoomTurnBindingFailed=!1;preparedExternalOwnerThreadId=null;managedTurnReplay=null;managedAsyncRecovery=null;persistNativeSession=!0;nativeSessionVisibility="user";constructor(e={}){super(),this.options=e}externalChannel=null;shennianSessionId=null;extraEnv={};configure(e){const t=this.configurationFingerprint();this.shennianSessionId=e.sessionId??null,this.externalChannel=e.externalChannel??null,this.extraEnv=e.env??{},"managedAgentPolicy"in e&&(this.managedAgentPolicy=e.managedAgentPolicy??null),("managedRoomContextToken"in e||"managedRoomExecutor"in e)&&(this.managedRoomTools.deactivateTurn(),this.configuredManagedRoomContextToken=e.managedRoomContextToken?.trim()||null,this.configuredManagedRoomExecutor=e.managedRoomExecutor??null),this.managedAgentPolicy&&(this.workDir=this.managedAgentPolicy.adapterPolicy.workDir);const r=this.configurationFingerprint();t!==r&&this.process&&(this.configurationRestartRequired=!0)}configurationFingerprint(){const e=Object.keys(this.extraEnv).sort().map(t=>[t,this.extraEnv[t]??null]);return S("sha256").update(JSON.stringify({sessionId:this.shennianSessionId,externalChannel:this.externalChannel,env:e,managedAgentPolicy:this.managedAgentPolicy})).digest("hex")}buildProcessEnv(e={}){if(!this.managedAgentPolicy)return L({...e,...this.extraEnv});if(R(this.managedAgentPolicy))return U({...e,...this.extraEnv});const t=Object.fromEntries(Object.entries(this.extraEnv).filter(([r])=>r!=="SHENNIAN_MANAGED_ROOM_CONTEXT"&&r!=="SHENNIAN_MANAGED_ROOM_IPC_ROOT"));return $({agentType:"codex",providerEnv:t,sessionEnv:t,runtimeEnv:e})}async start(e,t,r,n){this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??t,this.seq=0,this.persistNativeSession=n?.persistNativeSession!==!1,this.nativeSessionVisibility=n?.nativeSessionVisibility??"user",r&&(this.agentSessionId=r)}async prepareSend(e,t,r,n,i,s){const a=i?.trim()??"";if(a!==this.agentSystemPrompt&&(this.agentSystemPrompt=a,this.process&&await this.killProcess(!0)),!(!this.agentSessionId||this.activeTurnId)){this.preparedExternalOwnerThreadId=null;try{await this.ensureAppServer(I(t))}catch(d){if(!P(d))throw d;if(s?.source==="room_activation"||s?.source==="managed_private")throw new Error("codex_managed_thread_owned_externally",{cause:d});if(this.isThreadTailInterrupted(this.agentSessionId))throw new Error(E,{cause:d});this.preparedExternalOwnerThreadId=this.agentSessionId}}}async send(e,t,r,n,i,s){if((s?.source==="room_activation"||s?.source==="managed_private")&&!this.managedAgentPolicy)throw new Error("managed_agent_policy_missing");if((s?.source==="room_activation"||s?.source==="managed_private")&&(!this.configuredManagedRoomContextToken||!this.configuredManagedRoomExecutor))throw new Error("codex_managed_room_tool_context_unavailable");const a=s?.source==="room_activation"||s?.source==="managed_private";this.managedRoomCapabilityExpectedForTurn=!1,this.activeTurnId&&(await this.interruptActiveTurn().catch(()=>{}),await this.killProcess(!0)),this.configurationRestartRequired&&this.process&&await this.killProcess(!0),this.configurationRestartRequired=!1;const d=I(t),l=oe(r),c=i?.trim()??"";if(c!==this.agentSystemPrompt&&(this.agentSystemPrompt=c,this.process&&await this.killProcess(!0)),(s?.source==="room_activation"||s?.source==="managed_private")&&this.managedRoomTools.configure(this.configuredManagedRoomContextToken,this.configuredManagedRoomExecutor),this.runId=N(),this.seq=0,this.resetRunState(),this.agentSessionId&&this.preparedExternalOwnerThreadId===this.agentSessionId)return this.preparedExternalOwnerThreadId=null,{deliveryMode:"external_owner_queue",queuedSubmissionId:await this.enqueueForExternalOwner(this.agentSessionId,e,n)};this.managedRoomCapabilityExpectedForTurn=a;try{await this.ensureAppServer(d)}catch(u){if(!this.agentSessionId||!P(u))throw u;if(s?.source==="room_activation"||s?.source==="managed_private")throw new Error("codex_managed_thread_owned_externally",{cause:u});if(this.isThreadTailInterrupted(this.agentSessionId))throw new Error(E,{cause:u});return{deliveryMode:"external_owner_queue",queuedSubmissionId:await this.enqueueForExternalOwner(this.agentSessionId,e,n)}}const h=this.agentSessionId;if(!h)throw new Error("codex app-server did not create a thread");this.emitEvent({state:"start",agentSessionId:h}),this.managedTurnReplay=this.managedPermissionConfig?{text:e,modelId:d,reasoningEffort:l,attachments:n,recoveryCount:0}:null;const m=await this.startTurnWithRecovery(h,e,d,l,n),g=this.agentSessionId??h;if(this.activeTurnId=m.turn?.id??null,this.managedRoomTurnBindingFailed)throw await this.killProcess(),new Error("codex_managed_room_turn_binding_failed");if(this.managedRoomCapabilityExpectedForTurn&&this.managedRoomToolThreadId===g&&this.activeTurnId&&!this.managedRoomTools.bindTurn(g,this.activeTurnId))throw await this.killProcess(),new Error("codex_managed_room_turn_binding_failed");return{deliveryMode:"direct"}}isThreadTailInterrupted(e){return this.options.isThreadTailInterrupted?.(e)??B(e)}async enqueueForExternalOwner(e,t,r){const n=T("codex");if(!n)throw new Error('Command "codex" not found. Is OpenAI Codex CLI installed?');const i=ye(e,t,r),s=x(n,i,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:this.buildProcessEnv({NO_COLOR:"1"})});return await new Promise((a,d)=>{let l="",c="",h=!1;const m=(u,f)=>{h||(h=!0,clearTimeout(g),u?d(u):a(f))},g=setTimeout(()=>{s.kill("SIGTERM"),m(new Error("Codex Desktop message queue timed out"))},6e4);g.unref?.(),s.stdout?.on("data",u=>{l+=u.toString()}),s.stderr?.on("data",u=>{c+=u.toString()}),s.once("error",u=>m(u)),s.once("close",u=>{const f=`${l}
|
|
4
|
-
${c}`.trim();if(u!==0){m(new Error(f||`codex queue exited with code ${u??"unknown"}`));return}const O=f.match(/Queued message\s+([^\s]+)\s+for thread/i)?.[1];m(void 0,O)})})}async resume(e){await this.killProcess(),this.agentSessionId=e,this.resetTextState()}async setTitle(e,t,r){const n=e.trim(),i=t.replace(/\s+/g," ").trim();!n||!i||(this.agentSessionId=n,r?.trim()&&(this.workDir=r),await this.ensureAppServer(),await this.sendRpc("thread/name/set",{threadId:n,name:i}))}async stop(){this.managedRoomTools.deactivateTurn(),await this.interruptActiveTurn().catch(()=>{}),await this.killProcess()}async getStatus(){const e=this.agentSessionId,t=this.activeTurnId;if(!e||!this.process)return{active:!1,runId:t,runPhase:null,canStop:!1};let r=null;try{r=(await this.sendRpc("thread/read",{threadId:e,includeTurns:!1},5e3)).thread?.status??null}catch{}const n=r?.type==="active"||!!t;return{active:n,runId:t,runPhase:n?this.mapThreadStatusToRunPhase(r):null,canStop:!!(n&&t&&this.process)}}spawnCodex(e){const t=T("codex");if(!t){this.emit("error",new Error('Command "codex" not found. Is OpenAI Codex CLI installed?'));return}const r=x(t,e,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:this.buildProcessEnv()});this.process=r,w({input:r.stdout}).on("line",s=>{if(s.trim())try{const a=JSON.parse(s);this.handleStreamEvent(a)}catch{this.emitEvent({state:"delta",text:s})}});let i="";r.stderr?.on("data",s=>{i+=s.toString()}),r.on("close",s=>{this.process===r&&(this.process=null,this.clearForceCloseTimer(),this.handleProcessClose(s,i))}),r.on("error",s=>{this.process===r&&(this.process=null,s.code==="ENOENT"?this.emit("error",new Error('Command "codex" not found. Is OpenAI Codex CLI installed?')):this.emit("error",s))})}spawnAppServer(){const e=T("codex");if(!e){this.emit("error",new Error('Command "codex" not found. Is OpenAI Codex CLI installed?'));return}const t=["app-server","--listen","stdio://"],r=this.options.modelInstructionsFile??W(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,this.agentSystemPrompt);r&&t.push("-c",`model_instructions_file=${JSON.stringify(r)}`);const n=x(e,t,{cwd:this.workDir??void 0,stdio:["pipe","pipe","pipe"],env:this.buildProcessEnv({NO_COLOR:"1"})});this.process=n,this.stderrBuf="",this.appServerStartupError=null,w({input:n.stdout}).on("line",s=>{if(!s.trim())return;let a;try{a=JSON.parse(s)}catch{this.handleAppServerNonJsonStdout(s);return}this.handleAppServerMessage(a)}),n.stderr?.on("data",s=>{this.stderrBuf+=s.toString()}),n.on("close",s=>{if(this.process!==n)return;const a=this.activeTurnId!=null;this.process=null,this.appServerReady=null,this.activeTurnId=null,this.managedRoomTools.reset(),this.clearConfiguredManagedRoomContext(),this.rejectAllPending(new Error(A(this.stderrBuf)||`codex app-server exited with code ${s}`)),this.terminalState==="open"&&a&&this.handleProcessClose(s,this.stderrBuf)}),n.on("error",s=>{this.process===n&&(this.process=null,this.managedRoomTools.reset(),this.clearConfiguredManagedRoomContext(),this.rejectAllPending(s),s.code==="ENOENT"?this.emit("error",new Error('Command "codex" not found. Is OpenAI Codex CLI installed?')):this.emit("error",s))})}async ensureAppServer(e){return this.appServerReady?this.appServerReady:(this.spawnAppServer(),this.appServerReady=this.initializeAppServer(e).catch(async t=>{throw this.appServerReady=null,await this.killProcess(),t}),this.appServerReady)}async initializeAppServer(e){const t=I(e);await this.sendRpc("initialize",{clientInfo:Y,capabilities:{experimentalApi:!0}}),this.managedPermissionConfig=this.managedAgentPolicy&&!R(this.managedAgentPolicy)?await this.buildManagedPermissionConfig():null;const r=!!(this.configuredManagedRoomContextToken||this.configuredManagedRoomExecutor);if(this.managedAgentPolicy&&r&&!this.managedRoomTools.isConfigured()&&(this.managedRoomTools.configure(this.configuredManagedRoomContextToken,this.configuredManagedRoomExecutor),!this.managedRoomTools.isConfigured()))throw new Error("codex_managed_room_tool_context_unavailable");if(this.agentSessionId&&this.managedAgentPolicy&&r&&this.agentSessionId!==this.managedRoomToolThreadId){if(!this.managedRoomTools.isConfigured())throw new Error("codex_managed_room_tool_context_unavailable");this.agentSessionId=null}if(this.agentSessionId){const l={threadId:this.agentSessionId,cwd:this.workDir,approvalPolicy:"never",...this.managedPermissionConfig?{config:this.managedPermissionConfig.threadConfig}:{sandbox:"danger-full-access"},persistExtendedHistory:!0,...t?{model:t}:{}};let c;try{c=await this.sendRpc("thread/resume",{...l,excludeTurns:!0})}catch(h){if(!ce(h))throw h;c=await this.sendRpc("thread/resume",l)}this.agentSessionId=c.thread?.id??this.agentSessionId,this.managedPermissionConfig&&C(c,this.managedPermissionConfig.profileId),this.managedAgentPolicy&&r&&(this.managedRoomTools.bindThread(this.agentSessionId),this.managedRoomToolThreadId=this.agentSessionId);return}const n=this.options.hidden||this.nativeSessionVisibility==="internal"||!this.persistNativeSession,i=n?void 0:await this.resolveCodexProjectId(),s={cwd:this.workDir,approvalPolicy:"never",...this.managedPermissionConfig?{config:this.managedPermissionConfig.threadConfig}:{sandbox:"danger-full-access"},serviceName:"Shennian",...n?{}:{threadSource:"user"},experimentalRawEvents:!1,persistExtendedHistory:!0,...this.managedAgentPolicy&&r?{dynamicTools:this.extraEnv.SHENNIAN_MANAGER_SESSION_ID?H:J}:{},...i?{projectId:i}:{},...t?{model:t}:{}};let a;if(n&&!this.managedPermissionConfig)a=await this.sendRpc("thread/start",s);else try{a=await this.sendRpc("thread/start",{...s,historyMode:"paginated"})}catch(l){throw le(l)?new Error("\u5F53\u524D Codex CLI \u4E0D\u652F\u6301\u521B\u5EFA\u53EF\u5728 Codex Desktop \u4E2D\u7EE7\u7EED\u7684\u65B0\u4F1A\u8BDD\uFF0C\u8BF7\u624B\u52A8\u5347\u7EA7 Codex CLI \u540E\u91CD\u8BD5\u3002\u795E\u5FF5\u4E0D\u4F1A\u81EA\u52A8\u5347\u7EA7\uFF0C\u4E5F\u4E0D\u4F1A\u964D\u7EA7\u521B\u5EFA\u4E0D\u53EF\u89C1\u7684 legacy \u4F1A\u8BDD\u3002",{cause:l}):l}const d=a.thread?.id;if(!d)throw new Error("codex app-server thread/start returned no thread id");this.managedPermissionConfig&&C(a,this.managedPermissionConfig.profileId),this.managedAgentPolicy&&r&&(this.managedRoomTools.bindThread(d),this.managedRoomToolThreadId=d),this.agentSessionId=d}async buildManagedPermissionConfig(){const e=this.managedAgentPolicy;if(!e)throw new Error("managed_agent_policy_missing");const t=e.adapterPolicy.externalCapabilities.mcp?[]:Q(await this.sendRpc("config/read",{cwd:e.adapterPolicy.workDir}));return K(G(e),e.adapterPolicy.workDir,{configuredMcpServerNames:t,shellSubprocessPolicy:e.environmentPolicy.shellSubprocess})}async resolveCodexProjectId(){const e=this.workDir?.trim();if(e)try{const t=[];let r;do{const l=await this.sendRpc("project/list",{limit:100,...r?{cursor:r}:{}});t.push(...l.data??[]),r=l.nextCursor}while(r);const n=he(t,e);if(n)return n;const i=p.resolve(e),s=`shennian-project-${S("sha256").update(i).digest("hex")}`,d=(await this.sendRpc("project/create",{idempotencyKey:s,name:p.basename(i)||i,roots:[{path:i}],metadata:{createdBy:"Shennian"}})).project?.id;if(!d)throw new Error("codex app-server project/create returned no project id");return d}catch(t){throw ue(t)?new Error("\u5F53\u524D Codex CLI \u4E0D\u652F\u6301\u521B\u5EFA\u53EF\u5F52\u5C5E\u5230 Codex Desktop \u9879\u76EE\u7684\u65B0\u4F1A\u8BDD\uFF0C\u8BF7\u624B\u52A8\u5347\u7EA7 Codex CLI \u540E\u91CD\u8BD5\u3002\u795E\u5FF5\u4E0D\u4F1A\u81EA\u52A8\u5347\u7EA7\uFF0C\u4E5F\u4E0D\u4F1A\u76F4\u63A5\u4FEE\u6539 Codex Desktop \u7684\u79C1\u6709\u4FA7\u680F\u7D22\u5F15\u3002",{cause:t}):t}}async startTurnWithRecovery(e,t,r,n,i){try{return await this.startTurn(e,t,r,n,i)}catch(s){if(!v(s))throw s;if(this.managedAgentPolicy||this.managedPermissionConfig){this.logManagedThreadLifecycle("rollout.missing",{threadId:e,recovery:"recreate"}),await this.killProcess(!0),this.agentSessionId=null,this.managedRoomToolThreadId=null,await this.ensureAppServer(r);const a=this.agentSessionId;if(!a)throw new Error("codex app-server did not recreate the managed thread",{cause:s});return this.logManagedThreadLifecycle("thread.recreated",{previousThreadId:e,threadId:a}),this.emitEvent({state:"start",agentSessionId:a}),await this.startFreshManagedTurnWithReadinessRetry(a,t,r,n,i)}return await this.killProcess(),await this.ensureAppServer(r),await this.startTurn(e,t,r,n,i)}}async startFreshManagedTurnWithReadinessRetry(e,t,r,n,i){const s=[0,100,300,1e3];let a;for(let d=0;d<s.length;d+=1){const l=s[d];l>0&&await new Promise(c=>setTimeout(c,l));try{const c=await this.startTurn(e,t,r,n,i);return d>0&&this.logManagedThreadLifecycle("rollout.ready",{threadId:e,attempt:d+1}),c}catch(c){if(a=c,!v(c)||d===s.length-1)throw c;this.logManagedThreadLifecycle("rollout.retry",{threadId:e,attempt:d+2,delayMs:s[d+1]})}}throw a}logManagedThreadLifecycle(e,t){console.error(`[codex.managed] ${JSON.stringify({event:e,...t})}`)}async startTurn(e,t,r,n,i){try{return await this.sendRpc("turn/start",{threadId:e,input:[M(t,i)],approvalPolicy:"never",...this.managedPermissionConfig?{}:{sandboxPolicy:{type:"dangerFullAccess"}},...r?{model:r}:{},...n?{effort:n}:{}})}catch(s){throw n&&re(s)?new Error(`Codex app-server does not accept reasoning effort "${n}" for this turn. Refresh models or upgrade Codex CLI, then retry.`,{cause:s}):s}}async interruptActiveTurn(){const e=this.agentSessionId,t=this.activeTurnId;this.activeTurnId=null,this.managedRoomTools.deactivateTurn(),!(!e||!t||!this.process)&&await this.sendRpc("turn/interrupt",{threadId:e,turnId:t},5e3)}sendRpc(e,t,r=6e4){if(this.appServerStartupError)return Promise.reject(this.appServerStartupError);const n=this.process;if(!n?.stdin)return Promise.reject(new Error("codex app-server is not running"));const i=this.rpcSeq++,s=JSON.stringify({id:i,method:e,params:t});return new Promise((a,d)=>{const l=setTimeout(()=>{this.pendingRequests.delete(i),d(new Error(`codex app-server request timed out: ${e}`))},r);this.pendingRequests.set(i,{resolve:a,reject:d,timer:l}),n.stdin.write(`${s}
|
|
5
|
-
`,c=>{c&&(clearTimeout(l),this.pendingRequests.delete(i),d(c))})})}handleAppServerMessage(e){if(e.method==="item/tool/call"&&e.id!=null){this.handleManagedRoomToolCall(e.id,e.params??{});return}if(e.id!=null){const r=typeof e.id=="number"?this.pendingRequests.get(e.id):void 0;r&&(clearTimeout(r.timer),this.pendingRequests.delete(e.id),e.error?r.reject(new Error(e.error.message||`codex app-server error ${e.error.code??""}`.trim())):r.resolve(e.result))}if(!e.method)return;const t=e.params??{};switch(e.method){case"turn/started":{const r=typeof t.turn=="object"&&t.turn!==null?t.turn:null,n=typeof r?.id=="string"?r.id:null,i=typeof t.threadId=="string"?t.threadId:"";n&&(this.activeTurnId=n,this.managedRoomCapabilityExpectedForTurn&&this.managedRoomToolThreadId===i&&!this.managedRoomTools.bindTurn(i,n)&&(this.managedRoomTurnBindingFailed=!0,this.emitErrorIfOpen("codex_managed_room_turn_binding_failed")));break}case"thread/status/changed":{const r=typeof t.threadId=="string"?t.threadId:"";if(r&&this.agentSessionId&&r!==this.agentSessionId)break;const n=typeof t.status=="object"&&t.status!==null?t.status:null;n?.type==="active"&&this.emitEvent({state:"heartbeat",runPhase:this.mapThreadStatusToRunPhase(n)});break}case"item/agentMessage/delta":{const r=typeof t.itemId=="string"?t.itemId:"";r&&this.deltaItemIds.add(r),typeof t.delta=="string"&&this.emitText(t.delta);break}case"item/completed":this.handleAppServerCompletedItem(t);break;case"thread/tokenUsage/updated":this.handleAppServerUsage(t);break;case"turn/completed":{const r=typeof t.turn=="object"&&t.turn!==null?t.turn:null,n=typeof r?.id=="string"?r.id:null;(!this.activeTurnId||n===this.activeTurnId)&&(this.activeTurnId=null,this.managedRoomTools.deactivateTurn(),this.emitFinalIfOpen());break}case"turn/failed":{const r=_(t);if(this.scheduleManagedAsyncRolloutRecovery(r))return;this.emitErrorIfOpen(r||"turn failed");break}case"error":{const r=_(t);if(ne(r)){this.emitTransientStatus(r);return}if(this.scheduleManagedAsyncRolloutRecovery(r))return;this.emitErrorIfOpen(r);break}}}scheduleManagedAsyncRolloutRecovery(e){if(!this.managedAgentPolicy&&!this.managedPermissionConfig||!this.managedTurnReplay||!v(new Error(e)))return!1;if(this.managedAsyncRecovery)return!0;if(this.managedTurnReplay.recoveryCount>=2)return!1;this.managedTurnReplay.recoveryCount+=1;const t=this.managedTurnReplay.recoveryCount;return this.logManagedThreadLifecycle("rollout.failed-async",{threadId:this.agentSessionId,recoveryCount:t}),this.managedAsyncRecovery=this.recoverManagedTurnAfterAsyncRolloutFailure().catch(r=>{const n=v(r)?"no rollout found after managed thread recovery":r instanceof Error?r.message:"managed thread recovery failed";this.emitErrorIfOpen(n)}).finally(()=>{this.managedAsyncRecovery=null}),!0}async recoverManagedTurnAfterAsyncRolloutFailure(){const e=this.managedTurnReplay,t=this.agentSessionId;if(!e||!t||this.terminalState!=="open")return;this.activeTurnId=null,this.managedRoomTools.deactivateTurn(),await this.killProcess(!0),this.agentSessionId=null,this.managedRoomToolThreadId=null,await this.ensureAppServer(e.modelId);const r=this.agentSessionId;if(!r)throw new Error("codex app-server did not recreate the managed thread");this.logManagedThreadLifecycle("thread.recreated-async",{previousThreadId:t,threadId:r,recoveryCount:e.recoveryCount}),this.emitEvent({state:"start",agentSessionId:r});const n=await this.startFreshManagedTurnWithReadinessRetry(r,e.text,e.modelId,e.reasoningEffort,e.attachments);if(this.activeTurnId=n.turn?.id??null,this.managedRoomTurnBindingFailed)throw new Error("codex_managed_room_turn_binding_failed");if(this.managedRoomCapabilityExpectedForTurn&&this.managedRoomToolThreadId===r&&this.activeTurnId&&!this.managedRoomTools.bindTurn(r,this.activeTurnId))throw new Error("codex_managed_room_turn_binding_failed")}async handleManagedRoomToolCall(e,t){const r=await this.managedRoomTools.execute(t);if(this.writeAppServerResponse(e,r),r.success&&t.tool==="shennian_room_send"){const n=typeof t.arguments=="object"&&t.arguments!==null?t.arguments:null,i=typeof n?.text=="string"?n.text.trim():"";i&&this.emitText(i,"block")}}writeAppServerResponse(e,t){const r=this.process;r?.stdin&&r.stdin.write(`${JSON.stringify({id:e,result:t})}
|
|
6
|
-
`)}mapThreadStatusToRunPhase(e){const t=e?.type==="active"&&Array.isArray(e.activeFlags)?e.activeFlags:[];return t.includes("waitingOnApproval")?"waiting_approval":t.includes("waitingOnUserInput")?"waiting_user_input":"thinking"}handleAppServerNonJsonStdout(e){const t=ae(e);se(t)&&this.failAppServerStartup(new Error("Codex \u672A\u767B\u5F55\u3002\u8BF7\u5148\u5728\u8FD9\u53F0\u7535\u8111\u7684\u7EC8\u7AEF\u8FD0\u884C `codex`\uFF0C\u6309\u63D0\u793A\u5B8C\u6210 ChatGPT \u767B\u5F55\u6216\u914D\u7F6E API key\uFF0C\u7136\u540E\u518D\u56DE\u5230\u795E\u5FF5\u53D1\u9001\u6D88\u606F\u3002"))}failAppServerStartup(e){this.appServerStartupError||(this.appServerStartupError=e,this.rejectAllPending(e),this.process?.kill("SIGTERM"))}handleAppServerCompletedItem(e){const t=typeof e.item=="object"&&e.item!==null?e.item:null;if(!(!t||typeof t.type!="string")&&!ee(t))switch(t.type){case"agentMessage":{const r=typeof t.id=="string"?t.id:"";if(r&&this.deltaItemIds.has(r))return;typeof t.text=="string"&&this.emitText(t.text,"block");break}case"commandExecution":{const r=typeof t.command=="string"?t.command:"",n=typeof t.aggregatedOutput=="string"?t.aggregatedOutput:"";r&&this.emitEvent({state:"tool-call",name:"command_execution",args:{command:r}}),this.emitEvent({state:"tool-result",name:"command_execution",result:[n,t.exitCode!=null?`
|
|
7
|
-
(exit ${t.exitCode})`:""].join("").trim()});break}case"mcpToolCall":case"dynamicToolCall":{const r=typeof t.tool=="string"?t.tool:t.type;if(y(r))return;const n=typeof t.arguments=="object"&&t.arguments!==null?t.arguments:{};this.emitEvent({state:"tool-call",name:r,args:n}),this.emitEvent({state:"tool-result",name:r,result:k(t.error??t.result??t.contentItems??"")});break}case"fileChange":break;case"approvalRequest":case"approval_request":case"permissionRequest":case"permission_request":case"userInputRequired":case"user_input_required":{this.emitApprovalPending(t);break}}}handleAppServerUsage(e){const t=typeof e.tokenUsage=="object"&&e.tokenUsage!==null?e.tokenUsage:null,r=typeof t?.last=="object"&&t.last!==null?t.last:null,n=typeof t?.total=="object"&&t.total!==null?t.total:null,i=r??n;if(!i)return;const s=typeof i.inputTokens=="number"?i.inputTokens:void 0,a=typeof i.outputTokens=="number"?i.outputTokens:void 0;(s!=null||a!=null)&&(this.pendingUsage={inputTokens:s??0,outputTokens:a??0})}handleCodexItemLine(e){const t=e.item;if(t?.type&&!te(t))switch(t.type){case"agent_message":case"reasoning":{e.type==="item.completed"&&t.text&&this.emitText(t.text,"block");break}case"command_execution":{if(e.type==="item.started"&&t.command&&this.emitEvent({state:"tool-call",name:"command_execution",args:{command:t.command}}),e.type==="item.completed"){const r=[t.aggregated_output??"",t.exit_code!=null?`
|
|
8
|
-
(exit ${t.exit_code})`:""];this.emitEvent({state:"tool-result",name:"command_execution",result:r.join("").trim()||String(t.status??"")})}break}case"mcp_tool_call":{if(t.tool&&y(t.tool))return;if(e.type==="item.started"&&this.emitEvent({state:"tool-call",name:t.tool??"mcp_tool",args:{server:t.server,...t.arguments&&typeof t.arguments=="object"?t.arguments:{}}}),e.type==="item.completed"){const r=t.error&&typeof t.error=="object"?t.error.message:void 0;this.emitEvent({state:"tool-result",name:t.tool??"mcp_tool",result:r??k(t.result)})}break}case"file_change":break;case"web_search":{e.type==="item.completed"&&t.query&&this.emitText(`[web_search] ${t.query}`,"block");break}case"todo_list":{if(e.type==="item.completed"&&t.items?.length){const r=t.items.map(n=>`- [${n.completed?"x":" "}] ${n.text}`).join(`
|
|
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 n=e.usage;if(n){const i=n.input_tokens??n.prompt_tokens,s=n.output_tokens??n.completion_tokens;(i!=null||s!=null)&&(this.pendingUsage={inputTokens:i??0,outputTokens:s??0})}this.emitFinalIfOpen();return}case"turn.failed":{const n=typeof e.error=="object"&&e.error?.message?e.error.message:typeof e.error=="string"?e.error:"turn failed";this.emitErrorIfOpen(n);return}case"error":{const n=typeof e.message=="string"?e.message:"";if(n.includes("Reconnecting"))return;this.emitErrorIfOpen(n||(typeof e.error=="string"?e.error:"stream error"));return}case"thread.started":{const n=e.thread_id??e.session_id??e.id;typeof n=="string"&&n&&(this.agentSessionId=n,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 n=e.content??e.text;n&&this.emitText(n);break}case"function_call":case"tool_call":{if(this.isApprovalLikeName(e.name)){this.emitApprovalPending(e);break}if(e.name&&y(e.name))return;this.emitEvent({state:"tool-call",name:e.name,args:e.arguments??e.input});break}case"function_call_output":case"tool_result":{if(e.name&&y(e.name))return;this.emitEvent({state:"tool-result",name:e.name,result:e.output??e.result});break}case"approval_request":case"approvalRequest":case"permission_request":case"permissionRequest":case"user_input_required":case"userInputRequired":{this.emitApprovalPending(e);break}case"error":break;case"done":case"completed":{e.usage&&(this.pendingUsage={inputTokens:e.usage.prompt_tokens??e.usage.input_tokens??0,outputTokens:e.usage.completion_tokens??e.usage.output_tokens??0}),this.emitFinalIfOpen();break}}}emitEvent(e){if(this.terminalState!=="open"&&e.state!=="final"&&e.state!=="error"&&e.state!=="aborted")return;const t={...e,runId:this.runId,seq:this.seq++};this.emit("agentEvent",t)}isApprovalLikeName(e){return typeof e!="string"?!1:/approval|permission|confirm|user[_-]?input|request[_-]?user/i.test(e)}emitApprovalPending(e){const t=typeof e.command=="string"?e.command:"",r=typeof e.title=="string"&&e.title.trim()?e.title:"\u9700\u8981\u7528\u6237\u786E\u8BA4",n=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:n,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=A(t);if(e!==0&&e!==null){const n=r||`codex exited with code ${e}`;this.emitErrorIfOpen(n)}else ie(r)?this.emitErrorIfOpen(r):this.emitFinalIfOpen();this.pendingUsage=void 0}emitFinalIfOpen(){this.terminalState==="open"&&(this.terminalState="final",this.managedTurnReplay=null,this.managedRoomCapabilityExpectedForTurn=!1,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.managedRoomCapabilityExpectedForTurn=!1,this.managedRoomTools.deactivateTurn(),this.clearConfiguredManagedRoomContext(),this.emitEvent({state:"error",message:j(e)}),this.scheduleProcessClose())}resetRunState(){this.pendingUsage=void 0,this.terminalState="open",this.managedRoomTurnBindingFailed=!1,this.deltaItemIds.clear(),this.lastTransientStatus="",this.clearForceCloseTimer(),this.resetTextState()}clearConfiguredManagedRoomContext(){this.configuredManagedRoomContextToken=null,this.configuredManagedRoomExecutor=null}emitTransientStatus(e){const t=Z(e);!t||t===this.lastTransientStatus||this.terminalState!=="open"||(this.lastTransientStatus=t,this.emitEvent({state:"delta",text:`${t}
|
|
10
|
-
`,thinking:!0}))}resetTextState(){this.hasEmittedText=!1,this.textTail=""}emitText(e,t="delta"){if(!e)return;let r=de(e);r&&(t==="block"&&this.hasEmittedText&&!r.startsWith(`
|
|
11
|
-
`)&&(this.textTail.endsWith(`
|
|
12
|
-
`)?r=`
|
|
13
|
-
${r}`:this.textTail.endsWith(`
|
|
14
|
-
|
|
15
|
-
`)||(r=`
|
|
16
|
-
|
|
17
|
-
${r}`)),this.hasEmittedText=!0,this.textTail=(this.textTail+r).slice(-4),this.emitEvent({state:"delta",text:r}))}scheduleProcessClose(){const e=this.process;!e||this.forceCloseTimer||(this.forceCloseTimer=setTimeout(()=>{this.forceCloseTimer=null,this.process===e&&(e.kill("SIGTERM"),setTimeout(()=>{this.process===e&&e.kill("SIGKILL")},1e3))},250))}clearForceCloseTimer(){this.forceCloseTimer&&(clearTimeout(this.forceCloseTimer),this.forceCloseTimer=null)}}D("codex",()=>new ve);export{ve as CodexAdapter,ye as buildCodexQueueArgs,fe as buildCodexQueuedText,P as isCodexActiveWriterError,ce as isCodexExcludeTurnsUnsupportedError,le as isCodexPaginatedHistoryUnsupportedError,ue as isCodexProjectApiUnsupportedError,Fe as isCodexUnsupportedEffortError,De as isMissingCodexRolloutError,Le as normalizeCodexModelId,$e as normalizeCodexReasoningEffort,he as selectCodexProjectIdForWorkDir};
|
|
1
|
+
import{CODEX_DESKTOP_SEND_UNAVAILABLE as x}from"@shennian/wire";import{createHash as v,randomUUID as R}from"node:crypto";import I from"node:path";import{createInterface as y}from"node:readline";import{buildAgentProcessEnv as A,buildManagedAgentProcessEnv as M,buildManagedNativeFullProcessEnv as N}from"../agent-env.js";import{isCodexThreadTailInterrupted as O}from"../native-fusion/codex-files.js";import{isManagedAgentNativeFull as C,resolveManagedAgentAdapterEnforcement as b}from"../security/managed-agent-policy.js";import{registerManagedAgentRuntimeSecurity as k}from"../security/managed-agent-runtime.js";import{registerAgent as D}from"./adapter.js";import{CODEX_MANAGED_RUNTIME_SECURITY as F,assertCodexManagedPermissionProfile as S,compileCodexManagedPermissions as j,extractCodexMcpServerNames as L}from"./codex-managed-permissions.js";import{CODEX_MANAGED_MANAGER_DYNAMIC_TOOLS as q,CODEX_MANAGED_ROOM_DYNAMIC_TOOLS as U}from"./codex-managed-room-tools.js";import{CODEX_APP_SERVER_CLIENT_INFO as B,isCodexUnsupportedEffortError as z,isMissingCodexRolloutError as E,normalizeCodexModelId as g,normalizeCodexReasoningEffort as W,normalizeCodexStderr as G}from"./codex-utils.js";import{resolveBuiltinCommand as f,spawnAgentCommand as w}from"./command-spec.js";import{ensurePlatformInstructionsFile as H}from"./platform-instructions.js";import{buildCodexQueueArgs as xe,buildCodexQueuedText as ve,isCodexActiveWriterError as Ie,isCodexExcludeTurnsUnsupportedError as ye,isCodexPaginatedHistoryUnsupportedError as Ce,isCodexProjectApiUnsupportedError as Se,selectCodexProjectIdForWorkDir as Ee}from"./codex-protocol.js";import{isCodexUnsupportedEffortError as _e,isMissingCodexRolloutError as Pe,normalizeCodexModelId as Re,normalizeCodexReasoningEffort as Ae}from"./codex-utils.js";import{buildCodexQueueArgs as $,buildCodexTextInput as T,isCodexActiveWriterError as _,isCodexExcludeTurnsUnsupportedError as J,isCodexPaginatedHistoryUnsupportedError as V,isCodexProjectApiUnsupportedError as X,selectCodexProjectIdForWorkDir as Q}from"./codex-protocol.js";import{CodexRuntime as Y}from"./codex-runtime.js";k("codex",F);class K extends Y{get supportsActiveInput(){return!0}async injectActiveInput(e){const r=this.agentSessionId,i=this.activeTurnId;if(!r||!i||!this.process)throw new Error("codex_active_turn_unavailable");const s=await this.sendRpc("turn/steer",{threadId:r,expectedTurnId:i,input:[T(e.text,e.attachments)],...e.clientMessageId?{clientUserMessageId:e.clientMessageId}:{}});if(s.turnId&&s.turnId!==i)throw new Error("codex_active_turn_changed")}type="codex";get recoveryCapabilities(){return{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!0}}configure(e){const r=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 i=this.configurationFingerprint();r!==i&&this.process&&(this.configurationRestartRequired=!0)}configurationFingerprint(){const e=Object.keys(this.extraEnv).sort().map(r=>[r,this.extraEnv[r]??null]);return v("sha256").update(JSON.stringify({sessionId:this.shennianSessionId,externalChannel:this.externalChannel,env:e,managedAgentPolicy:this.managedAgentPolicy})).digest("hex")}buildProcessEnv(e={}){if(!this.managedAgentPolicy)return A({...e,...this.extraEnv});if(C(this.managedAgentPolicy))return N({...e,...this.extraEnv});const r=Object.fromEntries(Object.entries(this.extraEnv).filter(([i])=>i!=="SHENNIAN_MANAGED_ROOM_CONTEXT"&&i!=="SHENNIAN_MANAGED_ROOM_IPC_ROOT"));return M({agentType:"codex",providerEnv:r,sessionEnv:r,runtimeEnv:e})}async start(e,r,i,s){this.shennianSessionId=e,this.workDir=this.managedAgentPolicy?.adapterPolicy.workDir??r,this.seq=0,this.persistNativeSession=s?.persistNativeSession!==!1,this.nativeSessionVisibility=s?.nativeSessionVisibility??"user",i&&(this.agentSessionId=i),this.notifyNativeSession()}async prepareSend(e,r,i,s,n,t){const o=n?.trim()??"";if(o!==this.agentSystemPrompt&&(this.agentSystemPrompt=o,this.process&&await this.killProcess(!0)),!(!this.agentSessionId||this.activeTurnId)){this.preparedExternalOwnerThreadId=null;try{await this.ensureAppServer(g(r))}catch(a){if(!_(a))throw a;if(t?.source==="room_activation"||t?.source==="managed_private")throw new Error("codex_managed_thread_owned_externally",{cause:a});if(this.isThreadTailInterrupted(this.agentSessionId))throw new Error(x,{cause:a});this.preparedExternalOwnerThreadId=this.agentSessionId}}}async send(e,r,i,s,n,t){if((t?.source==="room_activation"||t?.source==="managed_private")&&!this.managedAgentPolicy)throw new Error("managed_agent_policy_missing");if((t?.source==="room_activation"||t?.source==="managed_private")&&(!this.configuredManagedRoomContextToken||!this.configuredManagedRoomExecutor))throw new Error("codex_managed_room_tool_context_unavailable");const o=t?.source==="room_activation"||t?.source==="managed_private";this.managedRoomCapabilityExpectedForTurn=!1,this.activeTurnId&&(await this.interruptActiveTurn().catch(()=>{}),await this.killProcess(!0)),this.configurationRestartRequired&&this.process&&await this.killProcess(!0),this.configurationRestartRequired=!1;const a=g(r),d=W(i),c=n?.trim()??"";if(c!==this.agentSystemPrompt&&(this.agentSystemPrompt=c,this.process&&await this.killProcess(!0)),(t?.source==="room_activation"||t?.source==="managed_private")&&this.managedRoomTools.configure(this.configuredManagedRoomContextToken,this.configuredManagedRoomExecutor),this.runId=R(),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)};this.managedRoomCapabilityExpectedForTurn=o;try{await this.ensureAppServer(a)}catch(h){if(!this.agentSessionId||!_(h))throw h;if(t?.source==="room_activation"||t?.source==="managed_private")throw new Error("codex_managed_thread_owned_externally",{cause:h});if(this.isThreadTailInterrupted(this.agentSessionId))throw new Error(x,{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 u=await this.startTurnWithRecovery(l,e,a,d,s),m=this.agentSessionId??l;if(this.activeTurnId=u.turn?.id??null,this.managedRoomTurnBindingFailed)throw await this.killProcess(),new Error("codex_managed_room_turn_binding_failed");if(this.managedRoomCapabilityExpectedForTurn&&this.managedRoomToolThreadId===m&&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)??O(e)}async enqueueForExternalOwner(e,r,i){if(this.options.hidden||this.nativeSessionVisibility==="internal")throw new Error("codex_managed_thread_owned_externally");const s=f("codex");if(!s)throw new Error('Command "codex" not found. Is OpenAI Codex CLI installed?');const n=$(e,r,i),t=w(s,n,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:this.buildProcessEnv({NO_COLOR:"1"})});return await new Promise((o,a)=>{let d="",c="",l=!1;const u=(h,p)=>{l||(l=!0,clearTimeout(m),h?a(h):o(p))},m=setTimeout(()=>{t.kill("SIGTERM"),u(new Error("Codex Desktop message queue timed out"))},6e4);m.unref?.(),t.stdout?.on("data",h=>{d+=h.toString()}),t.stderr?.on("data",h=>{c+=h.toString()}),t.once("error",h=>u(h)),t.once("close",h=>{const p=`${d}
|
|
2
|
+
${c}`.trim();if(h!==0){u(new Error(p||`codex queue exited with code ${h??"unknown"}`));return}const P=p.match(/Queued message\s+([^\s]+)\s+for thread/i)?.[1];u(void 0,P)})})}async resume(e){await this.killProcess(),this.agentSessionId=e,this.resetTextState()}async setTitle(e,r,i){const s=e.trim(),n=r.replace(/\s+/g," ").trim();!s||!n||(this.agentSessionId=s,this.notifyNativeSession(),i?.trim()&&(this.workDir=i),await this.ensureAppServer(),await this.sendRpc("thread/name/set",{threadId:s,name:n}))}async stop(){this.managedRoomTools.deactivateTurn(),await this.interruptActiveTurn().catch(()=>{}),await this.killProcess()}async getStatus(){const e=this.agentSessionId,r=this.activeTurnId;if(!e||!this.process)return{active:!1,runId:r,runPhase:null,canStop:!1};let i=null;try{i=(await this.sendRpc("thread/read",{threadId:e,includeTurns:!1},5e3)).thread?.status??null}catch{}const s=i?.type==="active"||!!r;return{active:s,runId:r,runPhase:s?this.mapThreadStatusToRunPhase(i):null,canStop:!!(s&&r&&this.process)}}spawnCodex(e){const r=f("codex");if(!r){this.emit("error",new Error('Command "codex" not found. Is OpenAI Codex CLI installed?'));return}const i=w(r,e,{cwd:this.workDir??void 0,stdio:["ignore","pipe","pipe"],env:this.buildProcessEnv()});this.process=i,y({input:i.stdout}).on("line",t=>{if(t.trim())try{const o=JSON.parse(t);this.handleStreamEvent(o)}catch{this.emitEvent({state:"delta",text:t})}});let n="";i.stderr?.on("data",t=>{n+=t.toString()}),i.on("close",t=>{this.process===i&&(this.process=null,this.clearForceCloseTimer(),this.handleProcessClose(t,n))}),i.on("error",t=>{this.process===i&&(this.process=null,t.code==="ENOENT"?this.emit("error",new Error('Command "codex" not found. Is OpenAI Codex CLI installed?')):this.emit("error",t))})}spawnAppServer(){const e=f("codex");if(!e){this.emit("error",new Error('Command "codex" not found. Is OpenAI Codex CLI installed?'));return}const r=["app-server","--listen","stdio://"],i=this.options.modelInstructionsFile??H(this.workDir??process.cwd(),this.externalChannel,this.shennianSessionId??void 0,this.agentSystemPrompt);i&&r.push("-c",`model_instructions_file=${JSON.stringify(i)}`);const s=w(e,r,{cwd:this.workDir??void 0,stdio:["pipe","pipe","pipe"],env:this.buildProcessEnv({NO_COLOR:"1"})});this.process=s,this.stderrBuf="",this.appServerStartupError=null,y({input:s.stdout}).on("line",t=>{if(!t.trim())return;let o;try{o=JSON.parse(t)}catch{this.handleAppServerNonJsonStdout(t);return}this.handleAppServerMessage(o)}),s.stderr?.on("data",t=>{this.stderrBuf+=t.toString()}),s.on("close",t=>{if(this.process!==s)return;const o=this.activeTurnId!=null;this.process=null,this.appServerReady=null,this.activeTurnId=null,this.managedRoomTools.reset(),this.clearConfiguredManagedRoomContext(),this.rejectAllPending(new Error(G(this.stderrBuf)||`codex app-server exited with code ${t}`)),this.terminalState==="open"&&o&&this.handleProcessClose(t,this.stderrBuf)}),s.on("error",t=>{this.process===s&&(this.process=null,this.managedRoomTools.reset(),this.clearConfiguredManagedRoomContext(),this.rejectAllPending(t),t.code==="ENOENT"?this.emit("error",new Error('Command "codex" not found. Is OpenAI Codex CLI installed?')):this.emit("error",t))})}async ensureAppServer(e){return this.appServerReady?this.appServerReady:(this.spawnAppServer(),this.appServerReady=this.initializeAppServer(e).catch(async r=>{throw this.appServerReady=null,await this.killProcess(),r}),this.appServerReady)}async initializeAppServer(e){const r=g(e);await this.sendRpc("initialize",{clientInfo:B,capabilities:{experimentalApi:!0}}),this.managedPermissionConfig=this.managedAgentPolicy&&!C(this.managedAgentPolicy)?await this.buildManagedPermissionConfig():null;const i=!!(this.configuredManagedRoomContextToken||this.configuredManagedRoomExecutor);if(this.managedAgentPolicy&&i&&!this.managedRoomTools.isConfigured()&&(this.managedRoomTools.configure(this.configuredManagedRoomContextToken,this.configuredManagedRoomExecutor),!this.managedRoomTools.isConfigured()))throw new Error("codex_managed_room_tool_context_unavailable");if(this.agentSessionId&&this.managedAgentPolicy&&i&&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,...r?{model:r}:{}};let c;try{c=await this.sendRpc("thread/resume",{...d,excludeTurns:!0})}catch(l){if(!J(l))throw l;c=await this.sendRpc("thread/resume",d)}this.agentSessionId=c.thread?.id??this.agentSessionId,this.notifyNativeSession(),this.managedPermissionConfig&&S(c,this.managedPermissionConfig.profileId),this.managedAgentPolicy&&i&&(this.managedRoomTools.bindThread(this.agentSessionId),this.managedRoomToolThreadId=this.agentSessionId);return}const s=this.options.hidden||this.nativeSessionVisibility==="internal"||!this.persistNativeSession,n=s?void 0:await this.resolveCodexProjectId(),t={cwd:this.workDir,approvalPolicy:"never",...this.managedPermissionConfig?{config:this.managedPermissionConfig.threadConfig}:{sandbox:"danger-full-access"},serviceName:"Shennian",threadSource:s?"shennian_internal":"user",experimentalRawEvents:!1,persistExtendedHistory:!0,...this.managedAgentPolicy&&i?{dynamicTools:this.extraEnv.SHENNIAN_MANAGER_SESSION_ID?q:U}:{},...n?{projectId:n}:{},...r?{model:r}:{}};let o;if(s&&!this.managedPermissionConfig)o=await this.sendRpc("thread/start",t);else try{o=await this.sendRpc("thread/start",{...t,historyMode:"paginated"})}catch(d){throw V(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=o.thread?.id;if(!a)throw new Error("codex app-server thread/start returned no thread id");this.managedPermissionConfig&&S(o,this.managedPermissionConfig.profileId),this.managedAgentPolicy&&i&&(this.managedRoomTools.bindThread(a),this.managedRoomToolThreadId=a),this.agentSessionId=a,this.notifyNativeSession()}notifyNativeSession(){this.agentSessionId&&this.emit("nativeSession","codex",this.agentSessionId)}async buildManagedPermissionConfig(){const e=this.managedAgentPolicy;if(!e)throw new Error("managed_agent_policy_missing");const r=e.adapterPolicy.externalCapabilities.mcp?[]:L(await this.sendRpc("config/read",{cwd:e.adapterPolicy.workDir}));return j(b(e),e.adapterPolicy.workDir,{configuredMcpServerNames:r,shellSubprocessPolicy:e.environmentPolicy.shellSubprocess})}async resolveCodexProjectId(){const e=this.workDir?.trim();if(e)try{const r=[];let i;do{const d=await this.sendRpc("project/list",{limit:100,...i?{cursor:i}:{}});r.push(...d.data??[]),i=d.nextCursor}while(i);const s=Q(r,e);if(s)return s;const n=I.resolve(e),t=`shennian-project-${v("sha256").update(n).digest("hex")}`,a=(await this.sendRpc("project/create",{idempotencyKey:t,name:I.basename(n)||n,roots:[{path:n}],metadata:{createdBy:"Shennian"}})).project?.id;if(!a)throw new Error("codex app-server project/create returned no project id");return a}catch(r){throw X(r)?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:r}):r}}async startTurnWithRecovery(e,r,i,s,n){try{return await this.startTurn(e,r,i,s,n)}catch(t){if(!E(t))throw t;if(this.managedAgentPolicy||this.managedPermissionConfig){this.logManagedThreadLifecycle("rollout.missing",{threadId:e,recovery:"recreate"}),await this.killProcess(!0),this.agentSessionId=null,this.managedRoomToolThreadId=null,await this.ensureAppServer(i);const o=this.agentSessionId;if(!o)throw new Error("codex app-server did not recreate the managed thread",{cause:t});return this.logManagedThreadLifecycle("thread.recreated",{previousThreadId:e,threadId:o}),this.emitEvent({state:"start",agentSessionId:o}),await this.startFreshManagedTurnWithReadinessRetry(o,r,i,s,n)}return await this.killProcess(),await this.ensureAppServer(i),await this.startTurn(e,r,i,s,n)}}async startFreshManagedTurnWithReadinessRetry(e,r,i,s,n){const t=[0,100,300,1e3];let o;for(let a=0;a<t.length;a+=1){const d=t[a];d>0&&await new Promise(c=>setTimeout(c,d));try{const c=await this.startTurn(e,r,i,s,n);return a>0&&this.logManagedThreadLifecycle("rollout.ready",{threadId:e,attempt:a+1}),c}catch(c){if(o=c,!E(c)||a===t.length-1)throw c;this.logManagedThreadLifecycle("rollout.retry",{threadId:e,attempt:a+2,delayMs:t[a+1]})}}throw o}logManagedThreadLifecycle(e,r){console.error(`[codex.managed] ${JSON.stringify({event:e,...r})}`)}async startTurn(e,r,i,s,n){try{return await this.sendRpc("turn/start",{threadId:e,input:[T(r,n)],approvalPolicy:"never",...this.managedPermissionConfig?{}:{sandboxPolicy:{type:"dangerFullAccess"}},...i?{model:i}:{},...s?{effort:s}:{}})}catch(t){throw s&&z(t)?new Error(`Codex app-server does not accept reasoning effort "${s}" for this turn. Refresh models or upgrade Codex CLI, then retry.`,{cause:t}):t}}async interruptActiveTurn(){const e=this.agentSessionId,r=this.activeTurnId;this.activeTurnId=null,this.managedRoomTools.deactivateTurn(),!(!e||!r||!this.process)&&await this.sendRpc("turn/interrupt",{threadId:e,turnId:r},5e3)}}D("codex",()=>new K);export{K as CodexAdapter,xe as buildCodexQueueArgs,ve as buildCodexQueuedText,Ie as isCodexActiveWriterError,ye as isCodexExcludeTurnsUnsupportedError,Ce as isCodexPaginatedHistoryUnsupportedError,Se as isCodexProjectApiUnsupportedError,_e as isCodexUnsupportedEffortError,Pe as isMissingCodexRolloutError,Re as normalizeCodexModelId,Ae as normalizeCodexReasoningEffort,Ee as selectCodexProjectIdForWorkDir};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import{spawn as
|
|
2
|
-
${t.stderr??""}`.trim().match(/\d+\.\d+[\w.-]*/)?.[0]}function an(n,e){if(n
|
|
3
|
-
${
|
|
1
|
+
import{spawn as j,spawnSync as x}from"node:child_process";import l from"node:fs";import $ from"node:crypto";import P from"node:os";import s from"node:path";const A={claude:[{command:"claude",args:[],display:"claude"}],codex:[{command:"codex",args:[],display:"codex"}],workbuddy:[{command:"codebuddy",args:[],display:"WorkBuddy"}],gemini:[{command:"gemini",args:[],display:"gemini"}],cursor:[{command:"agent",args:[],display:"agent"},{command:"cursor",args:["agent"],display:"cursor agent"}],openclaw:[],opencode:[{command:"opencode",args:[],display:"opencode"}],pi:[{command:"shennian",args:[],display:"shennian"}],"pi-coding-agent":[{command:"pi",args:[],display:"pi"}],manager:[{command:"shennian",args:["manager"],display:"shennian manager"}]},m=new Map,f=new Map,h=new Map,p=new Map;function Y(){m.clear(),f.clear(),h.clear(),p.clear()}function d(){return process.platform}function V(n){return n.split(/\r?\n/).map(e=>e.trim()).filter(Boolean)}function C(n){if(s.basename(n)!==n)return[n];const e=P.homedir();if(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"),u=process.env.LOCALAPPDATA||o.join(e,"AppData","Local"),y=[o.join(e,".shennian","node"),o.join("C:\\","nvm4w","nodejs"),o.join(u,"npm-global"),o.join(a,"npm"),o.join(u,"pnpm"),o.join(e,"scoop","shims"),o.join("C:\\","Program Files","nodejs")].flatMap(w=>r.map(g=>o.join(w,g)));if(n==="codebuddy"){const w=[o.join(u,"Programs","WorkBuddy"),o.join(u,"WorkBuddy"),o.join("C:\\","Program Files","WorkBuddy")];for(const g of w)for(const N of["codebuddy.exe","codebuddy.cmd","codebuddy"])y.push(o.join(g,"resources","app.asar.unpacked","cli","bin",N))}return y}const i=[s.join(e,".npm-global","bin"),s.join(e,".local","bin"),s.join(e,".bun","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin"].map(o=>s.join(o,n));return n==="claude"&&d()==="darwin"&&i.push(...I(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 z(n=d(),e=P.homedir()){return n!=="darwin"?[]:["/Applications",s.join(e,"Applications")].flatMap(t=>["ChatGPT.app","Codex.app"].map(i=>s.join(t,i,"Contents","Resources","codex")))}function I(n){const e=[s.join(n,"Library","Application Support","Claude","claude-code")],t=[];for(const i of e){let o;try{o=l.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 S(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 C("shennian")){const o=s.win32.dirname(i);t.includes(o)||t.push(o)}return t.join(s.delimiter)}if(e&&s.basename(e)!==e){const i=s.dirname(e);t.includes(i)||t.unshift(i)}for(const i of C("shennian")){const o=s.dirname(i);t.includes(o)||t.push(o)}return t.join(s.delimiter)}function c(n){if(h.has(n))return h.get(n)??[];const e=d()==="win32",i=x(e?"where":"which",[n],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:3e3,windowsHide:!0,env:{...process.env,PATH:e?process.env.PATH:S(process.env.PATH,n)}}),r=[...i.status===0?V(i.stdout??""):[]];for(const a of C(n))l.existsSync(a)&&!r.includes(a)&&r.push(a);return h.set(n,r),r}function W(){return process.env.ComSpec||"cmd.exe"}function B(n){const e=s.extname(n).toLowerCase();return e===".exe"||e===".com"}function b(n){const e=s.extname(n).toLowerCase();return e===".cmd"||e===".bat"}function H(n){const e=s.extname(n).toLowerCase();return e===".js"||e===".mjs"||e===".cjs"}function L(){return c("node.exe")[0]??c("node")[0]??"node"}function D(n){return`"${n.replace(/"/g,'""')}"`}function v(n){return`'${n.replace(/'/g,"'\\''")}'`}function O(n){if(!n)return;const e=n.replace(/\//g,"\\"),t=e.match(/^([A-Za-z]):\\(.*)$/);if(t){const[,i,o]=t,r=o.replace(/\\/g,"/");return`/mnt/${i.toLowerCase()}/${r}`}if(e.startsWith("\\\\wsl$\\"))return`/${e.replace(/^\\\\wsl\$\\[^\\]+\\?/,"").replace(/\\/g,"/")}`;if(n.startsWith("/"))return n}function M(n){const e=n.trim();if(!e)throw new Error("Command string is empty");if(/[\\/]/.test(e)||/^[A-Za-z]:/.test(e))return b(e)?{kind:"cmd-shim",path:e}:{kind:"direct",path:e};const i=c(e),o=i.find(B);if(o)return{kind:"direct",path:o};const r=i.find(b);return r?{kind:"cmd-shim",path:r}:{kind:"direct",path:e}}function T(n){if(p.has(n))return p.get(n)??!1;const e=c("wsl.exe")[0]??c("wsl")[0];if(!e)return p.set(n,!1),!1;const i=x(e,["-e","sh","-lc",`command -v ${v(n)} >/dev/null 2>&1`],{stdio:"ignore",timeout:5e3,windowsHide:!0}).status===0;return p.set(n,i),i}function nn(n){if(m.has(n))return m.get(n)??!1;const e=c(n).length>0||d()==="win32"&&T(n);return m.set(n,e),e}function en(n){const e=c(n)[0];if(!e)return null;try{const t=l.realpathSync(e),i=l.statSync(t,{bigint:!0}),o=$.createHash("sha256").update(t).digest("hex"),r=$.createHash("sha256").update(`${i.dev}:${i.ino}:${i.size}:${i.mtimeNs}`).digest("hex");return{pathHash:o,fingerprint:r}}catch{return null}}function tn(n){return c(n)[0]??null}function q(n){const e=c(n.command),t=e.find(B);if(t)return{...n,kind:"native",path:t};const i=e.find(b);if(i)return{...n,kind:"cmd-shim",path:i};if(T(n.command)){const o=c("wsl.exe")[0]??c("wsl")[0];if(o)return{...n,kind:"wsl-bridge",path:o}}return null}function on(n){if(f.has(n))return f.get(n)??null;const e=n==="codex"?z().find(i=>l.existsSync(i)?!!R({command:i,args:[],display:"Codex Desktop",kind:"native",path:i}):!1):void 0,t=e?{...A.codex[0],kind:"native",path:e}:A[n].map(i=>{if(d()==="win32")return q(i);const o=c(i.command)[0];return o?{...i,kind:"native",path:o}:null}).find(Boolean)??null;return f.set(n,t),t}function F(n,e,t){if(n.kind==="native")return d()==="win32"&&H(n.path)?{command:L(),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(D).join(" ");return{command:W(),args:["/d","/s","/c",`"${r}"`],cwd:t}}const i=t?O(t):void 0;if(t&&!i)throw new Error(`Cannot map Windows path to WSL workDir: ${t}`);const o=[i?`cd ${v(i)}`:"",`exec ${[n.command,...n.args,...e].map(v).join(" ")}`].filter(Boolean).join(" && ");return{command:n.path,args:["-e","sh","-lc",o],cwd:void 0}}function U(n,e,t={}){const i=F(n,e,t.cwd);return j(i.command,i.args,{...t,cwd:i.cwd,windowsHide:t.windowsHide??!0,...d()==="win32"&&n.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function rn(n,e,t={}){return U(n,e,t)}function k(n,e,t={}){const i=F(n,e,t.cwd);return x(i.command,i.args,{...t,cwd:i.cwd,windowsHide:t.windowsHide??!0,...d()==="win32"&&n.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function E(n){const e=[];let t="",i=!1,o=!1;for(const r of n){if(r==="'"&&!o){i=!i;continue}if(r==='"'&&!i){o=!o;continue}if(r===" "&&!i&&!o){t&&(e.push(t),t="");continue}t+=r}return t&&e.push(t),e}function Z(n,e,t){const i=E(n),o=i[0];if(!o)throw new Error("Command string is empty");const r=i.slice(1);if(d()!=="win32")return{command:o,args:[...r,...e],cwd:t};const a=M(o);return a.kind==="cmd-shim"?{command:W(),args:["/d","/s","/c",`"${[a.path,...r,...e].map(D).join(" ")}"`],cwd:t}:H(a.path)?{command:L(),args:[a.path,...r,...e],cwd:t}:{command:a.path,args:[...r,...e],cwd:t}}function sn(n,e,t={}){const i=Z(n,e,t.cwd),o=E(n),r=d()==="win32"&&o[0]?M(o[0]):null;return j(i.command,i.args,{...t,cwd:i.cwd,windowsHide:t.windowsHide??!0,env:{...t.env,PATH:S(t.env?.PATH??process.env.PATH,o[0])},...d()==="win32"&&r?.kind==="cmd-shim"?{windowsVerbatimArguments:!0}:{}})}function R(n,e="--version"){const t=k(n,[e],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:5e3});return t.status!==0?void 0:`${t.stdout??""}
|
|
2
|
+
${t.stderr??""}`.trim().match(/\d+\.\d+[\w.-]*/)?.[0]}function an(n,e){if(n==="codex"||n==="claude"){const r=k(e,["--version"],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:5e3});if(r.status!==0)return;const a=`${r.stdout??""}
|
|
3
|
+
${r.stderr??""}`.replace(/\u001b\[[0-9;]*m/g,"");return(n==="codex"?a.match(/^\s*codex-cli\s+(\d+\.\d+\.\d+[\w.-]*)\s*$/im):a.match(/^\s*(\d+\.\d+\.\d+[\w.-]*)\s+\(Claude Code\)\s*$/im))?.[1]}if(n!=="cursor")return R(e);const t=k(e,["about"],{encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:5e3});return t.status!==0?void 0:`${t.stdout??""}
|
|
4
|
+
${t.stderr??""}`.match(/^\s*CLI Version\s+(\d+\.\d+(?:\.\d+)?[\w.-]*)\s*$/im)?.[1]}export{Z as buildCommandStringLaunchSpec,F as buildLaunchSpec,nn as commandExists,an as getBuiltinAgentVersion,z as getCodexDesktopCommandCandidates,R as getCommandVersion,d as getProcessPlatform,E as parseCommandString,Y as resetCommandSpecCache,on as resolveBuiltinCommand,en as resolveCommandFileIdentity,tn as resolveCommandFilePath,rn as spawnAgentCommand,sn as spawnCommandString,U as spawnResolvedCommand,k as spawnResolvedCommandSync,O as windowsPathToWsl};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AVAILABLE_BUILTIN_AGENT_TYPES as m}from"@shennian/wire";import{loadConfig as
|
|
1
|
+
import{probeBuiltinAuthStatus as c}from"./auth-status.js";import{AVAILABLE_BUILTIN_AGENT_TYPES as m}from"@shennian/wire";import{loadConfig as u}from"../config/index.js";import{getBuiltinAgentVersion as a,resolveBuiltinCommand as l}from"./command-spec.js";import{registerCustomRuntimeSecurity as f,resolveCustomRuntimeExecutableFingerprint as p}from"./custom-managed-runtime.js";import{resolveManagedAgentExecutableIdentity as d}from"../security/managed-agent-executable.js";import{discoverAcpAgents as g}from"./acp/discovery.js";const A=m.filter(n=>n!=="pi");function v(n,o){const i=n?.match(/(?:^|v)(\d+)\.(\d+)\.(\d+)/);if(!i)return!1;const t=i.slice(1,4).map(Number);for(let e=0;e<o.length;e+=1)if(t[e]!==o[e])return t[e]>o[e];return!0}function x(n){return v(n,[0,85,0])}function b(n){const o=n.models?.length?n.models:n.model?[n.model]:[],i=n.defaultModel??n.model;return o.map(t=>({id:t,name:t,isDefault:t===i}))}async function B(n={}){const o=[];for(const t of A){const e=l(t);if(!e)continue;const r=a(t,e);if((t==="codex"||t==="claude")&&!r||t==="pi-coding-agent"&&!x(r))continue;const s=d(e);o.push({type:t,command:e.command,args:e.args,version:r,runtimePlatform:s.platform,runtimeIsWsl:s.isWsl,executableFingerprint:s.executableFingerprint,authState:await c(t,e,r)})}const i=u();for(const[t,e]of Object.entries(i.customAgents??{})){const r=`custom:${t}`;f(r,e),o.push({type:r,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:p(e),models:b(e.caps)})}return o.push(...await g(n)),o}export{B as detectAgents,x as isPiCodingAgentRuntimeCompatible};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { AgentSendContext, AgentSendResult } from './adapter.js';
|
|
2
|
-
import { AgentAdapter } from './adapter.js';
|
|
3
1
|
import type { ChatAttachmentMeta, ExternalChannelSessionStatus } from '@shennian/wire';
|
|
4
2
|
import type { CompiledManagedAgentPolicy } from '../security/managed-agent-policy.js';
|
|
3
|
+
import type { AgentSendContext, AgentSendResult } from './adapter.js';
|
|
4
|
+
import { AgentAdapter } from './adapter.js';
|
|
5
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. */
|
|
@@ -45,7 +45,8 @@ export declare class ManagerAdapter extends AgentAdapter {
|
|
|
45
45
|
private workDir;
|
|
46
46
|
private agentSessionId;
|
|
47
47
|
private modelId;
|
|
48
|
-
|
|
48
|
+
private startOptions?;
|
|
49
|
+
start(sessionId: string, workDir: string, agentSessionId?: string | null, options?: import('./adapter.js').AgentStartOptions): Promise<void>;
|
|
49
50
|
send(text: string, modelId?: string): Promise<void>;
|
|
50
51
|
resume(agentSessionId: string): Promise<void>;
|
|
51
52
|
stop(): Promise<void>;
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import
|
|
1
|
+
import d from"node:fs";import c from"node:path";import{MANAGER_SYSTEM_PROMPT as I,buildManagerPrompt as g}from"../manager/prompt.js";import{getManagerRuntimeService as a}from"../manager/runtime.js";import{AgentAdapter as l,registerAgent as p}from"./adapter.js";import{ClaudeAdapter as f}from"./claude.js";import{CodexAdapter as y}from"./codex.js";import{PLATFORM_OUTPUT_INSTRUCTIONS as S}from"./platform-instructions.js";function M(r){return r==="claude"?"claude":"codex"}function v(r){return r.replace(/[^a-zA-Z0-9_.-]/g,"_")}function w(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",v(e),"instructions.md")}function h(r,e){const n=w(r),t=a(),s=t?.getManagerExternalChannelSystemPrompt(e)??"",i=typeof t?.getManagerWorkerDefaults=="function"?t.getManagerWorkerDefaults(e):void 0,o=i?.agentType?`\u9ED8\u8BA4 worker Agent\uFF1A${i.agentType}${i.modelId?`
|
|
2
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
|
-
${
|
|
6
|
+
${I}`,o?`## Worker Defaults
|
|
7
7
|
|
|
8
8
|
${o}`:"",s?`## External Message Channel Instructions
|
|
9
9
|
|
|
10
10
|
${s}`:"",S].filter(Boolean).join(`
|
|
11
11
|
|
|
12
12
|
`)}
|
|
13
|
-
`}function k(r,e){const n=A(r,e),t=
|
|
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 l{inner;substrate;type;get recoveryCapabilities(){return this.inner.recoveryCapabilities}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("nativeSession",(t,s)=>this.emit("nativeSession",t,s)),e.on("error",t=>this.emit("error",t))}configure(e){this.configured=e,e.sessionId&&a()?.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),a()?.registerManager({sessionId:e,agentSessionId:this.agentSessionId,workDir:n,modelId:this.substrate,agentType:this.type,status:"idle"}),a()?.bindManagerAdapterEvents(e,this.inner)}async send(e,n,t,s,i,o){a()?.registerManager({sessionId:this.sessionId,agentSessionId:this.agentSessionId,workDir:this.workDir,modelId:this.substrate,agentType:this.type,providerModelId:n??null,status:"running"}),await a()?.ready(),this.applyEnvironment();const u=h(this.workDir,this.sessionId),m=E(u,i);return this.inner.send(g(e),n,t,s,m,o)}async resume(e){this.agentSessionId=e,await this.inner.resume(e)}async stop(){a()?.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?a()?.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,o)=>i-o)[0]??-1;return n.startsWith("[\u795E\u5FF5\u53D7\u7BA1\u4F1A\u8BDD\u89C4\u5219]")&&s>=0?`${n.slice(0,s)}[\u4F1A\u8BDD\u6A21\u5F0F]
|
|
14
14
|
${r.trim()}
|
|
15
15
|
|
|
16
16
|
${n.slice(s)}`:`${r.trim()}
|
|
17
17
|
|
|
18
|
-
${n}`}class b extends
|
|
18
|
+
${n}`}class b extends l{type="manager";get recoveryCapabilities(){return this.inner?.recoveryCapabilities??{inspectTerminal:!1,reattachRun:!1,resumeRun:!1,resumeSession:!0}}inner=null;sessionId="";workDir="";agentSessionId=null;modelId="codex";startOptions;async start(e,n,t,s){this.startOptions=s,this.sessionId=e,this.workDir=n,this.agentSessionId=t??null,a()?.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 y({modelInstructionsFile:s,hidden:!0}),this.bindInner(this.inner),await this.inner.start(this.sessionId,this.workDir,this.agentSessionId,this.startOptions),a()?.bindManagerAdapterEvents(this.sessionId,this.inner)}a()?.registerManager({sessionId:this.sessionId,agentSessionId:this.agentSessionId,workDir:this.workDir,modelId:this.modelId,agentType:"manager",status:"running"}),await a()?.ready(),await this.withManagerEnv(()=>this.inner.send(g(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("nativeSession",(n,t)=>this.emit("nativeSession",n,t)),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=a()?.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}}}p("manager",()=>new b);export{b as ManagerAdapter,R as ManagerModeAdapter,E as combineManagerInstructions};
|