Skip to content

Commit ef03a92

Browse files
authored
sdk/go: expose GetIndexInfo for locally loaded indexes (#444)
## What Adds `Client.GetIndexInfo(ctx, indexName)` to the Go SDK's public API. ## Why `bindings/libmoss.go` already implements `IndexManager.GetIndexInfo` against the native runtime, but nothing in `sdk/` exposed it. The existing `Client.GetIndex` only queries the cloud/manage-plane index metadata and there was no way to ask "what does the copy I currently have loaded in memory look like right now" (doc count, model, staleness relative to a `RefreshIndex` call, etc.) without dropping down to the internal bindings package directly. ## Changes - `sdk/local.go`: new `Client.GetIndexInfo`, mirroring the existing `RefreshIndex` method and validates credentials, gets the index runtime, delegates to `manager.GetIndexInfo`, converts via `fromCoreIndexInfo`. - `sdk/client_test.go`: two new tests - confirms `GetIndexInfo` reads from the local index runtime, not the manage runtime (this is the whole point of the method) - confirms credential validation happens before the index runtime is ever initialized, consistent with the pattern used by `RefreshIndex` - `sdks/go/README.md` / `sdks/go/sdk/README.md`: updated capability lists to mention `GetIndexInfo`. ## Testing `go test ./...` passes locally (stub build, no native `libmoss` required and this method has no cgo-specific logic of its own, it's a thin wrapper, consistent with the rest of `local.go`). <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/usemoss/moss/pull/444?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
1 parent 40f2d90 commit ef03a92

4 files changed

Lines changed: 99 additions & 2 deletions

File tree

sdks/go/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ The Go work now has the same two-layer direction as the other Moss SDKs:
88
Current status:
99

1010
- bindings-backed manage operations for mutations and metadata reads
11-
- local `LoadIndex` / `UnloadIndex` / local `Query` via `libmoss`
11+
- local `LoadIndex` / `UnloadIndex` / `GetIndexInfo` / local `Query` via `libmoss`
1212
- examples under `examples/go/` and unit tests
1313
- env-gated integration test scaffold
1414

sdks/go/sdk/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ The Go SDK now has two layers:
1212
- typed Go client and models
1313
- bindings-backed index creation and document mutation
1414
- bindings-backed index metadata and document reads
15-
- local index loading and query via native bindings
15+
- local index loading, metadata, and query via native bindings
1616
- cloud query fallback when an index is not loaded locally
1717
- optional caller-provided embeddings for custom indexes
1818
- env-gated live integration tests

sdks/go/sdk/client_test.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,82 @@ func TestLoadIndexRejectsUnsupportedCachePath(t *testing.T) {
529529
}
530530
}
531531

532+
func TestGetIndexInfoUsesLocalRuntime(t *testing.T) {
533+
manageCalled := false
534+
client := newTestClient(&fakeManageRuntime{
535+
getIndexFn: func(name string) (mosscore.IndexInfo, error) {
536+
manageCalled = true
537+
return mosscore.IndexInfo{}, nil
538+
},
539+
}, &fakeIndexRuntime{
540+
getIndexInfoFn: func(indexName string) (mosscore.IndexInfo, error) {
541+
if indexName != "support-docs" {
542+
t.Fatalf("unexpected index name: %q", indexName)
543+
}
544+
version := "v1"
545+
createdAt := "2026-01-02T03:04:05Z"
546+
updatedAt := "2026-01-03T03:04:05Z"
547+
modelVersion := "0.8.7"
548+
return mosscore.IndexInfo{
549+
ID: "idx-local",
550+
Name: "support-docs",
551+
Version: &version,
552+
Status: "Ready",
553+
DocCount: 42,
554+
CreatedAt: &createdAt,
555+
UpdatedAt: &updatedAt,
556+
Model: mosscore.ModelRef{ID: string(ModelMossMiniLM), Version: &modelVersion},
557+
}, nil
558+
},
559+
})
560+
561+
info, err := client.GetIndexInfo(context.Background(), "support-docs")
562+
if err != nil {
563+
t.Fatalf("GetIndexInfo returned error: %v", err)
564+
}
565+
if manageCalled {
566+
t.Fatal("expected GetIndexInfo to use local index runtime, not manage runtime")
567+
}
568+
if info.ID != "idx-local" || info.Name != "support-docs" || info.DocCount != 42 {
569+
t.Fatalf("unexpected index info: %#v", info)
570+
}
571+
if info.Version == nil || *info.Version != "v1" {
572+
t.Fatalf("unexpected version: %#v", info.Version)
573+
}
574+
if info.Model.ID != string(ModelMossMiniLM) || info.Model.Version == nil || *info.Model.Version != "0.8.7" {
575+
t.Fatalf("unexpected model: %#v", info.Model)
576+
}
577+
}
578+
579+
func TestGetIndexInfoValidatesCredentialsBeforeInitializingRuntime(t *testing.T) {
580+
for _, tc := range []struct {
581+
name string
582+
projectID string
583+
projectKey string
584+
wantErr error
585+
}{
586+
{name: "missing project ID", projectID: "", projectKey: "project-key", wantErr: ErrMissingProjectID},
587+
{name: "missing project key", projectID: "project-id", projectKey: "", wantErr: ErrMissingProjectKey},
588+
} {
589+
t.Run(tc.name, func(t *testing.T) {
590+
client := NewClient(tc.projectID, tc.projectKey)
591+
factoryCalled := false
592+
client.indexFactory = func(projectID, projectKey string) (indexRuntime, error) {
593+
factoryCalled = true
594+
return &fakeIndexRuntime{}, nil
595+
}
596+
597+
_, err := client.GetIndexInfo(context.Background(), "support-docs")
598+
if !errors.Is(err, tc.wantErr) {
599+
t.Fatalf("expected %v, got %v", tc.wantErr, err)
600+
}
601+
if factoryCalled {
602+
t.Fatal("expected index runtime initialization to be skipped")
603+
}
604+
})
605+
}
606+
}
607+
532608
func TestRefreshIndexValidatesCredentialsBeforeInitializingRuntime(t *testing.T) {
533609
for _, tc := range []struct {
534610
name string

sdks/go/sdk/local.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,24 @@ func (c *Client) RefreshIndex(ctx context.Context, indexName string) (RefreshRes
8888
WasUpdated: result.WasUpdated,
8989
}, nil
9090
}
91+
92+
// GetIndexInfo returns metadata for a locally loaded index.
93+
func (c *Client) GetIndexInfo(ctx context.Context, indexName string) (IndexInfo, error) {
94+
if err := ctx.Err(); err != nil {
95+
return IndexInfo{}, err
96+
}
97+
if err := c.validateManageRequest(indexName); err != nil {
98+
return IndexInfo{}, err
99+
}
100+
101+
manager, err := c.ensureIndexManager()
102+
if err != nil {
103+
return IndexInfo{}, err
104+
}
105+
106+
info, err := manager.GetIndexInfo(indexName)
107+
if err != nil {
108+
return IndexInfo{}, err
109+
}
110+
return fromCoreIndexInfo(info), nil
111+
}

0 commit comments

Comments
 (0)