Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions internal/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import (
"bufio"
"crypto/rand"
"encoding/json"
"fmt"
"net"
Expand Down Expand Up @@ -84,9 +85,19 @@
return c.encoder.Encode(env)
}

func uuidV4() string {
b := make([]byte, 16)
rand.Read(b)

Check failure on line 90 in internal/client/client.go

View workflow job for this annotation

GitHub Actions / build

Error return value of `rand.Read` is not checked (errcheck)
b[6] = (b[6] & 0x0f) | 0x40
b[8] = (b[8] & 0x3f) | 0x80
return fmt.Sprintf("%08x-%04x-%04x-%04x-%012x",
b[0:4], b[4:6], b[6:8], b[8:10], b[10:16])
}

func (c *Conn) SendMessage(msgType string, payload interface{}) error {
env := Envelope{
Type: msgType,
ID: uuidV4(),
Timestamp: time.Now().UTC().Format(time.RFC3339),
From: "cli",
}
Expand All @@ -108,6 +119,16 @@
})
}

func (c *Conn) SendVoice() error {
return c.SendMessage("input_forward", map[string]interface{}{
"mode": "voice",
"content": "",
"context": map[string]interface{}{
"session_id": fmt.Sprintf("sess_%d", time.Now().UnixNano()),
},
})
}

func (c *Conn) SendSystemCode(code string, unlockCode string) error {
payload := map[string]interface{}{
"code": code,
Expand Down
7 changes: 2 additions & 5 deletions internal/tui/keybind.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,8 @@
switch msg.String() {
case "ctrl+c", "ctrl+d":
return m, tea.Quit
case "ctrl+alt+s":
m.conn.SendSystemCode("security", "")
return m, nil
case "/":
m.conn.SendInput("[voice input]")
m.conn.SendVoice()

Check failure on line 33 in internal/tui/keybind.go

View workflow job for this annotation

GitHub Actions / build

Error return value of `m.conn.SendVoice` is not checked (errcheck)
return m, nil
case "esc":
return m, nil
Expand All @@ -59,8 +56,8 @@
m.historyIdx = len(m.history)
m.input.Reset()
m.state = StateProcessing
m.conn.SendInput(input)

Check failure on line 59 in internal/tui/keybind.go

View workflow job for this annotation

GitHub Actions / build

Error return value of `m.conn.SendInput` is not checked (errcheck)
m.conn.RequestStatus()

Check failure on line 60 in internal/tui/keybind.go

View workflow job for this annotation

GitHub Actions / build

Error return value of `m.conn.RequestStatus` is not checked (errcheck)
return m, nil

case "esc":
Expand Down Expand Up @@ -104,7 +101,7 @@
return m, tea.ClearScreen

case "/":
m.conn.SendInput("[voice input]")
m.conn.SendVoice()

Check failure on line 104 in internal/tui/keybind.go

View workflow job for this annotation

GitHub Actions / build

Error return value of `m.conn.SendVoice` is not checked (errcheck)
return m, nil

default:
Expand Down Expand Up @@ -147,7 +144,7 @@
m.historyIdx = len(m.history)
m.input.Reset()
m.state = StateProcessing
m.conn.SendInput(input)

Check failure on line 147 in internal/tui/keybind.go

View workflow job for this annotation

GitHub Actions / build

Error return value of `m.conn.SendInput` is not checked (errcheck)
return m, nil

case "esc":
Expand Down Expand Up @@ -201,7 +198,7 @@
m.historyIdx = len(m.history)
m.input.Reset()
m.state = StateProcessing
m.conn.SendInput(input)

Check failure on line 201 in internal/tui/keybind.go

View workflow job for this annotation

GitHub Actions / build

Error return value of `m.conn.SendInput` is not checked (errcheck)
} else {
m.state = StateIdle
}
Expand Down Expand Up @@ -230,7 +227,7 @@
case "enter":
code := m.codeInput.String()
if len(code) >= 4 {
m.conn.SendSystemCode("unlock", code)

Check failure on line 230 in internal/tui/keybind.go

View workflow job for this annotation

GitHub Actions / build

Error return value of `m.conn.SendSystemCode` is not checked (errcheck)
m.codeInput.Reset()
m.state = StateIdle
}
Expand Down
41 changes: 36 additions & 5 deletions internal/tui/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@

type outputMsg string
type statusMsg string
type connStatusMsg connectionStatus
type connStatusMsg connectionStatus
type reconnectMsg struct{}

func NewModel(conn *client.Conn) Model {
return Model{
Expand All @@ -71,14 +72,28 @@

func connectCmd(conn *client.Conn) tea.Cmd {
return func() tea.Msg {
for i := 0; i < 30; i++ {
for i := 0; ; i++ {
if err := conn.Connect(); err == nil {
conn.RequestStatus()

Check failure on line 77 in internal/tui/model.go

View workflow job for this annotation

GitHub Actions / build

Error return value of `conn.RequestStatus` is not checked (errcheck)
return connStatusMsg(ConnConnected)
}
if i >= 30 {
return connStatusMsg(ConnFailed)
}
time.Sleep(time.Second)
}
}
}

func reconnectCmd(conn *client.Conn) tea.Cmd {
return func() tea.Msg {
for {
if err := conn.Connect(); err == nil {
conn.RequestStatus()

Check failure on line 92 in internal/tui/model.go

View workflow job for this annotation

GitHub Actions / build

Error return value of `conn.RequestStatus` is not checked (errcheck)
return connStatusMsg(ConnConnected)
}
time.Sleep(time.Second)
}
return connStatusMsg(ConnFailed)
}
}

Expand Down Expand Up @@ -106,8 +121,21 @@
if m.connStatus == ConnConnected {
return m, listenCmd(m.conn)
}
if m.connStatus == ConnFailed {
return m, reconnectCmd(m.conn)
}
return m, nil

case reconnectMsg:
if m.connStatus == ConnFailed || m.connStatus == ConnDisconnected {
if err := m.conn.Connect(); err == nil {
m.conn.RequestStatus()
m.connStatus = ConnConnected
return m, listenCmd(m.conn)
}
}
return m, reconnectCmd(m.conn)

case outputMsg:
m.output.Reset()
m.output.WriteString(string(msg))
Expand Down Expand Up @@ -137,7 +165,7 @@
select {
case env, ok := <-conn.Messages:
if !ok {
return connStatusMsg(ConnDisconnected)
return reconnectMsg{}
}
switch env.Type {
case "output_deliver":
Expand Down Expand Up @@ -165,8 +193,11 @@
return "\n Loading..."
}

if m.connStatus == ConnConnecting {
return "\n\n Connecting...\n"
}
if m.connStatus == ConnFailed {
return m.renderError("Daemon unavailable. Check system.")
return "\n\n ⚠ Daemon unavailable. Check system.\n\n Retrying connection...\n"
}

switch m.state {
Expand Down
Loading