feat: integrate 5 feature branches + daemon/job 命令层级化 + 跨平台后台引擎 + TypeScript 错误修复

Squashed merge of:
1. fix/mcp-tsc-errors — 修复上游 MCP 重构后的 tsc 错误和测试失败
2. feat/pipe-mute-disconnect — Pipe IPC 逻辑断开、/lang 命令、mute 状态机
3. feat/stub-recovery-all — 实现全部 stub 恢复 (task 001-012)
4. feat/kairos-activation — KAIROS 激活解除阻塞 + 工具实现
5. codex/openclaw-autonomy-pr — 自治权限系统、运行记录、managed flows

Additional:
6. daemon/job 命令层级化重构 (subcommand 架构)
7. 跨平台后台引擎抽象 (detached/tmux engines)
8. 修复 src/ 中 43 个预存在的 TypeScript 类型错误
9. 修复 langfuse isolated test mock 完整性
10. 修复 CodeRabbit 审查的 Critical/Major/Minor 问题
11. remote-control-server logger 抽象 (测试 stderr 静默化)
12. /simplify 审查修复 (代码复用、质量、效率)
This commit is contained in:
unraid
2026-04-14 14:19:00 +08:00
parent dad3ad2b8d
commit 637c9081f6
123 changed files with 13536 additions and 1887 deletions

View File

@@ -1,7 +1,9 @@
import { feature } from 'bun:bundle'
import { z } from 'zod/v4'
import type { ToolResultBlockParam } from 'src/Tool.js'
import { buildTool } from 'src/Tool.js'
import { lazySchema } from 'src/utils/lazySchema.js'
import { logForDebugging } from 'src/utils/debug.js'
const PUSH_NOTIFICATION_TOOL_NAME = 'PushNotification'
@@ -74,14 +76,58 @@ Requires Remote Control to be configured. Respects user notification settings (t
}
},
async call(_input: PushInput) {
// Push delivery is handled by the Remote Control / KAIROS transport layer.
// Without the KAIROS runtime, this tool is not available.
return {
data: {
sent: false,
error: 'PushNotification requires the KAIROS transport layer.',
},
async call(input: PushInput, context) {
const appState = context.getAppState()
// Try bridge delivery first (for remote/mobile viewers)
if (appState.replBridgeEnabled) {
if (feature('BRIDGE_MODE')) {
try {
const { getBridgeAccessToken, getBridgeBaseUrl } = await import(
'src/bridge/bridgeConfig.js'
)
const { getSessionId } = await import('src/bootstrap/state.js')
const token = getBridgeAccessToken()
const sessionId = getSessionId()
if (token && sessionId) {
const baseUrl = getBridgeBaseUrl()
const axios = (await import('axios')).default
const response = await axios.post(
`${baseUrl}/v1/sessions/${sessionId}/events`,
{
events: [
{
type: 'push_notification',
title: input.title,
body: input.body,
priority: input.priority ?? 'normal',
},
],
},
{
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
'anthropic-version': '2023-06-01',
},
timeout: 10_000,
validateStatus: (s: number) => s < 500,
},
)
if (response.status >= 200 && response.status < 300) {
logForDebugging(`[PushNotification] delivered via bridge session=${sessionId}`)
return { data: { sent: true } }
}
logForDebugging(`[PushNotification] bridge delivery failed: status=${response.status}`)
}
} catch (e) {
logForDebugging(`[PushNotification] bridge delivery error: ${e}`)
}
}
}
// Fallback: no bridge available, push was not delivered to a remote device.
logForDebugging(`[PushNotification] no bridge available, not delivered: ${input.title}`)
return { data: { sent: false, error: 'No Remote Control bridge configured. Notification not delivered.' } }
},
})

View File

@@ -70,14 +70,51 @@ Guidelines:
}
},
async call(_input: SendUserFileInput) {
// File transfer is handled by the KAIROS assistant transport layer.
// Without the KAIROS runtime, this tool is not available.
async call(input: SendUserFileInput, context) {
const { file_path } = input
const { stat } = await import('fs/promises')
// Verify file exists and is readable
let fileSize: number
try {
const fileStat = await stat(file_path)
if (!fileStat.isFile()) {
return {
data: { sent: false, file_path, error: 'Path is not a file.' },
}
}
fileSize = fileStat.size
} catch {
return {
data: { sent: false, file_path, error: 'File does not exist or is not readable.' },
}
}
// Attempt bridge upload if available (so web viewers can download)
const appState = context.getAppState()
let fileUuid: string | undefined
if (appState.replBridgeEnabled) {
try {
const { uploadBriefAttachment } = await import(
'@claude-code-best/builtin-tools/tools/BriefTool/upload.js'
)
fileUuid = await uploadBriefAttachment(file_path, fileSize, {
replBridgeEnabled: true,
signal: context.abortController.signal,
})
} catch {
// Best-effort upload — local path is always available
}
}
const delivered = !appState.replBridgeEnabled || Boolean(fileUuid)
return {
data: {
sent: false,
file_path: _input.file_path,
error: 'SendUserFile requires the KAIROS assistant transport layer.',
sent: delivered,
file_path,
size: fileSize,
...(fileUuid ? { file_uuid: fileUuid } : {}),
...(!delivered ? { error: 'Bridge upload failed. File available at local path.' } : {}),
},
}
},