mirror of
https://github.com/ddworken/hishtory.git
synced 2025-06-23 13:31:39 +02:00
Swap AI completions to be behind a dedicated config option and add docs on it
This commit is contained in:
parent
aeadaf4e0d
commit
0be6fe9724
15
README.md
15
README.md
@ -62,6 +62,19 @@ To update `hishtory` to the latest version, just run `hishtory update` to secure
|
||||
|
||||
### Advanced Features
|
||||
|
||||
<details>
|
||||
<summary>AI Shell Assistance</summary>
|
||||
If you are ever trying to figure out a bash command and searching your history isn't working, you can query ChatGPT by prefixing your query with `?`. For example, press `Control+R` and then type in `? list all files larger than 1MB`:
|
||||
|
||||

|
||||
|
||||
If you would like to:
|
||||
* Disable this, you can run `hishtory config-set ai-completion false`
|
||||
* Run this with your own OpenAI API key (thereby ensuring that your queries do not pass through the centrally hosted hiSHtory server), you can run `export OPENAI_API_KEY='...'`
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>TUI key bindings</summary>
|
||||
The TUI (opened via `Control+R`) supports a number of key bindings:
|
||||
@ -74,6 +87,8 @@ The TUI (opened via `Control+R`) supports a number of key bindings:
|
||||
| Shift + Left/Right | Scroll the table left/right |
|
||||
| Control+K | Delete the selected command |
|
||||
|
||||
Press `Control+H` to view a help page documenting these.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
BIN
backend/web/landing/www/img/aidemo.png
Normal file
BIN
backend/web/landing/www/img/aidemo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
@ -1934,7 +1934,7 @@ func testTui_ai(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// Test running an AI query
|
||||
tester.RunInteractiveShell(t, `hishtory config-set beta-mode true`)
|
||||
require.Equal(t, "true", strings.TrimSpace(tester.RunInteractiveShell(t, `hishtory config-get ai-completion`)))
|
||||
out := captureTerminalOutputWithComplexCommands(t, tester, []TmuxCommand{
|
||||
{Keys: "hishtory SPACE tquery ENTER"},
|
||||
// ExtraDelay since AI queries are debounced and thus slower
|
||||
@ -1942,6 +1942,16 @@ func testTui_ai(t *testing.T) {
|
||||
})
|
||||
out = stripTuiCommandPrefix(t, out)
|
||||
testutils.CompareGoldens(t, out, "TestTui-AiQuery")
|
||||
|
||||
// Test that when it is disabled, no AI queries are run
|
||||
tester.RunInteractiveShell(t, `hishtory config-set ai-completion false`)
|
||||
out = captureTerminalOutput(t, tester, []string{
|
||||
"hishtory SPACE tquery ENTER",
|
||||
"'?myQuery'",
|
||||
})
|
||||
out = stripTuiCommandPrefix(t, out)
|
||||
testutils.CompareGoldens(t, out, "TestTui-AiQuery-Disabled")
|
||||
|
||||
}
|
||||
|
||||
func testControlR(t *testing.T, tester shellTester, shellName string, onlineStatus OnlineStatus) {
|
||||
|
@ -50,6 +50,17 @@ var getFilterDuplicateCommandsCmd = &cobra.Command{
|
||||
},
|
||||
}
|
||||
|
||||
var getEnableAiCompletion = &cobra.Command{
|
||||
Use: "ai-completion",
|
||||
Short: "Enable AI completion for searches starting with '?'",
|
||||
Long: "Note that AI completion requests are sent to the shared hiSHtory backend and then to OpenAI. Requests are not logged, but still be careful not to put anything sensitive in queries.",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
ctx := hctx.MakeContext()
|
||||
config := hctx.GetConf(ctx)
|
||||
fmt.Println(config.AiCompletion)
|
||||
},
|
||||
}
|
||||
|
||||
var getBetaModeCmd = &cobra.Command{
|
||||
Use: "beta-mode",
|
||||
Short: "Enable beta-mode to opt-in to unreleased features",
|
||||
@ -109,4 +120,5 @@ func init() {
|
||||
configGetCmd.AddCommand(getCustomColumnsCmd)
|
||||
configGetCmd.AddCommand(getBetaModeCmd)
|
||||
configGetCmd.AddCommand(getHighlightMatchesCmd)
|
||||
configGetCmd.AddCommand(getEnableAiCompletion)
|
||||
}
|
||||
|
@ -70,6 +70,24 @@ var setBetaModeCommand = &cobra.Command{
|
||||
},
|
||||
}
|
||||
|
||||
var setEnableAiCompletionCmd = &cobra.Command{
|
||||
Use: "ai-completion",
|
||||
Short: "Enable AI completion for searches starting with '?'",
|
||||
Long: "Note that AI completion requests are sent to the shared hiSHtory backend and then to OpenAI. Requests are not logged, but still be careful not to put anything sensitive in queries.",
|
||||
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
|
||||
ValidArgs: []string{"true", "false"},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
val := args[0]
|
||||
if val != "true" && val != "false" {
|
||||
log.Fatalf("Unexpected config value %s, must be one of: true, false", val)
|
||||
}
|
||||
ctx := hctx.MakeContext()
|
||||
config := hctx.GetConf(ctx)
|
||||
config.AiCompletion = (val == "true")
|
||||
lib.CheckFatalError(hctx.SetConfig(config))
|
||||
},
|
||||
}
|
||||
|
||||
var setHighlightMatchesCmd = &cobra.Command{
|
||||
Use: "highlight-matches",
|
||||
Short: "Enable highlight-matches to enable highlighting of matches in the search results",
|
||||
@ -119,4 +137,5 @@ func init() {
|
||||
configSetCmd.AddCommand(setTimestampFormatCmd)
|
||||
configSetCmd.AddCommand(setBetaModeCommand)
|
||||
configSetCmd.AddCommand(setHighlightMatchesCmd)
|
||||
configSetCmd.AddCommand(setEnableAiCompletionCmd)
|
||||
}
|
||||
|
@ -198,8 +198,8 @@ func handleDbUpgrades(ctx context.Context) error {
|
||||
|
||||
// Handles people running `hishtory update` from an old version of hishtory that
|
||||
// doesn't support certain config options that we now default to true. This ensures
|
||||
// that upgrades get them enabled by default, but if someone has it explicitly disabled,
|
||||
// we keep it that way.
|
||||
// that we can customize the behavior for upgrades while still respecting the option
|
||||
// if someone has it explicitly set.
|
||||
func handleUpgradedFeatures() error {
|
||||
configContents, err := hctx.GetConfigContents()
|
||||
if err != nil {
|
||||
@ -218,6 +218,10 @@ func handleUpgradedFeatures() error {
|
||||
// highlighting is not yet configured, so enable it
|
||||
config.HighlightMatches = true
|
||||
}
|
||||
if !strings.Contains(string(configContents), "ai_completion") {
|
||||
// AI completion is not yet configured, disable it for upgrades since this is a new feature
|
||||
config.AiCompletion = false
|
||||
}
|
||||
return hctx.SetConfig(&config)
|
||||
}
|
||||
|
||||
@ -562,6 +566,8 @@ func setup(userSecret string, isOffline bool) error {
|
||||
config.IsEnabled = true
|
||||
config.DeviceId = uuid.Must(uuid.NewRandom()).String()
|
||||
config.ControlRSearchEnabled = true
|
||||
// TODO: Set config.HighlightMatches = true here, so that we enable highlighting by default
|
||||
config.AiCompletion = true
|
||||
config.IsOffline = isOffline
|
||||
err := hctx.SetConfig(&config)
|
||||
if err != nil {
|
||||
|
@ -197,6 +197,8 @@ type ClientConfig struct {
|
||||
BetaMode bool `json:"beta_mode"`
|
||||
// Whether to highlight matches in search results
|
||||
HighlightMatches bool `json:"highlight_matches"`
|
||||
// Whether to enable AI completion
|
||||
AiCompletion bool `json:"ai_completion"`
|
||||
}
|
||||
|
||||
type CustomColumnDefinition struct {
|
||||
|
27
client/lib/goldens/TestTui-AiQuery-Disabled
Normal file
27
client/lib/goldens/TestTui-AiQuery-Disabled
Normal file
@ -0,0 +1,27 @@
|
||||
Search Query: > ?myQuery
|
||||
|
||||
┌────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│ Hostname CWD Timestamp Runtime Exit Code Command │
|
||||
│────────────────────────────────────────────────────────────────────────────────────────────────────────│
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
└────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
hiSHtory: Search your shell history • ctrl+h help
|
@ -471,7 +471,7 @@ func getRowsFromAiSuggestions(ctx context.Context, columnNames []string, query s
|
||||
func getRows(ctx context.Context, columnNames []string, query string, numEntries int) ([]table.Row, []*data.HistoryEntry, error) {
|
||||
db := hctx.GetDb(ctx)
|
||||
config := hctx.GetConf(ctx)
|
||||
if config.BetaMode && strings.HasPrefix(query, "?") && len(query) > 1 {
|
||||
if config.AiCompletion && !config.IsOffline && strings.HasPrefix(query, "?") && len(query) > 1 {
|
||||
return getRowsFromAiSuggestions(ctx, columnNames, query)
|
||||
}
|
||||
searchResults, err := lib.Search(ctx, db, query, numEntries)
|
||||
|
Loading…
x
Reference in New Issue
Block a user