@messenger-agent/codex-agent 0.26.0-alpha.3 → 0.26.0-alpha.6
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/app-server-protocol.d.ts +5 -0
- package/dist/app.js +1 -1
- package/dist/assets/workspace-templates/basic/AGENTS.md +14 -0
- package/dist/assets/workspace-templates/developer/AGENTS.md +14 -0
- package/dist/codex.d.ts +2 -0
- package/dist/codex.js +3 -3
- package/dist/config.d.ts +2 -0
- package/dist/config.js +1 -1
- package/dist/dynamic-tools.js +1 -1
- package/dist/platform-instructions.js +4 -2
- package/dist/routes/chat.js +2 -2
- package/dist/routes/shared.d.ts +2 -1
- package/dist/routes/shared.js +5 -5
- package/dist/schemas.d.ts +15 -0
- package/dist/schemas.js +1 -1
- package/package.json +2 -2
|
@@ -95,6 +95,7 @@ export type TurnSteerParams = {
|
|
|
95
95
|
};
|
|
96
96
|
export type Thread = {
|
|
97
97
|
id: string;
|
|
98
|
+
name?: string | null;
|
|
98
99
|
turns?: Turn[];
|
|
99
100
|
};
|
|
100
101
|
export type Turn = {
|
|
@@ -227,6 +228,10 @@ export type ItemDeltaEvent = {
|
|
|
227
228
|
export type AppServerEvent = {
|
|
228
229
|
type: "thread.started";
|
|
229
230
|
thread_id: string;
|
|
231
|
+
} | {
|
|
232
|
+
type: "thread.name.updated";
|
|
233
|
+
thread_id: string;
|
|
234
|
+
name: string;
|
|
230
235
|
} | {
|
|
231
236
|
type: "turn.started";
|
|
232
237
|
turn_id: string;
|
package/dist/app.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Hono as e}from"hono";import
|
|
1
|
+
import{Hono as e}from"hono";import r from"./routes/chat.js";import{infoRequestLogger as i}from"@messenger-agent/shared/http-logger";import{agentAuthMiddleware as m}from"@messenger-agent/shared/agent-auth";import{appConfig as p}from"./config.js";import{installAgentActivityResponder as a}from"@messenger-agent/shared/agent-activity";import{codexActivitySnapshot as n}from"./routes/chat.js";const o=new e;a("codex",n),o.use(i(["/health"])),o.get("/health",t=>t.json({status:"ok"})),o.use("/*",m(p.authTokens)),o.route("/",r);var l=o;export{l as default};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Working In This Workspace
|
|
2
|
+
|
|
3
|
+
Before making changes:
|
|
4
|
+
|
|
5
|
+
- Inspect the workspace structure and read the relevant README, project documentation, and any more specific `AGENTS.md` files.
|
|
6
|
+
- Follow the project's existing conventions, package manager, lockfiles, scripts, and test commands.
|
|
7
|
+
- Keep changes focused. Preserve unrelated user changes and do not overwrite files you have not understood.
|
|
8
|
+
- Run the most relevant available checks after editing and clearly report anything that could not be verified.
|
|
9
|
+
|
|
10
|
+
## Environment
|
|
11
|
+
|
|
12
|
+
This basic workspace is intended for source inspection, scripting, and lightweight development. Common tools include Bash, Git, Python 3, Node.js, ripgrep, curl, and GitHub/GitLab CLI tools.
|
|
13
|
+
|
|
14
|
+
System package installation and `sudo` access are not available. If the task requires a compiler, Rust, native system libraries, or other missing system dependencies, explain the limitation and recommend using a developer workspace.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Working In This Workspace
|
|
2
|
+
|
|
3
|
+
Before making changes:
|
|
4
|
+
|
|
5
|
+
- Inspect the workspace structure and read the relevant README, project documentation, and any more specific `AGENTS.md` files.
|
|
6
|
+
- Follow the project's existing conventions, package manager, lockfiles, scripts, and test commands.
|
|
7
|
+
- Keep changes focused. Preserve unrelated user changes and do not overwrite files you have not understood.
|
|
8
|
+
- Run the relevant tests, lint checks, or builds after editing and clearly report anything that could not be verified.
|
|
9
|
+
|
|
10
|
+
## Environment
|
|
11
|
+
|
|
12
|
+
This developer workspace includes common development tools, C/C++ build tools, Rust, ffmpeg, and `sudo`-based apt package installation.
|
|
13
|
+
|
|
14
|
+
Prefer the project's existing toolchain and package manager. Install additional system packages only when the task genuinely requires them, and avoid unrelated environment changes.
|
package/dist/codex.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ export declare class CodexThread {
|
|
|
27
27
|
usage?: Usage | null;
|
|
28
28
|
}>;
|
|
29
29
|
runStreamed(_prompt: string, options?: TurnRunOptions): Promise<StreamedTurn>;
|
|
30
|
+
private waitForTurnStart;
|
|
30
31
|
steerStreamed(prompt: string, expectedTurnId: string, options?: {
|
|
31
32
|
signal?: AbortSignal;
|
|
32
33
|
}): Promise<StreamedTurn>;
|
|
@@ -37,6 +38,7 @@ export declare class CodexThread {
|
|
|
37
38
|
submitPendingUserInput(itemId: string, response: ToolRequestUserInputResponse): Promise<string | undefined>;
|
|
38
39
|
interrupt(turnId: string): Promise<void>;
|
|
39
40
|
interruptPendingUserInput(turnId: string, itemId: string): Promise<void>;
|
|
41
|
+
readName(): Promise<string | undefined>;
|
|
40
42
|
private interruptStaleTurn;
|
|
41
43
|
private turnStartParams;
|
|
42
44
|
private eventsForTurn;
|
package/dist/codex.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{mkdirSync as
|
|
2
|
-
`);return{items:d,finalResponse:
|
|
3
|
-
`)}class
|
|
1
|
+
import{mkdirSync as _,existsSync as P}from"node:fs";import{appServerClient as c}from"./app-server-client.js";import{dynamicToolSpecs as E}from"./dynamic-tools.js";import{loadAllSessions as U,persistSession as I}from"./db.js";import{appConfig as f}from"./config.js";import{logger as v}from"@messenger-agent/shared/logger";import{resolveAgentWorkdir as N}from"@messenger-agent/shared/agent-workspaces";import{codexPlatformInstructions as x}from"./platform-instructions.js";class T extends Error{path;constructor(e){super(`Workdir not found: ${e}`),this.path=e}}class k{id;model;workingDirectory;constructor(e,r,n){this.id=e,this.model=r,this.workingDirectory=n}async run(e,r){const n=await this.runStreamed(e,r),t=new Map,o=new Set;let a=null;for await(const u of n.events)if(u.type==="item.started")o.has(u.item.id)||t.set(u.item.id,u.item);else if(u.type==="item.completed")o.add(u.item.id),t.set(u.item.id,u.item);else if(u.type==="thread.tokenUsage.updated")a=u.usage;else if(u.type==="turn.failed")throw new Error(u.error.message);const d=Array.from(t.values()),i=d.filter(u=>u.type==="agentMessage").map(u=>u.text).join(`
|
|
2
|
+
`);return{items:d,finalResponse:i||void 0,usage:a}}async runStreamed(e,r){const n=c.request("turn/start",this.turnStartParams(e,r)),t=await this.waitForTurnStart(n,r?.signal),o=t.turn.id;return{turnId:o,events:this.eventsForTurn(o,t.turn,r?.signal)}}async waitForTurnStart(e,r){if(!r)return e;let n,t;const o=new Promise((d,i)=>{t=i}),a=()=>{n=r.reason??new DOMException("The operation was aborted","AbortError"),t(n)};r.addEventListener("abort",a,{once:!0}),r.aborted&&a();try{return await Promise.race([e,o])}catch(d){throw d===n&&e.then(i=>this.interrupt(i.turn.id)).catch(i=>v.error("Failed to clean up aborted Codex turn start:",i)),d}finally{r.removeEventListener("abort",a)}}async steerStreamed(e,r,n){const t={threadId:this.id,input:[{type:"text",text:e}],expectedTurnId:r},o=await c.request("turn/steer",t);return{turnId:o.turnId,events:this.eventsForTurn(o.turnId,void 0,n?.signal,void 0,!0)}}async continueWithUserInput(e,r,n){const t=c.pendingUserInputTurnId(this.id,e);return t?{turnId:t,events:this.eventsForTurn(t,void 0,n?.signal,async()=>{if(!await c.respondToUserInput(this.id,e,r))throw new Error(`No pending user input request found for item: ${e}`)})}:(await this.interruptStaleTurn(n?.sourceTurnId),this.runStreamed(C(e,r),n))}async submitPendingUserInput(e,r){const n=c.pendingUserInputTurnId(this.id,e);if(!(!n||!await c.respondToUserInput(this.id,e,r)))return n}async interrupt(e){await c.request("turn/interrupt",{threadId:this.id,turnId:e})}async interruptPendingUserInput(e,r){await this.interrupt(e),c.discardPendingUserInput(this.id,r)}async readName(){try{return(await c.request("thread/read",{threadId:this.id,includeTurns:!1})).thread?.name?.trim()||void 0}catch(e){v.warn(`Failed to read Codex thread name for ${this.id}:`,e);return}}async interruptStaleTurn(e){if(!e)return;(await c.request("thread/read",{threadId:this.id,includeTurns:!0})).thread.turns?.find(t=>t.id===e)?.status==="inProgress"&&await this.interrupt(e)}turnStartParams(e,r){return{threadId:this.id,input:[{type:"text",text:e,text_elements:[]}],cwd:this.workingDirectory,approvalPolicy:"never",model:this.model,...r?.collaborationMode?{collaborationMode:r.collaborationMode}:null}}async*eventsForTurn(e,r,n,t,o=!1){const a=[...r||o?[{type:"thread.started",thread_id:this.id},{type:"turn.started",turn_id:e}]:[],...r?A(r):[]];let d=r?.status==="completed"||r?.status==="failed"||r?.status==="interrupted",i,u=!1,p=()=>{};const l=({method:h,params:w})=>{if(u)return;const g=M(h,w,this.id,e);g&&(a.push(g),(g.type==="turn.completed"||g.type==="turn.failed")&&(d=!0),p())},y=h=>{i=h,d=!0,p()},m=()=>{u=!0,a.length=0,d=!0,p()};c.on("notification",l),c.on("exit",y),n?.addEventListener("abort",m,{once:!0}),n?.aborted&&m();try{for(await t?.();!d||a.length>0;){for(;a.length>0;)yield a.shift();if(d)break;await new Promise(h=>{const w=setTimeout(()=>{p=()=>{},h()},50);p=()=>{clearTimeout(w),p=()=>{},h()}})}i&&(yield{type:"error",message:i.message})}finally{c.off("notification",l),c.off("exit",y),n?.removeEventListener("abort",m)}}}function C(s,e){return[`The user answered a previous request_user_input prompt (${s}), but the original pending tool request is no longer active.`,"Continue the task using this answer:",JSON.stringify(e,null,2)].join(`
|
|
3
|
+
`)}class F{sessions=new Map;constructor(){for(const e of U())this.sessions.set(e.sessionId,{workdir:e.workdir,botName:e.botName??"main",llmProxyBinding:e.llmProxyBinding});v.info(`SessionManager: loaded ${this.sessions.size} persisted sessions`)}async getOrCreate(e,r,n,t,o,a,d){const i=this.resolveWorkdir(n,t);if(e){const p=this.sessions.get(e);if(p&&p.workdir===i){const l=p.llmProxyBinding??d,y=await c.request("thread/resume",this.threadResumeParams(e,o,i,a,l));if(!p.llmProxyBinding&&l){const m={...p,llmProxyBinding:l};this.sessions.set(e,m),I({sessionId:e,botName:m.botName,workdir:m.workdir,createdAt:Date.now(),llmProxyBinding:l})}return{thread:new k(y.thread.id,o,i),sessionId:e,isNewSession:!1}}}if(n&&!P(i))throw new T(i);_(i,{recursive:!0});const u=await c.request("thread/start",this.threadStartParams(o,i,a,d));return{thread:new k(u.thread.id,o,i),sessionId:void 0,isNewSession:!0}}async fork(e,r,n,t,o,a,d){const i=this.resolveWorkdir(n,t);if(n&&!P(i))throw new T(i);_(i,{recursive:!0});const p=(await c.request("thread/fork",this.threadForkParams(e.threadId,e.turnId,o,i,a,d))).thread.id;return this.persist(p,r,n,t,d),{thread:new k(p,o,i),sessionId:p,isNewSession:!1}}persist(e,r,n,t,o){const a=r??"main",d=this.resolveWorkdir(n,t);this.sessions.set(e,{botName:a,workdir:d,llmProxyBinding:o}),I({sessionId:e,botName:a,workdir:d,createdAt:Date.now(),llmProxyBinding:o})}bindingFor(e){return e?this.sessions.get(e)?.llmProxyBinding:void 0}workdirFor(e){return e?this.sessions.get(e)?.workdir:void 0}hasSession(e){return!!e&&this.sessions.has(e)}resolveWorkdir(e,r){return N(f,r,e)}threadStartParams(e,r,n,t){return{model:e,modelProvider:f.codex.baseUrl?"custom":null,cwd:r,approvalPolicy:"never",sandbox:n,config:this.codexConfig(t),developerInstructions:x,dynamicTools:E(),experimentalRawEvents:!1,persistExtendedHistory:!1}}threadResumeParams(e,r,n,t,o){return{threadId:e,model:r,modelProvider:f.codex.baseUrl?"custom":null,cwd:n,approvalPolicy:"never",sandbox:t,config:this.codexConfig(o),developerInstructions:x,excludeTurns:!0,persistExtendedHistory:!1}}threadForkParams(e,r,n,t,o,a){return{threadId:e,lastTurnId:r,model:n,modelProvider:f.codex.baseUrl?"custom":null,cwd:t,approvalPolicy:"never",sandbox:o,config:this.codexConfig(a),developerInstructions:x,ephemeral:!1,excludeTurns:!0}}codexConfig(e){return{approval_policy:"never",...f.codex.baseUrl?{model_provider:"custom",model_reasoning_effort:"medium",disable_response_storage:!0,model_providers:{custom:{name:"custom",base_url:f.codex.baseUrl,wire_api:"responses",...f.codex.apiKey?{env_key:"OPENAI_API_KEY"}:null,...e?{http_headers:{"X-Elevo-LLM-Binding":e}}:null}},"features.default_mode_request_user_input":!0}:null}}}f.codex.apiKey&&!process.env.OPENAI_API_KEY&&(process.env.OPENAI_API_KEY=f.codex.apiKey);function A(s){const e=[];for(const r of s.items??[])e.push({type:"item.completed",item:r});return s.status==="completed"?e.push({type:"turn.completed"}):s.status==="failed"&&e.push({type:"turn.failed",error:{message:s.error?.message??"Codex turn failed"}}),e}function M(s,e,r,n){const t=e;if(!t)return;const o=t.threadId,a=t.turnId;if(!(typeof o=="string"&&o!==r)&&!(typeof a=="string"&&a!==n)){if(s==="item/started"&&S(t.item))return{type:"item.started",item:t.item};if(s==="item/completed"&&S(t.item))return{type:"item.completed",item:t.item};if(s==="item/agentMessage/delta")return b(t,"agentMessage");if(s==="item/reasoning/summaryTextDelta"||s==="item/reasoning/textDelta")return b(t,"reasoning");if(s==="item/plan/delta")return b(t,"plan");if(s==="item/tool/requestUserInput")return{type:"item.tool.requestUserInput",params:t};if(s==="turn/diff/updated"&&typeof t.diff=="string")return{type:"turn.diff.updated",diff:t.diff};if(s==="thread/tokenUsage/updated")return{type:"thread.tokenUsage.updated",usage:R(t)};if(s==="thread/name/updated"&&typeof t.name=="string"&&t.name.trim())return{type:"thread.name.updated",thread_id:r,name:t.name.trim()};if(s==="turn/completed"){const d=t.turn;return d?.status==="failed"?{type:"turn.failed",error:{message:d.error?.message??"Codex turn failed"}}:{type:"turn.completed"}}if(s==="error")return console.error("Received error notification from app-server:",t),{type:"error",message:q(t)}}}function q(s){const e=s.error,r=e&&typeof e=="object"&&"message"in e?e.message:void 0,n=s.additionalDetails,t=typeof r=="string"&&r.trim()?r:"Codex app-server error";return typeof n=="string"&&n.trim()?`${t}: ${n}`:t}function b(s,e){if(!(typeof s.itemId!="string"||typeof s.delta!="string"))return{type:"item.delta",item_id:s.itemId,item_type:e,delta:s.delta}}function R(s){const e=s.tokenUsage;if(!e||typeof e!="object")return null;const r=e,n=r.total,t=r.last;if(!n||typeof n!="object"||!t||typeof t!="object")return null;const o=d=>{const i=d;return{input_tokens:typeof i.inputTokens=="number"?i.inputTokens:void 0,output_tokens:typeof i.outputTokens=="number"?i.outputTokens:void 0,total_tokens:typeof i.totalTokens=="number"?i.totalTokens:void 0}},a=r.modelContextWindow;return{total:o(n),last:o(t),model_context_window:typeof a=="number"?a:void 0}}function S(s){return!!(s&&typeof s=="object"&&"type"in s&&"id"in s)}const Y=new F;export{k as CodexThread,T as WorkdirNotFoundError,Y as sessionManager};
|
package/dist/config.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type AgentAuthConfig, type AgentWorkspacesConfig, type GitInitConfig } from "@messenger-agent/shared/agent-config";
|
|
2
2
|
import { type LogLevel } from "@messenger-agent/shared/logger";
|
|
3
|
+
import { type ScheduleServiceConfig } from "@messenger-agent/shared/schedule-tools";
|
|
3
4
|
export type AppConfig = {
|
|
4
5
|
configPath: string;
|
|
5
6
|
logLevel: LogLevel;
|
|
@@ -19,6 +20,7 @@ export type AppConfig = {
|
|
|
19
20
|
baseUrl?: string;
|
|
20
21
|
imageModel: string;
|
|
21
22
|
};
|
|
23
|
+
schedule: ScheduleServiceConfig;
|
|
22
24
|
tunnel: {
|
|
23
25
|
enabled: boolean;
|
|
24
26
|
serverUrl?: string;
|
package/dist/config.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{existsSync as
|
|
1
|
+
import{existsSync as M,readFileSync as U}from"node:fs";import{tmpdir as b}from"node:os";import{join as a}from"node:path";import{parse as I}from"yaml";import{z as e}from"zod";import{normalizeOptional as n,parseAgentAuthConfig as v,parseAgentWorkspacesConfig as h,parseGitInitConfig as x}from"@messenger-agent/shared/agent-config";import{logger as s,normalizeLogLevel as L,setLogFile as y,setLogLevel as k}from"@messenger-agent/shared/logger";import{deriveScheduleServiceConfig as A}from"@messenger-agent/shared/schedule-tools";const D="wss://m.elevo.vip/agent-bridge/tunnel",j="https://m.elevo.vip/agent-bridge/llm/v1",F=e.object({log_level:e.string().optional(),port:e.coerce.number().int().positive().optional(),auth_tokens:e.record(e.string(),e.string()).optional(),workspaces:e.array(e.object({id:e.string().optional(),name:e.string().optional(),path:e.string().optional()})).optional(),file_uploads:e.object({temp_dir:e.string().optional()}).optional(),data_dir:e.string().optional(),codex:e.object({port:e.coerce.number().int().positive().optional(),data_dir:e.string().optional(),file_uploads:e.object({temp_dir:e.string().optional()}).optional(),api_key:e.string().optional(),base_url:e.string().optional()}).optional(),openai:e.object({api_key:e.string().optional(),base_url:e.string().optional(),image_model:e.string().optional()}).optional(),schedule:e.object({base_url:e.string().optional(),api_key:e.string().optional()}).optional(),gitlab:e.object({ca_cert_path:e.string().optional(),host:e.string().optional()}).optional(),git:e.object({co_authors:e.array(e.string()).optional()}).optional(),tunnel:e.object({enabled:e.boolean().optional(),server_url:e.string().optional(),tunnel_id:e.string().optional(),token:e.string().optional(),reconnect_initial_ms:e.number().int().positive().optional(),reconnect_max_ms:e.number().int().positive().optional(),heartbeat_interval_ms:e.number().int().positive().optional()}).optional()}).loose();function S(){const t=process.env.AGENT_CONFIG_PATH??"./agent-config.yaml";if(!M(t)){const l="./data",_=a(l,"logs","codex-agent.log");return k("info"),y(_),s.warn(`Config file not found at ${t}`),{configPath:t,logLevel:"info",logFile:_,port:3e3,fileUploads:{tempDir:a(b(),"codex-agent-uploads")},dataDir:l,sessionsDbPath:a(l,"sessions.db"),codex:{},openai:{imageModel:"gpt-image-2"},schedule:{},tunnel:{enabled:!1,reconnectInitialMs:1e3,reconnectMaxMs:3e4,heartbeatIntervalMs:3e4},...v({}),...h({}),...x({})}}let p;try{p=I(U(t,"utf-8"))}catch(l){s.error(`Failed to parse config file at ${t}:`,l),p={}}const r=F.safeParse(p??{});r.success||s.error(`Invalid config format at ${t}:`,r.error.issues);const o=r.success?r.data:{},g=L(o.log_level),c=n(o.codex?.data_dir)??n(o.data_dir)??"./data",u=a(c,"logs","codex-agent.log"),i=o.tunnel?.enabled??!1,d=n(o.tunnel?.token),m=n(o.openai?.api_key)??(i?d:void 0),f=n(o.openai?.base_url)??(i?j:void 0);k(g),y(u);const C={configPath:t,logLevel:g,logFile:u,port:o.codex?.port??o.port??3e3,fileUploads:{tempDir:n(o.codex?.file_uploads?.temp_dir)??n(o.file_uploads?.temp_dir)??a(b(),"codex-agent-uploads")},dataDir:c,sessionsDbPath:a(c,"sessions.db"),codex:{apiKey:n(o.codex?.api_key)??(i?d:void 0),baseUrl:n(o.codex?.base_url)??(i?j:void 0)},openai:{apiKey:m,baseUrl:f,imageModel:n(o.openai?.image_model)??"gpt-image-2"},schedule:A({baseUrl:n(o.schedule?.base_url),apiKey:n(o.schedule?.api_key)},f,m),tunnel:{enabled:i,serverUrl:n(o.tunnel?.server_url)??(i?D:void 0),tunnelId:n(o.tunnel?.tunnel_id),token:d,reconnectInitialMs:o.tunnel?.reconnect_initial_ms??1e3,reconnectMaxMs:o.tunnel?.reconnect_max_ms??3e4,heartbeatIntervalMs:o.tunnel?.heartbeat_interval_ms??3e4},...v(o),...h(o),...x(o)};return s.info(`Loaded agent config from ${t}`),C}const E=S();export{E as appConfig};
|
package/dist/dynamic-tools.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import l from"node:path";import{mkdir as f,writeFile as y}from"node:fs/promises";import{generateImage as T}from"ai";import{createOpenAI as w}from"@ai-sdk/openai";import{Agent as I,fetch as x}from"undici";import{z as i}from"zod";import{executeManagedTaskTool as S,isManagedTaskToolName as b,MANAGED_TASK_TOOL_DEFINITIONS as A}from"@messenger-agent/shared/managed-task-tools";import{AgentFileError as k,resolveAgentFilePath as v}from"@messenger-agent/shared/agent-files";import{executeScheduleTool as E,SCHEDULE_TOOL_DEFINITION as c,ScheduleToolError as _}from"@messenger-agent/shared/schedule-tools";const d=1200*1e3,M=new I({headersTimeout:d,bodyTimeout:d}),R=(t,e)=>x(t,{...e,dispatcher:M}),p=i.object({prompt:i.string().describe("The text prompt describing the image to generate"),store_path:i.string().describe("Absolute file path (including filename) to save the image. If omitted, saves to the current working directory with an auto-generated name.").optional(),size:i.enum(["1024x1024","1536x1024","1024x1536"]).describe("Image size. Leave it undefined to use the auto size.").optional()}),m=i.object({path:i.string().describe("File to send. Absolute paths use the system path; relative paths resolve from the active workspace.")}),N=i.toJSONSchema(p),O=i.toJSONSchema(m);function g(t){return{contentItems:[{type:"inputText",text:JSON.stringify(t)}],success:!0}}const a=new Map;function F(t,e){const o=e.threadRef?.trim();a.set(t,{workspaceRoot:e.workspaceRoot,...o?{threadRef:o}:null,...e.matrixEvent?{matrixEvent:e.matrixEvent}:null,...e.llmProxyBinding?{llmProxyBinding:e.llmProxyBinding}:null})}function u(t,e){const o=a.get(t);if(o)for(const n of e)n&&n!==t&&F(n,o)}function $(t,e){if(t!=="item/started"&&t!=="item/completed"||!e||typeof e!="object")return;const o=e,n=o.item;if(!n||typeof n!="object")return;const r=n;if(r.type==="subAgentActivity"&&r.kind==="started"&&typeof o.threadId=="string"&&typeof r.agentThreadId=="string"){u(o.threadId,[r.agentThreadId]);return}r.type==="collabAgentToolCall"&&r.tool==="spawnAgent"&&typeof r.senderThreadId=="string"&&Array.isArray(r.receiverThreadIds)&&u(r.senderThreadId,r.receiverThreadIds.filter(s=>typeof s=="string"))}async function h(t){const e=a.get(t);if(e)return e.workspaceRoot;const{sessionManager:o}=await import("./codex.js"),n=o.workdirFor(t);if(!n)throw new Error(`No workspace context for thread ${t}; the session may not exist in this process`);return n}async function L(t){const{appConfig:e}=await import("./config.js");if(!e.openai.apiKey)throw new Error("Missing openai.api_key in LLM config");return{apiKey:e.openai.apiKey,baseURL:e.openai.baseUrl,imageModel:e.openai.imageModel,llmProxyBinding:a.get(t)?.llmProxyBinding}}async function C(){const{appConfig:t}=await import("./config.js");return t.schedule}function H(){return[{name:"generate_image",description:"Generate an image from a text prompt. The image is saved to the specified path (absolute path including filename) or the current working directory if not specified. Returns the saved file path.",inputSchema:N},{name:"send_file",description:"Send any readable file to the client. Absolute paths use the system path; relative paths resolve from the active workspace. The agent runtime captures this tool call and performs the actual send.",inputSchema:O},...A.map(t=>({name:t.name,description:t.description,inputSchema:t.inputSchema})),{name:c.name,description:c.description,inputSchema:c.inputSchema}]}async function V(t){try{if(t.tool==="generate_image"){const e=p.parse(t.arguments),o=await L(t.threadId),n=w({apiKey:o.apiKey,baseURL:o.baseURL,fetch:R,...o.llmProxyBinding?{headers:{"X-Elevo-LLM-Binding":o.llmProxyBinding}}:null}),{image:r}=await T({model:n.image(o.imageModel),prompt:e.prompt,size:e.size,maxRetries:0,abortSignal:AbortSignal.timeout(d)}),s=e.store_path?l.resolve(e.store_path):l.join(process.cwd(),`generated_${Date.now()}.png`);return await f(l.dirname(s),{recursive:!0}),await y(s,Buffer.from(r.uint8Array)),{contentItems:[{type:"inputText",text:s}],success:!0}}if(t.tool==="send_file"){const e=m.parse(t.arguments),o=await v(e.path,await h(t.threadId));return{contentItems:[{type:"inputText",text:JSON.stringify({path:o})}],success:!0}}if(b(t.tool)){const e=await S(await h(t.threadId),t.tool,t.arguments,a.get(t.threadId));return g(e)}if(t.tool===c.name)return g(await E(await C(),a.get(t.threadId),t.arguments));throw new Error(`Unknown dynamic tool: ${t.tool}`)}catch(e){const o=e instanceof k&&e.code==="INVALID_PATH"||e instanceof Error?e.message:String(e),n=e instanceof _?{error:{code:e.code,message:e.message,retryable:e.retryable,currentRevision:e.currentRevision}}:o;return{contentItems:[{type:"inputText",text:typeof n=="string"?n:JSON.stringify(n)}],success:!1}}}export{H as dynamicToolSpecs,V as handleDynamicToolCall,u as inheritManagedTaskToolContext,$ as inheritManagedTaskToolContextFromNotification,F as setManagedTaskToolContext};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
import{existsSync as
|
|
1
|
+
import{existsSync as r,readFileSync as c}from"node:fs";import{fileURLToPath as o}from"node:url";import{logger as i}from"@messenger-agent/shared/logger";const d=[o(new URL("./assets/codex-home/AGENTS.md",import.meta.url)),o(new URL("../../../assets/codex-home/AGENTS.md",import.meta.url)),"/app/assets/codex-home/AGENTS.md"],a="## Codex Managed Task Tools\n\nWhen using managed task tools in Codex, call these tool names directly: `search_managed_tasks`, `get_managed_task`, `create_managed_task`, `update_managed_task`, `apply_managed_task_patch`, and `delete_managed_task`.\n",n="## Schedule Tool\n\nUse the single `schedule` tool to create, list, inspect, update, pause, resume, or cancel schedules in the current trusted Matrix context. The action is selected inside `input.action`; never ask for or invent a Room ID, actor ID, source event, or service credential. After create or update succeeds, repeat the service's normalized rule, absolute next run time, IANA timezone, message, and mention MXIDs to the user so relative times and recurrence are unambiguous.\n";function m(s){const e=[s??process.env.CODEX_AGENTS_TEMPLATE_PATH,...d].find(t=>!!(t&&r(t)));return e?`${c(e,"utf-8").trimEnd()}
|
|
2
2
|
|
|
3
|
-
${
|
|
3
|
+
${a}
|
|
4
|
+
${n}`:(i.warn("Codex platform instructions template not found"),`${a}
|
|
5
|
+
${n}`)}const _=m();export{_ as codexPlatformInstructions,m as loadCodexPlatformInstructions};
|
package/dist/routes/chat.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Hono as
|
|
2
|
-
`).trim();if(!r)throw new D(400,{message:"No supported message content found"});return r}function he(t){if(!t.some(o=>o.type==="tool"))return;if(t.length!==1)throw new D(400,{message:"When a tool part is present, the message must contain exactly one part"});const r=Gt.safeParse(t[0]);if(!r.success)throw new D(400,{message:`Invalid requestUserInput tool part: ${r.error.message}`});return{itemId:r.data.toolCallId,response:r.data.output,sourceTurnId:r.data.sourceTurnId}}function m(t,e,r,o){const i=[e,r,o].filter(Boolean).join(":"),d=t.get(i);if(d)return d;const x=Kt();return t.set(i,x),x}function Ce(t,e){return t&&t.length>0?t:e}function ve(t){at.debug("Received chat stream event:",t)}function xe(t){if(t instanceof Qt||t&&typeof t=="object"&&"path"in t&&typeof t.path=="string")return t.path;if(t instanceof Error&&t.message.startsWith("Workdir not found: "))return t.message.slice(19)}B.post("/v1/chat/:conversation_id/cancel",async t=>{const e=t.req.param("conversation_id");try{return await Ot(e)?t.json({success:!0}):t.json({error:se(e)},404)}catch(r){const o=r instanceof Error?r.message:"Failed to interrupt Codex conversation";return at.error(`Failed to cancel Codex conversation ${e}:`,r),t.json({error:{type:"server_error",code:"cancel_failed",message:o}},500)}}),B.get("/admin/status",t=>t.json({activeTaskCount:z.size,waitingClientToolCount:k.size,clientToolWaits:[...k.values()].map(({conversationId:e,toolCallId:r,toolName:o,since:i})=>({conversationId:e,toolCallId:r,toolName:o,since:i}))}));async function Nt({body:t,headers:e}){const{conversationId:r,fork:o,model:i,message:d}=t,x=v(e,"X-Matrix-Bot-Name"),K=v(e,"X-Matrix-Workdir"),U=v(e,"X-Matrix-Workspace-ID"),Ut=v(e,"X-Matrix-Agent-Mode"),Q=v(e,"X-Elevo-LLM-Binding")?.trim()||void 0,V=o?void 0:j.bindingFor(r);if(Q&&V&&Q!==V)throw new q(409,"LLM proxy binding does not match the existing conversation");const L=V??Q,Lt=de(e),At=ue(e),G=he(d.parts),Y=G?void 0:await Ie(d.parts),ot=G?void 0:we(r),c=G,O=Y&&ot?ot:void 0;let A=!o&&r?_t(r):void 0;const Wt=(()=>{try{return Zt(vt,U)}catch(S){throw new q(400,S instanceof Error?S.message:"Invalid workspace")}})(),{thread:y,isNewSession:Ft}=await(async()=>{try{if(o){if(!("threadId"in o))throw new q(400,"Codex fork requires threadId and turnId");return await j.fork(o,x,K,U,i,"danger-full-access",L)}return await j.getOrCreate(r,x,K,U,i,"danger-full-access",L)}catch(S){A&&me(A);const _=xe(S);throw _?new q(400,`Workdir not found: ${_}`):S}})();A??=_t(y.id),Yt(y.id,{workspaceRoot:Wt,threadRef:Lt,matrixEvent:At,llmProxyBinding:L});const it=ie(Ut,i);return{run:async(S,_)=>{const w=A,W=w.abortController;z.add(W);const Z=()=>{N(w)&&Ot(w.state.conversationId).catch(a=>at.error("Failed to cancel disconnected Codex stream:",a))};_?.aborted&&Z(),_?.addEventListener("abort",Z,{once:!0});let b=!!c,st=!!c,dt=!1,l,I=y.id,h,F=!1,P;const ut=new Set,lt=new Set,X=new Set,p=new Map,ct=new Set,Xt=new Set,pt=new Set;let ft,tt,mt;const wt=()=>{P=setTimeout(()=>{s({type:"heartbeat"}).catch(()=>{})},6e4)},yt=async a=>{P&&clearTimeout(P),a.data==="[DONE]"?await S.writeDone():await S.writeData(JSON.parse(String(a.data))),wt()},s=async a=>{await yt({data:JSON.stringify(a)})},$=async()=>{await yt({data:"[DONE]"})},$t=async()=>{const a=qt(l,y.id),n=rt.get(a);n&&(rt.delete(a),await s({type:"data",kind:"diff",data:{diff:n}}))},gt=async(a,n)=>{if(a.type!=="contextCompaction")return!1;if(n==="end"&&!ct.has(a.id))return!0;const u=n==="start"?ct:Xt;return u.has(a.id)||(u.add(a.id),await s({type:"data",kind:"compact",data:n==="start"?{phase:n,activityId:a.id}:{phase:n,activityId:a.id,status:"completed"}})),!0},et=async a=>{if(a.type!=="subAgentActivity")return!1;if(pt.has(a.id))return!0;pt.add(a.id);const n=m(p,l,a.id),u={activity:a.kind,agentThreadId:a.agentThreadId,...a.agentPath?{agentPath:a.agentPath}:null};return await s({type:"tool-input-available",toolCallId:n,toolName:`subagent_${a.kind}`,...a.agentPath?{title:a.agentPath}:null,input:u}),await s(a.kind==="interrupted"?{type:"tool-output-error",toolCallId:n,errorText:"Subagent interrupted"}:{type:"tool-output-available",toolCallId:n,output:u}),!0};wt();const It=a=>{l!==a&&(l=a,Ft&&j.persist(a,x,K,U,L))},E=async(a,n)=>{b||(b=!0,It(a),await s({type:"start",messageMetadata:{conversationId:a,threadId:a,...n?{turnId:n}:null}}),await s({type:"start-step"}),st=!0)},nt=async a=>{dt||(dt=!0,st&&(await $t(),a==="stop"&&tt&&await s({type:"data",kind:"token_usage",data:tt}),await s({type:"finish-step"})),await s({type:"finish",finishReason:a}),await $())},ht=async a=>{if(ut.has(a.id))return;ut.add(a.id);const n=a.type==="plan"?{type:"plan"}:void 0;await s({type:"text-start",id:a.id,...n?{textMetadata:n}:{}})},Ct=async a=>{lt.has(a.id)||(lt.add(a.id),await s({type:"reasoning-start",id:a.id}))},jt=async a=>{const n=xt(a);if(n)return await s({type:"tool-input-available",toolCallId:m(p,l,a.id),toolName:"bash",input:ne(n.command)}),!0;const u=Tt(a);if(u){for(const[T,C]of u.changes.entries())await s({type:"tool-input-available",toolCallId:m(p,l,a.id,String(T)),toolName:C.kind.type==="update"?"Edit":C.kind.type==="add"?"Add":"Delete",title:C.path,input:C});return!0}const g=Et(a);if(g)return await s({type:"tool-input-available",toolCallId:m(p,l,a.id),toolName:g.tool,input:g.arguments}),!0;const R=bt(a);if(R)return await s({type:"tool-input-available",toolCallId:m(p,l,a.id),toolName:R.tool,input:R.arguments}),!0;const M=Rt(a);return M?(await s({type:"tool-input-available",toolCallId:m(p,l,a.id),toolName:"web_search",title:M.query,input:kt(M)}),!0):!1},Bt=async a=>{const n=xt(a);if(n){const T=n.status==="failed"||n.status==="declined";return await s(T?{type:"tool-output-error",toolCallId:m(p,l,a.id),errorText:Ce(n.aggregatedOutput,"Command execution failed")}:{type:"tool-output-available",toolCallId:m(p,l,a.id),output:n.aggregatedOutput??""}),!0}const u=Tt(a);if(u){const T=u.status==="failed"||u.status==="declined";for(const[C]of u.changes.entries())await s(T?{type:"tool-output-error",toolCallId:m(p,l,a.id,String(C)),errorText:u.status}:{type:"tool-output-available",toolCallId:m(p,l,a.id,String(C)),output:u.status,preliminary:!1});return!0}const g=Et(a);if(g){const T=g.status==="failed";return await s(T?{type:"tool-output-error",toolCallId:m(p,l,a.id),errorText:g.error?.message??"MCP tool call failed"}:{type:"tool-output-available",toolCallId:m(p,l,a.id),output:re(g)}),!0}const R=bt(a);if(R){const T=R.status==="failed"||R.success===!1,C=ae(R);return await s(T?{type:"tool-output-error",toolCallId:m(p,l,a.id),errorText:C||"Dynamic tool call failed"}:{type:"tool-output-available",toolCallId:m(p,l,a.id),output:C}),!0}const M=Rt(a);return M?(await s({type:"tool-output-available",toolCallId:m(p,l,a.id),output:kt(M)}),!0):!1};try{if(c&&!w.ownsOutput){await pe(w,y,c.itemId,c.response),k.delete(J(r,c.itemId)),await $();return}const a=O?await fe(w,y,O,Y,it):c?await ce(w,y,()=>y.continueWithUserInput(c.itemId,c.response,{signal:W.signal,sourceTurnId:c.sourceTurnId})):await le(w,y,Y,it);if(c?k.delete(J(r,c.itemId)):O&&k.delete(J(r,O.toolCallId)),Mt(w,y,a.turnId),!w.ownsOutput){await $();return}c?(await s({type:"data",kind:"agent_session",data:{agentType:"codex",threadId:y.id,turnId:a.turnId}}),await s({type:"tool-output-available",toolCallId:c.itemId,toolName:"request_user_input",output:c.response})):O&&await s({type:"tool-output-error",toolCallId:O.toolCallId,toolName:"request_user_input",errorText:"Question interrupted by text response"});for await(const n of a.events)if(n.type!=="item.delta"&&ve(n),n.type==="thread.started")I=n.thread_id,It(I);else if(n.type==="turn.started")h=n.turn_id,Mt(w,y,h),await E(I,h);else if(n.type==="item.started"){if(b||await E(I,h),await gt(n.item,"start")||await et(n.item)||await jt(n.item))continue;n.item.type==="agentMessage"||n.item.type==="plan"?await ht(n.item):n.item.type==="reasoning"&&await Ct(n.item)}else if(n.type==="item.delta")b||await E(I,h),n.item_type==="agentMessage"||n.item_type==="plan"?(X.add(n.item_id),await s({type:"text-delta",id:n.item_id,delta:n.delta})):n.item_type==="reasoning"&&(X.add(n.item_id),await s({type:"reasoning-delta",id:n.item_id,delta:n.delta}));else if(n.type==="item.updated"){if(await et(n.item))continue}else if(n.type==="item.completed"){if(b||await E(I,h),await gt(n.item,"end")||await et(n.item)||await Bt(n.item))continue;if(n.item.type==="agentMessage"||n.item.type==="plan"){await ht(n.item);const u=St(n.item)??"";u&&!X.has(n.item.id)&&await s({type:"text-delta",id:n.item.id,delta:u}),await s({type:"text-end",id:n.item.id})}else if(n.item.type==="reasoning"){await Ct(n.item);const u=St(n.item)??"";u&&!X.has(n.item.id)&&await s({type:"reasoning-delta",id:n.item.id,delta:u}),await s({type:"reasoning-end",id:n.item.id})}}else if(n.type==="item.tool.requestUserInput"){b||await E(I,h),k.set(J(l,n.params.itemId),{conversationId:l,toolCallId:n.params.itemId,toolName:"request_user_input",turnId:n.params.turnId,since:new Date().toISOString()}),await s({type:"tool-input-available",toolCallId:n.params.itemId,toolName:"request_user_input",input:n.params}),await $();return}else if(n.type==="turn.diff.updated")b||await E(I,h),rt.set(qt(l,y.id),n.diff);else if(n.type==="thread.tokenUsage.updated"){const u=oe(n.usage);if(u){const g=ee(mt,u.last);g&&(mt=g,tt={...u,last:g})}}else if(n.type==="turn.failed"){ft!==n.error.message&&await s({type:"error",errorText:n.error.message}),await nt("error"),F=!0,Pt(w);return}else n.type==="error"&&(ft=n.message,await s({type:"error",errorText:n.message}));F=!W.signal.aborted,F&&Pt(w),b||await E(I,h),await nt("stop")}catch(a){const n=a instanceof Error?a.message:"Chat stream failed";b||await E(I,h),await s({type:"error",errorText:n}),await nt("error")}finally{P&&clearTimeout(P),_?.removeEventListener("abort",Z),z.delete(W),F||Dt(w)}}}}async function Le({body:t,headers:e,signal:r},o){await(await Nt({body:t,headers:e})).run(o,r)}B.post("/v1/chat/stream",Ht("json",Vt),async t=>{const e=t.req.valid("json"),r=await(async()=>{try{return await Nt({body:e,headers:t.req.raw.headers})}catch(o){throw o instanceof q?new D(o.status,{message:o.message}):o}})();return Jt(t,async o=>{const i=async d=>{await o.writeSSE(d)};await r.run({writeData:async d=>{await i({data:JSON.stringify(d)})},writeDone:async()=>{await i({data:"[DONE]"})}},t.req.raw.signal)})});var Ae=B;export{q as ChatRequestError,Ot as cancelCodexConversation,Ue as codexActivitySnapshot,Ae as default,Le as handleCodexChatStream,Nt as prepareCodexChatStream};
|
|
1
|
+
import{Hono as Kt}from"hono";import{HTTPException as D}from"hono/http-exception";import{zValidator as Qt}from"@hono/zod-validator";import{streamSSE as Vt}from"hono/streaming";import{randomUUID as Gt}from"node:crypto";import{sessionManager as j,WorkdirNotFoundError as Yt}from"../codex.js";import{logger as ot}from"@messenger-agent/shared/logger";import{ChatBodySchema as Zt,RequestUserInputToolPartSchema as te}from"../schemas.js";import{appConfig as Tt}from"../config.js";import{setManagedTaskToolContext as ee}from"../dynamic-tools.js";import{resolveAgentWorkspaceRoot as ae}from"@messenger-agent/shared/agent-workspaces";import{saveUploadedFilePart as ne}from"@messenger-agent/shared/uploaded-files";import{commandExecutionItem as St,addTokenUsage as re,displayCommand as oe,dynamicToolCallItem as Et,dynamicToolCallOutput as ie,fileChangeItem as Rt,itemText as kt,mcpToolCallItem as _t,mcpToolCallOutput as se,toUsage as de,turnOptions as ue,webSearchItem as Ot,webSearchPayload as Mt}from"./shared.js";const B=new Kt,m=new Map,z=new Set,it=new Map,k=new Map;function We(){const t=new Set([...k.values()].map(e=>e.conversationId).filter(e=>!!e));return{active:z.size,waiting:t.size}}function le(t){return{type:"not_found_error",code:"conversation_not_found",message:`Conversation not found or already completed: ${t}`,param:"conversation_id"}}function ce(t){const e=v(t,"X-Matrix-Room-Id")?.trim(),r=v(t,"X-Matrix-Thread-ID")?.trim();return e&&r?`${e}/${r}`:void 0}function pe(t){const e=v(t,"X-Matrix-Room-Id")?.trim(),r=v(t,"X-Matrix-Event-ID")?.trim(),o=v(t,"X-Matrix-Thread-ID")?.trim();if(!(!e||!r))return{roomId:e,eventId:r,...o?{threadRootEventId:o}:null}}class N extends Error{status;constructor(e,r){super(r),this.status=e,this.name="ChatRequestError"}}function v(t,e){return t?.get(e)??void 0}async function Pt(t){const e=m.get(t);if(!e)return!1;for(e.cancelRequested=!0,e.turnId||e.owner?.abortController.abort();;){const r=e.transition;if(await r,r===e.transition)break}return e.thread&&e.turnId&&(e.interrupt||(e.interrupt=e.thread.interrupt(e.turnId).finally(()=>{e.interrupt=void 0})),await e.interrupt),e.owner?.abortController.abort(),e.resolveOwnerReady?.(),m.get(t)===e&&m.delete(t),!0}function Dt(t){let e=m.get(t);e||(e={conversationId:t,generation:0,cancelRequested:!1,transition:Promise.resolve()},m.set(t,e));const r=++e.generation,o=new AbortController,i=!e.owner;return i&&(e.owner={generation:r,abortController:o},e.ownerReady=new Promise(u=>{e.resolveOwnerReady=u})),{state:e,generation:r,abortController:o,ownsOutput:i}}function q(t){return m.get(t.state.conversationId)===t.state&&t.state.owner?.generation===t.generation}async function H(t,e){const r=t.transition;let o;const i=new Promise(u=>{o=u});t.transition=r.then(()=>i),await r;try{return await e()}finally{o()}}async function fe(t,e,r,o){!t.ownsOutput&&!t.state.turnId&&await t.state.ownerReady;try{return await H(t.state,async()=>{const{state:i}=t;if(m.get(i.conversationId)!==i||i.cancelRequested)throw new DOMException("Chat stream was cancelled before the turn started","AbortError");i.thread=e;const u=i.turnId?await e.steerStreamed(r,i.turnId,{signal:t.abortController.signal}):await e.runStreamed(r,{...o,signal:t.abortController.signal});return i.turnId=u.turnId,u})}finally{t.ownsOutput&&t.state.resolveOwnerReady?.()}}async function me(t,e,r){return H(t.state,async()=>{const{state:o}=t;if(!q(t)||o.cancelRequested)throw new DOMException("Chat stream was cancelled before user input was submitted","AbortError");o.thread=e;const i=await r();return o.turnId=i.turnId,o.resolveOwnerReady?.(),i})}async function we(t,e,r,o){return H(t.state,async()=>{const{state:i}=t;if(m.get(i.conversationId)!==i||i.cancelRequested)throw new DOMException("Chat stream was cancelled before user input was submitted","AbortError");i.thread=e;const u=await e.submitPendingUserInput(r,o);return u&&(i.turnId=u),u})}async function ye(t,e,r,o,i){return H(t.state,async()=>{const{state:u}=t;if(m.get(u.conversationId)!==u||u.cancelRequested)throw new DOMException("Chat stream was cancelled before the turn started","AbortError");u.thread=e,await e.interruptPendingUserInput(r.turnId,r.toolCallId),u.turnId=void 0;const T=await e.runStreamed(o,{...i,signal:t.abortController.signal});return u.turnId=T.turnId,T})}function Nt(t,e,r){t.state.thread=e,t.state.turnId=r}function qt(t){const{state:e}=t;q(t)&&(e.owner=void 0,e.resolveOwnerReady?.(),e.turnId=void 0,m.get(e.conversationId)===e&&m.delete(e.conversationId))}function Ut(t){q(t)&&(t.state.owner=void 0,t.state.resolveOwnerReady?.(),!t.state.turnId&&m.get(t.state.conversationId)===t.state&&m.delete(t.state.conversationId))}function ge(t){q(t)&&(Ut(t),t.state.resolveOwnerReady?.(),!t.state.turnId&&m.get(t.state.conversationId)===t.state&&m.delete(t.state.conversationId))}function J(t,e){return`${t??"unknown"}:${e}`}function Ie(t){if(t)return[...k.values()].find(e=>e.conversationId===t)}function Lt(t,e){return t??e}function he(t){return t.type==="file"&&"mediaType"in t&&typeof t.mediaType=="string"&&"url"in t&&typeof t.url=="string"&&(!("filename"in t)||t.filename===void 0||typeof t.filename=="string")}async function Ce(t){if(t.type==="text"&&typeof t.text=="string")return t.text;if(he(t))return ne(t,Tt.fileUploads.tempDir);throw new D(400,{message:`Unsupported message part type: ${t.type}`})}async function ve(t){const r=(await Promise.all(t.map(Ce))).filter(o=>!!(o&&o.trim().length>0)).join(`
|
|
2
|
+
`).trim();if(!r)throw new D(400,{message:"No supported message content found"});return r}function xe(t){if(!t.some(o=>o.type==="tool"))return;if(t.length!==1)throw new D(400,{message:"When a tool part is present, the message must contain exactly one part"});const r=te.safeParse(t[0]);if(!r.success)throw new D(400,{message:`Invalid requestUserInput tool part: ${r.error.message}`});return{itemId:r.data.toolCallId,response:r.data.output,sourceTurnId:r.data.sourceTurnId}}function w(t,e,r,o){const i=[e,r,o].filter(Boolean).join(":"),u=t.get(i);if(u)return u;const T=Gt();return t.set(i,T),T}function be(t,e){return t&&t.length>0?t:e}function Te(t){ot.debug("Received chat stream event:",t)}function Se(t){if(t instanceof Yt||t&&typeof t=="object"&&"path"in t&&typeof t.path=="string")return t.path;if(t instanceof Error&&t.message.startsWith("Workdir not found: "))return t.message.slice(19)}B.post("/v1/chat/:conversation_id/cancel",async t=>{const e=t.req.param("conversation_id");try{return await Pt(e)?t.json({success:!0}):t.json({error:le(e)},404)}catch(r){const o=r instanceof Error?r.message:"Failed to interrupt Codex conversation";return ot.error(`Failed to cancel Codex conversation ${e}:`,r),t.json({error:{type:"server_error",code:"cancel_failed",message:o}},500)}}),B.get("/admin/status",t=>t.json({activeTaskCount:z.size,waitingClientToolCount:k.size,clientToolWaits:[...k.values()].map(({conversationId:e,toolCallId:r,toolName:o,since:i})=>({conversationId:e,toolCallId:r,toolName:o,since:i}))}));async function At({body:t,headers:e}){const{conversationId:r,fork:o,model:i,effort:u,message:T}=t,K=v(e,"X-Matrix-Bot-Name"),Q=v(e,"X-Matrix-Workdir"),U=v(e,"X-Matrix-Workspace-ID"),Wt=v(e,"X-Matrix-Agent-Mode"),V=v(e,"X-Elevo-LLM-Binding")?.trim()||void 0,G=o?void 0:j.bindingFor(r);if(V&&G&&V!==G)throw new N(409,"LLM proxy binding does not match the existing conversation");const L=G??V,Ft=ce(e),Xt=pe(e),Y=xe(T.parts),Z=Y?void 0:await ve(T.parts),st=Y?void 0:Ie(r),p=Y,_=Z&&st?st:void 0;let A=!o&&r?Dt(r):void 0;const $t=(()=>{try{return ae(Tt,U)}catch(S){throw new N(400,S instanceof Error?S.message:"Invalid workspace")}})(),{thread:c,isNewSession:jt}=await(async()=>{try{if(o){if(!("threadId"in o))throw new N(400,"Codex fork requires threadId and turnId");return await j.fork(o,K,Q,U,i,"danger-full-access",L)}return await j.getOrCreate(r,K,Q,U,i,"danger-full-access",L)}catch(S){A&&ge(A);const O=Se(S);throw O?new N(400,`Workdir not found: ${O}`):S}})();A??=Dt(c.id),ee(c.id,{workspaceRoot:$t,threadRef:Ft,matrixEvent:Xt,llmProxyBinding:L});const dt=ue(Wt,i,u);return{run:async(S,O)=>{const y=A,W=y.abortController;z.add(W);const tt=()=>{q(y)&&Pt(y.state.conversationId).catch(n=>ot.error("Failed to cancel disconnected Codex stream:",n))};O?.aborted&&tt(),O?.addEventListener("abort",tt,{once:!0});let x=!!p,ut=!!p,lt=!1,l,I=c.id,h,F=!1,P;const ct=new Set,pt=new Set,X=new Set,f=new Map,ft=new Set,Bt=new Set,mt=new Set;let wt,et,yt;const gt=()=>{P=setTimeout(()=>{s({type:"heartbeat"}).catch(()=>{})},6e4)},It=async n=>{P&&clearTimeout(P),n.data==="[DONE]"?await S.writeDone():await S.writeData(JSON.parse(String(n.data))),gt()},s=async n=>{await It({data:JSON.stringify(n)})},$=async()=>{await It({data:"[DONE]"})},zt=async()=>{const n=Lt(l,c.id),a=it.get(n);a&&(it.delete(n),await s({type:"data",kind:"diff",data:{diff:a}}))},ht=async(n,a)=>{if(n.type!=="contextCompaction")return!1;if(a==="end"&&!ft.has(n.id))return!0;const d=a==="start"?ft:Bt;return d.has(n.id)||(d.add(n.id),await s({type:"data",kind:"compact",data:a==="start"?{phase:a,activityId:n.id}:{phase:a,activityId:n.id,status:"completed"}})),!0},at=async n=>{if(n.type!=="subAgentActivity")return!1;if(mt.has(n.id))return!0;mt.add(n.id);const a=w(f,l,n.id),d={activity:n.kind,agentThreadId:n.agentThreadId,...n.agentPath?{agentPath:n.agentPath}:null};return await s({type:"tool-input-available",toolCallId:a,toolName:`subagent_${n.kind}`,...n.agentPath?{title:n.agentPath}:null,input:d}),await s(n.kind==="interrupted"?{type:"tool-output-error",toolCallId:a,errorText:"Subagent interrupted"}:{type:"tool-output-available",toolCallId:a,output:d}),!0};gt();const Ct=n=>{l!==n&&(l=n,jt&&j.persist(n,K,Q,U,L))},E=async(n,a)=>{x||(x=!0,Ct(n),await s({type:"start",messageMetadata:{conversationId:n,threadId:n,...a?{turnId:a}:null}}),await s({type:"start-step"}),ut=!0)},nt=async n=>{lt||(lt=!0,ut&&(await zt(),n==="stop"&&et&&await s({type:"data",kind:"token_usage",data:et}),await s({type:"finish-step"})),await s({type:"finish",finishReason:n}),await $())};let vt;const rt=async(n,a)=>{const d=a?.trim();!d||d===vt||(vt=d,await s({type:"data",kind:"session_title",data:{agentType:"codex",threadId:n,title:d}}))},xt=async n=>{if(ct.has(n.id))return;ct.add(n.id);const a=n.type==="plan"?{type:"plan"}:void 0;await s({type:"text-start",id:n.id,...a?{textMetadata:a}:{}})},bt=async n=>{pt.has(n.id)||(pt.add(n.id),await s({type:"reasoning-start",id:n.id}))},Ht=async n=>{const a=St(n);if(a)return await s({type:"tool-input-available",toolCallId:w(f,l,n.id),toolName:"bash",input:oe(a.command)}),!0;const d=Rt(n);if(d){for(const[b,C]of d.changes.entries())await s({type:"tool-input-available",toolCallId:w(f,l,n.id,String(b)),toolName:C.kind.type==="update"?"Edit":C.kind.type==="add"?"Add":"Delete",title:C.path,input:C});return!0}const g=_t(n);if(g)return await s({type:"tool-input-available",toolCallId:w(f,l,n.id),toolName:g.tool,input:g.arguments}),!0;const R=Et(n);if(R)return await s({type:"tool-input-available",toolCallId:w(f,l,n.id),toolName:R.tool,input:R.arguments}),!0;const M=Ot(n);return M?(await s({type:"tool-input-available",toolCallId:w(f,l,n.id),toolName:"web_search",title:M.query,input:Mt(M)}),!0):!1},Jt=async n=>{const a=St(n);if(a){const b=a.status==="failed"||a.status==="declined";return await s(b?{type:"tool-output-error",toolCallId:w(f,l,n.id),errorText:be(a.aggregatedOutput,"Command execution failed")}:{type:"tool-output-available",toolCallId:w(f,l,n.id),output:a.aggregatedOutput??""}),!0}const d=Rt(n);if(d){const b=d.status==="failed"||d.status==="declined";for(const[C]of d.changes.entries())await s(b?{type:"tool-output-error",toolCallId:w(f,l,n.id,String(C)),errorText:d.status}:{type:"tool-output-available",toolCallId:w(f,l,n.id,String(C)),output:d.status,preliminary:!1});return!0}const g=_t(n);if(g){const b=g.status==="failed";return await s(b?{type:"tool-output-error",toolCallId:w(f,l,n.id),errorText:g.error?.message??"MCP tool call failed"}:{type:"tool-output-available",toolCallId:w(f,l,n.id),output:se(g)}),!0}const R=Et(n);if(R){const b=R.status==="failed"||R.success===!1,C=ie(R);return await s(b?{type:"tool-output-error",toolCallId:w(f,l,n.id),errorText:C||"Dynamic tool call failed"}:{type:"tool-output-available",toolCallId:w(f,l,n.id),output:C}),!0}const M=Ot(n);return M?(await s({type:"tool-output-available",toolCallId:w(f,l,n.id),output:Mt(M)}),!0):!1};try{if(p&&!y.ownsOutput){await we(y,c,p.itemId,p.response),k.delete(J(r,p.itemId)),await $();return}const n=_?await ye(y,c,_,Z,dt):p?await me(y,c,()=>c.continueWithUserInput(p.itemId,p.response,{signal:W.signal,sourceTurnId:p.sourceTurnId})):await fe(y,c,Z,dt);if(p?k.delete(J(r,p.itemId)):_&&k.delete(J(r,_.toolCallId)),Nt(y,c,n.turnId),!y.ownsOutput){await $();return}p?(await s({type:"data",kind:"agent_session",data:{agentType:"codex",threadId:c.id,turnId:n.turnId}}),await s({type:"tool-output-available",toolCallId:p.itemId,toolName:"request_user_input",output:p.response})):_&&await s({type:"tool-output-error",toolCallId:_.toolCallId,toolName:"request_user_input",errorText:"Question interrupted by text response"});for await(const a of n.events)if(a.type!=="item.delta"&&Te(a),a.type==="thread.started")I=a.thread_id,Ct(I);else if(a.type==="thread.name.updated")await rt(a.thread_id,a.name);else if(a.type==="turn.started")h=a.turn_id,Nt(y,c,h),await E(I,h);else if(a.type==="item.started"){if(x||await E(I,h),await ht(a.item,"start")||await at(a.item)||await Ht(a.item))continue;a.item.type==="agentMessage"||a.item.type==="plan"?await xt(a.item):a.item.type==="reasoning"&&await bt(a.item)}else if(a.type==="item.delta")x||await E(I,h),a.item_type==="agentMessage"||a.item_type==="plan"?(X.add(a.item_id),await s({type:"text-delta",id:a.item_id,delta:a.delta})):a.item_type==="reasoning"&&(X.add(a.item_id),await s({type:"reasoning-delta",id:a.item_id,delta:a.delta}));else if(a.type==="item.updated"){if(await at(a.item))continue}else if(a.type==="item.completed"){if(x||await E(I,h),await ht(a.item,"end")||await at(a.item)||await Jt(a.item))continue;if(a.item.type==="agentMessage"||a.item.type==="plan"){await xt(a.item);const d=kt(a.item)??"";d&&!X.has(a.item.id)&&await s({type:"text-delta",id:a.item.id,delta:d}),await s({type:"text-end",id:a.item.id})}else if(a.item.type==="reasoning"){await bt(a.item);const d=kt(a.item)??"";d&&!X.has(a.item.id)&&await s({type:"reasoning-delta",id:a.item.id,delta:d}),await s({type:"reasoning-end",id:a.item.id})}}else if(a.type==="item.tool.requestUserInput"){x||await E(I,h),k.set(J(l,a.params.itemId),{conversationId:l,toolCallId:a.params.itemId,toolName:"request_user_input",turnId:a.params.turnId,since:new Date().toISOString()}),await s({type:"tool-input-available",toolCallId:a.params.itemId,toolName:"request_user_input",input:a.params}),await $();return}else if(a.type==="turn.diff.updated")x||await E(I,h),it.set(Lt(l,c.id),a.diff);else if(a.type==="thread.tokenUsage.updated"){const d=de(a.usage);if(d){const g=re(yt,d.last);g&&(yt=g,et={...d,last:g})}}else if(a.type==="turn.failed"){await rt(c.id,await c.readName()),wt!==a.error.message&&await s({type:"error",errorText:a.error.message}),await nt("error"),F=!0,qt(y);return}else a.type==="error"&&(wt=a.message,await s({type:"error",errorText:a.message}));F=!W.signal.aborted,F&&qt(y),x||await E(I,h),await rt(c.id,await c.readName()),await nt("stop")}catch(n){const a=n instanceof Error?n.message:"Chat stream failed";x||await E(I,h),await s({type:"error",errorText:a}),await nt("error")}finally{P&&clearTimeout(P),O?.removeEventListener("abort",tt),z.delete(W),F||Ut(y)}}}}async function Fe({body:t,headers:e,signal:r},o){await(await At({body:t,headers:e})).run(o,r)}B.post("/v1/chat/stream",Qt("json",Zt),async t=>{const e=t.req.valid("json"),r=await(async()=>{try{return await At({body:e,headers:t.req.raw.headers})}catch(o){throw o instanceof N?new D(o.status,{message:o.message}):o}})();return Vt(t,async o=>{const i=async u=>{await o.writeSSE(u)};await r.run({writeData:async u=>{await i({data:JSON.stringify(u)})},writeDone:async()=>{await i({data:"[DONE]"})}},t.req.raw.signal)})});var Xe=B;export{N as ChatRequestError,Pt as cancelCodexConversation,We as codexActivitySnapshot,Xe as default,Fe as handleCodexChatStream,At as prepareCodexChatStream};
|
package/dist/routes/shared.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CommandExecutionItem, DynamicToolCallItem, FileChangeItem, McpToolCallItem, ThreadItem, TurnStartParams, Usage, WebSearchItem } from "../app-server-protocol.js";
|
|
2
|
+
import type { AgentEffort } from "../schemas.js";
|
|
2
3
|
export type TokenUsageBreakdown = {
|
|
3
4
|
input_tokens: number;
|
|
4
5
|
output_tokens: number;
|
|
@@ -19,7 +20,7 @@ export declare function textFromContent(content: string | Array<{
|
|
|
19
20
|
text?: string;
|
|
20
21
|
}>): string;
|
|
21
22
|
export declare function inputToPrompt(input: unknown, instructions: string | undefined, isNewSession: boolean, systemReminder?: string): string;
|
|
22
|
-
export declare function turnOptions(agentMode: string | undefined, model: string): {
|
|
23
|
+
export declare function turnOptions(agentMode: string | undefined, model: string, effort: AgentEffort): {
|
|
23
24
|
collaborationMode: TurnStartParams["collaborationMode"];
|
|
24
25
|
};
|
|
25
26
|
export declare function itemText(item: ThreadItem): string | undefined;
|
package/dist/routes/shared.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import{HTTPException as
|
|
2
|
-
`)}function
|
|
1
|
+
import{HTTPException as c}from"hono/http-exception";function h(t,e){const n=(t?.input_tokens??0)+e.input_tokens,o=(t?.output_tokens??0)+e.output_tokens,r=(t?.total_tokens??0)+e.total_tokens;if([n,o,r].every(Number.isSafeInteger))return{input_tokens:n,output_tokens:o,total_tokens:r}}function g(t){const e=s=>{const l=s?.input_tokens,i=s?.output_tokens,f=s?.total_tokens;if(!(typeof l!="number"||typeof i!="number"||typeof f!="number"||!Number.isSafeInteger(l)||l<0||!Number.isSafeInteger(i)||i<0||!Number.isSafeInteger(f)||f<0))return{input_tokens:l,output_tokens:i,total_tokens:f}},n=e(t?.total),o=e(t?.last),r=t?.model_context_window;if(!(!n||!o))return{total:n,last:o,...typeof r=="number"&&Number.isSafeInteger(r)&&r>0?{context:{used_tokens:o.total_tokens,window_tokens:r}}:{}}}function p(t){return typeof t=="string"?t:t.filter(e=>e.type==="input_text").map(e=>e.text??"").join(`
|
|
2
|
+
`)}function k(t,e,n,o){const r=(n?[o,e]:[o]).filter(u=>!!u),s=r.length>0?`${r.join(`
|
|
3
3
|
|
|
4
4
|
`)}
|
|
5
5
|
|
|
6
|
-
`:"";if(typeof t=="string")return`${s}${t}`;if(!Array.isArray(t))throw new
|
|
6
|
+
`:"";if(typeof t=="string")return`${s}${t}`;if(!Array.isArray(t))throw new c(400,{message:"Invalid input"});const l=[...t].reverse().find(u=>!!(u&&typeof u=="object"&&"role"in u&&u.role==="user"));if(!l)throw new c(400,{message:"No user message found"});let i=e;if(n&&!i){const u=[...t].reverse().find(a=>!!(a&&typeof a=="object"&&"role"in a)&&(a.role==="system"||a.role==="developer"));u&&(i=p(u.content))}const f=n?[o,i].filter(u=>!!u):[];return`${f.length>0?`${f.join(`
|
|
7
7
|
|
|
8
8
|
`)}
|
|
9
9
|
|
|
10
|
-
`:""}${p(l.content)}`}function m(t,e){return{collaborationMode:{mode:t==="plan"?"plan":"default",settings:{model:e||null,reasoning_effort:"
|
|
10
|
+
`:""}${p(l.content)}`}function m(t,e,n){return{collaborationMode:{mode:t==="plan"?"plan":"default",settings:{model:e||null,reasoning_effort:n==="max"?"xhigh":n,developer_instructions:null}}}}function _(t){if(t.type==="agentMessage")return t.text;if(t.type==="reasoning")return t.summary.join(`
|
|
11
11
|
`)||t.content.join(`
|
|
12
12
|
`);if(t.type==="plan")return t.text}function T(t){if(t.type==="commandExecution")return t}function b(t){if(t.type==="fileChange")return t}function C(t){if(t.type==="mcpToolCall")return t}function w(t){if(t.type==="dynamicToolCall")return t}function I(t){if(t.type==="webSearch")return t}function d(t){if(!Array.isArray(t))return;const e=t.map(n=>n&&typeof n=="object"&&"type"in n&&n.type==="text"&&"text"in n&&typeof n.text=="string"?n.text:"").filter(n=>n.length>0).join(`
|
|
13
13
|
`);return e.length>0?e:void 0}function j(t){const e=t.result?.structuredContent;return e&&typeof e=="object"&&"filePath"in e&&typeof e.filePath=="string"?e.filePath:d(t.result?.content)??JSON.stringify(t.result??null)}function x(t){let e=0,n="";for(;e<t.length;){const o=t[e];if(/\s/.test(o))break;if(o==="'"){for(e+=1;e<t.length;){if(t[e]==="'"){e+=1;break}n+=t[e],e+=1}continue}if(o==='"'){for(e+=1;e<t.length;){const r=t[e];if(r==='"'){e+=1;break}if(r==="\\"&&e+1<t.length){n+=t[e+1],e+=2;continue}n+=r,e+=1}continue}if(o==="\\"&&e+1<t.length){n+=t[e+1],e+=2;continue}n+=o,e+=1}return t.slice(e).trim()===""?n:void 0}function S(t){const e=t.match(/^\/bin\/bash\s+-lc\s+([\s\S]+)$/);return e?x(e[1].trim())??t:t}function v(t){return(t.contentItems??[]).map(n=>n.type==="inputText"?n.text:n.imageUrl).filter(n=>n.length>0).join(`
|
|
14
|
-
`)}function $(t){return{query:t.query,...t.action?{action:t.action}:null}}export{h as addTokenUsage,T as commandExecutionItem,S as displayCommand,w as dynamicToolCallItem,v as dynamicToolCallOutput,b as fileChangeItem,
|
|
14
|
+
`)}function $(t){return{query:t.query,...t.action?{action:t.action}:null}}export{h as addTokenUsage,T as commandExecutionItem,S as displayCommand,w as dynamicToolCallItem,v as dynamicToolCallOutput,b as fileChangeItem,k as inputToPrompt,_ as itemText,C as mcpToolCallItem,j as mcpToolCallOutput,p as textFromContent,g as toUsage,m as turnOptions,I as webSearchItem,$ as webSearchPayload};
|
package/dist/schemas.d.ts
CHANGED
|
@@ -44,6 +44,14 @@ export declare const ChatForkSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
44
44
|
sessionId: z.ZodString;
|
|
45
45
|
messageId: z.ZodString;
|
|
46
46
|
}, z.core.$strict>]>;
|
|
47
|
+
export declare const AgentEffortSchema: z.ZodEnum<{
|
|
48
|
+
medium: "medium";
|
|
49
|
+
high: "high";
|
|
50
|
+
low: "low";
|
|
51
|
+
xhigh: "xhigh";
|
|
52
|
+
max: "max";
|
|
53
|
+
}>;
|
|
54
|
+
export type AgentEffort = z.infer<typeof AgentEffortSchema>;
|
|
47
55
|
export declare const ChatBodySchema: z.ZodObject<{
|
|
48
56
|
conversationId: z.ZodOptional<z.ZodString>;
|
|
49
57
|
fork: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
|
|
@@ -54,6 +62,13 @@ export declare const ChatBodySchema: z.ZodObject<{
|
|
|
54
62
|
messageId: z.ZodString;
|
|
55
63
|
}, z.core.$strict>]>>;
|
|
56
64
|
model: z.ZodString;
|
|
65
|
+
effort: z.ZodDefault<z.ZodEnum<{
|
|
66
|
+
medium: "medium";
|
|
67
|
+
high: "high";
|
|
68
|
+
low: "low";
|
|
69
|
+
xhigh: "xhigh";
|
|
70
|
+
max: "max";
|
|
71
|
+
}>>;
|
|
57
72
|
message: z.ZodObject<{
|
|
58
73
|
id: z.ZodOptional<z.ZodString>;
|
|
59
74
|
role: z.ZodOptional<z.ZodEnum<{
|
package/dist/schemas.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{z as t}from"zod";const o=t.object({type:t.literal("text"),text:t.string()}),e=t.object({type:t.literal("file"),mediaType:t.string(),filename:t.string().optional(),url:t.string()}),r=t.object({type:t.literal("step-start")}),n=t.object({type:t.literal("tool"),toolCallId:t.string(),toolName:t.string(),title:t.string().optional(),state:t.string(),input:t.unknown().optional(),output:t.unknown().optional(),approval:t.object({id:t.string(),approved:t.boolean().optional(),reason:t.string().optional()}).optional()}),a=t.looseObject({type:t.string()}),s=t.strictObject({threadId:t.string().min(1),turnId:t.string().min(1)}),i=t.strictObject({sessionId:t.string().min(1),messageId:t.string().min(1)}),l=t.union([s,i]),
|
|
1
|
+
import{z as t}from"zod";const o=t.object({type:t.literal("text"),text:t.string()}),e=t.object({type:t.literal("file"),mediaType:t.string(),filename:t.string().optional(),url:t.string()}),r=t.object({type:t.literal("step-start")}),n=t.object({type:t.literal("tool"),toolCallId:t.string(),toolName:t.string(),title:t.string().optional(),state:t.string(),input:t.unknown().optional(),output:t.unknown().optional(),approval:t.object({id:t.string(),approved:t.boolean().optional(),reason:t.string().optional()}).optional()}),a=t.looseObject({type:t.string()}),s=t.strictObject({threadId:t.string().min(1),turnId:t.string().min(1)}),i=t.strictObject({sessionId:t.string().min(1),messageId:t.string().min(1)}),l=t.union([s,i]),p=t.enum(["low","medium","high","xhigh","max"]),g=t.object({conversationId:t.string().optional(),fork:l.optional(),model:t.string(),effort:p.default("medium"),message:t.object({id:t.string().optional(),role:t.enum(["user","assistant"]).optional(),parts:t.array(t.union([o,e,r,n,a]))})}),c=t.object({answers:t.array(t.string())}),m=t.object({answers:t.record(t.string(),c)}),h=t.object({type:t.literal("tool"),toolCallId:t.string(),toolName:t.literal("request_user_input"),state:t.literal("output-available"),sourceTurnId:t.string().min(1).optional(),output:m});export{p as AgentEffortSchema,g as ChatBodySchema,a as ChatCustomPartSchema,e as ChatFilePartSchema,l as ChatForkSchema,r as ChatStepStartPartSchema,o as ChatTextPartSchema,n as ChatToolPartSchema,i as ClaudeChatForkSchema,s as CodexChatForkSchema,h as RequestUserInputToolPartSchema,c as ToolRequestUserInputAnswerSchema,m as ToolRequestUserInputResponseSchema};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@messenger-agent/codex-agent",
|
|
3
|
-
"version": "0.26.0-alpha.
|
|
3
|
+
"version": "0.26.0-alpha.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"ws": "^8.21.0",
|
|
23
23
|
"yaml": "^2.9.0",
|
|
24
24
|
"zod": "^4.4.3",
|
|
25
|
-
"@messenger-agent/shared": "0.26.0-alpha.
|
|
25
|
+
"@messenger-agent/shared": "0.26.0-alpha.6"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/ws": "^8.18.1"
|