Skip to content
This repository was archived by the owner on Sep 18, 2025. It is now read-only.

Commit cfdd687

Browse files
committed
add initial lsp support
1 parent afd9ad0 commit cfdd687

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+13991
-451
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ go build -o termai
9191
./termai
9292
```
9393

94+
## Acknowledgments
95+
96+
TermAI builds upon the work of several open source projects and developers:
97+
98+
- [@isaacphi](https://github.com/isaacphi) - LSP client implementation
99+
94100
## License
95101

96102
[License information coming soon]

cmd/lsp/main.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package main
2+
3+
func main() {
4+
}

cmd/root.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ var rootCmd = &cobra.Command{
3636
ctx := context.Background()
3737

3838
app := app.New(ctx, conn)
39+
defer app.Close()
3940
app.Logger.Info("Starting termai...")
4041
zone.NewGlobal()
4142
tui := tea.NewProgram(

go.mod

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
module github.com/kujtimiihoxha/termai
22

3-
go 1.23.5
3+
go 1.24.0
4+
5+
toolchain go1.24.2
46

57
require (
68
github.com/anthropics/anthropic-sdk-go v0.2.0-beta.2
@@ -11,6 +13,7 @@ require (
1113
github.com/charmbracelet/glamour v0.9.1
1214
github.com/charmbracelet/huh v0.6.0
1315
github.com/charmbracelet/lipgloss v1.1.0
16+
github.com/fsnotify/fsnotify v1.8.0
1417
github.com/go-logfmt/logfmt v0.6.0
1518
github.com/golang-migrate/migrate/v4 v4.18.2
1619
github.com/google/generative-ai-go v0.19.0
@@ -53,7 +56,6 @@ require (
5356
github.com/dustin/go-humanize v1.0.1 // indirect
5457
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
5558
github.com/felixge/httpsnoop v1.0.4 // indirect
56-
github.com/fsnotify/fsnotify v1.8.0 // indirect
5759
github.com/go-logr/logr v1.4.2 // indirect
5860
github.com/go-logr/stdr v1.2.2 // indirect
5961
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect

internal/app/services.go

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
"github.com/kujtimiihoxha/termai/internal/config"
88
"github.com/kujtimiihoxha/termai/internal/db"
99
"github.com/kujtimiihoxha/termai/internal/logging"
10+
"github.com/kujtimiihoxha/termai/internal/lsp"
11+
"github.com/kujtimiihoxha/termai/internal/lsp/watcher"
1012
"github.com/kujtimiihoxha/termai/internal/message"
1113
"github.com/kujtimiihoxha/termai/internal/permission"
1214
"github.com/kujtimiihoxha/termai/internal/session"
@@ -19,23 +21,59 @@ type App struct {
1921
Messages message.Service
2022
Permissions permission.Service
2123

24+
LSPClients map[string]*lsp.Client
25+
2226
Logger logging.Interface
27+
28+
ceanups []func()
2329
}
2430

2531
func New(ctx context.Context, conn *sql.DB) *App {
32+
cfg := config.Get()
2633
q := db.New(conn)
2734
log := logging.NewLogger(logging.Options{
28-
Level: config.Get().Log.Level,
35+
Level: cfg.Log.Level,
2936
})
3037
sessions := session.NewService(ctx, q)
3138
messages := message.NewService(ctx, q)
3239

33-
return &App{
40+
app := &App{
3441
Context: ctx,
3542
Sessions: sessions,
3643
Messages: messages,
3744
Permissions: permission.Default,
3845
Logger: log,
46+
LSPClients: make(map[string]*lsp.Client),
47+
}
48+
49+
for name, client := range cfg.LSP {
50+
lspClient, err := lsp.NewClient(client.Command, client.Args...)
51+
app.ceanups = append(app.ceanups, func() {
52+
lspClient.Close()
53+
})
54+
workspaceWatcher := watcher.NewWorkspaceWatcher(lspClient)
55+
if err != nil {
56+
log.Error("Failed to create LSP client for", name, err)
57+
continue
58+
}
59+
60+
_, err = lspClient.InitializeLSPClient(ctx, config.WorkingDirectory())
61+
if err != nil {
62+
log.Error("Initialize failed", "error", err)
63+
continue
64+
}
65+
go workspaceWatcher.WatchWorkspace(ctx, config.WorkingDirectory())
66+
app.LSPClients[name] = lspClient
3967
}
68+
return app
4069
}
4170

71+
func (a *App) Close() {
72+
for _, cleanup := range a.ceanups {
73+
cleanup()
74+
}
75+
for _, client := range a.LSPClients {
76+
client.Close()
77+
}
78+
a.Logger.Info("App closed")
79+
}

internal/config/config.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,21 @@ type Log struct {
4949
Level string `json:"level"`
5050
}
5151

52+
type LSPConfig struct {
53+
Disabled bool `json:"enabled"`
54+
Command string `json:"command"`
55+
Args []string `json:"args"`
56+
Options any `json:"options"`
57+
}
58+
5259
type Config struct {
5360
Data *Data `json:"data,omitempty"`
5461
Log *Log `json:"log,omitempty"`
5562
MCPServers map[string]MCPServer `json:"mcpServers,omitempty"`
5663
Providers map[models.ModelProvider]Provider `json:"providers,omitempty"`
5764

65+
LSP map[string]LSPConfig `json:"lsp,omitempty"`
66+
5867
Model *Model `json:"model,omitempty"`
5968
}
6069

internal/db/messages.sql.go

Lines changed: 17 additions & 54 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/db/migrations/000001_initial.up.sql

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,7 @@ CREATE TABLE IF NOT EXISTS messages (
2323
id TEXT PRIMARY KEY,
2424
session_id TEXT NOT NULL,
2525
role TEXT NOT NULL,
26-
content TEXT NOT NULL,
27-
thinking Text NOT NULL DEFAULT '',
28-
finished BOOLEAN NOT NULL DEFAULT 0,
29-
tool_calls TEXT,
30-
tool_results TEXT,
26+
parts TEXT NOT NULL default '[]',
3127
created_at INTEGER NOT NULL, -- Unix timestamp in milliseconds
3228
updated_at INTEGER NOT NULL, -- Unix timestamp in milliseconds
3329
FOREIGN KEY (session_id) REFERENCES sessions (id) ON DELETE CASCADE

internal/db/models.go

Lines changed: 6 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/db/sql/messages.sql

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,18 @@ INSERT INTO messages (
1414
id,
1515
session_id,
1616
role,
17-
finished,
18-
content,
19-
tool_calls,
20-
tool_results,
17+
parts,
2118
created_at,
2219
updated_at
2320
) VALUES (
24-
?, ?, ?, ?, ?, ?, ?, strftime('%s', 'now'), strftime('%s', 'now')
21+
?, ?, ?, ?, strftime('%s', 'now'), strftime('%s', 'now')
2522
)
2623
RETURNING *;
2724

2825
-- name: UpdateMessage :exec
2926
UPDATE messages
3027
SET
31-
content = ?,
32-
thinking = ?,
33-
tool_calls = ?,
34-
tool_results = ?,
35-
finished = ?,
28+
parts = ?,
3629
updated_at = strftime('%s', 'now')
3730
WHERE id = ?;
3831

0 commit comments

Comments
 (0)