- Parse tools/tool_choice from OpenAI and Anthropic requests - Inject tool definitions into system prompt via toolemulation - Parse action blocks (```json action) from model responses - Retry logic for forced tool_choice (any/required) - Return proper tool_calls / tool_use in responses - Support streaming tools via collect-and-replay pattern - Add tool history projection (assistant tool_calls + tool results) - Model ID normalization: use official names (Qwen3.6-Plus, etc.) - Fix resolveSessionMode to use Fresh mode when tools present
58 lines
1.1 KiB
Go
58 lines
1.1 KiB
Go
//go:build windows
|
|
|
|
package lingmaipc
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net"
|
|
"sync"
|
|
|
|
winio "github.com/Microsoft/go-winio"
|
|
)
|
|
|
|
type pipeTransport struct {
|
|
path string
|
|
conn net.Conn
|
|
reader *framedReader
|
|
write sync.Mutex
|
|
}
|
|
|
|
func connectPipeTransport(ctx context.Context, pipePath string) (framedTransport, error) {
|
|
conn, err := winio.DialPipeContext(ctx, pipePath)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("connect Lingma IPC pipe %s: %w", pipePath, err)
|
|
}
|
|
return &pipeTransport{
|
|
path: pipePath,
|
|
conn: conn,
|
|
reader: newFramedReader(conn),
|
|
}, nil
|
|
}
|
|
|
|
func (t *pipeTransport) ReadFrame() ([]byte, error) {
|
|
return t.reader.ReadFrame()
|
|
}
|
|
|
|
func (t *pipeTransport) WriteFrame(body []byte) error {
|
|
t.write.Lock()
|
|
defer t.write.Unlock()
|
|
|
|
frame := []byte(fmt.Sprintf("Content-Length: %d\r\n\r\n", len(body)))
|
|
if _, err := t.conn.Write(frame); err != nil {
|
|
return fmt.Errorf("write frame header: %w", err)
|
|
}
|
|
if _, err := t.conn.Write(body); err != nil {
|
|
return fmt.Errorf("write frame body: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (t *pipeTransport) Close() error {
|
|
return t.conn.Close()
|
|
}
|
|
|
|
func (t *pipeTransport) Address() string {
|
|
return t.path
|
|
}
|