mirror of
https://github.com/wu736139669/hapi.git
synced 2026-10-31 23:31:39 +00:00
The 5-minute reconciliation read the multi-GB OpenCode store on the hub's event loop with bun:sqlite; a cold scan froze every request for ~88s and stalled each machine's runner the same way. - scan in a spawned `hapi usage-scan` child process (stdin/stdout JSON) - refresh on demand from the usage page (debounced) + a daily fallback - a runner whose hub is localhost skips the store the hub already owns - machine scans run every 30min and read the message table sequentially in one pass instead of per-session indexed lookups
92 lines
2.8 KiB
TypeScript
92 lines
2.8 KiB
TypeScript
import chalk from 'chalk'
|
|
import { agyCommand } from './agy'
|
|
import { authCommand } from './auth'
|
|
import { claudeCommand } from './claude'
|
|
import { codexCommand } from './codex'
|
|
import { dshCommand } from './dsh'
|
|
import { cursorCommand } from './cursor'
|
|
import { connectCommand } from './connect'
|
|
import { runnerCommand } from './runner'
|
|
import { resumeCommand } from './resume'
|
|
import { doctorCommand } from './doctor'
|
|
import { kimiCommand } from './kimi'
|
|
import { copilotCommand } from './copilot'
|
|
import { grokCommand } from './grok'
|
|
import { opencodeCommand } from './opencode'
|
|
import { piCommand } from './pi'
|
|
import { hookForwarderCommand } from './hookForwarder'
|
|
import { mcpCommand } from './mcp'
|
|
import { mcpProxyCommand } from './mcpProxy'
|
|
import { notifyCommand } from './notify'
|
|
import { hubCommand } from './hub'
|
|
import { pingPeerCommand } from './pingPeer'
|
|
import { inspectPeerCommand } from './inspectPeer'
|
|
import { usageScanCommand } from './usageScan'
|
|
import type { CommandContext, CommandDefinition } from './types'
|
|
|
|
// Gemini CLI was sunset (Google stopped serving the consumer Gemini CLI on
|
|
// 2026-06-18) so the agent is no longer launchable. Keep an explicit tombstone
|
|
// command so `hapi gemini` explains why the agent is no longer available.
|
|
const removedGeminiCommand: CommandDefinition = {
|
|
name: 'gemini',
|
|
requiresRuntimeAssets: false,
|
|
run: async () => {
|
|
console.error(
|
|
chalk.red('Error:'),
|
|
'Gemini CLI is no longer supported and cannot be launched (Google sunset the consumer Gemini CLI on 2026-06-18). Existing Gemini sessions remain viewable in the web UI.'
|
|
)
|
|
process.exit(1)
|
|
}
|
|
}
|
|
|
|
const COMMANDS: CommandDefinition[] = [
|
|
agyCommand,
|
|
authCommand,
|
|
claudeCommand,
|
|
connectCommand,
|
|
codexCommand,
|
|
dshCommand,
|
|
cursorCommand,
|
|
dshCommand,
|
|
removedGeminiCommand,
|
|
grokCommand,
|
|
kimiCommand,
|
|
copilotCommand,
|
|
opencodeCommand,
|
|
piCommand,
|
|
mcpCommand,
|
|
mcpProxyCommand,
|
|
hubCommand,
|
|
{ ...hubCommand, name: 'server' },
|
|
hookForwarderCommand,
|
|
doctorCommand,
|
|
resumeCommand,
|
|
runnerCommand,
|
|
notifyCommand,
|
|
pingPeerCommand,
|
|
inspectPeerCommand,
|
|
// Internal: spawned by the hub to scan the local OpenCode store without
|
|
// blocking its event loop (see hub/src/sync/usageReconciliation.ts).
|
|
usageScanCommand
|
|
]
|
|
|
|
const commandMap = new Map<string, CommandDefinition>()
|
|
for (const command of COMMANDS) {
|
|
commandMap.set(command.name, command)
|
|
}
|
|
|
|
export function resolveCommand(args: string[]): { command: CommandDefinition; context: CommandContext } | null {
|
|
const subcommand = args[0]
|
|
const command = subcommand ? commandMap.get(subcommand) : undefined
|
|
if (!command) return null
|
|
|
|
return {
|
|
command,
|
|
context: {
|
|
args,
|
|
subcommand,
|
|
commandArgs: args.slice(1)
|
|
}
|
|
}
|
|
}
|