feat: load packet logs from directory source

This commit is contained in:
zhaoyilun
2026-07-10 01:09:44 +08:00
parent 8f526e9aa9
commit 87a787ee1b
9 changed files with 361 additions and 25 deletions

View File

@@ -17,6 +17,7 @@ const (
ServerTitle = "iSphere AI Bridge"
ServerVersion = "0.1.0"
EnvPacketLogFileKey = "ISPHERE_PACKET_LOG_FILE"
EnvPacketLogDirKey = "ISPHERE_PACKET_LOG_DIR"
)
func NewServer() *mcp.Server {
@@ -26,12 +27,22 @@ func NewServer() *mcp.Server {
func NewServerFromEnv() (*mcp.Server, error) {
var source tools.ReceiveMessagesSource = isphere.EncryptedPacketLogSource{}
packetLogFile := strings.TrimSpace(os.Getenv(EnvPacketLogFileKey))
packetLogDir := strings.TrimSpace(os.Getenv(EnvPacketLogDirKey))
if packetLogFile != "" && packetLogDir != "" {
return nil, fmt.Errorf("configure packet log source: set only one of %s or %s", EnvPacketLogFileKey, EnvPacketLogDirKey)
}
if packetLogFile != "" {
loaded, err := isphere.LoadEncryptedPacketLogSourceFromFile(packetLogFile)
if err != nil {
return nil, fmt.Errorf("configure %s: %w", EnvPacketLogFileKey, err)
}
source = loaded
} else if packetLogDir != "" {
loaded, err := isphere.LoadEncryptedPacketLogSourceFromDirectory(packetLogDir)
if err != nil {
return nil, fmt.Errorf("configure %s: %w", EnvPacketLogDirKey, err)
}
source = loaded
}
return NewServerWithReceiveSource(source), nil
}

View File

@@ -127,6 +127,70 @@ func TestNewServerFromEnvUsesPacketLogFile(t *testing.T) {
}
}
func TestNewServerFromEnvUsesPacketLogDirectory(t *testing.T) {
plaintext := `--------------------------------------------------------------------------------------------------------------------------------------------
2026/7/7 15:30:07
<message id="msg-dir-1" from="sender@imopenfire1-lanzhou/imp_pc_4.1.2.6842" to="receiver@imopenfire1-lanzhou" type="chat">
<body>redacted from dir</body>
<received xmlns="urn:xmpp:receipts" id="receipt-dir-1" type="1" stamp="" />
<subject>DIR_SOURCE</subject>
<isphere xmlns="isphere.im" type="1001" sendtime="1783423807000" version="1" />
<readed />
</message>`
dirPath := writeEncryptedPacketLogDirectoryForServerTest(t, plaintext)
t.Setenv("ISPHERE_PACKET_LOG_DIR", dirPath)
server, err := NewServerFromEnv()
if err != nil {
t.Fatalf("NewServerFromEnv returned error: %v", err)
}
session, cleanup := connectServerTestSession(t, server)
defer cleanup()
callResult, err := session.CallTool(context.Background(), &mcp.CallToolParams{
Name: "isphere_receive_messages",
Arguments: map[string]any{"limit": 10},
})
if err != nil {
t.Fatalf("call isphere_receive_messages: %v", err)
}
if callResult.IsError {
t.Fatalf("call result is error: %+v", callResult)
}
var decoded struct {
Messages []struct {
ID string `json:"id"`
Text string `json:"text"`
Subject string `json:"subject"`
} `json:"messages"`
}
payload, err := json.Marshal(callResult.StructuredContent)
if err != nil {
t.Fatalf("marshal structured content: %v", err)
}
if err := json.Unmarshal(payload, &decoded); err != nil {
t.Fatalf("decode structured content %s: %v", payload, err)
}
if len(decoded.Messages) != 1 {
t.Fatalf("message count = %d, want 1", len(decoded.Messages))
}
msg := decoded.Messages[0]
if msg.ID != "msg-dir-1" || msg.Text != "redacted from dir" || msg.Subject != "DIR_SOURCE" {
t.Fatalf("unexpected message: %+v", msg)
}
}
func writeEncryptedPacketLogDirectoryForServerTest(t *testing.T, plaintext string) string {
t.Helper()
dir := t.TempDir()
line := encryptPacketLogLineForServerTest(t, plaintext)
if err := os.WriteFile(dir+"\\packet-reader-2.txt", []byte("\n"+line+"\n"), 0o600); err != nil {
t.Fatalf("write encrypted packet log directory fixture: %v", err)
}
return dir
}
func connectServerTestSession(t *testing.T, server *mcp.Server) (*mcp.ClientSession, func()) {
t.Helper()
ctx, cancel := context.WithCancel(context.Background())