mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-12 11:10:43 +00:00
fix: preserve restart continuation authority
This commit is contained in:
@@ -212,6 +212,7 @@ Docs: https://docs.openclaw.ai
|
||||
- CLI/router: when `openclaw <name>` does not match a CLI subcommand, check plugin tool manifests first so names like `lcm_recent` get an agent-tool diagnostic instead of the misleading suggestion to add the tool name to `plugins.allow`. Fixes #77214. Thanks @100yenadmin.
|
||||
- QA-lab/parity: bump the live mock-openai parity baseline from `claude-opus-4-6`/`claude-sonnet-4-6` to `claude-opus-4-7`/`claude-sonnet-4-7` and the candidate alt from `gpt-5.4-alt` to `gpt-5.5-alt` in `openclaw-release-checks.yml` and `qa-live-transports-convex.yml`, matching the active Opus 4.7 / GPT-5.5 defaults already used elsewhere on main. Carries forward the surface-bump portion of #74290. Thanks @100yenadmin.
|
||||
- QA-lab/scenarios: raise the `approval-turn-tool-followthrough` per-turn fallback timeouts from 20s/30s to 60s so cold mock-gateway parity runs do not flake on the approval-turn chain. Carries forward the timeout-bump portion of #74290. Thanks @100yenadmin.
|
||||
- Gateway/restart continuation: treat routed post-reboot agent turns as trusted internal continuations while preserving the original Telegram topic route, so owner-only tools remain available for chained restart workflows after reboot.
|
||||
- Agents/compaction: keep the recent tail after manual `/compact` when Pi returns an empty or no-op compaction summary, preventing blank checkpoints from replacing the live context.
|
||||
- Native commands: handle slash commands before workspace and agent-reply bootstrap so Telegram `/status` and other command-only native replies do not wait behind full agent turn setup.
|
||||
- Telegram/groups: include the recent local chat window and nearby reply-target window as generic inbound context so stale reply ancestry does not overshadow the live group conversation.
|
||||
|
||||
@@ -543,10 +543,16 @@ describe("scheduleRestartSentinelWake", () => {
|
||||
BodyForAgent: "stamped:Reply with exactly: Yay! I did it!",
|
||||
BodyForCommands: "",
|
||||
CommandBody: "",
|
||||
CommandAuthorized: false,
|
||||
CommandAuthorized: true,
|
||||
GatewayClientScopes: ["operator.admin"],
|
||||
InputProvenance: {
|
||||
kind: "internal_system",
|
||||
sourceChannel: "whatsapp",
|
||||
sourceTool: "restart-sentinel",
|
||||
},
|
||||
SessionKey: "agent:main:main",
|
||||
Provider: "whatsapp",
|
||||
Surface: "whatsapp",
|
||||
Provider: "webchat",
|
||||
Surface: "webchat",
|
||||
OriginatingChannel: "whatsapp",
|
||||
OriginatingTo: "+15550002",
|
||||
MessageThreadId: "thread-42",
|
||||
@@ -600,6 +606,72 @@ describe("scheduleRestartSentinelWake", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("authorizes routed agentTurn continuations while preserving Telegram topic routing", async () => {
|
||||
mocks.readRestartSentinel.mockResolvedValue({
|
||||
payload: {
|
||||
sessionKey: "agent:main:telegram:group:-1003826723328:topic:13757",
|
||||
ts: 123,
|
||||
continuation: {
|
||||
kind: "agentTurn",
|
||||
message: "continue in topic",
|
||||
},
|
||||
},
|
||||
} as unknown as Awaited<ReturnType<typeof mocks.readRestartSentinel>>);
|
||||
mocks.parseSessionThreadInfo.mockReturnValue({
|
||||
baseSessionKey: "agent:main:telegram:group:-1003826723328",
|
||||
threadId: "13757",
|
||||
});
|
||||
mocks.loadSessionEntry.mockReturnValue({
|
||||
cfg: {},
|
||||
entry: {
|
||||
sessionId: "agent:main:telegram:group:-1003826723328:topic:13757",
|
||||
updatedAt: 0,
|
||||
origin: { provider: "telegram", chatType: "group" },
|
||||
},
|
||||
store: {},
|
||||
storePath: "/tmp/sessions.json",
|
||||
canonicalKey: "agent:main:telegram:group:-1003826723328:topic:13757",
|
||||
legacyKey: undefined,
|
||||
});
|
||||
mocks.deliveryContextFromSession.mockReturnValue({
|
||||
channel: "telegram",
|
||||
to: "telegram:-1003826723328:topic:13757",
|
||||
accountId: "default",
|
||||
threadId: 13757,
|
||||
});
|
||||
mocks.resolveOutboundTarget.mockReturnValue({
|
||||
ok: true as const,
|
||||
to: "telegram:-1003826723328:topic:13757",
|
||||
});
|
||||
|
||||
await scheduleRestartSentinelWake({ deps: {} as never });
|
||||
|
||||
expect(mocks.recordInboundSessionAndDispatchReply).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
channel: "telegram",
|
||||
accountId: "default",
|
||||
routeSessionKey: "agent:main:telegram:group:-1003826723328:topic:13757",
|
||||
ctxPayload: expect.objectContaining({
|
||||
Body: "continue in topic",
|
||||
CommandAuthorized: true,
|
||||
GatewayClientScopes: ["operator.admin"],
|
||||
InputProvenance: {
|
||||
kind: "internal_system",
|
||||
sourceChannel: "telegram",
|
||||
sourceTool: "restart-sentinel",
|
||||
},
|
||||
Provider: "webchat",
|
||||
Surface: "webchat",
|
||||
ChatType: "group",
|
||||
OriginatingChannel: "telegram",
|
||||
OriginatingTo: "telegram:-1003826723328:topic:13757",
|
||||
ExplicitDeliverRoute: true,
|
||||
MessageThreadId: "13757",
|
||||
}),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("preserves derived reply transport ids in continuation context", async () => {
|
||||
mocks.getChannelPlugin.mockReturnValue({
|
||||
id: "whatsapp",
|
||||
|
||||
@@ -41,6 +41,7 @@ import {
|
||||
deliveryContextFromSession,
|
||||
mergeDeliveryContext,
|
||||
} from "../utils/delivery-context.shared.js";
|
||||
import { INTERNAL_MESSAGE_CHANNEL } from "../utils/message-channel.js";
|
||||
import { injectTimestamp, timestampOptsFromConfig } from "./server-methods/agent-timestamp.js";
|
||||
import { loadSessionEntry } from "./session-utils.js";
|
||||
import { runStartupTasks, type StartupTask } from "./startup-tasks.js";
|
||||
@@ -287,10 +288,16 @@ async function deliverQueuedSessionDelivery(params: {
|
||||
AccountId: route.accountId,
|
||||
MessageSid: messageId,
|
||||
Timestamp: Date.now(),
|
||||
Provider: route.channel,
|
||||
Surface: route.channel,
|
||||
InputProvenance: {
|
||||
kind: "internal_system",
|
||||
sourceChannel: route.channel,
|
||||
sourceTool: "restart-sentinel",
|
||||
},
|
||||
Provider: INTERNAL_MESSAGE_CHANNEL,
|
||||
Surface: INTERNAL_MESSAGE_CHANNEL,
|
||||
ChatType: route.chatType,
|
||||
CommandAuthorized: false,
|
||||
CommandAuthorized: true,
|
||||
GatewayClientScopes: ["operator.admin"],
|
||||
ReplyToId: route.replyToId,
|
||||
OriginatingChannel: route.channel,
|
||||
OriginatingTo: route.to,
|
||||
|
||||
Reference in New Issue
Block a user