- PromptStore/Frontmatter : un prompt = un fichier Markdown, en-tête au sous-ensemble strict du document d'architecture (§7), écriture UTF-8 - VariableEngine : variables typées + automatiques (selection, clipboard, date, app, cursor), résolution et profils de destination - Injector/ClipboardGuard : focus capturé/rendu, presse-papiers sauvegardé puis restauré conditionnellement, aucun envoi automatique par défaut - Search : classement flou insensible aux accents, pondéré par l'usage - UsageStats (usage.json), HotkeyManager (conflits signalés, jamais muets) - Settings : config.ini + profils par IA (claude, chatgpt, qwen, terminal…) - PromptKey.ahk : tray, instance unique, capture du contexte, surveillance de la bibliothèque, installation du pack au premier lancement
76 lines
2.4 KiB
AutoHotkey
76 lines
2.4 KiB
AutoHotkey
; UsageStats.ahk — Compteurs d'usage et derniers choix de variables (architecture §15).
|
|
; Fichier usage.json à côté de la bibliothèque. Ne contient JAMAIS de valeurs 'password'
|
|
; ni le contenu des variables automatiques (sélection / presse-papiers).
|
|
|
|
class UsageStats {
|
|
Path := ""
|
|
Data := Map() ; id -> Map(count, last_used, last_values: Map)
|
|
|
|
__New(path) {
|
|
this.Path := path
|
|
this.Load()
|
|
}
|
|
|
|
Load() {
|
|
this.Data := Map()
|
|
if !FileExist(this.Path)
|
|
return
|
|
try {
|
|
raw := FileRead(this.Path, "UTF-8")
|
|
parsed := Json.Parse(raw)
|
|
if (parsed is Map)
|
|
this.Data := parsed
|
|
} catch as e {
|
|
Util.Log("usage.json illisible, reparti de zéro : " e.Message)
|
|
this.Data := Map()
|
|
}
|
|
}
|
|
|
|
Save() {
|
|
try {
|
|
f := FileOpen(this.Path, "w", "UTF-8")
|
|
f.Write(Json.Stringify(this.Data, 1))
|
|
f.Close()
|
|
} catch as e {
|
|
Util.Log("Écriture usage.json impossible : " e.Message)
|
|
}
|
|
}
|
|
|
|
RecordUse(id, manualValues := "") {
|
|
if !this.Data.Has(id)
|
|
this.Data[id] := Map("count", 0, "last_used", "", "last_values", Map())
|
|
entry := this.Data[id]
|
|
entry["count"] := (entry.Has("count") ? Integer(entry["count"]) : 0) + 1
|
|
entry["last_used"] := A_Now ; format AHK YYYYMMDDHH24MISS (comparaisons et DateDiff)
|
|
if (manualValues is Map) {
|
|
if !entry.Has("last_values") || !(entry["last_values"] is Map)
|
|
entry["last_values"] := Map()
|
|
lv := entry["last_values"]
|
|
for name, val in manualValues {
|
|
; Les mots de passe et les contextes ne sont jamais mémorisés (§10.4 / §15).
|
|
if (name = "password" || name = "selection" || name = "clipboard")
|
|
continue
|
|
lv[name] := String(val)
|
|
}
|
|
}
|
|
this.Save()
|
|
}
|
|
|
|
LastValues(id) {
|
|
if (this.Data.Has(id) && this.Data[id].Has("last_values") && (this.Data[id]["last_values"] is Map))
|
|
return this.Data[id]["last_values"]
|
|
return Map()
|
|
}
|
|
|
|
Count(id) {
|
|
if (this.Data.Has(id) && this.Data[id].Has("count"))
|
|
return Integer(this.Data[id]["count"])
|
|
return 0
|
|
}
|
|
|
|
Reset() {
|
|
this.Data := Map()
|
|
this.Save()
|
|
}
|
|
}
|