mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
refactor: extract chat normalization and reducer logic, cleanup legacy credentials
- Split normalize.ts into focused modules: normalizeAgent, normalizeUser, normalizeUtils - Extract reducer.ts into specialized modules: reducerCliOutput, reducerEvents, reducerTimeline, reducerTools - Remove legacy credentials support (zod schema, readCredentials, writeCredentialsLegacy) - Refactor NewSession component from monolithic file into modular subcomponents - Improves code organization and maintainability across chat and authentication layers
This commit is contained in:
+1
-61
@@ -1,14 +1,13 @@
|
||||
/**
|
||||
* Minimal persistence functions for HAPI CLI
|
||||
*
|
||||
* Handles settings and private key storage in ~/.hapi/ (or HAPI_HOME override)
|
||||
* Handles settings, encryption key, and daemon state storage in ~/.hapi/ (or HAPI_HOME override)
|
||||
*/
|
||||
|
||||
import { FileHandle } from 'node:fs/promises'
|
||||
import { readFile, writeFile, mkdir, open, unlink, rename, stat } from 'node:fs/promises'
|
||||
import { existsSync, writeFileSync, readFileSync, unlinkSync } from 'node:fs'
|
||||
import { configuration } from '@/configuration'
|
||||
import * as z from 'zod';
|
||||
import { encodeBase64 } from '@/api/encryption';
|
||||
import { isProcessAlive } from '@/utils/process';
|
||||
|
||||
@@ -132,65 +131,6 @@ export async function updateSettings(
|
||||
// Authentication
|
||||
//
|
||||
|
||||
const credentialsSchema = z.object({
|
||||
token: z.string(),
|
||||
secret: z.string().base64().nullish(), // Legacy
|
||||
encryption: z.object({
|
||||
publicKey: z.string().base64(),
|
||||
machineKey: z.string().base64()
|
||||
}).nullish()
|
||||
})
|
||||
|
||||
export type Credentials = {
|
||||
token: string,
|
||||
encryption: {
|
||||
type: 'legacy', secret: Uint8Array
|
||||
} | {
|
||||
type: 'dataKey', publicKey: Uint8Array, machineKey: Uint8Array
|
||||
}
|
||||
}
|
||||
|
||||
export async function readCredentials(): Promise<Credentials | null> {
|
||||
if (!existsSync(configuration.privateKeyFile)) {
|
||||
return null
|
||||
}
|
||||
try {
|
||||
const keyBase64 = (await readFile(configuration.privateKeyFile, 'utf8'));
|
||||
const credentials = credentialsSchema.parse(JSON.parse(keyBase64));
|
||||
if (credentials.secret) {
|
||||
return {
|
||||
token: credentials.token,
|
||||
encryption: {
|
||||
type: 'legacy',
|
||||
secret: new Uint8Array(Buffer.from(credentials.secret, 'base64'))
|
||||
}
|
||||
};
|
||||
} else if (credentials.encryption) {
|
||||
return {
|
||||
token: credentials.token,
|
||||
encryption: {
|
||||
type: 'dataKey',
|
||||
publicKey: new Uint8Array(Buffer.from(credentials.encryption.publicKey, 'base64')),
|
||||
machineKey: new Uint8Array(Buffer.from(credentials.encryption.machineKey, 'base64'))
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export async function writeCredentialsLegacy(credentials: { secret: Uint8Array, token: string }): Promise<void> {
|
||||
if (!existsSync(configuration.happyHomeDir)) {
|
||||
await mkdir(configuration.happyHomeDir, { recursive: true })
|
||||
}
|
||||
await writeFile(configuration.privateKeyFile, JSON.stringify({
|
||||
secret: encodeBase64(credentials.secret),
|
||||
token: credentials.token
|
||||
}, null, 2));
|
||||
}
|
||||
|
||||
export async function writeCredentialsDataKey(credentials: { publicKey: Uint8Array, machineKey: Uint8Array, token: string }): Promise<void> {
|
||||
if (!existsSync(configuration.happyHomeDir)) {
|
||||
await mkdir(configuration.happyHomeDir, { recursive: true })
|
||||
|
||||
+1
-10
@@ -7,7 +7,7 @@
|
||||
|
||||
import chalk from 'chalk'
|
||||
import { configuration } from '@/configuration'
|
||||
import { readSettings, readCredentials } from '@/persistence'
|
||||
import { readSettings } from '@/persistence'
|
||||
import { checkIfDaemonRunningAndCleanupStaleState } from '@/daemon/controlClient'
|
||||
import { findRunawayHappyProcesses, findAllHappyProcesses } from '@/daemon/doctor'
|
||||
import { readDaemonState } from '@/persistence'
|
||||
@@ -147,15 +147,6 @@ export async function runDoctorCommand(filter?: 'all' | 'daemon'): Promise<void>
|
||||
console.log(chalk.gray(' Run `hapi auth login` to configure or set CLI_API_TOKEN env var'));
|
||||
}
|
||||
|
||||
// Legacy credentials (unused in direct-connect mode)
|
||||
try {
|
||||
const credentials = await readCredentials();
|
||||
if (credentials) {
|
||||
console.log(chalk.yellow('⚠️ Legacy credentials file present (unused in direct-connect mode)'));
|
||||
}
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
// Daemon status - shown for both 'all' and 'daemon' filters
|
||||
|
||||
Reference in New Issue
Block a user