惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Docker
人人都是产品经理
人人都是产品经理
小众软件
小众软件
博客园 - Franky
WordPress大学
WordPress大学
Jina AI
Jina AI
Google DeepMind News
Google DeepMind News
I
InfoQ
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
F
Fortinet All Blogs
博客园 - 【当耐特】
IT之家
IT之家
G
Google Developers Blog
J
Java Code Geeks
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
云风的 BLOG
云风的 BLOG
Recent Announcements
Recent Announcements
有赞技术团队
有赞技术团队
V
Visual Studio Blog
U
Unit 42
阮一峰的网络日志
阮一峰的网络日志
月光博客
月光博客
GbyAI
GbyAI
雷峰网
雷峰网

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4
fix(codex): preserve agent scope for bound app-server ses...
steipete · 2026-05-17 · via Recent Commits to openclaw:main

@@ -1,4 +1,5 @@

11

import crypto from "node:crypto";

2+

import { resolveAgentDir, resolveSessionAgentIds } from "openclaw/plugin-sdk/agent-runtime";

23

import type { PluginCommandContext, PluginCommandResult } from "openclaw/plugin-sdk/plugin-entry";

34

import { CODEX_CONTROL_METHODS, type CodexControlMethod } from "./app-server/capabilities.js";

45

import {

@@ -425,14 +426,19 @@ async function bindConversation(

425426

text: "Cannot bind Codex because this command did not include an OpenClaw session file.",

426427

};

427428

}

429+

const scope = resolveCodexConversationControlScope(ctx);

428430

const workspaceDir = parsed.cwd ?? deps.resolveCodexDefaultWorkspaceDir(pluginConfig);

429-

const existingBinding = await deps.readCodexAppServerBinding(ctx.sessionFile);

431+

const existingBinding = await deps.readCodexAppServerBinding(ctx.sessionFile, {

432+

agentDir: scope.agentDir,

433+

config: ctx.config,

434+

});

430435

const authProfileId = existingBinding?.authProfileId;

431436

const startParams: Parameters<CodexCommandDeps["startCodexConversationThread"]>[0] = {

432437

pluginConfig,

433438

config: ctx.config,

434439

sessionFile: ctx.sessionFile,

435440

workspaceDir,

441+

agentDir: scope.agentDir,

436442

threadId: parsed.threadId,

437443

model: parsed.model,

438444

modelProvider: parsed.provider,

@@ -441,7 +447,10 @@ async function bindConversation(

441447

startParams.authProfileId = authProfileId;

442448

}

443449

const data = await deps.startCodexConversationThread(startParams);

444-

const binding = await deps.readCodexAppServerBinding(ctx.sessionFile);

450+

const binding = await deps.readCodexAppServerBinding(ctx.sessionFile, {

451+

agentDir: scope.agentDir,

452+

config: ctx.config,

453+

});

445454

const threadId = binding?.threadId ?? parsed.threadId ?? "new thread";

446455

const summary = `Codex app-server thread ${formatCodexDisplayText(threadId)} in ${formatCodexDisplayText(workspaceDir)}`;

447456

let request: Awaited<ReturnType<PluginCommandContext["requestConversationBinding"]>>;

@@ -505,7 +514,10 @@ async function describeConversationBinding(

505514

"- Active run: not tracked",

506515

].join("\n");

507516

}

508-

const threadBinding = await deps.readCodexAppServerBinding(data.sessionFile);

517+

const threadBinding = await deps.readCodexAppServerBinding(data.sessionFile, {

518+

agentDir: data.agentDir,

519+

config: ctx.config,

520+

});

509521

const active = deps.readCodexConversationActiveTurn(data.sessionFile);

510522

return [

511523

"Codex conversation binding:",

@@ -634,11 +646,18 @@ async function stopConversationTurn(

634646

ctx: PluginCommandContext,

635647

pluginConfig: unknown,

636648

): Promise<string> {

637-

const sessionFile = await resolveControlSessionFile(ctx);

638-

if (!sessionFile) {

649+

const target = await resolveControlTarget(ctx);

650+

if (!target) {

639651

return "Cannot stop Codex because this command did not include an OpenClaw session file.";

640652

}

641-

return (await deps.stopCodexConversationTurn({ sessionFile, pluginConfig })).message;

653+

return (

654+

await deps.stopCodexConversationTurn({

655+

sessionFile: target.sessionFile,

656+

pluginConfig,

657+

agentDir: target.agentDir,

658+

config: ctx.config,

659+

})

660+

).message;

642661

}

643662644663

async function steerConversationTurn(

@@ -647,15 +666,17 @@ async function steerConversationTurn(

647666

pluginConfig: unknown,

648667

message: string,

649668

): Promise<string> {

650-

const sessionFile = await resolveControlSessionFile(ctx);

651-

if (!sessionFile) {

669+

const target = await resolveControlTarget(ctx);

670+

if (!target) {

652671

return "Cannot steer Codex because this command did not include an OpenClaw session file.";

653672

}

654673

return (

655674

await deps.steerCodexConversationTurn({

656-

sessionFile,

675+

sessionFile: target.sessionFile,

657676

pluginConfig,

658677

message,

678+

agentDir: target.agentDir,

679+

config: ctx.config,

659680

})

660681

).message;

661682

}

@@ -669,22 +690,27 @@ async function setConversationModel(

669690

if (args.length > 1) {

670691

return "Usage: /codex model <model>";

671692

}

672-

const sessionFile = await resolveControlSessionFile(ctx);

673-

if (!sessionFile) {

693+

const target = await resolveControlTarget(ctx);

694+

if (!target) {

674695

return "Cannot set Codex model because this command did not include an OpenClaw session file.";

675696

}

676697

const [model = ""] = args;

677698

const normalized = model.trim();

678699

if (!normalized) {

679-

const binding = await deps.readCodexAppServerBinding(sessionFile);

700+

const binding = await deps.readCodexAppServerBinding(target.sessionFile, {

701+

agentDir: target.agentDir,

702+

config: ctx.config,

703+

});

680704

return binding?.model

681705

? `Codex model: ${formatCodexDisplayText(binding.model)}`

682706

: "Usage: /codex model <model>";

683707

}

684708

return await deps.setCodexConversationModel({

685-

sessionFile,

709+

sessionFile: target.sessionFile,

686710

pluginConfig,

687711

model: normalized,

712+

agentDir: target.agentDir,

713+

config: ctx.config,

688714

});

689715

}

690716

@@ -697,8 +723,8 @@ async function setConversationFastMode(

697723

if (args.length > 1) {

698724

return "Usage: /codex fast [on|off|status]";

699725

}

700-

const sessionFile = await resolveControlSessionFile(ctx);

701-

if (!sessionFile) {

726+

const target = await resolveControlTarget(ctx);

727+

if (!target) {

702728

return "Cannot set Codex fast mode because this command did not include an OpenClaw session file.";

703729

}

704730

const value = args[0];

@@ -707,9 +733,11 @@ async function setConversationFastMode(

707733

return "Usage: /codex fast [on|off|status]";

708734

}

709735

return await deps.setCodexConversationFastMode({

710-

sessionFile,

736+

sessionFile: target.sessionFile,

711737

pluginConfig,

712738

enabled: parsed,

739+

agentDir: target.agentDir,

740+

config: ctx.config,

713741

});

714742

}

715743

@@ -722,8 +750,8 @@ async function setConversationPermissions(

722750

if (args.length > 1) {

723751

return "Usage: /codex permissions [default|yolo|status]";

724752

}

725-

const sessionFile = await resolveControlSessionFile(ctx);

726-

if (!sessionFile) {

753+

const target = await resolveControlTarget(ctx);

754+

if (!target) {

727755

return "Cannot set Codex permissions because this command did not include an OpenClaw session file.";

728756

}

729757

const value = args[0];

@@ -732,16 +760,46 @@ async function setConversationPermissions(

732760

return "Usage: /codex permissions [default|yolo|status]";

733761

}

734762

return await deps.setCodexConversationPermissions({

735-

sessionFile,

763+

sessionFile: target.sessionFile,

736764

pluginConfig,

737765

mode: parsed,

766+

agentDir: target.agentDir,

767+

config: ctx.config,

738768

});

739769

}

740770741-

async function resolveControlSessionFile(ctx: PluginCommandContext): Promise<string | undefined> {

771+

type CodexConversationControlTarget = {

772+

sessionFile: string;

773+

agentDir: string;

774+

};

775+776+

async function resolveControlTarget(

777+

ctx: PluginCommandContext,

778+

): Promise<CodexConversationControlTarget | undefined> {

742779

const binding = await ctx.getCurrentConversationBinding();

743780

const data = readCodexConversationBindingData(binding);

744-

return data?.kind === "codex-app-server-session" ? data.sessionFile : ctx.sessionFile;

781+

const scope = resolveCodexConversationControlScope(ctx);

782+

if (data?.kind === "codex-app-server-session") {

783+

return {

784+

sessionFile: data.sessionFile,

785+

agentDir: data.agentDir ?? scope.agentDir,

786+

};

787+

}

788+

return ctx.sessionFile ? { sessionFile: ctx.sessionFile, agentDir: scope.agentDir } : undefined;

789+

}

790+791+

async function resolveControlSessionFile(ctx: PluginCommandContext): Promise<string | undefined> {

792+

return (await resolveControlTarget(ctx))?.sessionFile;

793+

}

794+795+

function resolveCodexConversationControlScope(ctx: PluginCommandContext): { agentDir: string } {

796+

const { sessionAgentId } = resolveSessionAgentIds({

797+

sessionKey: ctx.sessionKey,

798+

config: ctx.config,

799+

});

800+

return {

801+

agentDir: resolveAgentDir(ctx.config, sessionAgentId),

802+

};

745803

}

746804747805

async function handleCodexDiagnosticsFeedback(

@@ -1603,21 +1661,42 @@ async function startThreadAction(

16031661

if (args.length > 0) {

16041662

return `Usage: /codex ${label === "compaction" ? "compact" : label}`;

16051663

}

1606-

const sessionFile = await resolveControlSessionFile(ctx);

1607-

if (!sessionFile) {

1664+

const target = await resolveControlTarget(ctx);

1665+

if (!target) {

16081666

return `Cannot start Codex ${label} because this command did not include an OpenClaw session file.`;

16091667

}

1610-

const binding = await deps.readCodexAppServerBinding(sessionFile);

1668+

const binding = await deps.readCodexAppServerBinding(target.sessionFile, {

1669+

agentDir: target.agentDir,

1670+

config: ctx.config,

1671+

});

16111672

if (!binding?.threadId) {

16121673

return `No Codex thread is attached to this OpenClaw session yet.`;

16131674

}

16141675

if (method === CODEX_CONTROL_METHODS.review) {

1615-

await deps.codexControlRequest(pluginConfig, method, {

1616-

threadId: binding.threadId,

1617-

target: { type: "uncommittedChanges" },

1618-

});

1676+

await deps.codexControlRequest(

1677+

pluginConfig,

1678+

method,

1679+

{

1680+

threadId: binding.threadId,

1681+

target: { type: "uncommittedChanges" },

1682+

},

1683+

{

1684+

agentDir: target.agentDir,

1685+

authProfileId: binding.authProfileId,

1686+

config: ctx.config,

1687+

},

1688+

);

16191689

} else {

1620-

await deps.codexControlRequest(pluginConfig, method, { threadId: binding.threadId });

1690+

await deps.codexControlRequest(

1691+

pluginConfig,

1692+

method,

1693+

{ threadId: binding.threadId },

1694+

{

1695+

agentDir: target.agentDir,

1696+

authProfileId: binding.authProfileId,

1697+

config: ctx.config,

1698+

},

1699+

);

16211700

}

16221701

return `Started Codex ${label} for thread ${formatCodexDisplayText(binding.threadId)}.`;

16231702

}