chore: prepare 2026.4.10 release

This commit is contained in:
Peter Steinberger
2026-04-11 03:20:57 +01:00
parent 8f94032dc1
commit 3b6fac85ea
10 changed files with 34 additions and 13 deletions

View File

@@ -6,6 +6,12 @@ Docs: https://docs.openclaw.ai
### Changes
### Fixes
## 2026.4.10
### Changes
- Models/Codex: add the bundled Codex provider and plugin-owned app-server harness so `codex/gpt-*` models use Codex-managed auth, native threads, model discovery, and compaction while `openai/gpt-*` stays on the normal OpenAI provider path. (#64298)
- Memory/Active Memory: add a new optional Active Memory plugin that gives OpenClaw a dedicated memory sub-agent right before the main reply, so ongoing chats can automatically pull in relevant preferences, context, and past details without making users remember to manually say "remember this" or "search memory" first. Includes configurable message/recent/full context modes, live `/verbose` inspection, advanced prompt/thinking overrides for tuning, and opt-in transcript persistence for debugging. Docs: https://docs.openclaw.ai/concepts/active-memory. (#63286) Thanks @Takhoffman.
- macOS/Talk: add an experimental local MLX speech provider for Talk Mode, with explicit provider selection, local utterance playback, interruption handling, and system-voice fallback. (#63539) Thanks @ImLukeF.
@@ -46,6 +52,7 @@ Docs: https://docs.openclaw.ai
- Agents/timeouts: extend the default LLM idle window to 120s and keep silent no-token idle timeouts on recovery paths, so slow models can retry or fall back before users see an error.
- Gateway/agents: preserve configured model selection and richer `IDENTITY.md` content across agent create/update flows and workspace moves, and fail safely instead of silently overwriting unreadable identity files. (#61577) Thanks @samzong.
- Skills/TaskFlow: restore valid frontmatter fences for the bundled `taskflow` and `taskflow-inbox-triage` skills and copy bundled `SKILL.md` files as hard dist-runtime copies so skills stay discoverable and loadable after updates. (#64166, #64469) Thanks @extrasmall0.
- Skills: respect overridden home directories when loading personal skills so service, test, and custom launch environments read the intended user skill directory instead of the process home.
- Windows/exec: settle supervisor waits from child exit state after stdout and stderr drain even when `close` never arrives, so CLI commands stop hanging or dying with forced `SIGKILL` on Windows. (#64072) Thanks @obviyus.
- Browser/sandbox: prevent sandbox browser CDP startup hangs by recreating containers when the browser security hash changes and by waiting on the correct sandbox browser lifecycle. (#62873) Thanks @Syysean.
- QQBot/streaming: make block streaming configurable per QQ bot account via `streaming.mode` (`"partial"` | `"off"`, default `"partial"`) instead of hardcoding it off, so responses can be delivered incrementally. (#63746)

View File

@@ -1,2 +1,2 @@
0b3c1d24d91e5b7b02d0e6322a8d32c280d1555f82f9a9fa948c28304712f9dd plugin-sdk-api-baseline.json
b50013d51b21a9cd7b3b21baa8ef22ba3be5d97392e040ed740f147e95ccb544 plugin-sdk-api-baseline.jsonl
ee16273fa5ad8c5408e9dad8d96fde86dfa666ef8eb44840b78135814ff97173 plugin-sdk-api-baseline.json
2bd0d5edf23e6a889d6bedb74d0d06411dd7750dac6ebf24971c789f8a69253a plugin-sdk-api-baseline.jsonl

View File

@@ -4,7 +4,7 @@
"description": "OpenClaw Codex harness and model provider plugin",
"type": "module",
"dependencies": {
"@mariozechner/pi-coding-agent": "0.65.2",
"@mariozechner/pi-coding-agent": "0.66.1",
"ws": "^8.20.0",
"zod": "^4.3.6"
},

4
pnpm-lock.yaml generated
View File

@@ -421,8 +421,8 @@ importers:
extensions/codex:
dependencies:
'@mariozechner/pi-coding-agent':
specifier: 0.65.2
version: 0.65.2(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.20.0)(zod@4.3.6)
specifier: 0.66.1
version: 0.66.1(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.20.0)(zod@4.3.6)
ws:
specifier: ^8.20.0
version: 8.20.0

View File

@@ -1,10 +1,16 @@
import type { StreamFn } from "@mariozechner/pi-agent-core";
import { streamSimple } from "@mariozechner/pi-ai";
import type { ThinkLevel } from "../../auto-reply/thinking.js";
import { normalizeOptionalLowercaseString } from "../../shared/string-coerce.js";
import { streamWithPayloadPatch } from "./stream-payload-utils.js";
type MoonshotThinkingType = "enabled" | "disabled";
let piAiRuntimePromise: Promise<typeof import("@mariozechner/pi-ai")> | undefined;
async function loadDefaultStreamFn(): Promise<StreamFn> {
piAiRuntimePromise ??= import("@mariozechner/pi-ai");
const runtime = await piAiRuntimePromise;
return runtime.streamSimple;
}
function normalizeMoonshotThinkingType(value: unknown): MoonshotThinkingType | undefined {
if (typeof value === "boolean") {
@@ -66,9 +72,9 @@ export function createMoonshotThinkingWrapper(
baseStreamFn: StreamFn | undefined,
thinkingType?: MoonshotThinkingType,
): StreamFn {
const underlying = baseStreamFn ?? streamSimple;
return (model, context, options) =>
streamWithPayloadPatch(underlying, model, context, options, (payloadObj) => {
return async (model, context, options) => {
const underlying = baseStreamFn ?? (await loadDefaultStreamFn());
return streamWithPayloadPatch(underlying, model, context, options, (payloadObj) => {
let effectiveThinkingType = normalizeMoonshotThinkingType(payloadObj.thinking);
if (thinkingType) {
@@ -87,4 +93,5 @@ export function createMoonshotThinkingWrapper(
}
}
});
};
}

View File

@@ -47,3 +47,9 @@ export type RegisteredSandboxBackend = {
};
export type { SandboxBackendHandle, SandboxBackendId } from "./backend-handle.types.js";
export type {
SandboxBackendCommandParams,
SandboxBackendCommandResult,
SandboxBackendExecSpec,
SandboxFsBridgeContext,
} from "./backend-handle.types.js";

View File

@@ -319,6 +319,7 @@ describe("handleCompactCommand", () => {
sessionId: "target-session",
}),
tokensAfter: 321,
skillsSnapshot: { prompt: "target", skills: [] },
}),
);
});

View File

@@ -18,11 +18,11 @@ const modelAuthLabelMocks = vi.hoisted(() => ({
}));
vi.mock("../../agents/model-catalog.js", () => ({
loadModelCatalog: (params: unknown) => modelCatalogMocks.loadModelCatalog(params),
loadModelCatalog: modelCatalogMocks.loadModelCatalog,
}));
vi.mock("../../agents/model-auth-label.js", () => ({
resolveModelAuthLabel: (params: unknown) => modelAuthLabelMocks.resolveModelAuthLabel(params),
resolveModelAuthLabel: modelAuthLabelMocks.resolveModelAuthLabel,
}));
const telegramModelsTestPlugin: ChannelPlugin = {
@@ -260,7 +260,7 @@ describe("handleModelsCommand", () => {
updatedAt: Date.now(),
providerOverride: "wrapper-provider",
modelOverride: "wrapper-model",
} as HandleCommandsParams["sessionEntry"];
};
params.sessionStore = {
"agent:support:main": {
sessionId: "target-session",

View File

@@ -82,6 +82,7 @@ function makeParams(): HandleCommandsParams {
agentId: "main",
sessionEntry: {
sessionId: "session-1",
updatedAt: Date.now(),
groupId: "group-1",
groupChannel: "#general",
space: "guild-1",

View File

@@ -669,7 +669,6 @@ export type ChannelApprovalDeliveryAdapter = {
request: ExecApprovalRequest;
}) => boolean;
};
export type ChannelApproveCommandBehavior =
| { kind: "allow" }
| { kind: "ignore" }