- Injected HTTPUpstream service into LanguageServerService - Implemented real upstream API requests via callUpstreamAPI() - Added SSE streaming response handler for streaming messages - Complete error handling and structured logging - Support for masquerading headers (User-Agent, Authorization) - Request/response body marshaling and streaming - Thread-safe session management with metadata storage Core implementation: - LanguageServerService now depends on HTTPUpstream for all HTTP operations - HTTP requests sent to configured Anthropic API endpoint - SSE event parsing and forwarding to clients via update channels - Proper context and timeout handling for streaming operations Phase 1 Status: 95% complete - Upstream API integration: ✅ DONE - Wire dependency injection: ⏳ TODO - Masquerading layer: ⏳ TODO (Phase 2) Next steps: 1. Add Wire provider for LanguageServerService 2. Register HTTP routes in application startup 3. Implement device fingerprinting and token refresh 4. End-to-end testing with real Anthropic API Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
219 lines
6.1 KiB
Protocol Buffer
219 lines
6.1 KiB
Protocol Buffer
syntax = "proto3";
|
||
|
||
package exa.language_server_pb;
|
||
|
||
option go_package = "github.com/Wei-Shaw/sub2api/internal/gen/language_server_pb";
|
||
|
||
import "google/protobuf/timestamp.proto";
|
||
import "google/protobuf/empty.proto";
|
||
|
||
// ============================================================================
|
||
// 核心 Cascade 消息类型(Agent 流程)
|
||
// ============================================================================
|
||
|
||
message StartCascadeRequest {
|
||
string model = 1; // 模型名称(e.g., "claude-opus-4-6")
|
||
string system_prompt = 2; // 系统提示(可选)
|
||
map<string, string> metadata = 3; // 元数据(设备指纹、User-Agent 等)
|
||
}
|
||
|
||
message StartCascadeResponse {
|
||
string cascade_id = 1; // 新建会话的 ID
|
||
}
|
||
|
||
message SendUserCascadeMessageRequest {
|
||
string cascade_id = 1; // 会话 ID
|
||
string message = 2; // 用户消息
|
||
map<string, string> context = 3; // 上下文信息(文件、符号等)
|
||
}
|
||
|
||
message CascadeReactiveUpdate {
|
||
enum UpdateType {
|
||
UNKNOWN = 0;
|
||
STATE_CHANGE = 1; // Agent 状态变化
|
||
MESSAGE_DELTA = 2; // 消息增量(流式文本)
|
||
TOOL_CALL = 3; // 工具调用
|
||
CODE_EDIT = 4; // 代码编辑提案
|
||
COMPLETION = 5; // Agent 完成
|
||
}
|
||
|
||
UpdateType type = 1;
|
||
string payload = 2; // JSON 格式的负载
|
||
google.protobuf.Timestamp timestamp = 3;
|
||
}
|
||
|
||
message CancelCascadeInvocationRequest {
|
||
string cascade_id = 1;
|
||
}
|
||
|
||
message CancelCascadeInvocationResponse {
|
||
}
|
||
|
||
message AcknowledgeCascadeCodeEditRequest {
|
||
string cascade_id = 1;
|
||
string code_edit_id = 2;
|
||
bool accepted = 3;
|
||
}
|
||
|
||
message AcknowledgeCascadeCodeEditResponse {
|
||
}
|
||
|
||
// ============================================================================
|
||
// 模型配置消息类型
|
||
// ============================================================================
|
||
|
||
message ModelConfig {
|
||
string name = 1; // 模型名称(e.g., "claude-opus-4-6")
|
||
string display_name = 2; // 显示名称(e.g., "Claude Opus 4.6")
|
||
int32 model_id = 3; // 模型 ID(枚举值)
|
||
int32 max_tokens = 4; // 最大输出 token 数
|
||
bool supports_thinking = 5; // 是否支持 thinking
|
||
int32 thinking_budget = 6; // thinking token 预算
|
||
bool supports_images = 7; // 是否支持图像
|
||
string provider = 8; // 提供者(anthropic/google/openai)
|
||
}
|
||
|
||
message GetCascadeModelConfigsRequest {
|
||
}
|
||
|
||
message GetCascadeModelConfigsResponse {
|
||
repeated ModelConfig models = 1;
|
||
string default_model = 2;
|
||
}
|
||
|
||
message GetCommandModelConfigsRequest {
|
||
}
|
||
|
||
message GetCommandModelConfigsResponse {
|
||
repeated ModelConfig models = 1;
|
||
}
|
||
|
||
// ============================================================================
|
||
// 文件操作消息类型
|
||
// ============================================================================
|
||
|
||
message FileInfo {
|
||
enum Type {
|
||
UNKNOWN = 0;
|
||
FILE = 1;
|
||
DIRECTORY = 2;
|
||
SYMLINK = 3;
|
||
}
|
||
|
||
string path = 1;
|
||
Type type = 2;
|
||
int64 size = 3;
|
||
google.protobuf.Timestamp modified_time = 4;
|
||
}
|
||
|
||
message ReadFileRequest {
|
||
string path = 1;
|
||
}
|
||
|
||
message ReadFileResponse {
|
||
string content = 1;
|
||
string encoding = 2; // UTF-8, binary, etc.
|
||
}
|
||
|
||
message WriteFileRequest {
|
||
string path = 1;
|
||
string content = 2;
|
||
bool create_parent = 3; // 是否创建父目录
|
||
}
|
||
|
||
message WriteFileResponse {
|
||
bool success = 1;
|
||
}
|
||
|
||
message ReadDirRequest {
|
||
string path = 1;
|
||
}
|
||
|
||
message ReadDirResponse {
|
||
repeated FileInfo files = 1;
|
||
}
|
||
|
||
message DeleteFileOrDirectoryRequest {
|
||
string path = 1;
|
||
bool recursive = 2; // 递归删除目录
|
||
}
|
||
|
||
message DeleteFileOrDirectoryResponse {
|
||
bool success = 1;
|
||
}
|
||
|
||
message StatUriRequest {
|
||
string path = 1;
|
||
}
|
||
|
||
message StatUriResponse {
|
||
FileInfo file_info = 1;
|
||
}
|
||
|
||
message WatchDirectoryRequest {
|
||
string path = 1;
|
||
repeated string patterns = 2; // 文件模式(glob)
|
||
}
|
||
|
||
message WatchDirectoryResponse {
|
||
string event_type = 1; // created, modified, deleted
|
||
string path = 2;
|
||
google.protobuf.Timestamp timestamp = 3;
|
||
}
|
||
|
||
// ============================================================================
|
||
// 通用消息类型
|
||
// ============================================================================
|
||
|
||
message HeartbeatRequest {
|
||
string session_id = 1;
|
||
}
|
||
|
||
message HeartbeatResponse {
|
||
bool healthy = 1;
|
||
string version = 2;
|
||
}
|
||
|
||
message GetStatusRequest {
|
||
}
|
||
|
||
message GetStatusResponse {
|
||
string status = 1; // running, degraded, down
|
||
string version = 2;
|
||
map<string, string> info = 3;
|
||
}
|
||
|
||
message ErrorInfo {
|
||
string code = 1;
|
||
string message = 2;
|
||
map<string, string> details = 3;
|
||
}
|
||
|
||
// ============================================================================
|
||
// LanguageServerService RPC 定义(核心方法)
|
||
// ============================================================================
|
||
|
||
service LanguageServerService {
|
||
// Cascade 流程
|
||
rpc StartCascade(StartCascadeRequest) returns (StartCascadeResponse);
|
||
rpc SendUserCascadeMessage(SendUserCascadeMessageRequest) returns (stream CascadeReactiveUpdate);
|
||
rpc CancelCascadeInvocation(CancelCascadeInvocationRequest) returns (CancelCascadeInvocationResponse);
|
||
rpc AcknowledgeCascadeCodeEdit(AcknowledgeCascadeCodeEditRequest) returns (AcknowledgeCascadeCodeEditResponse);
|
||
|
||
// 模型配置
|
||
rpc GetCascadeModelConfigs(GetCascadeModelConfigsRequest) returns (GetCascadeModelConfigsResponse);
|
||
rpc GetCommandModelConfigs(GetCommandModelConfigsRequest) returns (GetCommandModelConfigsResponse);
|
||
|
||
// 文件操作
|
||
rpc ReadFile(ReadFileRequest) returns (ReadFileResponse);
|
||
rpc WriteFile(WriteFileRequest) returns (WriteFileResponse);
|
||
rpc ReadDir(ReadDirRequest) returns (ReadDirResponse);
|
||
rpc DeleteFileOrDirectory(DeleteFileOrDirectoryRequest) returns (DeleteFileOrDirectoryResponse);
|
||
rpc StatUri(StatUriRequest) returns (StatUriResponse);
|
||
rpc WatchDirectory(WatchDirectoryRequest) returns (stream WatchDirectoryResponse);
|
||
|
||
// 健康检查
|
||
rpc Heartbeat(HeartbeatRequest) returns (HeartbeatResponse);
|
||
rpc GetStatus(GetStatusRequest) returns (GetStatusResponse);
|
||
}
|