mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-27 01:11:40 +00:00
chore: formatting etc
This commit is contained in:
parent
56a69e519b
commit
5a5d90c85a
14 changed files with 698 additions and 237 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import { existsSync, mkdirSync, readFileSync, appendFileSync } from 'node:fs'
|
||||
import { appendFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs'
|
||||
import { homedir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
|
||||
|
|
@ -17,34 +17,51 @@ function decode(s: string): string {
|
|||
}
|
||||
|
||||
export function load(): string[] {
|
||||
if (cache) return cache
|
||||
if (cache) {
|
||||
return cache
|
||||
}
|
||||
|
||||
try {
|
||||
if (existsSync(file)) {
|
||||
cache = readFileSync(file, 'utf8')
|
||||
.split('\n')
|
||||
.filter(Boolean)
|
||||
.map(decode)
|
||||
.slice(-MAX)
|
||||
cache = readFileSync(file, 'utf8').split('\n').filter(Boolean).map(decode).slice(-MAX)
|
||||
} else {
|
||||
cache = []
|
||||
}
|
||||
} catch {
|
||||
cache = []
|
||||
}
|
||||
|
||||
return cache
|
||||
}
|
||||
|
||||
export function append(line: string): void {
|
||||
const trimmed = line.trim()
|
||||
if (!trimmed) return
|
||||
|
||||
if (!trimmed) {
|
||||
return
|
||||
}
|
||||
|
||||
const items = load()
|
||||
if (items.at(-1) === trimmed) return
|
||||
|
||||
if (items.at(-1) === trimmed) {
|
||||
return
|
||||
}
|
||||
|
||||
items.push(trimmed)
|
||||
if (items.length > MAX) items.splice(0, items.length - MAX)
|
||||
|
||||
if (items.length > MAX) {
|
||||
items.splice(0, items.length - MAX)
|
||||
}
|
||||
|
||||
try {
|
||||
if (!existsSync(dir)) mkdirSync(dir, { recursive: true })
|
||||
if (!existsSync(dir)) {
|
||||
mkdirSync(dir, { recursive: true })
|
||||
}
|
||||
|
||||
appendFileSync(file, encode(trimmed) + '\n')
|
||||
} catch { /* ignore */ }
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
|
||||
export function all(): string[] {
|
||||
|
|
|
|||
124
ui-tui/src/lib/slash.ts
Normal file
124
ui-tui/src/lib/slash.ts
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
import type { SlashCatalog } from '../types.js'
|
||||
|
||||
/** Match SlashCommandCompleter: command names, subcommands, then skills. */
|
||||
export function paletteForLine(line: string, c: SlashCatalog | null): [string, string][] {
|
||||
if (!c || !line.startsWith('/')) {
|
||||
return []
|
||||
}
|
||||
|
||||
const parts = line.split(/\s+/)
|
||||
const baseRaw = parts[0]!
|
||||
const base = baseRaw.toLowerCase()
|
||||
const inSub = parts.length > 1 || (parts.length === 1 && line.endsWith(' '))
|
||||
|
||||
if (inSub) {
|
||||
const subText = parts.length > 1 ? parts.slice(1).join(' ') : ''
|
||||
|
||||
if (subText.includes(' ') || parts.length > 2) {
|
||||
return []
|
||||
}
|
||||
|
||||
const head = subText.split(/\s+/)[0] ?? ''
|
||||
|
||||
if (subText.includes(' ') && head !== subText) {
|
||||
return []
|
||||
}
|
||||
|
||||
const canonical = c.canon[base] ?? baseRaw
|
||||
const subs = c.sub[canonical]
|
||||
|
||||
if (!subs?.length) {
|
||||
return []
|
||||
}
|
||||
|
||||
const lo = head.toLowerCase()
|
||||
|
||||
return subs
|
||||
.filter(s => s.toLowerCase().startsWith(lo) && s.toLowerCase() !== lo)
|
||||
.slice(0, 14)
|
||||
.map(s => [s, ''])
|
||||
}
|
||||
|
||||
const word = line.slice(1)
|
||||
|
||||
return c.pairs
|
||||
.filter(([k]) => k.slice(1).startsWith(word))
|
||||
.slice(0, 16)
|
||||
.map(([k, d]) => [k, d])
|
||||
}
|
||||
|
||||
/** Tab: longest common prefix of palette matches, or first unique completion + space. */
|
||||
export function tabAdvance(line: string, c: SlashCatalog | null): string | null {
|
||||
if (!c || !line.startsWith('/')) {
|
||||
return null
|
||||
}
|
||||
|
||||
const rows = paletteForLine(line, c)
|
||||
|
||||
if (!rows.length) {
|
||||
return null
|
||||
}
|
||||
|
||||
const parts = line.split(/\s+/)
|
||||
const baseRaw = parts[0]!
|
||||
const base = baseRaw.toLowerCase()
|
||||
const inSub = parts.length > 1 || (parts.length === 1 && line.endsWith(' '))
|
||||
|
||||
if (inSub) {
|
||||
const subText = parts.length > 1 ? parts.slice(1).join(' ') : ''
|
||||
const head = subText.split(/\s+/)[0] ?? ''
|
||||
const picks = rows.map(([s]) => s)
|
||||
|
||||
if (picks.length === 1) {
|
||||
return `${baseRaw} ${picks[0]!} `
|
||||
}
|
||||
|
||||
const cp = commonPrefix(picks)
|
||||
|
||||
if (cp.length > head.length) {
|
||||
return `${baseRaw} ${cp}`
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
const word = line.slice(1)
|
||||
const names = rows.map(([k]) => k.slice(1))
|
||||
const cp = commonPrefix(names)
|
||||
|
||||
if (names.length === 1) {
|
||||
return `/${names[0]!} `
|
||||
}
|
||||
|
||||
if (cp.length > word.length) {
|
||||
return `/${cp}`
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
function commonPrefix(xs: string[]): string {
|
||||
if (!xs.length) {
|
||||
return ''
|
||||
}
|
||||
|
||||
let n = 0
|
||||
|
||||
outer: while (true) {
|
||||
const ch = xs[0]![n]
|
||||
|
||||
if (ch === undefined) {
|
||||
break
|
||||
}
|
||||
|
||||
for (const x of xs) {
|
||||
if (x[n] !== ch) {
|
||||
break outer
|
||||
}
|
||||
}
|
||||
|
||||
n++
|
||||
}
|
||||
|
||||
return xs[0]!.slice(0, n)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue