Skip to content
Open
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
10 changes: 5 additions & 5 deletions .github/workflows/artifacts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,22 +56,22 @@ jobs:
echo "commit=$COMMIT" >> $GITHUB_OUTPUT
echo "date=$DATE" >> $GITHUB_OUTPUT

- name: Build binary (Linux in Alpine container)
- name: Build binary (Linux portable - no CGO/SQLite for maximum compatibility)
if: matrix.goos == 'linux'
run: |
docker run --rm \
-v $PWD:/workspace \
-w /workspace \
-e CGO_ENABLED=1 \
-e CGO_ENABLED=0 \
golang:1.25-alpine3.23 \
sh -c "apk add --no-cache gcc musl-dev sqlite-dev && go build -tags libsqlite3 -ldflags '-w -s -X github.com/inference-gateway/cli/cmd.version=${{ steps.version.outputs.version }} -X github.com/inference-gateway/cli/cmd.commit=${{ steps.version.outputs.commit }} -X github.com/inference-gateway/cli/cmd.date=${{ steps.version.outputs.date }}' -o infer-${{ matrix.goos }}-${{ matrix.goarch }} ."
sh -c "go build -ldflags '-w -s -X github.com/inference-gateway/cli/cmd.version=${{ steps.version.outputs.version }} -X github.com/inference-gateway/cli/cmd.commit=${{ steps.version.outputs.commit }} -X github.com/inference-gateway/cli/cmd.date=${{ steps.version.outputs.date }}' -o infer-${{ matrix.goos }}-${{ matrix.goarch }} ."

- name: Build binary (macOS native)
- name: Build binary (macOS native with CGO for clipboard support)
if: matrix.goos == 'darwin'
env:
CGO_ENABLED: ${{ matrix.cgo }}
run: |
go build -tags libsqlite3 -ldflags "-w -s -X github.com/inference-gateway/cli/cmd.version=${{ steps.version.outputs.version }} -X github.com/inference-gateway/cli/cmd.commit=${{ steps.version.outputs.commit }} -X github.com/inference-gateway/cli/cmd.date=${{ steps.version.outputs.date }}" -o infer-${{ matrix.goos }}-${{ matrix.goarch }} .
go build -ldflags "-w -s -X github.com/inference-gateway/cli/cmd.version=${{ steps.version.outputs.version }} -X github.com/inference-gateway/cli/cmd.commit=${{ steps.version.outputs.commit }} -X github.com/inference-gateway/cli/cmd.date=${{ steps.version.outputs.date }}" -o infer-${{ matrix.goos }}-${{ matrix.goarch }} .

- name: Upload artifact
uses: actions/upload-artifact@v5
Expand Down
20 changes: 20 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,30 @@ tasks:
- mkdir -p dist
- CGO_ENABLED=1 GOOS=darwin GOARCH={{.GOARCH}} go build -tags libsqlite3 -ldflags "-w -s -X github.com/inference-gateway/cli/cmd.version={{.VERSION}} -X github.com/inference-gateway/cli/cmd.commit={{.COMMIT}} -X github.com/inference-gateway/cli/cmd.date={{.DATE}}" -o dist/{{.BINARY_NAME}}-darwin-{{.GOARCH}} {{.MAIN_PACKAGE}}

release:build:linux:
desc: Build portable Linux binary using Docker (no CGO/SQLite for maximum compatibility)
vars:
GOARCH:
sh: go env GOARCH
cmds:
- mkdir -p dist
- |
echo "Building portable Linux binary using Docker (no SQLite dependencies)..."
docker run --rm \
-v "{{.PWD}}":/build \
-w /build \
golang:1.25-alpine \
sh -c 'CGO_ENABLED=0 GOOS=linux GOARCH={{.GOARCH}} \
go build \
-ldflags "-w -s -X github.com/inference-gateway/cli/cmd.version={{.VERSION}} -X github.com/inference-gateway/cli/cmd.commit={{.COMMIT}} -X github.com/inference-gateway/cli/cmd.date={{.DATE}}" \
-o dist/{{.BINARY_NAME}}-linux-{{.GOARCH}} .'
echo "✓ Built portable dist/{{.BINARY_NAME}}-linux-{{.GOARCH}} (JSONL/Redis/PostgreSQL support, no SQLite)"

container:build:
desc: Build container image locally for testing
cmds:
- task: release:build
- task: release:build:linux
- |
docker build \
--build-context binaries=dist/ \
Expand Down
34 changes: 34 additions & 0 deletions cmd/chat.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,34 @@ and have a conversational interface with the inference gateway.`,
if cmd.Flags().Changed("port") {
cfg.Web.Port, _ = cmd.Flags().GetInt("port")
}
if cmd.Flags().Changed("host") {
cfg.Web.Host, _ = cmd.Flags().GetString("host")
}

// SSH remote mode flags
if cmd.Flags().Changed("ssh-host") {
cfg.Web.SSH.Enabled = true
sshHost, _ := cmd.Flags().GetString("ssh-host")
sshUser, _ := cmd.Flags().GetString("ssh-user")
sshPort, _ := cmd.Flags().GetInt("ssh-port")
sshCommand, _ := cmd.Flags().GetString("ssh-command")
noInstall, _ := cmd.Flags().GetBool("ssh-no-install")

// Create a single server config from CLI flags
cfg.Web.Servers = []config.SSHServerConfig{
{
Name: "CLI Remote Server",
ID: "cli-remote",
RemoteHost: sshHost,
RemotePort: sshPort,
RemoteUser: sshUser,
CommandPath: sshCommand,
AutoInstall: func() *bool { b := !noInstall; return &b }(),
Description: "Remote server configured via CLI flags",
},
}
}

return StartWebChatSession(cfg, V)
}

Expand Down Expand Up @@ -345,4 +373,10 @@ func init() {
rootCmd.AddCommand(chatCmd)
chatCmd.Flags().Bool("web", false, "Start web terminal interface")
chatCmd.Flags().Int("port", 0, "Web server port (default: 3000)")
chatCmd.Flags().String("host", "", "Web server host (default: localhost)")
chatCmd.Flags().String("ssh-host", "", "Remote SSH server hostname")
chatCmd.Flags().String("ssh-user", "", "Remote SSH username")
chatCmd.Flags().Int("ssh-port", 22, "Remote SSH port")
chatCmd.Flags().Bool("ssh-no-install", false, "Disable auto-installation of infer on remote")
chatCmd.Flags().String("ssh-command", "infer", "Path to infer binary on remote")
}
7 changes: 7 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,13 @@ func initConfig() { // nolint:funlen
v.SetDefault("web.port", defaults.Web.Port)
v.SetDefault("web.host", defaults.Web.Host)
v.SetDefault("web.session_inactivity_mins", defaults.Web.SessionInactivityMins)
v.SetDefault("web.ssh", defaults.Web.SSH)
v.SetDefault("web.ssh.enabled", defaults.Web.SSH.Enabled)
v.SetDefault("web.ssh.use_ssh_config", defaults.Web.SSH.UseSSHConfig)
v.SetDefault("web.ssh.known_hosts_path", defaults.Web.SSH.KnownHostsPath)
v.SetDefault("web.ssh.auto_install", defaults.Web.SSH.AutoInstall)
v.SetDefault("web.ssh.install_version", defaults.Web.SSH.InstallVersion)
v.SetDefault("web.servers", defaults.Web.Servers)
v.SetDefault("git", defaults.Git)
v.SetDefault("storage", defaults.Storage)
v.SetDefault("conversation", defaults.Conversation)
Expand Down
42 changes: 38 additions & 4 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,10 +267,36 @@ type CompactConfig struct {

// WebConfig contains web terminal settings
type WebConfig struct {
Enabled bool `yaml:"enabled" mapstructure:"enabled"`
Port int `yaml:"port" mapstructure:"port"`
Host string `yaml:"host" mapstructure:"host"`
SessionInactivityMins int `yaml:"session_inactivity_mins" mapstructure:"session_inactivity_mins"`
Enabled bool `yaml:"enabled" mapstructure:"enabled"`
Port int `yaml:"port" mapstructure:"port"`
Host string `yaml:"host" mapstructure:"host"`
SessionInactivityMins int `yaml:"session_inactivity_mins" mapstructure:"session_inactivity_mins"`
SSH WebSSHConfig `yaml:"ssh" mapstructure:"ssh"`
Servers []SSHServerConfig `yaml:"servers" mapstructure:"servers"`
}

// WebSSHConfig contains SSH connection settings for remote servers
type WebSSHConfig struct {
Enabled bool `yaml:"enabled" mapstructure:"enabled"`
UseSSHConfig bool `yaml:"use_ssh_config" mapstructure:"use_ssh_config"`
KnownHostsPath string `yaml:"known_hosts_path" mapstructure:"known_hosts_path"`
AutoInstall bool `yaml:"auto_install" mapstructure:"auto_install"`
InstallVersion string `yaml:"install_version" mapstructure:"install_version"`
}

// SSHServerConfig contains configuration for a single remote SSH server
type SSHServerConfig struct {
Name string `yaml:"name" mapstructure:"name"`
ID string `yaml:"id" mapstructure:"id"`
RemoteHost string `yaml:"remote_host" mapstructure:"remote_host"`
RemotePort int `yaml:"remote_port" mapstructure:"remote_port"`
RemoteUser string `yaml:"remote_user" mapstructure:"remote_user"`
CommandPath string `yaml:"command_path" mapstructure:"command_path"`
CommandArgs []string `yaml:"command_args" mapstructure:"command_args"`
AutoInstall *bool `yaml:"auto_install,omitempty" mapstructure:"auto_install"`
InstallPath string `yaml:"install_path" mapstructure:"install_path"`
Description string `yaml:"description" mapstructure:"description"`
Tags []string `yaml:"tags" mapstructure:"tags"`
}

// SystemRemindersConfig contains settings for dynamic system reminders
Expand Down Expand Up @@ -936,6 +962,14 @@ Write the AGENTS.md file to the project root when you have gathered enough infor
Port: 3000,
Host: "localhost",
SessionInactivityMins: 5,
SSH: WebSSHConfig{
Enabled: false,
UseSSHConfig: true,
KnownHostsPath: "~/.ssh/known_hosts",
AutoInstall: true,
InstallVersion: "latest",
},
Servers: []SSHServerConfig{},
},
}
}
Expand Down
10 changes: 10 additions & 0 deletions examples/web-terminal/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
ANTHROPIC_API_KEY=
CLOUDFLARE_API_KEY=
COHERE_API_KEY=
GROQ_API_KEY=
OLLAMA_API_KEY=
OLLAMA_CLOUD_API_KEY=
OPENAI_API_KEY=
DEEPSEEK_API_KEY=
GOOGLE_API_KEY=
MISTRAL_API_KEY=
1 change: 1 addition & 0 deletions examples/web-terminal/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.ssh-keys/
Loading