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

推荐订阅源

大猫的无限游戏
大猫的无限游戏
H
Hackread – Cybersecurity News, Data Breaches, AI and More
博客园_首页
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
D
Docker
酷 壳 – CoolShell
酷 壳 – CoolShell
宝玉的分享
宝玉的分享
Martin Fowler
Martin Fowler
美团技术团队
量子位
M
MIT News - Artificial intelligence
Apple Machine Learning Research
Apple Machine Learning Research
阮一峰的网络日志
阮一峰的网络日志
博客园 - 叶小钗
博客园 - 三生石上(FineUI控件)
腾讯CDC
Hugging Face - Blog
Hugging Face - Blog
博客园 - 【当耐特】
小众软件
小众软件
博客园 - 司徒正美
罗磊的独立博客
云风的 BLOG
云风的 BLOG
B
Blog RSS Feed
博客园 - 聂微东

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(ui): abort orphaned workboard runs · openclaw/opencla...
vincentkoc · 2026-05-30 · via Recent Commits to openclaw:main

@@ -1449,6 +1449,31 @@ function buildWorkboardExecution(params: {

14491449

};

14501450

}

145114511452+

async function abortWorkboardSessionRun(params: {

1453+

client: GatewayBrowserClient;

1454+

sessionKey: string;

1455+

runId?: string;

1456+

}): Promise<boolean> {

1457+

let abortResult = await params.client.request("chat.abort", {

1458+

sessionKey: params.sessionKey,

1459+

...(params.runId ? { runId: params.runId } : {}),

1460+

});

1461+

let aborted =

1462+

isRecord(abortResult) &&

1463+

(abortResult.aborted === true ||

1464+

(Array.isArray(abortResult.runIds) && abortResult.runIds.length > 0));

1465+

if (!aborted && params.runId) {

1466+

abortResult = await params.client.request("chat.abort", {

1467+

sessionKey: params.sessionKey,

1468+

});

1469+

aborted =

1470+

isRecord(abortResult) &&

1471+

(abortResult.aborted === true ||

1472+

(Array.isArray(abortResult.runIds) && abortResult.runIds.length > 0));

1473+

}

1474+

return aborted;

1475+

}

1476+14521477

export async function startWorkboardCard(params: {

14531478

host: WorkboardHost;

14541479

client: GatewayBrowserClient | null;

@@ -1472,6 +1497,8 @@ export async function startWorkboardCard(params: {

14721497

state.busyCardId = params.card.id;

14731498

params.requestUpdate?.();

14741499

let preflightCard: WorkboardCard | null = null;

1500+

let createdSessionKey: string | null = null;

1501+

let createdRunId: string | undefined;

14751502

try {

14761503

const shouldClearManualSchedule =

14771504

mode === "manual" && params.card.metadata?.automation?.scheduledAt !== undefined;

@@ -1505,6 +1532,8 @@ export async function startWorkboardCard(params: {

15051532

isRecord(created) && typeof created.runId === "string" && created.runId.trim()

15061533

? created.runId.trim()

15071534

: undefined;

1535+

createdSessionKey = sessionKey;

1536+

createdRunId = runId;

15081537

const initialRunFailed =

15091538

mode === "autonomous" && isRecord(created) && created.runStarted === false;

15101539

if (initialRunFailed) {

@@ -1559,6 +1588,17 @@ export async function startWorkboardCard(params: {

15591588

replaceCard(state, normalizeCardPayload(payload));

15601589

return sessionKey;

15611590

} catch (error) {

1591+

if (mode === "autonomous" && createdSessionKey) {

1592+

try {

1593+

await abortWorkboardSessionRun({

1594+

client: params.client,

1595+

sessionKey: createdSessionKey,

1596+

runId: createdRunId,

1597+

});

1598+

} catch {

1599+

// Preserve the card-start failure; the user-facing repair is the rollback below.

1600+

}

1601+

}

15621602

if (preflightCard) {

15631603

try {

15641604

const rollbackPayload = await params.client.request("workboard.cards.update", {

@@ -1598,23 +1638,11 @@ export async function stopWorkboardCard(params: {

15981638

state.error = null;

15991639

params.requestUpdate?.();

16001640

try {

1601-

let abortResult = await params.client.request("chat.abort", {

1641+

const aborted = await abortWorkboardSessionRun({

1642+

client: params.client,

16021643

sessionKey,

1603-

...(workboardCardRunId(params.card) ? { runId: workboardCardRunId(params.card) } : {}),

1644+

runId: workboardCardRunId(params.card),

16041645

});

1605-

let aborted =

1606-

isRecord(abortResult) &&

1607-

(abortResult.aborted === true ||

1608-

(Array.isArray(abortResult.runIds) && abortResult.runIds.length > 0));

1609-

if (!aborted && workboardCardRunId(params.card)) {

1610-

abortResult = await params.client.request("chat.abort", {

1611-

sessionKey,

1612-

});

1613-

aborted =

1614-

isRecord(abortResult) &&

1615-

(abortResult.aborted === true ||

1616-

(Array.isArray(abortResult.runIds) && abortResult.runIds.length > 0));

1617-

}

16181646

if (!aborted) {

16191647

return;

16201648

}