1 Star 0 Fork 0

up/claude-code-source-code

加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
activityManager.ts 4.86 KB
一键复制 编辑 原始数据 按行查看 历史
sanbucat 提交于 2026-03-31 17:08 +08:00 . v2.1.88 反编译源码
import { getActiveTimeCounter as getActiveTimeCounterImpl } from '../bootstrap/state.js'
type ActivityManagerOptions = {
getNow?: () => number
getActiveTimeCounter?: typeof getActiveTimeCounterImpl
}
/**
* ActivityManager handles generic activity tracking for both user and CLI operations.
* It automatically deduplicates overlapping activities and provides separate metrics
* for user vs CLI active time.
*/
export class ActivityManager {
private activeOperations = new Set<string>()
private lastUserActivityTime: number = 0 // Start with 0 to indicate no activity yet
private lastCLIRecordedTime: number
private isCLIActive: boolean = false
private readonly USER_ACTIVITY_TIMEOUT_MS = 5000 // 5 seconds
private readonly getNow: () => number
private readonly getActiveTimeCounter: typeof getActiveTimeCounterImpl
private static instance: ActivityManager | null = null
constructor(options?: ActivityManagerOptions) {
this.getNow = options?.getNow ?? (() => Date.now())
this.getActiveTimeCounter =
options?.getActiveTimeCounter ?? getActiveTimeCounterImpl
this.lastCLIRecordedTime = this.getNow()
}
static getInstance(): ActivityManager {
if (!ActivityManager.instance) {
ActivityManager.instance = new ActivityManager()
}
return ActivityManager.instance
}
/**
* Reset the singleton instance (for testing purposes)
*/
static resetInstance(): void {
ActivityManager.instance = null
}
/**
* Create a new instance with custom options (for testing purposes)
*/
static createInstance(options?: ActivityManagerOptions): ActivityManager {
ActivityManager.instance = new ActivityManager(options)
return ActivityManager.instance
}
/**
* Called when user interacts with the CLI (typing, commands, etc.)
*/
recordUserActivity(): void {
// Don't record user time if CLI is active (CLI takes precedence)
if (!this.isCLIActive && this.lastUserActivityTime !== 0) {
const now = this.getNow()
const timeSinceLastActivity = (now - this.lastUserActivityTime) / 1000
if (timeSinceLastActivity > 0) {
const activeTimeCounter = this.getActiveTimeCounter()
if (activeTimeCounter) {
const timeoutSeconds = this.USER_ACTIVITY_TIMEOUT_MS / 1000
// Only record time if within the timeout window
if (timeSinceLastActivity < timeoutSeconds) {
activeTimeCounter.add(timeSinceLastActivity, { type: 'user' })
}
}
}
}
// Update the last user activity timestamp
this.lastUserActivityTime = this.getNow()
}
/**
* Starts tracking CLI activity (tool execution, AI response, etc.)
*/
startCLIActivity(operationId: string): void {
// If operation already exists, it likely means the previous one didn't clean up
// properly (e.g., component crashed/unmounted without calling end). Force cleanup
// to avoid overestimating time - better to underestimate than overestimate.
if (this.activeOperations.has(operationId)) {
this.endCLIActivity(operationId)
}
const wasEmpty = this.activeOperations.size === 0
this.activeOperations.add(operationId)
if (wasEmpty) {
this.isCLIActive = true
this.lastCLIRecordedTime = this.getNow()
}
}
/**
* Stops tracking CLI activity
*/
endCLIActivity(operationId: string): void {
this.activeOperations.delete(operationId)
if (this.activeOperations.size === 0) {
// Last operation ended - CLI becoming inactive
// Record the CLI time before switching to inactive
const now = this.getNow()
const timeSinceLastRecord = (now - this.lastCLIRecordedTime) / 1000
if (timeSinceLastRecord > 0) {
const activeTimeCounter = this.getActiveTimeCounter()
if (activeTimeCounter) {
activeTimeCounter.add(timeSinceLastRecord, { type: 'cli' })
}
}
this.lastCLIRecordedTime = now
this.isCLIActive = false
}
}
/**
* Convenience method to track an async operation automatically (mainly for testing/debugging)
*/
async trackOperation<T>(
operationId: string,
fn: () => Promise<T>,
): Promise<T> {
this.startCLIActivity(operationId)
try {
return await fn()
} finally {
this.endCLIActivity(operationId)
}
}
/**
* Gets current activity states (mainly for testing/debugging)
*/
getActivityStates(): {
isUserActive: boolean
isCLIActive: boolean
activeOperationCount: number
} {
const now = this.getNow()
const timeSinceUserActivity = (now - this.lastUserActivityTime) / 1000
const isUserActive =
timeSinceUserActivity < this.USER_ACTIVITY_TIMEOUT_MS / 1000
return {
isUserActive,
isCLIActive: this.isCLIActive,
activeOperationCount: this.activeOperations.size,
}
}
}
// Export singleton instance
export const activityManager = ActivityManager.getInstance()
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/up/claude-code-source-code.git
git@gitee.com:up/claude-code-source-code.git
up
claude-code-source-code
claude-code-source-code
main

搜索帮助