skills-experimental/app-state-store/SKILL.md
# AppState Store Skill 应用状态存储 - Zustand-style store + onChange hook + Selector pattern + External metadata sync。 ## 功能概述 从Claude Code的AppState系统提取的状态管理模式,用于OpenClaw的全局状态管理。 ## 核心机制 ### Zustand-style Store ```typescript export type Store<T> = { getState: () => T setState: (updater: (prev: T) => T) => void subscribe: (listener: Listener) => () => void } export function createStore<T>(initialState: T, onChange?: OnChange<T>): Store<T> { let state = initialState const listeners = ne
npx skillsauth add bianhaifeng789-hue/openclaw-config skills-experimental/app-state-storeInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
应用状态存储 - Zustand-style store + onChange hook + Selector pattern + External metadata sync。
从Claude Code的AppState系统提取的状态管理模式,用于OpenClaw的全局状态管理。
export type Store<T> = {
getState: () => T
setState: (updater: (prev: T) => T) => void
subscribe: (listener: Listener) => () => void
}
export function createStore<T>(initialState: T, onChange?: OnChange<T>): Store<T> {
let state = initialState
const listeners = new Set<Listener>()
return {
getState: () => state,
setState: (updater: (prev: T) => T) => {
const prev = state
const next = updater(prev)
if (Object.is(next, prev)) return // No change → skip
state = next
onChange?.({ newState: next, oldState: prev })
for (const listener of listeners) listener()
},
subscribe: (listener: Listener) => {
listeners.add(listener)
return () => listeners.delete(listener)
},
}
}
// Zustand-style minimal store
// updater function pattern
// Object.is compare (no unnecessary notify)
export function onChangeAppState({ newState, oldState }) {
// toolPermissionContext.mode — single choke point for CCR/SDK mode sync
const prevMode = oldState.toolPermissionContext.mode
const newMode = newState.toolPermissionContext.mode
if (prevMode !== newMode) {
const prevExternal = toExternalPermissionMode(prevMode)
const newExternal = toExternalPermissionMode(newMode)
if (prevExternal !== newExternal) {
notifySessionMetadataChanged({ permission_mode: newExternal })
}
notifyPermissionModeChanged(newMode)
}
// Any setAppState call → onChange hook → notify
// Scattered callsites need zero changes
}
export function useAppState<T>(selector: (state: AppState) => T): T {
const store = useAppStore()
const get = () => selector(store.getState())
return useSyncExternalStore(store.subscribe, get, get)
}
// useSyncExternalStore for reactivity
// Selector for optimized rendering
// Only re-render when selected value changes
export type ActiveAgentForInput =
| { type: 'leader' }
| { type: 'viewed'; task: InProcessTeammateTaskState }
| { type: 'named_agent'; task: LocalAgentTaskState }
export function getActiveAgentForInput(appState: AppState): ActiveAgentForInput {
const viewedTask = getViewedTeammateTask(appState)
if (viewedTask) return { type: 'viewed', task: viewedTask }
// Discriminated union for type-safe routing
}
// Inverse push/restore for worker restart
export function externalMetadataToAppState(metadata: SessionExternalMetadata): (prev: AppState) => AppState {
return prev => ({
...prev,
...(typeof metadata.permission_mode === 'string' ? {
toolPermissionContext: { ...prev.toolPermissionContext, mode: permissionModeFromString(metadata.permission_mode) }
} : {}),
})
}
// Remote state → AppState updater function
// Worker restart restore
export function useSetAppState() {
return useAppStore().setState
}
// Returns stable reference
// Components using only this never re-render
export function useAppStateMaybeOutsideOfProvider<T>(selector): T | undefined {
const store = useContext(AppStoreContext)
return useSyncExternalStore(
store ? store.subscribe : NOOP_SUBSCRIBE,
() => store ? selector(store.getState()) : undefined
)
}
// Safe version when AppStateProvider may not be available
export type AppState = DeepImmutable<{
settings: SettingsJson
verbose: boolean
mainLoopModel: ModelSetting
// ... all fields deeply immutable
}> & {
// Excluded from DeepImmutable (function types)
tasks: { [taskId: string]: TaskState }
agentNameRegistry: Map<string, AgentId>
}
// DeepImmutable for type safety
// Exceptions for Map/function types
if (newState.settings !== oldState.settings) {
clearApiKeyHelperCache()
clearAwsCredentialsCache()
clearGcpCredentialsCache()
// Settings change → clear auth caches
}
{
"storeType": "zustand",
"onChangeHook": true,
"selectorPattern": true,
"externalSync": true,
"deepImmutable": true
}
getState + setState(updater) + subscribe
// 最小API
// Updater function
onChange hook → all mutations notify
// 不需要每个callsite单独处理
// 统一sync点
useSyncExternalStore + selector → only re-render when selected value changes
// 优化渲染
// 不订阅整个state
type: 'leader' | 'viewed' | 'named_agent' → type-safe routing
// 类型安全
// 编译器检查
state/AppState.tsx, AppStateStore.ts, store.ts, onChangeAppState.tsbusiness
IAA 日报飞书输出能力。 支持把固定 CSV 模板一键转换成: - 中文运营结论 - 飞书卡片 JSON - 飞书发送载荷 Use when: - 需要把 IAA 日报直接发到飞书 - 需要从 CSV 一键生成运营日报
data-ai
IAA日报分析模型 功能: - 渠道日报自动分析 - 小时级+日级ROI联动判断 - 按地区输出加量/降量/停投建议 - 按产品类型输出阈值 - 自动识别利润区/观察区/止损区 Use when: - 分析每天投放数据 - 生成运营日报结论 - 判断是否加量/降量/停投 - 对比美加澳/日韩表现 Keywords: - 日报模型, 投放日报, 加量, 降量, 停投, ROI日报, 分地区分析
data-ai
IAA固定日报分析模板 功能: - 固定字段模板(可直接贴每天数据) - 自动输出总盘结论 - 自动输出美加澳/日韩结论 - 自动给出加量/降量/停投建议 - 适配文件修复/清理两类产品 Use when: - 需要固定日报格式 - 每天复盘渠道表现 - 给运营团队出统一结论 Keywords: - 固定模板, 日报模板, ROI模板, IAA日报, 运营模板
development
# HyperlinkPool Pattern Skill HyperlinkPool Pattern - HyperlinkPool class + strings array + stringMap + Index 0 no hyperlink + intern(hyperlink) + get(id) + undefined handling + 5-minute reset + OSC8 hyperlink interning。 ## 功能概述 从Claude Code的ink/screen.ts提取的HyperlinkPool模式,用于OpenClaw的OSC8超链接池管理。 ## 核心机制 ### HyperlinkPool Class ```typescript export class HyperlinkPool { private strings: string[] = [''] // Index 0 = no hyperlink private stringMap = new Map<string, number>() // strings