Files
llmgw/internal/vscodeext/e2e/pack/main.go
T
Ilker ManapandClaude Opus 5.5 38dfe268c9
CI / test (push) Successful in 8m43s
VS Code gets the gateway's models from an extension the gateway serves
llmgw's own extension for VS Code, plain JavaScript with no dependencies,
packed into a .vsix by the binary at /setup/vscode/llmgw.vsix with the
serving gateway's address in it, so it needs no build, no Node and no
marketplace. It registers llmgw as a language-model provider: the chat's
model picker, agent mode and any extension that asks VS Code for a model
get every chat model the key may use, sized and with tool and vision
capabilities as the catalog says, streamed, tool calls both ways.

VS Code is a tool on the account page's Connect your editor: a key, the
install command, and an Open in VS Code link that hands the key to the
extension's secret storage. The extension's Sign In opens the page with a
state of its own; a link without it is confirmed, the gateway named, since
it decides where code is sent.

Tested in VS Code 1.138 against the PoC: 27 models listed, an answer from
qwen2.5-0.5b-instruct, and qwen3-coder-30b calling a tool and using its
result (internal/vscodeext/e2e).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 01:39:50 +02:00

61 lines
1.5 KiB
Go

// Command pack writes the VS Code extension as a gateway would serve it: the
// .vsix, and the same files unpacked, for VS Code's --extensionDevelopmentPath.
package main
import (
"archive/zip"
"bytes"
"flag"
"log"
"os"
"path/filepath"
"strings"
"gitea.mynodes.xyz/ilker/llmgw/internal/vscodeext"
)
func main() {
out := flag.String("out", "llmgw-vsix", "directory to write llmgw.vsix and its unpacked files into")
version := flag.String("version", "v0.0.1", "llmgw version the extension says it is")
gateway := flag.String("gateway", "", "gateway address the extension's setting starts at")
flag.Parse()
b, err := vscodeext.Build(*version, *gateway)
if err != nil {
log.Fatal(err)
}
if err := os.MkdirAll(*out, 0o755); err != nil {
log.Fatal(err)
}
if err := os.WriteFile(filepath.Join(*out, vscodeext.FileName), b, 0o644); err != nil {
log.Fatal(err)
}
zr, err := zip.NewReader(bytes.NewReader(b), int64(len(b)))
if err != nil {
log.Fatal(err)
}
for _, f := range zr.File {
if strings.Contains(f.Name, "..") {
log.Fatalf("unsafe name %q", f.Name)
}
dst := filepath.Join(*out, filepath.FromSlash(f.Name))
if err := os.MkdirAll(filepath.Dir(dst), 0o755); err != nil {
log.Fatal(err)
}
rc, err := f.Open()
if err != nil {
log.Fatal(err)
}
var body bytes.Buffer
_, err = body.ReadFrom(rc)
rc.Close()
if err != nil {
log.Fatal(err)
}
if err := os.WriteFile(dst, body.Bytes(), 0o644); err != nil {
log.Fatal(err)
}
}
log.Printf("wrote %s and its files under %s", vscodeext.FileName, *out)
}