From 6d558c5a630d12837820786c443b2f7502989dd7 Mon Sep 17 00:00:00 2001 From: Merge Date: Sat, 11 Jul 2026 08:29:08 -0400 Subject: [PATCH] chore(agent-client): update codex protocol to 0.144.0 --- .changeset/update-codex-protocol-0-144-0.md | 5 +++ packages/agent-client/package.json | 2 +- packages/agent-client/src/chat/define-tool.ts | 28 ++++++++++--- .../agent-client/src/chat/tool-catalog.ts | 19 ++++++++- .../agent-client/src/codex-oneshot-client.ts | 3 +- .../agent-client/src/codex-thread-client.ts | 9 ++--- .../agent-client/test/define-tool.test.ts | 40 +++++++++++++++---- packages/agent-client/test/normalize.test.ts | 1 + pnpm-lock.yaml | 10 ++--- 9 files changed, 88 insertions(+), 29 deletions(-) create mode 100644 .changeset/update-codex-protocol-0-144-0.md diff --git a/.changeset/update-codex-protocol-0-144-0.md b/.changeset/update-codex-protocol-0-144-0.md new file mode 100644 index 0000000..d28d17d --- /dev/null +++ b/.changeset/update-codex-protocol-0-144-0.md @@ -0,0 +1,5 @@ +--- +"@pwrdrvr/agent-client": patch +--- + +Update @pwrdrvr/codex-app-server-protocol to 0.144.0. diff --git a/packages/agent-client/package.json b/packages/agent-client/package.json index 1c359a6..1c712b2 100644 --- a/packages/agent-client/package.json +++ b/packages/agent-client/package.json @@ -25,7 +25,7 @@ "dependencies": { "@pwrdrvr/agent-core": "workspace:^", "@pwrdrvr/agent-transport": "workspace:^", - "@pwrdrvr/codex-app-server-protocol": "^0.135.0", + "@pwrdrvr/codex-app-server-protocol": "^0.144.0", "@pwrdrvr/codex-discovery": "workspace:^", "zod": "^4.0.0" }, diff --git a/packages/agent-client/src/chat/define-tool.ts b/packages/agent-client/src/chat/define-tool.ts index ed78b75..6f392b1 100644 --- a/packages/agent-client/src/chat/define-tool.ts +++ b/packages/agent-client/src/chat/define-tool.ts @@ -18,6 +18,7 @@ import { z } from "zod"; import type { DynamicToolCallOutputContentItem, + DynamicToolNamespaceTool, DynamicToolSpec } from "@pwrdrvr/codex-app-server-protocol/v2"; @@ -83,15 +84,30 @@ export function defineTool(spec: ToolSpec): ToolSpec { export type AnyToolSpec = ToolSpec; /** - * Convert a `ToolSpec` into the protocol `DynamicToolSpec` registered with Codex - * at `thread/start`. The `inputSchema` is derived from the tool's zod - * `argsSchema` via zod v4's `z.toJSONSchema()` (JSON Schema draft 2020-12). + * Convert a `ToolSpec` into the protocol function-tool shape nested inside a + * Codex dynamic-tool namespace. The `inputSchema` is derived from the tool's + * zod `argsSchema` via zod v4's `z.toJSONSchema()` (JSON Schema draft 2020-12). */ -export function toDynamicToolSpec(spec: AnyToolSpec): DynamicToolSpec { +export function toDynamicToolNamespaceTool(spec: AnyToolSpec): DynamicToolNamespaceTool { return { - namespace: spec.namespace, + type: "function", name: spec.name, description: spec.description, - inputSchema: z.toJSONSchema(spec.argsSchema) as DynamicToolSpec["inputSchema"] + inputSchema: z.toJSONSchema(spec.argsSchema) as DynamicToolNamespaceTool["inputSchema"] + }; +} + +/** + * Convert a `ToolSpec` into a standalone protocol `DynamicToolSpec`. The current + * protocol carries namespaces as top-level specs containing function tools, so a + * single tool becomes a one-tool namespace. `buildToolCatalog` groups tools that + * share a namespace before registration. + */ +export function toDynamicToolSpec(spec: AnyToolSpec): DynamicToolSpec { + return { + type: "namespace", + name: spec.namespace, + description: `Tools in the ${spec.namespace} namespace.`, + tools: [toDynamicToolNamespaceTool(spec)] }; } diff --git a/packages/agent-client/src/chat/tool-catalog.ts b/packages/agent-client/src/chat/tool-catalog.ts index 9315ae4..942042d 100644 --- a/packages/agent-client/src/chat/tool-catalog.ts +++ b/packages/agent-client/src/chat/tool-catalog.ts @@ -16,17 +16,32 @@ import { z } from "zod"; import type { DynamicToolCallParams, DynamicToolCallResponse, + DynamicToolNamespaceTool, DynamicToolSpec } from "@pwrdrvr/codex-app-server-protocol/v2"; import type { AnyToolSpec } from "./define-tool"; -import { toDynamicToolSpec } from "./define-tool"; +import { toDynamicToolNamespaceTool } from "./define-tool"; /** * Build the `DynamicToolSpec[]` registered with Codex at `thread/start`. Pure * projection of the catalog — an empty catalog yields an empty spec list. */ export function buildToolCatalog(catalog: ReadonlyArray): DynamicToolSpec[] { - return catalog.map(toDynamicToolSpec); + const namespaces = new Map(); + for (const tool of catalog) { + const group = namespaces.get(tool.namespace); + if (group === undefined) { + namespaces.set(tool.namespace, [toDynamicToolNamespaceTool(tool)]); + } else { + group.push(toDynamicToolNamespaceTool(tool)); + } + } + return Array.from(namespaces, ([name, tools]) => ({ + type: "namespace", + name, + description: `Tools in the ${name} namespace.`, + tools + })); } /** diff --git a/packages/agent-client/src/codex-oneshot-client.ts b/packages/agent-client/src/codex-oneshot-client.ts index 3afa4f0..3caf260 100644 --- a/packages/agent-client/src/codex-oneshot-client.ts +++ b/packages/agent-client/src/codex-oneshot-client.ts @@ -332,8 +332,7 @@ export class CodexOneShotClient { // dedicated cwd keeps the worker out of any host repo/worktree. ...(this.options.threadConfig !== undefined ? { config: this.options.threadConfig } : {}), environments: [], - experimentalRawEvents: false, - persistExtendedHistory: false + experimentalRawEvents: false }, this.requestTimeoutMs )) as ThreadStartResponse; diff --git a/packages/agent-client/src/codex-thread-client.ts b/packages/agent-client/src/codex-thread-client.ts index d8131d9..6d05906 100644 --- a/packages/agent-client/src/codex-thread-client.ts +++ b/packages/agent-client/src/codex-thread-client.ts @@ -248,8 +248,7 @@ export class CodexThreadClient implements AgentBackend { await this.initialize(); const params: ThreadForkParams = { - threadId: opts.sourceThreadId, - persistExtendedHistory: false + threadId: opts.sourceThreadId }; if (opts.cwd !== undefined) params.cwd = opts.cwd; if (opts.workspaceRoots !== undefined) params.runtimeWorkspaceRoots = [...opts.workspaceRoots]; @@ -283,8 +282,7 @@ export class CodexThreadClient implements AgentBackend { // exactOptionalPropertyTypes: only attach a key when the caller supplied it. const params: ThreadStartParams = { - experimentalRawEvents: false, - persistExtendedHistory: false + experimentalRawEvents: false }; if (opts.cwd !== undefined) params.cwd = opts.cwd; if (opts.model !== undefined) params.model = opts.model; @@ -331,8 +329,7 @@ export class CodexThreadClient implements AgentBackend { await this.initialize(); const params: ThreadResumeParams = { - threadId, - persistExtendedHistory: false + threadId }; const response = (await connection.request( "thread/resume", diff --git a/packages/agent-client/test/define-tool.test.ts b/packages/agent-client/test/define-tool.test.ts index f258859..59cc3b1 100644 --- a/packages/agent-client/test/define-tool.test.ts +++ b/packages/agent-client/test/define-tool.test.ts @@ -16,10 +16,19 @@ const listTool = defineTool({ describe("defineTool / toDynamicToolSpec", () => { it("serializes a tool spec to a valid DynamicToolSpec via z.toJSONSchema", () => { const spec = toDynamicToolSpec(listTool as ToolSpec); - expect(spec.namespace).toBe("host_tools"); - expect(spec.name).toBe("library_list"); - expect(spec.description).toBe("List captures in the library."); - expect(spec.inputSchema).toMatchObject({ + expect(spec.type).toBe("namespace"); + if (spec.type !== "namespace") { + throw new Error("expected namespace dynamic tool spec"); + } + expect(spec.name).toBe("host_tools"); + expect(spec.description).toBe("Tools in the host_tools namespace."); + expect(spec.tools).toHaveLength(1); + expect(spec.tools[0]).toMatchObject({ + type: "function", + name: "library_list", + description: "List captures in the library." + }); + expect(spec.tools[0]?.inputSchema).toMatchObject({ type: "object", properties: { limit: { type: "integer", exclusiveMinimum: 0, maximum: 200 } @@ -27,10 +36,27 @@ describe("defineTool / toDynamicToolSpec", () => { }); }); - it("builds the catalog as a pure projection of the tool list", () => { - const catalog = buildToolCatalog([listTool as ToolSpec]); + it("builds the catalog grouped by namespace", () => { + const renderTool = defineTool({ + namespace: "host_tools", + name: "render", + description: "Render a capture.", + argsSchema: z.object({ id: z.string() }), + dispatch: async () => ({ ok: true, data: {} }) + }); + const catalog = buildToolCatalog([ + listTool as ToolSpec, + renderTool as ToolSpec + ]); expect(catalog).toHaveLength(1); - expect(catalog[0]?.name).toBe("library_list"); + expect(catalog[0]?.name).toBe("host_tools"); + expect(catalog[0]).toMatchObject({ + type: "namespace", + tools: [ + { type: "function", name: "library_list" }, + { type: "function", name: "render" } + ] + }); expect(buildToolCatalog([])).toEqual([]); }); }); diff --git a/packages/agent-client/test/normalize.test.ts b/packages/agent-client/test/normalize.test.ts index 3d0b30e..f0760c6 100644 --- a/packages/agent-client/test/normalize.test.ts +++ b/packages/agent-client/test/normalize.test.ts @@ -141,6 +141,7 @@ function syntheticSequence(): Array<{ method: string; params: unknown }> { effort: "medium" as never, summary: null, collaborationMode: "off" as never, + multiAgentMode: "explicitRequestOnly", personality: null } }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b21982f..5d713fb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -107,8 +107,8 @@ importers: specifier: workspace:^ version: link:../agent-transport '@pwrdrvr/codex-app-server-protocol': - specifier: ^0.135.0 - version: 0.135.0 + specifier: ^0.144.0 + version: 0.144.0 '@pwrdrvr/codex-discovery': specifier: workspace:^ version: link:../codex-discovery @@ -594,8 +594,8 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@pwrdrvr/codex-app-server-protocol@0.135.0': - resolution: {integrity: sha512-lmebPpbmaE7yfe0EDqcT2MPRtKurUc1o9NinHAVdA3lBdF3c8ZK3okiHIw6r6GEQLqOTd+7dpEuPsk4a1dEpkw==} + '@pwrdrvr/codex-app-server-protocol@0.144.0': + resolution: {integrity: sha512-WmURXzmmNEY8lmnNZunNQj/Bnn3yjzS6Rc0gzlDU7sBHMd0kvtskXE9BCMcR+E7sVJ53V/gwjfksRUli0xUgdA==} engines: {node: '>=20'} '@rollup/rollup-android-arm-eabi@4.60.4': @@ -2243,7 +2243,7 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 - '@pwrdrvr/codex-app-server-protocol@0.135.0': {} + '@pwrdrvr/codex-app-server-protocol@0.144.0': {} '@rollup/rollup-android-arm-eabi@4.60.4': optional: true