Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
/services/mo*

/bin/moling
12 changes: 7 additions & 5 deletions cli/cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ import (
"context"
"encoding/json"
"fmt"
"github.com/gojue/moling/services"
"github.com/rs/zerolog"
"github.com/spf13/cobra"
"os"
"path/filepath"
"time"

"github.com/gojue/moling/pkg/comm"
"github.com/gojue/moling/pkg/services"
"github.com/rs/zerolog"
"github.com/spf13/cobra"
)

var configCmd = &cobra.Command{
Expand All @@ -50,8 +52,8 @@ func ConfigCommandFunc(command *cobra.Command, args []string) error {
logger = zerolog.New(multi).With().Timestamp().Logger()
mlConfig.SetLogger(logger)
logger.Info().Msg("Start to show config")
ctx := context.WithValue(context.Background(), services.MoLingConfigKey, mlConfig)
ctx = context.WithValue(ctx, services.MoLingLoggerKey, logger)
ctx := context.WithValue(context.Background(), comm.MoLingConfigKey, mlConfig)
ctx = context.WithValue(ctx, comm.MoLingLoggerKey, logger)

// 当前配置文件检测
hasConfig := false
Expand Down
5 changes: 3 additions & 2 deletions cli/cmd/perrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
package cmd

import (
"github.com/gojue/moling/utils"
"github.com/spf13/cobra"
"path/filepath"

"github.com/gojue/moling/pkg/utils"
"github.com/spf13/cobra"
)

// mlsCommandPreFunc is a pre-run function for the MoLing command.
Expand Down
25 changes: 15 additions & 10 deletions cli/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ import (
"context"
"encoding/json"
"fmt"
"github.com/gojue/moling/cli/cobrautl"
"github.com/gojue/moling/services"
"github.com/gojue/moling/utils"
"github.com/rs/zerolog"
"github.com/spf13/cobra"
"os"
"os/signal"
"os/user"
Expand All @@ -33,6 +28,16 @@ import (
"sync"
"syscall"
"time"

"github.com/gojue/moling/cli/cobrautl"
"github.com/gojue/moling/pkg/comm"
"github.com/gojue/moling/pkg/config"
"github.com/gojue/moling/pkg/server"
"github.com/gojue/moling/pkg/services"
"github.com/gojue/moling/pkg/services/abstract"
"github.com/gojue/moling/pkg/utils"
"github.com/rs/zerolog"
"github.com/spf13/cobra"
)

const (
Expand Down Expand Up @@ -78,7 +83,7 @@ const (

var (
GitVersion = "unknown_arm64_v0.0.0_2025-03-22 20:08"
mlConfig = &services.MoLingConfig{
mlConfig = &config.MoLingConfig{
Version: GitVersion,
ConfigFile: filepath.Join("config", MLConfigName),
BasePath: filepath.Join(os.TempDir(), MLRootPath), // will set in mlsCommandPreFunc
Expand Down Expand Up @@ -188,15 +193,15 @@ func mlsCommandFunc(command *cobra.Command, args []string) error {
}
}
loger.Info().Str("config_file", configFilePath).Msg("load config file")
ctx := context.WithValue(context.Background(), services.MoLingConfigKey, mlConfig)
ctx = context.WithValue(ctx, services.MoLingLoggerKey, loger)
ctx := context.WithValue(context.Background(), comm.MoLingConfigKey, mlConfig)
ctx = context.WithValue(ctx, comm.MoLingLoggerKey, loger)
ctxNew, cancelFunc := context.WithCancel(ctx)

var modules []string
if mlConfig.Module != "all" {
modules = strings.Split(mlConfig.Module, ",")
}
var srvs []services.Service
var srvs []abstract.Service
var closers = make(map[string]func() error)
for srvName, nsv := range services.ServiceList() {
if len(modules) > 0 {
Expand Down Expand Up @@ -228,7 +233,7 @@ func mlsCommandFunc(command *cobra.Command, args []string) error {
closers[string(srv.Name())] = srv.Close
}
// MCPServer
srv, err := services.NewMoLingServer(ctxNew, srvs, *mlConfig)
srv, err := server.NewMoLingServer(ctxNew, srvs, *mlConfig)
if err != nil {
loger.Error().Err(err).Msg("failed to create server")
cancelFunc()
Expand Down
55 changes: 55 additions & 0 deletions pkg/comm/comm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2025 CFC4N <cfc4n.cs@gmail.com>. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Repository: https://github.com/gojue/moling

package comm

import (
"context"
"os"
"path/filepath"

"github.com/gojue/moling/pkg/config"
"github.com/rs/zerolog"
)

type MoLingServerType string

type contextKey string

// MoLingConfigKey is a context key for storing the version of MoLing
const (
MoLingConfigKey contextKey = "moling_config"
MoLingLoggerKey contextKey = "moling_logger"
)

// InitTestEnv initializes the test environment by creating a temporary log file and setting up the logger.
func InitTestEnv() (zerolog.Logger, context.Context, error) {
logFile := filepath.Join(os.TempDir(), "moling.log")
zerolog.SetGlobalLevel(zerolog.DebugLevel)
var logger zerolog.Logger
f, err := os.OpenFile(logFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o600)
if err != nil {
return zerolog.Logger{}, nil, err
}
logger = zerolog.New(f).With().Timestamp().Logger()
mlConfig := &config.MoLingConfig{
ConfigFile: filepath.Join("config", "test_config.json"),
BasePath: os.TempDir(),
}
ctx := context.WithValue(context.Background(), MoLingConfigKey, mlConfig)
ctx = context.WithValue(ctx, MoLingLoggerKey, logger)
return logger, ctx, nil
}
21 changes: 5 additions & 16 deletions services/register.go → pkg/comm/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,10 @@
//
// Repository: https://github.com/gojue/moling

package services
package comm

import (
"context"
)

var serviceLists = make(map[MoLingServerType]func(ctx context.Context) (Service, error))
import "errors"

// RegisterServ register service
func RegisterServ(n MoLingServerType, f func(ctx context.Context) (Service, error)) {
//serviceLists = append(, f)
serviceLists[n] = f
}

// ServiceList get service lists
func ServiceList() map[MoLingServerType]func(ctx context.Context) (Service, error) {
return serviceLists
}
var (
ErrConfigNotLoaded = errors.New("config not loaded, please call LoadConfig() first")
)
36 changes: 1 addition & 35 deletions services/config.go → pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,10 @@
//
// Repository: https://github.com/gojue/moling

package services
package config

import (
"fmt"
"github.com/rs/zerolog"
"reflect"
)

// Config is an interface that defines a method for checking configuration validity.
Expand Down Expand Up @@ -61,35 +59,3 @@ func (cfg *MoLingConfig) Logger() zerolog.Logger {
func (cfg *MoLingConfig) SetLogger(logger zerolog.Logger) {
cfg.logger = logger
}

// mergeJSONToStruct 将JSON中的字段合并到结构体中

func mergeJSONToStruct(target interface{}, jsonMap map[string]interface{}) error {
// 获取目标结构体的反射值
val := reflect.ValueOf(target).Elem()
typ := val.Type()

// 遍历JSON map中的每个字段
for jsonKey, jsonValue := range jsonMap {
// 遍历结构体的每个字段
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
// 检查JSON字段名是否与结构体的JSON tag匹配
if field.Tag.Get("json") == jsonKey {
// 获取结构体字段的反射值
fieldVal := val.Field(i)
// 检查字段是否可设置
if fieldVal.CanSet() {
// 将JSON值转换为结构体字段的类型
jsonVal := reflect.ValueOf(jsonValue)
if jsonVal.Type().ConvertibleTo(fieldVal.Type()) {
fieldVal.Set(jsonVal.Convert(fieldVal.Type()))
} else {
return fmt.Errorf("type mismatch for field %s, value:%v", jsonKey, jsonValue)
}
}
}
}
}
return nil
}
40 changes: 19 additions & 21 deletions services/config_test.go → pkg/config/config_test.go
Original file line number Diff line number Diff line change
@@ -1,29 +1,27 @@
/*
*
* Copyright 2025 CFC4N <cfc4n.cs@gmail.com>. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Repository: https://github.com/gojue/moling
*
*/
// Copyright 2025 CFC4N <cfc4n.cs@gmail.com>. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Repository: https://github.com/gojue/moling

package services
package config

import (
"encoding/json"
"os"
"testing"

"github.com/gojue/moling/pkg/utils"
)

// TestConfigLoad tests the loading of the configuration from a JSON file.
Expand Down Expand Up @@ -51,7 +49,7 @@ func TestConfigLoad(t *testing.T) {
if !ok {
t.Fatalf("failed to parse MoLingConfig from JSON")
}
if err := mergeJSONToStruct(cfg, mlConfig); err != nil {
if err := utils.MergeJSONToStruct(cfg, mlConfig); err != nil {
t.Fatalf("failed to merge JSON to struct: %v", err)
}
t.Logf("Config loaded, MoLing Config.BasePath: %s", cfg.BasePath)
Expand Down
File renamed without changes.
57 changes: 27 additions & 30 deletions services/moling.go → pkg/server/server.go
Original file line number Diff line number Diff line change
@@ -1,48 +1,45 @@
/*
*
* Copyright 2025 CFC4N <cfc4n.cs@gmail.com>. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Repository: https://github.com/gojue/moling
*
*/

package services
// Copyright 2025 CFC4N <cfc4n.cs@gmail.com>. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Repository: https://github.com/gojue/moling
package server

import (
"context"
"fmt"
"github.com/mark3labs/mcp-go/server"
"github.com/rs/zerolog"
"log"
"os"
"strings"
"time"
)

type MoLingServerType string // MoLingServerType is the type of the server
"github.com/gojue/moling/pkg/comm"
"github.com/gojue/moling/pkg/config"
"github.com/gojue/moling/pkg/services/abstract"
"github.com/mark3labs/mcp-go/server"
"github.com/rs/zerolog"
)

type MoLingServer struct {
ctx context.Context
server *server.MCPServer
services []Service
services []abstract.Service
logger zerolog.Logger
mlConfig MoLingConfig
mlConfig config.MoLingConfig
listenAddr string // SSE mode listen address, if empty, use STDIO mode.
}

func NewMoLingServer(ctx context.Context, srvs []Service, mlConfig MoLingConfig) (*MoLingServer, error) {
func NewMoLingServer(ctx context.Context, srvs []abstract.Service, mlConfig config.MoLingConfig) (*MoLingServer, error) {
mcpServer := server.NewMCPServer(
mlConfig.ServerName,
mlConfig.Version,
Expand All @@ -56,7 +53,7 @@ func NewMoLingServer(ctx context.Context, srvs []Service, mlConfig MoLingConfig)
server: mcpServer,
services: srvs,
listenAddr: mlConfig.ListenAddr,
logger: ctx.Value(MoLingLoggerKey).(zerolog.Logger),
logger: ctx.Value(comm.MoLingLoggerKey).(zerolog.Logger),
mlConfig: mlConfig,
}
err := ms.init()
Expand All @@ -75,7 +72,7 @@ func (m *MoLingServer) init() error {
return err
}

func (m *MoLingServer) loadService(srv Service) error {
func (m *MoLingServer) loadService(srv abstract.Service) error {

// Add resources
for r, rhf := range srv.Resources() {
Expand Down
Loading
Loading