diff --git a/cmd/README.en.md b/cmd/README.en.md index 36f59d5..368d3c4 100644 --- a/cmd/README.en.md +++ b/cmd/README.en.md @@ -14,6 +14,8 @@ Entry Layer: process entry points. `umodel-server` and `umodel-mcp` both support `--graphstore`: +When `--graphstore` is omitted, Go entrypoints use `local.ladybug`. Builds without `-tags ladybug` report clear startup guidance: build with the Ladybug tag, or pass `--graphstore file.memory` for local development. + | Provider | Description | |---|---| | `memory` | In-memory provider for fast local verification; data is lost on process exit. | diff --git a/cmd/README.md b/cmd/README.md index b24c26e..0bd5713 100644 --- a/cmd/README.md +++ b/cmd/README.md @@ -12,6 +12,8 @@ Entry Layer — 二进制入口点。 `umodel-server` 和 `umodel-mcp` 都支持 `--graphstore`: +未显式传入 `--graphstore` 时,Go 入口默认使用 `local.ladybug`。如果构建时没有 `-tags ladybug`,启动错误会提示两条路径:使用 Ladybug tag 构建,或在本地开发时传入 `--graphstore file.memory`。 + | Provider | 说明 | |---|---| | `memory` | 纯内存,适合本地快速验证,进程退出后数据丢失;通过纯 Go 引擎支持 Ladybug 兼容只读 Cypher。 | diff --git a/cmd/umodel-mcp/main_no_ladybug_test.go b/cmd/umodel-mcp/main_no_ladybug_test.go new file mode 100644 index 0000000..8c10b92 --- /dev/null +++ b/cmd/umodel-mcp/main_no_ladybug_test.go @@ -0,0 +1,24 @@ +//go:build !ladybug + +package main + +import ( + "bytes" + "strings" + "testing" +) + +func TestRunDefaultLadybugUnavailableGuidesLocalDevelopment(t *testing.T) { + var out bytes.Buffer + var errOut bytes.Buffer + + err := run([]string{"--manifest", "--data", t.TempDir()}, strings.NewReader(""), &out, &errOut) + if err == nil { + t.Fatal("expected default local.ladybug stub to be unavailable in no-ladybug build") + } + for _, want := range []string{"local.ladybug", "-tags ladybug", "--graphstore file.memory"} { + if !strings.Contains(err.Error(), want) { + t.Fatalf("expected %q in error %q", want, err.Error()) + } + } +} diff --git a/docs/en/graphstore-providers.md b/docs/en/graphstore-providers.md index c8360f1..893bca5 100644 --- a/docs/en/graphstore-providers.md +++ b/docs/en/graphstore-providers.md @@ -4,6 +4,8 @@ UModel stores UModel elements, CMS 2.0 entities, and topology relations behind the `GraphStore` interface. Go entry binaries default to `local.ladybug` when `--graphstore` is omitted; select another provider with `--graphstore` on `umodel-server` or `umodel-mcp`. +If a build omits the `ladybug` tag, the default `local.ladybug` provider reports an unavailable health status. Build with `-tags ladybug` to enable the real `local.ladybug` provider, or pass `--graphstore file.memory` for local development without Ladybug. + ```bash go run ./cmd/umodel-server --addr :8080 --data data --graphstore file.memory ``` diff --git a/docs/zh/graphstore-providers.md b/docs/zh/graphstore-providers.md index b8457d4..b54cd43 100644 --- a/docs/zh/graphstore-providers.md +++ b/docs/zh/graphstore-providers.md @@ -5,6 +5,8 @@ English: [GraphStore Providers](../en/graphstore-providers.md) UModel 通过 `GraphStore` 接口保存和查询 UModel elements、CMS 2.0 实体以及拓扑关系。运行时通过 `--graphstore` 选择 provider。 +未显式传入 `--graphstore` 时,Go 入口默认使用 `local.ladybug`。如果构建时没有 `-tags ladybug`,该 provider 会报告不可用状态。使用 `-tags ladybug` 构建即可启用真实的 `local.ladybug` provider;本地开发且不使用 Ladybug 时请显式传入 `--graphstore file.memory`。 + ## Providers | Provider | 持久化 | 典型用途 | diff --git a/internal/graphstore/provider/ladybug/provider_stub.go b/internal/graphstore/provider/ladybug/provider_stub.go index fcb84f2..9c04302 100644 --- a/internal/graphstore/provider/ladybug/provider_stub.go +++ b/internal/graphstore/provider/ladybug/provider_stub.go @@ -13,6 +13,8 @@ import ( type Provider struct{} +const noLadybugBuildGuidance = "build with -tags ladybug to enable local.ladybug, or run with --graphstore file.memory for local development" + func NewProvider(config graphstore.ProviderConfig) (*Provider, error) { return &Provider{}, nil } @@ -64,11 +66,11 @@ func (p *Provider) Capabilities(ctx context.Context) (model.GraphStoreCapabiliti } func (p *Provider) Health(ctx context.Context) (model.GraphStoreHealth, error) { - return model.GraphStoreHealth{Provider: graphstore.ProviderTypeLadybug, Status: "unavailable", Message: "build with -tags ladybug to enable local.ladybug"}, nil + return model.GraphStoreHealth{Provider: graphstore.ProviderTypeLadybug, Status: "unavailable", Message: noLadybugBuildGuidance}, nil } func unavailable() error { - return apperrors.New(apperrors.CodeProviderUnavailable, "local.ladybug provider is disabled in this build") + return apperrors.New(apperrors.CodeProviderUnavailable, "local.ladybug provider is disabled in this build; "+noLadybugBuildGuidance) } func ladybugCapabilities() model.GraphStoreCapabilities { diff --git a/internal/graphstore/provider/ladybug/provider_stub_test.go b/internal/graphstore/provider/ladybug/provider_stub_test.go index caf716d..ac0731c 100644 --- a/internal/graphstore/provider/ladybug/provider_stub_test.go +++ b/internal/graphstore/provider/ladybug/provider_stub_test.go @@ -4,6 +4,7 @@ package ladybug import ( "context" + "strings" "testing" "github.com/alibaba/UnifiedModel/internal/graphstore" @@ -20,9 +21,13 @@ func TestStubProviderReportsUnavailable(t *testing.T) { ctx := context.Background() if health, err := provider.Health(ctx); err != nil || health.Status != "unavailable" || health.Provider != graphstore.ProviderTypeLadybug { t.Fatalf("health: %+v err=%v", health, err) + } else { + requireLadybugGuidance(t, health.Message) } if err := provider.OpenWorkspace(ctx, model.WorkspaceMetadata{ID: "demo"}); !apperrors.IsCode(err, apperrors.CodeProviderUnavailable) { t.Fatalf("expected provider unavailable, got %v", err) + } else { + requireLadybugGuidance(t, err.Error()) } if capabilities, err := provider.Capabilities(ctx); err != nil || !capabilities.ControlledCypher || capabilities.MaxLimit == 0 { t.Fatalf("stub should expose intended local.ladybug capabilities for planning, got %+v err=%v", capabilities, err) @@ -36,5 +41,16 @@ func TestStubProviderIsRegisteredButUnavailable(t *testing.T) { } if err := provider.EnsureSchema(context.Background(), "demo"); !apperrors.IsCode(err, apperrors.CodeProviderUnavailable) { t.Fatalf("expected registered stub provider to be unavailable, got %v", err) + } else { + requireLadybugGuidance(t, err.Error()) + } +} + +func requireLadybugGuidance(t *testing.T, message string) { + t.Helper() + for _, want := range []string{"-tags ladybug", "--graphstore file.memory"} { + if !strings.Contains(message, want) { + t.Fatalf("expected %q guidance in %q", want, message) + } } }