diff --git a/go/contract_test.go b/go/contract_test.go index 4bdea64..e153a5e 100644 --- a/go/contract_test.go +++ b/go/contract_test.go @@ -1,63 +1,46 @@ package cstx import ( - "encoding/json" - "reflect" - "sort" - "strings" + "go/ast" + "go/parser" + "go/token" + "path/filepath" "testing" ) -// The transport contract is owned by cstx.core.elements (Node/Edge pydantic -// models) and mirrored by codegen/generate_transport_ts.py. These tests pin -// the Go structs to the same field sets so the three languages cannot drift. -func jsonFieldNames(t *testing.T, value any) []string { - t.Helper() - typ := reflect.TypeOf(value) - var names []string - for i := 0; i < typ.NumField(); i++ { - tag := typ.Field(i).Tag.Get("json") - if tag == "" || tag == "-" { - continue - } - names = append(names, strings.Split(tag, ",")[0]) - } - sort.Strings(names) - return names -} - -func TestNodeMatchesTransportContract(t *testing.T) { - got := jsonFieldNames(t, Node{}) - want := []string{"extras", "id", "model", "sources", "type", "value"} - if !reflect.DeepEqual(got, want) { - t.Fatalf("node fields drifted from transport contract: got %v want %v", got, want) +// This gate prevents the SDK from quietly growing another public graph or +// repository model beside the generated protobuf package. +func TestNoDuplicatedPublicModelTypes(t *testing.T) { + banned := map[string]bool{ + "Node": true, "Edge": true, "Relationship": true, "GraphStats": true, + "Delta": true, "ChangeSet": true, "Commit": true, "GraphDiff": true, + "History": true, "HistoryEntry": true, "RepositorySync": true, + "MissingPlan": true, "NodeFilter": true, "EdgeFilter": true, + "RelationshipFilter": true, "QueryOptions": true, "Config": true, } -} - -func TestEdgeMatchesTransportContract(t *testing.T) { - got := jsonFieldNames(t, Edge{}) - want := []string{"attrs", "id", "relation_type", "source_id", "sources", "target_id"} - if !reflect.DeepEqual(got, want) { - t.Fatalf("edge fields drifted from transport contract: got %v want %v", got, want) - } -} - -func TestQueryOptionsMatchesRustTransportContract(t *testing.T) { - got := jsonFieldNames(t, QueryOptions{}) - want := []string{"collection", "exclude_mask", "include_mask"} - if !reflect.DeepEqual(got, want) { - t.Fatalf("query option fields drifted from Rust contract: got %v want %v", got, want) - } - - payload, err := json.Marshal(QueryOptions{ExcludeMask: 5, IncludeMask: 8}) + files, err := filepath.Glob("*.go") if err != nil { - t.Fatalf("marshal query options: %v", err) - } - var wire map[string]any - if err := json.Unmarshal(payload, &wire); err != nil { - t.Fatalf("unmarshal query options: %v", err) + t.Fatal(err) } - if wire["exclude_mask"] != float64(5) || wire["include_mask"] != float64(8) { - t.Fatalf("query option values drifted from Rust contract: %s", payload) + for _, file := range files { + if filepath.Ext(file) != ".go" || filepath.Base(file) == "contract_test.go" { + continue + } + parsed, err := parser.ParseFile(token.NewFileSet(), file, nil, 0) + if err != nil { + t.Fatalf("parse %s: %v", file, err) + } + for _, declaration := range parsed.Decls { + general, ok := declaration.(*ast.GenDecl) + if !ok || general.Tok != token.TYPE { + continue + } + for _, spec := range general.Specs { + name := spec.(*ast.TypeSpec).Name.Name + if banned[name] { + t.Fatalf("%s declares duplicated public model %s; use cstxproto.%s", file, name, name) + } + } + } } } diff --git a/go/cstx.go b/go/cstx.go index bee651a..e033ef8 100644 --- a/go/cstx.go +++ b/go/cstx.go @@ -4,25 +4,27 @@ import ( "context" "errors" "sync" + + "github.com/chainreactors/libcstx/go/proto/cstxproto" ) -// Config configures an in-memory CSTX runtime. -type Config struct { - // ProjectID namespaces the runtime; defaults to "default". - ProjectID string - // CursorPageSize bounds incremental cursor materialization; defaults to - // DefaultCursorPageSize. - CursorPageSize int +type runtimeConfig struct { + projectID string + cursorPageSize int } -func (c Config) normalize() Config { - if c.ProjectID == "" { - c.ProjectID = "default" +func normalizeRuntimeConfig(value *cstxproto.RuntimeConfig) runtimeConfig { + config := runtimeConfig{projectID: "default", cursorPageSize: DefaultCursorPageSize} + if value == nil { + return config + } + if value.ProjectId != "" { + config.projectID = value.ProjectId } - if c.CursorPageSize <= 0 { - c.CursorPageSize = DefaultCursorPageSize + if value.CursorPageSize > 0 { + config.cursorPageSize = int(value.CursorPageSize) } - return c + return config } // CSTX is the single owner of shared schema, graph, and repository @@ -31,38 +33,34 @@ type CSTX struct { eng engine projectID string - // Schemas, Graph, and Repo are lightweight namespaces sharing + // Extensions, Graph, and Repo are lightweight namespaces sharing // this runtime's state. - Schemas *Schemas - Graph *Graph - Repo *Repository - Raw *Raw + Extensions *Extensions + Graph *Graph + Repo *Repository mu sync.Mutex closed bool } // Open creates an in-memory native runtime. -func Open(ctx context.Context, config Config) (*CSTX, error) { +func Open(ctx context.Context, value *cstxproto.RuntimeConfig) (*CSTX, error) { if err := contextError(ctx); err != nil { return nil, err } - config = config.normalize() + config := normalizeRuntimeConfig(value) eng, err := newEngine(config) if err != nil { return nil, err } - return wrapRuntime(eng, config.ProjectID), nil + return wrapRuntime(eng, config.projectID), nil } func wrapRuntime(eng engine, projectID string) *CSTX { rt := &CSTX{eng: eng, projectID: projectID} - rt.Schemas = &Schemas{eng: eng} + rt.Extensions = &Extensions{eng: eng} rt.Graph = &Graph{eng: eng} rt.Repo = &Repository{eng: eng} - if raw, ok := eng.(rawEngine); ok { - rt.Raw = &Raw{eng: raw} - } return rt } @@ -96,9 +94,9 @@ func (c *CSTX) Closed() bool { } // LastChange returns the IDs changed by the most recent committed mutation. -func (c *CSTX) LastChange(ctx context.Context) (ChangeSet, error) { +func (c *CSTX) LastChange(ctx context.Context) (*cstxproto.GraphChangeSet, error) { if err := contextError(ctx); err != nil { - return ChangeSet{}, err + return nil, err } return c.eng.lastChange(ctx) } diff --git a/go/cstx_ffi.h b/go/cstx_ffi.h index 6c1e802..ae52695 100644 --- a/go/cstx_ffi.h +++ b/go/cstx_ffi.h @@ -60,120 +60,136 @@ typedef struct CstxSlice { */ void cstx_buffer_free(struct CstxBuffer *buffer); -CstxStatusCode cstx_open(struct CstxSlice config_json, +/** + * Open a runtime from the canonical protobuf configuration message. + */ +CstxStatusCode cstx_open(struct CstxSlice config, struct CstxHandle **output, struct CstxBuffer *error); void cstx_free(struct CstxHandle *handle); -CstxStatusCode cstx_last_change_json(struct CstxHandle *handle, - struct CstxBuffer *output, +/** + * Return the last graph mutation as a protobuf message. + */ +CstxStatusCode cstx_last_change(struct CstxHandle *handle, + struct CstxBuffer *output, + struct CstxBuffer *error); + +/** + * Register an extension contract encoded as protobuf. + */ +CstxStatusCode cstx_extension_register(struct CstxHandle *handle, + struct CstxSlice contract, + struct CstxBuffer *error); + +/** + * Explicitly enable one linked native Rust extension. + */ +CstxStatusCode cstx_extension_enable(struct CstxHandle *handle, + struct CstxSlice name, struct CstxBuffer *error); -CstxStatusCode cstx_schema_register(struct CstxHandle *handle, - struct CstxSlice node_type, - struct CstxSlice schema_json, - struct CstxSlice value_field, - struct CstxBuffer *error); +/** + * List extension metadata as protobuf. + */ +CstxStatusCode cstx_extension_list(struct CstxHandle *handle, + struct CstxBuffer *output, + struct CstxBuffer *error); -CstxStatusCode cstx_schema_import_schema(struct CstxHandle *handle, - struct CstxSlice contract_json, - struct CstxBuffer *error); +/** + * Return extension metadata as protobuf. + */ +CstxStatusCode cstx_extension_info(struct CstxHandle *handle, + struct CstxSlice name, + struct CstxBuffer *output, + struct CstxBuffer *error); -CstxStatusCode cstx_schema_export_schema_json(struct CstxHandle *handle, +/** + * Export the extension contract as protobuf for low-level synchronization. + */ +CstxStatusCode cstx_extension_export_contract(struct CstxHandle *handle, struct CstxBuffer *output, struct CstxBuffer *error); -CstxStatusCode cstx_schema_contains(struct CstxHandle *handle, - struct CstxSlice node_type, - uint8_t *output, - struct CstxBuffer *error); +/** + * Test whether an extension has registered a schema for a node type. + */ +CstxStatusCode cstx_extension_contains(struct CstxHandle *handle, + struct CstxSlice node_type, + uint8_t *output, + struct CstxBuffer *error); -CstxStatusCode cstx_schema_list_json(struct CstxHandle *handle, +CstxStatusCode cstx_extension_schema(struct CstxHandle *handle, + struct CstxSlice node_type, struct CstxBuffer *output, struct CstxBuffer *error); -CstxStatusCode cstx_schema_get_json(struct CstxHandle *handle, - struct CstxSlice node_type, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_schema_load_plugin(struct CstxHandle *handle, - struct CstxSlice name, - struct CstxBuffer *error); - -CstxStatusCode cstx_schema_load_all_plugins(struct CstxHandle *handle, struct CstxBuffer *error); - -CstxStatusCode cstx_schema_available_plugins_json(struct CstxHandle *handle, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_schema_plugin_artifacts_json(struct CstxHandle *handle, - struct CstxSlice name, - struct CstxBuffer *output, - struct CstxBuffer *error); +CstxStatusCode cstx_extension_schemas(struct CstxHandle *handle, + struct CstxBuffer *output, + struct CstxBuffer *error); -CstxStatusCode cstx_schema_register_join_rule(struct CstxHandle *handle, - struct CstxSlice rule_json, +/** + * Test whether an enabled native extension provides an artifact parser. + */ +CstxStatusCode cstx_extension_parses_artifact(struct CstxHandle *handle, + struct CstxSlice artifact, + uint8_t *output, struct CstxBuffer *error); -CstxStatusCode cstx_schema_has_native_artifact(struct CstxHandle *handle, - struct CstxSlice artifact, - uint8_t *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_schema_anchor_concepts_json(struct CstxHandle *handle, - struct CstxBuffer *output, - struct CstxBuffer *error); +CstxStatusCode cstx_extension_anchor_concepts(struct CstxHandle *handle, + struct CstxBuffer *output, + struct CstxBuffer *error); +/** + * Add or merge a protobuf graph aggregate at the Rust-owned semantic boundary. + */ CstxStatusCode cstx_graph_add_nodes(struct CstxHandle *handle, struct CstxSlice data, uint64_t *affected, struct CstxBuffer *error); /** - * Write each node as its current state, replacing the stored record. - * - * The merge path (`cstx_graph_add_nodes`) owns bulk ingest and keeps its JSON - * fast path. A replace batch is a caller restating records it already holds — - * a task's oracles, a document's current revision — so it goes through the - * shared `Value` path rather than earning a second parser. + * Replace the current graph content from a protobuf aggregate. */ CstxStatusCode cstx_graph_replace_nodes(struct CstxHandle *handle, struct CstxSlice data, uint64_t *affected, struct CstxBuffer *error); -CstxStatusCode cstx_graph_add_edges(struct CstxHandle *handle, - struct CstxSlice data, - uint64_t *affected, - struct CstxBuffer *error); +/** + * Add or merge relationships from a protobuf graph aggregate. + */ +CstxStatusCode cstx_graph_add_relationships(struct CstxHandle *handle, + struct CstxSlice data, + uint64_t *affected, + struct CstxBuffer *error); CstxStatusCode cstx_graph_delete_nodes(struct CstxHandle *handle, - struct CstxSlice node_ids_json, - uint64_t *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_graph_delete_edges(struct CstxHandle *handle, - struct CstxSlice edge_ids_json, + struct CstxSlice node_ids, uint64_t *output, struct CstxBuffer *error); -CstxStatusCode cstx_graph_ingest(struct CstxHandle *handle, - struct CstxSlice source, - struct CstxSlice data, - uint64_t *affected, - struct CstxBuffer *error); +CstxStatusCode cstx_graph_delete_relationships(struct CstxHandle *handle, + struct CstxSlice relationship_ids, + uint64_t *output, + struct CstxBuffer *error); +/** + * Return one node as a protobuf envelope. + */ CstxStatusCode cstx_graph_node(struct CstxHandle *handle, struct CstxSlice node_id, struct CstxBuffer *output, struct CstxBuffer *error); -CstxStatusCode cstx_graph_edge(struct CstxHandle *handle, - struct CstxSlice edge_id, - struct CstxBuffer *output, - struct CstxBuffer *error); +/** + * Return one relationship as a protobuf envelope. + */ +CstxStatusCode cstx_graph_relationship(struct CstxHandle *handle, + struct CstxSlice relationship_id, + struct CstxBuffer *output, + struct CstxBuffer *error); CstxStatusCode cstx_graph_contains(struct CstxHandle *handle, struct CstxSlice node_id, @@ -184,57 +200,59 @@ CstxStatusCode cstx_graph_node_count(struct CstxHandle *handle, uint64_t *output, struct CstxBuffer *error); -CstxStatusCode cstx_graph_edge_count(struct CstxHandle *handle, - uint64_t *output, - struct CstxBuffer *error); +CstxStatusCode cstx_graph_relationship_count(struct CstxHandle *handle, + uint64_t *output, + struct CstxBuffer *error); +/** + * Create a node cursor from a protobuf `NodeQuery` (filter + window). + */ CstxStatusCode cstx_graph_nodes(struct CstxHandle *handle, - struct CstxSlice filter_json, - struct CstxSlice options_json, + struct CstxSlice request, struct CstxGraphCursor **output, struct CstxBuffer *error); -CstxStatusCode cstx_graph_edges(struct CstxHandle *handle, - struct CstxSlice filter_json, - struct CstxSlice options_json, - struct CstxGraphCursor **output, - struct CstxBuffer *error); +/** + * Create a relationship cursor from a protobuf `RelationshipQuery` (filter + window). + */ +CstxStatusCode cstx_graph_relationships(struct CstxHandle *handle, + struct CstxSlice request, + struct CstxGraphCursor **output, + struct CstxBuffer *error); +/** + * Create a neighbor cursor from a semantic query. + */ CstxStatusCode cstx_graph_neighbors(struct CstxHandle *handle, - struct CstxSlice node_id, - struct CstxSlice direction, - struct CstxSlice options_json, + struct CstxSlice request, struct CstxGraphCursor **output, struct CstxBuffer *error); +/** + * Create a query cursor from a semantic query. + */ CstxStatusCode cstx_graph_query(struct CstxHandle *handle, - struct CstxSlice expression, - struct CstxSlice options_json, + struct CstxSlice request, struct CstxGraphCursor **output, struct CstxBuffer *error); -CstxStatusCode cstx_graph_ingest_native_json(struct CstxHandle *handle, - struct CstxSlice plugin, - struct CstxSlice artifact, - struct CstxSlice data, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_graph_find_node_json(struct CstxHandle *handle, - struct CstxSlice identifier, - struct CstxBuffer *output, - struct CstxBuffer *error); +/** + * Resolve an identifier and return the matching node as protobuf. + */ +CstxStatusCode cstx_graph_find_node(struct CstxHandle *handle, + struct CstxSlice identifier, + struct CstxBuffer *output, + struct CstxBuffer *error); -CstxStatusCode cstx_graph_patch_node_extras(struct CstxHandle *handle, - struct CstxSlice node_ids_json, - struct CstxSlice patch_json, - uint64_t *affected, - struct CstxBuffer *error); +CstxStatusCode cstx_graph_patch_node_annotations(struct CstxHandle *handle, + struct CstxSlice request, + uint64_t *affected, + struct CstxBuffer *error); -CstxStatusCode cstx_graph_create_relationship_json(struct CstxHandle *handle, - struct CstxSlice request_json, - struct CstxBuffer *output, - struct CstxBuffer *error); +CstxStatusCode cstx_graph_add_relationship(struct CstxHandle *handle, + struct CstxSlice request_bytes, + struct CstxBuffer *output, + struct CstxBuffer *error); CstxStatusCode cstx_is_path_expression(struct CstxSlice expression, uint8_t *output, @@ -256,23 +274,23 @@ CstxStatusCode cstx_graph_difference(struct CstxHandle *left, struct CstxHandle **output, struct CstxBuffer *error); -CstxStatusCode cstx_graph_node_types_json(struct CstxHandle *handle, - struct CstxBuffer *output, - struct CstxBuffer *error); +CstxStatusCode cstx_graph_node_types(struct CstxHandle *handle, + struct CstxBuffer *output, + struct CstxBuffer *error); -CstxStatusCode cstx_graph_link_json(struct CstxHandle *handle, - struct CstxSlice node_ids_json, - struct CstxSlice data_source, - struct CstxBuffer *output, - struct CstxBuffer *error); +CstxStatusCode cstx_graph_link(struct CstxHandle *handle, + struct CstxSlice node_ids, + struct CstxSlice data_source, + struct CstxBuffer *output, + struct CstxBuffer *error); CstxStatusCode cstx_graph_update_node_flags(struct CstxHandle *handle, - struct CstxSlice request_json, + struct CstxSlice request_bytes, uint64_t *affected, struct CstxBuffer *error); CstxStatusCode cstx_graph_analyze(struct CstxHandle *handle, - struct CstxSlice algorithm_json, + struct CstxSlice algorithm_bytes, struct CstxSlice selection, uint8_t *kind, uint8_t *boolean, @@ -286,36 +304,36 @@ CstxStatusCode cstx_graph_degree(struct CstxHandle *handle, struct CstxBuffer *error); CstxStatusCode cstx_graph_subgraph(struct CstxHandle *handle, - struct CstxSlice seed_ids_json, + struct CstxSlice seed_ids, uint32_t depth, struct CstxHandle **output, struct CstxBuffer *error); CstxStatusCode cstx_graph_query_subgraph(struct CstxHandle *handle, - struct CstxSlice request_json, + struct CstxSlice request_bytes, struct CstxHandle **output, struct CstxBuffer *error); CstxStatusCode cstx_graph_induced_subgraph(struct CstxHandle *handle, - struct CstxSlice request_json, + struct CstxSlice request_bytes, struct CstxHandle **output, struct CstxBuffer *error); CstxStatusCode cstx_graph_filter(struct CstxHandle *handle, - struct CstxSlice request_json, + struct CstxSlice request_bytes, struct CstxHandle **output, struct CstxBuffer *error); -CstxStatusCode cstx_graph_filter_with_reasons_json(struct CstxHandle *handle, - struct CstxSlice request_json, - struct CstxHandle **output, - struct CstxBuffer *details_json, - struct CstxBuffer *error); +CstxStatusCode cstx_graph_filter_with_reasons(struct CstxHandle *handle, + struct CstxSlice request_bytes, + struct CstxHandle **output, + struct CstxBuffer *details, + struct CstxBuffer *error); -CstxStatusCode cstx_graph_find_anchors_json(struct CstxHandle *handle, - struct CstxSlice concept_name, - struct CstxBuffer *output, - struct CstxBuffer *error); +CstxStatusCode cstx_graph_find_anchors(struct CstxHandle *handle, + struct CstxSlice concept_name, + struct CstxBuffer *output, + struct CstxBuffer *error); CstxStatusCode cstx_graph_elevate(struct CstxHandle *handle, struct CstxSlice concept_name, @@ -328,36 +346,9 @@ CstxStatusCode cstx_graph_stats(struct CstxHandle *handle, struct CstxBuffer *output, struct CstxBuffer *error); -CstxStatusCode cstx_graph_nodes_page_json(struct CstxHandle *handle, - struct CstxSlice request_json, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_graph_nodes_json(struct CstxHandle *handle, - struct CstxSlice node_type, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_graph_edges_json(struct CstxHandle *handle, - struct CstxSlice source_id, - struct CstxSlice target_id, - struct CstxSlice relation, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_graph_neighbors_json(struct CstxHandle *handle, - struct CstxSlice node_id, - struct CstxSlice direction, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_graph_query_json(struct CstxHandle *handle, - struct CstxSlice expression, - size_t limit, - uint8_t has_limit, - struct CstxBuffer *output, - struct CstxBuffer *error); - +/** + * Materialize one cursor page as protobuf bytes. + */ CstxStatusCode cstx_graph_cursor_page(struct CstxGraphCursor *cursor, size_t limit, size_t page, @@ -366,6 +357,9 @@ CstxStatusCode cstx_graph_cursor_page(struct CstxGraphCursor *cursor, void cstx_graph_cursor_free(struct CstxGraphCursor *cursor); +/** + * Resolve a revision and return its UTF-8 commit id in `output`. + */ CstxStatusCode cstx_repo_resolve(struct CstxHandle *handle, struct CstxSlice revision, struct CstxBuffer *output, @@ -381,7 +375,7 @@ CstxStatusCode cstx_repo_commit(struct CstxHandle *handle, struct CstxSlice message, struct CstxSlice ref_name, struct CstxSlice expected_head, - struct CstxSlice metadata_json, + struct CstxSlice metadata, struct CstxBuffer *output, struct CstxBuffer *error); @@ -389,7 +383,7 @@ CstxStatusCode cstx_repo_prepare(struct CstxHandle *handle, struct CstxSlice message, struct CstxSlice ref_name, struct CstxSlice expected_head, - struct CstxSlice metadata_json, + struct CstxSlice metadata, int64_t timestamp, uint8_t has_timestamp, struct CstxBuffer *output, @@ -402,7 +396,7 @@ CstxStatusCode cstx_repo_accept(struct CstxHandle *handle, CstxStatusCode cstx_repo_discard(struct CstxHandle *handle, struct CstxBuffer *error); CstxStatusCode cstx_repo_synchronize(struct CstxHandle *handle, - struct CstxSlice payload_json, + struct CstxSlice payload_bytes, struct CstxBuffer *error); CstxStatusCode cstx_repo_contains(struct CstxHandle *handle, @@ -410,59 +404,10 @@ CstxStatusCode cstx_repo_contains(struct CstxHandle *handle, uint8_t *output, struct CstxBuffer *error); -CstxStatusCode cstx_repo_missing_tree(struct CstxHandle *handle, - struct CstxSlice commit, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_repo_object_closure(struct CstxHandle *handle, - struct CstxSlice commit, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_repo_missing_prepare(struct CstxHandle *handle, - struct CstxSlice commit, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_repo_missing_history(struct CstxHandle *handle, - struct CstxSlice commit, - struct CstxSlice entity_id, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_repo_missing_stat(struct CstxHandle *handle, - struct CstxSlice commit, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_repo_missing_commits(struct CstxHandle *handle, - struct CstxSlice commit, - size_t limit, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_repo_missing_diff(struct CstxHandle *handle, - struct CstxSlice base, - struct CstxSlice head, - struct CstxSlice detail, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_repo_missing_delta(struct CstxHandle *handle, - struct CstxSlice commit, - int64_t start_timestamp, - uint8_t has_start, - int64_t end_timestamp, - uint8_t has_end, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_repo_missing_merge(struct CstxHandle *handle, - struct CstxSlice source, - struct CstxSlice target, - struct CstxBuffer *output, - struct CstxBuffer *error); +CstxStatusCode cstx_repo_missing(struct CstxHandle *handle, + struct CstxSlice request_bytes, + struct CstxBuffer *output, + struct CstxBuffer *error); CstxStatusCode cstx_repo_release_transient_objects(struct CstxHandle *handle, struct CstxBuffer *error); @@ -476,6 +421,9 @@ CstxStatusCode cstx_repo_diff(struct CstxHandle *handle, struct CstxBuffer *output, struct CstxBuffer *error); +/** + * Return the UTF-8 commit id at a ref, or an empty buffer when it is absent. + */ CstxStatusCode cstx_repo_head(struct CstxHandle *handle, struct CstxSlice ref_name, struct CstxBuffer *output, @@ -495,6 +443,22 @@ CstxStatusCode cstx_repo_history(struct CstxHandle *handle, struct CstxBuffer *output, struct CstxBuffer *error); +/** + * Read entity records at one revision and return a `Graph` in `output`. + * + * The selection's node and relationship ids are one set; the engine tells them + * apart by the `relationship:` prefix, as `history` does. Entities that are not + * live at `revision` are absent from the returned graph. + */ +CstxStatusCode cstx_repo_entities(struct CstxHandle *handle, + struct CstxSlice revision, + struct CstxSlice selection_bytes, + struct CstxBuffer *output, + struct CstxBuffer *error); + +/** + * Create a ref and return the target UTF-8 commit id in `output`. + */ CstxStatusCode cstx_repo_branch(struct CstxHandle *handle, struct CstxSlice name, struct CstxSlice start_point, @@ -526,23 +490,23 @@ CstxStatusCode cstx_repo_delta(struct CstxHandle *handle, struct CstxBuffer *error); CstxStatusCode cstx_rag_index(struct CstxHandle *handle, - struct CstxSlice request_json, + struct CstxSlice request_bytes, struct CstxRagIndexSession **output, struct CstxBuffer *error); -CstxStatusCode cstx_rag_index_session_metadata_json(struct CstxRagIndexSession *session, - struct CstxBuffer *output, - struct CstxBuffer *error); +CstxStatusCode cstx_rag_index_session_metadata(struct CstxRagIndexSession *session, + struct CstxBuffer *output, + struct CstxBuffer *error); -CstxStatusCode cstx_rag_index_session_pending_json(struct CstxRagIndexSession *session, - size_t offset, - size_t limit, - struct CstxBuffer *output, - struct CstxBuffer *error); +CstxStatusCode cstx_rag_index_session_pending(struct CstxRagIndexSession *session, + size_t offset, + size_t limit, + struct CstxBuffer *output, + struct CstxBuffer *error); -CstxStatusCode cstx_rag_index_session_deletes_json(struct CstxRagIndexSession *session, - struct CstxBuffer *output, - struct CstxBuffer *error); +CstxStatusCode cstx_rag_index_session_deletes(struct CstxRagIndexSession *session, + struct CstxBuffer *output, + struct CstxBuffer *error); CstxStatusCode cstx_rag_index_session_records(struct CstxRagIndexSession *session, struct CstxRagRecordIterator **output, @@ -562,18 +526,18 @@ void cstx_rag_index_session_close(struct CstxRagIndexSession *session); void cstx_rag_index_session_free(struct CstxRagIndexSession *session); CstxStatusCode cstx_rag_retrieve(struct CstxHandle *handle, - struct CstxSlice query_json, + struct CstxSlice query_bytes, struct CstxRagRetrieval **output, struct CstxBuffer *error); -CstxStatusCode cstx_rag_retrieval_requests_json(struct CstxRagRetrieval *retrieval, - struct CstxBuffer *output, - struct CstxBuffer *error); +CstxStatusCode cstx_rag_retrieval_requests(struct CstxRagRetrieval *retrieval, + struct CstxBuffer *output, + struct CstxBuffer *error); -CstxStatusCode cstx_rag_retrieval_complete_json(struct CstxRagRetrieval *retrieval, - struct CstxSlice batches_json, - struct CstxBuffer *output, - struct CstxBuffer *error); +CstxStatusCode cstx_rag_retrieval_complete(struct CstxRagRetrieval *retrieval, + struct CstxSlice batches_bytes, + struct CstxBuffer *output, + struct CstxBuffer *error); void cstx_rag_retrieval_close(struct CstxRagRetrieval *retrieval); diff --git a/go/cstx_native_test.go b/go/cstx_native_test.go index 7844080..a8ca155 100644 --- a/go/cstx_native_test.go +++ b/go/cstx_native_test.go @@ -8,6 +8,10 @@ import ( "reflect" "slices" "testing" + + "github.com/chainreactors/libcstx/go/plugins/easm" + "github.com/chainreactors/libcstx/go/proto/cstxproto" + "google.golang.org/protobuf/types/known/structpb" ) var testContext = context.Background() @@ -15,11 +19,11 @@ var testContext = context.Background() //go:embed testdata/conformance.json var conformanceFixture []byte -var domainSchema = map[string]any{"properties": map[string]any{"domain": map[string]any{"type": "string"}}} +func stringPtr(value string) *string { return &value } func openRuntime(t *testing.T) *CSTX { t.Helper() - rt, err := Open(testContext, Config{ProjectID: "sdk-go-test"}) + rt, err := Open(testContext, &cstxproto.RuntimeConfig{ProjectId: "sdk-go-test"}) if err != nil { t.Fatalf("open: %v", err) } @@ -28,37 +32,53 @@ func openRuntime(t *testing.T) *CSTX { t.Fatalf("close: %v", err) } }) - if err := rt.Schemas.Register(testContext, "domain", domainSchema, "domain"); err != nil { - t.Fatalf("register schema: %v", err) + // The built-in extension ships its own schema document; enabling it is + // the whole registration step. + if err := rt.Extensions.Enable(testContext, "easm"); err != nil { + t.Fatalf("enable easm: %v", err) } return rt } -func domainNode(value string) Node { - return Node{ - ID: "domain:" + value, - Type: "domain", - Value: value, - Model: map[string]any{"domain": value, "cstx_flags": 0}, - Sources: []string{"test"}, - Extras: map[string]any{}, +func domainNode(value string) *cstxproto.Node { + // Through the generated typed layer, which builds the schema-named payload. + // Nothing here holds a generated protobuf message for the node type, which + // is the property a type declared at runtime depends on. + node, err := easm.Domain{Host: value}.Node("test") + if err != nil { + panic(err) } + id := "domain:" + value + node.Id = &id + return node } -func relatedEdge(source, target string) Edge { - return Edge{ - ID: "relationship:" + source + ":related:" + target, - SourceID: source, - TargetID: target, - RelationType: "related", - Sources: []string{"test"}, - Attrs: map[string]any{}, +func usesRelationship(source, target string) *cstxproto.Relationship { + id := "relationship:" + source + ":uses:" + target + return &cstxproto.Relationship{ + Id: &id, + SourceId: source, + TargetId: target, + Sources: []string{"test"}, + Value: &cstxproto.RelationshipValue{RelationshipType: easm.RelUses}, + } +} + +func domainValue(t *testing.T, node *cstxproto.Node) string { + t.Helper() + if node == nil { + t.Fatal("invalid domain node: nil") + } + domain, err := easm.DomainFrom(node.GetValue()) + if err != nil { + t.Fatalf("invalid domain node: %+v (%v)", node, err) } + return domain.Host } func addDomain(t *testing.T, rt *CSTX, value string) uint64 { t.Helper() - affected, err := rt.Graph.AddNodes(testContext, []Node{domainNode(value)}) + affected, err := rt.Graph.AddNodes(testContext, []*cstxproto.Node{domainNode(value)}) if err != nil { t.Fatalf("add node %s: %v", value, err) } @@ -74,66 +94,66 @@ func TestRepositoryExternalPersistenceRoundTrip(t *testing.T) { "external persistence", "main", nil, - map[string]any{"source": "go-test"}, + &structpb.Struct{Fields: map[string]*structpb.Value{"source": structpb.NewStringValue("go-test")}}, nil, ) if err != nil { t.Fatalf("prepare: %v", err) } - if prepared.Commit.ID == "" || prepared.IndexRoot == "" || len(prepared.Objects) == 0 { + if prepared.Commit.Id == "" || prepared.IndexRoot == "" || len(prepared.Objects) == 0 { t.Fatalf("incomplete prepared payload: %+v", prepared) } - objects := make(map[string]RepositoryObject, len(prepared.Objects)) - var commitObject, indexObject RepositoryObject + objects := make(map[string]*cstxproto.RepositoryState_Object, len(prepared.Objects)) + var commitObject, indexObject *cstxproto.RepositoryState_Object for _, object := range prepared.Objects { - stored := RepositoryObject{ID: object.ID, Envelope: append([]byte(nil), object.Envelope...)} - objects[object.ID] = stored - if object.Kind == "commit" && object.ID == prepared.Commit.ID { + stored := &cstxproto.RepositoryState_Object{Id: object.Id, Payload: append([]byte(nil), object.Payload...)} + objects[object.Id] = stored + if object.Kind == cstxproto.RepositoryObjectKind_REPOSITORY_OBJECT_KIND_COMMIT && object.Id == prepared.Commit.Id { commitObject = stored } - if object.ID == prepared.IndexRoot { + if object.Id == prepared.IndexRoot { indexObject = stored } } - if commitObject.ID == "" || indexObject.ID == "" { + if commitObject == nil || indexObject == nil { t.Fatal("prepared payload does not contain commit and index-root envelopes") } - if err := writer.Repo.Accept(testContext, prepared.Commit.ID); err != nil { + if err := writer.Repo.Accept(testContext, prepared.Commit.Id); err != nil { t.Fatalf("accept: %v", err) } reader := openRuntime(t) - head := prepared.Commit.ID - if err := reader.Repo.Synchronize(testContext, RepositorySync{ - Objects: []RepositoryObject{commitObject, indexObject}, + head := prepared.Commit.Id + if err := reader.Repo.Synchronize(testContext, &cstxproto.RepositoryState{ + Objects: []*cstxproto.RepositoryState_Object{commitObject, indexObject}, }); err != nil { t.Fatalf("synchronize commit objects: %v", err) } - if err := reader.Repo.Synchronize(testContext, RepositorySync{ - Refs: []RepositoryRef{{Name: "main", Commit: &head}}, - Indexes: []RepositoryIndex{{Commit: head, IndexRoot: prepared.IndexRoot}}, + if err := reader.Repo.Synchronize(testContext, &cstxproto.RepositoryState{ + Refs: []*cstxproto.RepositoryState_Ref{{Name: "main", CommitId: &head}}, + Indexes: []*cstxproto.RepositoryState_Index{{CommitId: head, IndexRoot: prepared.IndexRoot}}, }); err != nil { t.Fatalf("synchronize commit frontier: %v", err) } for { - missing, err := reader.Repo.MissingTree(testContext, head) + missing, err := reader.Repo.Missing(testContext, &cstxproto.RepositoryObjectPlan{Kind: cstxproto.RepositoryPlanKind_REPOSITORY_PLAN_TREE, CommitId: head}) if err != nil { t.Fatalf("plan missing tree: %v", err) } - if len(missing) == 0 { + if len(missing.ObjectIds) == 0 { break } - batch := make([]RepositoryObject, 0, len(missing)) - for _, id := range missing { + batch := make([]*cstxproto.RepositoryState_Object, 0, len(missing.ObjectIds)) + for _, id := range missing.ObjectIds { object, ok := objects[id] if !ok { t.Fatalf("planner requested unknown object %s", id) } batch = append(batch, object) } - if err := reader.Repo.Synchronize(testContext, RepositorySync{Objects: batch}); err != nil { + if err := reader.Repo.Synchronize(testContext, &cstxproto.RepositoryState{Objects: batch}); err != nil { t.Fatalf("hydrate tree: %v", err) } } @@ -141,7 +161,7 @@ func TestRepositoryExternalPersistenceRoundTrip(t *testing.T) { t.Fatalf("checkout hydrated main: %v", err) } node, err := reader.Graph.Node(testContext, "domain:persisted.example") - if err != nil || node.Value != "persisted.example" { + if err != nil || domainValue(t, node) != "persisted.example" { t.Fatalf("restored node: %+v err=%v", node, err) } if err := reader.Repo.ReleaseTransientObjects(testContext); err != nil { @@ -154,18 +174,18 @@ func TestGraphDeleteNodesCascadesAndCommits(t *testing.T) { addDomain(t, rt, "delete-a.example") addDomain(t, rt, "delete-b.example") addDomain(t, rt, "keep.example") - edges := []Edge{ - relatedEdge("domain:delete-a.example", "domain:delete-b.example"), - relatedEdge("domain:delete-b.example", "domain:keep.example"), + relationships := []*cstxproto.Relationship{ + usesRelationship("domain:delete-a.example", "domain:delete-b.example"), + usesRelationship("domain:delete-b.example", "domain:keep.example"), } - if _, err := rt.Graph.AddEdges(testContext, edges); err != nil { - t.Fatalf("add edges: %v", err) + if _, err := rt.Graph.AddRelationships(testContext, relationships); err != nil { + t.Fatalf("add relationships: %v", err) } base, err := rt.Repo.Commit(testContext, "base", "main", nil, nil) if err != nil { t.Fatalf("commit base: %v", err) } - cursor, err := rt.Graph.Nodes(testContext, NodeFilter{}, CollectionOptions{}) + cursor, err := rt.Graph.Nodes(testContext, &cstxproto.NodeQuery{}) if err != nil { t.Fatalf("open cursor: %v", err) } @@ -181,19 +201,19 @@ func TestGraphDeleteNodesCascadesAndCommits(t *testing.T) { if count, _ := rt.Graph.NodeCount(testContext); count != 2 { t.Fatalf("node count after delete=%d", count) } - if count, _ := rt.Graph.EdgeCount(testContext); count != 0 { - t.Fatalf("edge count after cascade=%d", count) + if count, _ := rt.Graph.RelationshipCount(testContext); count != 0 { + t.Fatalf("relationship count after cascade=%d", count) } change, err := rt.LastChange(testContext) - if err != nil || !reflect.DeepEqual(change.RemovedNodeIDs, []string{"domain:delete-b.example"}) || len(change.RemovedEdgeIDs) != 2 { + if err != nil || !reflect.DeepEqual(change.RemovedNodeIds, []string{"domain:delete-b.example"}) || len(change.RemovedRelationshipIds) != 2 { t.Fatalf("delete change=%+v err=%v", change, err) } - head, err := rt.Repo.Commit(testContext, "delete", "main", &base.ID, nil) + head, err := rt.Repo.Commit(testContext, "delete", "main", &base.Id, nil) if err != nil { t.Fatalf("commit delete: %v", err) } - diff, err := rt.Repo.Diff(testContext, base.ID, head.ID, DiffOptions{}) - if err != nil || !reflect.DeepEqual(diff.Removed["domain"], []string{"domain:delete-b.example"}) || len(diff.Removed["edge:related"]) != 2 { + diff, err := rt.Repo.Diff(testContext, base.Id, head.Id, nil, cstxproto.DiffDetail_DIFF_DETAIL_ENTITIES) + if err != nil || !reflect.DeepEqual(diff.Removed.NodeIds, []string{"domain:delete-b.example"}) || len(diff.Removed.RelationshipIds) != 2 { t.Fatalf("delete diff=%+v err=%v", diff, err) } } @@ -210,83 +230,93 @@ func TestGraphDeleteIsAtomicOnMissingID(t *testing.T) { } } -func TestSchemas(t *testing.T) { +func TestExtensionsSchemaSurface(t *testing.T) { rt := openRuntime(t) - valueField := "domain" - contract := SchemaContract{ - Format: "cstx.schema", - Plugins: map[string]PluginSchemaContract{ - "sdk-test": { - Version: "1", - SCO: map[string]SCOSchemaContract{ - "domain": { - Schema: domainSchema, - ValueField: &valueField, - Metadata: map[string]any{}, - }, - }, - SRO: map[string]SROSchemaContract{}, - Parsers: map[string]ParserSchemaContract{}, - }, - }, - } - if err := rt.Schemas.Import(testContext, contract); err != nil { - t.Fatalf("import schema contract: %v", err) - } - exported, err := rt.Schemas.Export(testContext) - if err != nil || exported.Format != "cstx.schema" || exported.Plugins["sdk-test"].Version != "1" { - t.Fatalf("export schema contract: %+v err=%v", exported, err) - } - if err := rt.Schemas.RegisterJoinRule(testContext, JoinRuleSpec{ - LeftType: "domain", RightType: "domain", Relation: "related", - LeftKey: "domain", RightKey: "domain", - }); err != nil { - t.Fatalf("register join rule: %v", err) + if err := rt.Extensions.Enable(testContext, "easm"); err != nil { + t.Fatalf("enable easm: %v", err) } - - contains, err := rt.Schemas.Contains(testContext, "domain") + builder := newExtensionBuilder("sdk-test", "1") + builder.Rule(&cstxproto.JoinRule{LeftTypeUrl: "type.googleapis.com/easm.Domain", RightTypeUrl: "type.googleapis.com/easm.Domain", RelationshipTypeUrl: "type.googleapis.com/easm.Uses", LeftKey: "domain", RightKey: "domain"}) + if err := rt.Extensions.Register(testContext, builder.Build()); err != nil { + t.Fatalf("register schema contract: %v", err) + } + contains, err := rt.Extensions.Contains(testContext, "domain") if err != nil || !contains { t.Fatalf("contains: %v %v", contains, err) } - schema, err := rt.Schemas.Get(testContext, "domain") + schema, err := rt.Extensions.Schema(testContext, "domain") if err != nil { t.Fatalf("get: %v", err) } - if schema["node_type"] != "domain" || schema["value_field"] != "domain" { - t.Fatalf("unexpected schema: %v", schema) + if schema.TypeUrl != "type.googleapis.com/easm.Domain" { + t.Fatalf("unexpected schema type: %v", schema.TypeUrl) } - if _, ok := schema["schema"].(map[string]any)["properties"]; !ok { - t.Fatalf("unexpected schema body: %v", schema) + // value_field comes from the generated schema document, not from a + // hand-written restatement of it. + if schema.Metadata == nil || schema.Metadata.Fields["value_field"].GetStringValue() != "host" { + t.Fatalf("unexpected schema metadata: %v", schema.Metadata) } - list, err := rt.Schemas.List(testContext) - if err != nil || len(list) == 0 { + list, err := rt.Extensions.Schemas(testContext) + if err != nil || len(list.Schemas) == 0 { t.Fatalf("list: %v %v", list, err) } - plugins, err := rt.Schemas.AvailablePlugins(testContext) - if err != nil { - t.Fatalf("available plugins: %v", err) - } - if !reflect.DeepEqual(plugins, []string{"easm"}) { - t.Fatalf("available plugins: %v", plugins) - } - artifacts, err := rt.Schemas.PluginArtifacts(testContext, "easm") - if err != nil || !slices.Contains(artifacts, "gogo") { - t.Fatalf("easm artifacts: %v err=%v", artifacts, err) + easmInfo, err := rt.Extensions.Info(testContext, "easm") + if err != nil || !slices.Contains(easmInfo.Artifacts, "gogo") { + t.Fatalf("easm artifacts: %+v err=%v", easmInfo, err) } - concepts, err := rt.Schemas.AnchorConcepts(testContext) - if err != nil || len(concepts) == 0 || concepts[0].Name == "" { + concepts, err := rt.Extensions.AnchorConcepts(testContext) + if err != nil || len(concepts.Concepts) == 0 || concepts.Concepts[0].Name == "" { t.Fatalf("anchor concepts: %+v err=%v", concepts, err) } - if err := rt.Schemas.LoadPlugin(testContext, "easm"); err != nil { - t.Fatalf("load easm plugin: %v", err) + if err := rt.Extensions.Enable(testContext, "easm"); err != nil { + t.Fatalf("enable easm plugin: %v", err) } - hasGogo, err := rt.Schemas.HasNativeArtifact(testContext, "gogo") + hasGogo, err := rt.Extensions.ParsesArtifact(testContext, "gogo") if err != nil || !hasGogo { t.Fatalf("has native gogo artifact: %v err=%v", hasGogo, err) } - gogo := []byte(`{"ip":"192.0.2.1","port":"80","protocol":"tcp","status":"200"}` + "\n") - if affected, err := rt.Graph.Ingest(testContext, "gogo", gogo); err != nil || affected == 0 { - t.Fatalf("ingest gogo: affected=%d err=%v", affected, err) +} + +func TestExtensions(t *testing.T) { + // This one watches the disabled -> enabled transition, so it must not + // use the fixture that enables easm up front. + rt, err := Open(testContext, &cstxproto.RuntimeConfig{ProjectId: "sdk-go-extensions"}) + if err != nil { + t.Fatalf("open: %v", err) + } + t.Cleanup(func() { _ = rt.Close() }) + ctx := testContext + + items, err := rt.Extensions.List(ctx) + if err != nil || len(items.Extensions) == 0 || items.Extensions[0].Name != "easm" || items.Extensions[0].Enabled { + t.Fatalf("extension list: %+v err=%v", items, err) + } + if err := rt.Extensions.Enable(ctx, "easm"); err != nil { + t.Fatalf("enable easm: %v", err) + } + info, err := rt.Extensions.Info(ctx, "easm") + if err != nil || !info.Enabled || info.Kind != "native" { + t.Fatalf("extension info: %+v err=%v", info, err) + } + + builder := newExtensionBuilder("sdk-external", "") + inputSchema, _ := structpb.NewStruct(map[string]any{"type": "object"}) + builder.Parser("report", &cstxproto.ParserType{Artifact: "report", InputSchema: inputSchema}) + builder.Rule(&cstxproto.JoinRule{LeftTypeUrl: "type.googleapis.com/easm.Domain", RightTypeUrl: "type.googleapis.com/easm.Domain", RelationshipTypeUrl: "type.googleapis.com/easm.Uses", LeftKey: "domain", RightKey: "domain"}) + if err := rt.Extensions.Register(ctx, builder.Build()); err != nil { + t.Fatalf("register external extension: %v", err) + } + contract, err := rt.Extensions.ExportContract(ctx) + if err != nil { + t.Fatalf("export extension contract: %v", err) + } + definition, ok := contract.Extensions["sdk-external"] + if !ok || definition.Parsers["report"] == nil { + t.Fatalf("exported contract lost sdk-external parser: %+v", contract.Extensions) + } + external, err := rt.Extensions.Info(ctx, "sdk-external") + if err != nil || external.Kind != "external" || !external.Enabled || !slices.Contains(external.Artifacts, "report") { + t.Fatalf("external extension info: %+v err=%v", external, err) } } @@ -309,12 +339,9 @@ func TestGraphMutationAndCursors(t *testing.T) { if err != nil { t.Fatalf("node: %v", err) } - if node.ID != "domain:example.com" || node.Type != "domain" { + if node.GetId() != "domain:example.com" || domainValue(t, node) != "example.com" { t.Fatalf("unexpected node: %+v", node) } - if node.Model["domain"] != "example.com" { - t.Fatalf("unexpected model: %+v", node.Model) - } if _, err := rt.Graph.Node(testContext, "domain:missing.example"); !IsCode(err, CodeNotFound) { t.Fatalf("expected NOT_FOUND, got %v", err) @@ -322,7 +349,7 @@ func TestGraphMutationAndCursors(t *testing.T) { // Re-adding identical content is a no-op: zero affected and live cursors // stay valid. - cursor, err := rt.Graph.Nodes(testContext, NodeFilter{Types: []string{"domain"}}, CollectionOptions{Order: OrderIDAsc}) + cursor, err := rt.Graph.Nodes(testContext, &cstxproto.NodeQuery{Filter: &cstxproto.NodeFilter{NodeTypes: []string{"domain"}}, Window: &cstxproto.QueryWindow{Order: cstxproto.SortOrder_SORT_ORDER_ID_ASC}}) if err != nil { t.Fatalf("nodes: %v", err) } @@ -334,13 +361,10 @@ func TestGraphMutationAndCursors(t *testing.T) { if err != nil { t.Fatalf("cursor page: %v", err) } - nodes, err := page.Nodes() - if err != nil { - t.Fatalf("decode nodes: %v", err) - } - ids := make([]string, len(nodes)) - for index, node := range nodes { - ids[index] = node.ID + resultNodes := page.GetNodes().GetValues() + ids := make([]string, len(resultNodes)) + for index, node := range resultNodes { + ids[index] = node.GetId() } if err := cursor.Close(); err != nil { t.Fatalf("cursor close: %v", err) @@ -353,7 +377,7 @@ func TestGraphMutationAndCursors(t *testing.T) { if err != nil { t.Fatalf("stats: %v", err) } - if stats.Nodes["domain"] != 2 { + if stats.NodesByType["domain"] != 2 { t.Fatalf("unexpected stats: %+v", stats) } } @@ -362,7 +386,7 @@ func TestCursorInvalidation(t *testing.T) { rt := openRuntime(t) addDomain(t, rt, "example.com") - cursor, err := rt.Graph.Nodes(testContext, NodeFilter{}, CollectionOptions{}) + cursor, err := rt.Graph.Nodes(testContext, &cstxproto.NodeQuery{}) if err != nil { t.Fatalf("nodes: %v", err) } @@ -376,40 +400,40 @@ func TestCursorInvalidation(t *testing.T) { } } -func TestGraphEdgesNeighborsAndQuery(t *testing.T) { +func TestGraphRelationshipsNeighborsAndQuery(t *testing.T) { rt := openRuntime(t) addDomain(t, rt, "example.com") addDomain(t, rt, "www.example.com") - affected, err := rt.Graph.AddEdges(testContext, []Edge{relatedEdge("domain:www.example.com", "domain:example.com")}) + affected, err := rt.Graph.AddRelationships(testContext, []*cstxproto.Relationship{usesRelationship("domain:www.example.com", "domain:example.com")}) if err != nil { t.Fatalf("add edge: %v", err) } if affected != 1 { t.Fatalf("add edge affected=%d", affected) } - if count, err := rt.Graph.EdgeCount(testContext); err != nil || count != 1 { + if count, err := rt.Graph.RelationshipCount(testContext); err != nil || count != 1 { t.Fatalf("edge count: %v %v", count, err) } - edges, err := rt.Graph.Edges(testContext, EdgeFilter{SourceID: "domain:www.example.com"}, CollectionOptions{}) + relationships, err := rt.Graph.Relationships(testContext, &cstxproto.RelationshipQuery{Filter: &cstxproto.RelationshipFilter{SourceId: stringPtr("domain:www.example.com")}}) if err != nil { t.Fatalf("edges: %v", err) } - defer edges.Close() - edgePage, err := edges.Page(testContext, 10, 1) + defer relationships.Close() + relationshipPage, err := relationships.Page(testContext, 10, 1) if err != nil { t.Fatalf("edge page: %v", err) } - edgeItems, err := edgePage.Edges() - if err != nil || len(edgeItems) != 1 { - t.Fatalf("decode edge page: items=%v err=%v", edgeItems, err) + relationshipItems := relationshipPage.GetRelationships().GetValues() + if len(relationshipItems) != 1 { + t.Fatalf("decode relationship page: items=%v", relationshipItems) } - if edgeItems[0].RelationType != "related" || edgeItems[0].TargetID != "domain:example.com" { - t.Fatalf("unexpected edge: %+v", edgeItems[0]) + if relationshipItems[0].GetTargetId() != "domain:example.com" { + t.Fatalf("unexpected relationship: %+v", relationshipItems[0]) } - neighbors, err := rt.Graph.Neighbors(testContext, "domain:www.example.com", "out", CollectionOptions{}) + neighbors, err := rt.Graph.Neighbors(testContext, &cstxproto.NeighborQuery{NodeId: "domain:www.example.com", Direction: cstxproto.Direction_DIRECTION_OUT}) if err != nil { t.Fatalf("neighbors: %v", err) } @@ -418,12 +442,12 @@ func TestGraphEdgesNeighborsAndQuery(t *testing.T) { if err != nil { t.Fatalf("neighbor page: %v", err) } - neighborItems, err := neighborPage.Nodes() - if err != nil || len(neighborItems) != 1 || neighborItems[0].ID != "domain:example.com" { - t.Fatalf("unexpected neighbor: items=%v err=%v", neighborItems, err) + neighborItems := neighborPage.GetNodes().GetValues() + if len(neighborItems) != 1 || neighborItems[0].GetId() != "domain:example.com" { + t.Fatalf("unexpected neighbor: items=%v", neighborItems) } - matches, err := rt.Graph.Query(testContext, "domain", QueryOptions{}) + matches, err := rt.Graph.Query(testContext, &cstxproto.GraphQuery{Expression: "domain"}) if err != nil { t.Fatalf("query: %v", err) } @@ -432,8 +456,8 @@ func TestGraphEdgesNeighborsAndQuery(t *testing.T) { if err != nil { t.Fatalf("query page: %v", err) } - if len(matchPage.Items) != 2 { - t.Fatalf("expected 2 query matches, got %d", len(matchPage.Items)) + if len(matchPage.GetNodes().GetValues()) != 2 { + t.Fatalf("expected 2 query matches, got %d", len(matchPage.GetNodes().GetValues())) } } @@ -442,21 +466,18 @@ func TestGraphAlgorithmsAndCommunityCursor(t *testing.T) { for _, value := range []string{"a.example", "b.example", "c.example", "d.example"} { addDomain(t, rt, value) } - _, err := rt.Graph.AddEdges(testContext, []Edge{ - relatedEdge("domain:a.example", "domain:b.example"), - relatedEdge("domain:b.example", "domain:c.example"), + _, err := rt.Graph.AddRelationships(testContext, []*cstxproto.Relationship{ + usesRelationship("domain:a.example", "domain:b.example"), + usesRelationship("domain:b.example", "domain:c.example"), }) if err != nil { t.Fatalf("add algorithm fixture edges: %v", err) } - bfsResult, err := rt.Graph.Analyze(testContext, map[string]any{ - "name": "bfs", "seed_id": "domain:a.example", "depth": 2, "direction": "out", - }) + bfs, _, err := rt.Graph.Analyze(testContext, &cstxproto.Algorithm{Kind: &cstxproto.Algorithm_Bfs{Bfs: &cstxproto.BfsAlgorithm{SeedId: "domain:a.example", Depth: 2, Direction: cstxproto.Direction_DIRECTION_OUT}}}, nil) if err != nil { t.Fatalf("bfs: %v", err) } - bfs := bfsResult.(*GraphCursor) defer bfs.Close() if bfs.Kind() != CursorKindNodes { t.Fatalf("bfs kind=%q", bfs.Kind()) @@ -465,79 +486,66 @@ func TestGraphAlgorithmsAndCommunityCursor(t *testing.T) { if err != nil { t.Fatalf("bfs page: %v", err) } - if bfsPage.Total == nil || *bfsPage.Total != 2 || bfsPage.HasNext { + if bfsPage.Total == nil || *bfsPage.Total != 2 || bfsPage.GetHasNext() { t.Fatalf("unexpected bfs page metadata: %+v", bfsPage) } - bfsNodes, err := bfsPage.Nodes() - if err != nil || len(bfsNodes) != 2 || bfsNodes[0].ID != "domain:b.example" { - t.Fatalf("unexpected bfs rows: nodes=%v err=%v", bfsNodes, err) + bfsNodes := bfsPage.GetNodes().GetValues() + if len(bfsNodes) != 2 || bfsNodes[0].GetId() != "domain:b.example" { + t.Fatalf("unexpected bfs rows: nodes=%v", bfsNodes) } - componentsResult, err := rt.Graph.Analyze(testContext, map[string]any{"name": "weak_components"}) + components, _, err := rt.Graph.Analyze(testContext, &cstxproto.Algorithm{Kind: &cstxproto.Algorithm_Parameterless{Parameterless: cstxproto.ParameterlessAlgorithm_PARAMETERLESS_WEAK_COMPONENTS}}, nil) if err != nil { t.Fatalf("weak components: %v", err) } - components := componentsResult.(*GraphCursor) defer components.Close() componentPage, err := components.Page(testContext, 10, 1) if err != nil { t.Fatalf("component page: %v", err) } - if components.Kind() != CursorKindComponents || len(componentPage.Items) != 4 { + if components.Kind() != CursorKindComponents || len(componentPage.GetComponents().GetValues()) != 4 { t.Fatalf("unexpected component cursor: kind=%q page=%+v", components.Kind(), componentPage) } - var componentSummary struct { - ComponentCount uint64 `json:"component_count"` - Projection string `json:"projection"` - } - if err := json.Unmarshal(componentPage.Summary, &componentSummary); err != nil || componentSummary.ComponentCount != 2 || componentSummary.Projection != "undirected" { - t.Fatalf("component summary=%+v err=%v", componentSummary, err) + componentSummary := componentPage.GetComponent() + if componentSummary.GetComponentCount() != 2 || componentSummary.GetProjection() != "undirected" { + t.Fatalf("component summary=%+v", componentSummary) } - isDAGResult, err := rt.Graph.Analyze(testContext, map[string]any{"name": "is_dag"}) - if err != nil || !isDAGResult.(bool) { - t.Fatalf("is dag=%v err=%v", isDAGResult, err) + _, isDAG, err := rt.Graph.Analyze(testContext, &cstxproto.Algorithm{Kind: &cstxproto.Algorithm_Parameterless{Parameterless: cstxproto.ParameterlessAlgorithm_PARAMETERLESS_IS_DAG}}, nil) + if err != nil || isDAG == nil || !*isDAG { + t.Fatalf("is dag=%v err=%v", isDAG, err) } - orderResult, err := rt.Graph.Analyze(testContext, map[string]any{"name": "topological_order"}) - if err != nil || orderResult == nil { - t.Fatalf("topological order result=%v err=%v", orderResult, err) + order, _, err := rt.Graph.Analyze(testContext, &cstxproto.Algorithm{Kind: &cstxproto.Algorithm_Parameterless{Parameterless: cstxproto.ParameterlessAlgorithm_PARAMETERLESS_TOPOLOGICAL_ORDER}}, nil) + if err != nil || order == nil { + t.Fatalf("topological order result=%v err=%v", order, err) } - order := orderResult.(*GraphCursor) defer order.Close() orderPage, err := order.Page(testContext, 10, 1) if err != nil { t.Fatalf("topological page: %v", err) } - if len(orderPage.Items) != 4 { - t.Fatalf("topological row count=%d", len(orderPage.Items)) + if len(orderPage.GetNodes().GetValues()) != 4 { + t.Fatalf("topological row count=%d", len(orderPage.GetNodes().GetValues())) } - coreResult, err := rt.Graph.Analyze(testContext, map[string]any{"name": "core_numbers"}) + core, _, err := rt.Graph.Analyze(testContext, &cstxproto.Algorithm{Kind: &cstxproto.Algorithm_Parameterless{Parameterless: cstxproto.ParameterlessAlgorithm_PARAMETERLESS_CORE_NUMBERS}}, nil) if err != nil { t.Fatalf("core numbers: %v", err) } - core := coreResult.(*GraphCursor) defer core.Close() corePage, err := core.Page(testContext, 10, 1) - if err != nil || len(corePage.Items) != 4 || core.Kind() != CursorKindNodeScores { + if err != nil || len(corePage.GetScores().GetValues()) != 4 || core.Kind() != CursorKindNodeScores { t.Fatalf("core page=%+v kind=%q err=%v", corePage, core.Kind(), err) } - var coreRow struct { - NodeID string `json:"node_id"` - Metric string `json:"metric"` - Score float64 `json:"score"` - } - if err := json.Unmarshal(corePage.Items[0], &coreRow); err != nil || coreRow.Metric != "core_number" || coreRow.NodeID == "" { - t.Fatalf("core row=%+v err=%v", coreRow, err) + coreRow := corePage.GetScores().GetValues()[0] + if coreRow.GetMetric() != "core_number" || coreRow.GetNodeId() == "" { + t.Fatalf("core row=%+v", coreRow) } - communityResult, err := rt.Graph.Analyze(testContext, map[string]any{ - "name": "leiden", "resolution": 1.0, "min_community_size": 1, - }) + communities, _, err := rt.Graph.Analyze(testContext, &cstxproto.Algorithm{Kind: &cstxproto.Algorithm_Leiden{Leiden: &cstxproto.LeidenAlgorithm{Resolution: 1, MinCommunitySize: 1}}}, nil) if err != nil { t.Fatalf("analyze leiden: %v", err) } - communities := communityResult.(*GraphCursor) defer communities.Close() if communities.Kind() != CursorKindCommunities { t.Fatalf("unexpected community cursor kind: %q", communities.Kind()) @@ -546,23 +554,16 @@ func TestGraphAlgorithmsAndCommunityCursor(t *testing.T) { if err != nil { t.Fatalf("community assignment page: %v", err) } - var communitySummary struct { - Algorithm string `json:"algorithm"` - Projection string `json:"projection"` - TotalCommunities uint64 `json:"total_communities"` - } - if err := json.Unmarshal(assignmentPage.Summary, &communitySummary); err != nil || communitySummary.Algorithm != "leiden" || communitySummary.Projection != "undirected" || communitySummary.TotalCommunities == 0 { - t.Fatalf("unexpected community summary: %+v err=%v", communitySummary, err) + communitySummary := assignmentPage.GetCommunity() + if communitySummary.GetAlgorithm() != "leiden" || communitySummary.GetProjection() != "undirected" || communitySummary.GetTotalCommunities() == 0 { + t.Fatalf("unexpected community summary: %+v", communitySummary) } - if assignmentPage.Total == nil || *assignmentPage.Total != 4 || len(assignmentPage.Items) != 2 || !assignmentPage.HasNext { + if assignmentPage.Total == nil || *assignmentPage.Total != 4 || len(assignmentPage.GetCommunities().GetValues()) != 2 || !assignmentPage.GetHasNext() { t.Fatalf("unexpected assignment page: %+v", assignmentPage) } - var assignment struct { - NodeID string `json:"node_id"` - Community uint32 `json:"community"` - } - if err := json.Unmarshal(assignmentPage.Items[0], &assignment); err != nil || assignment.NodeID == "" { - t.Fatalf("community assignment=%+v err=%v", assignment, err) + assignment := assignmentPage.GetCommunities().GetValues()[0] + if assignment.GetNodeId() == "" { + t.Fatalf("community assignment=%+v", assignment) } } @@ -571,47 +572,44 @@ func TestGraphQueryOptionsCrossFFIBoundary(t *testing.T) { external := domainNode("external.example.com") internal := domainNode("internal.example.com") - internal.Model["cstx_flags"] = FlagInternal - if affected, err := rt.Graph.AddNodes(testContext, []Node{external, internal}); err != nil || affected != 2 { + internal.FlagsMask = 1 << 6 // easm declares `internal` at bit 6 + if affected, err := rt.Graph.AddNodes(testContext, []*cstxproto.Node{external, internal}); err != nil || affected != 2 { t.Fatalf("add query option nodes: affected=%d err=%v", affected, err) } - collect := func(options QueryOptions) []string { + collect := func(query *cstxproto.GraphQuery) []string { t.Helper() - cursor, err := rt.Graph.Query(testContext, "domain", options) + cursor, err := rt.Graph.Query(testContext, query) if err != nil { - t.Fatalf("query with options %+v: %v", options, err) + t.Fatalf("query with options %+v: %v", query, err) } defer cursor.Close() limit := 1024 pageNumber := 1 - if options.Collection.Limit != nil { - limit = *options.Collection.Limit - pageNumber = options.Collection.Page + if query.Options != nil && query.Options.Window != nil && query.Options.Window.Limit != nil { + limit = int(*query.Options.Window.Limit) + pageNumber = int(query.Options.Window.Page) } page, err := cursor.Page(testContext, limit, pageNumber) if err != nil { - t.Fatalf("query cursor with options %+v: %v", options, err) - } - nodes, err := page.Nodes() - if err != nil { - t.Fatalf("decode query page: %v", err) + t.Fatalf("query cursor with options %+v: %v", query, err) } + nodes := page.GetNodes().GetValues() ids := make([]string, len(nodes)) for index, node := range nodes { - ids[index] = node.ID + ids[index] = node.GetId() } return ids } - one := 1 - if ids := collect(QueryOptions{Collection: CollectionOptions{Limit: &one, Page: 2}}); !reflect.DeepEqual(ids, []string{internal.ID}) { + one := uint64(1) + if ids := collect(&cstxproto.GraphQuery{Expression: "domain", Options: &cstxproto.QueryOptions{Window: &cstxproto.QueryWindow{Limit: &one, Page: 2}}}); !reflect.DeepEqual(ids, []string{internal.GetId()}) { t.Fatalf("second query page returned %v", ids) } - if ids := collect(QueryOptions{IncludeMask: FlagInternal}); !reflect.DeepEqual(ids, []string{internal.ID}) { + if ids := collect(&cstxproto.GraphQuery{Expression: "domain", Options: &cstxproto.QueryOptions{ResultFilter: &cstxproto.NodeFilter{FlagsAllMask: 1 << 6}}}); !reflect.DeepEqual(ids, []string{internal.GetId()}) { t.Fatalf("include-mask query returned %v", ids) } - if ids := collect(QueryOptions{ExcludeMask: FlagInternal}); !reflect.DeepEqual(ids, []string{external.ID}) { + if ids := collect(&cstxproto.GraphQuery{Expression: "domain", Options: &cstxproto.QueryOptions{ResultFilter: &cstxproto.NodeFilter{FlagsNoneMask: 1 << 6}}}); !reflect.DeepEqual(ids, []string{external.GetId()}) { t.Fatalf("exclude-mask query returned %v", ids) } } @@ -620,20 +618,23 @@ func TestRepositoryRoundTrip(t *testing.T) { rt := openRuntime(t) addDomain(t, rt, "example.com") - commit, err := rt.Repo.Commit(testContext, "initial", "main", nil, map[string]any{"origin": "test"}) + commit, err := rt.Repo.Commit(testContext, "initial", "main", nil, &structpb.Struct{Fields: map[string]*structpb.Value{"origin": structpb.NewStringValue("test")}}) if err != nil { t.Fatalf("commit: %v", err) } - if commit.ID == "" { + if commit.Id == "" { t.Fatalf("unexpected commit: %+v", commit) } + if commit.Metadata.GetFields()["origin"].GetStringValue() != "test" { + t.Fatalf("commit metadata: %#v", commit.Metadata) + } head, err := rt.Repo.Head(testContext, "main") - if err != nil || head == nil || *head != commit.ID { + if err != nil || head == nil || *head != commit.Id { t.Fatalf("head: %v %v", head, err) } resolved, err := rt.Repo.Resolve(testContext, "main") - if err != nil || resolved != commit.ID { + if err != nil || resolved != commit.Id { t.Fatalf("resolve: %s %v", resolved, err) } if _, err := rt.Repo.Branch(testContext, "initial", "main"); err != nil { @@ -641,27 +642,27 @@ func TestRepositoryRoundTrip(t *testing.T) { } addDomain(t, rt, "www.example.com") - second, err := rt.Repo.Commit(testContext, "second", "main", &commit.ID, nil) + second, err := rt.Repo.Commit(testContext, "second", "main", &commit.Id, nil) if err != nil { t.Fatalf("second commit: %v", err) } - diff, err := rt.Repo.Diff(testContext, commit.ID, second.ID, DiffOptions{}) - if err != nil || len(diff.Added["domain"]) != 1 || diff.Stats.AddedNodes != 1 { + diff, err := rt.Repo.Diff(testContext, commit.Id, second.Id, nil, cstxproto.DiffDetail_DIFF_DETAIL_ENTITIES) + if err != nil || len(diff.Added.NodeIds) != 1 || diff.Stats.AddedNodes != 1 { t.Fatalf("diff: %+v %v", diff, err) } - counted, err := rt.Repo.Diff(testContext, commit.ID, second.ID, DiffOptions{Detail: DiffCounts}) - if err != nil || counted.Stats.AddedNodes != 1 || len(counted.Added) != 0 { + counted, err := rt.Repo.Diff(testContext, commit.Id, second.Id, nil, cstxproto.DiffDetail_DIFF_DETAIL_COUNTS) + if err != nil || counted.Stats.AddedNodes != 1 || len(counted.Added.NodeIds) != 0 { t.Fatalf("counted diff: %+v %v", counted, err) } log, err := rt.Repo.Log(testContext, "main", 10) - if err != nil || len(log) != 2 { + if err != nil || len(log.Commits) != 2 { t.Fatalf("log: %+v %v", log, err) } history, err := rt.Repo.History(testContext, "domain:www.example.com", "main", nil) - if err != nil || len(history.Entries) != 1 { + if err != nil || len(history.Changes) != 1 { t.Fatalf("history: %+v %v", history, err) } - if stat, err := rt.Repo.Stat(testContext, "main", 0, 0); err != nil || stat.Nodes["domain"] != 2 { + if stat, err := rt.Repo.Stat(testContext, "main", 0, 0); err != nil || stat.NodesByType["domain"] != 2 { t.Fatalf("stat: %+v %v", stat, err) } if _, err := rt.Repo.Delta(testContext, "main", nil, nil); err != nil { @@ -686,7 +687,7 @@ func TestLastChange(t *testing.T) { if err != nil { t.Fatalf("last change: %v", err) } - if len(change.AddedNodeIDs) != 1 || change.Affected() != 1 { + if len(change.AddedNodeIds) != 1 || Affected(change) != 1 { t.Fatalf("unexpected change set: %+v", change) } } @@ -700,7 +701,7 @@ func TestServicesAndCursorsHonorCanceledContext(t *testing.T) { t.Fatalf("expected canceled service call, got %v", err) } - cursor, err := rt.Graph.Nodes(testContext, NodeFilter{}, CollectionOptions{}) + cursor, err := rt.Graph.Nodes(testContext, &cstxproto.NodeQuery{}) if err != nil { t.Fatalf("nodes: %v", err) } @@ -711,69 +712,85 @@ func TestServicesAndCursorsHonorCanceledContext(t *testing.T) { } func TestConformanceFixtureMatchesGoContract(t *testing.T) { - var fixture struct { - Schema struct { - NodeType string `json:"node_type"` - JSONSchema map[string]any `json:"json_schema"` - ValueField string `json:"value_field"` - } `json:"schema"` - Nodes []Node `json:"nodes"` - Edges []Edge `json:"edges"` - Query string `json:"query"` - Expected struct { - NodeIDs []string `json:"node_ids"` - NodeCount uint64 `json:"node_count"` - EdgeCount uint64 `json:"edge_count"` - } `json:"expected"` - } - if err := json.Unmarshal(conformanceFixture, &fixture); err != nil { - t.Fatalf("decode fixture: %v", err) - } - - rt, err := Open(testContext, Config{}) + // Rust and Python run this same file and assert the same ids, counts and + // query result. That only means something if all three use it as written: + // this used to decode the fixture's schema and then overwrite every field + // of it with easm's `domain`, so what it actually checked was easm. + fixture := loadConformanceFixture(t) + + rt, err := Open(testContext, &cstxproto.RuntimeConfig{}) if err != nil { t.Fatalf("open: %v", err) } defer rt.Close() - if err := rt.Schemas.Register( - testContext, - fixture.Schema.NodeType, - fixture.Schema.JSONSchema, - fixture.Schema.ValueField, - ); err != nil { + contract := newExtensionBuilder("conformance", "1.0"). + Schema(string(fixture.Document)).Build() + if err := rt.Extensions.Register(testContext, contract); err != nil { t.Fatalf("register: %v", err) } - if _, err := rt.Graph.AddNodes(testContext, fixture.Nodes); err != nil { + + nodes := make([]*cstxproto.Node, 0, len(fixture.Nodes)) + for _, item := range fixture.Nodes { + entity := &cstxproto.EntityValue{NodeType: item.Type} + for _, name := range sortedKeys(item.Model) { + entity.Fields = append(entity.Fields, &cstxproto.EntityField{ + Name: name, + Value: &cstxproto.EntityField_Text{Text: item.Model[name]}, + }) + } + id := item.ID + nodes = append(nodes, &cstxproto.Node{ + Id: &id, Sources: item.Sources, Value: entity, + }) + } + if _, err := rt.Graph.AddNodes(testContext, nodes); err != nil { t.Fatalf("add nodes: %v", err) } - if _, err := rt.Graph.AddEdges(testContext, fixture.Edges); err != nil { - t.Fatalf("add edges: %v", err) + + var document struct { + Relations map[string]struct { + Message string `json:"message"` + } `json:"relations"` + } + if err := json.Unmarshal(fixture.Document, &document); err != nil { + t.Fatalf("document: %v", err) } + edges := make([]*cstxproto.Relationship, 0, len(fixture.Relationships)) + for _, item := range fixture.Relationships { + id := item.ID + edges = append(edges, &cstxproto.Relationship{ + Id: &id, SourceId: item.SourceID, TargetId: item.TargetID, + Sources: item.Sources, + // A relation type is a field-less marker: the document names it and + // the payload carries nothing else. + Value: &cstxproto.RelationshipValue{RelationshipType: item.Type}, + }) + } + if _, err := rt.Graph.AddRelationships(testContext, edges); err != nil { + t.Fatalf("add relationships: %v", err) + } + if count, err := rt.Graph.NodeCount(testContext); err != nil || count != fixture.Expected.NodeCount { t.Fatalf("node count: got %d err=%v", count, err) } - if count, err := rt.Graph.EdgeCount(testContext); err != nil || count != fixture.Expected.EdgeCount { - t.Fatalf("edge count: got %d err=%v", count, err) + if count, err := rt.Graph.RelationshipCount(testContext); err != nil || count != fixture.Expected.RelationshipCount { + t.Fatalf("relationship count: got %d err=%v", count, err) } - cursor, err := rt.Graph.Query(testContext, fixture.Query, QueryOptions{}) + cursor, err := rt.Graph.Query(testContext, &cstxproto.GraphQuery{Expression: fixture.Query}) if err != nil { t.Fatalf("query: %v", err) } defer cursor.Close() - page, err := cursor.Page(testContext, 1024, 1) - if err != nil { - t.Fatalf("page query: %v", err) - } - nodes, err := page.Nodes() + page, err := cursor.Page(testContext, 100, 1) if err != nil { - t.Fatalf("decode query: %v", err) + t.Fatalf("page: %v", err) } - ids := make([]string, len(nodes)) - for index, node := range nodes { - ids[index] = node.ID + ids := make([]string, 0, len(page.GetNodes().GetValues())) + for _, node := range page.GetNodes().GetValues() { + ids = append(ids, node.GetId()) } - if stringSliceMismatch(ids, fixture.Expected.NodeIDs) { - t.Fatalf("query IDs: got %v want %v", ids, fixture.Expected.NodeIDs) + if !reflect.DeepEqual(ids, fixture.Expected.NodeIDs) { + t.Fatalf("query ids = %v; want %v", ids, fixture.Expected.NodeIDs) } } diff --git a/go/cstx_test.go b/go/cstx_test.go index 756e5dc..daa3332 100644 --- a/go/cstx_test.go +++ b/go/cstx_test.go @@ -1,94 +1,32 @@ package cstx import ( - "encoding/json" "testing" -) - -func TestConfigNormalize(t *testing.T) { - cfg := Config{}.normalize() - if cfg.ProjectID != "default" { - t.Fatalf("project id: %q", cfg.ProjectID) - } - if cfg.CursorPageSize != DefaultCursorPageSize { - t.Fatalf("page size: %d", cfg.CursorPageSize) - } -} - -func TestNodeMarshalKeepsEmptyLists(t *testing.T) { - data, err := json.Marshal(Node{ID: "n1", Type: "Domain", Value: "example.com"}) - if err != nil { - t.Fatal(err) - } - var decoded map[string]any - if err := json.Unmarshal(data, &decoded); err != nil { - t.Fatal(err) - } - for _, field := range []string{"sources", "model", "extras"} { - if decoded[field] == nil { - t.Fatalf("field %s must not be null: %s", field, data) - } - } -} - -func TestEdgeFilterNullIDs(t *testing.T) { - data, err := json.Marshal(EdgeFilter{}) - if err != nil { - t.Fatal(err) - } - var decoded map[string]any - if err := json.Unmarshal(data, &decoded); err != nil { - t.Fatal(err) - } - for _, field := range []string{"source_id", "target_id"} { - value, present := decoded[field] - if !present || value != nil { - t.Fatalf("field %s must be explicit null: %s", field, data) - } - } - for _, field := range []string{"relations", "sources"} { - if decoded[field] == nil { - t.Fatalf("field %s must be []: %s", field, data) - } - } -} -func TestCollectionOptionsNormalize(t *testing.T) { - options := CollectionOptions{}.normalize() - if options.Page != 1 || options.Order != OrderUnspecified { - t.Fatalf("unexpected defaults: %+v", options) - } -} + "github.com/chainreactors/libcstx/go/proto/cstxproto" +) -func TestRefUnmarshalTuple(t *testing.T) { - var refs []Ref - if err := json.Unmarshal([]byte(`[["main","abc123"],["dev","def456"]]`), &refs); err != nil { - t.Fatal(err) +func TestRuntimeConfigNormalize(t *testing.T) { + cfg := normalizeRuntimeConfig(&cstxproto.RuntimeConfig{}) + if cfg.projectID != "default" { + t.Fatalf("project id: %q", cfg.projectID) } - if len(refs) != 2 || refs[0].Name != "main" || refs[0].Head != "abc123" { - t.Fatalf("unexpected refs: %+v", refs) + if cfg.cursorPageSize != DefaultCursorPageSize { + t.Fatalf("page size: %d", cfg.cursorPageSize) } } func TestParseErrorRoundTrip(t *testing.T) { - raw := []byte(`{"code":"NOT_FOUND","operation":"graph.node","item_index":null,"field":"node_id","message":"missing","expected":null,"actual":null}`) - cerr := parseError(raw, CodeInternal) - if cerr.Code != CodeNotFound || cerr.Operation != "graph.node" || cerr.Field != "node_id" { + raw := []byte("missing") + cerr := parseError(raw, CodeNotFound) + if cerr.Code != CodeNotFound || cerr.Message != "missing" || !IsCode(cerr, CodeNotFound) { t.Fatalf("unexpected error: %+v", cerr) } - if !IsCode(cerr, CodeNotFound) { - t.Fatal("IsCode mismatch") - } - - fallback := parseError([]byte("plain failure"), CodeIO) - if fallback.Code != CodeIO || fallback.Message != "plain failure" { - t.Fatalf("unexpected fallback: %+v", fallback) - } } -func TestChangeSetAffected(t *testing.T) { - change := ChangeSet{AddedNodeIDs: []string{"a"}, UpdatedEdgeIDs: []string{"b", "c"}} - if change.Affected() != 3 { - t.Fatalf("affected: %d", change.Affected()) +func TestAffected(t *testing.T) { + change := &cstxproto.GraphChangeSet{AddedNodeIds: []string{"a"}, UpdatedRelationshipIds: []string{"b", "c"}} + if got := Affected(change); got != 3 { + t.Fatalf("affected: %d", got) } } diff --git a/go/cursor.go b/go/cursor.go index 335ed6b..76a6dfb 100644 --- a/go/cursor.go +++ b/go/cursor.go @@ -2,59 +2,25 @@ package cstx import ( "context" - "encoding/json" - "fmt" + + "github.com/chainreactors/libcstx/go/proto/cstxproto" ) // CursorKind identifies the row shape returned by a GraphCursor. type CursorKind string const ( - CursorKindNodes CursorKind = "nodes" - CursorKindEdges CursorKind = "edges" - CursorKindComponents CursorKind = "components" - CursorKindNodeScores CursorKind = "node_scores" - CursorKindNodePairs CursorKind = "node_pairs" - CursorKindCycles CursorKind = "cycles" - CursorKindPaths CursorKind = "paths" - CursorKindCommunities CursorKind = "communities" + CursorKindNodes CursorKind = "nodes" + CursorKindRelationships CursorKind = "relationships" + CursorKindComponents CursorKind = "components" + CursorKindNodeScores CursorKind = "node_scores" + CursorKindNodePairs CursorKind = "node_pairs" + CursorKindCycles CursorKind = "cycles" + CursorKindPaths CursorKind = "paths" + CursorKindCommunities CursorKind = "communities" ) -// CursorPage is one bounded, one-based page from a native graph result. -// Items stay as raw JSON until the caller chooses the domain type, avoiding a -// second in-memory graph or eager decoding of rows outside the requested page. -type CursorPage struct { - Items []json.RawMessage `json:"items"` - Page int `json:"page"` - Limit int `json:"limit"` - HasNext bool `json:"has_next"` - Total *uint64 `json:"total,omitempty"` - Summary json.RawMessage `json:"summary,omitempty"` -} - -// Nodes decodes this page as CSTX nodes. -func (p CursorPage) Nodes() ([]Node, error) { - items := make([]Node, len(p.Items)) - for index, item := range p.Items { - if err := json.Unmarshal(item, &items[index]); err != nil { - return nil, fmt.Errorf("cstx: decode node at page index %d: %w", index, err) - } - } - return items, nil -} - -// Edges decodes this page as CSTX relationships. -func (p CursorPage) Edges() ([]Edge, error) { - items := make([]Edge, len(p.Items)) - for index, item := range p.Items { - if err := json.Unmarshal(item, &items[index]); err != nil { - return nil, fmt.Errorf("cstx: decode edge at page index %d: %w", index, err) - } - } - return items, nil -} - -// GraphCursor is the single cursor type for nodes, edges, queries and graph +// GraphCursor is the single cursor type for nodes, relationships, queries and graph // analysis results. Page uses a one-based page number and never reruns the // operation that created the cursor. type GraphCursor struct { @@ -66,13 +32,15 @@ type GraphCursor struct { // Kind returns the logical row shape emitted by this cursor. func (c *GraphCursor) Kind() CursorKind { return c.kind } -// Page materializes one bounded page. -func (c *GraphCursor) Page(ctx context.Context, limit, page int) (CursorPage, error) { +// Page returns the generated protobuf page from the native boundary. The +// caller can inspect the result oneof directly, avoiding an intermediate DTO +// and any JSON conversion. +func (c *GraphCursor) Page(ctx context.Context, limit, page int) (*cstxproto.GraphResultPage, error) { if c.done || c.inner == nil { - return CursorPage{}, &Error{Code: CodeInvalidArgument, Operation: "cursor.page", Message: "cursor is closed"} + return nil, &Error{Code: CodeInvalidArgument, Operation: "cursor.page", Message: "cursor is closed"} } if err := contextError(ctx); err != nil { - return CursorPage{}, err + return nil, err } return c.inner.page(ctx, limit, page) } diff --git a/go/doc.go b/go/doc.go index c49718f..f272ab8 100644 --- a/go/doc.go +++ b/go/doc.go @@ -2,8 +2,8 @@ // // The Rust core is the sole owner of graph, repository, validation, // and ingest semantics (issue #6). This package only converts between Go -// domain values and the JSON transport used by the cstx-ffi C boundary; it -// never reimplements business behavior. +// domain values and the protobuf transport used by the cstx-ffi C boundary; +// it never reimplements business behavior. // // The engine behind Open always uses the bundled cstx-ffi static library. // Consumers therefore build this package with CGO enabled. Prebuilt libraries diff --git a/go/dynamic_conformance_test.go b/go/dynamic_conformance_test.go new file mode 100644 index 0000000..90fe2b6 --- /dev/null +++ b/go/dynamic_conformance_test.go @@ -0,0 +1,245 @@ +package cstx + +import ( + "context" + "encoding/json" + "reflect" + "sort" + "strings" + "testing" + + "github.com/chainreactors/libcstx/go/proto/cstxproto" +) + +// One field as the shared fixture's schema document declares it. +type declaredField struct { + Name string `json:"name"` + Type string `json:"type"` + Repeated bool `json:"repeated"` +} + +type dynamicFixture struct { + Document json.RawMessage `json:"document"` + // Raw, so it can be decoded with UseNumber: one of the fixture's int64 + // values is outside what a float64 can hold, and that is why it is there. + RawValues json.RawMessage `json:"values"` + ExpectedID string `json:"expected_id"` + Relation struct { + RelationType string `json:"type"` + TypeURL string `json:"type_url"` + } `json:"relation"` +} + +// fixtureValues converts the fixture's JSON into the Go types the schema's +// columns hold. The document says which type each field is, so nothing here +// guesses — and the conversion is what proves Go and Python agree about it. +func fixtureValues(t *testing.T, fixture dynamicFixture) NodeValues { + t.Helper() + var document struct { + Nodes map[string]struct { + Fields []declaredField `json:"fields"` + } `json:"nodes"` + } + if err := json.Unmarshal(fixture.Document, &document); err != nil { + t.Fatalf("document: %v", err) + } + declared := map[string]declaredField{} + for _, field := range document.Nodes["acme_asset"].Fields { + declared[field.Name] = field + } + + decoder := json.NewDecoder(strings.NewReader(string(fixture.RawValues))) + decoder.UseNumber() + raw := map[string]any{} + if err := decoder.Decode(&raw); err != nil { + t.Fatalf("values: %v", err) + } + + values := NodeValues{} + for name, value := range raw { + field, ok := declared[name] + if !ok { + t.Fatalf("fixture value %q is not declared by the document", name) + } + switch { + case field.Repeated: + items := value.([]any) + list := make([]string, 0, len(items)) + for _, item := range items { + list = append(list, item.(string)) + } + values[name] = list + case field.Type == "bool": + values[name] = value.(bool) + case field.Type == "string": + values[name] = value.(string) + case field.Type == "double" || field.Type == "float": + real, err := value.(json.Number).Float64() + if err != nil { + t.Fatalf("%s: %v", name, err) + } + values[name] = real + default: + number, err := value.(json.Number).Int64() + if err != nil { + t.Fatalf("%s: %v", name, err) + } + values[name] = number + } + } + return values +} + +func openDynamicRuntime(t *testing.T, fixture dynamicFixture) *CSTX { + t.Helper() + runtime, err := Open(context.Background(), &cstxproto.RuntimeConfig{ + ProjectId: "go-dyn-conformance", + }) + if err != nil { + t.Fatalf("open: %v", err) + } + t.Cleanup(func() { runtime.Close() }) + contract := newExtensionBuilder("acme", "1.0").Schema(string(fixture.Document)).Build() + if err := runtime.Extensions.Register(context.Background(), contract); err != nil { + t.Fatalf("register: %v", err) + } + return runtime +} + +func loadDynamicFixture(t *testing.T) dynamicFixture { + t.Helper() + var fixture struct { + DynamicExtension dynamicFixture `json:"dynamic_extension"` + } + if err := json.Unmarshal(conformanceFixture, &fixture); err != nil { + t.Fatalf("fixture: %v", err) + } + return fixture.DynamicExtension +} + +// The shared fixture's runtime-declared type, written and read from Go. +// +// The point of the fixture being shared is that Python runs the same document +// and the same values through its own SDK and asserts the same id and the same +// values. Neither language has a generated message type for `acme.Asset`, and +// neither can: the type is declared by a document that ships as test data. +// +// Its fields cover every proto type a schema document may declare, so a column +// that cannot survive the trip fails here rather than the first time a plugin +// uses it. +func TestDynamicExtensionConformance(t *testing.T) { + ctx := context.Background() + fixture := loadDynamicFixture(t) + runtime := openDynamicRuntime(t, fixture) + values := fixtureValues(t, fixture) + + if _, err := runtime.Graph.AddNodeValues(ctx, "acme_asset", values); err != nil { + t.Fatalf("add_node_values: %v", err) + } + + node, err := runtime.Graph.Node(ctx, fixture.ExpectedID) + if err != nil { + t.Fatalf("node %q: %v", fixture.ExpectedID, err) + } + nodeType, read, err := FieldValues(node) + if err != nil { + t.Fatalf("field values: %v", err) + } + if nodeType != "acme_asset" { + t.Fatalf("node_type = %q", nodeType) + } + if !reflect.DeepEqual(read, values) { + t.Fatalf("read back %#v; want %#v", read, values) + } +} + +// A relation type declared by the same document, with no generated code. +// +// A relation carries no payload — the document declares that the type exists +// and which message names it, and the bytes are empty. The write uses that +// type URL; this runtime is configured for the semantic value spelling, so +// the read must resolve it back to the declared relationship type. +func TestDynamicExtensionRelationRoundTrips(t *testing.T) { + ctx := context.Background() + fixture := loadDynamicFixture(t) + runtime := openDynamicRuntime(t, fixture) + values := fixtureValues(t, fixture) + + other := NodeValues{"asset_id": "a-2"} + for _, payload := range []NodeValues{values, other} { + if _, err := runtime.Graph.AddNodeValues(ctx, "acme_asset", payload); err != nil { + t.Fatalf("add_node_values: %v", err) + } + } + + edge := &cstxproto.Relationship{ + SourceId: fixture.ExpectedID, + TargetId: "acme_asset:a-2", + Sources: []string{"test"}, + Value: &cstxproto.RelationshipValue{RelationshipType: fixture.Relation.RelationType}, + } + if _, err := runtime.Graph.AddRelationships(ctx, []*cstxproto.Relationship{edge}); err != nil { + t.Fatalf("add_relationships: %v", err) + } + + cursor, err := runtime.Graph.Relationships(ctx, &cstxproto.RelationshipQuery{}) + if err != nil { + t.Fatalf("relationships: %v", err) + } + defer cursor.Close() + page, err := cursor.Page(ctx, 10, 1) + if err != nil { + t.Fatalf("page: %v", err) + } + stored := page.GetRelationships().GetValues() + if len(stored) != 1 { + t.Fatalf("relationship count = %d; want 1", len(stored)) + } + if got := stored[0].GetValue().GetRelationshipType(); got != fixture.Relation.RelationType { + t.Fatalf("relationship type = %q; want %q", got, fixture.Relation.RelationType) + } +} + +// conformanceFixture is the whole shared file, as the three languages read it. +type conformanceFile struct { + Document json.RawMessage `json:"document"` + Nodes []struct { + ID string `json:"id"` + Type string `json:"type"` + Model map[string]string `json:"model"` + Sources []string `json:"sources"` + } `json:"nodes"` + Relationships []struct { + ID string `json:"id"` + SourceID string `json:"source_id"` + TargetID string `json:"target_id"` + Type string `json:"type"` + Sources []string `json:"sources"` + } `json:"relationships"` + Query string `json:"query"` + Expected struct { + NodeIDs []string `json:"node_ids"` + NodeCount uint64 `json:"node_count"` + RelationshipCount uint64 `json:"relationship_count"` + } `json:"expected"` +} + +func loadConformanceFixture(t *testing.T) conformanceFile { + t.Helper() + var fixture conformanceFile + if err := json.Unmarshal(conformanceFixture, &fixture); err != nil { + t.Fatalf("fixture: %v", err) + } + return fixture +} + +// sortedKeys keeps one map producing one message: Go randomizes map iteration, +// and a node's payload is content, not a bag. +func sortedKeys(values map[string]string) []string { + names := make([]string, 0, len(values)) + for name := range values { + names = append(names, name) + } + sort.Strings(names) + return names +} diff --git a/go/engine.go b/go/engine.go index 0e13433..729e75b 100644 --- a/go/engine.go +++ b/go/engine.go @@ -1,6 +1,11 @@ package cstx -import "context" +import ( + "context" + + "github.com/chainreactors/libcstx/go/proto/cstxproto" + "google.golang.org/protobuf/types/known/structpb" +) // engine is the internal boundary between the typed facade and the transport // implementation. The native build implements it over the cstx-ffi C ABI; @@ -8,69 +13,60 @@ import "context" type engine interface { close() error - lastChange(context.Context) (ChangeSet, error) + lastChange(context.Context) (*cstxproto.GraphChangeSet, error) - schemaImport(context.Context, SchemaContract) error - schemaExport(context.Context) (SchemaContract, error) - schemaRegister(context.Context, string, map[string]any, string) error - schemaRegisterJoinRule(context.Context, JoinRuleSpec) error - schemaContains(context.Context, string) (bool, error) - schemaGet(context.Context, string) (map[string]any, error) - schemaList(context.Context) ([]map[string]any, error) - schemaLoadPlugin(context.Context, string) error - schemaLoadAllPlugins(context.Context) error - schemaAvailablePlugins(context.Context) ([]string, error) - schemaPluginArtifacts(context.Context, string) ([]string, error) - schemaHasNativeArtifact(context.Context, string) (bool, error) - schemaAnchorConcepts(context.Context) ([]AnchorConcept, error) + extensionRegister(context.Context, *cstxproto.ExtensionContract) error + extensionExportContract(context.Context) (cstxproto.ExtensionContract, error) + extensionEnable(context.Context, string) error + extensionList(context.Context) (*cstxproto.ExtensionCatalog, error) + extensionInfo(context.Context, string) (*cstxproto.ExtensionInfo, error) + extensionContains(context.Context, string) (bool, error) + extensionSchema(context.Context, string) (cstxproto.NodeType, error) + extensionSchemas(context.Context) (cstxproto.NodeTypeCatalog, error) + extensionParsesArtifact(context.Context, string) (bool, error) + extensionAnchorConcepts(context.Context) (cstxproto.AnchorConceptCatalog, error) - graphAddNodes(context.Context, []Node) (uint64, error) - graphReplaceNodes(context.Context, []Node) (uint64, error) - graphAddEdges(context.Context, []Edge) (uint64, error) + graphAddNodes(context.Context, []*cstxproto.Node) (uint64, error) + graphReplaceNodes(context.Context, []*cstxproto.Node) (uint64, error) + graphAddRelationships(context.Context, []*cstxproto.Relationship) (uint64, error) + graphAddRelationship(context.Context, *cstxproto.Relationship) (*cstxproto.Relationship, error) graphDeleteNodes(context.Context, []string) (uint64, error) - graphDeleteEdges(context.Context, []string) (uint64, error) - graphIngest(context.Context, string, []byte) (uint64, error) - graphNode(context.Context, string) (Node, error) + graphDeleteRelationships(context.Context, []string) (uint64, error) + graphNode(context.Context, string) (*cstxproto.Node, error) + graphRelationship(context.Context, string) (*cstxproto.Relationship, error) graphContains(context.Context, string) (bool, error) graphNodeCount(context.Context) (uint64, error) - graphEdgeCount(context.Context) (uint64, error) - graphStats(context.Context) (GraphStats, error) - graphNodes(context.Context, NodeFilter, CollectionOptions) (graphCursor, error) - graphEdges(context.Context, EdgeFilter, CollectionOptions) (graphCursor, error) - graphNeighbors(context.Context, string, string, CollectionOptions) (graphCursor, error) - graphQuery(context.Context, string, QueryOptions) (graphCursor, error) - graphAnalyze(context.Context, any, *string) (uint8, bool, graphCursor, error) + graphRelationshipCount(context.Context) (uint64, error) + graphStats(context.Context) (*cstxproto.GraphStats, error) + graphNodes(context.Context, *cstxproto.NodeQuery) (graphCursor, error) + graphRelationships(context.Context, *cstxproto.RelationshipQuery) (graphCursor, error) + graphNeighbors(context.Context, *cstxproto.NeighborQuery) (graphCursor, error) + graphQuery(context.Context, *cstxproto.GraphQuery) (graphCursor, error) + graphAnalyze(context.Context, *cstxproto.Algorithm, *string) (uint8, bool, graphCursor, error) graphSubgraph(context.Context, []string, uint32) (engine, error) repoResolve(context.Context, string) (string, error) repoHead(context.Context, string) (*string, error) - repoCheckout(context.Context, string, bool) (Commit, error) - repoCommit(context.Context, string, string, *string, any) (Commit, error) - repoPrepare(context.Context, string, string, *string, any, *int64) (PreparedCommit, error) + repoCheckout(context.Context, string, bool) (*cstxproto.Commit, error) + repoCommit(context.Context, string, string, *string, *structpb.Struct) (*cstxproto.Commit, error) + repoPrepare(context.Context, string, string, *string, *structpb.Struct, *int64) (*cstxproto.PublicationPlan, error) repoAccept(context.Context, string) error repoDiscard(context.Context) error - repoSynchronize(context.Context, RepositorySync) error + repoSynchronize(context.Context, *cstxproto.RepositoryState) error repoContains(context.Context, string) (bool, error) - repoMissingTree(context.Context, string) ([]string, error) - repoObjectClosure(context.Context, string) ([]string, error) - repoMissingPrepare(context.Context, string) ([]string, error) - repoMissingHistory(context.Context, string, string) ([]string, error) - repoMissingStat(context.Context, string) ([]string, error) - repoMissingCommits(context.Context, string, int) ([]string, error) - repoMissingDiff(context.Context, string, string, DiffDetail) ([]string, error) - repoMissingDelta(context.Context, string, *int64, *int64) ([]string, error) - repoMissingMerge(context.Context, string, string) ([]string, error) + repoMissing(context.Context, *cstxproto.RepositoryObjectPlan) (*cstxproto.ObjectSelection, error) repoReleaseTransientObjects(context.Context) error - repoDiff(context.Context, string, string, DiffOptions) (GraphDiff, error) - repoLog(context.Context, string, int) ([]map[string]any, error) - repoHistory(context.Context, string, string, *int) ([]map[string]any, error) + repoDiff(context.Context, string, string, *uint64, cstxproto.DiffDetail) (*cstxproto.GraphDiff, error) + repoLog(context.Context, string, int) (*cstxproto.CommitLog, error) + repoEntities(context.Context, string, []string) (*cstxproto.Graph, error) + repoHistory(context.Context, string, string, *int) (*cstxproto.EntityHistory, error) repoBranch(context.Context, string, string) (string, error) - repoMerge(context.Context, string, string, *string, *string) (Commit, error) - repoStat(context.Context, string, uint64, uint64) (GraphStats, error) - repoDelta(context.Context, string, *int64, *int64) (Delta, error) + repoMerge(context.Context, string, string, *string, *string) (*cstxproto.Commit, error) + repoStat(context.Context, string, uint64, uint64) (*cstxproto.GraphStats, error) + repoDelta(context.Context, string, *int64, *int64) (*cstxproto.GraphChangeSummary, error) } type graphCursor interface { - page(context.Context, int, int) (CursorPage, error) + page(context.Context, int, int) (*cstxproto.GraphResultPage, error) close() } diff --git a/go/engine_native.go b/go/engine_native.go index c435763..ef18ae6 100644 --- a/go/engine_native.go +++ b/go/engine_native.go @@ -13,20 +13,23 @@ import "C" import ( "context" - "encoding/hex" - "encoding/json" + "fmt" "runtime" "unsafe" + + "github.com/chainreactors/libcstx/go/proto/cstxproto" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/structpb" ) type nativeEngine struct { handle *C.CstxHandle } -func newEngine(config Config) (engine, error) { - payload, err := json.Marshal(map[string]any{ - "project_id": config.ProjectID, - "cursor_page_size": config.CursorPageSize, +func newEngine(config runtimeConfig) (engine, error) { + payload, err := proto.Marshal(&cstxproto.RuntimeConfig{ + ProjectId: config.projectID, + CursorPageSize: uint64(config.cursorPageSize), }) if err != nil { return nil, err @@ -57,7 +60,7 @@ func (e *nativeEngine) close() error { } func (e *nativeEngine) graphSubgraph(_ context.Context, seedIDs []string, depth uint32) (engine, error) { - payload, err := json.Marshal(seedIDs) + payload, err := proto.Marshal(&cstxproto.GraphSelection{NodeIds: seedIDs}) if err != nil { return nil, err } @@ -76,7 +79,7 @@ func (e *nativeEngine) graphSubgraph(_ context.Context, seedIDs []string, depth } func (e *nativeEngine) graphDeleteNodes(_ context.Context, nodeIDs []string) (uint64, error) { - payload, err := marshalInput("graph.delete_nodes", nodeIDs) + payload, err := proto.Marshal(&cstxproto.GraphSelection{NodeIds: nodeIDs}) if err != nil { return 0, err } @@ -87,13 +90,13 @@ func (e *nativeEngine) graphDeleteNodes(_ context.Context, nodeIDs []string) (ui }) } -func (e *nativeEngine) graphDeleteEdges(_ context.Context, edgeIDs []string) (uint64, error) { - payload, err := marshalInput("graph.delete_edges", edgeIDs) +func (e *nativeEngine) graphDeleteRelationships(_ context.Context, relationshipIDs []string) (uint64, error) { + payload, err := proto.Marshal(&cstxproto.GraphSelection{RelationshipIds: relationshipIDs}) if err != nil { return 0, err } - return countResult("graph.delete_edges", func(out *C.uint64_t, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_graph_delete_edges(e.handle, byteSlice(payload), out, errBuf) + return countResult("graph.delete_relationships", func(out *C.uint64_t, errBuf *C.CstxBuffer) C.CstxStatusCode { + rc := C.cstx_graph_delete_relationships(e.handle, byteSlice(payload), out, errBuf) runtime.KeepAlive(payload) return rc }) @@ -101,8 +104,6 @@ func (e *nativeEngine) graphDeleteEdges(_ context.Context, edgeIDs []string) (ui // --- C transport helpers ------------------------------------------------- -var emptySliceByte byte - func byteSlice(value []byte) C.CstxSlice { if len(value) == 0 { return C.CstxSlice{} @@ -185,17 +186,6 @@ func statusCall(op string, call func(errBuf *C.CstxBuffer) C.CstxStatusCode) err return statusError(call(&errBuf), op, &errBuf) } -// jsonResult runs a call whose success output is a JSON buffer and decodes it -// into result. -func jsonResult(op string, result any, call func(out, errBuf *C.CstxBuffer) C.CstxStatusCode) error { - var out, errBuf C.CstxBuffer - if err := statusError(call(&out, &errBuf), op, &errBuf); err != nil { - C.cstx_buffer_free(&out) - return err - } - return json.Unmarshal(takeBuffer(&out), result) -} - func bufferResult(op string, call func(out, errBuf *C.CstxBuffer) C.CstxStatusCode) ([]byte, error) { var out, errBuf C.CstxBuffer if err := statusError(call(&out, &errBuf), op, &errBuf); err != nil { @@ -205,6 +195,14 @@ func bufferResult(op string, call func(out, errBuf *C.CstxBuffer) C.CstxStatusCo return takeBuffer(&out), nil } +func textResult(op string, call func(out, errBuf *C.CstxBuffer) C.CstxStatusCode) (string, error) { + data, err := bufferResult(op, call) + if err != nil { + return "", err + } + return string(data), nil +} + func countResult(op string, call func(out *C.uint64_t, errBuf *C.CstxBuffer) C.CstxStatusCode) (uint64, error) { var out C.uint64_t var errBuf C.CstxBuffer @@ -230,201 +228,182 @@ func boolByte(value bool) uint8 { return 0 } -func marshal(value any) []byte { - data, err := json.Marshal(value) - if err != nil { - // All marshaled types are internal contracts; a failure here is a bug. - panic("cstx: marshal transport value: " + err.Error()) - } - return data -} - -func marshalInput(op string, value any) ([]byte, error) { - data, err := json.Marshal(value) - if err != nil { - return nil, &Error{Code: CodeInvalidArgument, Operation: op, Message: err.Error()} - } - return data, nil -} - // --- runtime ------------------------------------------------------------- -func (e *nativeEngine) lastChange(_ context.Context) (ChangeSet, error) { - var change ChangeSet - err := jsonResult("cstx.last_change", &change, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - return C.cstx_last_change_json(e.handle, out, errBuf) +func (e *nativeEngine) lastChange(_ context.Context) (*cstxproto.GraphChangeSet, error) { + data, err := bufferResult("cstx.last_change", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { + return C.cstx_last_change(e.handle, out, errBuf) }) - return change, err + if err != nil { + return nil, err + } + var wire cstxproto.GraphChangeSet + if err := proto.Unmarshal(data, &wire); err != nil { + return nil, fmt.Errorf("cstx: decode change set protobuf: %w", err) + } + return &wire, nil } -// --- schemas ------------------------------------------------------------- +// --- extensions ---------------------------------------------------------- -func (e *nativeEngine) schemaImport(_ context.Context, contract SchemaContract) error { - payload, err := marshalInput("schemas.import_schema", contract) +func (e *nativeEngine) extensionRegister(_ context.Context, contract *cstxproto.ExtensionContract) error { + payload, err := proto.Marshal(contract) if err != nil { return err } - return statusCall("schemas.import_schema", func(errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_schema_import_schema(e.handle, byteSlice(payload), errBuf) + return statusCall("extensions.register", func(errBuf *C.CstxBuffer) C.CstxStatusCode { + rc := C.cstx_extension_register(e.handle, byteSlice(payload), errBuf) runtime.KeepAlive(payload) return rc }) } -func (e *nativeEngine) schemaExport(_ context.Context) (SchemaContract, error) { - var contract SchemaContract - err := jsonResult("schemas.export_schema", &contract, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - return C.cstx_schema_export_schema_json(e.handle, out, errBuf) +func (e *nativeEngine) extensionExportContract(_ context.Context) (cstxproto.ExtensionContract, error) { + data, err := bufferResult("extensions.export_contract", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { + return C.cstx_extension_export_contract(e.handle, out, errBuf) }) - return contract, err -} - -func (e *nativeEngine) schemaRegister(_ context.Context, nodeType string, schema map[string]any, valueField string) error { - payload, err := marshalInput("schemas.register", schema) if err != nil { - return err + return cstxproto.ExtensionContract{}, err } - return statusCall("schemas.register", func(errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_schema_register(e.handle, stringSlice(nodeType), byteSlice(payload), optionalStringSlice(valueField), errBuf) - runtime.KeepAlive(nodeType) - runtime.KeepAlive(payload) - runtime.KeepAlive(valueField) + var value cstxproto.ExtensionContract + if err := proto.Unmarshal(data, &value); err != nil { + return cstxproto.ExtensionContract{}, fmt.Errorf("cstx: decode extensions.export_contract protobuf: %w", err) + } + return value, nil +} + +func (e *nativeEngine) extensionEnable(_ context.Context, name string) error { + return statusCall("extensions.enable", func(errBuf *C.CstxBuffer) C.CstxStatusCode { + rc := C.cstx_extension_enable(e.handle, stringSlice(name), errBuf) + runtime.KeepAlive(name) return rc }) } -func (e *nativeEngine) schemaRegisterJoinRule(_ context.Context, rule JoinRuleSpec) error { - payload, err := marshalInput("schemas.register_join_rule", rule) +func (e *nativeEngine) extensionList(_ context.Context) (*cstxproto.ExtensionCatalog, error) { + data, err := bufferResult("extensions.list", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { return C.cstx_extension_list(e.handle, out, errBuf) }) if err != nil { - return err + return nil, err } - return statusCall("schemas.register_join_rule", func(errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_schema_register_join_rule(e.handle, byteSlice(payload), errBuf) - runtime.KeepAlive(payload) - return rc - }) + var value cstxproto.ExtensionCatalog + if err := proto.Unmarshal(data, &value); err != nil { + return nil, err + } + return &value, nil } -func (e *nativeEngine) schemaContains(_ context.Context, nodeType string) (bool, error) { - return boolResult("schemas.contains", func(out *C.uint8_t, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_schema_contains(e.handle, stringSlice(nodeType), out, errBuf) - runtime.KeepAlive(nodeType) +func (e *nativeEngine) extensionInfo(_ context.Context, name string) (*cstxproto.ExtensionInfo, error) { + data, err := bufferResult("extensions.info", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { + rc := C.cstx_extension_info(e.handle, stringSlice(name), out, errBuf) + runtime.KeepAlive(name) return rc }) + if err != nil { + return nil, err + } + var value cstxproto.ExtensionInfo + if err := proto.Unmarshal(data, &value); err != nil { + return nil, err + } + return &value, nil } -func (e *nativeEngine) schemaGet(_ context.Context, nodeType string) (map[string]any, error) { - var schema map[string]any - err := jsonResult("schemas.get", &schema, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_schema_get_json(e.handle, stringSlice(nodeType), out, errBuf) +func (e *nativeEngine) extensionContains(_ context.Context, nodeType string) (bool, error) { + return boolResult("extensions.contains", func(out *C.uint8_t, errBuf *C.CstxBuffer) C.CstxStatusCode { + rc := C.cstx_extension_contains(e.handle, stringSlice(nodeType), out, errBuf) runtime.KeepAlive(nodeType) return rc }) - return schema, err -} - -func (e *nativeEngine) schemaList(_ context.Context) ([]map[string]any, error) { - var schemas []map[string]any - err := jsonResult("schemas.list", &schemas, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - return C.cstx_schema_list_json(e.handle, out, errBuf) - }) - return schemas, err } -func (e *nativeEngine) schemaLoadPlugin(_ context.Context, name string) error { - return statusCall("schemas.load_plugin", func(errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_schema_load_plugin(e.handle, stringSlice(name), errBuf) - runtime.KeepAlive(name) +func (e *nativeEngine) extensionSchema(_ context.Context, nodeType string) (cstxproto.NodeType, error) { + data, err := bufferResult("extensions.schema", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { + rc := C.cstx_extension_schema(e.handle, stringSlice(nodeType), out, errBuf) + runtime.KeepAlive(nodeType) return rc }) + if err != nil { + return cstxproto.NodeType{}, err + } + var value cstxproto.NodeType + if err := proto.Unmarshal(data, &value); err != nil { + return cstxproto.NodeType{}, err + } + return value, nil } -func (e *nativeEngine) schemaLoadAllPlugins(_ context.Context) error { - return statusCall("schemas.load_all_plugins", func(errBuf *C.CstxBuffer) C.CstxStatusCode { - return C.cstx_schema_load_all_plugins(e.handle, errBuf) - }) -} - -func (e *nativeEngine) schemaAvailablePlugins(_ context.Context) ([]string, error) { - var plugins []string - err := jsonResult("schemas.available_plugins", &plugins, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - return C.cstx_schema_available_plugins_json(e.handle, out, errBuf) - }) - return plugins, err -} - -func (e *nativeEngine) schemaPluginArtifacts(_ context.Context, name string) ([]string, error) { - var artifacts []string - err := jsonResult("schemas.plugin_artifacts", &artifacts, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_schema_plugin_artifacts_json(e.handle, stringSlice(name), out, errBuf) - runtime.KeepAlive(name) - return rc +func (e *nativeEngine) extensionSchemas(_ context.Context) (cstxproto.NodeTypeCatalog, error) { + data, err := bufferResult("extensions.schemas", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { + return C.cstx_extension_schemas(e.handle, out, errBuf) }) - return artifacts, err + if err != nil { + return cstxproto.NodeTypeCatalog{}, err + } + var value cstxproto.NodeTypeCatalog + if err := proto.Unmarshal(data, &value); err != nil { + return cstxproto.NodeTypeCatalog{}, err + } + return value, nil } -func (e *nativeEngine) schemaHasNativeArtifact(_ context.Context, artifact string) (bool, error) { - return boolResult("schemas.has_native_artifact", func(out *C.uint8_t, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_schema_has_native_artifact(e.handle, stringSlice(artifact), out, errBuf) +func (e *nativeEngine) extensionParsesArtifact(_ context.Context, artifact string) (bool, error) { + return boolResult("extensions.parses_artifact", func(out *C.uint8_t, errBuf *C.CstxBuffer) C.CstxStatusCode { + rc := C.cstx_extension_parses_artifact(e.handle, stringSlice(artifact), out, errBuf) runtime.KeepAlive(artifact) return rc }) } -func (e *nativeEngine) schemaAnchorConcepts(_ context.Context) ([]AnchorConcept, error) { - var concepts []AnchorConcept - err := jsonResult("schemas.anchor_concepts", &concepts, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - return C.cstx_schema_anchor_concepts_json(e.handle, out, errBuf) +func (e *nativeEngine) extensionAnchorConcepts(_ context.Context) (cstxproto.AnchorConceptCatalog, error) { + data, err := bufferResult("extensions.anchor_concepts", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { + return C.cstx_extension_anchor_concepts(e.handle, out, errBuf) }) - return concepts, err + if err != nil { + return cstxproto.AnchorConceptCatalog{}, err + } + var value cstxproto.AnchorConceptCatalog + if err := proto.Unmarshal(data, &value); err != nil { + return cstxproto.AnchorConceptCatalog{}, err + } + return value, nil } // --- graph --------------------------------------------------------------- -func (e *nativeEngine) graphAddNodes(_ context.Context, nodes []Node) (uint64, error) { - payload := marshal(nodes) - return countResult("graph.add_nodes", func(out *C.uint64_t, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_graph_add_nodes(e.handle, byteSlice(payload), out, errBuf) - runtime.KeepAlive(payload) - return rc - }) +func (e *nativeEngine) graphAddNodes(_ context.Context, nodes []*cstxproto.Node) (uint64, error) { + return e.graphAddNodesWire(context.Background(), &cstxproto.Graph{Nodes: nodes}) } -func (e *nativeEngine) graphReplaceNodes(_ context.Context, nodes []Node) (uint64, error) { - payload := marshal(nodes) - return countResult("graph.replace_nodes", func(out *C.uint64_t, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_graph_replace_nodes(e.handle, byteSlice(payload), out, errBuf) - runtime.KeepAlive(payload) - return rc - }) +func (e *nativeEngine) graphReplaceNodes(_ context.Context, nodes []*cstxproto.Node) (uint64, error) { + return e.graphReplaceNodesWire(context.Background(), &cstxproto.Graph{Nodes: nodes}) } -func (e *nativeEngine) graphAddEdges(_ context.Context, edges []Edge) (uint64, error) { - payload := marshal(edges) - return countResult("graph.add_edges", func(out *C.uint64_t, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_graph_add_edges(e.handle, byteSlice(payload), out, errBuf) - runtime.KeepAlive(payload) - return rc - }) +func (e *nativeEngine) graphAddRelationships(_ context.Context, relationships []*cstxproto.Relationship) (uint64, error) { + return e.graphAddRelationshipsWire(context.Background(), &cstxproto.Graph{Relationships: relationships}) } -func (e *nativeEngine) graphIngest(_ context.Context, source string, data []byte) (uint64, error) { - return countResult("graph.ingest", func(out *C.uint64_t, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_graph_ingest(e.handle, stringSlice(source), byteSlice(data), out, errBuf) - runtime.KeepAlive(source) - runtime.KeepAlive(data) - return rc - }) +func (e *nativeEngine) graphAddRelationship(_ context.Context, relationship *cstxproto.Relationship) (*cstxproto.Relationship, error) { + value, err := e.graphAddRelationshipWire(context.Background(), relationship) + if err != nil { + return nil, err + } + return &value, nil } -func (e *nativeEngine) graphNode(_ context.Context, nodeID string) (Node, error) { - var node Node - err := jsonResult("graph.node", &node, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_graph_node(e.handle, stringSlice(nodeID), out, errBuf) - runtime.KeepAlive(nodeID) - return rc - }) - return node, err +func (e *nativeEngine) graphNode(_ context.Context, nodeID string) (*cstxproto.Node, error) { + node, err := e.graphNodeWire(context.Background(), nodeID) + if err != nil { + return nil, err + } + return &node, nil +} + +func (e *nativeEngine) graphRelationship(_ context.Context, relationshipID string) (*cstxproto.Relationship, error) { + relationship, err := e.graphRelationshipWire(context.Background(), relationshipID) + if err != nil { + return nil, err + } + return &relationship, nil } func (e *nativeEngine) graphContains(_ context.Context, nodeID string) (bool, error) { @@ -441,28 +420,35 @@ func (e *nativeEngine) graphNodeCount(_ context.Context) (uint64, error) { }) } -func (e *nativeEngine) graphEdgeCount(_ context.Context) (uint64, error) { - return countResult("graph.edge_count", func(out *C.uint64_t, errBuf *C.CstxBuffer) C.CstxStatusCode { - return C.cstx_graph_edge_count(e.handle, out, errBuf) +func (e *nativeEngine) graphRelationshipCount(_ context.Context) (uint64, error) { + return countResult("graph.relationship_count", func(out *C.uint64_t, errBuf *C.CstxBuffer) C.CstxStatusCode { + return C.cstx_graph_relationship_count(e.handle, out, errBuf) }) } -func (e *nativeEngine) graphStats(_ context.Context) (GraphStats, error) { - var stats GraphStats - err := jsonResult("graph.stats", &stats, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { +func (e *nativeEngine) graphStats(_ context.Context) (*cstxproto.GraphStats, error) { + data, err := bufferResult("graph.stats", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { return C.cstx_graph_stats(e.handle, 0, 0, out, errBuf) }) - return stats, err + if err != nil { + return nil, err + } + var wire cstxproto.GraphStats + if err := proto.Unmarshal(data, &wire); err != nil { + return nil, err + } + return &wire, nil } -func (e *nativeEngine) graphNodes(_ context.Context, filter NodeFilter, options CollectionOptions) (graphCursor, error) { - filterJSON := marshal(filter) - optionsJSON := marshal(options) +func (e *nativeEngine) graphNodes(_ context.Context, query *cstxproto.NodeQuery) (graphCursor, error) { + payload, err := proto.Marshal(query) + if err != nil { + return nil, err + } var cursor *C.CstxGraphCursor - err := statusCall("graph.nodes", func(errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_graph_nodes(e.handle, byteSlice(filterJSON), byteSlice(optionsJSON), &cursor, errBuf) - runtime.KeepAlive(filterJSON) - runtime.KeepAlive(optionsJSON) + err = statusCall("graph.nodes", func(errBuf *C.CstxBuffer) C.CstxStatusCode { + rc := C.cstx_graph_nodes(e.handle, byteSlice(payload), &cursor, errBuf) + runtime.KeepAlive(payload) return rc }) if err != nil { @@ -471,14 +457,15 @@ func (e *nativeEngine) graphNodes(_ context.Context, filter NodeFilter, options return newNativeGraphCursor(cursor), nil } -func (e *nativeEngine) graphEdges(_ context.Context, filter EdgeFilter, options CollectionOptions) (graphCursor, error) { - filterJSON := marshal(filter) - optionsJSON := marshal(options) +func (e *nativeEngine) graphRelationships(_ context.Context, query *cstxproto.RelationshipQuery) (graphCursor, error) { + payload, err := proto.Marshal(query) + if err != nil { + return nil, err + } var cursor *C.CstxGraphCursor - err := statusCall("graph.edges", func(errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_graph_edges(e.handle, byteSlice(filterJSON), byteSlice(optionsJSON), &cursor, errBuf) - runtime.KeepAlive(filterJSON) - runtime.KeepAlive(optionsJSON) + err = statusCall("graph.relationships", func(errBuf *C.CstxBuffer) C.CstxStatusCode { + rc := C.cstx_graph_relationships(e.handle, byteSlice(payload), &cursor, errBuf) + runtime.KeepAlive(payload) return rc }) if err != nil { @@ -487,14 +474,15 @@ func (e *nativeEngine) graphEdges(_ context.Context, filter EdgeFilter, options return newNativeGraphCursor(cursor), nil } -func (e *nativeEngine) graphNeighbors(_ context.Context, nodeID, direction string, options CollectionOptions) (graphCursor, error) { - optionsJSON := marshal(options) +func (e *nativeEngine) graphNeighbors(_ context.Context, query *cstxproto.NeighborQuery) (graphCursor, error) { + payload, err := proto.Marshal(query) + if err != nil { + return nil, err + } var cursor *C.CstxGraphCursor - err := statusCall("graph.neighbors", func(errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_graph_neighbors(e.handle, stringSlice(nodeID), stringSlice(direction), byteSlice(optionsJSON), &cursor, errBuf) - runtime.KeepAlive(nodeID) - runtime.KeepAlive(direction) - runtime.KeepAlive(optionsJSON) + err = statusCall("graph.neighbors", func(errBuf *C.CstxBuffer) C.CstxStatusCode { + rc := C.cstx_graph_neighbors(e.handle, byteSlice(payload), &cursor, errBuf) + runtime.KeepAlive(payload) return rc }) if err != nil { @@ -503,13 +491,15 @@ func (e *nativeEngine) graphNeighbors(_ context.Context, nodeID, direction strin return newNativeGraphCursor(cursor), nil } -func (e *nativeEngine) graphQuery(_ context.Context, expression string, options QueryOptions) (graphCursor, error) { - optionsJSON := marshal(options) +func (e *nativeEngine) graphQuery(_ context.Context, query *cstxproto.GraphQuery) (graphCursor, error) { + payload, err := proto.Marshal(query) + if err != nil { + return nil, err + } var cursor *C.CstxGraphCursor - err := statusCall("graph.query", func(errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_graph_query(e.handle, stringSlice(expression), byteSlice(optionsJSON), &cursor, errBuf) - runtime.KeepAlive(expression) - runtime.KeepAlive(optionsJSON) + err = statusCall("graph.query", func(errBuf *C.CstxBuffer) C.CstxStatusCode { + rc := C.cstx_graph_query(e.handle, byteSlice(payload), &cursor, errBuf) + runtime.KeepAlive(payload) return rc }) if err != nil { @@ -518,8 +508,8 @@ func (e *nativeEngine) graphQuery(_ context.Context, expression string, options return newNativeGraphCursor(cursor), nil } -func (e *nativeEngine) graphAnalyze(_ context.Context, algorithm any, selection *string) (uint8, bool, graphCursor, error) { - payload, err := marshalInput("graph.analyze", algorithm) +func (e *nativeEngine) graphAnalyze(_ context.Context, algorithm *cstxproto.Algorithm, selection *string) (uint8, bool, graphCursor, error) { + payload, err := proto.Marshal(algorithm) if err != nil { return 0, false, nil, err } @@ -556,27 +546,31 @@ func (e *nativeEngine) graphAnalyze(_ context.Context, algorithm any, selection // --- repository ---------------------------------------------------------- func (e *nativeEngine) repoResolve(_ context.Context, revision string) (string, error) { - var resolved string - err := jsonResult("repo.resolve", &resolved, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { + return textResult("repo.resolve", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { rc := C.cstx_repo_resolve(e.handle, stringSlice(revision), out, errBuf) runtime.KeepAlive(revision) return rc }) - return resolved, err } -func (e *nativeEngine) repoCheckout(_ context.Context, revision string, force bool) (Commit, error) { - var commit Commit +func (e *nativeEngine) repoCheckout(_ context.Context, revision string, force bool) (*cstxproto.Commit, error) { var nativeForce C.uint8_t if force { nativeForce = 1 } - err := jsonResult("repo.checkout", &commit, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { + data, err := bufferResult("repo.checkout", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { rc := C.cstx_repo_checkout(e.handle, stringSlice(revision), nativeForce, out, errBuf) runtime.KeepAlive(revision) return rc }) - return commit, err + if err != nil { + return nil, err + } + var wire cstxproto.Commit + if err := proto.Unmarshal(data, &wire); err != nil { + return nil, err + } + return &wire, nil } func (e *nativeEngine) repoCommit( @@ -584,42 +578,35 @@ func (e *nativeEngine) repoCommit( message string, refName string, expectedHead *string, - metadata any, -) (Commit, error) { - var metadataJSON []byte - if metadata != nil { - var err error - metadataJSON, err = marshalInput("repo.commit", metadata) - if err != nil { - return Commit{}, err - } + metadata *structpb.Struct, +) (*cstxproto.Commit, error) { + if metadata == nil { + metadata = &structpb.Struct{} + } + metadataBytes, err := proto.Marshal(metadata) + if err != nil { + return nil, err } - var commit Commit - err := jsonResult("repo.commit", &commit, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { + data, err := bufferResult("repo.commit", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { var expected C.CstxSlice if expectedHead != nil { expected = stringSlice(*expectedHead) } - rc := C.cstx_repo_commit(e.handle, stringSlice(message), stringSlice(refName), expected, byteSlice(metadataJSON), out, errBuf) + rc := C.cstx_repo_commit(e.handle, stringSlice(message), stringSlice(refName), expected, byteSlice(metadataBytes), out, errBuf) runtime.KeepAlive(refName) runtime.KeepAlive(message) runtime.KeepAlive(expectedHead) - runtime.KeepAlive(metadataJSON) + runtime.KeepAlive(metadataBytes) return rc }) - return commit, err -} - -type preparedObjectWire struct { - ID string `json:"id"` - Kind string `json:"kind"` - Envelope string `json:"envelope"` -} - -type preparedCommitWire struct { - Commit Commit `json:"commit"` - IndexRoot string `json:"index_root"` - Objects []preparedObjectWire `json:"objects"` + if err != nil { + return nil, err + } + var wire cstxproto.Commit + if err := proto.Unmarshal(data, &wire); err != nil { + return nil, err + } + return &wire, nil } func (e *nativeEngine) repoPrepare( @@ -627,44 +614,42 @@ func (e *nativeEngine) repoPrepare( message string, refName string, expectedHead *string, - metadata any, + metadata *structpb.Struct, timestamp *int64, -) (PreparedCommit, error) { - metadataJSON, err := marshalInput("repo.prepare", metadata) +) (*cstxproto.PublicationPlan, error) { + if metadata == nil { + metadata = &structpb.Struct{} + } + metadataBytes, err := proto.Marshal(metadata) if err != nil { - return PreparedCommit{}, err + return nil, err } - var wire preparedCommitWire var nativeTimestamp C.int64_t var hasTimestamp C.uint8_t if timestamp != nil { nativeTimestamp = C.int64_t(*timestamp) hasTimestamp = 1 } - err = jsonResult("repo.prepare", &wire, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { + data, err := bufferResult("repo.prepare", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { var expected C.CstxSlice if expectedHead != nil { expected = stringSlice(*expectedHead) } - rc := C.cstx_repo_prepare(e.handle, stringSlice(message), stringSlice(refName), expected, byteSlice(metadataJSON), nativeTimestamp, hasTimestamp, out, errBuf) + rc := C.cstx_repo_prepare(e.handle, stringSlice(message), stringSlice(refName), expected, byteSlice(metadataBytes), nativeTimestamp, hasTimestamp, out, errBuf) runtime.KeepAlive(message) runtime.KeepAlive(refName) runtime.KeepAlive(expectedHead) - runtime.KeepAlive(metadataJSON) + runtime.KeepAlive(metadataBytes) return rc }) if err != nil { - return PreparedCommit{}, err + return nil, err } - prepared := PreparedCommit{Commit: wire.Commit, IndexRoot: wire.IndexRoot, Objects: make([]PreparedObject, len(wire.Objects))} - for i, object := range wire.Objects { - envelope, err := hex.DecodeString(object.Envelope) - if err != nil { - return PreparedCommit{}, &Error{Code: CodeCorruptData, Operation: "repo.prepare", Message: "invalid object envelope: " + err.Error()} - } - prepared.Objects[i] = PreparedObject{ID: object.ID, Kind: object.Kind, Envelope: envelope} + var wire cstxproto.PublicationPlan + if err := proto.Unmarshal(data, &wire); err != nil { + return nil, err } - return prepared, nil + return &wire, nil } func (e *nativeEngine) repoAccept(_ context.Context, commit string) error { @@ -681,38 +666,11 @@ func (e *nativeEngine) repoDiscard(_ context.Context) error { }) } -func (e *nativeEngine) repoSynchronize(_ context.Context, state RepositorySync) error { - type objectWire struct { - ID string `json:"id"` - Envelope string `json:"envelope"` - } - type refWire struct { - Name string `json:"name"` - Commit *string `json:"commit"` - } - type indexWire struct { - Commit string `json:"commit"` - IndexRoot string `json:"index_root"` - } - payload := struct { - Objects []objectWire `json:"objects"` - Refs []refWire `json:"refs"` - Indexes []indexWire `json:"indexes"` - }{ - Objects: make([]objectWire, len(state.Objects)), - Refs: make([]refWire, len(state.Refs)), - Indexes: make([]indexWire, len(state.Indexes)), - } - for i, object := range state.Objects { - payload.Objects[i] = objectWire{ID: object.ID, Envelope: hex.EncodeToString(object.Envelope)} - } - for i, ref := range state.Refs { - payload.Refs[i] = refWire{Name: ref.Name, Commit: ref.Commit} +func (e *nativeEngine) repoSynchronize(_ context.Context, state *cstxproto.RepositoryState) error { + if state == nil { + state = &cstxproto.RepositoryState{} } - for i, index := range state.Indexes { - payload.Indexes[i] = indexWire{Commit: index.Commit, IndexRoot: index.IndexRoot} - } - data, err := marshalInput("repo.synchronize", payload) + data, err := proto.Marshal(state) if err != nil { return err } @@ -731,111 +689,27 @@ func (e *nativeEngine) repoContains(_ context.Context, object string) (bool, err }) } -func (e *nativeEngine) repoMissingTree(_ context.Context, commit string) ([]string, error) { - var ids []string - err := jsonResult("repo.missing_tree", &ids, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_repo_missing_tree(e.handle, stringSlice(commit), out, errBuf) - runtime.KeepAlive(commit) - return rc - }) - return ids, err -} - -func (e *nativeEngine) repoObjectClosure(_ context.Context, commit string) ([]string, error) { - var ids []string - err := jsonResult("repo.object_closure", &ids, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_repo_object_closure(e.handle, stringSlice(commit), out, errBuf) - runtime.KeepAlive(commit) - return rc - }) - return ids, err -} - -func (e *nativeEngine) repoMissingPrepare(_ context.Context, commit string) ([]string, error) { - var ids []string - err := jsonResult("repo.missing_prepare", &ids, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_repo_missing_prepare(e.handle, stringSlice(commit), out, errBuf) - runtime.KeepAlive(commit) - return rc - }) - return ids, err -} - -func (e *nativeEngine) repoMissingHistory(_ context.Context, commit, entity string) ([]string, error) { - var ids []string - err := jsonResult("repo.missing_history", &ids, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_repo_missing_history(e.handle, stringSlice(commit), stringSlice(entity), out, errBuf) - runtime.KeepAlive(commit) - runtime.KeepAlive(entity) - return rc - }) - return ids, err -} - -func (e *nativeEngine) repoMissingStat(_ context.Context, commit string) ([]string, error) { - var ids []string - err := jsonResult("repo.missing_stat", &ids, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_repo_missing_stat(e.handle, stringSlice(commit), out, errBuf) - runtime.KeepAlive(commit) - return rc - }) - return ids, err -} - -func (e *nativeEngine) repoMissingCommits(_ context.Context, commit string, limit int) ([]string, error) { - var ids []string - err := jsonResult("repo.missing_commits", &ids, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_repo_missing_commits(e.handle, stringSlice(commit), C.size_t(limit), out, errBuf) - runtime.KeepAlive(commit) - return rc - }) - return ids, err -} - -func (e *nativeEngine) repoMissingDiff(_ context.Context, base, head string, detail DiffDetail) ([]string, error) { - var ids []string - nativeDetail := string(detail) - err := jsonResult("repo.missing_diff", &ids, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_repo_missing_diff(e.handle, stringSlice(base), stringSlice(head), stringSlice(nativeDetail), out, errBuf) - runtime.KeepAlive(base) - runtime.KeepAlive(head) - runtime.KeepAlive(nativeDetail) - return rc - }) - return ids, err -} - -func (e *nativeEngine) repoMissingDelta(_ context.Context, commit string, start, end *int64) ([]string, error) { - var ids []string - var nativeStart, nativeEnd C.int64_t - var hasStart, hasEnd C.uint8_t - if start != nil { - nativeStart = C.int64_t(*start) - hasStart = 1 +func (e *nativeEngine) repoMissing(_ context.Context, plan *cstxproto.RepositoryObjectPlan) (*cstxproto.ObjectSelection, error) { + if plan == nil { + return nil, fmt.Errorf("cstx: repository object plan must not be nil") } - if end != nil { - nativeEnd = C.int64_t(*end) - hasEnd = 1 + payload, err := proto.Marshal(plan) + if err != nil { + return nil, err } - err := jsonResult("repo.missing_delta", &ids, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_repo_missing_delta(e.handle, stringSlice(commit), nativeStart, hasStart, nativeEnd, hasEnd, out, errBuf) - runtime.KeepAlive(commit) - return rc - }) - return ids, err -} - -// repoMissingMerge takes an empty target to mean "merge into the current head", -// which optionalStringSlice turns into the runtime's None. -func (e *nativeEngine) repoMissingMerge(_ context.Context, source, target string) ([]string, error) { - var ids []string - err := jsonResult("repo.missing_merge", &ids, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_repo_missing_merge(e.handle, stringSlice(source), optionalStringSlice(target), out, errBuf) - runtime.KeepAlive(source) - runtime.KeepAlive(target) + data, err := bufferResult("repo.missing", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { + rc := C.cstx_repo_missing(e.handle, byteSlice(payload), out, errBuf) + runtime.KeepAlive(payload) return rc }) - return ids, err + if err != nil { + return nil, err + } + var value cstxproto.ObjectSelection + if err := proto.Unmarshal(data, &value); err != nil { + return nil, err + } + return &value, nil } func (e *nativeEngine) repoReleaseTransientObjects(_ context.Context) error { @@ -844,43 +718,63 @@ func (e *nativeEngine) repoReleaseTransientObjects(_ context.Context) error { }) } -func (e *nativeEngine) repoDiff(_ context.Context, baseRef, headRef string, options DiffOptions) (GraphDiff, error) { - var diff GraphDiff +func (e *nativeEngine) repoDiff(_ context.Context, baseRef, headRef string, limit *uint64, detailValue cstxproto.DiffDetail) (*cstxproto.GraphDiff, error) { var nativeLimit C.size_t var hasLimit C.uint8_t - if options.Limit != nil { - nativeLimit = C.size_t(*options.Limit) + if limit != nil { + nativeLimit = C.size_t(*limit) hasLimit = 1 } - detail := string(options.detail()) - err := jsonResult("repo.diff", &diff, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { + detail := "entities" + if detailValue == cstxproto.DiffDetail_DIFF_DETAIL_COUNTS { + detail = "counts" + } + data, err := bufferResult("repo.diff", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { rc := C.cstx_repo_diff(e.handle, stringSlice(baseRef), stringSlice(headRef), nativeLimit, hasLimit, stringSlice(detail), out, errBuf) runtime.KeepAlive(baseRef) runtime.KeepAlive(headRef) runtime.KeepAlive(detail) return rc }) - return diff, err + if err != nil { + return nil, err + } + var wire cstxproto.GraphDiff + if err := proto.Unmarshal(data, &wire); err != nil { + return nil, err + } + return &wire, nil } func (e *nativeEngine) repoHead(_ context.Context, refName string) (*string, error) { - var head *string - err := jsonResult("repo.head", &head, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { + value, err := textResult("repo.head", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { rc := C.cstx_repo_head(e.handle, stringSlice(refName), out, errBuf) runtime.KeepAlive(refName) return rc }) - return head, err + if err != nil { + return nil, err + } + if value == "" { + return nil, nil + } + return &value, nil } -func (e *nativeEngine) repoLog(_ context.Context, revision string, limit int) ([]map[string]any, error) { - var commits []map[string]any - err := jsonResult("repo.log", &commits, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { +func (e *nativeEngine) repoLog(_ context.Context, revision string, limit int) (*cstxproto.CommitLog, error) { + data, err := bufferResult("repo.log", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { rc := C.cstx_repo_log(e.handle, stringSlice(revision), C.size_t(limit), out, errBuf) runtime.KeepAlive(revision) return rc }) - return commits, err + if err != nil { + return nil, err + } + var wire cstxproto.CommitLog + if err := proto.Unmarshal(data, &wire); err != nil { + return nil, err + } + return &wire, nil } func (e *nativeEngine) repoHistory( @@ -888,32 +782,63 @@ func (e *nativeEngine) repoHistory( entityID string, revision string, limit *int, -) ([]map[string]any, error) { - var entries []map[string]any +) (*cstxproto.EntityHistory, error) { var nativeLimit C.size_t var hasLimit C.uint8_t if limit != nil { nativeLimit = C.size_t(*limit) hasLimit = 1 } - err := jsonResult("repo.history", &entries, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { + data, err := bufferResult("repo.history", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { rc := C.cstx_repo_history(e.handle, stringSlice(entityID), stringSlice(revision), nativeLimit, hasLimit, out, errBuf) runtime.KeepAlive(entityID) runtime.KeepAlive(revision) return rc }) - return entries, err + if err != nil { + return nil, err + } + var wire cstxproto.EntityHistory + if err := proto.Unmarshal(data, &wire); err != nil { + return nil, err + } + return &wire, nil +} + +func (e *nativeEngine) repoEntities( + _ context.Context, + revision string, + entityIDs []string, +) (*cstxproto.Graph, error) { + // Node and relationship ids are one set to the engine, which tells them + // apart by the `relationship:` prefix. + selection, err := proto.Marshal(&cstxproto.GraphSelection{NodeIds: entityIDs}) + if err != nil { + return nil, err + } + data, err := bufferResult("repo.entities", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { + rc := C.cstx_repo_entities(e.handle, stringSlice(revision), byteSlice(selection), out, errBuf) + runtime.KeepAlive(revision) + runtime.KeepAlive(selection) + return rc + }) + if err != nil { + return nil, err + } + var wire cstxproto.Graph + if err := proto.Unmarshal(data, &wire); err != nil { + return nil, err + } + return &wire, nil } func (e *nativeEngine) repoBranch(_ context.Context, name, startPoint string) (string, error) { - var commit string - err := jsonResult("repo.branch", &commit, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { + return textResult("repo.branch", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { rc := C.cstx_repo_branch(e.handle, stringSlice(name), stringSlice(startPoint), out, errBuf) runtime.KeepAlive(name) runtime.KeepAlive(startPoint) return rc }) - return commit, err } func (e *nativeEngine) repoMerge( @@ -922,9 +847,8 @@ func (e *nativeEngine) repoMerge( target string, expectedHead *string, message *string, -) (Commit, error) { - var commit Commit - err := jsonResult("repo.merge", &commit, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { +) (*cstxproto.Commit, error) { + data, err := bufferResult("repo.merge", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { var expected, commitMessage C.CstxSlice if expectedHead != nil { expected = stringSlice(*expectedHead) @@ -939,7 +863,14 @@ func (e *nativeEngine) repoMerge( runtime.KeepAlive(message) return rc }) - return commit, err + if err != nil { + return nil, err + } + var wire cstxproto.Commit + if err := proto.Unmarshal(data, &wire); err != nil { + return nil, err + } + return &wire, nil } func (e *nativeEngine) repoStat( @@ -947,14 +878,20 @@ func (e *nativeEngine) repoStat( revision string, excludeMask uint64, includeMask uint64, -) (GraphStats, error) { - var value GraphStats - err := jsonResult("repo.stat", &value, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { +) (*cstxproto.GraphStats, error) { + data, err := bufferResult("repo.stat", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { rc := C.cstx_repo_stat(e.handle, stringSlice(revision), C.uint64_t(excludeMask), C.uint64_t(includeMask), out, errBuf) runtime.KeepAlive(revision) return rc }) - return value, err + if err != nil { + return nil, err + } + var wire cstxproto.GraphStats + if err := proto.Unmarshal(data, &wire); err != nil { + return nil, err + } + return &wire, nil } func (e *nativeEngine) repoDelta( @@ -962,8 +899,7 @@ func (e *nativeEngine) repoDelta( revision string, startTimestamp *int64, endTimestamp *int64, -) (Delta, error) { - var value Delta +) (*cstxproto.GraphChangeSummary, error) { var start, end C.int64_t var hasStart, hasEnd C.uint8_t if startTimestamp != nil { @@ -974,12 +910,19 @@ func (e *nativeEngine) repoDelta( end = C.int64_t(*endTimestamp) hasEnd = 1 } - err := jsonResult("repo.delta", &value, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { + data, err := bufferResult("repo.delta", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { rc := C.cstx_repo_delta(e.handle, stringSlice(revision), start, hasStart, end, hasEnd, out, errBuf) runtime.KeepAlive(revision) return rc }) - return value, err + if err != nil { + return nil, err + } + var wire cstxproto.GraphChangeSummary + if err := proto.Unmarshal(data, &wire); err != nil { + return nil, err + } + return &wire, nil } // --- unified graph cursor ------------------------------------------------ @@ -991,15 +934,21 @@ func newNativeGraphCursor(cursor *C.CstxGraphCursor) *nativeGraphCursor { return result } -func (c *nativeGraphCursor) page(_ context.Context, limit, page int) (CursorPage, error) { +func (c *nativeGraphCursor) page(_ context.Context, limit, page int) (*cstxproto.GraphResultPage, error) { if c.cursor == nil { - return CursorPage{}, &Error{Code: CodeInvalidArgument, Operation: "cursor.page", Message: "cursor is closed"} + return nil, &Error{Code: CodeInvalidArgument, Operation: "cursor.page", Message: "cursor is closed"} } - var result CursorPage - err := jsonResult("cursor.page", &result, func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { + data, err := bufferResult("cursor.page", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { return C.cstx_graph_cursor_page(c.cursor, C.size_t(limit), C.size_t(page), out, errBuf) }) - return result, err + if err != nil { + return nil, err + } + var wire cstxproto.GraphResultPage + if err := proto.Unmarshal(data, &wire); err != nil { + return nil, err + } + return &wire, nil } func (c *nativeGraphCursor) close() { diff --git a/go/errors.go b/go/errors.go index 4e6880d..f05df94 100644 --- a/go/errors.go +++ b/go/errors.go @@ -1,7 +1,6 @@ package cstx import ( - "encoding/json" "errors" "fmt" ) @@ -51,37 +50,9 @@ func IsCode(err error, code Code) bool { return errors.As(err, &cerr) && cerr.Code == code } -// errorJSON is the FFI transport shape; nullable string fields distinguish -// absent context from empty strings on the Rust side. -type errorJSON struct { - Code Code `json:"code"` - Operation string `json:"operation"` - ItemIndex *int `json:"item_index"` - Field *string `json:"field"` - Message string `json:"message"` - Expected *string `json:"expected"` - Actual *string `json:"actual"` -} - +// parseError decodes the error channel. Structured runtime payloads use +// protobuf; failures intentionally remain a compact UTF-8 diagnostic paired +// with the CstxStatusCode so callers never need a second error codec. func parseError(data []byte, fallback Code) *Error { - var wire errorJSON - if err := json.Unmarshal(data, &wire); err != nil || wire.Code == "" { - return &Error{Code: fallback, Message: string(data)} - } - return &Error{ - Code: wire.Code, - Operation: wire.Operation, - ItemIndex: wire.ItemIndex, - Field: deref(wire.Field), - Message: wire.Message, - Expected: deref(wire.Expected), - Actual: deref(wire.Actual), - } -} - -func deref(value *string) string { - if value == nil { - return "" - } - return *value + return &Error{Code: fallback, Message: string(data)} } diff --git a/go/extensions.go b/go/extensions.go new file mode 100644 index 0000000..36e0860 --- /dev/null +++ b/go/extensions.go @@ -0,0 +1,148 @@ +package cstx + +import ( + "context" + + "github.com/chainreactors/libcstx/go/proto/cstxproto" +) + +// ExtensionBuilder constructs one canonical protobuf extension contract. It +// is a convenience for code-defined extensions, not a second wire format. +type ExtensionBuilder struct { + contract *cstxproto.ExtensionContract + name string +} + +func newExtensionBuilder(name, version string) *ExtensionBuilder { + contract := &cstxproto.ExtensionContract{ + ContractVersion: 1, + Extensions: map[string]*cstxproto.ExtensionDefinition{}, + } + contract.Extensions[name] = &cstxproto.ExtensionDefinition{ + Name: name, + Version: version, + Parsers: map[string]*cstxproto.ParserType{}, + } + return &ExtensionBuilder{contract: contract, name: name} +} + +func (b *ExtensionBuilder) definition() *cstxproto.ExtensionDefinition { + return b.contract.Extensions[b.name] +} + +// Schema sets this extension's runtime schema document. +// +// One JSON document declares every node and relation type the extension +// contributes — the same artifact `make codegen` produces for the built-in +// extension. Nothing else is needed to make the types usable. +func (b *ExtensionBuilder) Schema(document string) *ExtensionBuilder { + b.definition().Schema = document + return b +} + +// Parser adds one generated parser declaration. +func (b *ExtensionBuilder) Parser(name string, parserType *cstxproto.ParserType) *ExtensionBuilder { + b.definition().Parsers[name] = parserType + return b +} + +// Rule adds one declarative native linker rule. +func (b *ExtensionBuilder) Rule(rule *cstxproto.JoinRule) *ExtensionBuilder { + b.definition().Rules = append(b.definition().Rules, rule) + return b +} + +// Build returns the canonical generated protobuf message. +func (b *ExtensionBuilder) Build() *cstxproto.ExtensionContract { return b.contract } + +// Extensions is the unified extension lifecycle and schema namespace. +type Extensions struct{ eng engine } + +// Register atomically registers one canonical protobuf extension contract. +func (e *Extensions) Register(ctx context.Context, contract *cstxproto.ExtensionContract) error { + if err := contextError(ctx); err != nil { + return err + } + if contract == nil { + return &Error{Code: CodeInvalidArgument, Operation: "extensions.register", Message: "contract must not be nil"} + } + return e.eng.extensionRegister(ctx, contract) +} + +// ExportContract returns the canonical registered extension contract. +// Consumers should derive any metadata view from this generated protobuf +// instead of maintaining a second schema registry. +func (e *Extensions) ExportContract(ctx context.Context) (cstxproto.ExtensionContract, error) { + if err := contextError(ctx); err != nil { + return cstxproto.ExtensionContract{}, err + } + return e.eng.extensionExportContract(ctx) +} + +// Enable explicitly enables one linked native Rust extension. +func (e *Extensions) Enable(ctx context.Context, name string) error { + if err := contextError(ctx); err != nil { + return err + } + return e.eng.extensionEnable(ctx, name) +} + +// List returns linked and registered extension metadata. +func (e *Extensions) List(ctx context.Context) (*cstxproto.ExtensionCatalog, error) { + if err := contextError(ctx); err != nil { + return nil, err + } + return e.eng.extensionList(ctx) +} + +// Info returns one linked or registered extension's metadata. +func (e *Extensions) Info(ctx context.Context, name string) (*cstxproto.ExtensionInfo, error) { + if err := contextError(ctx); err != nil { + return nil, err + } + return e.eng.extensionInfo(ctx, name) +} + +// Contains reports whether a schema exists. +func (e *Extensions) Contains(ctx context.Context, nodeType string) (bool, error) { + if err := contextError(ctx); err != nil { + return false, err + } + return e.eng.extensionContains(ctx, nodeType) +} + +// Schema returns one retained schema. +func (e *Extensions) Schema(ctx context.Context, nodeType string) (cstxproto.NodeType, error) { + if err := contextError(ctx); err != nil { + return cstxproto.NodeType{}, err + } + return e.eng.extensionSchema(ctx, nodeType) +} + +// Schemas returns retained schemas in deterministic order. +func (e *Extensions) Schemas(ctx context.Context) (cstxproto.NodeTypeCatalog, error) { + if err := contextError(ctx); err != nil { + return cstxproto.NodeTypeCatalog{}, err + } + return e.eng.extensionSchemas(ctx) +} + +// ParsesArtifact reports whether any enabled extension parses this artifact. +// +// Capability, not implementation: the answer says the engine can take this +// payload, never which parser will. Callers routing work want this; nothing +// should branch on "is it native". +func (e *Extensions) ParsesArtifact(ctx context.Context, artifact string) (bool, error) { + if err := contextError(ctx); err != nil { + return false, err + } + return e.eng.extensionParsesArtifact(ctx, artifact) +} + +// AnchorConcepts lists native concepts and their member node types. +func (e *Extensions) AnchorConcepts(ctx context.Context) (cstxproto.AnchorConceptCatalog, error) { + if err := contextError(ctx); err != nil { + return cstxproto.AnchorConceptCatalog{}, err + } + return e.eng.extensionAnchorConcepts(ctx) +} diff --git a/go/extensions_dynamic_test.go b/go/extensions_dynamic_test.go new file mode 100644 index 0000000..6107d54 --- /dev/null +++ b/go/extensions_dynamic_test.go @@ -0,0 +1,52 @@ +package cstx + +import ( + "context" + "encoding/json" + "testing" +) + +// What a Go consumer can ask about a type it declared at runtime. +// +// No generated message type exists for `acme.Asset` and none can, because the +// type is declared by a document that ships as test data — so registering it +// is the whole story, and the runtime must answer for it exactly as it does +// for a built-in. Writing and reading one is `TestDynamicExtensionConformance` +// next door, against the same document; this covers the registration surface +// that test does not touch. +func TestDynamicExtensionRegistration(t *testing.T) { + ctx := context.Background() + fixture := loadDynamicFixture(t) + runtime := openDynamicRuntime(t, fixture) + + ok, err := runtime.Extensions.Contains(ctx, "acme_asset") + if err != nil || !ok { + t.Fatalf("contains acme_asset = %v, %v; want true", ok, err) + } + + var document struct { + Nodes map[string]struct { + Message string `json:"message"` + } `json:"nodes"` + } + if err := json.Unmarshal(fixture.Document, &document); err != nil { + t.Fatalf("document: %v", err) + } + + schema, err := runtime.Extensions.Schema(ctx, "acme_asset") + if err != nil { + t.Fatalf("schema: %v", err) + } + want := "type.googleapis.com/" + document.Nodes["acme_asset"].Message + if schema.GetTypeUrl() != want { + t.Fatalf("type_url = %q; want %q", schema.GetTypeUrl(), want) + } + + // A type the document never declared is not registered by accident. + if ok, err := runtime.Extensions.Contains(ctx, "acme_absent"); err != nil || ok { + t.Fatalf("contains acme_absent = %v, %v; want false", ok, err) + } + if _, err := runtime.Extensions.Schema(ctx, "acme_absent"); err == nil { + t.Fatal("schema of an undeclared type should fail") + } +} diff --git a/go/flags.go b/go/flags.go new file mode 100644 index 0000000..a4fa482 --- /dev/null +++ b/go/flags.go @@ -0,0 +1,101 @@ +package cstx + +import ( + "encoding/json" + "sort" + + "github.com/chainreactors/libcstx/go/proto/cstxproto" +) + +// FlagRegistry answers what a node flag bit means, from the schema documents +// the runtime holds. +// +// The counterpart of Python's `cstxpy.flags.NodeFlags`. Neither side compiles +// in a vocabulary: a flag's name and its bit are declared by the extension +// that owns them, so a third party's flags are reachable here on exactly the +// same terms as the built-in ones. Bits 0-55 belong to extensions; 56-63 are +// reserved for the runtime. +type FlagRegistry struct { + bits map[string]uint32 + defaultExclude uint64 +} + +type flagDeclaration struct { + Bit uint32 `json:"bit"` + DefaultExclude bool `json:"default_exclude"` +} + +type schemaDocument struct { + Flags map[string]flagDeclaration `json:"flags"` +} + +// Flags reads every loaded extension's declarations out of an exported +// contract. `Extensions.ExportContract` returns what the core accepted, so +// this needs no ABI call of its own. +func Flags(contract *cstxproto.ExtensionContract) (*FlagRegistry, error) { + registry := &FlagRegistry{bits: map[string]uint32{}} + if contract == nil { + return registry, nil + } + for _, definition := range contract.GetExtensions() { + document := definition.GetSchema() + if document == "" { + continue + } + var parsed schemaDocument + if err := json.Unmarshal([]byte(document), &parsed); err != nil { + return nil, err + } + for name, declaration := range parsed.Flags { + // First claimant keeps the bit, as the core decides at + // registration: a bit is what a stored mask means, so a second + // claim would make one stored value ambiguous. + if _, taken := registry.bits[name]; taken { + continue + } + registry.bits[name] = declaration.Bit + if declaration.DefaultExclude { + registry.defaultExclude |= uint64(1) << declaration.Bit + } + } + } + return registry, nil +} + +// Bit returns the bit one declared flag occupies, and whether it is declared. +func (r *FlagRegistry) Bit(name string) (uint32, bool) { + bit, ok := r.bits[name] + return bit, ok +} + +// Mask returns the single-bit mask for one declared flag; 0 if undeclared. +func (r *FlagRegistry) Mask(name string) uint64 { + bit, ok := r.bits[name] + if !ok { + return 0 + } + return uint64(1) << bit +} + +// AllMask returns every bit any loaded extension declared. +func (r *FlagRegistry) AllMask() uint64 { + var mask uint64 + for _, bit := range r.bits { + mask |= uint64(1) << bit + } + return mask +} + +// DefaultExcludeMask returns the bits extensions advise hiding from an +// ordinary view. Advice, not enforcement: nothing applies it on its own. +func (r *FlagRegistry) DefaultExcludeMask() uint64 { return r.defaultExclude } + +// Names returns the declared flag names, lowest bit first. +func (r *FlagRegistry) Names() []string { + names := make([]string, 0, len(r.bits)) + for name := range r.bits { + names = append(names, name) + } + sort.Slice(names, func(i, j int) bool { return r.bits[names[i]] < r.bits[names[j]] }) + return names +} diff --git a/go/flags_test.go b/go/flags_test.go new file mode 100644 index 0000000..0190a21 --- /dev/null +++ b/go/flags_test.go @@ -0,0 +1,78 @@ +package cstx + +import ( + "encoding/json" + "testing" + + "github.com/chainreactors/libcstx/go/proto/cstxproto" +) + +// The registry reads declarations, it does not carry them: a flag any +// extension declares is reachable on the same terms as a built-in one, which +// is the whole reason the wire stopped carrying a closed enum. +func TestFlagRegistryReadsExtensionDeclarations(t *testing.T) { + document, err := json.Marshal(map[string]any{ + "schema_version": 1, + "extension": "acme", + "flags": map[string]any{ + "honeypot": map[string]any{"bit": 0, "default_exclude": true}, + "quarantined": map[string]any{"bit": 40, "default_exclude": true}, + "reviewed": map[string]any{"bit": 41}, + }, + }) + if err != nil { + t.Fatal(err) + } + + contract := &cstxproto.ExtensionContract{ + Extensions: map[string]*cstxproto.ExtensionDefinition{ + "acme": {Name: "acme", Schema: string(document)}, + }, + } + registry, err := Flags(contract) + if err != nil { + t.Fatal(err) + } + + // A bit the retired enum could not express at all. + if bit, ok := registry.Bit("quarantined"); !ok || bit != 40 { + t.Fatalf("quarantined: got bit %d ok=%v, want 40 true", bit, ok) + } + if mask := registry.Mask("quarantined"); mask != 1<<40 { + t.Fatalf("quarantined mask: got %#x, want %#x", mask, uint64(1)<<40) + } + if mask := registry.Mask("nosuchflag"); mask != 0 { + t.Fatalf("undeclared flag must mask to 0, got %#x", mask) + } + + wantAll := uint64(1)<<0 | uint64(1)<<40 | uint64(1)<<41 + if got := registry.AllMask(); got != wantAll { + t.Fatalf("AllMask: got %#x, want %#x", got, wantAll) + } + // Advice, not enforcement -- `reviewed` declares no default_exclude. + wantExclude := uint64(1)<<0 | uint64(1)<<40 + if got := registry.DefaultExcludeMask(); got != wantExclude { + t.Fatalf("DefaultExcludeMask: got %#x, want %#x", got, wantExclude) + } + + names := registry.Names() + want := []string{"honeypot", "quarantined", "reviewed"} // lowest bit first + if len(names) != len(want) { + t.Fatalf("Names: got %v, want %v", names, want) + } + for i := range want { + if names[i] != want[i] { + t.Fatalf("Names: got %v, want %v", names, want) + } + } +} + +func TestFlagRegistryToleratesAnEmptyContract(t *testing.T) { + registry, err := Flags(nil) + if err != nil { + t.Fatal(err) + } + if registry.AllMask() != 0 || len(registry.Names()) != 0 { + t.Fatal("an empty contract must declare no flags") + } +} diff --git a/go/go.mod b/go/go.mod index 5d51d8e..e2c4571 100644 --- a/go/go.mod +++ b/go/go.mod @@ -1,3 +1,5 @@ module github.com/chainreactors/libcstx/go go 1.25.0 + +require google.golang.org/protobuf v1.36.11 diff --git a/go/go.sum b/go/go.sum new file mode 100644 index 0000000..296be18 --- /dev/null +++ b/go/go.sum @@ -0,0 +1,4 @@ +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= diff --git a/go/graph.go b/go/graph.go index 24c03fd..aa98dda 100644 --- a/go/graph.go +++ b/go/graph.go @@ -1,15 +1,19 @@ package cstx -import "context" +import ( + "context" -// Graph is the graph namespace of a CSTX runtime. It owns graph data, graph -// queries, and ingest; the repository lifecycle lives elsewhere. + "github.com/chainreactors/libcstx/go/proto/cstxproto" +) + +// Graph is the graph namespace of a CSTX runtime. It owns graph data, native +// ingestion, and queries; the repository lifecycle lives elsewhere. type Graph struct{ eng engine } // AddNodes atomically adds or merges nodes and returns the number of elements // actually changed. A no-op write reports zero and does not invalidate // cursors. -func (g *Graph) AddNodes(ctx context.Context, nodes []Node) (uint64, error) { +func (g *Graph) AddNodes(ctx context.Context, nodes []*cstxproto.Node) (uint64, error) { if err := contextError(ctx); err != nil { return 0, err } @@ -20,24 +24,36 @@ func (g *Graph) AddNodes(ctx context.Context, nodes []Node) (uint64, error) { // number of elements actually changed. // // AddNodes merges: fields fill in, sources accumulate, and two different values -// under one extras key are kept as both. That is what aggregating sightings of +// under one annotations key are kept as both. That is what aggregating sightings of // one entity needs. ReplaceNodes is for records that have a current value — an // oracle that moved from "future" to "intent" has one status — where merging // would silently keep the old value alongside the new one. Restating an // unchanged record still reports zero and writes no history. -func (g *Graph) ReplaceNodes(ctx context.Context, nodes []Node) (uint64, error) { +func (g *Graph) ReplaceNodes(ctx context.Context, nodes []*cstxproto.Node) (uint64, error) { if err := contextError(ctx); err != nil { return 0, err } return g.eng.graphReplaceNodes(ctx, nodes) } -// AddEdges atomically adds or merges relationships. -func (g *Graph) AddEdges(ctx context.Context, edges []Edge) (uint64, error) { +// AddRelationships atomically adds or merges generated protobuf relationships. +func (g *Graph) AddRelationships(ctx context.Context, relationships []*cstxproto.Relationship) (uint64, error) { if err := contextError(ctx); err != nil { return 0, err } - return g.eng.graphAddEdges(ctx, edges) + return g.eng.graphAddRelationships(ctx, relationships) +} + +// AddRelationship adds or merges one generated protobuf relationship and +// returns its canonical stored representation. +func (g *Graph) AddRelationship(ctx context.Context, relationship *cstxproto.Relationship) (*cstxproto.Relationship, error) { + if err := contextError(ctx); err != nil { + return nil, err + } + if relationship == nil { + return nil, &Error{Code: CodeInvalidArgument, Operation: "graph.add_relationship", Message: "relationship must not be nil"} + } + return g.eng.graphAddRelationship(ctx, relationship) } // DeleteNodes atomically removes nodes and all incident relationships. @@ -48,28 +64,28 @@ func (g *Graph) DeleteNodes(ctx context.Context, nodeIDs []string) (uint64, erro return g.eng.graphDeleteNodes(ctx, nodeIDs) } -// DeleteEdges atomically removes relationships by stable CSTX ID. -func (g *Graph) DeleteEdges(ctx context.Context, edgeIDs []string) (uint64, error) { +// DeleteRelationships atomically removes relationships by stable CSTX ID. +func (g *Graph) DeleteRelationships(ctx context.Context, relationshipIDs []string) (uint64, error) { if err := contextError(ctx); err != nil { return 0, err } - return g.eng.graphDeleteEdges(ctx, edgeIDs) + return g.eng.graphDeleteRelationships(ctx, relationshipIDs) } -// Ingest feeds one linked native-plugin payload into the shared graph. -func (g *Graph) Ingest(ctx context.Context, source string, data []byte) (uint64, error) { +// Node returns one node or a *Error with CodeNotFound. +func (g *Graph) Node(ctx context.Context, nodeID string) (*cstxproto.Node, error) { if err := contextError(ctx); err != nil { - return 0, err + return nil, err } - return g.eng.graphIngest(ctx, source, data) + return g.eng.graphNode(ctx, nodeID) } -// Node returns one node or a *Error with CodeNotFound. -func (g *Graph) Node(ctx context.Context, nodeID string) (Node, error) { +// Relationship returns one generated protobuf relationship or CodeNotFound. +func (g *Graph) Relationship(ctx context.Context, relationshipID string) (*cstxproto.Relationship, error) { if err := contextError(ctx); err != nil { - return Node{}, err + return nil, err } - return g.eng.graphNode(ctx, nodeID) + return g.eng.graphRelationship(ctx, relationshipID) } // Contains reports node existence without materializing the node. @@ -88,54 +104,63 @@ func (g *Graph) NodeCount(ctx context.Context) (uint64, error) { return g.eng.graphNodeCount(ctx) } -// EdgeCount returns the current number of relationships. -func (g *Graph) EdgeCount(ctx context.Context) (uint64, error) { +// RelationshipCount returns the current number of relationships. +func (g *Graph) RelationshipCount(ctx context.Context) (uint64, error) { if err := contextError(ctx); err != nil { return 0, err } - return g.eng.graphEdgeCount(ctx) + return g.eng.graphRelationshipCount(ctx) } // Stats returns small aggregate counts. -func (g *Graph) Stats(ctx context.Context) (GraphStats, error) { +func (g *Graph) Stats(ctx context.Context) (*cstxproto.GraphStats, error) { if err := contextError(ctx); err != nil { - return GraphStats{}, err + return nil, err } return g.eng.graphStats(ctx) } // Nodes creates a lazy cursor over nodes matching the filter. The zero // filter and options select everything with runtime defaults. -func (g *Graph) Nodes(ctx context.Context, filter NodeFilter, options CollectionOptions) (*GraphCursor, error) { +func (g *Graph) Nodes(ctx context.Context, query *cstxproto.NodeQuery) (*GraphCursor, error) { if err := contextError(ctx); err != nil { return nil, err } - cursor, err := g.eng.graphNodes(ctx, filter, options.normalize()) + if query == nil { + query = &cstxproto.NodeQuery{} + } + cursor, err := g.eng.graphNodes(ctx, query) if err != nil { return nil, err } return &GraphCursor{inner: cursor, kind: CursorKindNodes}, nil } -// Edges creates a lazy cursor over relationships matching the filter. -func (g *Graph) Edges(ctx context.Context, filter EdgeFilter, options CollectionOptions) (*GraphCursor, error) { +// Relationships creates a lazy cursor over generated protobuf relationships. +func (g *Graph) Relationships(ctx context.Context, query *cstxproto.RelationshipQuery) (*GraphCursor, error) { if err := contextError(ctx); err != nil { return nil, err } - cursor, err := g.eng.graphEdges(ctx, filter, options.normalize()) + if query == nil { + query = &cstxproto.RelationshipQuery{} + } + cursor, err := g.eng.graphRelationships(ctx, query) if err != nil { return nil, err } - return &GraphCursor{inner: cursor, kind: CursorKindEdges}, nil + return &GraphCursor{inner: cursor, kind: CursorKindRelationships}, nil } // Neighbors lazily traverses neighboring nodes. Direction is "out", "in", // or "both". -func (g *Graph) Neighbors(ctx context.Context, nodeID, direction string, options CollectionOptions) (*GraphCursor, error) { +func (g *Graph) Neighbors(ctx context.Context, query *cstxproto.NeighborQuery) (*GraphCursor, error) { if err := contextError(ctx); err != nil { return nil, err } - cursor, err := g.eng.graphNeighbors(ctx, nodeID, direction, options.normalize()) + if query == nil { + return nil, &Error{Code: CodeInvalidArgument, Operation: "graph.neighbors", Message: "query must not be nil"} + } + cursor, err := g.eng.graphNeighbors(ctx, query) if err != nil { return nil, err } @@ -143,63 +168,43 @@ func (g *Graph) Neighbors(ctx context.Context, nodeID, direction string, options } // Query executes the graph DSL and returns a lazy cursor over terminal nodes. -func (g *Graph) Query(ctx context.Context, expression string, options QueryOptions) (*GraphCursor, error) { +func (g *Graph) Query(ctx context.Context, query *cstxproto.GraphQuery) (*GraphCursor, error) { if err := contextError(ctx); err != nil { return nil, err } - options.Collection = options.Collection.normalize() - cursor, err := g.eng.graphQuery(ctx, expression, options) + if query == nil { + return nil, &Error{Code: CodeInvalidArgument, Operation: "graph.query", Message: "query must not be nil"} + } + cursor, err := g.eng.graphQuery(ctx, query) if err != nil { return nil, err } return &GraphCursor{inner: cursor, kind: CursorKindNodes}, nil } -// Analyze executes one graph algorithm. The result is nil, bool, or -// *GraphCursor according to the selected algorithm. -func (g *Graph) Analyze(ctx context.Context, algorithm map[string]any, selection ...string) (any, error) { +// Analyze executes one generated protobuf algorithm. A boolean result is +// returned through boolean; collection results use cursor. Both are nil when +// the algorithm has no value result. +func (g *Graph) Analyze(ctx context.Context, algorithm *cstxproto.Algorithm, selection *string) (cursor *GraphCursor, boolean *bool, err error) { if err := contextError(ctx); err != nil { - return nil, err - } - if len(selection) > 1 { - return nil, &Error{Code: CodeInvalidArgument, Operation: "graph.analyze", Message: "at most one selection expression is allowed"} + return nil, nil, err } - var selected *string - if len(selection) == 1 { - selected = &selection[0] + if algorithm == nil { + return nil, nil, &Error{Code: CodeInvalidArgument, Operation: "graph.analyze", Message: "algorithm must not be nil"} } - kind, boolean, cursor, err := g.eng.graphAnalyze(ctx, algorithm, selected) + kind, value, nativeCursor, err := g.eng.graphAnalyze(ctx, algorithm, selection) if err != nil { - return nil, err + return nil, nil, err } switch kind { case 0: - return nil, nil + return nil, nil, nil case 1: - return boolean, nil + return nil, &value, nil case 2: - return &GraphCursor{inner: cursor, kind: algorithmCursorKind(algorithm)}, nil - default: - return nil, &Error{Code: CodeInternal, Operation: "graph.analyze", Message: "unknown algorithm result kind"} - } -} - -func algorithmCursorKind(algorithm map[string]any) CursorKind { - switch algorithm["name"] { - case "weak_components", "strong_components": - return CursorKindComponents - case "cycle_basis": - return CursorKindCycles - case "bridges": - return CursorKindNodePairs - case "core_numbers", "betweenness", "closeness": - return CursorKindNodeScores - case "shortest_paths": - return CursorKindPaths - case "leiden": - return CursorKindCommunities + return &GraphCursor{inner: nativeCursor, kind: algorithmCursorKind(algorithm)}, nil, nil default: - return CursorKindNodes + return nil, nil, &Error{Code: CodeInternal, Operation: "graph.analyze", Message: "unknown algorithm result kind"} } } diff --git a/go/lib/darwin_amd64/libcstx_ffi.a b/go/lib/darwin_amd64/libcstx_ffi.a index 8597bd2..728b112 100644 Binary files a/go/lib/darwin_amd64/libcstx_ffi.a and b/go/lib/darwin_amd64/libcstx_ffi.a differ diff --git a/go/lib/darwin_arm64/libcstx_ffi.a b/go/lib/darwin_arm64/libcstx_ffi.a index 33186b3..ba9e7cc 100644 Binary files a/go/lib/darwin_arm64/libcstx_ffi.a and b/go/lib/darwin_arm64/libcstx_ffi.a differ diff --git a/go/lib/linux_amd64/libcstx_ffi.a b/go/lib/linux_amd64/libcstx_ffi.a index addff3c..568f8bf 100644 Binary files a/go/lib/linux_amd64/libcstx_ffi.a and b/go/lib/linux_amd64/libcstx_ffi.a differ diff --git a/go/lib/linux_arm64/libcstx_ffi.a b/go/lib/linux_arm64/libcstx_ffi.a index 7a19a6f..cadec22 100644 Binary files a/go/lib/linux_arm64/libcstx_ffi.a and b/go/lib/linux_arm64/libcstx_ffi.a differ diff --git a/go/lib/windows_amd64/libcstx_ffi.a b/go/lib/windows_amd64/libcstx_ffi.a index 6dfffbd..75b82ec 100644 Binary files a/go/lib/windows_amd64/libcstx_ffi.a and b/go/lib/windows_amd64/libcstx_ffi.a differ diff --git a/go/options.go b/go/options.go index f7be232..d36b9b7 100644 --- a/go/options.go +++ b/go/options.go @@ -1,88 +1,4 @@ package cstx -import "encoding/json" - // DefaultCursorPageSize matches the Rust runtime default. const DefaultCursorPageSize = 1024 - -// NodeFilter pushes node selection into Rust before values are materialized. -type NodeFilter struct { - Types []string `json:"types"` - IDs []string `json:"ids"` - Sources []string `json:"sources"` - FlagsAll uint64 `json:"flags_all"` - FlagsAny uint64 `json:"flags_any"` - FlagsNone uint64 `json:"flags_none"` -} - -func (f NodeFilter) MarshalJSON() ([]byte, error) { - type wire NodeFilter - f.Types = orEmpty(f.Types) - f.IDs = orEmpty(f.IDs) - f.Sources = orEmpty(f.Sources) - return json.Marshal(wire(f)) -} - -// EdgeFilter pushes relationship selection into Rust. -type EdgeFilter struct { - SourceID string `json:"source_id"` - TargetID string `json:"target_id"` - Relations []string `json:"relations"` - Sources []string `json:"sources"` -} - -func (f EdgeFilter) MarshalJSON() ([]byte, error) { - // source_id/target_id are Option in Rust: absent means null, - // and Some("") would filter on an empty ID instead of disabling it. - type wire struct { - SourceID *string `json:"source_id"` - TargetID *string `json:"target_id"` - Relations []string `json:"relations"` - Sources []string `json:"sources"` - } - return json.Marshal(wire{ - SourceID: nonEmpty(f.SourceID), - TargetID: nonEmpty(f.TargetID), - Relations: orEmpty(f.Relations), - Sources: orEmpty(f.Sources), - }) -} - -// CollectionOptions selects the iterator convenience window and ordering. -// Explicit random access uses GraphCursor.Page(limit, page). -type CollectionOptions struct { - Limit *int `json:"limit"` - Page int `json:"page"` - Order Order `json:"order"` -} - -func (o CollectionOptions) normalize() CollectionOptions { - if o.Page <= 0 { - o.Page = 1 - } - if o.Order == "" { - o.Order = OrderUnspecified - } - return o -} - -// QueryOptions applies unified collection paging and CSTX flag semantics. -type QueryOptions struct { - Collection CollectionOptions `json:"collection"` - ExcludeMask uint64 `json:"exclude_mask"` - IncludeMask uint64 `json:"include_mask"` -} - -func orEmpty(value []string) []string { - if value == nil { - return []string{} - } - return value -} - -func nonEmpty(value string) *string { - if value == "" { - return nil - } - return &value -} diff --git a/go/plugins/easm/easm.go b/go/plugins/easm/easm.go new file mode 100644 index 0000000..0708658 --- /dev/null +++ b/go/plugins/easm/easm.go @@ -0,0 +1,2046 @@ +// @generated by cstx-codegen — DO NOT EDIT MANUALLY + +package easm + +import ( + "encoding/json" + "fmt" + + "github.com/chainreactors/libcstx/go/proto/cstxproto" +) + +// Node is one graph node as this extension's schema declares it. +// +// The payload crosses the boundary as an EntityValue: field names from the +// schema document, each value in the branch its column declares. Nothing here +// carries a field number, which is what lets a type declared at runtime travel +// the same way with no generated code at all. +type Node interface { + CstxType() string + EntityValue() (*cstxproto.EntityValue, error) +} + +// Domain is the "domain" node type. +type Domain struct { + Host string // host + Extra map[string]any // extra +} + +func (d Domain) CstxType() string { return "domain" } + +// EntityValue encodes Domain as the schema-named payload. +func (d Domain) EntityValue() (*cstxproto.EntityValue, error) { + fields := make([]*cstxproto.EntityField, 0, 2) + if len(d.Extra) > 0 { + encoded, err := json.Marshal(d.Extra) + if err != nil { + return nil, fmt.Errorf("cstx: field %q is not encodable as JSON: %w", "extra", err) + } + fields = append(fields, &cstxproto.EntityField{Name: "extra", Value: &cstxproto.EntityField_Text{Text: string(encoded)}}) + } + fields = append(fields, &cstxproto.EntityField{Name: "host", Value: &cstxproto.EntityField_Text{Text: d.Host}}) + return &cstxproto.EntityValue{NodeType: "domain", Fields: fields}, nil +} + +// Node wraps the payload as a graph node. The id is left unset: identity is +// the schema document's rule and the runtime derives it from the payload. +func (d Domain) Node(sources ...string) (*cstxproto.Node, error) { + value, err := d.EntityValue() + if err != nil { + return nil, err + } + return &cstxproto.Node{Value: value, Sources: sources}, nil +} + +// DomainFrom reads one payload back into Domain. Names the schema does not +// declare are left alone: a producer may send more than this build knows. +func DomainFrom(value *cstxproto.EntityValue) (Domain, error) { + var out Domain + if got := value.GetNodeType(); got != "domain" { + return out, fmt.Errorf("cstx: expected node type %q, got %q", "domain", got) + } + for _, field := range value.GetFields() { + switch field.GetName() { + case "host": + out.Host = field.GetText() + case "extra": + if raw := field.GetText(); raw != "" { + if err := json.Unmarshal([]byte(raw), &out.Extra); err != nil { + return out, fmt.Errorf("cstx: field %q is not a JSON document: %w", "extra", err) + } + } + } + } + return out, nil +} + +// Subdomain is the "subdomain" node type. +type Subdomain struct { + Host string // host + IsTld *bool // is_tld + Ttl *int64 // ttl + Resolver []string // resolver + A []string // a + Aaaa []string // aaaa + Cname []string // cname + Mx []string // mx + Ns []string // ns + Txt []string // txt + Extra map[string]any // extra + RootDomain *string // root_domain +} + +func (s Subdomain) CstxType() string { return "subdomain" } + +// EntityValue encodes Subdomain as the schema-named payload. +func (s Subdomain) EntityValue() (*cstxproto.EntityValue, error) { + fields := make([]*cstxproto.EntityField, 0, 12) + if len(s.A) > 0 { + fields = append(fields, &cstxproto.EntityField{Name: "a", Value: &cstxproto.EntityField_List{List: &cstxproto.StringList{Values: s.A}}}) + } + if len(s.Aaaa) > 0 { + fields = append(fields, &cstxproto.EntityField{Name: "aaaa", Value: &cstxproto.EntityField_List{List: &cstxproto.StringList{Values: s.Aaaa}}}) + } + if len(s.Cname) > 0 { + fields = append(fields, &cstxproto.EntityField{Name: "cname", Value: &cstxproto.EntityField_List{List: &cstxproto.StringList{Values: s.Cname}}}) + } + if len(s.Extra) > 0 { + encoded, err := json.Marshal(s.Extra) + if err != nil { + return nil, fmt.Errorf("cstx: field %q is not encodable as JSON: %w", "extra", err) + } + fields = append(fields, &cstxproto.EntityField{Name: "extra", Value: &cstxproto.EntityField_Text{Text: string(encoded)}}) + } + fields = append(fields, &cstxproto.EntityField{Name: "host", Value: &cstxproto.EntityField_Text{Text: s.Host}}) + if s.IsTld != nil { + fields = append(fields, &cstxproto.EntityField{Name: "is_tld", Value: &cstxproto.EntityField_Flag{Flag: *s.IsTld}}) + } + if len(s.Mx) > 0 { + fields = append(fields, &cstxproto.EntityField{Name: "mx", Value: &cstxproto.EntityField_List{List: &cstxproto.StringList{Values: s.Mx}}}) + } + if len(s.Ns) > 0 { + fields = append(fields, &cstxproto.EntityField{Name: "ns", Value: &cstxproto.EntityField_List{List: &cstxproto.StringList{Values: s.Ns}}}) + } + if len(s.Resolver) > 0 { + fields = append(fields, &cstxproto.EntityField{Name: "resolver", Value: &cstxproto.EntityField_List{List: &cstxproto.StringList{Values: s.Resolver}}}) + } + if s.RootDomain != nil { + fields = append(fields, &cstxproto.EntityField{Name: "root_domain", Value: &cstxproto.EntityField_Text{Text: *s.RootDomain}}) + } + if s.Ttl != nil { + fields = append(fields, &cstxproto.EntityField{Name: "ttl", Value: &cstxproto.EntityField_Number{Number: *s.Ttl}}) + } + if len(s.Txt) > 0 { + fields = append(fields, &cstxproto.EntityField{Name: "txt", Value: &cstxproto.EntityField_List{List: &cstxproto.StringList{Values: s.Txt}}}) + } + return &cstxproto.EntityValue{NodeType: "subdomain", Fields: fields}, nil +} + +// Node wraps the payload as a graph node. The id is left unset: identity is +// the schema document's rule and the runtime derives it from the payload. +func (s Subdomain) Node(sources ...string) (*cstxproto.Node, error) { + value, err := s.EntityValue() + if err != nil { + return nil, err + } + return &cstxproto.Node{Value: value, Sources: sources}, nil +} + +// SubdomainFrom reads one payload back into Subdomain. Names the schema does not +// declare are left alone: a producer may send more than this build knows. +func SubdomainFrom(value *cstxproto.EntityValue) (Subdomain, error) { + var out Subdomain + if got := value.GetNodeType(); got != "subdomain" { + return out, fmt.Errorf("cstx: expected node type %q, got %q", "subdomain", got) + } + for _, field := range value.GetFields() { + switch field.GetName() { + case "host": + out.Host = field.GetText() + case "is_tld": + carried := field.GetFlag() + out.IsTld = &carried + case "ttl": + carried := field.GetNumber() + out.Ttl = &carried + case "resolver": + out.Resolver = field.GetList().GetValues() + case "a": + out.A = field.GetList().GetValues() + case "aaaa": + out.Aaaa = field.GetList().GetValues() + case "cname": + out.Cname = field.GetList().GetValues() + case "mx": + out.Mx = field.GetList().GetValues() + case "ns": + out.Ns = field.GetList().GetValues() + case "txt": + out.Txt = field.GetList().GetValues() + case "extra": + if raw := field.GetText(); raw != "" { + if err := json.Unmarshal([]byte(raw), &out.Extra); err != nil { + return out, fmt.Errorf("cstx: field %q is not a JSON document: %w", "extra", err) + } + } + case "root_domain": + carried := field.GetText() + out.RootDomain = &carried + } + } + return out, nil +} + +// Ip is the "ip" node type. +type Ip struct { + Ip string // ip + Country *string // country + Area *string // area + AsnNumber *string // asn_number + AsName *string // as_name + CdnName *string // cdn_name + CloudName *string // cloud_name + WafName *string // waf_name + Cdn *bool // cdn + Cloud *bool // cloud + Waf *bool // waf + Extra map[string]any // extra + Cidr *string // cidr +} + +func (i Ip) CstxType() string { return "ip" } + +// EntityValue encodes Ip as the schema-named payload. +func (i Ip) EntityValue() (*cstxproto.EntityValue, error) { + fields := make([]*cstxproto.EntityField, 0, 13) + if i.Area != nil { + fields = append(fields, &cstxproto.EntityField{Name: "area", Value: &cstxproto.EntityField_Text{Text: *i.Area}}) + } + if i.AsName != nil { + fields = append(fields, &cstxproto.EntityField{Name: "as_name", Value: &cstxproto.EntityField_Text{Text: *i.AsName}}) + } + if i.AsnNumber != nil { + fields = append(fields, &cstxproto.EntityField{Name: "asn_number", Value: &cstxproto.EntityField_Text{Text: *i.AsnNumber}}) + } + if i.Cdn != nil { + fields = append(fields, &cstxproto.EntityField{Name: "cdn", Value: &cstxproto.EntityField_Flag{Flag: *i.Cdn}}) + } + if i.CdnName != nil { + fields = append(fields, &cstxproto.EntityField{Name: "cdn_name", Value: &cstxproto.EntityField_Text{Text: *i.CdnName}}) + } + if i.Cidr != nil { + fields = append(fields, &cstxproto.EntityField{Name: "cidr", Value: &cstxproto.EntityField_Text{Text: *i.Cidr}}) + } + if i.Cloud != nil { + fields = append(fields, &cstxproto.EntityField{Name: "cloud", Value: &cstxproto.EntityField_Flag{Flag: *i.Cloud}}) + } + if i.CloudName != nil { + fields = append(fields, &cstxproto.EntityField{Name: "cloud_name", Value: &cstxproto.EntityField_Text{Text: *i.CloudName}}) + } + if i.Country != nil { + fields = append(fields, &cstxproto.EntityField{Name: "country", Value: &cstxproto.EntityField_Text{Text: *i.Country}}) + } + if len(i.Extra) > 0 { + encoded, err := json.Marshal(i.Extra) + if err != nil { + return nil, fmt.Errorf("cstx: field %q is not encodable as JSON: %w", "extra", err) + } + fields = append(fields, &cstxproto.EntityField{Name: "extra", Value: &cstxproto.EntityField_Text{Text: string(encoded)}}) + } + fields = append(fields, &cstxproto.EntityField{Name: "ip", Value: &cstxproto.EntityField_Text{Text: i.Ip}}) + if i.Waf != nil { + fields = append(fields, &cstxproto.EntityField{Name: "waf", Value: &cstxproto.EntityField_Flag{Flag: *i.Waf}}) + } + if i.WafName != nil { + fields = append(fields, &cstxproto.EntityField{Name: "waf_name", Value: &cstxproto.EntityField_Text{Text: *i.WafName}}) + } + return &cstxproto.EntityValue{NodeType: "ip", Fields: fields}, nil +} + +// Node wraps the payload as a graph node. The id is left unset: identity is +// the schema document's rule and the runtime derives it from the payload. +func (i Ip) Node(sources ...string) (*cstxproto.Node, error) { + value, err := i.EntityValue() + if err != nil { + return nil, err + } + return &cstxproto.Node{Value: value, Sources: sources}, nil +} + +// IpFrom reads one payload back into Ip. Names the schema does not +// declare are left alone: a producer may send more than this build knows. +func IpFrom(value *cstxproto.EntityValue) (Ip, error) { + var out Ip + if got := value.GetNodeType(); got != "ip" { + return out, fmt.Errorf("cstx: expected node type %q, got %q", "ip", got) + } + for _, field := range value.GetFields() { + switch field.GetName() { + case "ip": + out.Ip = field.GetText() + case "country": + carried := field.GetText() + out.Country = &carried + case "area": + carried := field.GetText() + out.Area = &carried + case "asn_number": + carried := field.GetText() + out.AsnNumber = &carried + case "as_name": + carried := field.GetText() + out.AsName = &carried + case "cdn_name": + carried := field.GetText() + out.CdnName = &carried + case "cloud_name": + carried := field.GetText() + out.CloudName = &carried + case "waf_name": + carried := field.GetText() + out.WafName = &carried + case "cdn": + carried := field.GetFlag() + out.Cdn = &carried + case "cloud": + carried := field.GetFlag() + out.Cloud = &carried + case "waf": + carried := field.GetFlag() + out.Waf = &carried + case "extra": + if raw := field.GetText(); raw != "" { + if err := json.Unmarshal([]byte(raw), &out.Extra); err != nil { + return out, fmt.Errorf("cstx: field %q is not a JSON document: %w", "extra", err) + } + } + case "cidr": + carried := field.GetText() + out.Cidr = &carried + } + } + return out, nil +} + +// Cidr is the "cidr" node type. +type Cidr struct { + Cidr string // cidr + Extra map[string]any // extra +} + +func (c Cidr) CstxType() string { return "cidr" } + +// EntityValue encodes Cidr as the schema-named payload. +func (c Cidr) EntityValue() (*cstxproto.EntityValue, error) { + fields := make([]*cstxproto.EntityField, 0, 2) + fields = append(fields, &cstxproto.EntityField{Name: "cidr", Value: &cstxproto.EntityField_Text{Text: c.Cidr}}) + if len(c.Extra) > 0 { + encoded, err := json.Marshal(c.Extra) + if err != nil { + return nil, fmt.Errorf("cstx: field %q is not encodable as JSON: %w", "extra", err) + } + fields = append(fields, &cstxproto.EntityField{Name: "extra", Value: &cstxproto.EntityField_Text{Text: string(encoded)}}) + } + return &cstxproto.EntityValue{NodeType: "cidr", Fields: fields}, nil +} + +// Node wraps the payload as a graph node. The id is left unset: identity is +// the schema document's rule and the runtime derives it from the payload. +func (c Cidr) Node(sources ...string) (*cstxproto.Node, error) { + value, err := c.EntityValue() + if err != nil { + return nil, err + } + return &cstxproto.Node{Value: value, Sources: sources}, nil +} + +// CidrFrom reads one payload back into Cidr. Names the schema does not +// declare are left alone: a producer may send more than this build knows. +func CidrFrom(value *cstxproto.EntityValue) (Cidr, error) { + var out Cidr + if got := value.GetNodeType(); got != "cidr" { + return out, fmt.Errorf("cstx: expected node type %q, got %q", "cidr", got) + } + for _, field := range value.GetFields() { + switch field.GetName() { + case "cidr": + out.Cidr = field.GetText() + case "extra": + if raw := field.GetText(); raw != "" { + if err := json.Unmarshal([]byte(raw), &out.Extra); err != nil { + return out, fmt.Errorf("cstx: field %q is not a JSON document: %w", "extra", err) + } + } + } + } + return out, nil +} + +// Port is the "port" node type. +type Port struct { + Ip string // ip + Port string // port + Protocol string // protocol + Extra map[string]any // extra +} + +func (p Port) CstxType() string { return "port" } + +// EntityValue encodes Port as the schema-named payload. +func (p Port) EntityValue() (*cstxproto.EntityValue, error) { + fields := make([]*cstxproto.EntityField, 0, 4) + if len(p.Extra) > 0 { + encoded, err := json.Marshal(p.Extra) + if err != nil { + return nil, fmt.Errorf("cstx: field %q is not encodable as JSON: %w", "extra", err) + } + fields = append(fields, &cstxproto.EntityField{Name: "extra", Value: &cstxproto.EntityField_Text{Text: string(encoded)}}) + } + fields = append(fields, &cstxproto.EntityField{Name: "ip", Value: &cstxproto.EntityField_Text{Text: p.Ip}}) + fields = append(fields, &cstxproto.EntityField{Name: "port", Value: &cstxproto.EntityField_Text{Text: p.Port}}) + fields = append(fields, &cstxproto.EntityField{Name: "protocol", Value: &cstxproto.EntityField_Text{Text: p.Protocol}}) + return &cstxproto.EntityValue{NodeType: "port", Fields: fields}, nil +} + +// Node wraps the payload as a graph node. The id is left unset: identity is +// the schema document's rule and the runtime derives it from the payload. +func (p Port) Node(sources ...string) (*cstxproto.Node, error) { + value, err := p.EntityValue() + if err != nil { + return nil, err + } + return &cstxproto.Node{Value: value, Sources: sources}, nil +} + +// PortFrom reads one payload back into Port. Names the schema does not +// declare are left alone: a producer may send more than this build knows. +func PortFrom(value *cstxproto.EntityValue) (Port, error) { + var out Port + if got := value.GetNodeType(); got != "port" { + return out, fmt.Errorf("cstx: expected node type %q, got %q", "port", got) + } + for _, field := range value.GetFields() { + switch field.GetName() { + case "ip": + out.Ip = field.GetText() + case "port": + out.Port = field.GetText() + case "protocol": + out.Protocol = field.GetText() + case "extra": + if raw := field.GetText(); raw != "" { + if err := json.Unmarshal([]byte(raw), &out.Extra); err != nil { + return out, fmt.Errorf("cstx: field %q is not a JSON document: %w", "extra", err) + } + } + } + } + return out, nil +} + +// App is the "app" node type. +type App struct { + AppId string // app_id + Url *string // url + Frameworks []string // frameworks + Title *string // title + Midware *string // midware + Status *string // status + StatusCode *int64 // status_code + Host *string // host + ContentType *string // content_type + BodyLength *int64 // body_length + HeaderLength *int64 // header_length + ScreenshotId *string // screenshot_id + ScreenshotPath *string // screenshot_path + Ip *string // ip + Port *string // port + Extra map[string]any // extra +} + +func (a App) CstxType() string { return "app" } + +// EntityValue encodes App as the schema-named payload. +func (a App) EntityValue() (*cstxproto.EntityValue, error) { + fields := make([]*cstxproto.EntityField, 0, 16) + fields = append(fields, &cstxproto.EntityField{Name: "app_id", Value: &cstxproto.EntityField_Text{Text: a.AppId}}) + if a.BodyLength != nil { + fields = append(fields, &cstxproto.EntityField{Name: "body_length", Value: &cstxproto.EntityField_Number{Number: *a.BodyLength}}) + } + if a.ContentType != nil { + fields = append(fields, &cstxproto.EntityField{Name: "content_type", Value: &cstxproto.EntityField_Text{Text: *a.ContentType}}) + } + if len(a.Extra) > 0 { + encoded, err := json.Marshal(a.Extra) + if err != nil { + return nil, fmt.Errorf("cstx: field %q is not encodable as JSON: %w", "extra", err) + } + fields = append(fields, &cstxproto.EntityField{Name: "extra", Value: &cstxproto.EntityField_Text{Text: string(encoded)}}) + } + if len(a.Frameworks) > 0 { + fields = append(fields, &cstxproto.EntityField{Name: "frameworks", Value: &cstxproto.EntityField_List{List: &cstxproto.StringList{Values: a.Frameworks}}}) + } + if a.HeaderLength != nil { + fields = append(fields, &cstxproto.EntityField{Name: "header_length", Value: &cstxproto.EntityField_Number{Number: *a.HeaderLength}}) + } + if a.Host != nil { + fields = append(fields, &cstxproto.EntityField{Name: "host", Value: &cstxproto.EntityField_Text{Text: *a.Host}}) + } + if a.Ip != nil { + fields = append(fields, &cstxproto.EntityField{Name: "ip", Value: &cstxproto.EntityField_Text{Text: *a.Ip}}) + } + if a.Midware != nil { + fields = append(fields, &cstxproto.EntityField{Name: "midware", Value: &cstxproto.EntityField_Text{Text: *a.Midware}}) + } + if a.Port != nil { + fields = append(fields, &cstxproto.EntityField{Name: "port", Value: &cstxproto.EntityField_Text{Text: *a.Port}}) + } + if a.ScreenshotId != nil { + fields = append(fields, &cstxproto.EntityField{Name: "screenshot_id", Value: &cstxproto.EntityField_Text{Text: *a.ScreenshotId}}) + } + if a.ScreenshotPath != nil { + fields = append(fields, &cstxproto.EntityField{Name: "screenshot_path", Value: &cstxproto.EntityField_Text{Text: *a.ScreenshotPath}}) + } + if a.Status != nil { + fields = append(fields, &cstxproto.EntityField{Name: "status", Value: &cstxproto.EntityField_Text{Text: *a.Status}}) + } + if a.StatusCode != nil { + fields = append(fields, &cstxproto.EntityField{Name: "status_code", Value: &cstxproto.EntityField_Number{Number: *a.StatusCode}}) + } + if a.Title != nil { + fields = append(fields, &cstxproto.EntityField{Name: "title", Value: &cstxproto.EntityField_Text{Text: *a.Title}}) + } + if a.Url != nil { + fields = append(fields, &cstxproto.EntityField{Name: "url", Value: &cstxproto.EntityField_Text{Text: *a.Url}}) + } + return &cstxproto.EntityValue{NodeType: "app", Fields: fields}, nil +} + +// Node wraps the payload as a graph node. The id is left unset: identity is +// the schema document's rule and the runtime derives it from the payload. +func (a App) Node(sources ...string) (*cstxproto.Node, error) { + value, err := a.EntityValue() + if err != nil { + return nil, err + } + return &cstxproto.Node{Value: value, Sources: sources}, nil +} + +// AppFrom reads one payload back into App. Names the schema does not +// declare are left alone: a producer may send more than this build knows. +func AppFrom(value *cstxproto.EntityValue) (App, error) { + var out App + if got := value.GetNodeType(); got != "app" { + return out, fmt.Errorf("cstx: expected node type %q, got %q", "app", got) + } + for _, field := range value.GetFields() { + switch field.GetName() { + case "app_id": + out.AppId = field.GetText() + case "url": + carried := field.GetText() + out.Url = &carried + case "frameworks": + out.Frameworks = field.GetList().GetValues() + case "title": + carried := field.GetText() + out.Title = &carried + case "midware": + carried := field.GetText() + out.Midware = &carried + case "status": + carried := field.GetText() + out.Status = &carried + case "status_code": + carried := field.GetNumber() + out.StatusCode = &carried + case "host": + carried := field.GetText() + out.Host = &carried + case "content_type": + carried := field.GetText() + out.ContentType = &carried + case "body_length": + carried := field.GetNumber() + out.BodyLength = &carried + case "header_length": + carried := field.GetNumber() + out.HeaderLength = &carried + case "screenshot_id": + carried := field.GetText() + out.ScreenshotId = &carried + case "screenshot_path": + carried := field.GetText() + out.ScreenshotPath = &carried + case "ip": + carried := field.GetText() + out.Ip = &carried + case "port": + carried := field.GetText() + out.Port = &carried + case "extra": + if raw := field.GetText(); raw != "" { + if err := json.Unmarshal([]byte(raw), &out.Extra); err != nil { + return out, fmt.Errorf("cstx: field %q is not a JSON document: %w", "extra", err) + } + } + } + } + return out, nil +} + +// Url is the "url" node type. +type Url struct { + Scheme string // scheme + Host *string // host + Port *string // port + Path *string // path + Ip *string // ip + StatusCode *int64 // status_code + Title *string // title + BodyLength *int64 // body_length + ContentType *string // content_type + RedirectUrl *string // redirect_url + Frameworks []string // frameworks + Url string // url + Extra map[string]any // extra +} + +func (u Url) CstxType() string { return "url" } + +// EntityValue encodes Url as the schema-named payload. +func (u Url) EntityValue() (*cstxproto.EntityValue, error) { + fields := make([]*cstxproto.EntityField, 0, 13) + if u.BodyLength != nil { + fields = append(fields, &cstxproto.EntityField{Name: "body_length", Value: &cstxproto.EntityField_Number{Number: *u.BodyLength}}) + } + if u.ContentType != nil { + fields = append(fields, &cstxproto.EntityField{Name: "content_type", Value: &cstxproto.EntityField_Text{Text: *u.ContentType}}) + } + if len(u.Extra) > 0 { + encoded, err := json.Marshal(u.Extra) + if err != nil { + return nil, fmt.Errorf("cstx: field %q is not encodable as JSON: %w", "extra", err) + } + fields = append(fields, &cstxproto.EntityField{Name: "extra", Value: &cstxproto.EntityField_Text{Text: string(encoded)}}) + } + if len(u.Frameworks) > 0 { + fields = append(fields, &cstxproto.EntityField{Name: "frameworks", Value: &cstxproto.EntityField_List{List: &cstxproto.StringList{Values: u.Frameworks}}}) + } + if u.Host != nil { + fields = append(fields, &cstxproto.EntityField{Name: "host", Value: &cstxproto.EntityField_Text{Text: *u.Host}}) + } + if u.Ip != nil { + fields = append(fields, &cstxproto.EntityField{Name: "ip", Value: &cstxproto.EntityField_Text{Text: *u.Ip}}) + } + if u.Path != nil { + fields = append(fields, &cstxproto.EntityField{Name: "path", Value: &cstxproto.EntityField_Text{Text: *u.Path}}) + } + if u.Port != nil { + fields = append(fields, &cstxproto.EntityField{Name: "port", Value: &cstxproto.EntityField_Text{Text: *u.Port}}) + } + if u.RedirectUrl != nil { + fields = append(fields, &cstxproto.EntityField{Name: "redirect_url", Value: &cstxproto.EntityField_Text{Text: *u.RedirectUrl}}) + } + fields = append(fields, &cstxproto.EntityField{Name: "scheme", Value: &cstxproto.EntityField_Text{Text: u.Scheme}}) + if u.StatusCode != nil { + fields = append(fields, &cstxproto.EntityField{Name: "status_code", Value: &cstxproto.EntityField_Number{Number: *u.StatusCode}}) + } + if u.Title != nil { + fields = append(fields, &cstxproto.EntityField{Name: "title", Value: &cstxproto.EntityField_Text{Text: *u.Title}}) + } + fields = append(fields, &cstxproto.EntityField{Name: "url", Value: &cstxproto.EntityField_Text{Text: u.Url}}) + return &cstxproto.EntityValue{NodeType: "url", Fields: fields}, nil +} + +// Node wraps the payload as a graph node. The id is left unset: identity is +// the schema document's rule and the runtime derives it from the payload. +func (u Url) Node(sources ...string) (*cstxproto.Node, error) { + value, err := u.EntityValue() + if err != nil { + return nil, err + } + return &cstxproto.Node{Value: value, Sources: sources}, nil +} + +// UrlFrom reads one payload back into Url. Names the schema does not +// declare are left alone: a producer may send more than this build knows. +func UrlFrom(value *cstxproto.EntityValue) (Url, error) { + var out Url + if got := value.GetNodeType(); got != "url" { + return out, fmt.Errorf("cstx: expected node type %q, got %q", "url", got) + } + for _, field := range value.GetFields() { + switch field.GetName() { + case "scheme": + out.Scheme = field.GetText() + case "host": + carried := field.GetText() + out.Host = &carried + case "port": + carried := field.GetText() + out.Port = &carried + case "path": + carried := field.GetText() + out.Path = &carried + case "ip": + carried := field.GetText() + out.Ip = &carried + case "status_code": + carried := field.GetNumber() + out.StatusCode = &carried + case "title": + carried := field.GetText() + out.Title = &carried + case "body_length": + carried := field.GetNumber() + out.BodyLength = &carried + case "content_type": + carried := field.GetText() + out.ContentType = &carried + case "redirect_url": + carried := field.GetText() + out.RedirectUrl = &carried + case "frameworks": + out.Frameworks = field.GetList().GetValues() + case "url": + out.Url = field.GetText() + case "extra": + if raw := field.GetText(); raw != "" { + if err := json.Unmarshal([]byte(raw), &out.Extra); err != nil { + return out, fmt.Errorf("cstx: field %q is not a JSON document: %w", "extra", err) + } + } + } + } + return out, nil +} + +// Framework is the "framework" node type. +type Framework struct { + Name string // name + Part *string // part + Vendor *string // vendor + Product *string // product + Version *string // version + Tags []string // tags + IsFocus *bool // is_focus + Sources []string // sources + Extra map[string]any // extra +} + +func (f Framework) CstxType() string { return "framework" } + +// EntityValue encodes Framework as the schema-named payload. +func (f Framework) EntityValue() (*cstxproto.EntityValue, error) { + fields := make([]*cstxproto.EntityField, 0, 9) + if len(f.Extra) > 0 { + encoded, err := json.Marshal(f.Extra) + if err != nil { + return nil, fmt.Errorf("cstx: field %q is not encodable as JSON: %w", "extra", err) + } + fields = append(fields, &cstxproto.EntityField{Name: "extra", Value: &cstxproto.EntityField_Text{Text: string(encoded)}}) + } + if f.IsFocus != nil { + fields = append(fields, &cstxproto.EntityField{Name: "is_focus", Value: &cstxproto.EntityField_Flag{Flag: *f.IsFocus}}) + } + fields = append(fields, &cstxproto.EntityField{Name: "name", Value: &cstxproto.EntityField_Text{Text: f.Name}}) + if f.Part != nil { + fields = append(fields, &cstxproto.EntityField{Name: "part", Value: &cstxproto.EntityField_Text{Text: *f.Part}}) + } + if f.Product != nil { + fields = append(fields, &cstxproto.EntityField{Name: "product", Value: &cstxproto.EntityField_Text{Text: *f.Product}}) + } + if len(f.Sources) > 0 { + fields = append(fields, &cstxproto.EntityField{Name: "sources", Value: &cstxproto.EntityField_List{List: &cstxproto.StringList{Values: f.Sources}}}) + } + if len(f.Tags) > 0 { + fields = append(fields, &cstxproto.EntityField{Name: "tags", Value: &cstxproto.EntityField_List{List: &cstxproto.StringList{Values: f.Tags}}}) + } + if f.Vendor != nil { + fields = append(fields, &cstxproto.EntityField{Name: "vendor", Value: &cstxproto.EntityField_Text{Text: *f.Vendor}}) + } + if f.Version != nil { + fields = append(fields, &cstxproto.EntityField{Name: "version", Value: &cstxproto.EntityField_Text{Text: *f.Version}}) + } + return &cstxproto.EntityValue{NodeType: "framework", Fields: fields}, nil +} + +// Node wraps the payload as a graph node. The id is left unset: identity is +// the schema document's rule and the runtime derives it from the payload. +func (f Framework) Node(sources ...string) (*cstxproto.Node, error) { + value, err := f.EntityValue() + if err != nil { + return nil, err + } + return &cstxproto.Node{Value: value, Sources: sources}, nil +} + +// FrameworkFrom reads one payload back into Framework. Names the schema does not +// declare are left alone: a producer may send more than this build knows. +func FrameworkFrom(value *cstxproto.EntityValue) (Framework, error) { + var out Framework + if got := value.GetNodeType(); got != "framework" { + return out, fmt.Errorf("cstx: expected node type %q, got %q", "framework", got) + } + for _, field := range value.GetFields() { + switch field.GetName() { + case "name": + out.Name = field.GetText() + case "part": + carried := field.GetText() + out.Part = &carried + case "vendor": + carried := field.GetText() + out.Vendor = &carried + case "product": + carried := field.GetText() + out.Product = &carried + case "version": + carried := field.GetText() + out.Version = &carried + case "tags": + out.Tags = field.GetList().GetValues() + case "is_focus": + carried := field.GetFlag() + out.IsFocus = &carried + case "sources": + out.Sources = field.GetList().GetValues() + case "extra": + if raw := field.GetText(); raw != "" { + if err := json.Unmarshal([]byte(raw), &out.Extra); err != nil { + return out, fmt.Errorf("cstx: field %q is not a JSON document: %w", "extra", err) + } + } + } + } + return out, nil +} + +// Vuln is the "vuln" node type. +type Vuln struct { + Value string // value + VulnId *string // vuln_id + Name *string // name + AssetId *string // asset_id + Severity *string // severity + Tags []string // tags + Ip *string // ip + Host *string // host + Port *string // port + Protocol *string // protocol + Scheme *string // scheme + Url *string // url + Path *string // path + Pocname *string // pocname + Request *string // request + Response *string // response + Username *string // username + Password *string // password + Matched *bool // matched + Extracted *bool // extracted + Extra map[string]any // extra +} + +func (v Vuln) CstxType() string { return "vuln" } + +// EntityValue encodes Vuln as the schema-named payload. +func (v Vuln) EntityValue() (*cstxproto.EntityValue, error) { + fields := make([]*cstxproto.EntityField, 0, 21) + if v.AssetId != nil { + fields = append(fields, &cstxproto.EntityField{Name: "asset_id", Value: &cstxproto.EntityField_Text{Text: *v.AssetId}}) + } + if len(v.Extra) > 0 { + encoded, err := json.Marshal(v.Extra) + if err != nil { + return nil, fmt.Errorf("cstx: field %q is not encodable as JSON: %w", "extra", err) + } + fields = append(fields, &cstxproto.EntityField{Name: "extra", Value: &cstxproto.EntityField_Text{Text: string(encoded)}}) + } + if v.Extracted != nil { + fields = append(fields, &cstxproto.EntityField{Name: "extracted", Value: &cstxproto.EntityField_Flag{Flag: *v.Extracted}}) + } + if v.Host != nil { + fields = append(fields, &cstxproto.EntityField{Name: "host", Value: &cstxproto.EntityField_Text{Text: *v.Host}}) + } + if v.Ip != nil { + fields = append(fields, &cstxproto.EntityField{Name: "ip", Value: &cstxproto.EntityField_Text{Text: *v.Ip}}) + } + if v.Matched != nil { + fields = append(fields, &cstxproto.EntityField{Name: "matched", Value: &cstxproto.EntityField_Flag{Flag: *v.Matched}}) + } + if v.Name != nil { + fields = append(fields, &cstxproto.EntityField{Name: "name", Value: &cstxproto.EntityField_Text{Text: *v.Name}}) + } + if v.Password != nil { + fields = append(fields, &cstxproto.EntityField{Name: "password", Value: &cstxproto.EntityField_Text{Text: *v.Password}}) + } + if v.Path != nil { + fields = append(fields, &cstxproto.EntityField{Name: "path", Value: &cstxproto.EntityField_Text{Text: *v.Path}}) + } + if v.Pocname != nil { + fields = append(fields, &cstxproto.EntityField{Name: "pocname", Value: &cstxproto.EntityField_Text{Text: *v.Pocname}}) + } + if v.Port != nil { + fields = append(fields, &cstxproto.EntityField{Name: "port", Value: &cstxproto.EntityField_Text{Text: *v.Port}}) + } + if v.Protocol != nil { + fields = append(fields, &cstxproto.EntityField{Name: "protocol", Value: &cstxproto.EntityField_Text{Text: *v.Protocol}}) + } + if v.Request != nil { + fields = append(fields, &cstxproto.EntityField{Name: "request", Value: &cstxproto.EntityField_Text{Text: *v.Request}}) + } + if v.Response != nil { + fields = append(fields, &cstxproto.EntityField{Name: "response", Value: &cstxproto.EntityField_Text{Text: *v.Response}}) + } + if v.Scheme != nil { + fields = append(fields, &cstxproto.EntityField{Name: "scheme", Value: &cstxproto.EntityField_Text{Text: *v.Scheme}}) + } + if v.Severity != nil { + fields = append(fields, &cstxproto.EntityField{Name: "severity", Value: &cstxproto.EntityField_Text{Text: *v.Severity}}) + } + if len(v.Tags) > 0 { + fields = append(fields, &cstxproto.EntityField{Name: "tags", Value: &cstxproto.EntityField_List{List: &cstxproto.StringList{Values: v.Tags}}}) + } + if v.Url != nil { + fields = append(fields, &cstxproto.EntityField{Name: "url", Value: &cstxproto.EntityField_Text{Text: *v.Url}}) + } + if v.Username != nil { + fields = append(fields, &cstxproto.EntityField{Name: "username", Value: &cstxproto.EntityField_Text{Text: *v.Username}}) + } + fields = append(fields, &cstxproto.EntityField{Name: "value", Value: &cstxproto.EntityField_Text{Text: v.Value}}) + if v.VulnId != nil { + fields = append(fields, &cstxproto.EntityField{Name: "vuln_id", Value: &cstxproto.EntityField_Text{Text: *v.VulnId}}) + } + return &cstxproto.EntityValue{NodeType: "vuln", Fields: fields}, nil +} + +// Node wraps the payload as a graph node. The id is left unset: identity is +// the schema document's rule and the runtime derives it from the payload. +func (v Vuln) Node(sources ...string) (*cstxproto.Node, error) { + value, err := v.EntityValue() + if err != nil { + return nil, err + } + return &cstxproto.Node{Value: value, Sources: sources}, nil +} + +// VulnFrom reads one payload back into Vuln. Names the schema does not +// declare are left alone: a producer may send more than this build knows. +func VulnFrom(value *cstxproto.EntityValue) (Vuln, error) { + var out Vuln + if got := value.GetNodeType(); got != "vuln" { + return out, fmt.Errorf("cstx: expected node type %q, got %q", "vuln", got) + } + for _, field := range value.GetFields() { + switch field.GetName() { + case "value": + out.Value = field.GetText() + case "vuln_id": + carried := field.GetText() + out.VulnId = &carried + case "name": + carried := field.GetText() + out.Name = &carried + case "asset_id": + carried := field.GetText() + out.AssetId = &carried + case "severity": + carried := field.GetText() + out.Severity = &carried + case "tags": + out.Tags = field.GetList().GetValues() + case "ip": + carried := field.GetText() + out.Ip = &carried + case "host": + carried := field.GetText() + out.Host = &carried + case "port": + carried := field.GetText() + out.Port = &carried + case "protocol": + carried := field.GetText() + out.Protocol = &carried + case "scheme": + carried := field.GetText() + out.Scheme = &carried + case "url": + carried := field.GetText() + out.Url = &carried + case "path": + carried := field.GetText() + out.Path = &carried + case "pocname": + carried := field.GetText() + out.Pocname = &carried + case "request": + carried := field.GetText() + out.Request = &carried + case "response": + carried := field.GetText() + out.Response = &carried + case "username": + carried := field.GetText() + out.Username = &carried + case "password": + carried := field.GetText() + out.Password = &carried + case "matched": + carried := field.GetFlag() + out.Matched = &carried + case "extracted": + carried := field.GetFlag() + out.Extracted = &carried + case "extra": + if raw := field.GetText(); raw != "" { + if err := json.Unmarshal([]byte(raw), &out.Extra); err != nil { + return out, fmt.Errorf("cstx: field %q is not a JSON document: %w", "extra", err) + } + } + } + } + return out, nil +} + +// SarifVuln is the "sarif_vuln" node type. +type SarifVuln struct { + Value string // value + VulnId *string // vuln_id + Title *string // title + Description *string // description + Source *string // source + Target *string // target + Tags []string // tags + AssetCstxId *string // asset_cstx_id + Kind *string // kind + Level *string // level + BaselineState *string // baseline_state + RuleId *string // rule_id + Evidence *string // evidence + Extra map[string]any // extra +} + +func (s SarifVuln) CstxType() string { return "sarif_vuln" } + +// EntityValue encodes SarifVuln as the schema-named payload. +func (s SarifVuln) EntityValue() (*cstxproto.EntityValue, error) { + fields := make([]*cstxproto.EntityField, 0, 14) + if s.AssetCstxId != nil { + fields = append(fields, &cstxproto.EntityField{Name: "asset_cstx_id", Value: &cstxproto.EntityField_Text{Text: *s.AssetCstxId}}) + } + if s.BaselineState != nil { + fields = append(fields, &cstxproto.EntityField{Name: "baseline_state", Value: &cstxproto.EntityField_Text{Text: *s.BaselineState}}) + } + if s.Description != nil { + fields = append(fields, &cstxproto.EntityField{Name: "description", Value: &cstxproto.EntityField_Text{Text: *s.Description}}) + } + if s.Evidence != nil { + fields = append(fields, &cstxproto.EntityField{Name: "evidence", Value: &cstxproto.EntityField_Text{Text: *s.Evidence}}) + } + if len(s.Extra) > 0 { + encoded, err := json.Marshal(s.Extra) + if err != nil { + return nil, fmt.Errorf("cstx: field %q is not encodable as JSON: %w", "extra", err) + } + fields = append(fields, &cstxproto.EntityField{Name: "extra", Value: &cstxproto.EntityField_Text{Text: string(encoded)}}) + } + if s.Kind != nil { + fields = append(fields, &cstxproto.EntityField{Name: "kind", Value: &cstxproto.EntityField_Text{Text: *s.Kind}}) + } + if s.Level != nil { + fields = append(fields, &cstxproto.EntityField{Name: "level", Value: &cstxproto.EntityField_Text{Text: *s.Level}}) + } + if s.RuleId != nil { + fields = append(fields, &cstxproto.EntityField{Name: "rule_id", Value: &cstxproto.EntityField_Text{Text: *s.RuleId}}) + } + if s.Source != nil { + fields = append(fields, &cstxproto.EntityField{Name: "source", Value: &cstxproto.EntityField_Text{Text: *s.Source}}) + } + if len(s.Tags) > 0 { + fields = append(fields, &cstxproto.EntityField{Name: "tags", Value: &cstxproto.EntityField_List{List: &cstxproto.StringList{Values: s.Tags}}}) + } + if s.Target != nil { + fields = append(fields, &cstxproto.EntityField{Name: "target", Value: &cstxproto.EntityField_Text{Text: *s.Target}}) + } + if s.Title != nil { + fields = append(fields, &cstxproto.EntityField{Name: "title", Value: &cstxproto.EntityField_Text{Text: *s.Title}}) + } + fields = append(fields, &cstxproto.EntityField{Name: "value", Value: &cstxproto.EntityField_Text{Text: s.Value}}) + if s.VulnId != nil { + fields = append(fields, &cstxproto.EntityField{Name: "vuln_id", Value: &cstxproto.EntityField_Text{Text: *s.VulnId}}) + } + return &cstxproto.EntityValue{NodeType: "sarif_vuln", Fields: fields}, nil +} + +// Node wraps the payload as a graph node. The id is left unset: identity is +// the schema document's rule and the runtime derives it from the payload. +func (s SarifVuln) Node(sources ...string) (*cstxproto.Node, error) { + value, err := s.EntityValue() + if err != nil { + return nil, err + } + return &cstxproto.Node{Value: value, Sources: sources}, nil +} + +// SarifVulnFrom reads one payload back into SarifVuln. Names the schema does not +// declare are left alone: a producer may send more than this build knows. +func SarifVulnFrom(value *cstxproto.EntityValue) (SarifVuln, error) { + var out SarifVuln + if got := value.GetNodeType(); got != "sarif_vuln" { + return out, fmt.Errorf("cstx: expected node type %q, got %q", "sarif_vuln", got) + } + for _, field := range value.GetFields() { + switch field.GetName() { + case "value": + out.Value = field.GetText() + case "vuln_id": + carried := field.GetText() + out.VulnId = &carried + case "title": + carried := field.GetText() + out.Title = &carried + case "description": + carried := field.GetText() + out.Description = &carried + case "source": + carried := field.GetText() + out.Source = &carried + case "target": + carried := field.GetText() + out.Target = &carried + case "tags": + out.Tags = field.GetList().GetValues() + case "asset_cstx_id": + carried := field.GetText() + out.AssetCstxId = &carried + case "kind": + carried := field.GetText() + out.Kind = &carried + case "level": + carried := field.GetText() + out.Level = &carried + case "baseline_state": + carried := field.GetText() + out.BaselineState = &carried + case "rule_id": + carried := field.GetText() + out.RuleId = &carried + case "evidence": + carried := field.GetText() + out.Evidence = &carried + case "extra": + if raw := field.GetText(); raw != "" { + if err := json.Unmarshal([]byte(raw), &out.Extra); err != nil { + return out, fmt.Errorf("cstx: field %q is not a JSON document: %w", "extra", err) + } + } + } + } + return out, nil +} + +// Certificate is the "certificate" node type. +type Certificate struct { + Fingerprint string // fingerprint + Serial *string // serial + Issuer *string // issuer + Subject *string // subject + NotBefore *string // not_before + NotAfter *string // not_after + San []string // san + Host *string // host + Ip *string // ip + Extra map[string]any // extra +} + +func (c Certificate) CstxType() string { return "certificate" } + +// EntityValue encodes Certificate as the schema-named payload. +func (c Certificate) EntityValue() (*cstxproto.EntityValue, error) { + fields := make([]*cstxproto.EntityField, 0, 10) + if len(c.Extra) > 0 { + encoded, err := json.Marshal(c.Extra) + if err != nil { + return nil, fmt.Errorf("cstx: field %q is not encodable as JSON: %w", "extra", err) + } + fields = append(fields, &cstxproto.EntityField{Name: "extra", Value: &cstxproto.EntityField_Text{Text: string(encoded)}}) + } + fields = append(fields, &cstxproto.EntityField{Name: "fingerprint", Value: &cstxproto.EntityField_Text{Text: c.Fingerprint}}) + if c.Host != nil { + fields = append(fields, &cstxproto.EntityField{Name: "host", Value: &cstxproto.EntityField_Text{Text: *c.Host}}) + } + if c.Ip != nil { + fields = append(fields, &cstxproto.EntityField{Name: "ip", Value: &cstxproto.EntityField_Text{Text: *c.Ip}}) + } + if c.Issuer != nil { + fields = append(fields, &cstxproto.EntityField{Name: "issuer", Value: &cstxproto.EntityField_Text{Text: *c.Issuer}}) + } + if c.NotAfter != nil { + fields = append(fields, &cstxproto.EntityField{Name: "not_after", Value: &cstxproto.EntityField_Text{Text: *c.NotAfter}}) + } + if c.NotBefore != nil { + fields = append(fields, &cstxproto.EntityField{Name: "not_before", Value: &cstxproto.EntityField_Text{Text: *c.NotBefore}}) + } + if len(c.San) > 0 { + fields = append(fields, &cstxproto.EntityField{Name: "san", Value: &cstxproto.EntityField_List{List: &cstxproto.StringList{Values: c.San}}}) + } + if c.Serial != nil { + fields = append(fields, &cstxproto.EntityField{Name: "serial", Value: &cstxproto.EntityField_Text{Text: *c.Serial}}) + } + if c.Subject != nil { + fields = append(fields, &cstxproto.EntityField{Name: "subject", Value: &cstxproto.EntityField_Text{Text: *c.Subject}}) + } + return &cstxproto.EntityValue{NodeType: "certificate", Fields: fields}, nil +} + +// Node wraps the payload as a graph node. The id is left unset: identity is +// the schema document's rule and the runtime derives it from the payload. +func (c Certificate) Node(sources ...string) (*cstxproto.Node, error) { + value, err := c.EntityValue() + if err != nil { + return nil, err + } + return &cstxproto.Node{Value: value, Sources: sources}, nil +} + +// CertificateFrom reads one payload back into Certificate. Names the schema does not +// declare are left alone: a producer may send more than this build knows. +func CertificateFrom(value *cstxproto.EntityValue) (Certificate, error) { + var out Certificate + if got := value.GetNodeType(); got != "certificate" { + return out, fmt.Errorf("cstx: expected node type %q, got %q", "certificate", got) + } + for _, field := range value.GetFields() { + switch field.GetName() { + case "fingerprint": + out.Fingerprint = field.GetText() + case "serial": + carried := field.GetText() + out.Serial = &carried + case "issuer": + carried := field.GetText() + out.Issuer = &carried + case "subject": + carried := field.GetText() + out.Subject = &carried + case "not_before": + carried := field.GetText() + out.NotBefore = &carried + case "not_after": + carried := field.GetText() + out.NotAfter = &carried + case "san": + out.San = field.GetList().GetValues() + case "host": + carried := field.GetText() + out.Host = &carried + case "ip": + carried := field.GetText() + out.Ip = &carried + case "extra": + if raw := field.GetText(); raw != "" { + if err := json.Unmarshal([]byte(raw), &out.Extra); err != nil { + return out, fmt.Errorf("cstx: field %q is not a JSON document: %w", "extra", err) + } + } + } + } + return out, nil +} + +// Company is the "company" node type. +type Company struct { + Name string // name + Perc *string // perc + Tycid *string // tycid + Icp *string // icp + Parent *string // parent + Extra map[string]any // extra +} + +func (c Company) CstxType() string { return "company" } + +// EntityValue encodes Company as the schema-named payload. +func (c Company) EntityValue() (*cstxproto.EntityValue, error) { + fields := make([]*cstxproto.EntityField, 0, 6) + if len(c.Extra) > 0 { + encoded, err := json.Marshal(c.Extra) + if err != nil { + return nil, fmt.Errorf("cstx: field %q is not encodable as JSON: %w", "extra", err) + } + fields = append(fields, &cstxproto.EntityField{Name: "extra", Value: &cstxproto.EntityField_Text{Text: string(encoded)}}) + } + if c.Icp != nil { + fields = append(fields, &cstxproto.EntityField{Name: "icp", Value: &cstxproto.EntityField_Text{Text: *c.Icp}}) + } + fields = append(fields, &cstxproto.EntityField{Name: "name", Value: &cstxproto.EntityField_Text{Text: c.Name}}) + if c.Parent != nil { + fields = append(fields, &cstxproto.EntityField{Name: "parent", Value: &cstxproto.EntityField_Text{Text: *c.Parent}}) + } + if c.Perc != nil { + fields = append(fields, &cstxproto.EntityField{Name: "perc", Value: &cstxproto.EntityField_Text{Text: *c.Perc}}) + } + if c.Tycid != nil { + fields = append(fields, &cstxproto.EntityField{Name: "tycid", Value: &cstxproto.EntityField_Text{Text: *c.Tycid}}) + } + return &cstxproto.EntityValue{NodeType: "company", Fields: fields}, nil +} + +// Node wraps the payload as a graph node. The id is left unset: identity is +// the schema document's rule and the runtime derives it from the payload. +func (c Company) Node(sources ...string) (*cstxproto.Node, error) { + value, err := c.EntityValue() + if err != nil { + return nil, err + } + return &cstxproto.Node{Value: value, Sources: sources}, nil +} + +// CompanyFrom reads one payload back into Company. Names the schema does not +// declare are left alone: a producer may send more than this build knows. +func CompanyFrom(value *cstxproto.EntityValue) (Company, error) { + var out Company + if got := value.GetNodeType(); got != "company" { + return out, fmt.Errorf("cstx: expected node type %q, got %q", "company", got) + } + for _, field := range value.GetFields() { + switch field.GetName() { + case "name": + out.Name = field.GetText() + case "perc": + carried := field.GetText() + out.Perc = &carried + case "tycid": + carried := field.GetText() + out.Tycid = &carried + case "icp": + carried := field.GetText() + out.Icp = &carried + case "parent": + carried := field.GetText() + out.Parent = &carried + case "extra": + if raw := field.GetText(); raw != "" { + if err := json.Unmarshal([]byte(raw), &out.Extra); err != nil { + return out, fmt.Errorf("cstx: field %q is not a JSON document: %w", "extra", err) + } + } + } + } + return out, nil +} + +// Icp is the "icp" node type. +type Icp struct { + Icp string // icp + Sub *string // sub + Date *string // date + Company *string // company + Title *string // title + Domain *string // domain + Ip *string // ip + Extra map[string]any // extra +} + +func (i Icp) CstxType() string { return "icp" } + +// EntityValue encodes Icp as the schema-named payload. +func (i Icp) EntityValue() (*cstxproto.EntityValue, error) { + fields := make([]*cstxproto.EntityField, 0, 8) + if i.Company != nil { + fields = append(fields, &cstxproto.EntityField{Name: "company", Value: &cstxproto.EntityField_Text{Text: *i.Company}}) + } + if i.Date != nil { + fields = append(fields, &cstxproto.EntityField{Name: "date", Value: &cstxproto.EntityField_Text{Text: *i.Date}}) + } + if i.Domain != nil { + fields = append(fields, &cstxproto.EntityField{Name: "domain", Value: &cstxproto.EntityField_Text{Text: *i.Domain}}) + } + if len(i.Extra) > 0 { + encoded, err := json.Marshal(i.Extra) + if err != nil { + return nil, fmt.Errorf("cstx: field %q is not encodable as JSON: %w", "extra", err) + } + fields = append(fields, &cstxproto.EntityField{Name: "extra", Value: &cstxproto.EntityField_Text{Text: string(encoded)}}) + } + fields = append(fields, &cstxproto.EntityField{Name: "icp", Value: &cstxproto.EntityField_Text{Text: i.Icp}}) + if i.Ip != nil { + fields = append(fields, &cstxproto.EntityField{Name: "ip", Value: &cstxproto.EntityField_Text{Text: *i.Ip}}) + } + if i.Sub != nil { + fields = append(fields, &cstxproto.EntityField{Name: "sub", Value: &cstxproto.EntityField_Text{Text: *i.Sub}}) + } + if i.Title != nil { + fields = append(fields, &cstxproto.EntityField{Name: "title", Value: &cstxproto.EntityField_Text{Text: *i.Title}}) + } + return &cstxproto.EntityValue{NodeType: "icp", Fields: fields}, nil +} + +// Node wraps the payload as a graph node. The id is left unset: identity is +// the schema document's rule and the runtime derives it from the payload. +func (i Icp) Node(sources ...string) (*cstxproto.Node, error) { + value, err := i.EntityValue() + if err != nil { + return nil, err + } + return &cstxproto.Node{Value: value, Sources: sources}, nil +} + +// IcpFrom reads one payload back into Icp. Names the schema does not +// declare are left alone: a producer may send more than this build knows. +func IcpFrom(value *cstxproto.EntityValue) (Icp, error) { + var out Icp + if got := value.GetNodeType(); got != "icp" { + return out, fmt.Errorf("cstx: expected node type %q, got %q", "icp", got) + } + for _, field := range value.GetFields() { + switch field.GetName() { + case "icp": + out.Icp = field.GetText() + case "sub": + carried := field.GetText() + out.Sub = &carried + case "date": + carried := field.GetText() + out.Date = &carried + case "company": + carried := field.GetText() + out.Company = &carried + case "title": + carried := field.GetText() + out.Title = &carried + case "domain": + carried := field.GetText() + out.Domain = &carried + case "ip": + carried := field.GetText() + out.Ip = &carried + case "extra": + if raw := field.GetText(); raw != "" { + if err := json.Unmarshal([]byte(raw), &out.Extra); err != nil { + return out, fmt.Errorf("cstx: field %q is not a JSON document: %w", "extra", err) + } + } + } + } + return out, nil +} + +// Bucket is the "bucket" node type. +type Bucket struct { + Provider *string // provider + Name *string // name + Region *string // region + Endpoint string // endpoint + Acl *string // acl + ObjectCount *int64 // object_count + KnownPaths []string // known_paths + SourceUrl *string // source_url + Extra map[string]any // extra +} + +func (b Bucket) CstxType() string { return "bucket" } + +// EntityValue encodes Bucket as the schema-named payload. +func (b Bucket) EntityValue() (*cstxproto.EntityValue, error) { + fields := make([]*cstxproto.EntityField, 0, 9) + if b.Acl != nil { + fields = append(fields, &cstxproto.EntityField{Name: "acl", Value: &cstxproto.EntityField_Text{Text: *b.Acl}}) + } + fields = append(fields, &cstxproto.EntityField{Name: "endpoint", Value: &cstxproto.EntityField_Text{Text: b.Endpoint}}) + if len(b.Extra) > 0 { + encoded, err := json.Marshal(b.Extra) + if err != nil { + return nil, fmt.Errorf("cstx: field %q is not encodable as JSON: %w", "extra", err) + } + fields = append(fields, &cstxproto.EntityField{Name: "extra", Value: &cstxproto.EntityField_Text{Text: string(encoded)}}) + } + if len(b.KnownPaths) > 0 { + fields = append(fields, &cstxproto.EntityField{Name: "known_paths", Value: &cstxproto.EntityField_List{List: &cstxproto.StringList{Values: b.KnownPaths}}}) + } + if b.Name != nil { + fields = append(fields, &cstxproto.EntityField{Name: "name", Value: &cstxproto.EntityField_Text{Text: *b.Name}}) + } + if b.ObjectCount != nil { + fields = append(fields, &cstxproto.EntityField{Name: "object_count", Value: &cstxproto.EntityField_Number{Number: *b.ObjectCount}}) + } + if b.Provider != nil { + fields = append(fields, &cstxproto.EntityField{Name: "provider", Value: &cstxproto.EntityField_Text{Text: *b.Provider}}) + } + if b.Region != nil { + fields = append(fields, &cstxproto.EntityField{Name: "region", Value: &cstxproto.EntityField_Text{Text: *b.Region}}) + } + if b.SourceUrl != nil { + fields = append(fields, &cstxproto.EntityField{Name: "source_url", Value: &cstxproto.EntityField_Text{Text: *b.SourceUrl}}) + } + return &cstxproto.EntityValue{NodeType: "bucket", Fields: fields}, nil +} + +// Node wraps the payload as a graph node. The id is left unset: identity is +// the schema document's rule and the runtime derives it from the payload. +func (b Bucket) Node(sources ...string) (*cstxproto.Node, error) { + value, err := b.EntityValue() + if err != nil { + return nil, err + } + return &cstxproto.Node{Value: value, Sources: sources}, nil +} + +// BucketFrom reads one payload back into Bucket. Names the schema does not +// declare are left alone: a producer may send more than this build knows. +func BucketFrom(value *cstxproto.EntityValue) (Bucket, error) { + var out Bucket + if got := value.GetNodeType(); got != "bucket" { + return out, fmt.Errorf("cstx: expected node type %q, got %q", "bucket", got) + } + for _, field := range value.GetFields() { + switch field.GetName() { + case "provider": + carried := field.GetText() + out.Provider = &carried + case "name": + carried := field.GetText() + out.Name = &carried + case "region": + carried := field.GetText() + out.Region = &carried + case "endpoint": + out.Endpoint = field.GetText() + case "acl": + carried := field.GetText() + out.Acl = &carried + case "object_count": + carried := field.GetNumber() + out.ObjectCount = &carried + case "known_paths": + out.KnownPaths = field.GetList().GetValues() + case "source_url": + carried := field.GetText() + out.SourceUrl = &carried + case "extra": + if raw := field.GetText(); raw != "" { + if err := json.Unmarshal([]byte(raw), &out.Extra); err != nil { + return out, fmt.Errorf("cstx: field %q is not a JSON document: %w", "extra", err) + } + } + } + } + return out, nil +} + +// Endpoint is the "endpoint" node type. +type Endpoint struct { + Url string // url + Method *string // method + Path *string // path + ContentType *string // content_type + StatusCode *int64 // status_code + Source *string // source + SourceUrl *string // source_url + Parameters []string // parameters + Tags []string // tags + Extra map[string]any // extra +} + +func (e Endpoint) CstxType() string { return "endpoint" } + +// EntityValue encodes Endpoint as the schema-named payload. +func (e Endpoint) EntityValue() (*cstxproto.EntityValue, error) { + fields := make([]*cstxproto.EntityField, 0, 10) + if e.ContentType != nil { + fields = append(fields, &cstxproto.EntityField{Name: "content_type", Value: &cstxproto.EntityField_Text{Text: *e.ContentType}}) + } + if len(e.Extra) > 0 { + encoded, err := json.Marshal(e.Extra) + if err != nil { + return nil, fmt.Errorf("cstx: field %q is not encodable as JSON: %w", "extra", err) + } + fields = append(fields, &cstxproto.EntityField{Name: "extra", Value: &cstxproto.EntityField_Text{Text: string(encoded)}}) + } + if e.Method != nil { + fields = append(fields, &cstxproto.EntityField{Name: "method", Value: &cstxproto.EntityField_Text{Text: *e.Method}}) + } + if len(e.Parameters) > 0 { + fields = append(fields, &cstxproto.EntityField{Name: "parameters", Value: &cstxproto.EntityField_List{List: &cstxproto.StringList{Values: e.Parameters}}}) + } + if e.Path != nil { + fields = append(fields, &cstxproto.EntityField{Name: "path", Value: &cstxproto.EntityField_Text{Text: *e.Path}}) + } + if e.Source != nil { + fields = append(fields, &cstxproto.EntityField{Name: "source", Value: &cstxproto.EntityField_Text{Text: *e.Source}}) + } + if e.SourceUrl != nil { + fields = append(fields, &cstxproto.EntityField{Name: "source_url", Value: &cstxproto.EntityField_Text{Text: *e.SourceUrl}}) + } + if e.StatusCode != nil { + fields = append(fields, &cstxproto.EntityField{Name: "status_code", Value: &cstxproto.EntityField_Number{Number: *e.StatusCode}}) + } + if len(e.Tags) > 0 { + fields = append(fields, &cstxproto.EntityField{Name: "tags", Value: &cstxproto.EntityField_List{List: &cstxproto.StringList{Values: e.Tags}}}) + } + fields = append(fields, &cstxproto.EntityField{Name: "url", Value: &cstxproto.EntityField_Text{Text: e.Url}}) + return &cstxproto.EntityValue{NodeType: "endpoint", Fields: fields}, nil +} + +// Node wraps the payload as a graph node. The id is left unset: identity is +// the schema document's rule and the runtime derives it from the payload. +func (e Endpoint) Node(sources ...string) (*cstxproto.Node, error) { + value, err := e.EntityValue() + if err != nil { + return nil, err + } + return &cstxproto.Node{Value: value, Sources: sources}, nil +} + +// EndpointFrom reads one payload back into Endpoint. Names the schema does not +// declare are left alone: a producer may send more than this build knows. +func EndpointFrom(value *cstxproto.EntityValue) (Endpoint, error) { + var out Endpoint + if got := value.GetNodeType(); got != "endpoint" { + return out, fmt.Errorf("cstx: expected node type %q, got %q", "endpoint", got) + } + for _, field := range value.GetFields() { + switch field.GetName() { + case "url": + out.Url = field.GetText() + case "method": + carried := field.GetText() + out.Method = &carried + case "path": + carried := field.GetText() + out.Path = &carried + case "content_type": + carried := field.GetText() + out.ContentType = &carried + case "status_code": + carried := field.GetNumber() + out.StatusCode = &carried + case "source": + carried := field.GetText() + out.Source = &carried + case "source_url": + carried := field.GetText() + out.SourceUrl = &carried + case "parameters": + out.Parameters = field.GetList().GetValues() + case "tags": + out.Tags = field.GetList().GetValues() + case "extra": + if raw := field.GetText(); raw != "" { + if err := json.Unmarshal([]byte(raw), &out.Extra); err != nil { + return out, fmt.Errorf("cstx: field %q is not a JSON document: %w", "extra", err) + } + } + } + } + return out, nil +} + +// Host is the "host" node type. +type Host struct { + Hostname string // hostname + LocalIps []string // local_ips + GatewayIps []string // gateway_ips + DnsServers []string // dns_servers + DomainName *string // domain_name + DomainRole *string // domain_role + Extra map[string]any // extra +} + +func (h Host) CstxType() string { return "host" } + +// EntityValue encodes Host as the schema-named payload. +func (h Host) EntityValue() (*cstxproto.EntityValue, error) { + fields := make([]*cstxproto.EntityField, 0, 7) + if len(h.DnsServers) > 0 { + fields = append(fields, &cstxproto.EntityField{Name: "dns_servers", Value: &cstxproto.EntityField_List{List: &cstxproto.StringList{Values: h.DnsServers}}}) + } + if h.DomainName != nil { + fields = append(fields, &cstxproto.EntityField{Name: "domain_name", Value: &cstxproto.EntityField_Text{Text: *h.DomainName}}) + } + if h.DomainRole != nil { + fields = append(fields, &cstxproto.EntityField{Name: "domain_role", Value: &cstxproto.EntityField_Text{Text: *h.DomainRole}}) + } + if len(h.Extra) > 0 { + encoded, err := json.Marshal(h.Extra) + if err != nil { + return nil, fmt.Errorf("cstx: field %q is not encodable as JSON: %w", "extra", err) + } + fields = append(fields, &cstxproto.EntityField{Name: "extra", Value: &cstxproto.EntityField_Text{Text: string(encoded)}}) + } + if len(h.GatewayIps) > 0 { + fields = append(fields, &cstxproto.EntityField{Name: "gateway_ips", Value: &cstxproto.EntityField_List{List: &cstxproto.StringList{Values: h.GatewayIps}}}) + } + fields = append(fields, &cstxproto.EntityField{Name: "hostname", Value: &cstxproto.EntityField_Text{Text: h.Hostname}}) + if len(h.LocalIps) > 0 { + fields = append(fields, &cstxproto.EntityField{Name: "local_ips", Value: &cstxproto.EntityField_List{List: &cstxproto.StringList{Values: h.LocalIps}}}) + } + return &cstxproto.EntityValue{NodeType: "host", Fields: fields}, nil +} + +// Node wraps the payload as a graph node. The id is left unset: identity is +// the schema document's rule and the runtime derives it from the payload. +func (h Host) Node(sources ...string) (*cstxproto.Node, error) { + value, err := h.EntityValue() + if err != nil { + return nil, err + } + return &cstxproto.Node{Value: value, Sources: sources}, nil +} + +// HostFrom reads one payload back into Host. Names the schema does not +// declare are left alone: a producer may send more than this build knows. +func HostFrom(value *cstxproto.EntityValue) (Host, error) { + var out Host + if got := value.GetNodeType(); got != "host" { + return out, fmt.Errorf("cstx: expected node type %q, got %q", "host", got) + } + for _, field := range value.GetFields() { + switch field.GetName() { + case "hostname": + out.Hostname = field.GetText() + case "local_ips": + out.LocalIps = field.GetList().GetValues() + case "gateway_ips": + out.GatewayIps = field.GetList().GetValues() + case "dns_servers": + out.DnsServers = field.GetList().GetValues() + case "domain_name": + carried := field.GetText() + out.DomainName = &carried + case "domain_role": + carried := field.GetText() + out.DomainRole = &carried + case "extra": + if raw := field.GetText(); raw != "" { + if err := json.Unmarshal([]byte(raw), &out.Extra); err != nil { + return out, fmt.Errorf("cstx: field %q is not a JSON document: %w", "extra", err) + } + } + } + } + return out, nil +} + +// Repository is the "repository" node type. +type Repository struct { + Provider *string // provider + Name *string // name + Url string // url + Owner *string // owner + Description *string // description + Stars *int64 // stars + IsFork *bool // is_fork + MatchedDorks []string // matched_dorks + Extra map[string]any // extra +} + +func (r Repository) CstxType() string { return "repository" } + +// EntityValue encodes Repository as the schema-named payload. +func (r Repository) EntityValue() (*cstxproto.EntityValue, error) { + fields := make([]*cstxproto.EntityField, 0, 9) + if r.Description != nil { + fields = append(fields, &cstxproto.EntityField{Name: "description", Value: &cstxproto.EntityField_Text{Text: *r.Description}}) + } + if len(r.Extra) > 0 { + encoded, err := json.Marshal(r.Extra) + if err != nil { + return nil, fmt.Errorf("cstx: field %q is not encodable as JSON: %w", "extra", err) + } + fields = append(fields, &cstxproto.EntityField{Name: "extra", Value: &cstxproto.EntityField_Text{Text: string(encoded)}}) + } + if r.IsFork != nil { + fields = append(fields, &cstxproto.EntityField{Name: "is_fork", Value: &cstxproto.EntityField_Flag{Flag: *r.IsFork}}) + } + if len(r.MatchedDorks) > 0 { + fields = append(fields, &cstxproto.EntityField{Name: "matched_dorks", Value: &cstxproto.EntityField_List{List: &cstxproto.StringList{Values: r.MatchedDorks}}}) + } + if r.Name != nil { + fields = append(fields, &cstxproto.EntityField{Name: "name", Value: &cstxproto.EntityField_Text{Text: *r.Name}}) + } + if r.Owner != nil { + fields = append(fields, &cstxproto.EntityField{Name: "owner", Value: &cstxproto.EntityField_Text{Text: *r.Owner}}) + } + if r.Provider != nil { + fields = append(fields, &cstxproto.EntityField{Name: "provider", Value: &cstxproto.EntityField_Text{Text: *r.Provider}}) + } + if r.Stars != nil { + fields = append(fields, &cstxproto.EntityField{Name: "stars", Value: &cstxproto.EntityField_Number{Number: *r.Stars}}) + } + fields = append(fields, &cstxproto.EntityField{Name: "url", Value: &cstxproto.EntityField_Text{Text: r.Url}}) + return &cstxproto.EntityValue{NodeType: "repository", Fields: fields}, nil +} + +// Node wraps the payload as a graph node. The id is left unset: identity is +// the schema document's rule and the runtime derives it from the payload. +func (r Repository) Node(sources ...string) (*cstxproto.Node, error) { + value, err := r.EntityValue() + if err != nil { + return nil, err + } + return &cstxproto.Node{Value: value, Sources: sources}, nil +} + +// RepositoryFrom reads one payload back into Repository. Names the schema does not +// declare are left alone: a producer may send more than this build knows. +func RepositoryFrom(value *cstxproto.EntityValue) (Repository, error) { + var out Repository + if got := value.GetNodeType(); got != "repository" { + return out, fmt.Errorf("cstx: expected node type %q, got %q", "repository", got) + } + for _, field := range value.GetFields() { + switch field.GetName() { + case "provider": + carried := field.GetText() + out.Provider = &carried + case "name": + carried := field.GetText() + out.Name = &carried + case "url": + out.Url = field.GetText() + case "owner": + carried := field.GetText() + out.Owner = &carried + case "description": + carried := field.GetText() + out.Description = &carried + case "stars": + carried := field.GetNumber() + out.Stars = &carried + case "is_fork": + carried := field.GetFlag() + out.IsFork = &carried + case "matched_dorks": + out.MatchedDorks = field.GetList().GetValues() + case "extra": + if raw := field.GetText(); raw != "" { + if err := json.Unmarshal([]byte(raw), &out.Extra); err != nil { + return out, fmt.Errorf("cstx: field %q is not a JSON document: %w", "extra", err) + } + } + } + } + return out, nil +} + +// Secret is the "secret" node type. +type Secret struct { + Kind *string // kind + Detector *string // detector + Redacted *string // redacted + Fingerprint string // fingerprint + Source *string // source + SourceUrl *string // source_url + FilePath *string // file_path + Line *int64 // line + Commit *string // commit + Verified *bool // verified + Severity *string // severity + Extra map[string]any // extra +} + +func (s Secret) CstxType() string { return "secret" } + +// EntityValue encodes Secret as the schema-named payload. +func (s Secret) EntityValue() (*cstxproto.EntityValue, error) { + fields := make([]*cstxproto.EntityField, 0, 12) + if s.Commit != nil { + fields = append(fields, &cstxproto.EntityField{Name: "commit", Value: &cstxproto.EntityField_Text{Text: *s.Commit}}) + } + if s.Detector != nil { + fields = append(fields, &cstxproto.EntityField{Name: "detector", Value: &cstxproto.EntityField_Text{Text: *s.Detector}}) + } + if len(s.Extra) > 0 { + encoded, err := json.Marshal(s.Extra) + if err != nil { + return nil, fmt.Errorf("cstx: field %q is not encodable as JSON: %w", "extra", err) + } + fields = append(fields, &cstxproto.EntityField{Name: "extra", Value: &cstxproto.EntityField_Text{Text: string(encoded)}}) + } + if s.FilePath != nil { + fields = append(fields, &cstxproto.EntityField{Name: "file_path", Value: &cstxproto.EntityField_Text{Text: *s.FilePath}}) + } + fields = append(fields, &cstxproto.EntityField{Name: "fingerprint", Value: &cstxproto.EntityField_Text{Text: s.Fingerprint}}) + if s.Kind != nil { + fields = append(fields, &cstxproto.EntityField{Name: "kind", Value: &cstxproto.EntityField_Text{Text: *s.Kind}}) + } + if s.Line != nil { + fields = append(fields, &cstxproto.EntityField{Name: "line", Value: &cstxproto.EntityField_Number{Number: *s.Line}}) + } + if s.Redacted != nil { + fields = append(fields, &cstxproto.EntityField{Name: "redacted", Value: &cstxproto.EntityField_Text{Text: *s.Redacted}}) + } + if s.Severity != nil { + fields = append(fields, &cstxproto.EntityField{Name: "severity", Value: &cstxproto.EntityField_Text{Text: *s.Severity}}) + } + if s.Source != nil { + fields = append(fields, &cstxproto.EntityField{Name: "source", Value: &cstxproto.EntityField_Text{Text: *s.Source}}) + } + if s.SourceUrl != nil { + fields = append(fields, &cstxproto.EntityField{Name: "source_url", Value: &cstxproto.EntityField_Text{Text: *s.SourceUrl}}) + } + if s.Verified != nil { + fields = append(fields, &cstxproto.EntityField{Name: "verified", Value: &cstxproto.EntityField_Flag{Flag: *s.Verified}}) + } + return &cstxproto.EntityValue{NodeType: "secret", Fields: fields}, nil +} + +// Node wraps the payload as a graph node. The id is left unset: identity is +// the schema document's rule and the runtime derives it from the payload. +func (s Secret) Node(sources ...string) (*cstxproto.Node, error) { + value, err := s.EntityValue() + if err != nil { + return nil, err + } + return &cstxproto.Node{Value: value, Sources: sources}, nil +} + +// SecretFrom reads one payload back into Secret. Names the schema does not +// declare are left alone: a producer may send more than this build knows. +func SecretFrom(value *cstxproto.EntityValue) (Secret, error) { + var out Secret + if got := value.GetNodeType(); got != "secret" { + return out, fmt.Errorf("cstx: expected node type %q, got %q", "secret", got) + } + for _, field := range value.GetFields() { + switch field.GetName() { + case "kind": + carried := field.GetText() + out.Kind = &carried + case "detector": + carried := field.GetText() + out.Detector = &carried + case "redacted": + carried := field.GetText() + out.Redacted = &carried + case "fingerprint": + out.Fingerprint = field.GetText() + case "source": + carried := field.GetText() + out.Source = &carried + case "source_url": + carried := field.GetText() + out.SourceUrl = &carried + case "file_path": + carried := field.GetText() + out.FilePath = &carried + case "line": + carried := field.GetNumber() + out.Line = &carried + case "commit": + carried := field.GetText() + out.Commit = &carried + case "verified": + carried := field.GetFlag() + out.Verified = &carried + case "severity": + carried := field.GetText() + out.Severity = &carried + case "extra": + if raw := field.GetText(); raw != "" { + if err := json.Unmarshal([]byte(raw), &out.Extra); err != nil { + return out, fmt.Errorf("cstx: field %q is not a JSON document: %w", "extra", err) + } + } + } + } + return out, nil +} + +// Decode reads one payload back into the generated type for its node type. +func Decode(value *cstxproto.EntityValue) (Node, error) { + switch value.GetNodeType() { + case "domain": + decoded, err := DomainFrom(value) + return decoded, err + case "subdomain": + decoded, err := SubdomainFrom(value) + return decoded, err + case "ip": + decoded, err := IpFrom(value) + return decoded, err + case "cidr": + decoded, err := CidrFrom(value) + return decoded, err + case "port": + decoded, err := PortFrom(value) + return decoded, err + case "app": + decoded, err := AppFrom(value) + return decoded, err + case "url": + decoded, err := UrlFrom(value) + return decoded, err + case "framework": + decoded, err := FrameworkFrom(value) + return decoded, err + case "vuln": + decoded, err := VulnFrom(value) + return decoded, err + case "sarif_vuln": + decoded, err := SarifVulnFrom(value) + return decoded, err + case "certificate": + decoded, err := CertificateFrom(value) + return decoded, err + case "company": + decoded, err := CompanyFrom(value) + return decoded, err + case "icp": + decoded, err := IcpFrom(value) + return decoded, err + case "bucket": + decoded, err := BucketFrom(value) + return decoded, err + case "endpoint": + decoded, err := EndpointFrom(value) + return decoded, err + case "host": + decoded, err := HostFrom(value) + return decoded, err + case "repository": + decoded, err := RepositoryFrom(value) + return decoded, err + case "secret": + decoded, err := SecretFrom(value) + return decoded, err + default: + return nil, fmt.Errorf("cstx: no generated type for node type %q", value.GetNodeType()) + } +} + +const ( + RelVuln = "vuln" + RelResolve = "resolve" + RelOpen = "open" + RelHasSubdomain = "has-subdomain" + RelContain = "contain" + RelHosts = "hosts" + RelUses = "uses" + RelRefers = "refers" + RelSecuredBy = "secured_by" + RelExploit = "exploit" + RelAffect = "affect" + RelInvest = "invest" + RelOwn = "own" + RelFiledFor = "filed-for" +) + +var RelationTypes = []string{ + RelVuln, + RelResolve, + RelOpen, + RelHasSubdomain, + RelContain, + RelHosts, + RelUses, + RelRefers, + RelSecuredBy, + RelExploit, + RelAffect, + RelInvest, + RelOwn, + RelFiledFor, +} diff --git a/go/plugins/easm/easm_test.go b/go/plugins/easm/easm_test.go new file mode 100644 index 0000000..b4e6dde --- /dev/null +++ b/go/plugins/easm/easm_test.go @@ -0,0 +1,165 @@ +package easm + +import ( + "testing" + + "github.com/chainreactors/libcstx/go/proto/cstxproto" +) + +// The generated layer is a projection of the schema document, not a second wire +// format. These tests pin that: it produces the same `EntityValue` a caller +// with no generated code would build by hand, and it reads one back without +// consulting anything but the field names. +// +// Nothing here imports a generated protobuf extension package. Typed access to +// a node type no longer requires a generated protobuf message for it, which is +// the whole point: a +// type declared at runtime has none in any language and never will. + +func ptr[T any](value T) *T { return &value } + +func TestEntityValueNamesTheSchemaFields(t *testing.T) { + value, err := Subdomain{ + Host: "a.example.com", + IsTld: ptr(false), + Ttl: ptr(int64(300)), + A: []string{"1.1.1.1", "2.2.2.2"}, + }.EntityValue() + if err != nil { + t.Fatal(err) + } + if value.GetNodeType() != "subdomain" { + t.Fatalf("node type = %q, want %q", value.GetNodeType(), "subdomain") + } + + got := map[string]*cstxproto.EntityField{} + for _, field := range value.GetFields() { + got[field.GetName()] = field + } + if len(got) != 4 { + t.Fatalf("field count = %d, want 4 (an unset optional is absent, not zero)", len(got)) + } + if text := got["host"].GetText(); text != "a.example.com" { + t.Errorf("host = %q", text) + } + // `false` is a value the producer sent, not an absence. A bool that arrives + // as the flag branch is how the two stay distinguishable. + if _, ok := got["is_tld"].GetValue().(*cstxproto.EntityField_Flag); !ok { + t.Errorf("is_tld took the wrong oneof branch: %T", got["is_tld"].GetValue()) + } + if number := got["ttl"].GetNumber(); number != 300 { + t.Errorf("ttl = %d", number) + } + if values := got["a"].GetList().GetValues(); len(values) != 2 { + t.Errorf("a = %v", values) + } +} + +func TestFieldsAreOrderedByName(t *testing.T) { + // One value produces one message: the order is decided when the code is + // generated, so nothing sorts at run time and two encodings of the same + // content are byte-identical. + value, err := Subdomain{Host: "b.example.com", Ttl: ptr(int64(1)), A: []string{"9.9.9.9"}}.EntityValue() + if err != nil { + t.Fatal(err) + } + previous := "" + for _, field := range value.GetFields() { + if field.GetName() <= previous { + t.Fatalf("fields are not in ascending name order: %q after %q", field.GetName(), previous) + } + previous = field.GetName() + } +} + +func TestRoundTripThroughEntityValue(t *testing.T) { + original := Subdomain{ + Host: "c.example.com", + IsTld: ptr(true), + Ttl: ptr(int64(60)), + Cname: []string{"cdn.example.net"}, + Extra: map[string]any{"observed_by": "subfinder"}, + } + value, err := original.EntityValue() + if err != nil { + t.Fatal(err) + } + restored, err := SubdomainFrom(value) + if err != nil { + t.Fatal(err) + } + if restored.Host != original.Host { + t.Errorf("host = %q, want %q", restored.Host, original.Host) + } + if restored.IsTld == nil || *restored.IsTld != true { + t.Errorf("is_tld = %v", restored.IsTld) + } + if restored.Ttl == nil || *restored.Ttl != 60 { + t.Errorf("ttl = %v", restored.Ttl) + } + if len(restored.Cname) != 1 || restored.Cname[0] != "cdn.example.net" { + t.Errorf("cname = %v", restored.Cname) + } + // The declared bag is text on the wire and a document in the caller's hands. + if restored.Extra["observed_by"] != "subfinder" { + t.Errorf("extra = %v", restored.Extra) + } + // An optional the producer never set stays absent rather than becoming zero. + if restored.Resolver != nil { + t.Errorf("resolver = %v, want nil", restored.Resolver) + } +} + +func TestDecodeDispatchesOnTheDeclaredNodeType(t *testing.T) { + value, err := Ip{Ip: "192.0.2.1", Cdn: ptr(true)}.EntityValue() + if err != nil { + t.Fatal(err) + } + decoded, err := Decode(value) + if err != nil { + t.Fatal(err) + } + if decoded.CstxType() != "ip" { + t.Fatalf("decoded as %q", decoded.CstxType()) + } + if _, ok := decoded.(Ip); !ok { + t.Fatalf("decoded to %T, want Ip", decoded) + } +} + +func TestDecodeRefusesATypeThisBuildHasNoneFor(t *testing.T) { + // A type declared at runtime has no generated struct here, and saying so is + // the correct answer — the untyped `NodeValues` path is what reads it. + _, err := Decode(&cstxproto.EntityValue{NodeType: "acme_asset"}) + if err == nil { + t.Fatal("expected an error for a node type with no generated struct") + } +} + +func TestFromRefusesAPayloadOfAnotherType(t *testing.T) { + value, err := Ip{Ip: "192.0.2.2"}.EntityValue() + if err != nil { + t.Fatal(err) + } + if _, err := SubdomainFrom(value); err == nil { + t.Fatal("expected SubdomainFrom to refuse an ip payload") + } +} + +func TestNodeLeavesIdentityToTheRuntime(t *testing.T) { + // Identity is the schema document's rule; minting one here would be a second + // place deciding what a node is called. + node, err := Subdomain{Host: "d.example.com"}.Node("subfinder") + if err != nil { + t.Fatal(err) + } + if node.Id != nil { + t.Errorf("id = %v, want unset", node.Id) + } + if node.GetValue().GetNodeType() != "subdomain" { + t.Errorf("payload node type = %q", node.GetValue().GetNodeType()) + } + if len(node.GetSources()) != 1 || node.GetSources()[0] != "subfinder" { + t.Errorf("sources = %v", node.GetSources()) + } +} diff --git a/go/proto/README.md b/go/proto/README.md new file mode 100644 index 0000000..c3ca2ae --- /dev/null +++ b/go/proto/README.md @@ -0,0 +1,19 @@ +# CSTX protobuf package + +`cstxproto` is the only wire model the native SDK uses: nodes, relationships, +graphs, cursors, filters, pages, repository messages and extension contracts. + +Extension types do not live in this transport package. Their typed layer is +generated by `make codegen` into `go/plugins/`: a plain struct per +node type that converts to and from `cstxproto.EntityValue`, depending on this +package and nothing else. Runtime-declared types use the same value shape +without requiring generated code. + +`Node.value` and `Relationship.value` are the sole payload fields. They name +their data from the registered schema document; the retired field numbers stay +`reserved` and cannot be reused. + +Open-ended annotations and schema metadata use `google.protobuf.Struct`; no +envelope or JSON transport is part of this package. Repository commit metadata +uses that same `Struct` wire; it is not encoded as a standalone +`google.protobuf.Value`. diff --git a/go/proto/cstxproto/cstx.pb.go b/go/proto/cstxproto/cstx.pb.go new file mode 100644 index 0000000..24c53ee --- /dev/null +++ b/go/proto/cstxproto/cstx.pb.go @@ -0,0 +1,11098 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.34.1 +// protoc v6.33.0 +// source: cstx.proto + +package cstxproto + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + descriptorpb "google.golang.org/protobuf/types/descriptorpb" + structpb "google.golang.org/protobuf/types/known/structpb" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type ChangeOperation int32 + +const ( + ChangeOperation_CHANGE_OPERATION_UNSPECIFIED ChangeOperation = 0 + ChangeOperation_CHANGE_OPERATION_ADDED ChangeOperation = 1 + ChangeOperation_CHANGE_OPERATION_UPDATED ChangeOperation = 2 + ChangeOperation_CHANGE_OPERATION_REMOVED ChangeOperation = 3 +) + +// Enum value maps for ChangeOperation. +var ( + ChangeOperation_name = map[int32]string{ + 0: "CHANGE_OPERATION_UNSPECIFIED", + 1: "CHANGE_OPERATION_ADDED", + 2: "CHANGE_OPERATION_UPDATED", + 3: "CHANGE_OPERATION_REMOVED", + } + ChangeOperation_value = map[string]int32{ + "CHANGE_OPERATION_UNSPECIFIED": 0, + "CHANGE_OPERATION_ADDED": 1, + "CHANGE_OPERATION_UPDATED": 2, + "CHANGE_OPERATION_REMOVED": 3, + } +) + +func (x ChangeOperation) Enum() *ChangeOperation { + p := new(ChangeOperation) + *p = x + return p +} + +func (x ChangeOperation) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ChangeOperation) Descriptor() protoreflect.EnumDescriptor { + return file_cstx_proto_enumTypes[0].Descriptor() +} + +func (ChangeOperation) Type() protoreflect.EnumType { + return &file_cstx_proto_enumTypes[0] +} + +func (x ChangeOperation) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ChangeOperation.Descriptor instead. +func (ChangeOperation) EnumDescriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{0} +} + +type SortOrder int32 + +const ( + SortOrder_SORT_ORDER_UNSPECIFIED SortOrder = 0 + SortOrder_SORT_ORDER_ID_ASC SortOrder = 1 + SortOrder_SORT_ORDER_ID_DESC SortOrder = 2 +) + +// Enum value maps for SortOrder. +var ( + SortOrder_name = map[int32]string{ + 0: "SORT_ORDER_UNSPECIFIED", + 1: "SORT_ORDER_ID_ASC", + 2: "SORT_ORDER_ID_DESC", + } + SortOrder_value = map[string]int32{ + "SORT_ORDER_UNSPECIFIED": 0, + "SORT_ORDER_ID_ASC": 1, + "SORT_ORDER_ID_DESC": 2, + } +) + +func (x SortOrder) Enum() *SortOrder { + p := new(SortOrder) + *p = x + return p +} + +func (x SortOrder) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SortOrder) Descriptor() protoreflect.EnumDescriptor { + return file_cstx_proto_enumTypes[1].Descriptor() +} + +func (SortOrder) Type() protoreflect.EnumType { + return &file_cstx_proto_enumTypes[1] +} + +func (x SortOrder) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use SortOrder.Descriptor instead. +func (SortOrder) EnumDescriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{1} +} + +type Direction int32 + +const ( + Direction_DIRECTION_UNSPECIFIED Direction = 0 + Direction_DIRECTION_OUT Direction = 1 + Direction_DIRECTION_IN Direction = 2 + Direction_DIRECTION_BOTH Direction = 3 +) + +// Enum value maps for Direction. +var ( + Direction_name = map[int32]string{ + 0: "DIRECTION_UNSPECIFIED", + 1: "DIRECTION_OUT", + 2: "DIRECTION_IN", + 3: "DIRECTION_BOTH", + } + Direction_value = map[string]int32{ + "DIRECTION_UNSPECIFIED": 0, + "DIRECTION_OUT": 1, + "DIRECTION_IN": 2, + "DIRECTION_BOTH": 3, + } +) + +func (x Direction) Enum() *Direction { + p := new(Direction) + *p = x + return p +} + +func (x Direction) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Direction) Descriptor() protoreflect.EnumDescriptor { + return file_cstx_proto_enumTypes[2].Descriptor() +} + +func (Direction) Type() protoreflect.EnumType { + return &file_cstx_proto_enumTypes[2] +} + +func (x Direction) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Direction.Descriptor instead. +func (Direction) EnumDescriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{2} +} + +type ParameterlessAlgorithm int32 + +const ( + ParameterlessAlgorithm_PARAMETERLESS_ALGORITHM_UNSPECIFIED ParameterlessAlgorithm = 0 + ParameterlessAlgorithm_PARAMETERLESS_WEAK_COMPONENTS ParameterlessAlgorithm = 1 + ParameterlessAlgorithm_PARAMETERLESS_STRONG_COMPONENTS ParameterlessAlgorithm = 2 + ParameterlessAlgorithm_PARAMETERLESS_CYCLE_BASIS ParameterlessAlgorithm = 3 + ParameterlessAlgorithm_PARAMETERLESS_BRIDGES ParameterlessAlgorithm = 4 + ParameterlessAlgorithm_PARAMETERLESS_ARTICULATION_POINTS ParameterlessAlgorithm = 5 + ParameterlessAlgorithm_PARAMETERLESS_CORE_NUMBERS ParameterlessAlgorithm = 6 + ParameterlessAlgorithm_PARAMETERLESS_IS_DAG ParameterlessAlgorithm = 7 + ParameterlessAlgorithm_PARAMETERLESS_TOPOLOGICAL_ORDER ParameterlessAlgorithm = 8 +) + +// Enum value maps for ParameterlessAlgorithm. +var ( + ParameterlessAlgorithm_name = map[int32]string{ + 0: "PARAMETERLESS_ALGORITHM_UNSPECIFIED", + 1: "PARAMETERLESS_WEAK_COMPONENTS", + 2: "PARAMETERLESS_STRONG_COMPONENTS", + 3: "PARAMETERLESS_CYCLE_BASIS", + 4: "PARAMETERLESS_BRIDGES", + 5: "PARAMETERLESS_ARTICULATION_POINTS", + 6: "PARAMETERLESS_CORE_NUMBERS", + 7: "PARAMETERLESS_IS_DAG", + 8: "PARAMETERLESS_TOPOLOGICAL_ORDER", + } + ParameterlessAlgorithm_value = map[string]int32{ + "PARAMETERLESS_ALGORITHM_UNSPECIFIED": 0, + "PARAMETERLESS_WEAK_COMPONENTS": 1, + "PARAMETERLESS_STRONG_COMPONENTS": 2, + "PARAMETERLESS_CYCLE_BASIS": 3, + "PARAMETERLESS_BRIDGES": 4, + "PARAMETERLESS_ARTICULATION_POINTS": 5, + "PARAMETERLESS_CORE_NUMBERS": 6, + "PARAMETERLESS_IS_DAG": 7, + "PARAMETERLESS_TOPOLOGICAL_ORDER": 8, + } +) + +func (x ParameterlessAlgorithm) Enum() *ParameterlessAlgorithm { + p := new(ParameterlessAlgorithm) + *p = x + return p +} + +func (x ParameterlessAlgorithm) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ParameterlessAlgorithm) Descriptor() protoreflect.EnumDescriptor { + return file_cstx_proto_enumTypes[3].Descriptor() +} + +func (ParameterlessAlgorithm) Type() protoreflect.EnumType { + return &file_cstx_proto_enumTypes[3] +} + +func (x ParameterlessAlgorithm) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ParameterlessAlgorithm.Descriptor instead. +func (ParameterlessAlgorithm) EnumDescriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{3} +} + +type NodeFlagUpdateMode int32 + +const ( + NodeFlagUpdateMode_NODE_FLAG_UPDATE_UNSPECIFIED NodeFlagUpdateMode = 0 + NodeFlagUpdateMode_NODE_FLAG_UPDATE_MERGE NodeFlagUpdateMode = 1 + NodeFlagUpdateMode_NODE_FLAG_UPDATE_REPLACE NodeFlagUpdateMode = 2 +) + +// Enum value maps for NodeFlagUpdateMode. +var ( + NodeFlagUpdateMode_name = map[int32]string{ + 0: "NODE_FLAG_UPDATE_UNSPECIFIED", + 1: "NODE_FLAG_UPDATE_MERGE", + 2: "NODE_FLAG_UPDATE_REPLACE", + } + NodeFlagUpdateMode_value = map[string]int32{ + "NODE_FLAG_UPDATE_UNSPECIFIED": 0, + "NODE_FLAG_UPDATE_MERGE": 1, + "NODE_FLAG_UPDATE_REPLACE": 2, + } +) + +func (x NodeFlagUpdateMode) Enum() *NodeFlagUpdateMode { + p := new(NodeFlagUpdateMode) + *p = x + return p +} + +func (x NodeFlagUpdateMode) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (NodeFlagUpdateMode) Descriptor() protoreflect.EnumDescriptor { + return file_cstx_proto_enumTypes[4].Descriptor() +} + +func (NodeFlagUpdateMode) Type() protoreflect.EnumType { + return &file_cstx_proto_enumTypes[4] +} + +func (x NodeFlagUpdateMode) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use NodeFlagUpdateMode.Descriptor instead. +func (NodeFlagUpdateMode) EnumDescriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{4} +} + +// Operation-oriented repository hydration plan kinds. +type ObjectKind int32 + +const ( + ObjectKind_OBJECT_KIND_UNSPECIFIED ObjectKind = 0 + ObjectKind_OBJECT_KIND_TREE ObjectKind = 1 + ObjectKind_OBJECT_KIND_STAT ObjectKind = 2 + ObjectKind_OBJECT_KIND_MERGE ObjectKind = 3 + ObjectKind_OBJECT_KIND_DELTA ObjectKind = 4 + ObjectKind_OBJECT_KIND_PREPARE ObjectKind = 5 + ObjectKind_OBJECT_KIND_HISTORY ObjectKind = 6 + ObjectKind_OBJECT_KIND_COMMITS ObjectKind = 7 + ObjectKind_OBJECT_KIND_DIFF ObjectKind = 8 + ObjectKind_OBJECT_KIND_CLOSURE ObjectKind = 9 +) + +// Enum value maps for ObjectKind. +var ( + ObjectKind_name = map[int32]string{ + 0: "OBJECT_KIND_UNSPECIFIED", + 1: "OBJECT_KIND_TREE", + 2: "OBJECT_KIND_STAT", + 3: "OBJECT_KIND_MERGE", + 4: "OBJECT_KIND_DELTA", + 5: "OBJECT_KIND_PREPARE", + 6: "OBJECT_KIND_HISTORY", + 7: "OBJECT_KIND_COMMITS", + 8: "OBJECT_KIND_DIFF", + 9: "OBJECT_KIND_CLOSURE", + } + ObjectKind_value = map[string]int32{ + "OBJECT_KIND_UNSPECIFIED": 0, + "OBJECT_KIND_TREE": 1, + "OBJECT_KIND_STAT": 2, + "OBJECT_KIND_MERGE": 3, + "OBJECT_KIND_DELTA": 4, + "OBJECT_KIND_PREPARE": 5, + "OBJECT_KIND_HISTORY": 6, + "OBJECT_KIND_COMMITS": 7, + "OBJECT_KIND_DIFF": 8, + "OBJECT_KIND_CLOSURE": 9, + } +) + +func (x ObjectKind) Enum() *ObjectKind { + p := new(ObjectKind) + *p = x + return p +} + +func (x ObjectKind) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ObjectKind) Descriptor() protoreflect.EnumDescriptor { + return file_cstx_proto_enumTypes[5].Descriptor() +} + +func (ObjectKind) Type() protoreflect.EnumType { + return &file_cstx_proto_enumTypes[5] +} + +func (x ObjectKind) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ObjectKind.Descriptor instead. +func (ObjectKind) EnumDescriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{5} +} + +// Physical CAS object kinds carried by publication plans. This is deliberately +// separate from ObjectKind: a plan describes what to hydrate, while a +// publication object describes the immutable payload's storage kind. +type RepositoryObjectKind int32 + +const ( + RepositoryObjectKind_REPOSITORY_OBJECT_KIND_UNSPECIFIED RepositoryObjectKind = 0 + RepositoryObjectKind_REPOSITORY_OBJECT_KIND_TREE RepositoryObjectKind = 1 + RepositoryObjectKind_REPOSITORY_OBJECT_KIND_COMMIT RepositoryObjectKind = 2 + RepositoryObjectKind_REPOSITORY_OBJECT_KIND_INDEX RepositoryObjectKind = 3 + RepositoryObjectKind_REPOSITORY_OBJECT_KIND_BLOB RepositoryObjectKind = 4 +) + +// Enum value maps for RepositoryObjectKind. +var ( + RepositoryObjectKind_name = map[int32]string{ + 0: "REPOSITORY_OBJECT_KIND_UNSPECIFIED", + 1: "REPOSITORY_OBJECT_KIND_TREE", + 2: "REPOSITORY_OBJECT_KIND_COMMIT", + 3: "REPOSITORY_OBJECT_KIND_INDEX", + 4: "REPOSITORY_OBJECT_KIND_BLOB", + } + RepositoryObjectKind_value = map[string]int32{ + "REPOSITORY_OBJECT_KIND_UNSPECIFIED": 0, + "REPOSITORY_OBJECT_KIND_TREE": 1, + "REPOSITORY_OBJECT_KIND_COMMIT": 2, + "REPOSITORY_OBJECT_KIND_INDEX": 3, + "REPOSITORY_OBJECT_KIND_BLOB": 4, + } +) + +func (x RepositoryObjectKind) Enum() *RepositoryObjectKind { + p := new(RepositoryObjectKind) + *p = x + return p +} + +func (x RepositoryObjectKind) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (RepositoryObjectKind) Descriptor() protoreflect.EnumDescriptor { + return file_cstx_proto_enumTypes[6].Descriptor() +} + +func (RepositoryObjectKind) Type() protoreflect.EnumType { + return &file_cstx_proto_enumTypes[6] +} + +func (x RepositoryObjectKind) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use RepositoryObjectKind.Descriptor instead. +func (RepositoryObjectKind) EnumDescriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{6} +} + +// Explicit repository hydration plan. This is the sole input shape for +// repository.missing; it is intentionally operation-oriented rather than a +// generic request envelope. +type RepositoryPlanKind int32 + +const ( + RepositoryPlanKind_REPOSITORY_PLAN_UNSPECIFIED RepositoryPlanKind = 0 + RepositoryPlanKind_REPOSITORY_PLAN_TREE RepositoryPlanKind = 1 + RepositoryPlanKind_REPOSITORY_PLAN_STAT RepositoryPlanKind = 2 + RepositoryPlanKind_REPOSITORY_PLAN_PREPARE RepositoryPlanKind = 3 + RepositoryPlanKind_REPOSITORY_PLAN_COMMITS RepositoryPlanKind = 4 + RepositoryPlanKind_REPOSITORY_PLAN_DELTA RepositoryPlanKind = 5 + RepositoryPlanKind_REPOSITORY_PLAN_CLOSURE RepositoryPlanKind = 6 + RepositoryPlanKind_REPOSITORY_PLAN_HISTORY RepositoryPlanKind = 7 + RepositoryPlanKind_REPOSITORY_PLAN_MERGE RepositoryPlanKind = 8 + RepositoryPlanKind_REPOSITORY_PLAN_DIFF RepositoryPlanKind = 9 + RepositoryPlanKind_REPOSITORY_PLAN_ENTITIES RepositoryPlanKind = 10 +) + +// Enum value maps for RepositoryPlanKind. +var ( + RepositoryPlanKind_name = map[int32]string{ + 0: "REPOSITORY_PLAN_UNSPECIFIED", + 1: "REPOSITORY_PLAN_TREE", + 2: "REPOSITORY_PLAN_STAT", + 3: "REPOSITORY_PLAN_PREPARE", + 4: "REPOSITORY_PLAN_COMMITS", + 5: "REPOSITORY_PLAN_DELTA", + 6: "REPOSITORY_PLAN_CLOSURE", + 7: "REPOSITORY_PLAN_HISTORY", + 8: "REPOSITORY_PLAN_MERGE", + 9: "REPOSITORY_PLAN_DIFF", + 10: "REPOSITORY_PLAN_ENTITIES", + } + RepositoryPlanKind_value = map[string]int32{ + "REPOSITORY_PLAN_UNSPECIFIED": 0, + "REPOSITORY_PLAN_TREE": 1, + "REPOSITORY_PLAN_STAT": 2, + "REPOSITORY_PLAN_PREPARE": 3, + "REPOSITORY_PLAN_COMMITS": 4, + "REPOSITORY_PLAN_DELTA": 5, + "REPOSITORY_PLAN_CLOSURE": 6, + "REPOSITORY_PLAN_HISTORY": 7, + "REPOSITORY_PLAN_MERGE": 8, + "REPOSITORY_PLAN_DIFF": 9, + "REPOSITORY_PLAN_ENTITIES": 10, + } +) + +func (x RepositoryPlanKind) Enum() *RepositoryPlanKind { + p := new(RepositoryPlanKind) + *p = x + return p +} + +func (x RepositoryPlanKind) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (RepositoryPlanKind) Descriptor() protoreflect.EnumDescriptor { + return file_cstx_proto_enumTypes[7].Descriptor() +} + +func (RepositoryPlanKind) Type() protoreflect.EnumType { + return &file_cstx_proto_enumTypes[7] +} + +func (x RepositoryPlanKind) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use RepositoryPlanKind.Descriptor instead. +func (RepositoryPlanKind) EnumDescriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{7} +} + +type DiffDetail int32 + +const ( + DiffDetail_DIFF_DETAIL_UNSPECIFIED DiffDetail = 0 + DiffDetail_DIFF_DETAIL_ENTITIES DiffDetail = 1 + DiffDetail_DIFF_DETAIL_COUNTS DiffDetail = 2 +) + +// Enum value maps for DiffDetail. +var ( + DiffDetail_name = map[int32]string{ + 0: "DIFF_DETAIL_UNSPECIFIED", + 1: "DIFF_DETAIL_ENTITIES", + 2: "DIFF_DETAIL_COUNTS", + } + DiffDetail_value = map[string]int32{ + "DIFF_DETAIL_UNSPECIFIED": 0, + "DIFF_DETAIL_ENTITIES": 1, + "DIFF_DETAIL_COUNTS": 2, + } +) + +func (x DiffDetail) Enum() *DiffDetail { + p := new(DiffDetail) + *p = x + return p +} + +func (x DiffDetail) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (DiffDetail) Descriptor() protoreflect.EnumDescriptor { + return file_cstx_proto_enumTypes[8].Descriptor() +} + +func (DiffDetail) Type() protoreflect.EnumType { + return &file_cstx_proto_enumTypes[8] +} + +func (x DiffDetail) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use DiffDetail.Descriptor instead. +func (DiffDetail) EnumDescriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{8} +} + +type RagRecordKind int32 + +const ( + RagRecordKind_RAG_RECORD_KIND_UNSPECIFIED RagRecordKind = 0 + RagRecordKind_RAG_RECORD_NODE RagRecordKind = 1 + RagRecordKind_RAG_RECORD_RELATIONSHIP RagRecordKind = 2 +) + +// Enum value maps for RagRecordKind. +var ( + RagRecordKind_name = map[int32]string{ + 0: "RAG_RECORD_KIND_UNSPECIFIED", + 1: "RAG_RECORD_NODE", + 2: "RAG_RECORD_RELATIONSHIP", + } + RagRecordKind_value = map[string]int32{ + "RAG_RECORD_KIND_UNSPECIFIED": 0, + "RAG_RECORD_NODE": 1, + "RAG_RECORD_RELATIONSHIP": 2, + } +) + +func (x RagRecordKind) Enum() *RagRecordKind { + p := new(RagRecordKind) + *p = x + return p +} + +func (x RagRecordKind) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (RagRecordKind) Descriptor() protoreflect.EnumDescriptor { + return file_cstx_proto_enumTypes[9].Descriptor() +} + +func (RagRecordKind) Type() protoreflect.EnumType { + return &file_cstx_proto_enumTypes[9] +} + +func (x RagRecordKind) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use RagRecordKind.Descriptor instead. +func (RagRecordKind) EnumDescriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{9} +} + +type RagIndexMode int32 + +const ( + RagIndexMode_RAG_INDEX_MODE_UNSPECIFIED RagIndexMode = 0 + RagIndexMode_RAG_INDEX_INCREMENTAL RagIndexMode = 1 + RagIndexMode_RAG_INDEX_FULL RagIndexMode = 2 +) + +// Enum value maps for RagIndexMode. +var ( + RagIndexMode_name = map[int32]string{ + 0: "RAG_INDEX_MODE_UNSPECIFIED", + 1: "RAG_INDEX_INCREMENTAL", + 2: "RAG_INDEX_FULL", + } + RagIndexMode_value = map[string]int32{ + "RAG_INDEX_MODE_UNSPECIFIED": 0, + "RAG_INDEX_INCREMENTAL": 1, + "RAG_INDEX_FULL": 2, + } +) + +func (x RagIndexMode) Enum() *RagIndexMode { + p := new(RagIndexMode) + *p = x + return p +} + +func (x RagIndexMode) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (RagIndexMode) Descriptor() protoreflect.EnumDescriptor { + return file_cstx_proto_enumTypes[10].Descriptor() +} + +func (RagIndexMode) Type() protoreflect.EnumType { + return &file_cstx_proto_enumTypes[10] +} + +func (x RagIndexMode) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use RagIndexMode.Descriptor instead. +func (RagIndexMode) EnumDescriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{10} +} + +type CstxNodeOptions struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodeType string `protobuf:"bytes,1,opt,name=node_type,json=nodeType,proto3" json:"node_type,omitempty"` + ValueField string `protobuf:"bytes,2,opt,name=value_field,json=valueField,proto3" json:"value_field,omitempty"` + // The extension's own model composes this node type's identity, and no + // field or format string reproduces it (a URL brackets IPv6 hosts and + // omits an absent port; a vuln joins its asset and name). Declaring it + // here keeps the schema honest instead of naming a field that is merely + // part of the identity, and stops the runtime minting a wrong one. + IdentityComputed bool `protobuf:"varint,4,opt,name=identity_computed,json=identityComputed,proto3" json:"identity_computed,omitempty"` + // The column carrying this type's display label, when it is not the + // identity value. `find_node` falls back to it, so a person can look a node + // up by the name they see rather than by the key it is stored under. + // + // A declaration, not a reserved key: the runtime used to read an annotation + // literally named `name`, which nothing declared and nothing wrote. + LabelField string `protobuf:"bytes,5,opt,name=label_field,json=labelField,proto3" json:"label_field,omitempty"` +} + +func (x *CstxNodeOptions) Reset() { + *x = CstxNodeOptions{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CstxNodeOptions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CstxNodeOptions) ProtoMessage() {} + +func (x *CstxNodeOptions) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CstxNodeOptions.ProtoReflect.Descriptor instead. +func (*CstxNodeOptions) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{0} +} + +func (x *CstxNodeOptions) GetNodeType() string { + if x != nil { + return x.NodeType + } + return "" +} + +func (x *CstxNodeOptions) GetValueField() string { + if x != nil { + return x.ValueField + } + return "" +} + +func (x *CstxNodeOptions) GetIdentityComputed() bool { + if x != nil { + return x.IdentityComputed + } + return false +} + +func (x *CstxNodeOptions) GetLabelField() string { + if x != nil { + return x.LabelField + } + return "" +} + +type CstxComputeOptions struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Declared source column and a named pure string transform registered by + // the extension. Parsers never implement or invoke this step themselves. + From string `protobuf:"bytes,1,opt,name=from,proto3" json:"from,omitempty"` + Apply string `protobuf:"bytes,2,opt,name=apply,proto3" json:"apply,omitempty"` +} + +func (x *CstxComputeOptions) Reset() { + *x = CstxComputeOptions{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CstxComputeOptions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CstxComputeOptions) ProtoMessage() {} + +func (x *CstxComputeOptions) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CstxComputeOptions.ProtoReflect.Descriptor instead. +func (*CstxComputeOptions) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{1} +} + +func (x *CstxComputeOptions) GetFrom() string { + if x != nil { + return x.From + } + return "" +} + +func (x *CstxComputeOptions) GetApply() string { + if x != nil { + return x.Apply + } + return "" +} + +type CstxFieldOptions struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Identity bool `protobuf:"varint,1,opt,name=identity,proto3" json:"identity,omitempty"` + IdentityFormat string `protobuf:"bytes,2,opt,name=identity_format,json=identityFormat,proto3" json:"identity_format,omitempty"` + Semantic *bool `protobuf:"varint,3,opt,name=semantic,proto3,oneof" json:"semantic,omitempty"` + SemanticLabel string `protobuf:"bytes,4,opt,name=semantic_label,json=semanticLabel,proto3" json:"semantic_label,omitempty"` + // The column this field lands in, when it is not the one its proto type + // implies. Only `"json"` is meaningful, and only on a singular `string`: + // the field travels as text on the wire and is stored as a JSON document, + // which is how a type declares an open bag for values it has no column for. + // Declaring the bag is the point — an undeclared overflow channel is how a + // second, untyped half of every entity grows. + Column string `protobuf:"bytes,6,opt,name=column,proto3" json:"column,omitempty"` + // The field's value domain, in order, lowest first. + // + // A field that declares one compares by position rather than + // lexicographically, so `x > medium` means what the extension says it + // means. The runtime holds the mechanism and never the vocabulary: which + // tokens exist, and in what order, is the extension's business. This + // replaced a severity table compiled into the query engine, where a + // security domain's words decided how a neutral engine compared strings. + OrderedValues []string `protobuf:"bytes,5,rep,name=ordered_values,json=orderedValues,proto3" json:"ordered_values,omitempty"` + // A stored column derived by the Rust graph engine after graph_add and + // before link. This keeps parser implementations language-neutral. + Compute *CstxComputeOptions `protobuf:"bytes,7,opt,name=compute,proto3" json:"compute,omitempty"` +} + +func (x *CstxFieldOptions) Reset() { + *x = CstxFieldOptions{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CstxFieldOptions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CstxFieldOptions) ProtoMessage() {} + +func (x *CstxFieldOptions) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CstxFieldOptions.ProtoReflect.Descriptor instead. +func (*CstxFieldOptions) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{2} +} + +func (x *CstxFieldOptions) GetIdentity() bool { + if x != nil { + return x.Identity + } + return false +} + +func (x *CstxFieldOptions) GetIdentityFormat() string { + if x != nil { + return x.IdentityFormat + } + return "" +} + +func (x *CstxFieldOptions) GetSemantic() bool { + if x != nil && x.Semantic != nil { + return *x.Semantic + } + return false +} + +func (x *CstxFieldOptions) GetSemanticLabel() string { + if x != nil { + return x.SemanticLabel + } + return "" +} + +func (x *CstxFieldOptions) GetColumn() string { + if x != nil { + return x.Column + } + return "" +} + +func (x *CstxFieldOptions) GetOrderedValues() []string { + if x != nil { + return x.OrderedValues + } + return nil +} + +func (x *CstxFieldOptions) GetCompute() *CstxComputeOptions { + if x != nil { + return x.Compute + } + return nil +} + +type CstxRelationshipOptions struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RelationshipType string `protobuf:"bytes,1,opt,name=relationship_type,json=relationshipType,proto3" json:"relationship_type,omitempty"` +} + +func (x *CstxRelationshipOptions) Reset() { + *x = CstxRelationshipOptions{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CstxRelationshipOptions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CstxRelationshipOptions) ProtoMessage() {} + +func (x *CstxRelationshipOptions) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CstxRelationshipOptions.ProtoReflect.Descriptor instead. +func (*CstxRelationshipOptions) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{3} +} + +func (x *CstxRelationshipOptions) GetRelationshipType() string { + if x != nil { + return x.RelationshipType + } + return "" +} + +// One flag an extension declares, and the bit it occupies forever. +// +// The bit is part of the flag's identity exactly as a field number is part of +// a column's: it is what a stored mask means. So the extension names it here +// rather than letting a runtime hand one out in registration order, which +// would make the same stored mask mean different things depending on what +// else was registered that day. A published bit is never reused. +// +// Bits 56-63 are reserved for the runtime itself. Extensions declare 0-55. +type CstxFlagOptions struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Bit uint32 `protobuf:"varint,1,opt,name=bit,proto3" json:"bit,omitempty"` + // Whether a consumer's "ordinary view" is expected to hide this flag. + // Advice, not enforcement: the runtime never applies it on its own. + DefaultExclude bool `protobuf:"varint,2,opt,name=default_exclude,json=defaultExclude,proto3" json:"default_exclude,omitempty"` + Label string `protobuf:"bytes,3,opt,name=label,proto3" json:"label,omitempty"` +} + +func (x *CstxFlagOptions) Reset() { + *x = CstxFlagOptions{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CstxFlagOptions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CstxFlagOptions) ProtoMessage() {} + +func (x *CstxFlagOptions) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CstxFlagOptions.ProtoReflect.Descriptor instead. +func (*CstxFlagOptions) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{4} +} + +func (x *CstxFlagOptions) GetBit() uint32 { + if x != nil { + return x.Bit + } + return 0 +} + +func (x *CstxFlagOptions) GetDefaultExclude() bool { + if x != nil { + return x.DefaultExclude + } + return false +} + +func (x *CstxFlagOptions) GetLabel() string { + if x != nil { + return x.Label + } + return "" +} + +type RuntimeConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ProjectId string `protobuf:"bytes,1,opt,name=project_id,json=projectId,proto3" json:"project_id,omitempty"` + CursorPageSize uint64 `protobuf:"varint,2,opt,name=cursor_page_size,json=cursorPageSize,proto3" json:"cursor_page_size,omitempty"` +} + +func (x *RuntimeConfig) Reset() { + *x = RuntimeConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RuntimeConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RuntimeConfig) ProtoMessage() {} + +func (x *RuntimeConfig) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RuntimeConfig.ProtoReflect.Descriptor instead. +func (*RuntimeConfig) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{5} +} + +func (x *RuntimeConfig) GetProjectId() string { + if x != nil { + return x.ProjectId + } + return "" +} + +func (x *RuntimeConfig) GetCursorPageSize() uint64 { + if x != nil { + return x.CursorPageSize + } + return 0 +} + +type StringList struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Values []string `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"` +} + +func (x *StringList) Reset() { + *x = StringList{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StringList) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StringList) ProtoMessage() {} + +func (x *StringList) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StringList.ProtoReflect.Descriptor instead. +func (*StringList) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{6} +} + +func (x *StringList) GetValues() []string { + if x != nil { + return x.Values + } + return nil +} + +// One field of a node, typed without a descriptor. +// +// The branches are the column kinds the graph stores, which is the whole set +// a schema document can declare. An SDK builds these from a map of field +// names; it never needs the field numbers, and it never needs a message type +// generated for the node. +type EntityField struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // Types that are assignable to Value: + // + // *EntityField_Text + // *EntityField_Number + // *EntityField_Flag + // *EntityField_Real + // *EntityField_List + Value isEntityField_Value `protobuf_oneof:"value"` +} + +func (x *EntityField) Reset() { + *x = EntityField{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EntityField) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EntityField) ProtoMessage() {} + +func (x *EntityField) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EntityField.ProtoReflect.Descriptor instead. +func (*EntityField) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{7} +} + +func (x *EntityField) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (m *EntityField) GetValue() isEntityField_Value { + if m != nil { + return m.Value + } + return nil +} + +func (x *EntityField) GetText() string { + if x, ok := x.GetValue().(*EntityField_Text); ok { + return x.Text + } + return "" +} + +func (x *EntityField) GetNumber() int64 { + if x, ok := x.GetValue().(*EntityField_Number); ok { + return x.Number + } + return 0 +} + +func (x *EntityField) GetFlag() bool { + if x, ok := x.GetValue().(*EntityField_Flag); ok { + return x.Flag + } + return false +} + +func (x *EntityField) GetReal() float64 { + if x, ok := x.GetValue().(*EntityField_Real); ok { + return x.Real + } + return 0 +} + +func (x *EntityField) GetList() *StringList { + if x, ok := x.GetValue().(*EntityField_List); ok { + return x.List + } + return nil +} + +type isEntityField_Value interface { + isEntityField_Value() +} + +type EntityField_Text struct { + Text string `protobuf:"bytes,2,opt,name=text,proto3,oneof"` +} + +type EntityField_Number struct { + Number int64 `protobuf:"varint,3,opt,name=number,proto3,oneof"` +} + +type EntityField_Flag struct { + Flag bool `protobuf:"varint,4,opt,name=flag,proto3,oneof"` +} + +type EntityField_Real struct { + Real float64 `protobuf:"fixed64,5,opt,name=real,proto3,oneof"` +} + +type EntityField_List struct { + List *StringList `protobuf:"bytes,6,opt,name=list,proto3,oneof"` +} + +func (*EntityField_Text) isEntityField_Value() {} + +func (*EntityField_Number) isEntityField_Value() {} + +func (*EntityField_Flag) isEntityField_Value() {} + +func (*EntityField_Real) isEntityField_Value() {} + +func (*EntityField_List) isEntityField_Value() {} + +// A node payload as field names and values, for callers with no generated +// message type. The runtime encodes it into the extension's own protobuf +// message using the registered schema document. +type EntityValue struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodeType string `protobuf:"bytes,1,opt,name=node_type,json=nodeType,proto3" json:"node_type,omitempty"` + Fields []*EntityField `protobuf:"bytes,2,rep,name=fields,proto3" json:"fields,omitempty"` +} + +func (x *EntityValue) Reset() { + *x = EntityValue{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EntityValue) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EntityValue) ProtoMessage() {} + +func (x *EntityValue) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EntityValue.ProtoReflect.Descriptor instead. +func (*EntityValue) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{8} +} + +func (x *EntityValue) GetNodeType() string { + if x != nil { + return x.NodeType + } + return "" +} + +func (x *EntityValue) GetFields() []*EntityField { + if x != nil { + return x.Fields + } + return nil +} + +// A relationship payload named by the runtime schema. It carries the +// producer-owned model without requiring a generated relationship message. +type RelationshipValue struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RelationshipType string `protobuf:"bytes,1,opt,name=relationship_type,json=relationshipType,proto3" json:"relationship_type,omitempty"` + Fields []*EntityField `protobuf:"bytes,2,rep,name=fields,proto3" json:"fields,omitempty"` +} + +func (x *RelationshipValue) Reset() { + *x = RelationshipValue{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RelationshipValue) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RelationshipValue) ProtoMessage() {} + +func (x *RelationshipValue) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RelationshipValue.ProtoReflect.Descriptor instead. +func (*RelationshipValue) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{9} +} + +func (x *RelationshipValue) GetRelationshipType() string { + if x != nil { + return x.RelationshipType + } + return "" +} + +func (x *RelationshipValue) GetFields() []*EntityField { + if x != nil { + return x.Fields + } + return nil +} + +type Node struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id *string `protobuf:"bytes,1,opt,name=id,proto3,oneof" json:"id,omitempty"` + Sources []string `protobuf:"bytes,3,rep,name=sources,proto3" json:"sources,omitempty"` + Annotations *structpb.Struct `protobuf:"bytes,4,opt,name=annotations,proto3" json:"annotations,omitempty"` + // The payload, named by the schema document the extension registered. This + // is the only spelling; a caller holding no generated message type for the + // node writes and reads it on the same terms as one that does. + Value *EntityValue `protobuf:"bytes,6,opt,name=value,proto3" json:"value,omitempty"` + // This node's flag bits. What bit N means is declared by the extension that + // claimed it (`.schema.json`, `flags`); the runtime carries the + // mask and answers by name through `FlagRegistry`. Extensions declare bits + // 0-55; 56-63 belong to the runtime. + FlagsMask uint64 `protobuf:"varint,7,opt,name=flags_mask,json=flagsMask,proto3" json:"flags_mask,omitempty"` +} + +func (x *Node) Reset() { + *x = Node{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Node) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Node) ProtoMessage() {} + +func (x *Node) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Node.ProtoReflect.Descriptor instead. +func (*Node) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{10} +} + +func (x *Node) GetId() string { + if x != nil && x.Id != nil { + return *x.Id + } + return "" +} + +func (x *Node) GetSources() []string { + if x != nil { + return x.Sources + } + return nil +} + +func (x *Node) GetAnnotations() *structpb.Struct { + if x != nil { + return x.Annotations + } + return nil +} + +func (x *Node) GetValue() *EntityValue { + if x != nil { + return x.Value + } + return nil +} + +func (x *Node) GetFlagsMask() uint64 { + if x != nil { + return x.FlagsMask + } + return 0 +} + +type Relationship struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id *string `protobuf:"bytes,1,opt,name=id,proto3,oneof" json:"id,omitempty"` + SourceId string `protobuf:"bytes,2,opt,name=source_id,json=sourceId,proto3" json:"source_id,omitempty"` + TargetId string `protobuf:"bytes,3,opt,name=target_id,json=targetId,proto3" json:"target_id,omitempty"` + Sources []string `protobuf:"bytes,5,rep,name=sources,proto3" json:"sources,omitempty"` + // Third-party statements about the relationship, never producer content. + Annotations *structpb.Struct `protobuf:"bytes,6,opt,name=annotations,proto3" json:"annotations,omitempty"` + // The producer-owned model, named by the registered relationship schema. + Value *RelationshipValue `protobuf:"bytes,7,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *Relationship) Reset() { + *x = Relationship{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Relationship) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Relationship) ProtoMessage() {} + +func (x *Relationship) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Relationship.ProtoReflect.Descriptor instead. +func (*Relationship) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{11} +} + +func (x *Relationship) GetId() string { + if x != nil && x.Id != nil { + return *x.Id + } + return "" +} + +func (x *Relationship) GetSourceId() string { + if x != nil { + return x.SourceId + } + return "" +} + +func (x *Relationship) GetTargetId() string { + if x != nil { + return x.TargetId + } + return "" +} + +func (x *Relationship) GetSources() []string { + if x != nil { + return x.Sources + } + return nil +} + +func (x *Relationship) GetAnnotations() *structpb.Struct { + if x != nil { + return x.Annotations + } + return nil +} + +func (x *Relationship) GetValue() *RelationshipValue { + if x != nil { + return x.Value + } + return nil +} + +type Graph struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Nodes []*Node `protobuf:"bytes,1,rep,name=nodes,proto3" json:"nodes,omitempty"` + Relationships []*Relationship `protobuf:"bytes,2,rep,name=relationships,proto3" json:"relationships,omitempty"` +} + +func (x *Graph) Reset() { + *x = Graph{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Graph) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Graph) ProtoMessage() {} + +func (x *Graph) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Graph.ProtoReflect.Descriptor instead. +func (*Graph) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{12} +} + +func (x *Graph) GetNodes() []*Node { + if x != nil { + return x.Nodes + } + return nil +} + +func (x *Graph) GetRelationships() []*Relationship { + if x != nil { + return x.Relationships + } + return nil +} + +type GraphChangeSet struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AddedNodeIds []string `protobuf:"bytes,1,rep,name=added_node_ids,json=addedNodeIds,proto3" json:"added_node_ids,omitempty"` + UpdatedNodeIds []string `protobuf:"bytes,2,rep,name=updated_node_ids,json=updatedNodeIds,proto3" json:"updated_node_ids,omitempty"` + RemovedNodeIds []string `protobuf:"bytes,3,rep,name=removed_node_ids,json=removedNodeIds,proto3" json:"removed_node_ids,omitempty"` + AddedRelationshipIds []string `protobuf:"bytes,4,rep,name=added_relationship_ids,json=addedRelationshipIds,proto3" json:"added_relationship_ids,omitempty"` + UpdatedRelationshipIds []string `protobuf:"bytes,5,rep,name=updated_relationship_ids,json=updatedRelationshipIds,proto3" json:"updated_relationship_ids,omitempty"` + RemovedRelationshipIds []string `protobuf:"bytes,6,rep,name=removed_relationship_ids,json=removedRelationshipIds,proto3" json:"removed_relationship_ids,omitempty"` + Reset_ bool `protobuf:"varint,7,opt,name=reset,proto3" json:"reset,omitempty"` +} + +func (x *GraphChangeSet) Reset() { + *x = GraphChangeSet{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GraphChangeSet) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GraphChangeSet) ProtoMessage() {} + +func (x *GraphChangeSet) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GraphChangeSet.ProtoReflect.Descriptor instead. +func (*GraphChangeSet) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{13} +} + +func (x *GraphChangeSet) GetAddedNodeIds() []string { + if x != nil { + return x.AddedNodeIds + } + return nil +} + +func (x *GraphChangeSet) GetUpdatedNodeIds() []string { + if x != nil { + return x.UpdatedNodeIds + } + return nil +} + +func (x *GraphChangeSet) GetRemovedNodeIds() []string { + if x != nil { + return x.RemovedNodeIds + } + return nil +} + +func (x *GraphChangeSet) GetAddedRelationshipIds() []string { + if x != nil { + return x.AddedRelationshipIds + } + return nil +} + +func (x *GraphChangeSet) GetUpdatedRelationshipIds() []string { + if x != nil { + return x.UpdatedRelationshipIds + } + return nil +} + +func (x *GraphChangeSet) GetRemovedRelationshipIds() []string { + if x != nil { + return x.RemovedRelationshipIds + } + return nil +} + +func (x *GraphChangeSet) GetReset_() bool { + if x != nil { + return x.Reset_ + } + return false +} + +type GraphChangeSummary struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AddedNodes uint64 `protobuf:"varint,1,opt,name=added_nodes,json=addedNodes,proto3" json:"added_nodes,omitempty"` + UpdatedNodes uint64 `protobuf:"varint,2,opt,name=updated_nodes,json=updatedNodes,proto3" json:"updated_nodes,omitempty"` + RemovedNodes uint64 `protobuf:"varint,3,opt,name=removed_nodes,json=removedNodes,proto3" json:"removed_nodes,omitempty"` + AddedRelationships uint64 `protobuf:"varint,4,opt,name=added_relationships,json=addedRelationships,proto3" json:"added_relationships,omitempty"` + UpdatedRelationships uint64 `protobuf:"varint,5,opt,name=updated_relationships,json=updatedRelationships,proto3" json:"updated_relationships,omitempty"` + RemovedRelationships uint64 `protobuf:"varint,6,opt,name=removed_relationships,json=removedRelationships,proto3" json:"removed_relationships,omitempty"` +} + +func (x *GraphChangeSummary) Reset() { + *x = GraphChangeSummary{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GraphChangeSummary) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GraphChangeSummary) ProtoMessage() {} + +func (x *GraphChangeSummary) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GraphChangeSummary.ProtoReflect.Descriptor instead. +func (*GraphChangeSummary) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{14} +} + +func (x *GraphChangeSummary) GetAddedNodes() uint64 { + if x != nil { + return x.AddedNodes + } + return 0 +} + +func (x *GraphChangeSummary) GetUpdatedNodes() uint64 { + if x != nil { + return x.UpdatedNodes + } + return 0 +} + +func (x *GraphChangeSummary) GetRemovedNodes() uint64 { + if x != nil { + return x.RemovedNodes + } + return 0 +} + +func (x *GraphChangeSummary) GetAddedRelationships() uint64 { + if x != nil { + return x.AddedRelationships + } + return 0 +} + +func (x *GraphChangeSummary) GetUpdatedRelationships() uint64 { + if x != nil { + return x.UpdatedRelationships + } + return 0 +} + +func (x *GraphChangeSummary) GetRemovedRelationships() uint64 { + if x != nil { + return x.RemovedRelationships + } + return 0 +} + +type GraphStats struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodesByType map[string]uint64 `protobuf:"bytes,1,rep,name=nodes_by_type,json=nodesByType,proto3" json:"nodes_by_type,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` + RelationshipsByType map[string]uint64 `protobuf:"bytes,2,rep,name=relationships_by_type,json=relationshipsByType,proto3" json:"relationships_by_type,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` + ObjectsBySource map[string]uint64 `protobuf:"bytes,3,rep,name=objects_by_source,json=objectsBySource,proto3" json:"objects_by_source,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` + AnchorsByKind map[string]uint64 `protobuf:"bytes,4,rep,name=anchors_by_kind,json=anchorsByKind,proto3" json:"anchors_by_kind,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` +} + +func (x *GraphStats) Reset() { + *x = GraphStats{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GraphStats) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GraphStats) ProtoMessage() {} + +func (x *GraphStats) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GraphStats.ProtoReflect.Descriptor instead. +func (*GraphStats) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{15} +} + +func (x *GraphStats) GetNodesByType() map[string]uint64 { + if x != nil { + return x.NodesByType + } + return nil +} + +func (x *GraphStats) GetRelationshipsByType() map[string]uint64 { + if x != nil { + return x.RelationshipsByType + } + return nil +} + +func (x *GraphStats) GetObjectsBySource() map[string]uint64 { + if x != nil { + return x.ObjectsBySource + } + return nil +} + +func (x *GraphStats) GetAnchorsByKind() map[string]uint64 { + if x != nil { + return x.AnchorsByKind + } + return nil +} + +type Commit struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Parents []string `protobuf:"bytes,2,rep,name=parents,proto3" json:"parents,omitempty"` + Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"` + Metadata *structpb.Struct `protobuf:"bytes,4,opt,name=metadata,proto3" json:"metadata,omitempty"` + Stats *GraphChangeSummary `protobuf:"bytes,5,opt,name=stats,proto3" json:"stats,omitempty"` + CreatedAt int64 `protobuf:"varint,6,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` +} + +func (x *Commit) Reset() { + *x = Commit{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Commit) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Commit) ProtoMessage() {} + +func (x *Commit) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Commit.ProtoReflect.Descriptor instead. +func (*Commit) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{16} +} + +func (x *Commit) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *Commit) GetParents() []string { + if x != nil { + return x.Parents + } + return nil +} + +func (x *Commit) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +func (x *Commit) GetMetadata() *structpb.Struct { + if x != nil { + return x.Metadata + } + return nil +} + +func (x *Commit) GetStats() *GraphChangeSummary { + if x != nil { + return x.Stats + } + return nil +} + +func (x *Commit) GetCreatedAt() int64 { + if x != nil { + return x.CreatedAt + } + return 0 +} + +type CommitLog struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Commits []*Commit `protobuf:"bytes,1,rep,name=commits,proto3" json:"commits,omitempty"` +} + +func (x *CommitLog) Reset() { + *x = CommitLog{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CommitLog) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CommitLog) ProtoMessage() {} + +func (x *CommitLog) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CommitLog.ProtoReflect.Descriptor instead. +func (*CommitLog) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{17} +} + +func (x *CommitLog) GetCommits() []*Commit { + if x != nil { + return x.Commits + } + return nil +} + +type EntityChange struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CommitId string `protobuf:"bytes,1,opt,name=commit_id,json=commitId,proto3" json:"commit_id,omitempty"` + Ordinal uint64 `protobuf:"varint,2,opt,name=ordinal,proto3" json:"ordinal,omitempty"` + Timestamp int64 `protobuf:"varint,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + Operation ChangeOperation `protobuf:"varint,4,opt,name=operation,proto3,enum=cstx.ChangeOperation" json:"operation,omitempty"` + BeforeObjectId *string `protobuf:"bytes,5,opt,name=before_object_id,json=beforeObjectId,proto3,oneof" json:"before_object_id,omitempty"` + AfterObjectId *string `protobuf:"bytes,6,opt,name=after_object_id,json=afterObjectId,proto3,oneof" json:"after_object_id,omitempty"` +} + +func (x *EntityChange) Reset() { + *x = EntityChange{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EntityChange) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EntityChange) ProtoMessage() {} + +func (x *EntityChange) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EntityChange.ProtoReflect.Descriptor instead. +func (*EntityChange) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{18} +} + +func (x *EntityChange) GetCommitId() string { + if x != nil { + return x.CommitId + } + return "" +} + +func (x *EntityChange) GetOrdinal() uint64 { + if x != nil { + return x.Ordinal + } + return 0 +} + +func (x *EntityChange) GetTimestamp() int64 { + if x != nil { + return x.Timestamp + } + return 0 +} + +func (x *EntityChange) GetOperation() ChangeOperation { + if x != nil { + return x.Operation + } + return ChangeOperation_CHANGE_OPERATION_UNSPECIFIED +} + +func (x *EntityChange) GetBeforeObjectId() string { + if x != nil && x.BeforeObjectId != nil { + return *x.BeforeObjectId + } + return "" +} + +func (x *EntityChange) GetAfterObjectId() string { + if x != nil && x.AfterObjectId != nil { + return *x.AfterObjectId + } + return "" +} + +type EntityHistory struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Changes []*EntityChange `protobuf:"bytes,1,rep,name=changes,proto3" json:"changes,omitempty"` +} + +func (x *EntityHistory) Reset() { + *x = EntityHistory{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EntityHistory) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EntityHistory) ProtoMessage() {} + +func (x *EntityHistory) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[19] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EntityHistory.ProtoReflect.Descriptor instead. +func (*EntityHistory) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{19} +} + +func (x *EntityHistory) GetChanges() []*EntityChange { + if x != nil { + return x.Changes + } + return nil +} + +type GraphSelection struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodeIds []string `protobuf:"bytes,1,rep,name=node_ids,json=nodeIds,proto3" json:"node_ids,omitempty"` + RelationshipIds []string `protobuf:"bytes,2,rep,name=relationship_ids,json=relationshipIds,proto3" json:"relationship_ids,omitempty"` + AllNodes bool `protobuf:"varint,3,opt,name=all_nodes,json=allNodes,proto3" json:"all_nodes,omitempty"` +} + +func (x *GraphSelection) Reset() { + *x = GraphSelection{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GraphSelection) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GraphSelection) ProtoMessage() {} + +func (x *GraphSelection) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[20] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GraphSelection.ProtoReflect.Descriptor instead. +func (*GraphSelection) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{20} +} + +func (x *GraphSelection) GetNodeIds() []string { + if x != nil { + return x.NodeIds + } + return nil +} + +func (x *GraphSelection) GetRelationshipIds() []string { + if x != nil { + return x.RelationshipIds + } + return nil +} + +func (x *GraphSelection) GetAllNodes() bool { + if x != nil { + return x.AllNodes + } + return false +} + +type GraphDiff struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Added *GraphSelection `protobuf:"bytes,1,opt,name=added,proto3" json:"added,omitempty"` + Removed *GraphSelection `protobuf:"bytes,2,opt,name=removed,proto3" json:"removed,omitempty"` + Modified *GraphSelection `protobuf:"bytes,3,opt,name=modified,proto3" json:"modified,omitempty"` + Truncated bool `protobuf:"varint,4,opt,name=truncated,proto3" json:"truncated,omitempty"` + Stats *GraphChangeSummary `protobuf:"bytes,5,opt,name=stats,proto3" json:"stats,omitempty"` +} + +func (x *GraphDiff) Reset() { + *x = GraphDiff{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GraphDiff) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GraphDiff) ProtoMessage() {} + +func (x *GraphDiff) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[21] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GraphDiff.ProtoReflect.Descriptor instead. +func (*GraphDiff) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{21} +} + +func (x *GraphDiff) GetAdded() *GraphSelection { + if x != nil { + return x.Added + } + return nil +} + +func (x *GraphDiff) GetRemoved() *GraphSelection { + if x != nil { + return x.Removed + } + return nil +} + +func (x *GraphDiff) GetModified() *GraphSelection { + if x != nil { + return x.Modified + } + return nil +} + +func (x *GraphDiff) GetTruncated() bool { + if x != nil { + return x.Truncated + } + return false +} + +func (x *GraphDiff) GetStats() *GraphChangeSummary { + if x != nil { + return x.Stats + } + return nil +} + +type QueryWindow struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Limit *uint64 `protobuf:"varint,1,opt,name=limit,proto3,oneof" json:"limit,omitempty"` + Page uint64 `protobuf:"varint,2,opt,name=page,proto3" json:"page,omitempty"` + Order SortOrder `protobuf:"varint,3,opt,name=order,proto3,enum=cstx.SortOrder" json:"order,omitempty"` +} + +func (x *QueryWindow) Reset() { + *x = QueryWindow{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryWindow) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryWindow) ProtoMessage() {} + +func (x *QueryWindow) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[22] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use QueryWindow.ProtoReflect.Descriptor instead. +func (*QueryWindow) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{22} +} + +func (x *QueryWindow) GetLimit() uint64 { + if x != nil && x.Limit != nil { + return *x.Limit + } + return 0 +} + +func (x *QueryWindow) GetPage() uint64 { + if x != nil { + return x.Page + } + return 0 +} + +func (x *QueryWindow) GetOrder() SortOrder { + if x != nil { + return x.Order + } + return SortOrder_SORT_ORDER_UNSPECIFIED +} + +type NodeFilter struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodeTypes []string `protobuf:"bytes,1,rep,name=node_types,json=nodeTypes,proto3" json:"node_types,omitempty"` + NodeIds []string `protobuf:"bytes,2,rep,name=node_ids,json=nodeIds,proto3" json:"node_ids,omitempty"` + Sources []string `protobuf:"bytes,3,rep,name=sources,proto3" json:"sources,omitempty"` + NameContains *string `protobuf:"bytes,4,opt,name=name_contains,json=nameContains,proto3,oneof" json:"name_contains,omitempty"` + // Every bit set / at least one bit set / no bit set. Zero means "no + // predicate", which is what an empty repeated field used to mean. + FlagsAllMask uint64 `protobuf:"varint,8,opt,name=flags_all_mask,json=flagsAllMask,proto3" json:"flags_all_mask,omitempty"` + FlagsAnyMask uint64 `protobuf:"varint,9,opt,name=flags_any_mask,json=flagsAnyMask,proto3" json:"flags_any_mask,omitempty"` + FlagsNoneMask uint64 `protobuf:"varint,10,opt,name=flags_none_mask,json=flagsNoneMask,proto3" json:"flags_none_mask,omitempty"` +} + +func (x *NodeFilter) Reset() { + *x = NodeFilter{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodeFilter) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeFilter) ProtoMessage() {} + +func (x *NodeFilter) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[23] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodeFilter.ProtoReflect.Descriptor instead. +func (*NodeFilter) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{23} +} + +func (x *NodeFilter) GetNodeTypes() []string { + if x != nil { + return x.NodeTypes + } + return nil +} + +func (x *NodeFilter) GetNodeIds() []string { + if x != nil { + return x.NodeIds + } + return nil +} + +func (x *NodeFilter) GetSources() []string { + if x != nil { + return x.Sources + } + return nil +} + +func (x *NodeFilter) GetNameContains() string { + if x != nil && x.NameContains != nil { + return *x.NameContains + } + return "" +} + +func (x *NodeFilter) GetFlagsAllMask() uint64 { + if x != nil { + return x.FlagsAllMask + } + return 0 +} + +func (x *NodeFilter) GetFlagsAnyMask() uint64 { + if x != nil { + return x.FlagsAnyMask + } + return 0 +} + +func (x *NodeFilter) GetFlagsNoneMask() uint64 { + if x != nil { + return x.FlagsNoneMask + } + return 0 +} + +type RelationshipFilter struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SourceId *string `protobuf:"bytes,1,opt,name=source_id,json=sourceId,proto3,oneof" json:"source_id,omitempty"` + TargetId *string `protobuf:"bytes,2,opt,name=target_id,json=targetId,proto3,oneof" json:"target_id,omitempty"` + RelationshipTypes []string `protobuf:"bytes,3,rep,name=relationship_types,json=relationshipTypes,proto3" json:"relationship_types,omitempty"` + Sources []string `protobuf:"bytes,4,rep,name=sources,proto3" json:"sources,omitempty"` +} + +func (x *RelationshipFilter) Reset() { + *x = RelationshipFilter{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RelationshipFilter) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RelationshipFilter) ProtoMessage() {} + +func (x *RelationshipFilter) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[24] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RelationshipFilter.ProtoReflect.Descriptor instead. +func (*RelationshipFilter) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{24} +} + +func (x *RelationshipFilter) GetSourceId() string { + if x != nil && x.SourceId != nil { + return *x.SourceId + } + return "" +} + +func (x *RelationshipFilter) GetTargetId() string { + if x != nil && x.TargetId != nil { + return *x.TargetId + } + return "" +} + +func (x *RelationshipFilter) GetRelationshipTypes() []string { + if x != nil { + return x.RelationshipTypes + } + return nil +} + +func (x *RelationshipFilter) GetSources() []string { + if x != nil { + return x.Sources + } + return nil +} + +// Native collection requests keep selection and paging in one protobuf value. +// They are used by the C ABI and Go SDK; Python receives the same two semantic +// messages through its typed binding because PyO3 already has separate +// arguments for them. +type NodeQuery struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Filter *NodeFilter `protobuf:"bytes,1,opt,name=filter,proto3" json:"filter,omitempty"` + Window *QueryWindow `protobuf:"bytes,2,opt,name=window,proto3" json:"window,omitempty"` +} + +func (x *NodeQuery) Reset() { + *x = NodeQuery{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodeQuery) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeQuery) ProtoMessage() {} + +func (x *NodeQuery) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[25] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodeQuery.ProtoReflect.Descriptor instead. +func (*NodeQuery) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{25} +} + +func (x *NodeQuery) GetFilter() *NodeFilter { + if x != nil { + return x.Filter + } + return nil +} + +func (x *NodeQuery) GetWindow() *QueryWindow { + if x != nil { + return x.Window + } + return nil +} + +type RelationshipQuery struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Filter *RelationshipFilter `protobuf:"bytes,1,opt,name=filter,proto3" json:"filter,omitempty"` + Window *QueryWindow `protobuf:"bytes,2,opt,name=window,proto3" json:"window,omitempty"` +} + +func (x *RelationshipQuery) Reset() { + *x = RelationshipQuery{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RelationshipQuery) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RelationshipQuery) ProtoMessage() {} + +func (x *RelationshipQuery) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[26] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RelationshipQuery.ProtoReflect.Descriptor instead. +func (*RelationshipQuery) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{26} +} + +func (x *RelationshipQuery) GetFilter() *RelationshipFilter { + if x != nil { + return x.Filter + } + return nil +} + +func (x *RelationshipQuery) GetWindow() *QueryWindow { + if x != nil { + return x.Window + } + return nil +} + +type GraphProjection struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodeFilter *NodeFilter `protobuf:"bytes,1,opt,name=node_filter,json=nodeFilter,proto3" json:"node_filter,omitempty"` + Excluded *GraphSelection `protobuf:"bytes,2,opt,name=excluded,proto3" json:"excluded,omitempty"` +} + +func (x *GraphProjection) Reset() { + *x = GraphProjection{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GraphProjection) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GraphProjection) ProtoMessage() {} + +func (x *GraphProjection) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[27] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GraphProjection.ProtoReflect.Descriptor instead. +func (*GraphProjection) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{27} +} + +func (x *GraphProjection) GetNodeFilter() *NodeFilter { + if x != nil { + return x.NodeFilter + } + return nil +} + +func (x *GraphProjection) GetExcluded() *GraphSelection { + if x != nil { + return x.Excluded + } + return nil +} + +type QueryOptions struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Window *QueryWindow `protobuf:"bytes,1,opt,name=window,proto3" json:"window,omitempty"` + ResultFilter *NodeFilter `protobuf:"bytes,2,opt,name=result_filter,json=resultFilter,proto3" json:"result_filter,omitempty"` + Projection *GraphProjection `protobuf:"bytes,3,opt,name=projection,proto3" json:"projection,omitempty"` +} + +func (x *QueryOptions) Reset() { + *x = QueryOptions{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryOptions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryOptions) ProtoMessage() {} + +func (x *QueryOptions) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[28] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use QueryOptions.ProtoReflect.Descriptor instead. +func (*QueryOptions) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{28} +} + +func (x *QueryOptions) GetWindow() *QueryWindow { + if x != nil { + return x.Window + } + return nil +} + +func (x *QueryOptions) GetResultFilter() *NodeFilter { + if x != nil { + return x.ResultFilter + } + return nil +} + +func (x *QueryOptions) GetProjection() *GraphProjection { + if x != nil { + return x.Projection + } + return nil +} + +type NodeTypeCatalog struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodeTypes []string `protobuf:"bytes,1,rep,name=node_types,json=nodeTypes,proto3" json:"node_types,omitempty"` + // Retained schema metadata for extension introspection. `node_types` is + // kept for the cheap name-only query; `schemas` is the typed form. + Schemas []*NodeType `protobuf:"bytes,2,rep,name=schemas,proto3" json:"schemas,omitempty"` +} + +func (x *NodeTypeCatalog) Reset() { + *x = NodeTypeCatalog{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodeTypeCatalog) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeTypeCatalog) ProtoMessage() {} + +func (x *NodeTypeCatalog) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[29] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodeTypeCatalog.ProtoReflect.Descriptor instead. +func (*NodeTypeCatalog) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{29} +} + +func (x *NodeTypeCatalog) GetNodeTypes() []string { + if x != nil { + return x.NodeTypes + } + return nil +} + +func (x *NodeTypeCatalog) GetSchemas() []*NodeType { + if x != nil { + return x.Schemas + } + return nil +} + +type NeighborQuery struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` + Direction Direction `protobuf:"varint,2,opt,name=direction,proto3,enum=cstx.Direction" json:"direction,omitempty"` + Window *QueryWindow `protobuf:"bytes,3,opt,name=window,proto3" json:"window,omitempty"` +} + +func (x *NeighborQuery) Reset() { + *x = NeighborQuery{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NeighborQuery) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NeighborQuery) ProtoMessage() {} + +func (x *NeighborQuery) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[30] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NeighborQuery.ProtoReflect.Descriptor instead. +func (*NeighborQuery) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{30} +} + +func (x *NeighborQuery) GetNodeId() string { + if x != nil { + return x.NodeId + } + return "" +} + +func (x *NeighborQuery) GetDirection() Direction { + if x != nil { + return x.Direction + } + return Direction_DIRECTION_UNSPECIFIED +} + +func (x *NeighborQuery) GetWindow() *QueryWindow { + if x != nil { + return x.Window + } + return nil +} + +type GraphQuery struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Expression string `protobuf:"bytes,1,opt,name=expression,proto3" json:"expression,omitempty"` + Options *QueryOptions `protobuf:"bytes,2,opt,name=options,proto3" json:"options,omitempty"` +} + +func (x *GraphQuery) Reset() { + *x = GraphQuery{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[31] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GraphQuery) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GraphQuery) ProtoMessage() {} + +func (x *GraphQuery) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[31] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GraphQuery.ProtoReflect.Descriptor instead. +func (*GraphQuery) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{31} +} + +func (x *GraphQuery) GetExpression() string { + if x != nil { + return x.Expression + } + return "" +} + +func (x *GraphQuery) GetOptions() *QueryOptions { + if x != nil { + return x.Options + } + return nil +} + +type NodeAnnotationUpdate struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Selection *GraphSelection `protobuf:"bytes,1,opt,name=selection,proto3" json:"selection,omitempty"` + Annotations *structpb.Struct `protobuf:"bytes,2,opt,name=annotations,proto3" json:"annotations,omitempty"` +} + +func (x *NodeAnnotationUpdate) Reset() { + *x = NodeAnnotationUpdate{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[32] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodeAnnotationUpdate) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeAnnotationUpdate) ProtoMessage() {} + +func (x *NodeAnnotationUpdate) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[32] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodeAnnotationUpdate.ProtoReflect.Descriptor instead. +func (*NodeAnnotationUpdate) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{32} +} + +func (x *NodeAnnotationUpdate) GetSelection() *GraphSelection { + if x != nil { + return x.Selection + } + return nil +} + +func (x *NodeAnnotationUpdate) GetAnnotations() *structpb.Struct { + if x != nil { + return x.Annotations + } + return nil +} + +type NodeFlagChange struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Selection *GraphSelection `protobuf:"bytes,1,opt,name=selection,proto3" json:"selection,omitempty"` + Update *NodeFlagUpdate `protobuf:"bytes,2,opt,name=update,proto3" json:"update,omitempty"` +} + +func (x *NodeFlagChange) Reset() { + *x = NodeFlagChange{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[33] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodeFlagChange) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeFlagChange) ProtoMessage() {} + +func (x *NodeFlagChange) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[33] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodeFlagChange.ProtoReflect.Descriptor instead. +func (*NodeFlagChange) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{33} +} + +func (x *NodeFlagChange) GetSelection() *GraphSelection { + if x != nil { + return x.Selection + } + return nil +} + +func (x *NodeFlagChange) GetUpdate() *NodeFlagUpdate { + if x != nil { + return x.Update + } + return nil +} + +type BfsAlgorithm struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SeedId string `protobuf:"bytes,1,opt,name=seed_id,json=seedId,proto3" json:"seed_id,omitempty"` + Depth uint32 `protobuf:"varint,2,opt,name=depth,proto3" json:"depth,omitempty"` + Direction Direction `protobuf:"varint,3,opt,name=direction,proto3,enum=cstx.Direction" json:"direction,omitempty"` + MaxVisitedNodes *uint64 `protobuf:"varint,4,opt,name=max_visited_nodes,json=maxVisitedNodes,proto3,oneof" json:"max_visited_nodes,omitempty"` + TimeoutMs *uint64 `protobuf:"varint,5,opt,name=timeout_ms,json=timeoutMs,proto3,oneof" json:"timeout_ms,omitempty"` +} + +func (x *BfsAlgorithm) Reset() { + *x = BfsAlgorithm{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[34] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BfsAlgorithm) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BfsAlgorithm) ProtoMessage() {} + +func (x *BfsAlgorithm) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[34] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BfsAlgorithm.ProtoReflect.Descriptor instead. +func (*BfsAlgorithm) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{34} +} + +func (x *BfsAlgorithm) GetSeedId() string { + if x != nil { + return x.SeedId + } + return "" +} + +func (x *BfsAlgorithm) GetDepth() uint32 { + if x != nil { + return x.Depth + } + return 0 +} + +func (x *BfsAlgorithm) GetDirection() Direction { + if x != nil { + return x.Direction + } + return Direction_DIRECTION_UNSPECIFIED +} + +func (x *BfsAlgorithm) GetMaxVisitedNodes() uint64 { + if x != nil && x.MaxVisitedNodes != nil { + return *x.MaxVisitedNodes + } + return 0 +} + +func (x *BfsAlgorithm) GetTimeoutMs() uint64 { + if x != nil && x.TimeoutMs != nil { + return *x.TimeoutMs + } + return 0 +} + +type BetweennessAlgorithm struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IncludeEndpoints bool `protobuf:"varint,1,opt,name=include_endpoints,json=includeEndpoints,proto3" json:"include_endpoints,omitempty"` + Normalized bool `protobuf:"varint,2,opt,name=normalized,proto3" json:"normalized,omitempty"` + TopK *uint64 `protobuf:"varint,3,opt,name=top_k,json=topK,proto3,oneof" json:"top_k,omitempty"` +} + +func (x *BetweennessAlgorithm) Reset() { + *x = BetweennessAlgorithm{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[35] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BetweennessAlgorithm) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BetweennessAlgorithm) ProtoMessage() {} + +func (x *BetweennessAlgorithm) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[35] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BetweennessAlgorithm.ProtoReflect.Descriptor instead. +func (*BetweennessAlgorithm) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{35} +} + +func (x *BetweennessAlgorithm) GetIncludeEndpoints() bool { + if x != nil { + return x.IncludeEndpoints + } + return false +} + +func (x *BetweennessAlgorithm) GetNormalized() bool { + if x != nil { + return x.Normalized + } + return false +} + +func (x *BetweennessAlgorithm) GetTopK() uint64 { + if x != nil && x.TopK != nil { + return *x.TopK + } + return 0 +} + +type ClosenessAlgorithm struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + WfImproved bool `protobuf:"varint,1,opt,name=wf_improved,json=wfImproved,proto3" json:"wf_improved,omitempty"` + TopK *uint64 `protobuf:"varint,2,opt,name=top_k,json=topK,proto3,oneof" json:"top_k,omitempty"` +} + +func (x *ClosenessAlgorithm) Reset() { + *x = ClosenessAlgorithm{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[36] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ClosenessAlgorithm) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClosenessAlgorithm) ProtoMessage() {} + +func (x *ClosenessAlgorithm) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[36] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClosenessAlgorithm.ProtoReflect.Descriptor instead. +func (*ClosenessAlgorithm) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{36} +} + +func (x *ClosenessAlgorithm) GetWfImproved() bool { + if x != nil { + return x.WfImproved + } + return false +} + +func (x *ClosenessAlgorithm) GetTopK() uint64 { + if x != nil && x.TopK != nil { + return *x.TopK + } + return 0 +} + +type LeidenAlgorithm struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Resolution float64 `protobuf:"fixed64,1,opt,name=resolution,proto3" json:"resolution,omitempty"` + MinCommunitySize uint64 `protobuf:"varint,2,opt,name=min_community_size,json=minCommunitySize,proto3" json:"min_community_size,omitempty"` + TopK *uint64 `protobuf:"varint,3,opt,name=top_k,json=topK,proto3,oneof" json:"top_k,omitempty"` +} + +func (x *LeidenAlgorithm) Reset() { + *x = LeidenAlgorithm{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[37] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LeidenAlgorithm) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LeidenAlgorithm) ProtoMessage() {} + +func (x *LeidenAlgorithm) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[37] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LeidenAlgorithm.ProtoReflect.Descriptor instead. +func (*LeidenAlgorithm) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{37} +} + +func (x *LeidenAlgorithm) GetResolution() float64 { + if x != nil { + return x.Resolution + } + return 0 +} + +func (x *LeidenAlgorithm) GetMinCommunitySize() uint64 { + if x != nil { + return x.MinCommunitySize + } + return 0 +} + +func (x *LeidenAlgorithm) GetTopK() uint64 { + if x != nil && x.TopK != nil { + return *x.TopK + } + return 0 +} + +type ShortestPathsAlgorithm struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + StartId string `protobuf:"bytes,1,opt,name=start_id,json=startId,proto3" json:"start_id,omitempty"` + EndId string `protobuf:"bytes,2,opt,name=end_id,json=endId,proto3" json:"end_id,omitempty"` + Direction Direction `protobuf:"varint,3,opt,name=direction,proto3,enum=cstx.Direction" json:"direction,omitempty"` + MaxDepth uint32 `protobuf:"varint,4,opt,name=max_depth,json=maxDepth,proto3" json:"max_depth,omitempty"` + Limit uint64 `protobuf:"varint,5,opt,name=limit,proto3" json:"limit,omitempty"` + MaxVisitedNodes *uint64 `protobuf:"varint,6,opt,name=max_visited_nodes,json=maxVisitedNodes,proto3,oneof" json:"max_visited_nodes,omitempty"` + TimeoutMs *uint64 `protobuf:"varint,7,opt,name=timeout_ms,json=timeoutMs,proto3,oneof" json:"timeout_ms,omitempty"` +} + +func (x *ShortestPathsAlgorithm) Reset() { + *x = ShortestPathsAlgorithm{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[38] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ShortestPathsAlgorithm) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ShortestPathsAlgorithm) ProtoMessage() {} + +func (x *ShortestPathsAlgorithm) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[38] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ShortestPathsAlgorithm.ProtoReflect.Descriptor instead. +func (*ShortestPathsAlgorithm) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{38} +} + +func (x *ShortestPathsAlgorithm) GetStartId() string { + if x != nil { + return x.StartId + } + return "" +} + +func (x *ShortestPathsAlgorithm) GetEndId() string { + if x != nil { + return x.EndId + } + return "" +} + +func (x *ShortestPathsAlgorithm) GetDirection() Direction { + if x != nil { + return x.Direction + } + return Direction_DIRECTION_UNSPECIFIED +} + +func (x *ShortestPathsAlgorithm) GetMaxDepth() uint32 { + if x != nil { + return x.MaxDepth + } + return 0 +} + +func (x *ShortestPathsAlgorithm) GetLimit() uint64 { + if x != nil { + return x.Limit + } + return 0 +} + +func (x *ShortestPathsAlgorithm) GetMaxVisitedNodes() uint64 { + if x != nil && x.MaxVisitedNodes != nil { + return *x.MaxVisitedNodes + } + return 0 +} + +func (x *ShortestPathsAlgorithm) GetTimeoutMs() uint64 { + if x != nil && x.TimeoutMs != nil { + return *x.TimeoutMs + } + return 0 +} + +type Algorithm struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Kind: + // + // *Algorithm_Bfs + // *Algorithm_Parameterless + // *Algorithm_Betweenness + // *Algorithm_Closeness + // *Algorithm_Leiden + // *Algorithm_ShortestPaths + Kind isAlgorithm_Kind `protobuf_oneof:"kind"` +} + +func (x *Algorithm) Reset() { + *x = Algorithm{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[39] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Algorithm) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Algorithm) ProtoMessage() {} + +func (x *Algorithm) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[39] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Algorithm.ProtoReflect.Descriptor instead. +func (*Algorithm) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{39} +} + +func (m *Algorithm) GetKind() isAlgorithm_Kind { + if m != nil { + return m.Kind + } + return nil +} + +func (x *Algorithm) GetBfs() *BfsAlgorithm { + if x, ok := x.GetKind().(*Algorithm_Bfs); ok { + return x.Bfs + } + return nil +} + +func (x *Algorithm) GetParameterless() ParameterlessAlgorithm { + if x, ok := x.GetKind().(*Algorithm_Parameterless); ok { + return x.Parameterless + } + return ParameterlessAlgorithm_PARAMETERLESS_ALGORITHM_UNSPECIFIED +} + +func (x *Algorithm) GetBetweenness() *BetweennessAlgorithm { + if x, ok := x.GetKind().(*Algorithm_Betweenness); ok { + return x.Betweenness + } + return nil +} + +func (x *Algorithm) GetCloseness() *ClosenessAlgorithm { + if x, ok := x.GetKind().(*Algorithm_Closeness); ok { + return x.Closeness + } + return nil +} + +func (x *Algorithm) GetLeiden() *LeidenAlgorithm { + if x, ok := x.GetKind().(*Algorithm_Leiden); ok { + return x.Leiden + } + return nil +} + +func (x *Algorithm) GetShortestPaths() *ShortestPathsAlgorithm { + if x, ok := x.GetKind().(*Algorithm_ShortestPaths); ok { + return x.ShortestPaths + } + return nil +} + +type isAlgorithm_Kind interface { + isAlgorithm_Kind() +} + +type Algorithm_Bfs struct { + Bfs *BfsAlgorithm `protobuf:"bytes,1,opt,name=bfs,proto3,oneof"` +} + +type Algorithm_Parameterless struct { + Parameterless ParameterlessAlgorithm `protobuf:"varint,2,opt,name=parameterless,proto3,enum=cstx.ParameterlessAlgorithm,oneof"` +} + +type Algorithm_Betweenness struct { + Betweenness *BetweennessAlgorithm `protobuf:"bytes,3,opt,name=betweenness,proto3,oneof"` +} + +type Algorithm_Closeness struct { + Closeness *ClosenessAlgorithm `protobuf:"bytes,4,opt,name=closeness,proto3,oneof"` +} + +type Algorithm_Leiden struct { + Leiden *LeidenAlgorithm `protobuf:"bytes,5,opt,name=leiden,proto3,oneof"` +} + +type Algorithm_ShortestPaths struct { + ShortestPaths *ShortestPathsAlgorithm `protobuf:"bytes,6,opt,name=shortest_paths,json=shortestPaths,proto3,oneof"` +} + +func (*Algorithm_Bfs) isAlgorithm_Kind() {} + +func (*Algorithm_Parameterless) isAlgorithm_Kind() {} + +func (*Algorithm_Betweenness) isAlgorithm_Kind() {} + +func (*Algorithm_Closeness) isAlgorithm_Kind() {} + +func (*Algorithm_Leiden) isAlgorithm_Kind() {} + +func (*Algorithm_ShortestPaths) isAlgorithm_Kind() {} + +type NodePage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Values []*Node `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"` +} + +func (x *NodePage) Reset() { + *x = NodePage{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[40] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodePage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodePage) ProtoMessage() {} + +func (x *NodePage) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[40] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodePage.ProtoReflect.Descriptor instead. +func (*NodePage) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{40} +} + +func (x *NodePage) GetValues() []*Node { + if x != nil { + return x.Values + } + return nil +} + +type RelationshipPage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Values []*Relationship `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"` +} + +func (x *RelationshipPage) Reset() { + *x = RelationshipPage{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[41] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RelationshipPage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RelationshipPage) ProtoMessage() {} + +func (x *RelationshipPage) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[41] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RelationshipPage.ProtoReflect.Descriptor instead. +func (*RelationshipPage) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{41} +} + +func (x *RelationshipPage) GetValues() []*Relationship { + if x != nil { + return x.Values + } + return nil +} + +type ComponentMembership struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` + ComponentId uint64 `protobuf:"varint,2,opt,name=component_id,json=componentId,proto3" json:"component_id,omitempty"` +} + +func (x *ComponentMembership) Reset() { + *x = ComponentMembership{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[42] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ComponentMembership) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ComponentMembership) ProtoMessage() {} + +func (x *ComponentMembership) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[42] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ComponentMembership.ProtoReflect.Descriptor instead. +func (*ComponentMembership) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{42} +} + +func (x *ComponentMembership) GetNodeId() string { + if x != nil { + return x.NodeId + } + return "" +} + +func (x *ComponentMembership) GetComponentId() uint64 { + if x != nil { + return x.ComponentId + } + return 0 +} + +type ComponentMembershipPage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Values []*ComponentMembership `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"` +} + +func (x *ComponentMembershipPage) Reset() { + *x = ComponentMembershipPage{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[43] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ComponentMembershipPage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ComponentMembershipPage) ProtoMessage() {} + +func (x *ComponentMembershipPage) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[43] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ComponentMembershipPage.ProtoReflect.Descriptor instead. +func (*ComponentMembershipPage) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{43} +} + +func (x *ComponentMembershipPage) GetValues() []*ComponentMembership { + if x != nil { + return x.Values + } + return nil +} + +type NodeScore struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` + Metric string `protobuf:"bytes,2,opt,name=metric,proto3" json:"metric,omitempty"` + Score float64 `protobuf:"fixed64,3,opt,name=score,proto3" json:"score,omitempty"` +} + +func (x *NodeScore) Reset() { + *x = NodeScore{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[44] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodeScore) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeScore) ProtoMessage() {} + +func (x *NodeScore) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[44] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodeScore.ProtoReflect.Descriptor instead. +func (*NodeScore) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{44} +} + +func (x *NodeScore) GetNodeId() string { + if x != nil { + return x.NodeId + } + return "" +} + +func (x *NodeScore) GetMetric() string { + if x != nil { + return x.Metric + } + return "" +} + +func (x *NodeScore) GetScore() float64 { + if x != nil { + return x.Score + } + return 0 +} + +type NodeScorePage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Values []*NodeScore `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"` +} + +func (x *NodeScorePage) Reset() { + *x = NodeScorePage{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[45] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodeScorePage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeScorePage) ProtoMessage() {} + +func (x *NodeScorePage) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[45] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodeScorePage.ProtoReflect.Descriptor instead. +func (*NodeScorePage) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{45} +} + +func (x *NodeScorePage) GetValues() []*NodeScore { + if x != nil { + return x.Values + } + return nil +} + +type NodePair struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SourceId string `protobuf:"bytes,1,opt,name=source_id,json=sourceId,proto3" json:"source_id,omitempty"` + TargetId string `protobuf:"bytes,2,opt,name=target_id,json=targetId,proto3" json:"target_id,omitempty"` +} + +func (x *NodePair) Reset() { + *x = NodePair{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[46] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodePair) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodePair) ProtoMessage() {} + +func (x *NodePair) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[46] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodePair.ProtoReflect.Descriptor instead. +func (*NodePair) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{46} +} + +func (x *NodePair) GetSourceId() string { + if x != nil { + return x.SourceId + } + return "" +} + +func (x *NodePair) GetTargetId() string { + if x != nil { + return x.TargetId + } + return "" +} + +type NodePairPage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Values []*NodePair `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"` +} + +func (x *NodePairPage) Reset() { + *x = NodePairPage{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[47] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodePairPage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodePairPage) ProtoMessage() {} + +func (x *NodePairPage) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[47] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodePairPage.ProtoReflect.Descriptor instead. +func (*NodePairPage) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{47} +} + +func (x *NodePairPage) GetValues() []*NodePair { + if x != nil { + return x.Values + } + return nil +} + +type NodeCycle struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodeIds []string `protobuf:"bytes,1,rep,name=node_ids,json=nodeIds,proto3" json:"node_ids,omitempty"` +} + +func (x *NodeCycle) Reset() { + *x = NodeCycle{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[48] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodeCycle) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeCycle) ProtoMessage() {} + +func (x *NodeCycle) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[48] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodeCycle.ProtoReflect.Descriptor instead. +func (*NodeCycle) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{48} +} + +func (x *NodeCycle) GetNodeIds() []string { + if x != nil { + return x.NodeIds + } + return nil +} + +type CyclePage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Values []*NodeCycle `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"` +} + +func (x *CyclePage) Reset() { + *x = CyclePage{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[49] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CyclePage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CyclePage) ProtoMessage() {} + +func (x *CyclePage) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[49] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CyclePage.ProtoReflect.Descriptor instead. +func (*CyclePage) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{49} +} + +func (x *CyclePage) GetValues() []*NodeCycle { + if x != nil { + return x.Values + } + return nil +} + +type NodePath struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodeIds []string `protobuf:"bytes,1,rep,name=node_ids,json=nodeIds,proto3" json:"node_ids,omitempty"` +} + +func (x *NodePath) Reset() { + *x = NodePath{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[50] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodePath) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodePath) ProtoMessage() {} + +func (x *NodePath) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[50] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodePath.ProtoReflect.Descriptor instead. +func (*NodePath) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{50} +} + +func (x *NodePath) GetNodeIds() []string { + if x != nil { + return x.NodeIds + } + return nil +} + +type PathPage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Values []*NodePath `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"` +} + +func (x *PathPage) Reset() { + *x = PathPage{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[51] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PathPage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PathPage) ProtoMessage() {} + +func (x *PathPage) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[51] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PathPage.ProtoReflect.Descriptor instead. +func (*PathPage) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{51} +} + +func (x *PathPage) GetValues() []*NodePath { + if x != nil { + return x.Values + } + return nil +} + +type CommunityMembership struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` + CommunityId uint64 `protobuf:"varint,2,opt,name=community_id,json=communityId,proto3" json:"community_id,omitempty"` +} + +func (x *CommunityMembership) Reset() { + *x = CommunityMembership{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[52] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CommunityMembership) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CommunityMembership) ProtoMessage() {} + +func (x *CommunityMembership) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[52] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CommunityMembership.ProtoReflect.Descriptor instead. +func (*CommunityMembership) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{52} +} + +func (x *CommunityMembership) GetNodeId() string { + if x != nil { + return x.NodeId + } + return "" +} + +func (x *CommunityMembership) GetCommunityId() uint64 { + if x != nil { + return x.CommunityId + } + return 0 +} + +type CommunityMembershipPage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Values []*CommunityMembership `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"` +} + +func (x *CommunityMembershipPage) Reset() { + *x = CommunityMembershipPage{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[53] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CommunityMembershipPage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CommunityMembershipPage) ProtoMessage() {} + +func (x *CommunityMembershipPage) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[53] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CommunityMembershipPage.ProtoReflect.Descriptor instead. +func (*CommunityMembershipPage) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{53} +} + +func (x *CommunityMembershipPage) GetValues() []*CommunityMembership { + if x != nil { + return x.Values + } + return nil +} + +type QuerySummary struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodesByType map[string]uint64 `protobuf:"bytes,1,rep,name=nodes_by_type,json=nodesByType,proto3" json:"nodes_by_type,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` +} + +func (x *QuerySummary) Reset() { + *x = QuerySummary{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[54] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QuerySummary) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QuerySummary) ProtoMessage() {} + +func (x *QuerySummary) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[54] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use QuerySummary.ProtoReflect.Descriptor instead. +func (*QuerySummary) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{54} +} + +func (x *QuerySummary) GetNodesByType() map[string]uint64 { + if x != nil { + return x.NodesByType + } + return nil +} + +type TraversalSummary struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Algorithm string `protobuf:"bytes,1,opt,name=algorithm,proto3" json:"algorithm,omitempty"` + Direction Direction `protobuf:"varint,2,opt,name=direction,proto3,enum=cstx.Direction" json:"direction,omitempty"` + Truncated bool `protobuf:"varint,3,opt,name=truncated,proto3" json:"truncated,omitempty"` + Projection string `protobuf:"bytes,4,opt,name=projection,proto3" json:"projection,omitempty"` +} + +func (x *TraversalSummary) Reset() { + *x = TraversalSummary{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[55] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TraversalSummary) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TraversalSummary) ProtoMessage() {} + +func (x *TraversalSummary) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[55] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TraversalSummary.ProtoReflect.Descriptor instead. +func (*TraversalSummary) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{55} +} + +func (x *TraversalSummary) GetAlgorithm() string { + if x != nil { + return x.Algorithm + } + return "" +} + +func (x *TraversalSummary) GetDirection() Direction { + if x != nil { + return x.Direction + } + return Direction_DIRECTION_UNSPECIFIED +} + +func (x *TraversalSummary) GetTruncated() bool { + if x != nil { + return x.Truncated + } + return false +} + +func (x *TraversalSummary) GetProjection() string { + if x != nil { + return x.Projection + } + return "" +} + +type ComponentSummary struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Algorithm string `protobuf:"bytes,1,opt,name=algorithm,proto3" json:"algorithm,omitempty"` + ComponentCount uint64 `protobuf:"varint,2,opt,name=component_count,json=componentCount,proto3" json:"component_count,omitempty"` + Projection string `protobuf:"bytes,3,opt,name=projection,proto3" json:"projection,omitempty"` +} + +func (x *ComponentSummary) Reset() { + *x = ComponentSummary{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[56] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ComponentSummary) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ComponentSummary) ProtoMessage() {} + +func (x *ComponentSummary) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[56] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ComponentSummary.ProtoReflect.Descriptor instead. +func (*ComponentSummary) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{56} +} + +func (x *ComponentSummary) GetAlgorithm() string { + if x != nil { + return x.Algorithm + } + return "" +} + +func (x *ComponentSummary) GetComponentCount() uint64 { + if x != nil { + return x.ComponentCount + } + return 0 +} + +func (x *ComponentSummary) GetProjection() string { + if x != nil { + return x.Projection + } + return "" +} + +type ScoreSummary struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Metric string `protobuf:"bytes,1,opt,name=metric,proto3" json:"metric,omitempty"` + IncludeEndpoints bool `protobuf:"varint,2,opt,name=include_endpoints,json=includeEndpoints,proto3" json:"include_endpoints,omitempty"` + Normalized bool `protobuf:"varint,3,opt,name=normalized,proto3" json:"normalized,omitempty"` + WfImproved bool `protobuf:"varint,4,opt,name=wf_improved,json=wfImproved,proto3" json:"wf_improved,omitempty"` + TopK *uint64 `protobuf:"varint,5,opt,name=top_k,json=topK,proto3,oneof" json:"top_k,omitempty"` + Projection string `protobuf:"bytes,6,opt,name=projection,proto3" json:"projection,omitempty"` +} + +func (x *ScoreSummary) Reset() { + *x = ScoreSummary{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[57] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ScoreSummary) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ScoreSummary) ProtoMessage() {} + +func (x *ScoreSummary) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[57] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ScoreSummary.ProtoReflect.Descriptor instead. +func (*ScoreSummary) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{57} +} + +func (x *ScoreSummary) GetMetric() string { + if x != nil { + return x.Metric + } + return "" +} + +func (x *ScoreSummary) GetIncludeEndpoints() bool { + if x != nil { + return x.IncludeEndpoints + } + return false +} + +func (x *ScoreSummary) GetNormalized() bool { + if x != nil { + return x.Normalized + } + return false +} + +func (x *ScoreSummary) GetWfImproved() bool { + if x != nil { + return x.WfImproved + } + return false +} + +func (x *ScoreSummary) GetTopK() uint64 { + if x != nil && x.TopK != nil { + return *x.TopK + } + return 0 +} + +func (x *ScoreSummary) GetProjection() string { + if x != nil { + return x.Projection + } + return "" +} + +type CommunitySummary struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NumCommunities uint64 `protobuf:"varint,1,opt,name=num_communities,json=numCommunities,proto3" json:"num_communities,omitempty"` + TotalCommunities uint64 `protobuf:"varint,2,opt,name=total_communities,json=totalCommunities,proto3" json:"total_communities,omitempty"` + CommunitiesTruncated bool `protobuf:"varint,3,opt,name=communities_truncated,json=communitiesTruncated,proto3" json:"communities_truncated,omitempty"` + Modularity float64 `protobuf:"fixed64,4,opt,name=modularity,proto3" json:"modularity,omitempty"` + Resolution float64 `protobuf:"fixed64,5,opt,name=resolution,proto3" json:"resolution,omitempty"` + MinCommunitySize uint64 `protobuf:"varint,6,opt,name=min_community_size,json=minCommunitySize,proto3" json:"min_community_size,omitempty"` + TopK *uint64 `protobuf:"varint,7,opt,name=top_k,json=topK,proto3,oneof" json:"top_k,omitempty"` + CommunitySizes map[uint64]uint64 `protobuf:"bytes,8,rep,name=community_sizes,json=communitySizes,proto3" json:"community_sizes,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` + Projection string `protobuf:"bytes,9,opt,name=projection,proto3" json:"projection,omitempty"` + Algorithm string `protobuf:"bytes,10,opt,name=algorithm,proto3" json:"algorithm,omitempty"` +} + +func (x *CommunitySummary) Reset() { + *x = CommunitySummary{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[58] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CommunitySummary) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CommunitySummary) ProtoMessage() {} + +func (x *CommunitySummary) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[58] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CommunitySummary.ProtoReflect.Descriptor instead. +func (*CommunitySummary) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{58} +} + +func (x *CommunitySummary) GetNumCommunities() uint64 { + if x != nil { + return x.NumCommunities + } + return 0 +} + +func (x *CommunitySummary) GetTotalCommunities() uint64 { + if x != nil { + return x.TotalCommunities + } + return 0 +} + +func (x *CommunitySummary) GetCommunitiesTruncated() bool { + if x != nil { + return x.CommunitiesTruncated + } + return false +} + +func (x *CommunitySummary) GetModularity() float64 { + if x != nil { + return x.Modularity + } + return 0 +} + +func (x *CommunitySummary) GetResolution() float64 { + if x != nil { + return x.Resolution + } + return 0 +} + +func (x *CommunitySummary) GetMinCommunitySize() uint64 { + if x != nil { + return x.MinCommunitySize + } + return 0 +} + +func (x *CommunitySummary) GetTopK() uint64 { + if x != nil && x.TopK != nil { + return *x.TopK + } + return 0 +} + +func (x *CommunitySummary) GetCommunitySizes() map[uint64]uint64 { + if x != nil { + return x.CommunitySizes + } + return nil +} + +func (x *CommunitySummary) GetProjection() string { + if x != nil { + return x.Projection + } + return "" +} + +func (x *CommunitySummary) GetAlgorithm() string { + if x != nil { + return x.Algorithm + } + return "" +} + +type PathSummary struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Algorithm string `protobuf:"bytes,1,opt,name=algorithm,proto3" json:"algorithm,omitempty"` + StartId string `protobuf:"bytes,2,opt,name=start_id,json=startId,proto3" json:"start_id,omitempty"` + EndId string `protobuf:"bytes,3,opt,name=end_id,json=endId,proto3" json:"end_id,omitempty"` + Direction Direction `protobuf:"varint,4,opt,name=direction,proto3,enum=cstx.Direction" json:"direction,omitempty"` + MaxDepth uint32 `protobuf:"varint,5,opt,name=max_depth,json=maxDepth,proto3" json:"max_depth,omitempty"` + Limit uint64 `protobuf:"varint,6,opt,name=limit,proto3" json:"limit,omitempty"` +} + +func (x *PathSummary) Reset() { + *x = PathSummary{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[59] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PathSummary) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PathSummary) ProtoMessage() {} + +func (x *PathSummary) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[59] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PathSummary.ProtoReflect.Descriptor instead. +func (*PathSummary) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{59} +} + +func (x *PathSummary) GetAlgorithm() string { + if x != nil { + return x.Algorithm + } + return "" +} + +func (x *PathSummary) GetStartId() string { + if x != nil { + return x.StartId + } + return "" +} + +func (x *PathSummary) GetEndId() string { + if x != nil { + return x.EndId + } + return "" +} + +func (x *PathSummary) GetDirection() Direction { + if x != nil { + return x.Direction + } + return Direction_DIRECTION_UNSPECIFIED +} + +func (x *PathSummary) GetMaxDepth() uint32 { + if x != nil { + return x.MaxDepth + } + return 0 +} + +func (x *PathSummary) GetLimit() uint64 { + if x != nil { + return x.Limit + } + return 0 +} + +type GraphResultPage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Page uint64 `protobuf:"varint,1,opt,name=page,proto3" json:"page,omitempty"` + Limit uint64 `protobuf:"varint,2,opt,name=limit,proto3" json:"limit,omitempty"` + HasNext bool `protobuf:"varint,3,opt,name=has_next,json=hasNext,proto3" json:"has_next,omitempty"` + Total *uint64 `protobuf:"varint,4,opt,name=total,proto3,oneof" json:"total,omitempty"` + // Types that are assignable to Result: + // + // *GraphResultPage_Nodes + // *GraphResultPage_Relationships + // *GraphResultPage_Components + // *GraphResultPage_Scores + // *GraphResultPage_Pairs + // *GraphResultPage_Cycles + // *GraphResultPage_Paths + // *GraphResultPage_Communities + Result isGraphResultPage_Result `protobuf_oneof:"result"` + // Types that are assignable to Summary: + // + // *GraphResultPage_Query + // *GraphResultPage_Traversal + // *GraphResultPage_Component + // *GraphResultPage_Score + // *GraphResultPage_Community + // *GraphResultPage_Path + Summary isGraphResultPage_Summary `protobuf_oneof:"summary"` +} + +func (x *GraphResultPage) Reset() { + *x = GraphResultPage{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[60] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GraphResultPage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GraphResultPage) ProtoMessage() {} + +func (x *GraphResultPage) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[60] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GraphResultPage.ProtoReflect.Descriptor instead. +func (*GraphResultPage) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{60} +} + +func (x *GraphResultPage) GetPage() uint64 { + if x != nil { + return x.Page + } + return 0 +} + +func (x *GraphResultPage) GetLimit() uint64 { + if x != nil { + return x.Limit + } + return 0 +} + +func (x *GraphResultPage) GetHasNext() bool { + if x != nil { + return x.HasNext + } + return false +} + +func (x *GraphResultPage) GetTotal() uint64 { + if x != nil && x.Total != nil { + return *x.Total + } + return 0 +} + +func (m *GraphResultPage) GetResult() isGraphResultPage_Result { + if m != nil { + return m.Result + } + return nil +} + +func (x *GraphResultPage) GetNodes() *NodePage { + if x, ok := x.GetResult().(*GraphResultPage_Nodes); ok { + return x.Nodes + } + return nil +} + +func (x *GraphResultPage) GetRelationships() *RelationshipPage { + if x, ok := x.GetResult().(*GraphResultPage_Relationships); ok { + return x.Relationships + } + return nil +} + +func (x *GraphResultPage) GetComponents() *ComponentMembershipPage { + if x, ok := x.GetResult().(*GraphResultPage_Components); ok { + return x.Components + } + return nil +} + +func (x *GraphResultPage) GetScores() *NodeScorePage { + if x, ok := x.GetResult().(*GraphResultPage_Scores); ok { + return x.Scores + } + return nil +} + +func (x *GraphResultPage) GetPairs() *NodePairPage { + if x, ok := x.GetResult().(*GraphResultPage_Pairs); ok { + return x.Pairs + } + return nil +} + +func (x *GraphResultPage) GetCycles() *CyclePage { + if x, ok := x.GetResult().(*GraphResultPage_Cycles); ok { + return x.Cycles + } + return nil +} + +func (x *GraphResultPage) GetPaths() *PathPage { + if x, ok := x.GetResult().(*GraphResultPage_Paths); ok { + return x.Paths + } + return nil +} + +func (x *GraphResultPage) GetCommunities() *CommunityMembershipPage { + if x, ok := x.GetResult().(*GraphResultPage_Communities); ok { + return x.Communities + } + return nil +} + +func (m *GraphResultPage) GetSummary() isGraphResultPage_Summary { + if m != nil { + return m.Summary + } + return nil +} + +func (x *GraphResultPage) GetQuery() *QuerySummary { + if x, ok := x.GetSummary().(*GraphResultPage_Query); ok { + return x.Query + } + return nil +} + +func (x *GraphResultPage) GetTraversal() *TraversalSummary { + if x, ok := x.GetSummary().(*GraphResultPage_Traversal); ok { + return x.Traversal + } + return nil +} + +func (x *GraphResultPage) GetComponent() *ComponentSummary { + if x, ok := x.GetSummary().(*GraphResultPage_Component); ok { + return x.Component + } + return nil +} + +func (x *GraphResultPage) GetScore() *ScoreSummary { + if x, ok := x.GetSummary().(*GraphResultPage_Score); ok { + return x.Score + } + return nil +} + +func (x *GraphResultPage) GetCommunity() *CommunitySummary { + if x, ok := x.GetSummary().(*GraphResultPage_Community); ok { + return x.Community + } + return nil +} + +func (x *GraphResultPage) GetPath() *PathSummary { + if x, ok := x.GetSummary().(*GraphResultPage_Path); ok { + return x.Path + } + return nil +} + +type isGraphResultPage_Result interface { + isGraphResultPage_Result() +} + +type GraphResultPage_Nodes struct { + Nodes *NodePage `protobuf:"bytes,5,opt,name=nodes,proto3,oneof"` +} + +type GraphResultPage_Relationships struct { + Relationships *RelationshipPage `protobuf:"bytes,6,opt,name=relationships,proto3,oneof"` +} + +type GraphResultPage_Components struct { + Components *ComponentMembershipPage `protobuf:"bytes,7,opt,name=components,proto3,oneof"` +} + +type GraphResultPage_Scores struct { + Scores *NodeScorePage `protobuf:"bytes,8,opt,name=scores,proto3,oneof"` +} + +type GraphResultPage_Pairs struct { + Pairs *NodePairPage `protobuf:"bytes,9,opt,name=pairs,proto3,oneof"` +} + +type GraphResultPage_Cycles struct { + Cycles *CyclePage `protobuf:"bytes,10,opt,name=cycles,proto3,oneof"` +} + +type GraphResultPage_Paths struct { + Paths *PathPage `protobuf:"bytes,11,opt,name=paths,proto3,oneof"` +} + +type GraphResultPage_Communities struct { + Communities *CommunityMembershipPage `protobuf:"bytes,12,opt,name=communities,proto3,oneof"` +} + +func (*GraphResultPage_Nodes) isGraphResultPage_Result() {} + +func (*GraphResultPage_Relationships) isGraphResultPage_Result() {} + +func (*GraphResultPage_Components) isGraphResultPage_Result() {} + +func (*GraphResultPage_Scores) isGraphResultPage_Result() {} + +func (*GraphResultPage_Pairs) isGraphResultPage_Result() {} + +func (*GraphResultPage_Cycles) isGraphResultPage_Result() {} + +func (*GraphResultPage_Paths) isGraphResultPage_Result() {} + +func (*GraphResultPage_Communities) isGraphResultPage_Result() {} + +type isGraphResultPage_Summary interface { + isGraphResultPage_Summary() +} + +type GraphResultPage_Query struct { + Query *QuerySummary `protobuf:"bytes,13,opt,name=query,proto3,oneof"` +} + +type GraphResultPage_Traversal struct { + Traversal *TraversalSummary `protobuf:"bytes,14,opt,name=traversal,proto3,oneof"` +} + +type GraphResultPage_Component struct { + Component *ComponentSummary `protobuf:"bytes,15,opt,name=component,proto3,oneof"` +} + +type GraphResultPage_Score struct { + Score *ScoreSummary `protobuf:"bytes,16,opt,name=score,proto3,oneof"` +} + +type GraphResultPage_Community struct { + Community *CommunitySummary `protobuf:"bytes,17,opt,name=community,proto3,oneof"` +} + +type GraphResultPage_Path struct { + Path *PathSummary `protobuf:"bytes,18,opt,name=path,proto3,oneof"` +} + +func (*GraphResultPage_Query) isGraphResultPage_Summary() {} + +func (*GraphResultPage_Traversal) isGraphResultPage_Summary() {} + +func (*GraphResultPage_Component) isGraphResultPage_Summary() {} + +func (*GraphResultPage_Score) isGraphResultPage_Summary() {} + +func (*GraphResultPage_Community) isGraphResultPage_Summary() {} + +func (*GraphResultPage_Path) isGraphResultPage_Summary() {} + +type ParserPayload struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Plugin string `protobuf:"bytes,1,opt,name=plugin,proto3" json:"plugin,omitempty"` + Artifact string `protobuf:"bytes,2,opt,name=artifact,proto3" json:"artifact,omitempty"` + Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` + ContentType string `protobuf:"bytes,4,opt,name=content_type,json=contentType,proto3" json:"content_type,omitempty"` +} + +func (x *ParserPayload) Reset() { + *x = ParserPayload{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[61] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ParserPayload) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ParserPayload) ProtoMessage() {} + +func (x *ParserPayload) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[61] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ParserPayload.ProtoReflect.Descriptor instead. +func (*ParserPayload) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{61} +} + +func (x *ParserPayload) GetPlugin() string { + if x != nil { + return x.Plugin + } + return "" +} + +func (x *ParserPayload) GetArtifact() string { + if x != nil { + return x.Artifact + } + return "" +} + +func (x *ParserPayload) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +func (x *ParserPayload) GetContentType() string { + if x != nil { + return x.ContentType + } + return "" +} + +// Result of one native parser invocation. The raw parser input may be +// JSONL, but its transport and result are always semantic protobuf messages. +type GraphIngestResult struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RecordsParsed uint64 `protobuf:"varint,1,opt,name=records_parsed,json=recordsParsed,proto3" json:"records_parsed,omitempty"` + NewNodes uint64 `protobuf:"varint,2,opt,name=new_nodes,json=newNodes,proto3" json:"new_nodes,omitempty"` + UpdatedNodes uint64 `protobuf:"varint,3,opt,name=updated_nodes,json=updatedNodes,proto3" json:"updated_nodes,omitempty"` + NewRelationships uint64 `protobuf:"varint,4,opt,name=new_relationships,json=newRelationships,proto3" json:"new_relationships,omitempty"` + NodeIds []string `protobuf:"bytes,5,rep,name=node_ids,json=nodeIds,proto3" json:"node_ids,omitempty"` + NodeCount uint64 `protobuf:"varint,6,opt,name=node_count,json=nodeCount,proto3" json:"node_count,omitempty"` + RelationshipCount uint64 `protobuf:"varint,7,opt,name=relationship_count,json=relationshipCount,proto3" json:"relationship_count,omitempty"` + NodesByType map[string]uint64 `protobuf:"bytes,8,rep,name=nodes_by_type,json=nodesByType,proto3" json:"nodes_by_type,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` +} + +func (x *GraphIngestResult) Reset() { + *x = GraphIngestResult{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[62] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GraphIngestResult) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GraphIngestResult) ProtoMessage() {} + +func (x *GraphIngestResult) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[62] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GraphIngestResult.ProtoReflect.Descriptor instead. +func (*GraphIngestResult) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{62} +} + +func (x *GraphIngestResult) GetRecordsParsed() uint64 { + if x != nil { + return x.RecordsParsed + } + return 0 +} + +func (x *GraphIngestResult) GetNewNodes() uint64 { + if x != nil { + return x.NewNodes + } + return 0 +} + +func (x *GraphIngestResult) GetUpdatedNodes() uint64 { + if x != nil { + return x.UpdatedNodes + } + return 0 +} + +func (x *GraphIngestResult) GetNewRelationships() uint64 { + if x != nil { + return x.NewRelationships + } + return 0 +} + +func (x *GraphIngestResult) GetNodeIds() []string { + if x != nil { + return x.NodeIds + } + return nil +} + +func (x *GraphIngestResult) GetNodeCount() uint64 { + if x != nil { + return x.NodeCount + } + return 0 +} + +func (x *GraphIngestResult) GetRelationshipCount() uint64 { + if x != nil { + return x.RelationshipCount + } + return 0 +} + +func (x *GraphIngestResult) GetNodesByType() map[string]uint64 { + if x != nil { + return x.NodesByType + } + return nil +} + +// Result of running registered linker rules for an explicit node selection. +type GraphLinkResult struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NewNodes uint64 `protobuf:"varint,1,opt,name=new_nodes,json=newNodes,proto3" json:"new_nodes,omitempty"` + UpdatedNodes uint64 `protobuf:"varint,2,opt,name=updated_nodes,json=updatedNodes,proto3" json:"updated_nodes,omitempty"` + NewRelationships uint64 `protobuf:"varint,3,opt,name=new_relationships,json=newRelationships,proto3" json:"new_relationships,omitempty"` + RelationshipIds []string `protobuf:"bytes,4,rep,name=relationship_ids,json=relationshipIds,proto3" json:"relationship_ids,omitempty"` +} + +func (x *GraphLinkResult) Reset() { + *x = GraphLinkResult{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[63] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GraphLinkResult) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GraphLinkResult) ProtoMessage() {} + +func (x *GraphLinkResult) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[63] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GraphLinkResult.ProtoReflect.Descriptor instead. +func (*GraphLinkResult) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{63} +} + +func (x *GraphLinkResult) GetNewNodes() uint64 { + if x != nil { + return x.NewNodes + } + return 0 +} + +func (x *GraphLinkResult) GetUpdatedNodes() uint64 { + if x != nil { + return x.UpdatedNodes + } + return 0 +} + +func (x *GraphLinkResult) GetNewRelationships() uint64 { + if x != nil { + return x.NewRelationships + } + return 0 +} + +func (x *GraphLinkResult) GetRelationshipIds() []string { + if x != nil { + return x.RelationshipIds + } + return nil +} + +type GraphAnchor struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Concept string `protobuf:"bytes,1,opt,name=concept,proto3" json:"concept,omitempty"` + AnchorId string `protobuf:"bytes,2,opt,name=anchor_id,json=anchorId,proto3" json:"anchor_id,omitempty"` + AnchorType string `protobuf:"bytes,3,opt,name=anchor_type,json=anchorType,proto3" json:"anchor_type,omitempty"` + SourceId string `protobuf:"bytes,4,opt,name=source_id,json=sourceId,proto3" json:"source_id,omitempty"` + TargetId string `protobuf:"bytes,5,opt,name=target_id,json=targetId,proto3" json:"target_id,omitempty"` + InboundRelationshipId string `protobuf:"bytes,6,opt,name=inbound_relationship_id,json=inboundRelationshipId,proto3" json:"inbound_relationship_id,omitempty"` + OutboundRelationshipId string `protobuf:"bytes,7,opt,name=outbound_relationship_id,json=outboundRelationshipId,proto3" json:"outbound_relationship_id,omitempty"` +} + +func (x *GraphAnchor) Reset() { + *x = GraphAnchor{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[64] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GraphAnchor) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GraphAnchor) ProtoMessage() {} + +func (x *GraphAnchor) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[64] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GraphAnchor.ProtoReflect.Descriptor instead. +func (*GraphAnchor) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{64} +} + +func (x *GraphAnchor) GetConcept() string { + if x != nil { + return x.Concept + } + return "" +} + +func (x *GraphAnchor) GetAnchorId() string { + if x != nil { + return x.AnchorId + } + return "" +} + +func (x *GraphAnchor) GetAnchorType() string { + if x != nil { + return x.AnchorType + } + return "" +} + +func (x *GraphAnchor) GetSourceId() string { + if x != nil { + return x.SourceId + } + return "" +} + +func (x *GraphAnchor) GetTargetId() string { + if x != nil { + return x.TargetId + } + return "" +} + +func (x *GraphAnchor) GetInboundRelationshipId() string { + if x != nil { + return x.InboundRelationshipId + } + return "" +} + +func (x *GraphAnchor) GetOutboundRelationshipId() string { + if x != nil { + return x.OutboundRelationshipId + } + return "" +} + +type GraphAnchorCatalog struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Anchors []*GraphAnchor `protobuf:"bytes,1,rep,name=anchors,proto3" json:"anchors,omitempty"` +} + +func (x *GraphAnchorCatalog) Reset() { + *x = GraphAnchorCatalog{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[65] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GraphAnchorCatalog) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GraphAnchorCatalog) ProtoMessage() {} + +func (x *GraphAnchorCatalog) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[65] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GraphAnchorCatalog.ProtoReflect.Descriptor instead. +func (*GraphAnchorCatalog) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{65} +} + +func (x *GraphAnchorCatalog) GetAnchors() []*GraphAnchor { + if x != nil { + return x.Anchors + } + return nil +} + +type NodeFlagUpdate struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Mode NodeFlagUpdateMode `protobuf:"varint,1,opt,name=mode,proto3,enum=cstx.NodeFlagUpdateMode" json:"mode,omitempty"` + AddMask uint64 `protobuf:"varint,5,opt,name=add_mask,json=addMask,proto3" json:"add_mask,omitempty"` + RemoveMask uint64 `protobuf:"varint,6,opt,name=remove_mask,json=removeMask,proto3" json:"remove_mask,omitempty"` + // Read only when `mode` is `NODE_FLAG_UPDATE_REPLACE`. + ReplaceMask uint64 `protobuf:"varint,7,opt,name=replace_mask,json=replaceMask,proto3" json:"replace_mask,omitempty"` +} + +func (x *NodeFlagUpdate) Reset() { + *x = NodeFlagUpdate{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[66] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodeFlagUpdate) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeFlagUpdate) ProtoMessage() {} + +func (x *NodeFlagUpdate) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[66] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodeFlagUpdate.ProtoReflect.Descriptor instead. +func (*NodeFlagUpdate) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{66} +} + +func (x *NodeFlagUpdate) GetMode() NodeFlagUpdateMode { + if x != nil { + return x.Mode + } + return NodeFlagUpdateMode_NODE_FLAG_UPDATE_UNSPECIFIED +} + +func (x *NodeFlagUpdate) GetAddMask() uint64 { + if x != nil { + return x.AddMask + } + return 0 +} + +func (x *NodeFlagUpdate) GetRemoveMask() uint64 { + if x != nil { + return x.RemoveMask + } + return 0 +} + +func (x *NodeFlagUpdate) GetReplaceMask() uint64 { + if x != nil { + return x.ReplaceMask + } + return 0 +} + +type GraphProjectionReport struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ExcludedNodes []*GraphProjectionReport_NodeExclusion `protobuf:"bytes,1,rep,name=excluded_nodes,json=excludedNodes,proto3" json:"excluded_nodes,omitempty"` + Reused bool `protobuf:"varint,2,opt,name=reused,proto3" json:"reused,omitempty"` +} + +func (x *GraphProjectionReport) Reset() { + *x = GraphProjectionReport{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[67] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GraphProjectionReport) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GraphProjectionReport) ProtoMessage() {} + +func (x *GraphProjectionReport) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[67] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GraphProjectionReport.ProtoReflect.Descriptor instead. +func (*GraphProjectionReport) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{67} +} + +func (x *GraphProjectionReport) GetExcludedNodes() []*GraphProjectionReport_NodeExclusion { + if x != nil { + return x.ExcludedNodes + } + return nil +} + +func (x *GraphProjectionReport) GetReused() bool { + if x != nil { + return x.Reused + } + return false +} + +type RepositoryObject struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Kind RepositoryObjectKind `protobuf:"varint,2,opt,name=kind,proto3,enum=cstx.RepositoryObjectKind" json:"kind,omitempty"` + Payload []byte `protobuf:"bytes,3,opt,name=payload,proto3" json:"payload,omitempty"` +} + +func (x *RepositoryObject) Reset() { + *x = RepositoryObject{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[68] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RepositoryObject) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RepositoryObject) ProtoMessage() {} + +func (x *RepositoryObject) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[68] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RepositoryObject.ProtoReflect.Descriptor instead. +func (*RepositoryObject) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{68} +} + +func (x *RepositoryObject) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *RepositoryObject) GetKind() RepositoryObjectKind { + if x != nil { + return x.Kind + } + return RepositoryObjectKind_REPOSITORY_OBJECT_KIND_UNSPECIFIED +} + +func (x *RepositoryObject) GetPayload() []byte { + if x != nil { + return x.Payload + } + return nil +} + +type PublicationPlan struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Commit *Commit `protobuf:"bytes,1,opt,name=commit,proto3" json:"commit,omitempty"` + IndexRoot string `protobuf:"bytes,2,opt,name=index_root,json=indexRoot,proto3" json:"index_root,omitempty"` + Objects []*RepositoryObject `protobuf:"bytes,3,rep,name=objects,proto3" json:"objects,omitempty"` +} + +func (x *PublicationPlan) Reset() { + *x = PublicationPlan{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[69] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PublicationPlan) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PublicationPlan) ProtoMessage() {} + +func (x *PublicationPlan) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[69] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PublicationPlan.ProtoReflect.Descriptor instead. +func (*PublicationPlan) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{69} +} + +func (x *PublicationPlan) GetCommit() *Commit { + if x != nil { + return x.Commit + } + return nil +} + +func (x *PublicationPlan) GetIndexRoot() string { + if x != nil { + return x.IndexRoot + } + return "" +} + +func (x *PublicationPlan) GetObjects() []*RepositoryObject { + if x != nil { + return x.Objects + } + return nil +} + +type RepositoryState struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Objects []*RepositoryState_Object `protobuf:"bytes,1,rep,name=objects,proto3" json:"objects,omitempty"` + Refs []*RepositoryState_Ref `protobuf:"bytes,2,rep,name=refs,proto3" json:"refs,omitempty"` + Indexes []*RepositoryState_Index `protobuf:"bytes,3,rep,name=indexes,proto3" json:"indexes,omitempty"` +} + +func (x *RepositoryState) Reset() { + *x = RepositoryState{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[70] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RepositoryState) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RepositoryState) ProtoMessage() {} + +func (x *RepositoryState) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[70] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RepositoryState.ProtoReflect.Descriptor instead. +func (*RepositoryState) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{70} +} + +func (x *RepositoryState) GetObjects() []*RepositoryState_Object { + if x != nil { + return x.Objects + } + return nil +} + +func (x *RepositoryState) GetRefs() []*RepositoryState_Ref { + if x != nil { + return x.Refs + } + return nil +} + +func (x *RepositoryState) GetIndexes() []*RepositoryState_Index { + if x != nil { + return x.Indexes + } + return nil +} + +type ObjectSelection struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ObjectIds []string `protobuf:"bytes,1,rep,name=object_ids,json=objectIds,proto3" json:"object_ids,omitempty"` +} + +func (x *ObjectSelection) Reset() { + *x = ObjectSelection{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[71] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ObjectSelection) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ObjectSelection) ProtoMessage() {} + +func (x *ObjectSelection) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[71] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ObjectSelection.ProtoReflect.Descriptor instead. +func (*ObjectSelection) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{71} +} + +func (x *ObjectSelection) GetObjectIds() []string { + if x != nil { + return x.ObjectIds + } + return nil +} + +type RepositoryObjectPlan struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Kind RepositoryPlanKind `protobuf:"varint,1,opt,name=kind,proto3,enum=cstx.RepositoryPlanKind" json:"kind,omitempty"` + CommitId string `protobuf:"bytes,2,opt,name=commit_id,json=commitId,proto3" json:"commit_id,omitempty"` + Limit *uint64 `protobuf:"varint,3,opt,name=limit,proto3,oneof" json:"limit,omitempty"` + StartTimestamp *int64 `protobuf:"varint,4,opt,name=start_timestamp,json=startTimestamp,proto3,oneof" json:"start_timestamp,omitempty"` + EndTimestamp *int64 `protobuf:"varint,5,opt,name=end_timestamp,json=endTimestamp,proto3,oneof" json:"end_timestamp,omitempty"` + EntityId *string `protobuf:"bytes,6,opt,name=entity_id,json=entityId,proto3,oneof" json:"entity_id,omitempty"` + SourceId *string `protobuf:"bytes,7,opt,name=source_id,json=sourceId,proto3,oneof" json:"source_id,omitempty"` + TargetId *string `protobuf:"bytes,8,opt,name=target_id,json=targetId,proto3,oneof" json:"target_id,omitempty"` + Detail DiffDetail `protobuf:"varint,9,opt,name=detail,proto3,enum=cstx.DiffDetail" json:"detail,omitempty"` + // REPOSITORY_PLAN_ENTITIES reads a set at once; `entity_id` above is the + // single-entity history plan and cannot carry it. + EntityIds []string `protobuf:"bytes,10,rep,name=entity_ids,json=entityIds,proto3" json:"entity_ids,omitempty"` +} + +func (x *RepositoryObjectPlan) Reset() { + *x = RepositoryObjectPlan{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[72] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RepositoryObjectPlan) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RepositoryObjectPlan) ProtoMessage() {} + +func (x *RepositoryObjectPlan) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[72] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RepositoryObjectPlan.ProtoReflect.Descriptor instead. +func (*RepositoryObjectPlan) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{72} +} + +func (x *RepositoryObjectPlan) GetKind() RepositoryPlanKind { + if x != nil { + return x.Kind + } + return RepositoryPlanKind_REPOSITORY_PLAN_UNSPECIFIED +} + +func (x *RepositoryObjectPlan) GetCommitId() string { + if x != nil { + return x.CommitId + } + return "" +} + +func (x *RepositoryObjectPlan) GetLimit() uint64 { + if x != nil && x.Limit != nil { + return *x.Limit + } + return 0 +} + +func (x *RepositoryObjectPlan) GetStartTimestamp() int64 { + if x != nil && x.StartTimestamp != nil { + return *x.StartTimestamp + } + return 0 +} + +func (x *RepositoryObjectPlan) GetEndTimestamp() int64 { + if x != nil && x.EndTimestamp != nil { + return *x.EndTimestamp + } + return 0 +} + +func (x *RepositoryObjectPlan) GetEntityId() string { + if x != nil && x.EntityId != nil { + return *x.EntityId + } + return "" +} + +func (x *RepositoryObjectPlan) GetSourceId() string { + if x != nil && x.SourceId != nil { + return *x.SourceId + } + return "" +} + +func (x *RepositoryObjectPlan) GetTargetId() string { + if x != nil && x.TargetId != nil { + return *x.TargetId + } + return "" +} + +func (x *RepositoryObjectPlan) GetDetail() DiffDetail { + if x != nil { + return x.Detail + } + return DiffDetail_DIFF_DETAIL_UNSPECIFIED +} + +func (x *RepositoryObjectPlan) GetEntityIds() []string { + if x != nil { + return x.EntityIds + } + return nil +} + +type RagFilter struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodeTypes []string `protobuf:"bytes,1,rep,name=node_types,json=nodeTypes,proto3" json:"node_types,omitempty"` + RelationshipTypes []string `protobuf:"bytes,2,rep,name=relationship_types,json=relationshipTypes,proto3" json:"relationship_types,omitempty"` + ExcludeFlagsMask uint64 `protobuf:"varint,5,opt,name=exclude_flags_mask,json=excludeFlagsMask,proto3" json:"exclude_flags_mask,omitempty"` + IncludeFlagsMask uint64 `protobuf:"varint,6,opt,name=include_flags_mask,json=includeFlagsMask,proto3" json:"include_flags_mask,omitempty"` +} + +func (x *RagFilter) Reset() { + *x = RagFilter{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[73] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RagFilter) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RagFilter) ProtoMessage() {} + +func (x *RagFilter) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[73] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RagFilter.ProtoReflect.Descriptor instead. +func (*RagFilter) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{73} +} + +func (x *RagFilter) GetNodeTypes() []string { + if x != nil { + return x.NodeTypes + } + return nil +} + +func (x *RagFilter) GetRelationshipTypes() []string { + if x != nil { + return x.RelationshipTypes + } + return nil +} + +func (x *RagFilter) GetExcludeFlagsMask() uint64 { + if x != nil { + return x.ExcludeFlagsMask + } + return 0 +} + +func (x *RagFilter) GetIncludeFlagsMask() uint64 { + if x != nil { + return x.IncludeFlagsMask + } + return 0 +} + +type RagGraphChanges struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ChangedNodeIds []string `protobuf:"bytes,1,rep,name=changed_node_ids,json=changedNodeIds,proto3" json:"changed_node_ids,omitempty"` + DeletedNodeIds []string `protobuf:"bytes,2,rep,name=deleted_node_ids,json=deletedNodeIds,proto3" json:"deleted_node_ids,omitempty"` + ChangedRelationshipIds []string `protobuf:"bytes,3,rep,name=changed_relationship_ids,json=changedRelationshipIds,proto3" json:"changed_relationship_ids,omitempty"` + DeletedRelationshipIds []string `protobuf:"bytes,4,rep,name=deleted_relationship_ids,json=deletedRelationshipIds,proto3" json:"deleted_relationship_ids,omitempty"` +} + +func (x *RagGraphChanges) Reset() { + *x = RagGraphChanges{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[74] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RagGraphChanges) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RagGraphChanges) ProtoMessage() {} + +func (x *RagGraphChanges) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[74] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RagGraphChanges.ProtoReflect.Descriptor instead. +func (*RagGraphChanges) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{74} +} + +func (x *RagGraphChanges) GetChangedNodeIds() []string { + if x != nil { + return x.ChangedNodeIds + } + return nil +} + +func (x *RagGraphChanges) GetDeletedNodeIds() []string { + if x != nil { + return x.DeletedNodeIds + } + return nil +} + +func (x *RagGraphChanges) GetChangedRelationshipIds() []string { + if x != nil { + return x.ChangedRelationshipIds + } + return nil +} + +func (x *RagGraphChanges) GetDeletedRelationshipIds() []string { + if x != nil { + return x.DeletedRelationshipIds + } + return nil +} + +type RagRecord struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Kind RagRecordKind `protobuf:"varint,2,opt,name=kind,proto3,enum=cstx.RagRecordKind" json:"kind,omitempty"` + Text string `protobuf:"bytes,3,opt,name=text,proto3" json:"text,omitempty"` + ContentHash string `protobuf:"bytes,4,opt,name=content_hash,json=contentHash,proto3" json:"content_hash,omitempty"` + NodeIds []string `protobuf:"bytes,5,rep,name=node_ids,json=nodeIds,proto3" json:"node_ids,omitempty"` + RelationshipIds []string `protobuf:"bytes,6,rep,name=relationship_ids,json=relationshipIds,proto3" json:"relationship_ids,omitempty"` + NodeType *string `protobuf:"bytes,7,opt,name=node_type,json=nodeType,proto3,oneof" json:"node_type,omitempty"` + RelationshipType *string `protobuf:"bytes,8,opt,name=relationship_type,json=relationshipType,proto3,oneof" json:"relationship_type,omitempty"` +} + +func (x *RagRecord) Reset() { + *x = RagRecord{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[75] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RagRecord) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RagRecord) ProtoMessage() {} + +func (x *RagRecord) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[75] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RagRecord.ProtoReflect.Descriptor instead. +func (*RagRecord) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{75} +} + +func (x *RagRecord) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *RagRecord) GetKind() RagRecordKind { + if x != nil { + return x.Kind + } + return RagRecordKind_RAG_RECORD_KIND_UNSPECIFIED +} + +func (x *RagRecord) GetText() string { + if x != nil { + return x.Text + } + return "" +} + +func (x *RagRecord) GetContentHash() string { + if x != nil { + return x.ContentHash + } + return "" +} + +func (x *RagRecord) GetNodeIds() []string { + if x != nil { + return x.NodeIds + } + return nil +} + +func (x *RagRecord) GetRelationshipIds() []string { + if x != nil { + return x.RelationshipIds + } + return nil +} + +func (x *RagRecord) GetNodeType() string { + if x != nil && x.NodeType != nil { + return *x.NodeType + } + return "" +} + +func (x *RagRecord) GetRelationshipType() string { + if x != nil && x.RelationshipType != nil { + return *x.RelationshipType + } + return "" +} + +type RagIndexResult struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + OperationId string `protobuf:"bytes,1,opt,name=operation_id,json=operationId,proto3" json:"operation_id,omitempty"` + Commit string `protobuf:"bytes,2,opt,name=commit,proto3" json:"commit,omitempty"` + Mode RagIndexMode `protobuf:"varint,3,opt,name=mode,proto3,enum=cstx.RagIndexMode" json:"mode,omitempty"` + UpsertCount uint64 `protobuf:"varint,4,opt,name=upsert_count,json=upsertCount,proto3" json:"upsert_count,omitempty"` + DeleteCount uint64 `protobuf:"varint,5,opt,name=delete_count,json=deleteCount,proto3" json:"delete_count,omitempty"` +} + +func (x *RagIndexResult) Reset() { + *x = RagIndexResult{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[76] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RagIndexResult) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RagIndexResult) ProtoMessage() {} + +func (x *RagIndexResult) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[76] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RagIndexResult.ProtoReflect.Descriptor instead. +func (*RagIndexResult) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{76} +} + +func (x *RagIndexResult) GetOperationId() string { + if x != nil { + return x.OperationId + } + return "" +} + +func (x *RagIndexResult) GetCommit() string { + if x != nil { + return x.Commit + } + return "" +} + +func (x *RagIndexResult) GetMode() RagIndexMode { + if x != nil { + return x.Mode + } + return RagIndexMode_RAG_INDEX_MODE_UNSPECIFIED +} + +func (x *RagIndexResult) GetUpsertCount() uint64 { + if x != nil { + return x.UpsertCount + } + return 0 +} + +func (x *RagIndexResult) GetDeleteCount() uint64 { + if x != nil { + return x.DeleteCount + } + return 0 +} + +type RagIndexPlan struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Commit string `protobuf:"bytes,1,opt,name=commit,proto3" json:"commit,omitempty"` + Mode RagIndexMode `protobuf:"varint,2,opt,name=mode,proto3,enum=cstx.RagIndexMode" json:"mode,omitempty"` + Changes *RagGraphChanges `protobuf:"bytes,3,opt,name=changes,proto3" json:"changes,omitempty"` +} + +func (x *RagIndexPlan) Reset() { + *x = RagIndexPlan{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[77] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RagIndexPlan) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RagIndexPlan) ProtoMessage() {} + +func (x *RagIndexPlan) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[77] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RagIndexPlan.ProtoReflect.Descriptor instead. +func (*RagIndexPlan) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{77} +} + +func (x *RagIndexPlan) GetCommit() string { + if x != nil { + return x.Commit + } + return "" +} + +func (x *RagIndexPlan) GetMode() RagIndexMode { + if x != nil { + return x.Mode + } + return RagIndexMode_RAG_INDEX_MODE_UNSPECIFIED +} + +func (x *RagIndexPlan) GetChanges() *RagGraphChanges { + if x != nil { + return x.Changes + } + return nil +} + +type RagRecordPage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Records []*RagRecord `protobuf:"bytes,1,rep,name=records,proto3" json:"records,omitempty"` + Page uint64 `protobuf:"varint,2,opt,name=page,proto3" json:"page,omitempty"` + Limit uint64 `protobuf:"varint,3,opt,name=limit,proto3" json:"limit,omitempty"` + HasNext bool `protobuf:"varint,4,opt,name=has_next,json=hasNext,proto3" json:"has_next,omitempty"` +} + +func (x *RagRecordPage) Reset() { + *x = RagRecordPage{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[78] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RagRecordPage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RagRecordPage) ProtoMessage() {} + +func (x *RagRecordPage) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[78] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RagRecordPage.ProtoReflect.Descriptor instead. +func (*RagRecordPage) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{78} +} + +func (x *RagRecordPage) GetRecords() []*RagRecord { + if x != nil { + return x.Records + } + return nil +} + +func (x *RagRecordPage) GetPage() uint64 { + if x != nil { + return x.Page + } + return 0 +} + +func (x *RagRecordPage) GetLimit() uint64 { + if x != nil { + return x.Limit + } + return 0 +} + +func (x *RagRecordPage) GetHasNext() bool { + if x != nil { + return x.HasNext + } + return false +} + +type RecallQuery struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Text string `protobuf:"bytes,2,opt,name=text,proto3" json:"text,omitempty"` + Kind RagRecordKind `protobuf:"varint,3,opt,name=kind,proto3,enum=cstx.RagRecordKind" json:"kind,omitempty"` + Limit uint64 `protobuf:"varint,4,opt,name=limit,proto3" json:"limit,omitempty"` + Filter *RagFilter `protobuf:"bytes,5,opt,name=filter,proto3" json:"filter,omitempty"` +} + +func (x *RecallQuery) Reset() { + *x = RecallQuery{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[79] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RecallQuery) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RecallQuery) ProtoMessage() {} + +func (x *RecallQuery) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[79] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RecallQuery.ProtoReflect.Descriptor instead. +func (*RecallQuery) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{79} +} + +func (x *RecallQuery) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *RecallQuery) GetText() string { + if x != nil { + return x.Text + } + return "" +} + +func (x *RecallQuery) GetKind() RagRecordKind { + if x != nil { + return x.Kind + } + return RagRecordKind_RAG_RECORD_KIND_UNSPECIFIED +} + +func (x *RecallQuery) GetLimit() uint64 { + if x != nil { + return x.Limit + } + return 0 +} + +func (x *RecallQuery) GetFilter() *RagFilter { + if x != nil { + return x.Filter + } + return nil +} + +type RecallHit struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RecordId string `protobuf:"bytes,1,opt,name=record_id,json=recordId,proto3" json:"record_id,omitempty"` + Rank uint64 `protobuf:"varint,2,opt,name=rank,proto3" json:"rank,omitempty"` + Score *float32 `protobuf:"fixed32,3,opt,name=score,proto3,oneof" json:"score,omitempty"` +} + +func (x *RecallHit) Reset() { + *x = RecallHit{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[80] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RecallHit) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RecallHit) ProtoMessage() {} + +func (x *RecallHit) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[80] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RecallHit.ProtoReflect.Descriptor instead. +func (*RecallHit) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{80} +} + +func (x *RecallHit) GetRecordId() string { + if x != nil { + return x.RecordId + } + return "" +} + +func (x *RecallHit) GetRank() uint64 { + if x != nil { + return x.Rank + } + return 0 +} + +func (x *RecallHit) GetScore() float32 { + if x != nil && x.Score != nil { + return *x.Score + } + return 0 +} + +type ExtensionRecallResult struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + QueryId string `protobuf:"bytes,1,opt,name=query_id,json=queryId,proto3" json:"query_id,omitempty"` + Extension string `protobuf:"bytes,2,opt,name=extension,proto3" json:"extension,omitempty"` + Hits []*RecallHit `protobuf:"bytes,3,rep,name=hits,proto3" json:"hits,omitempty"` +} + +func (x *ExtensionRecallResult) Reset() { + *x = ExtensionRecallResult{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[81] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExtensionRecallResult) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExtensionRecallResult) ProtoMessage() {} + +func (x *ExtensionRecallResult) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[81] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExtensionRecallResult.ProtoReflect.Descriptor instead. +func (*ExtensionRecallResult) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{81} +} + +func (x *ExtensionRecallResult) GetQueryId() string { + if x != nil { + return x.QueryId + } + return "" +} + +func (x *ExtensionRecallResult) GetExtension() string { + if x != nil { + return x.Extension + } + return "" +} + +func (x *ExtensionRecallResult) GetHits() []*RecallHit { + if x != nil { + return x.Hits + } + return nil +} + +type RecallResults struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Results []*ExtensionRecallResult `protobuf:"bytes,1,rep,name=results,proto3" json:"results,omitempty"` +} + +func (x *RecallResults) Reset() { + *x = RecallResults{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[82] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RecallResults) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RecallResults) ProtoMessage() {} + +func (x *RecallResults) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[82] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RecallResults.ProtoReflect.Descriptor instead. +func (*RecallResults) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{82} +} + +func (x *RecallResults) GetResults() []*ExtensionRecallResult { + if x != nil { + return x.Results + } + return nil +} + +type RecallPlan struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Queries []*RecallQuery `protobuf:"bytes,1,rep,name=queries,proto3" json:"queries,omitempty"` +} + +func (x *RecallPlan) Reset() { + *x = RecallPlan{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[83] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RecallPlan) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RecallPlan) ProtoMessage() {} + +func (x *RecallPlan) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[83] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RecallPlan.ProtoReflect.Descriptor instead. +func (*RecallPlan) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{83} +} + +func (x *RecallPlan) GetQueries() []*RecallQuery { + if x != nil { + return x.Queries + } + return nil +} + +type RagPolicy struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RrfK float32 `protobuf:"fixed32,1,opt,name=rrf_k,json=rrfK,proto3" json:"rrf_k,omitempty"` + CandidateMultiplier uint64 `protobuf:"varint,2,opt,name=candidate_multiplier,json=candidateMultiplier,proto3" json:"candidate_multiplier,omitempty"` + Damping float32 `protobuf:"fixed32,3,opt,name=damping,proto3" json:"damping,omitempty"` + PropagationIterations uint64 `protobuf:"varint,4,opt,name=propagation_iterations,json=propagationIterations,proto3" json:"propagation_iterations,omitempty"` + MaxPathDepth uint64 `protobuf:"varint,5,opt,name=max_path_depth,json=maxPathDepth,proto3" json:"max_path_depth,omitempty"` + Epsilon float32 `protobuf:"fixed32,6,opt,name=epsilon,proto3" json:"epsilon,omitempty"` + Communities bool `protobuf:"varint,7,opt,name=communities,proto3" json:"communities,omitempty"` + UseLexical bool `protobuf:"varint,8,opt,name=use_lexical,json=useLexical,proto3" json:"use_lexical,omitempty"` +} + +func (x *RagPolicy) Reset() { + *x = RagPolicy{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[84] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RagPolicy) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RagPolicy) ProtoMessage() {} + +func (x *RagPolicy) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[84] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RagPolicy.ProtoReflect.Descriptor instead. +func (*RagPolicy) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{84} +} + +func (x *RagPolicy) GetRrfK() float32 { + if x != nil { + return x.RrfK + } + return 0 +} + +func (x *RagPolicy) GetCandidateMultiplier() uint64 { + if x != nil { + return x.CandidateMultiplier + } + return 0 +} + +func (x *RagPolicy) GetDamping() float32 { + if x != nil { + return x.Damping + } + return 0 +} + +func (x *RagPolicy) GetPropagationIterations() uint64 { + if x != nil { + return x.PropagationIterations + } + return 0 +} + +func (x *RagPolicy) GetMaxPathDepth() uint64 { + if x != nil { + return x.MaxPathDepth + } + return 0 +} + +func (x *RagPolicy) GetEpsilon() float32 { + if x != nil { + return x.Epsilon + } + return 0 +} + +func (x *RagPolicy) GetCommunities() bool { + if x != nil { + return x.Communities + } + return false +} + +func (x *RagPolicy) GetUseLexical() bool { + if x != nil { + return x.UseLexical + } + return false +} + +type RagQuery struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Text string `protobuf:"bytes,1,opt,name=text,proto3" json:"text,omitempty"` + Limit uint64 `protobuf:"varint,2,opt,name=limit,proto3" json:"limit,omitempty"` + Filter *RagFilter `protobuf:"bytes,3,opt,name=filter,proto3" json:"filter,omitempty"` + Policy *RagPolicy `protobuf:"bytes,4,opt,name=policy,proto3" json:"policy,omitempty"` + ContextBudget *uint64 `protobuf:"varint,5,opt,name=context_budget,json=contextBudget,proto3,oneof" json:"context_budget,omitempty"` +} + +func (x *RagQuery) Reset() { + *x = RagQuery{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[85] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RagQuery) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RagQuery) ProtoMessage() {} + +func (x *RagQuery) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[85] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RagQuery.ProtoReflect.Descriptor instead. +func (*RagQuery) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{85} +} + +func (x *RagQuery) GetText() string { + if x != nil { + return x.Text + } + return "" +} + +func (x *RagQuery) GetLimit() uint64 { + if x != nil { + return x.Limit + } + return 0 +} + +func (x *RagQuery) GetFilter() *RagFilter { + if x != nil { + return x.Filter + } + return nil +} + +func (x *RagQuery) GetPolicy() *RagPolicy { + if x != nil { + return x.Policy + } + return nil +} + +func (x *RagQuery) GetContextBudget() uint64 { + if x != nil && x.ContextBudget != nil { + return *x.ContextBudget + } + return 0 +} + +type RankedNode struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` + Score float32 `protobuf:"fixed32,2,opt,name=score,proto3" json:"score,omitempty"` + Direct bool `protobuf:"varint,3,opt,name=direct,proto3" json:"direct,omitempty"` + Provenance []string `protobuf:"bytes,4,rep,name=provenance,proto3" json:"provenance,omitempty"` +} + +func (x *RankedNode) Reset() { + *x = RankedNode{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[86] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RankedNode) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RankedNode) ProtoMessage() {} + +func (x *RankedNode) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[86] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RankedNode.ProtoReflect.Descriptor instead. +func (*RankedNode) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{86} +} + +func (x *RankedNode) GetNodeId() string { + if x != nil { + return x.NodeId + } + return "" +} + +func (x *RankedNode) GetScore() float32 { + if x != nil { + return x.Score + } + return 0 +} + +func (x *RankedNode) GetDirect() bool { + if x != nil { + return x.Direct + } + return false +} + +func (x *RankedNode) GetProvenance() []string { + if x != nil { + return x.Provenance + } + return nil +} + +type RankedRelationship struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RelationshipId string `protobuf:"bytes,1,opt,name=relationship_id,json=relationshipId,proto3" json:"relationship_id,omitempty"` + Score float32 `protobuf:"fixed32,2,opt,name=score,proto3" json:"score,omitempty"` + Direct bool `protobuf:"varint,3,opt,name=direct,proto3" json:"direct,omitempty"` + Provenance []string `protobuf:"bytes,4,rep,name=provenance,proto3" json:"provenance,omitempty"` +} + +func (x *RankedRelationship) Reset() { + *x = RankedRelationship{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[87] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RankedRelationship) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RankedRelationship) ProtoMessage() {} + +func (x *RankedRelationship) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[87] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RankedRelationship.ProtoReflect.Descriptor instead. +func (*RankedRelationship) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{87} +} + +func (x *RankedRelationship) GetRelationshipId() string { + if x != nil { + return x.RelationshipId + } + return "" +} + +func (x *RankedRelationship) GetScore() float32 { + if x != nil { + return x.Score + } + return 0 +} + +func (x *RankedRelationship) GetDirect() bool { + if x != nil { + return x.Direct + } + return false +} + +func (x *RankedRelationship) GetProvenance() []string { + if x != nil { + return x.Provenance + } + return nil +} + +type RagPath struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodeIds []string `protobuf:"bytes,1,rep,name=node_ids,json=nodeIds,proto3" json:"node_ids,omitempty"` + RelationshipIds []string `protobuf:"bytes,2,rep,name=relationship_ids,json=relationshipIds,proto3" json:"relationship_ids,omitempty"` + Score float32 `protobuf:"fixed32,3,opt,name=score,proto3" json:"score,omitempty"` +} + +func (x *RagPath) Reset() { + *x = RagPath{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[88] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RagPath) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RagPath) ProtoMessage() {} + +func (x *RagPath) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[88] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RagPath.ProtoReflect.Descriptor instead. +func (*RagPath) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{88} +} + +func (x *RagPath) GetNodeIds() []string { + if x != nil { + return x.NodeIds + } + return nil +} + +func (x *RagPath) GetRelationshipIds() []string { + if x != nil { + return x.RelationshipIds + } + return nil +} + +func (x *RagPath) GetScore() float32 { + if x != nil { + return x.Score + } + return 0 +} + +type RagCommunityHit struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Level uint64 `protobuf:"varint,2,opt,name=level,proto3" json:"level,omitempty"` + MemberNodeIds []string `protobuf:"bytes,3,rep,name=member_node_ids,json=memberNodeIds,proto3" json:"member_node_ids,omitempty"` + Score float32 `protobuf:"fixed32,4,opt,name=score,proto3" json:"score,omitempty"` +} + +func (x *RagCommunityHit) Reset() { + *x = RagCommunityHit{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[89] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RagCommunityHit) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RagCommunityHit) ProtoMessage() {} + +func (x *RagCommunityHit) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[89] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RagCommunityHit.ProtoReflect.Descriptor instead. +func (*RagCommunityHit) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{89} +} + +func (x *RagCommunityHit) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *RagCommunityHit) GetLevel() uint64 { + if x != nil { + return x.Level + } + return 0 +} + +func (x *RagCommunityHit) GetMemberNodeIds() []string { + if x != nil { + return x.MemberNodeIds + } + return nil +} + +func (x *RagCommunityHit) GetScore() float32 { + if x != nil { + return x.Score + } + return 0 +} + +type RagContextBlock struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Text string `protobuf:"bytes,1,opt,name=text,proto3" json:"text,omitempty"` + RecordIds []string `protobuf:"bytes,2,rep,name=record_ids,json=recordIds,proto3" json:"record_ids,omitempty"` + EstimatedTokens uint64 `protobuf:"varint,3,opt,name=estimated_tokens,json=estimatedTokens,proto3" json:"estimated_tokens,omitempty"` +} + +func (x *RagContextBlock) Reset() { + *x = RagContextBlock{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[90] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RagContextBlock) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RagContextBlock) ProtoMessage() {} + +func (x *RagContextBlock) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[90] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RagContextBlock.ProtoReflect.Descriptor instead. +func (*RagContextBlock) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{90} +} + +func (x *RagContextBlock) GetText() string { + if x != nil { + return x.Text + } + return "" +} + +func (x *RagContextBlock) GetRecordIds() []string { + if x != nil { + return x.RecordIds + } + return nil +} + +func (x *RagContextBlock) GetEstimatedTokens() uint64 { + if x != nil { + return x.EstimatedTokens + } + return 0 +} + +type EvidenceProvenance struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ResultId string `protobuf:"bytes,1,opt,name=result_id,json=resultId,proto3" json:"result_id,omitempty"` + RecordIds []string `protobuf:"bytes,2,rep,name=record_ids,json=recordIds,proto3" json:"record_ids,omitempty"` +} + +func (x *EvidenceProvenance) Reset() { + *x = EvidenceProvenance{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[91] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EvidenceProvenance) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EvidenceProvenance) ProtoMessage() {} + +func (x *EvidenceProvenance) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[91] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EvidenceProvenance.ProtoReflect.Descriptor instead. +func (*EvidenceProvenance) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{91} +} + +func (x *EvidenceProvenance) GetResultId() string { + if x != nil { + return x.ResultId + } + return "" +} + +func (x *EvidenceProvenance) GetRecordIds() []string { + if x != nil { + return x.RecordIds + } + return nil +} + +type RagResult struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Commit string `protobuf:"bytes,1,opt,name=commit,proto3" json:"commit,omitempty"` + Nodes []*RankedNode `protobuf:"bytes,2,rep,name=nodes,proto3" json:"nodes,omitempty"` + Relationships []*RankedRelationship `protobuf:"bytes,3,rep,name=relationships,proto3" json:"relationships,omitempty"` + Paths []*RagPath `protobuf:"bytes,4,rep,name=paths,proto3" json:"paths,omitempty"` + Communities []*RagCommunityHit `protobuf:"bytes,5,rep,name=communities,proto3" json:"communities,omitempty"` + Context []*RagContextBlock `protobuf:"bytes,6,rep,name=context,proto3" json:"context,omitempty"` + Provenance []*EvidenceProvenance `protobuf:"bytes,7,rep,name=provenance,proto3" json:"provenance,omitempty"` + DroppedRecords []string `protobuf:"bytes,8,rep,name=dropped_records,json=droppedRecords,proto3" json:"dropped_records,omitempty"` + Extensions []string `protobuf:"bytes,9,rep,name=extensions,proto3" json:"extensions,omitempty"` +} + +func (x *RagResult) Reset() { + *x = RagResult{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[92] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RagResult) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RagResult) ProtoMessage() {} + +func (x *RagResult) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[92] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RagResult.ProtoReflect.Descriptor instead. +func (*RagResult) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{92} +} + +func (x *RagResult) GetCommit() string { + if x != nil { + return x.Commit + } + return "" +} + +func (x *RagResult) GetNodes() []*RankedNode { + if x != nil { + return x.Nodes + } + return nil +} + +func (x *RagResult) GetRelationships() []*RankedRelationship { + if x != nil { + return x.Relationships + } + return nil +} + +func (x *RagResult) GetPaths() []*RagPath { + if x != nil { + return x.Paths + } + return nil +} + +func (x *RagResult) GetCommunities() []*RagCommunityHit { + if x != nil { + return x.Communities + } + return nil +} + +func (x *RagResult) GetContext() []*RagContextBlock { + if x != nil { + return x.Context + } + return nil +} + +func (x *RagResult) GetProvenance() []*EvidenceProvenance { + if x != nil { + return x.Provenance + } + return nil +} + +func (x *RagResult) GetDroppedRecords() []string { + if x != nil { + return x.DroppedRecords + } + return nil +} + +func (x *RagResult) GetExtensions() []string { + if x != nil { + return x.Extensions + } + return nil +} + +type ExtensionContract struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ContractVersion uint32 `protobuf:"varint,1,opt,name=contract_version,json=contractVersion,proto3" json:"contract_version,omitempty"` + Extensions map[string]*ExtensionDefinition `protobuf:"bytes,2,rep,name=extensions,proto3" json:"extensions,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *ExtensionContract) Reset() { + *x = ExtensionContract{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[93] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExtensionContract) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExtensionContract) ProtoMessage() {} + +func (x *ExtensionContract) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[93] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExtensionContract.ProtoReflect.Descriptor instead. +func (*ExtensionContract) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{93} +} + +func (x *ExtensionContract) GetContractVersion() uint32 { + if x != nil { + return x.ContractVersion + } + return 0 +} + +func (x *ExtensionContract) GetExtensions() map[string]*ExtensionDefinition { + if x != nil { + return x.Extensions + } + return nil +} + +type ExtensionDefinition struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` + Parsers map[string]*ParserType `protobuf:"bytes,5,rep,name=parsers,proto3" json:"parsers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Rules []*JoinRule `protobuf:"bytes,6,rep,name=rules,proto3" json:"rules,omitempty"` + // This extension's runtime schema document, as `make codegen` produces it. + // Node types, their identity and their columns are declared here and + // nowhere else; protobuf is how payloads are serialized, not how types are + // declared. The built-in extension carries the same artifact. + Schema string `protobuf:"bytes,7,opt,name=schema,proto3" json:"schema,omitempty"` +} + +func (x *ExtensionDefinition) Reset() { + *x = ExtensionDefinition{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[94] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExtensionDefinition) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExtensionDefinition) ProtoMessage() {} + +func (x *ExtensionDefinition) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[94] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExtensionDefinition.ProtoReflect.Descriptor instead. +func (*ExtensionDefinition) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{94} +} + +func (x *ExtensionDefinition) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ExtensionDefinition) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *ExtensionDefinition) GetParsers() map[string]*ParserType { + if x != nil { + return x.Parsers + } + return nil +} + +func (x *ExtensionDefinition) GetRules() []*JoinRule { + if x != nil { + return x.Rules + } + return nil +} + +func (x *ExtensionDefinition) GetSchema() string { + if x != nil { + return x.Schema + } + return "" +} + +type NodeType struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl,proto3" json:"type_url,omitempty"` + Metadata *structpb.Struct `protobuf:"bytes,2,opt,name=metadata,proto3" json:"metadata,omitempty"` +} + +func (x *NodeType) Reset() { + *x = NodeType{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[95] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NodeType) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NodeType) ProtoMessage() {} + +func (x *NodeType) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[95] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NodeType.ProtoReflect.Descriptor instead. +func (*NodeType) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{95} +} + +func (x *NodeType) GetTypeUrl() string { + if x != nil { + return x.TypeUrl + } + return "" +} + +func (x *NodeType) GetMetadata() *structpb.Struct { + if x != nil { + return x.Metadata + } + return nil +} + +type RelationshipType struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl,proto3" json:"type_url,omitempty"` + Metadata *structpb.Struct `protobuf:"bytes,2,opt,name=metadata,proto3" json:"metadata,omitempty"` +} + +func (x *RelationshipType) Reset() { + *x = RelationshipType{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[96] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RelationshipType) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RelationshipType) ProtoMessage() {} + +func (x *RelationshipType) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[96] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RelationshipType.ProtoReflect.Descriptor instead. +func (*RelationshipType) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{96} +} + +func (x *RelationshipType) GetTypeUrl() string { + if x != nil { + return x.TypeUrl + } + return "" +} + +func (x *RelationshipType) GetMetadata() *structpb.Struct { + if x != nil { + return x.Metadata + } + return nil +} + +type ParserType struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Artifact string `protobuf:"bytes,1,opt,name=artifact,proto3" json:"artifact,omitempty"` + InputSchema *structpb.Struct `protobuf:"bytes,2,opt,name=input_schema,json=inputSchema,proto3" json:"input_schema,omitempty"` + Metadata *structpb.Struct `protobuf:"bytes,3,opt,name=metadata,proto3" json:"metadata,omitempty"` +} + +func (x *ParserType) Reset() { + *x = ParserType{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[97] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ParserType) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ParserType) ProtoMessage() {} + +func (x *ParserType) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[97] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ParserType.ProtoReflect.Descriptor instead. +func (*ParserType) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{97} +} + +func (x *ParserType) GetArtifact() string { + if x != nil { + return x.Artifact + } + return "" +} + +func (x *ParserType) GetInputSchema() *structpb.Struct { + if x != nil { + return x.InputSchema + } + return nil +} + +func (x *ParserType) GetMetadata() *structpb.Struct { + if x != nil { + return x.Metadata + } + return nil +} + +type JoinRule struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + LeftTypeUrl string `protobuf:"bytes,1,opt,name=left_type_url,json=leftTypeUrl,proto3" json:"left_type_url,omitempty"` + RightTypeUrl string `protobuf:"bytes,2,opt,name=right_type_url,json=rightTypeUrl,proto3" json:"right_type_url,omitempty"` + RelationshipTypeUrl string `protobuf:"bytes,3,opt,name=relationship_type_url,json=relationshipTypeUrl,proto3" json:"relationship_type_url,omitempty"` + LeftKey string `protobuf:"bytes,4,opt,name=left_key,json=leftKey,proto3" json:"left_key,omitempty"` + RightKey string `protobuf:"bytes,5,opt,name=right_key,json=rightKey,proto3" json:"right_key,omitempty"` + Predicted bool `protobuf:"varint,6,opt,name=predicted,proto3" json:"predicted,omitempty"` + LeftTargetId *string `protobuf:"bytes,7,opt,name=left_target_id,json=leftTargetId,proto3,oneof" json:"left_target_id,omitempty"` + RightSourceId *string `protobuf:"bytes,8,opt,name=right_source_id,json=rightSourceId,proto3,oneof" json:"right_source_id,omitempty"` +} + +func (x *JoinRule) Reset() { + *x = JoinRule{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[98] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *JoinRule) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*JoinRule) ProtoMessage() {} + +func (x *JoinRule) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[98] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use JoinRule.ProtoReflect.Descriptor instead. +func (*JoinRule) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{98} +} + +func (x *JoinRule) GetLeftTypeUrl() string { + if x != nil { + return x.LeftTypeUrl + } + return "" +} + +func (x *JoinRule) GetRightTypeUrl() string { + if x != nil { + return x.RightTypeUrl + } + return "" +} + +func (x *JoinRule) GetRelationshipTypeUrl() string { + if x != nil { + return x.RelationshipTypeUrl + } + return "" +} + +func (x *JoinRule) GetLeftKey() string { + if x != nil { + return x.LeftKey + } + return "" +} + +func (x *JoinRule) GetRightKey() string { + if x != nil { + return x.RightKey + } + return "" +} + +func (x *JoinRule) GetPredicted() bool { + if x != nil { + return x.Predicted + } + return false +} + +func (x *JoinRule) GetLeftTargetId() string { + if x != nil && x.LeftTargetId != nil { + return *x.LeftTargetId + } + return "" +} + +func (x *JoinRule) GetRightSourceId() string { + if x != nil && x.RightSourceId != nil { + return *x.RightSourceId + } + return "" +} + +type ExtensionInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` + Kind string `protobuf:"bytes,3,opt,name=kind,proto3" json:"kind,omitempty"` + Enabled bool `protobuf:"varint,4,opt,name=enabled,proto3" json:"enabled,omitempty"` + Artifacts []string `protobuf:"bytes,5,rep,name=artifacts,proto3" json:"artifacts,omitempty"` +} + +func (x *ExtensionInfo) Reset() { + *x = ExtensionInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[99] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExtensionInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExtensionInfo) ProtoMessage() {} + +func (x *ExtensionInfo) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[99] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExtensionInfo.ProtoReflect.Descriptor instead. +func (*ExtensionInfo) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{99} +} + +func (x *ExtensionInfo) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ExtensionInfo) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *ExtensionInfo) GetKind() string { + if x != nil { + return x.Kind + } + return "" +} + +func (x *ExtensionInfo) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +func (x *ExtensionInfo) GetArtifacts() []string { + if x != nil { + return x.Artifacts + } + return nil +} + +type ExtensionCatalog struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Extensions []*ExtensionInfo `protobuf:"bytes,1,rep,name=extensions,proto3" json:"extensions,omitempty"` +} + +func (x *ExtensionCatalog) Reset() { + *x = ExtensionCatalog{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[100] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExtensionCatalog) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExtensionCatalog) ProtoMessage() {} + +func (x *ExtensionCatalog) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[100] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExtensionCatalog.ProtoReflect.Descriptor instead. +func (*ExtensionCatalog) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{100} +} + +func (x *ExtensionCatalog) GetExtensions() []*ExtensionInfo { + if x != nil { + return x.Extensions + } + return nil +} + +type AnchorConcept struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + NodeTypes []string `protobuf:"bytes,2,rep,name=node_types,json=nodeTypes,proto3" json:"node_types,omitempty"` +} + +func (x *AnchorConcept) Reset() { + *x = AnchorConcept{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[101] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AnchorConcept) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AnchorConcept) ProtoMessage() {} + +func (x *AnchorConcept) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[101] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AnchorConcept.ProtoReflect.Descriptor instead. +func (*AnchorConcept) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{101} +} + +func (x *AnchorConcept) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *AnchorConcept) GetNodeTypes() []string { + if x != nil { + return x.NodeTypes + } + return nil +} + +type AnchorConceptCatalog struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Concepts []*AnchorConcept `protobuf:"bytes,1,rep,name=concepts,proto3" json:"concepts,omitempty"` +} + +func (x *AnchorConceptCatalog) Reset() { + *x = AnchorConceptCatalog{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[102] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AnchorConceptCatalog) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AnchorConceptCatalog) ProtoMessage() {} + +func (x *AnchorConceptCatalog) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[102] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AnchorConceptCatalog.ProtoReflect.Descriptor instead. +func (*AnchorConceptCatalog) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{102} +} + +func (x *AnchorConceptCatalog) GetConcepts() []*AnchorConcept { + if x != nil { + return x.Concepts + } + return nil +} + +type GraphProjectionReport_NodeExclusion struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` + Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` +} + +func (x *GraphProjectionReport_NodeExclusion) Reset() { + *x = GraphProjectionReport_NodeExclusion{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[110] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GraphProjectionReport_NodeExclusion) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GraphProjectionReport_NodeExclusion) ProtoMessage() {} + +func (x *GraphProjectionReport_NodeExclusion) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[110] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GraphProjectionReport_NodeExclusion.ProtoReflect.Descriptor instead. +func (*GraphProjectionReport_NodeExclusion) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{67, 0} +} + +func (x *GraphProjectionReport_NodeExclusion) GetNodeId() string { + if x != nil { + return x.NodeId + } + return "" +} + +func (x *GraphProjectionReport_NodeExclusion) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +type RepositoryState_Object struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Payload []byte `protobuf:"bytes,2,opt,name=payload,proto3" json:"payload,omitempty"` +} + +func (x *RepositoryState_Object) Reset() { + *x = RepositoryState_Object{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[111] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RepositoryState_Object) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RepositoryState_Object) ProtoMessage() {} + +func (x *RepositoryState_Object) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[111] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RepositoryState_Object.ProtoReflect.Descriptor instead. +func (*RepositoryState_Object) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{70, 0} +} + +func (x *RepositoryState_Object) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *RepositoryState_Object) GetPayload() []byte { + if x != nil { + return x.Payload + } + return nil +} + +type RepositoryState_Ref struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + CommitId *string `protobuf:"bytes,2,opt,name=commit_id,json=commitId,proto3,oneof" json:"commit_id,omitempty"` +} + +func (x *RepositoryState_Ref) Reset() { + *x = RepositoryState_Ref{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[112] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RepositoryState_Ref) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RepositoryState_Ref) ProtoMessage() {} + +func (x *RepositoryState_Ref) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[112] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RepositoryState_Ref.ProtoReflect.Descriptor instead. +func (*RepositoryState_Ref) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{70, 1} +} + +func (x *RepositoryState_Ref) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *RepositoryState_Ref) GetCommitId() string { + if x != nil && x.CommitId != nil { + return *x.CommitId + } + return "" +} + +type RepositoryState_Index struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CommitId string `protobuf:"bytes,1,opt,name=commit_id,json=commitId,proto3" json:"commit_id,omitempty"` + IndexRoot string `protobuf:"bytes,2,opt,name=index_root,json=indexRoot,proto3" json:"index_root,omitempty"` +} + +func (x *RepositoryState_Index) Reset() { + *x = RepositoryState_Index{} + if protoimpl.UnsafeEnabled { + mi := &file_cstx_proto_msgTypes[113] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RepositoryState_Index) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RepositoryState_Index) ProtoMessage() {} + +func (x *RepositoryState_Index) ProtoReflect() protoreflect.Message { + mi := &file_cstx_proto_msgTypes[113] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RepositoryState_Index.ProtoReflect.Descriptor instead. +func (*RepositoryState_Index) Descriptor() ([]byte, []int) { + return file_cstx_proto_rawDescGZIP(), []int{70, 2} +} + +func (x *RepositoryState_Index) GetCommitId() string { + if x != nil { + return x.CommitId + } + return "" +} + +func (x *RepositoryState_Index) GetIndexRoot() string { + if x != nil { + return x.IndexRoot + } + return "" +} + +var file_cstx_proto_extTypes = []protoimpl.ExtensionInfo{ + { + ExtendedType: (*descriptorpb.MessageOptions)(nil), + ExtensionType: (*CstxNodeOptions)(nil), + Field: 50000, + Name: "cstx.cstx_node", + Tag: "bytes,50000,opt,name=cstx_node", + Filename: "cstx.proto", + }, + { + ExtendedType: (*descriptorpb.MessageOptions)(nil), + ExtensionType: (*CstxRelationshipOptions)(nil), + Field: 50002, + Name: "cstx.cstx_relationship", + Tag: "bytes,50002,opt,name=cstx_relationship", + Filename: "cstx.proto", + }, + { + ExtendedType: (*descriptorpb.FieldOptions)(nil), + ExtensionType: (*CstxFieldOptions)(nil), + Field: 50001, + Name: "cstx.cstx_field", + Tag: "bytes,50001,opt,name=cstx_field", + Filename: "cstx.proto", + }, + { + ExtendedType: (*descriptorpb.EnumValueOptions)(nil), + ExtensionType: (*CstxFlagOptions)(nil), + Field: 50003, + Name: "cstx.cstx_flag", + Tag: "bytes,50003,opt,name=cstx_flag", + Filename: "cstx.proto", + }, +} + +// Extension fields to descriptorpb.MessageOptions. +var ( + // optional cstx.CstxNodeOptions cstx_node = 50000; + E_CstxNode = &file_cstx_proto_extTypes[0] + // optional cstx.CstxRelationshipOptions cstx_relationship = 50002; + E_CstxRelationship = &file_cstx_proto_extTypes[1] +) + +// Extension fields to descriptorpb.FieldOptions. +var ( + // optional cstx.CstxFieldOptions cstx_field = 50001; + E_CstxField = &file_cstx_proto_extTypes[2] +) + +// Extension fields to descriptorpb.EnumValueOptions. +var ( + // optional cstx.CstxFlagOptions cstx_flag = 50003; + E_CstxFlag = &file_cstx_proto_extTypes[3] +) + +var File_cstx_proto protoreflect.FileDescriptor + +var file_cstx_proto_rawDesc = []byte{ + 0x0a, 0x0a, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x63, 0x73, + 0x74, 0x78, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x22, 0xa3, 0x01, 0x0a, 0x0f, 0x43, 0x73, 0x74, 0x78, 0x4e, 0x6f, 0x64, 0x65, 0x4f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x66, 0x69, 0x65, + 0x6c, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x46, + 0x69, 0x65, 0x6c, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x10, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, + 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x46, 0x69, 0x65, + 0x6c, 0x64, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x22, 0x3e, 0x0a, 0x12, 0x43, 0x73, 0x74, 0x78, + 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x12, + 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x72, + 0x6f, 0x6d, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x22, 0x9f, 0x02, 0x0a, 0x10, 0x43, 0x73, 0x74, + 0x78, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1a, 0x0a, + 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x46, 0x6f, 0x72, 0x6d, + 0x61, 0x74, 0x12, 0x1f, 0x0a, 0x08, 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x08, 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, + 0x88, 0x01, 0x01, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x5f, + 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x65, 0x6d, + 0x61, 0x6e, 0x74, 0x69, 0x63, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, + 0x6c, 0x75, 0x6d, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x6f, 0x6c, 0x75, + 0x6d, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x6f, 0x72, 0x64, 0x65, + 0x72, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x32, 0x0a, 0x07, 0x63, 0x6f, 0x6d, + 0x70, 0x75, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x73, 0x74, + 0x78, 0x2e, 0x43, 0x73, 0x74, 0x78, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x4f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x42, 0x0b, 0x0a, + 0x09, 0x5f, 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x22, 0x46, 0x0a, 0x17, 0x43, 0x73, + 0x74, 0x78, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x4f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x68, 0x69, 0x70, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x10, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x54, 0x79, + 0x70, 0x65, 0x22, 0x62, 0x0a, 0x0f, 0x43, 0x73, 0x74, 0x78, 0x46, 0x6c, 0x61, 0x67, 0x4f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x03, 0x62, 0x69, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x64, 0x65, 0x66, 0x61, 0x75, + 0x6c, 0x74, 0x5f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0e, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, + 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x6e, 0x0a, 0x0d, 0x52, 0x75, 0x6e, 0x74, 0x69, 0x6d, + 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x6f, + 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, + 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x0e, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x50, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, + 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x52, 0x0e, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, + 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x22, 0x24, 0x0a, 0x0a, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0xae, 0x01, 0x0a, + 0x0b, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x14, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, + 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x18, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, + 0x12, 0x14, 0x0a, 0x04, 0x66, 0x6c, 0x61, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, + 0x52, 0x04, 0x66, 0x6c, 0x61, 0x67, 0x12, 0x14, 0x0a, 0x04, 0x72, 0x65, 0x61, 0x6c, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x01, 0x48, 0x00, 0x52, 0x04, 0x72, 0x65, 0x61, 0x6c, 0x12, 0x26, 0x0a, 0x04, + 0x6c, 0x69, 0x73, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x63, 0x73, 0x74, + 0x78, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, 0x52, 0x04, + 0x6c, 0x69, 0x73, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x55, 0x0a, + 0x0b, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1b, 0x0a, 0x09, + 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x29, 0x0a, 0x06, 0x66, 0x69, 0x65, + 0x6c, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x73, 0x74, 0x78, + 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x06, 0x66, 0x69, + 0x65, 0x6c, 0x64, 0x73, 0x22, 0x6b, 0x0a, 0x11, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x68, 0x69, 0x70, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, + 0x69, 0x70, 0x54, 0x79, 0x70, 0x65, 0x12, 0x29, 0x0a, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x45, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x52, 0x06, 0x66, 0x69, 0x65, 0x6c, 0x64, + 0x73, 0x22, 0xda, 0x01, 0x0a, 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x13, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x02, 0x69, 0x64, 0x88, 0x01, 0x01, 0x12, + 0x18, 0x0a, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x0b, 0x61, 0x6e, 0x6e, + 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x27, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1d, 0x0a, + 0x0a, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x09, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x4d, 0x61, 0x73, 0x6b, 0x42, 0x05, 0x0a, 0x03, + 0x5f, 0x69, 0x64, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x52, + 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x52, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x22, 0xf8, + 0x01, 0x0a, 0x0c, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x12, + 0x13, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x02, 0x69, + 0x64, 0x88, 0x01, 0x01, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, + 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x49, 0x64, 0x12, 0x18, + 0x0a, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x2d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x42, 0x05, 0x0a, 0x03, 0x5f, 0x69, 0x64, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x52, + 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x63, 0x0a, 0x05, 0x47, 0x72, 0x61, + 0x70, 0x68, 0x12, 0x20, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x0a, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x6e, + 0x6f, 0x64, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x0d, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x68, 0x69, 0x70, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x73, + 0x74, 0x78, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x52, + 0x0d, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x73, 0x22, 0xca, + 0x02, 0x0a, 0x0e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x65, + 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, + 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x64, 0x64, 0x65, 0x64, + 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x75, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x64, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x0e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, + 0x73, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x6e, 0x6f, 0x64, + 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x73, 0x12, 0x34, 0x0a, 0x16, 0x61, + 0x64, 0x64, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, + 0x70, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x14, 0x61, 0x64, 0x64, + 0x65, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x49, 0x64, + 0x73, 0x12, 0x38, 0x0a, 0x18, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x05, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x16, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x49, 0x64, 0x73, 0x12, 0x38, 0x0a, 0x18, 0x72, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x68, 0x69, 0x70, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x16, 0x72, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, + 0x69, 0x70, 0x49, 0x64, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x65, 0x73, 0x65, 0x74, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x72, 0x65, 0x73, 0x65, 0x74, 0x22, 0x9a, 0x02, 0x0a, 0x12, + 0x47, 0x72, 0x61, 0x70, 0x68, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, + 0x72, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x6e, 0x6f, 0x64, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x61, 0x64, 0x64, 0x65, 0x64, 0x4e, 0x6f, + 0x64, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6e, + 0x6f, 0x64, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x64, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x0c, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x2f, 0x0a, + 0x13, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x68, 0x69, 0x70, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x12, 0x61, 0x64, 0x64, 0x65, + 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x73, 0x12, 0x33, + 0x0a, 0x15, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x14, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, + 0x69, 0x70, 0x73, 0x12, 0x33, 0x0a, 0x15, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x5f, 0x72, + 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x73, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x14, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x73, 0x22, 0xe0, 0x04, 0x0a, 0x0a, 0x47, 0x72, 0x61, + 0x70, 0x68, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x45, 0x0a, 0x0d, 0x6e, 0x6f, 0x64, 0x65, 0x73, + 0x5f, 0x62, 0x79, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, + 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x74, 0x61, 0x74, 0x73, + 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x0b, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x5d, + 0x0a, 0x15, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x73, 0x5f, + 0x62, 0x79, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, + 0x63, 0x73, 0x74, 0x78, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, + 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x73, 0x42, 0x79, 0x54, + 0x79, 0x70, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x13, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x73, 0x42, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x51, 0x0a, + 0x11, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, + 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x73, 0x42, 0x79, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x0f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x42, 0x79, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x12, 0x4b, 0x0a, 0x0f, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x6b, + 0x69, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x73, 0x74, 0x78, + 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x41, 0x6e, 0x63, 0x68, + 0x6f, 0x72, 0x73, 0x42, 0x79, 0x4b, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, + 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x73, 0x42, 0x79, 0x4b, 0x69, 0x6e, 0x64, 0x1a, 0x3e, 0x0a, + 0x10, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x46, 0x0a, + 0x18, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x73, 0x42, 0x79, + 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x42, 0x0a, 0x14, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, + 0x42, 0x79, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x40, 0x0a, 0x12, 0x41, 0x6e, 0x63, + 0x68, 0x6f, 0x72, 0x73, 0x42, 0x79, 0x4b, 0x69, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xd0, 0x01, 0x0a, 0x06, + 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, + 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x33, 0x0a, 0x08, 0x6d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, + 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, + 0x2e, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, + 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x43, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x12, + 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x33, + 0x0a, 0x09, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x4c, 0x6f, 0x67, 0x12, 0x26, 0x0a, 0x07, 0x63, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x63, + 0x73, 0x74, 0x78, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x73, 0x22, 0x9d, 0x02, 0x0a, 0x0c, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x43, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x49, + 0x64, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x74, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, + 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x33, 0x0a, 0x09, 0x6f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x63, + 0x73, 0x74, 0x78, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2d, + 0x0a, 0x10, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, + 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0e, 0x62, 0x65, 0x66, 0x6f, + 0x72, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x2b, 0x0a, + 0x0f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x4f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x62, + 0x65, 0x66, 0x6f, 0x72, 0x65, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x42, + 0x12, 0x0a, 0x10, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x5f, 0x69, 0x64, 0x22, 0x3d, 0x0a, 0x0d, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x48, 0x69, 0x73, + 0x74, 0x6f, 0x72, 0x79, 0x12, 0x2c, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x45, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x73, 0x22, 0x73, 0x0a, 0x0e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x6c, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x73, 0x12, + 0x29, 0x0a, 0x10, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x5f, + 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x49, 0x64, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x6c, + 0x6c, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, + 0x6c, 0x6c, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0xe7, 0x01, 0x0a, 0x09, 0x47, 0x72, 0x61, 0x70, + 0x68, 0x44, 0x69, 0x66, 0x66, 0x12, 0x2a, 0x0a, 0x05, 0x61, 0x64, 0x64, 0x65, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x47, 0x72, 0x61, 0x70, + 0x68, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x61, 0x64, 0x64, 0x65, + 0x64, 0x12, 0x2e, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, + 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, + 0x64, 0x12, 0x30, 0x0a, 0x08, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, + 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6d, 0x6f, 0x64, 0x69, 0x66, + 0x69, 0x65, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, + 0x64, 0x12, 0x2e, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x18, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x43, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, + 0x73, 0x22, 0x6d, 0x0a, 0x0b, 0x51, 0x75, 0x65, 0x72, 0x79, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, + 0x12, 0x19, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x48, + 0x00, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x88, 0x01, 0x01, 0x12, 0x12, 0x0a, 0x04, 0x70, + 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, + 0x25, 0x0a, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, + 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x53, 0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, + 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, + 0x22, 0xc4, 0x02, 0x0a, 0x0a, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, + 0x1d, 0x0a, 0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x19, + 0x0a, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x0d, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x6e, 0x61, + 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x88, 0x01, 0x01, 0x12, 0x24, 0x0a, + 0x0e, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x41, 0x6c, 0x6c, 0x4d, + 0x61, 0x73, 0x6b, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x61, 0x6e, 0x79, + 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x66, 0x6c, 0x61, + 0x67, 0x73, 0x41, 0x6e, 0x79, 0x4d, 0x61, 0x73, 0x6b, 0x12, 0x26, 0x0a, 0x0f, 0x66, 0x6c, 0x61, + 0x67, 0x73, 0x5f, 0x6e, 0x6f, 0x6e, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x0d, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x4e, 0x6f, 0x6e, 0x65, 0x4d, 0x61, 0x73, + 0x6b, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x73, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x4a, + 0x04, 0x08, 0x07, 0x10, 0x08, 0x52, 0x09, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x61, 0x6c, 0x6c, + 0x52, 0x09, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x61, 0x6e, 0x79, 0x52, 0x0a, 0x66, 0x6c, 0x61, + 0x67, 0x73, 0x5f, 0x6e, 0x6f, 0x6e, 0x65, 0x22, 0xbd, 0x01, 0x0a, 0x12, 0x52, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x20, + 0x0a, 0x09, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x00, 0x52, 0x08, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x88, 0x01, 0x01, + 0x12, 0x20, 0x0a, 0x09, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x08, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x49, 0x64, 0x88, + 0x01, 0x01, 0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, + 0x69, 0x70, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, + 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x54, 0x79, 0x70, 0x65, + 0x73, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x74, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x22, 0x60, 0x0a, 0x09, 0x4e, 0x6f, 0x64, 0x65, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x12, 0x28, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x4e, 0x6f, 0x64, 0x65, + 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x29, + 0x0a, 0x06, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, + 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x57, 0x69, 0x6e, 0x64, 0x6f, + 0x77, 0x52, 0x06, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x22, 0x70, 0x0a, 0x11, 0x52, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x30, + 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, + 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, + 0x69, 0x70, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, + 0x12, 0x29, 0x0a, 0x06, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x11, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x57, 0x69, 0x6e, + 0x64, 0x6f, 0x77, 0x52, 0x06, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x22, 0x76, 0x0a, 0x0f, 0x47, + 0x72, 0x61, 0x70, 0x68, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x31, + 0x0a, 0x0b, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x46, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x12, 0x30, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, + 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x65, 0x78, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x64, 0x22, 0xa7, 0x01, 0x0a, 0x0c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x29, 0x0a, 0x06, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x52, 0x06, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x12, + 0x35, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x4e, 0x6f, + 0x64, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x35, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x73, 0x74, + 0x78, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x5a, 0x0a, + 0x0f, 0x4e, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, 0x65, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, + 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, + 0x28, 0x0a, 0x07, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x0e, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, 0x65, + 0x52, 0x07, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x73, 0x22, 0x82, 0x01, 0x0a, 0x0d, 0x4e, 0x65, + 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x17, 0x0a, 0x07, 0x6e, + 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, 0x6f, + 0x64, 0x65, 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x44, + 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x06, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x52, 0x06, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x22, 0x5a, + 0x0a, 0x0a, 0x47, 0x72, 0x61, 0x70, 0x68, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x1e, 0x0a, 0x0a, + 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2c, 0x0a, 0x07, + 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, + 0x63, 0x73, 0x74, 0x78, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x85, 0x01, 0x0a, 0x14, 0x4e, + 0x6f, 0x64, 0x65, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x12, 0x32, 0x0a, 0x09, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x47, 0x72, + 0x61, 0x70, 0x68, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x73, 0x65, + 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, + 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x22, 0x72, 0x0a, 0x0e, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x43, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x12, 0x32, 0x0a, 0x09, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x47, + 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x73, + 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2c, 0x0a, 0x06, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, + 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x06, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x22, 0xe6, 0x01, 0x0a, 0x0c, 0x42, 0x66, 0x73, 0x41, 0x6c, + 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x65, 0x65, 0x64, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x65, 0x64, 0x49, 0x64, + 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, 0x12, 0x2d, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x63, 0x73, 0x74, 0x78, + 0x2e, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x11, 0x6d, 0x61, 0x78, 0x5f, 0x76, 0x69, 0x73, + 0x69, 0x74, 0x65, 0x64, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, + 0x48, 0x00, 0x52, 0x0f, 0x6d, 0x61, 0x78, 0x56, 0x69, 0x73, 0x69, 0x74, 0x65, 0x64, 0x4e, 0x6f, + 0x64, 0x65, 0x73, 0x88, 0x01, 0x01, 0x12, 0x22, 0x0a, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, + 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x48, 0x01, 0x52, 0x09, 0x74, 0x69, + 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x88, 0x01, 0x01, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x6d, + 0x61, 0x78, 0x5f, 0x76, 0x69, 0x73, 0x69, 0x74, 0x65, 0x64, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, + 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x6d, 0x73, 0x22, + 0x87, 0x01, 0x0a, 0x14, 0x42, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x6e, 0x65, 0x73, 0x73, 0x41, + 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x2b, 0x0a, 0x11, 0x69, 0x6e, 0x63, 0x6c, + 0x75, 0x64, 0x65, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x10, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x45, 0x6e, 0x64, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, + 0x7a, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x6e, 0x6f, 0x72, 0x6d, 0x61, + 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x5f, 0x6b, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x04, 0x74, 0x6f, 0x70, 0x4b, 0x88, 0x01, 0x01, 0x42, + 0x08, 0x0a, 0x06, 0x5f, 0x74, 0x6f, 0x70, 0x5f, 0x6b, 0x22, 0x59, 0x0a, 0x12, 0x43, 0x6c, 0x6f, + 0x73, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, + 0x1f, 0x0a, 0x0b, 0x77, 0x66, 0x5f, 0x69, 0x6d, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x77, 0x66, 0x49, 0x6d, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x64, + 0x12, 0x18, 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x5f, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x48, + 0x00, 0x52, 0x04, 0x74, 0x6f, 0x70, 0x4b, 0x88, 0x01, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x74, + 0x6f, 0x70, 0x5f, 0x6b, 0x22, 0x83, 0x01, 0x0a, 0x0f, 0x4c, 0x65, 0x69, 0x64, 0x65, 0x6e, 0x41, + 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x73, 0x6f, + 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a, 0x72, 0x65, + 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2c, 0x0a, 0x12, 0x6d, 0x69, 0x6e, 0x5f, + 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x6d, 0x69, 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, + 0x74, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x18, 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x5f, 0x6b, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x04, 0x74, 0x6f, 0x70, 0x4b, 0x88, 0x01, 0x01, + 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x74, 0x6f, 0x70, 0x5f, 0x6b, 0x22, 0xa6, 0x02, 0x0a, 0x16, 0x53, + 0x68, 0x6f, 0x72, 0x74, 0x65, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x73, 0x41, 0x6c, 0x67, 0x6f, + 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x74, 0x61, 0x72, 0x74, 0x49, 0x64, + 0x12, 0x15, 0x0a, 0x06, 0x65, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x65, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x63, 0x73, 0x74, + 0x78, 0x2e, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x64, 0x69, 0x72, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x64, 0x65, + 0x70, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x44, 0x65, + 0x70, 0x74, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x2f, 0x0a, 0x11, 0x6d, 0x61, 0x78, + 0x5f, 0x76, 0x69, 0x73, 0x69, 0x74, 0x65, 0x64, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x0f, 0x6d, 0x61, 0x78, 0x56, 0x69, 0x73, 0x69, 0x74, + 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x88, 0x01, 0x01, 0x12, 0x22, 0x0a, 0x0a, 0x74, 0x69, + 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x48, 0x01, + 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x88, 0x01, 0x01, 0x42, 0x14, + 0x0a, 0x12, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x76, 0x69, 0x73, 0x69, 0x74, 0x65, 0x64, 0x5f, 0x6e, + 0x6f, 0x64, 0x65, 0x73, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, + 0x5f, 0x6d, 0x73, 0x22, 0xf3, 0x02, 0x0a, 0x09, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, + 0x6d, 0x12, 0x26, 0x0a, 0x03, 0x62, 0x66, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, + 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x42, 0x66, 0x73, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, + 0x68, 0x6d, 0x48, 0x00, 0x52, 0x03, 0x62, 0x66, 0x73, 0x12, 0x44, 0x0a, 0x0d, 0x70, 0x61, 0x72, + 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x1c, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, + 0x72, 0x6c, 0x65, 0x73, 0x73, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x48, 0x00, + 0x52, 0x0d, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x12, + 0x3e, 0x0a, 0x0b, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x6e, 0x65, 0x73, 0x73, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x42, 0x65, 0x74, 0x77, + 0x65, 0x65, 0x6e, 0x6e, 0x65, 0x73, 0x73, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, + 0x48, 0x00, 0x52, 0x0b, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x6e, 0x65, 0x73, 0x73, 0x12, + 0x38, 0x0a, 0x09, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x6e, + 0x65, 0x73, 0x73, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x48, 0x00, 0x52, 0x09, + 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x12, 0x2f, 0x0a, 0x06, 0x6c, 0x65, 0x69, + 0x64, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x73, 0x74, 0x78, + 0x2e, 0x4c, 0x65, 0x69, 0x64, 0x65, 0x6e, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, + 0x48, 0x00, 0x52, 0x06, 0x6c, 0x65, 0x69, 0x64, 0x65, 0x6e, 0x12, 0x45, 0x0a, 0x0e, 0x73, 0x68, + 0x6f, 0x72, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x65, + 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x73, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, + 0x48, 0x00, 0x52, 0x0d, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x65, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, + 0x73, 0x42, 0x06, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x22, 0x2e, 0x0a, 0x08, 0x4e, 0x6f, 0x64, + 0x65, 0x50, 0x61, 0x67, 0x65, 0x12, 0x22, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x4e, 0x6f, 0x64, + 0x65, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x3e, 0x0a, 0x10, 0x52, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x50, 0x61, 0x67, 0x65, 0x12, 0x2a, 0x0a, + 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, + 0x63, 0x73, 0x74, 0x78, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, + 0x70, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x51, 0x0a, 0x13, 0x43, 0x6f, 0x6d, + 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, + 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, + 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x4c, 0x0a, 0x17, + 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, + 0x68, 0x69, 0x70, 0x50, 0x61, 0x67, 0x65, 0x12, 0x31, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x43, + 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, + 0x69, 0x70, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x52, 0x0a, 0x09, 0x4e, 0x6f, + 0x64, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, + 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x72, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x38, + 0x0a, 0x0d, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x50, 0x61, 0x67, 0x65, 0x12, + 0x27, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x0f, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, + 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x44, 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, + 0x50, 0x61, 0x69, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, + 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x49, 0x64, 0x22, 0x36, + 0x0a, 0x0c, 0x4e, 0x6f, 0x64, 0x65, 0x50, 0x61, 0x69, 0x72, 0x50, 0x61, 0x67, 0x65, 0x12, 0x26, + 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, + 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x50, 0x61, 0x69, 0x72, 0x52, 0x06, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x26, 0x0a, 0x09, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x79, + 0x63, 0x6c, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x73, 0x22, 0x34, + 0x0a, 0x09, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x50, 0x61, 0x67, 0x65, 0x12, 0x27, 0x0a, 0x06, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x73, + 0x74, 0x78, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x06, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x73, 0x22, 0x25, 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x50, 0x61, 0x74, 0x68, + 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x73, 0x22, 0x32, 0x0a, 0x08, 0x50, + 0x61, 0x74, 0x68, 0x50, 0x61, 0x67, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x4e, + 0x6f, 0x64, 0x65, 0x50, 0x61, 0x74, 0x68, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, + 0x51, 0x0a, 0x13, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x4d, 0x65, 0x6d, 0x62, + 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, + 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, + 0x49, 0x64, 0x22, 0x4c, 0x0a, 0x17, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x4d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x50, 0x61, 0x67, 0x65, 0x12, 0x31, 0x0a, + 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, + 0x63, 0x73, 0x74, 0x78, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x4d, 0x65, + 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, + 0x22, 0x97, 0x01, 0x0a, 0x0c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, + 0x79, 0x12, 0x47, 0x0a, 0x0d, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x2e, 0x4e, 0x6f, 0x64, + 0x65, 0x73, 0x42, 0x79, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x6e, + 0x6f, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x79, 0x70, 0x65, 0x1a, 0x3e, 0x0a, 0x10, 0x4e, 0x6f, + 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x9d, 0x01, 0x0a, 0x10, 0x54, + 0x72, 0x61, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, + 0x1c, 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x2d, 0x0a, + 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x0f, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, + 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x09, 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x72, + 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x79, 0x0a, 0x10, 0x43, 0x6f, + 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x1c, + 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x27, 0x0a, 0x0f, + 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, + 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xd8, 0x01, 0x0a, 0x0c, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x53, + 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x2b, + 0x0a, 0x11, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, + 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x69, 0x6e, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x6e, + 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0a, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x77, + 0x66, 0x5f, 0x69, 0x6d, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0a, 0x77, 0x66, 0x49, 0x6d, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x05, + 0x74, 0x6f, 0x70, 0x5f, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x04, 0x74, + 0x6f, 0x70, 0x4b, 0x88, 0x01, 0x01, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x6a, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x74, 0x6f, 0x70, 0x5f, 0x6b, + 0x22, 0x85, 0x04, 0x0a, 0x10, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x53, 0x75, + 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x6e, 0x75, 0x6d, 0x5f, 0x63, 0x6f, 0x6d, + 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, + 0x6e, 0x75, 0x6d, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x2b, + 0x0a, 0x11, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, + 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, + 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x33, 0x0a, 0x15, 0x63, + 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x69, 0x65, 0x73, 0x5f, 0x74, 0x72, 0x75, 0x6e, 0x63, + 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x63, 0x6f, 0x6d, 0x6d, + 0x75, 0x6e, 0x69, 0x74, 0x69, 0x65, 0x73, 0x54, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x64, + 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x61, 0x72, 0x69, 0x74, 0x79, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x61, 0x72, 0x69, 0x74, 0x79, + 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x2c, 0x0a, 0x12, 0x6d, 0x69, 0x6e, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, + 0x79, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x6d, 0x69, + 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x18, + 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x5f, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, + 0x04, 0x74, 0x6f, 0x70, 0x4b, 0x88, 0x01, 0x01, 0x12, 0x53, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, + 0x75, 0x6e, 0x69, 0x74, 0x79, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, + 0x74, 0x79, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, + 0x69, 0x74, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x63, + 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x73, 0x12, 0x1e, 0x0a, + 0x0a, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, + 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x1a, 0x41, 0x0a, 0x13, 0x43, + 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x53, 0x69, 0x7a, 0x65, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x08, + 0x0a, 0x06, 0x5f, 0x74, 0x6f, 0x70, 0x5f, 0x6b, 0x22, 0xbf, 0x01, 0x0a, 0x0b, 0x50, 0x61, 0x74, + 0x68, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, + 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x6c, 0x67, + 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x74, 0x61, 0x72, 0x74, 0x49, + 0x64, 0x12, 0x15, 0x0a, 0x06, 0x65, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x65, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x63, 0x73, + 0x74, 0x78, 0x2e, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x64, + 0x65, 0x70, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x44, + 0x65, 0x70, 0x74, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0xd3, 0x06, 0x0a, 0x0f, 0x47, + 0x72, 0x61, 0x70, 0x68, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x50, 0x61, 0x67, 0x65, 0x12, 0x12, + 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x70, 0x61, + 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x68, 0x61, 0x73, 0x5f, + 0x6e, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x68, 0x61, 0x73, 0x4e, + 0x65, 0x78, 0x74, 0x12, 0x19, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x04, 0x48, 0x02, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x26, + 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, + 0x63, 0x73, 0x74, 0x78, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x50, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, + 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x3e, 0x0a, 0x0d, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, + 0x63, 0x73, 0x74, 0x78, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, + 0x70, 0x50, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x0d, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x68, 0x69, 0x70, 0x73, 0x12, 0x3f, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, + 0x65, 0x6e, 0x74, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x73, 0x74, + 0x78, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x73, 0x68, 0x69, 0x70, 0x50, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x0a, 0x63, 0x6f, 0x6d, + 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x2d, 0x0a, 0x06, 0x73, 0x63, 0x6f, 0x72, 0x65, + 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x4e, + 0x6f, 0x64, 0x65, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x50, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x06, + 0x73, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x70, 0x61, 0x69, 0x72, 0x73, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x4e, 0x6f, 0x64, + 0x65, 0x50, 0x61, 0x69, 0x72, 0x50, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x05, 0x70, 0x61, 0x69, + 0x72, 0x73, 0x12, 0x29, 0x0a, 0x06, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x50, + 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x06, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x73, 0x12, 0x26, 0x0a, + 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, + 0x73, 0x74, 0x78, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x50, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x05, + 0x70, 0x61, 0x74, 0x68, 0x73, 0x12, 0x41, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, + 0x74, 0x69, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x73, 0x74, + 0x78, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x4d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x73, 0x68, 0x69, 0x70, 0x50, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x0b, 0x63, 0x6f, 0x6d, + 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x2a, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x48, 0x01, 0x52, 0x05, 0x71, + 0x75, 0x65, 0x72, 0x79, 0x12, 0x36, 0x0a, 0x09, 0x74, 0x72, 0x61, 0x76, 0x65, 0x72, 0x73, 0x61, + 0x6c, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x54, + 0x72, 0x61, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x48, + 0x01, 0x52, 0x09, 0x74, 0x72, 0x61, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c, 0x12, 0x36, 0x0a, 0x09, + 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x16, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, + 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x48, 0x01, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6f, + 0x6e, 0x65, 0x6e, 0x74, 0x12, 0x2a, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x10, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x53, 0x63, 0x6f, 0x72, 0x65, + 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x48, 0x01, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, + 0x12, 0x36, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x18, 0x11, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x75, + 0x6e, 0x69, 0x74, 0x79, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x48, 0x01, 0x52, 0x09, 0x63, + 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x12, 0x27, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, + 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x50, 0x61, + 0x74, 0x68, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x48, 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, + 0x68, 0x42, 0x08, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x73, + 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, + 0x22, 0x7a, 0x0a, 0x0d, 0x50, 0x61, 0x72, 0x73, 0x65, 0x72, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x72, 0x74, + 0x69, 0x66, 0x61, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x72, 0x74, + 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x22, 0xa0, 0x03, 0x0a, + 0x11, 0x47, 0x72, 0x61, 0x70, 0x68, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x5f, 0x70, 0x61, + 0x72, 0x73, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x72, 0x65, 0x63, 0x6f, + 0x72, 0x64, 0x73, 0x50, 0x61, 0x72, 0x73, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x65, 0x77, + 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6e, 0x65, + 0x77, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x64, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x6e, + 0x65, 0x77, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x73, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x6e, 0x65, 0x77, 0x52, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x6f, 0x64, 0x65, + 0x5f, 0x69, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x6f, 0x64, 0x65, + 0x49, 0x64, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x43, 0x6f, 0x75, + 0x6e, 0x74, 0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, + 0x69, 0x70, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, + 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x43, 0x6f, 0x75, 0x6e, + 0x74, 0x12, 0x4c, 0x0a, 0x0d, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, + 0x47, 0x72, 0x61, 0x70, 0x68, 0x49, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x0b, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x79, 0x70, 0x65, 0x1a, + 0x3e, 0x0a, 0x10, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x79, 0x70, 0x65, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, + 0xab, 0x01, 0x0a, 0x0f, 0x47, 0x72, 0x61, 0x70, 0x68, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x65, 0x77, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6e, 0x65, 0x77, 0x4e, 0x6f, 0x64, 0x65, 0x73, + 0x12, 0x23, 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6e, 0x6f, 0x64, 0x65, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, + 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x6e, 0x65, 0x77, 0x5f, 0x72, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x10, 0x6e, 0x65, 0x77, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, + 0x70, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, + 0x69, 0x70, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x49, 0x64, 0x73, 0x22, 0x91, 0x02, + 0x0a, 0x0b, 0x47, 0x72, 0x61, 0x70, 0x68, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x12, 0x18, 0x0a, + 0x07, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x70, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x6e, 0x63, 0x68, 0x6f, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x6e, 0x63, 0x68, + 0x6f, 0x72, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x6e, 0x63, 0x68, 0x6f, + 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, + 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x49, 0x64, 0x12, + 0x36, 0x0a, 0x17, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x15, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x68, 0x69, 0x70, 0x49, 0x64, 0x12, 0x38, 0x0a, 0x18, 0x6f, 0x75, 0x74, 0x62, 0x6f, + 0x75, 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, + 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x6f, 0x75, 0x74, 0x62, 0x6f, + 0x75, 0x6e, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x49, + 0x64, 0x22, 0x41, 0x0a, 0x12, 0x47, 0x72, 0x61, 0x70, 0x68, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, + 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, 0x2b, 0x0a, 0x07, 0x61, 0x6e, 0x63, 0x68, 0x6f, + 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, + 0x47, 0x72, 0x61, 0x70, 0x68, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x52, 0x07, 0x61, 0x6e, 0x63, + 0x68, 0x6f, 0x72, 0x73, 0x22, 0xc5, 0x01, 0x0a, 0x0e, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x6c, 0x61, + 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x2c, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x4e, 0x6f, 0x64, + 0x65, 0x46, 0x6c, 0x61, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x52, + 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x64, 0x64, 0x5f, 0x6d, 0x61, 0x73, + 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x61, 0x64, 0x64, 0x4d, 0x61, 0x73, 0x6b, + 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x61, 0x73, + 0x6b, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x73, + 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, + 0x4d, 0x61, 0x73, 0x6b, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, + 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x52, 0x03, 0x61, 0x64, 0x64, 0x52, 0x06, 0x72, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x52, 0x07, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x22, 0xc3, 0x01, 0x0a, + 0x15, 0x47, 0x72, 0x61, 0x70, 0x68, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x50, 0x0a, 0x0e, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, + 0x65, 0x64, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, + 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x50, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x4e, 0x6f, 0x64, 0x65, + 0x45, 0x78, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x65, 0x78, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x75, 0x73, + 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x75, 0x73, 0x65, 0x64, + 0x1a, 0x40, 0x0a, 0x0d, 0x4e, 0x6f, 0x64, 0x65, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, + 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, + 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, + 0x6f, 0x6e, 0x22, 0x6c, 0x0a, 0x10, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, + 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2e, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x52, 0x65, 0x70, 0x6f, + 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4b, 0x69, 0x6e, 0x64, + 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, + 0x22, 0x88, 0x01, 0x0a, 0x0f, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x50, 0x6c, 0x61, 0x6e, 0x12, 0x24, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x69, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x30, 0x0a, 0x07, 0x6f, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x73, 0x74, + 0x78, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x4f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x52, 0x07, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x22, 0xf3, 0x02, 0x0a, 0x0f, + 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, + 0x36, 0x0a, 0x07, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1c, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, + 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x07, + 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x2d, 0x0a, 0x04, 0x72, 0x65, 0x66, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x52, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x66, + 0x52, 0x04, 0x72, 0x65, 0x66, 0x73, 0x12, 0x35, 0x0a, 0x07, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x65, + 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x52, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x49, + 0x6e, 0x64, 0x65, 0x78, 0x52, 0x07, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x73, 0x1a, 0x32, 0x0a, + 0x06, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, + 0x61, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x1a, 0x49, 0x0a, 0x03, 0x52, 0x65, 0x66, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x09, + 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, + 0x00, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0c, + 0x0a, 0x0a, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x69, 0x64, 0x1a, 0x43, 0x0a, 0x05, + 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x72, 0x6f, 0x6f, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x6f, 0x6f, + 0x74, 0x22, 0x30, 0x0a, 0x0f, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, + 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x49, 0x64, 0x73, 0x22, 0xdd, 0x03, 0x0a, 0x14, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, + 0x72, 0x79, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6c, 0x61, 0x6e, 0x12, 0x2c, 0x0a, 0x04, + 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x63, 0x73, 0x74, + 0x78, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x50, 0x6c, 0x61, 0x6e, + 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6f, + 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x88, + 0x01, 0x01, 0x12, 0x2c, 0x0a, 0x0f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x48, 0x01, 0x52, 0x0e, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x88, 0x01, 0x01, + 0x12, 0x28, 0x0a, 0x0d, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x48, 0x02, 0x52, 0x0c, 0x65, 0x6e, 0x64, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x65, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, + 0x08, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, + 0x04, 0x52, 0x08, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x20, + 0x0a, 0x09, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x05, 0x52, 0x08, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x49, 0x64, 0x88, 0x01, 0x01, + 0x12, 0x28, 0x0a, 0x06, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x10, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x44, 0x69, 0x66, 0x66, 0x44, 0x65, 0x74, 0x61, + 0x69, 0x6c, 0x52, 0x06, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x49, 0x64, 0x73, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x6c, 0x69, + 0x6d, 0x69, 0x74, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x65, 0x6e, 0x64, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x65, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x5f, 0x69, 0x64, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x5f, 0x69, 0x64, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x5f, 0x69, 0x64, 0x22, 0xdf, 0x01, 0x0a, 0x09, 0x52, 0x61, 0x67, 0x46, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, + 0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, + 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x72, 0x65, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, + 0x2c, 0x0a, 0x12, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, + 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x65, 0x78, 0x63, + 0x6c, 0x75, 0x64, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x4d, 0x61, 0x73, 0x6b, 0x12, 0x2c, 0x0a, + 0x12, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x6d, + 0x61, 0x73, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x69, 0x6e, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x4d, 0x61, 0x73, 0x6b, 0x4a, 0x04, 0x08, 0x03, 0x10, + 0x04, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x52, 0x0d, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, + 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x52, 0x0d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, + 0x66, 0x6c, 0x61, 0x67, 0x73, 0x22, 0xd9, 0x01, 0x0a, 0x0f, 0x52, 0x61, 0x67, 0x47, 0x72, 0x61, + 0x70, 0x68, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x63, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x64, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, + 0x49, 0x64, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6e, + 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x64, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x73, 0x12, 0x38, 0x0a, + 0x18, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x68, 0x69, 0x70, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x16, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x68, 0x69, 0x70, 0x49, 0x64, 0x73, 0x12, 0x38, 0x0a, 0x18, 0x64, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x64, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x5f, + 0x69, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x16, 0x64, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x49, 0x64, + 0x73, 0x22, 0xb9, 0x02, 0x0a, 0x09, 0x52, 0x61, 0x67, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x27, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x13, 0x2e, + 0x63, 0x73, 0x74, 0x78, 0x2e, 0x52, 0x61, 0x67, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x4b, 0x69, + 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x21, 0x0a, 0x0c, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, + 0x19, 0x0a, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x06, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, + 0x69, 0x70, 0x49, 0x64, 0x73, 0x12, 0x20, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, + 0x54, 0x79, 0x70, 0x65, 0x88, 0x01, 0x01, 0x12, 0x30, 0x0a, 0x11, 0x72, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x09, 0x48, 0x01, 0x52, 0x10, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, + 0x69, 0x70, 0x54, 0x79, 0x70, 0x65, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x6e, 0x6f, + 0x64, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x42, 0x14, 0x0a, 0x12, 0x5f, 0x72, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0xb9, 0x01, + 0x0a, 0x0e, 0x52, 0x61, 0x67, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x26, 0x0a, 0x04, 0x6d, + 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x63, 0x73, 0x74, 0x78, + 0x2e, 0x52, 0x61, 0x67, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, + 0x6f, 0x64, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x75, 0x70, 0x73, 0x65, 0x72, 0x74, 0x5f, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x75, 0x70, 0x73, 0x65, 0x72, + 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x64, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x7f, 0x0a, 0x0c, 0x52, 0x61, 0x67, + 0x49, 0x6e, 0x64, 0x65, 0x78, 0x50, 0x6c, 0x61, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, + 0x74, 0x12, 0x26, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x12, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x52, 0x61, 0x67, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x4d, + 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x2f, 0x0a, 0x07, 0x63, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x73, 0x74, + 0x78, 0x2e, 0x52, 0x61, 0x67, 0x47, 0x72, 0x61, 0x70, 0x68, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x73, 0x52, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x22, 0x7f, 0x0a, 0x0d, 0x52, 0x61, + 0x67, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x50, 0x61, 0x67, 0x65, 0x12, 0x29, 0x0a, 0x07, 0x72, + 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, + 0x73, 0x74, 0x78, 0x2e, 0x52, 0x61, 0x67, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x07, 0x72, + 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, + 0x6d, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, + 0x12, 0x19, 0x0a, 0x08, 0x68, 0x61, 0x73, 0x5f, 0x6e, 0x65, 0x78, 0x74, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x07, 0x68, 0x61, 0x73, 0x4e, 0x65, 0x78, 0x74, 0x22, 0x99, 0x01, 0x0a, 0x0b, + 0x52, 0x65, 0x63, 0x61, 0x6c, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, + 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, + 0x27, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x13, 0x2e, + 0x63, 0x73, 0x74, 0x78, 0x2e, 0x52, 0x61, 0x67, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x4b, 0x69, + 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, + 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x27, + 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, + 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x52, 0x61, 0x67, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, + 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x61, 0x0a, 0x09, 0x52, 0x65, 0x63, 0x61, 0x6c, + 0x6c, 0x48, 0x69, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x49, + 0x64, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x61, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x04, 0x72, 0x61, 0x6e, 0x6b, 0x12, 0x19, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x02, 0x48, 0x00, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x88, 0x01, 0x01, + 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x75, 0x0a, 0x15, 0x45, 0x78, + 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x71, 0x75, 0x65, 0x72, 0x79, 0x49, 0x64, 0x12, 0x1c, + 0x0a, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x04, + 0x68, 0x69, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x73, 0x74, + 0x78, 0x2e, 0x52, 0x65, 0x63, 0x61, 0x6c, 0x6c, 0x48, 0x69, 0x74, 0x52, 0x04, 0x68, 0x69, 0x74, + 0x73, 0x22, 0x46, 0x0a, 0x0d, 0x52, 0x65, 0x63, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x73, 0x12, 0x35, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x22, 0x39, 0x0a, 0x0a, 0x52, 0x65, 0x63, + 0x61, 0x6c, 0x6c, 0x50, 0x6c, 0x61, 0x6e, 0x12, 0x2b, 0x0a, 0x07, 0x71, 0x75, 0x65, 0x72, 0x69, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, + 0x52, 0x65, 0x63, 0x61, 0x6c, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x07, 0x71, 0x75, 0x65, + 0x72, 0x69, 0x65, 0x73, 0x22, 0xa7, 0x02, 0x0a, 0x09, 0x52, 0x61, 0x67, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x12, 0x13, 0x0a, 0x05, 0x72, 0x72, 0x66, 0x5f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x02, 0x52, 0x04, 0x72, 0x72, 0x66, 0x4b, 0x12, 0x31, 0x0a, 0x14, 0x63, 0x61, 0x6e, 0x64, 0x69, + 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x63, 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, + 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x61, + 0x6d, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x07, 0x64, 0x61, 0x6d, + 0x70, 0x69, 0x6e, 0x67, 0x12, 0x35, 0x0a, 0x16, 0x70, 0x72, 0x6f, 0x70, 0x61, 0x67, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x15, 0x70, 0x72, 0x6f, 0x70, 0x61, 0x67, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x49, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x6d, + 0x61, 0x78, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x64, 0x65, 0x70, 0x74, 0x68, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x0c, 0x6d, 0x61, 0x78, 0x50, 0x61, 0x74, 0x68, 0x44, 0x65, 0x70, 0x74, + 0x68, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x70, 0x73, 0x69, 0x6c, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x02, 0x52, 0x07, 0x65, 0x70, 0x73, 0x69, 0x6c, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x63, + 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x1f, 0x0a, + 0x0b, 0x75, 0x73, 0x65, 0x5f, 0x6c, 0x65, 0x78, 0x69, 0x63, 0x61, 0x6c, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0a, 0x75, 0x73, 0x65, 0x4c, 0x65, 0x78, 0x69, 0x63, 0x61, 0x6c, 0x22, 0xc5, + 0x01, 0x0a, 0x08, 0x52, 0x61, 0x67, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x74, + 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, + 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, + 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x27, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x52, 0x61, 0x67, + 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x27, + 0x0a, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, + 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x52, 0x61, 0x67, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, + 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x2a, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x78, 0x74, 0x5f, 0x62, 0x75, 0x64, 0x67, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x48, + 0x00, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x42, 0x75, 0x64, 0x67, 0x65, 0x74, + 0x88, 0x01, 0x01, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, + 0x62, 0x75, 0x64, 0x67, 0x65, 0x74, 0x22, 0x73, 0x0a, 0x0a, 0x52, 0x61, 0x6e, 0x6b, 0x65, 0x64, + 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x14, 0x0a, + 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x73, 0x63, + 0x6f, 0x72, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x70, + 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x8b, 0x01, 0x0a, 0x12, + 0x52, 0x61, 0x6e, 0x6b, 0x65, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, + 0x69, 0x70, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, + 0x69, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, + 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x72, + 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x06, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x72, 0x6f, + 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x70, + 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x65, 0x0a, 0x07, 0x52, 0x61, 0x67, + 0x50, 0x61, 0x74, 0x68, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x73, 0x12, + 0x29, 0x0a, 0x10, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x5f, + 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x49, 0x64, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, + 0x6f, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, + 0x22, 0x75, 0x0a, 0x0f, 0x52, 0x61, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, + 0x48, 0x69, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0d, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, + 0x73, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x02, + 0x52, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x6f, 0x0a, 0x0f, 0x52, 0x61, 0x67, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x78, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, + 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x1d, + 0x0a, 0x0a, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x49, 0x64, 0x73, 0x12, 0x29, 0x0a, + 0x10, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, + 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, + 0x65, 0x64, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x22, 0x50, 0x0a, 0x12, 0x45, 0x76, 0x69, 0x64, + 0x65, 0x6e, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1b, + 0x0a, 0x09, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, + 0x65, 0x63, 0x6f, 0x72, 0x64, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x09, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x49, 0x64, 0x73, 0x22, 0x9d, 0x03, 0x0a, 0x09, 0x52, + 0x61, 0x67, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x12, 0x26, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x10, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x52, 0x61, 0x6e, 0x6b, 0x65, 0x64, 0x4e, 0x6f, 0x64, + 0x65, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x3e, 0x0a, 0x0d, 0x72, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x18, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x52, 0x61, 0x6e, 0x6b, 0x65, 0x64, 0x52, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x52, 0x0d, 0x72, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x73, 0x12, 0x23, 0x0a, 0x05, 0x70, 0x61, 0x74, 0x68, + 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x52, + 0x61, 0x67, 0x50, 0x61, 0x74, 0x68, 0x52, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x12, 0x37, 0x0a, + 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x52, 0x61, 0x67, 0x43, 0x6f, 0x6d, + 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x48, 0x69, 0x74, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x75, + 0x6e, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x2f, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, + 0x74, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x52, + 0x61, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x07, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x38, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x65, + 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x73, + 0x74, 0x78, 0x2e, 0x45, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x65, + 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x63, + 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x63, + 0x6f, 0x72, 0x64, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x64, 0x72, 0x6f, 0x70, + 0x70, 0x65, 0x64, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x78, + 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, + 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xe7, 0x01, 0x0a, 0x11, 0x45, + 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, + 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x61, 0x63, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x0a, 0x65, + 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x27, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, + 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, + 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x58, 0x0a, 0x0f, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, + 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2f, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, + 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x4a, 0x04, + 0x08, 0x03, 0x10, 0x04, 0x22, 0x9d, 0x02, 0x0a, 0x13, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, + 0x6f, 0x6e, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x40, 0x0a, 0x07, 0x70, 0x61, + 0x72, 0x73, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x63, 0x73, + 0x74, 0x78, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x66, 0x69, + 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x72, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x07, 0x70, 0x61, 0x72, 0x73, 0x65, 0x72, 0x73, 0x12, 0x24, 0x0a, 0x05, + 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x73, + 0x74, 0x78, 0x2e, 0x4a, 0x6f, 0x69, 0x6e, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x72, 0x75, 0x6c, + 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x1a, 0x4c, 0x0a, 0x0c, 0x50, 0x61, + 0x72, 0x73, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x26, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x63, 0x73, + 0x74, 0x78, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x4a, 0x04, + 0x08, 0x04, 0x10, 0x05, 0x22, 0x5a, 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x19, 0x0a, 0x08, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x74, 0x79, 0x70, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x33, 0x0a, 0x08, 0x6d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x22, 0x62, 0x0a, 0x10, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x75, 0x72, 0x6c, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x79, 0x70, 0x65, 0x55, 0x72, 0x6c, 0x12, + 0x33, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x22, 0x99, 0x01, 0x0a, 0x0a, 0x50, 0x61, 0x72, 0x73, 0x65, 0x72, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, + 0x3a, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0b, + 0x69, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x33, 0x0a, 0x08, 0x6d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x22, 0xdd, 0x02, 0x0a, 0x08, 0x4a, 0x6f, 0x69, 0x6e, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x22, 0x0a, + 0x0d, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6c, 0x65, 0x66, 0x74, 0x54, 0x79, 0x70, 0x65, 0x55, 0x72, + 0x6c, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, + 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x69, 0x67, 0x68, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x32, 0x0a, 0x15, 0x72, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x75, 0x72, 0x6c, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x68, 0x69, 0x70, 0x54, 0x79, 0x70, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x6c, + 0x65, 0x66, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6c, + 0x65, 0x66, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x69, 0x67, 0x68, 0x74, 0x5f, + 0x6b, 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x69, 0x67, 0x68, 0x74, + 0x4b, 0x65, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x72, 0x65, 0x64, 0x69, 0x63, 0x74, 0x65, 0x64, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x70, 0x72, 0x65, 0x64, 0x69, 0x63, 0x74, 0x65, + 0x64, 0x12, 0x29, 0x0a, 0x0e, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x6c, 0x65, 0x66, + 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x2b, 0x0a, 0x0f, + 0x72, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x53, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x6c, 0x65, + 0x66, 0x74, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x42, 0x12, 0x0a, 0x10, + 0x5f, 0x72, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, + 0x22, 0x89, 0x01, 0x0a, 0x0d, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x6e, + 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1c, + 0x0a, 0x09, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x09, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x22, 0x47, 0x0a, 0x10, + 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, + 0x12, 0x33, 0x0a, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x45, 0x78, 0x74, 0x65, + 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x42, 0x0a, 0x0d, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x43, + 0x6f, 0x6e, 0x63, 0x65, 0x70, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x6f, + 0x64, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, + 0x6e, 0x6f, 0x64, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0x47, 0x0a, 0x14, 0x41, 0x6e, 0x63, + 0x68, 0x6f, 0x72, 0x43, 0x6f, 0x6e, 0x63, 0x65, 0x70, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, + 0x67, 0x12, 0x2f, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x70, 0x74, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x41, 0x6e, 0x63, 0x68, 0x6f, + 0x72, 0x43, 0x6f, 0x6e, 0x63, 0x65, 0x70, 0x74, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x70, + 0x74, 0x73, 0x2a, 0x8b, 0x01, 0x0a, 0x0f, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x1c, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, + 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, + 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x48, 0x41, 0x4e, + 0x47, 0x45, 0x5f, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x44, 0x44, + 0x45, 0x44, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x4f, + 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x44, + 0x10, 0x02, 0x12, 0x1c, 0x0a, 0x18, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x4f, 0x50, 0x45, + 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x44, 0x10, 0x03, + 0x2a, 0x56, 0x0a, 0x09, 0x53, 0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x1a, 0x0a, + 0x16, 0x53, 0x4f, 0x52, 0x54, 0x5f, 0x4f, 0x52, 0x44, 0x45, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, + 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x4f, 0x52, + 0x54, 0x5f, 0x4f, 0x52, 0x44, 0x45, 0x52, 0x5f, 0x49, 0x44, 0x5f, 0x41, 0x53, 0x43, 0x10, 0x01, + 0x12, 0x16, 0x0a, 0x12, 0x53, 0x4f, 0x52, 0x54, 0x5f, 0x4f, 0x52, 0x44, 0x45, 0x52, 0x5f, 0x49, + 0x44, 0x5f, 0x44, 0x45, 0x53, 0x43, 0x10, 0x02, 0x2a, 0x5f, 0x0a, 0x09, 0x44, 0x69, 0x72, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x49, + 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, + 0x12, 0x11, 0x0a, 0x0d, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4f, 0x55, + 0x54, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, + 0x5f, 0x49, 0x4e, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x49, + 0x4f, 0x4e, 0x5f, 0x42, 0x4f, 0x54, 0x48, 0x10, 0x03, 0x2a, 0xc9, 0x02, 0x0a, 0x16, 0x50, 0x61, + 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x6c, 0x65, 0x73, 0x73, 0x41, 0x6c, 0x67, 0x6f, 0x72, + 0x69, 0x74, 0x68, 0x6d, 0x12, 0x27, 0x0a, 0x23, 0x50, 0x41, 0x52, 0x41, 0x4d, 0x45, 0x54, 0x45, + 0x52, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x41, 0x4c, 0x47, 0x4f, 0x52, 0x49, 0x54, 0x48, 0x4d, 0x5f, + 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, + 0x1d, 0x50, 0x41, 0x52, 0x41, 0x4d, 0x45, 0x54, 0x45, 0x52, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x57, + 0x45, 0x41, 0x4b, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x4e, 0x45, 0x4e, 0x54, 0x53, 0x10, 0x01, + 0x12, 0x23, 0x0a, 0x1f, 0x50, 0x41, 0x52, 0x41, 0x4d, 0x45, 0x54, 0x45, 0x52, 0x4c, 0x45, 0x53, + 0x53, 0x5f, 0x53, 0x54, 0x52, 0x4f, 0x4e, 0x47, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4f, 0x4e, 0x45, + 0x4e, 0x54, 0x53, 0x10, 0x02, 0x12, 0x1d, 0x0a, 0x19, 0x50, 0x41, 0x52, 0x41, 0x4d, 0x45, 0x54, + 0x45, 0x52, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x43, 0x59, 0x43, 0x4c, 0x45, 0x5f, 0x42, 0x41, 0x53, + 0x49, 0x53, 0x10, 0x03, 0x12, 0x19, 0x0a, 0x15, 0x50, 0x41, 0x52, 0x41, 0x4d, 0x45, 0x54, 0x45, + 0x52, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x42, 0x52, 0x49, 0x44, 0x47, 0x45, 0x53, 0x10, 0x04, 0x12, + 0x25, 0x0a, 0x21, 0x50, 0x41, 0x52, 0x41, 0x4d, 0x45, 0x54, 0x45, 0x52, 0x4c, 0x45, 0x53, 0x53, + 0x5f, 0x41, 0x52, 0x54, 0x49, 0x43, 0x55, 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x4f, + 0x49, 0x4e, 0x54, 0x53, 0x10, 0x05, 0x12, 0x1e, 0x0a, 0x1a, 0x50, 0x41, 0x52, 0x41, 0x4d, 0x45, + 0x54, 0x45, 0x52, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x43, 0x4f, 0x52, 0x45, 0x5f, 0x4e, 0x55, 0x4d, + 0x42, 0x45, 0x52, 0x53, 0x10, 0x06, 0x12, 0x18, 0x0a, 0x14, 0x50, 0x41, 0x52, 0x41, 0x4d, 0x45, + 0x54, 0x45, 0x52, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x49, 0x53, 0x5f, 0x44, 0x41, 0x47, 0x10, 0x07, + 0x12, 0x23, 0x0a, 0x1f, 0x50, 0x41, 0x52, 0x41, 0x4d, 0x45, 0x54, 0x45, 0x52, 0x4c, 0x45, 0x53, + 0x53, 0x5f, 0x54, 0x4f, 0x50, 0x4f, 0x4c, 0x4f, 0x47, 0x49, 0x43, 0x41, 0x4c, 0x5f, 0x4f, 0x52, + 0x44, 0x45, 0x52, 0x10, 0x08, 0x2a, 0x70, 0x0a, 0x12, 0x4e, 0x6f, 0x64, 0x65, 0x46, 0x6c, 0x61, + 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x20, 0x0a, 0x1c, 0x4e, + 0x4f, 0x44, 0x45, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, + 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1a, 0x0a, + 0x16, 0x4e, 0x4f, 0x44, 0x45, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, + 0x45, 0x5f, 0x4d, 0x45, 0x52, 0x47, 0x45, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x4e, 0x4f, 0x44, + 0x45, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x52, 0x45, + 0x50, 0x4c, 0x41, 0x43, 0x45, 0x10, 0x02, 0x2a, 0xfd, 0x01, 0x0a, 0x0a, 0x4f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x1b, 0x0a, 0x17, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, + 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x5f, 0x4b, 0x49, + 0x4e, 0x44, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x42, 0x4a, + 0x45, 0x43, 0x54, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x10, 0x02, 0x12, + 0x15, 0x0a, 0x11, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, + 0x45, 0x52, 0x47, 0x45, 0x10, 0x03, 0x12, 0x15, 0x0a, 0x11, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, + 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x44, 0x45, 0x4c, 0x54, 0x41, 0x10, 0x04, 0x12, 0x17, 0x0a, + 0x13, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x50, 0x52, 0x45, + 0x50, 0x41, 0x52, 0x45, 0x10, 0x05, 0x12, 0x17, 0x0a, 0x13, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, + 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x48, 0x49, 0x53, 0x54, 0x4f, 0x52, 0x59, 0x10, 0x06, 0x12, + 0x17, 0x0a, 0x13, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x43, + 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x53, 0x10, 0x07, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x42, 0x4a, 0x45, + 0x43, 0x54, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x44, 0x49, 0x46, 0x46, 0x10, 0x08, 0x12, 0x17, + 0x0a, 0x13, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x43, 0x4c, + 0x4f, 0x53, 0x55, 0x52, 0x45, 0x10, 0x09, 0x2a, 0xc5, 0x01, 0x0a, 0x14, 0x52, 0x65, 0x70, 0x6f, + 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4b, 0x69, 0x6e, 0x64, + 0x12, 0x26, 0x0a, 0x22, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x4f, + 0x42, 0x4a, 0x45, 0x43, 0x54, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, + 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1f, 0x0a, 0x1b, 0x52, 0x45, 0x50, 0x4f, + 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x5f, 0x4b, 0x49, + 0x4e, 0x44, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x10, 0x01, 0x12, 0x21, 0x0a, 0x1d, 0x52, 0x45, 0x50, + 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x5f, 0x4b, + 0x49, 0x4e, 0x44, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x02, 0x12, 0x20, 0x0a, 0x1c, + 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x4f, 0x42, 0x4a, 0x45, 0x43, + 0x54, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x10, 0x03, 0x12, 0x1f, + 0x0a, 0x1b, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x4f, 0x42, 0x4a, + 0x45, 0x43, 0x54, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x42, 0x4c, 0x4f, 0x42, 0x10, 0x04, 0x2a, + 0xcb, 0x02, 0x0a, 0x12, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x50, 0x6c, + 0x61, 0x6e, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x1f, 0x0a, 0x1b, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, + 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x50, 0x4c, 0x41, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, + 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x52, 0x45, 0x50, 0x4f, 0x53, + 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x50, 0x4c, 0x41, 0x4e, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x10, + 0x01, 0x12, 0x18, 0x0a, 0x14, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, + 0x50, 0x4c, 0x41, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x10, 0x02, 0x12, 0x1b, 0x0a, 0x17, 0x52, + 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x50, 0x4c, 0x41, 0x4e, 0x5f, 0x50, + 0x52, 0x45, 0x50, 0x41, 0x52, 0x45, 0x10, 0x03, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x45, 0x50, 0x4f, + 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x50, 0x4c, 0x41, 0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, + 0x49, 0x54, 0x53, 0x10, 0x04, 0x12, 0x19, 0x0a, 0x15, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, + 0x4f, 0x52, 0x59, 0x5f, 0x50, 0x4c, 0x41, 0x4e, 0x5f, 0x44, 0x45, 0x4c, 0x54, 0x41, 0x10, 0x05, + 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x50, + 0x4c, 0x41, 0x4e, 0x5f, 0x43, 0x4c, 0x4f, 0x53, 0x55, 0x52, 0x45, 0x10, 0x06, 0x12, 0x1b, 0x0a, + 0x17, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x50, 0x4c, 0x41, 0x4e, + 0x5f, 0x48, 0x49, 0x53, 0x54, 0x4f, 0x52, 0x59, 0x10, 0x07, 0x12, 0x19, 0x0a, 0x15, 0x52, 0x45, + 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x50, 0x4c, 0x41, 0x4e, 0x5f, 0x4d, 0x45, + 0x52, 0x47, 0x45, 0x10, 0x08, 0x12, 0x18, 0x0a, 0x14, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, + 0x4f, 0x52, 0x59, 0x5f, 0x50, 0x4c, 0x41, 0x4e, 0x5f, 0x44, 0x49, 0x46, 0x46, 0x10, 0x09, 0x12, + 0x1c, 0x0a, 0x18, 0x52, 0x45, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x4f, 0x52, 0x59, 0x5f, 0x50, 0x4c, + 0x41, 0x4e, 0x5f, 0x45, 0x4e, 0x54, 0x49, 0x54, 0x49, 0x45, 0x53, 0x10, 0x0a, 0x2a, 0x5b, 0x0a, + 0x0a, 0x44, 0x69, 0x66, 0x66, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x12, 0x1b, 0x0a, 0x17, 0x44, + 0x49, 0x46, 0x46, 0x5f, 0x44, 0x45, 0x54, 0x41, 0x49, 0x4c, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, + 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x44, 0x49, 0x46, 0x46, + 0x5f, 0x44, 0x45, 0x54, 0x41, 0x49, 0x4c, 0x5f, 0x45, 0x4e, 0x54, 0x49, 0x54, 0x49, 0x45, 0x53, + 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x49, 0x46, 0x46, 0x5f, 0x44, 0x45, 0x54, 0x41, 0x49, + 0x4c, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x53, 0x10, 0x02, 0x2a, 0x62, 0x0a, 0x0d, 0x52, 0x61, + 0x67, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x1f, 0x0a, 0x1b, 0x52, + 0x41, 0x47, 0x5f, 0x52, 0x45, 0x43, 0x4f, 0x52, 0x44, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, + 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, + 0x52, 0x41, 0x47, 0x5f, 0x52, 0x45, 0x43, 0x4f, 0x52, 0x44, 0x5f, 0x4e, 0x4f, 0x44, 0x45, 0x10, + 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x41, 0x47, 0x5f, 0x52, 0x45, 0x43, 0x4f, 0x52, 0x44, 0x5f, + 0x52, 0x45, 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x48, 0x49, 0x50, 0x10, 0x02, 0x2a, 0x5d, + 0x0a, 0x0c, 0x52, 0x61, 0x67, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1e, + 0x0a, 0x1a, 0x52, 0x41, 0x47, 0x5f, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x5f, 0x4d, 0x4f, 0x44, 0x45, + 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x19, + 0x0a, 0x15, 0x52, 0x41, 0x47, 0x5f, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x5f, 0x49, 0x4e, 0x43, 0x52, + 0x45, 0x4d, 0x45, 0x4e, 0x54, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x52, 0x41, 0x47, + 0x5f, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x5f, 0x46, 0x55, 0x4c, 0x4c, 0x10, 0x02, 0x3a, 0x55, 0x0a, + 0x09, 0x63, 0x73, 0x74, 0x78, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xd0, 0x86, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x43, 0x73, 0x74, 0x78, 0x4e, + 0x6f, 0x64, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x08, 0x63, 0x73, 0x74, 0x78, + 0x4e, 0x6f, 0x64, 0x65, 0x3a, 0x6d, 0x0a, 0x11, 0x63, 0x73, 0x74, 0x78, 0x5f, 0x72, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xd2, 0x86, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x43, 0x73, 0x74, 0x78, 0x52, 0x65, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x68, 0x69, 0x70, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x52, 0x10, 0x63, 0x73, 0x74, 0x78, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x68, 0x69, 0x70, 0x3a, 0x56, 0x0a, 0x0a, 0x63, 0x73, 0x74, 0x78, 0x5f, 0x66, 0x69, 0x65, 0x6c, + 0x64, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x18, 0xd1, 0x86, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, + 0x43, 0x73, 0x74, 0x78, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x52, 0x09, 0x63, 0x73, 0x74, 0x78, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x3a, 0x57, 0x0a, 0x09, 0x63, + 0x73, 0x74, 0x78, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x12, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xd3, 0x86, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x73, 0x74, 0x78, 0x2e, 0x43, 0x73, 0x74, 0x78, 0x46, + 0x6c, 0x61, 0x67, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x08, 0x63, 0x73, 0x74, 0x78, + 0x46, 0x6c, 0x61, 0x67, 0x42, 0x3f, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x72, 0x65, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x73, + 0x2f, 0x6c, 0x69, 0x62, 0x63, 0x73, 0x74, 0x78, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2f, 0x63, 0x73, 0x74, 0x78, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3b, 0x63, 0x73, 0x74, 0x78, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_cstx_proto_rawDescOnce sync.Once + file_cstx_proto_rawDescData = file_cstx_proto_rawDesc +) + +func file_cstx_proto_rawDescGZIP() []byte { + file_cstx_proto_rawDescOnce.Do(func() { + file_cstx_proto_rawDescData = protoimpl.X.CompressGZIP(file_cstx_proto_rawDescData) + }) + return file_cstx_proto_rawDescData +} + +var file_cstx_proto_enumTypes = make([]protoimpl.EnumInfo, 11) +var file_cstx_proto_msgTypes = make([]protoimpl.MessageInfo, 116) +var file_cstx_proto_goTypes = []interface{}{ + (ChangeOperation)(0), // 0: cstx.ChangeOperation + (SortOrder)(0), // 1: cstx.SortOrder + (Direction)(0), // 2: cstx.Direction + (ParameterlessAlgorithm)(0), // 3: cstx.ParameterlessAlgorithm + (NodeFlagUpdateMode)(0), // 4: cstx.NodeFlagUpdateMode + (ObjectKind)(0), // 5: cstx.ObjectKind + (RepositoryObjectKind)(0), // 6: cstx.RepositoryObjectKind + (RepositoryPlanKind)(0), // 7: cstx.RepositoryPlanKind + (DiffDetail)(0), // 8: cstx.DiffDetail + (RagRecordKind)(0), // 9: cstx.RagRecordKind + (RagIndexMode)(0), // 10: cstx.RagIndexMode + (*CstxNodeOptions)(nil), // 11: cstx.CstxNodeOptions + (*CstxComputeOptions)(nil), // 12: cstx.CstxComputeOptions + (*CstxFieldOptions)(nil), // 13: cstx.CstxFieldOptions + (*CstxRelationshipOptions)(nil), // 14: cstx.CstxRelationshipOptions + (*CstxFlagOptions)(nil), // 15: cstx.CstxFlagOptions + (*RuntimeConfig)(nil), // 16: cstx.RuntimeConfig + (*StringList)(nil), // 17: cstx.StringList + (*EntityField)(nil), // 18: cstx.EntityField + (*EntityValue)(nil), // 19: cstx.EntityValue + (*RelationshipValue)(nil), // 20: cstx.RelationshipValue + (*Node)(nil), // 21: cstx.Node + (*Relationship)(nil), // 22: cstx.Relationship + (*Graph)(nil), // 23: cstx.Graph + (*GraphChangeSet)(nil), // 24: cstx.GraphChangeSet + (*GraphChangeSummary)(nil), // 25: cstx.GraphChangeSummary + (*GraphStats)(nil), // 26: cstx.GraphStats + (*Commit)(nil), // 27: cstx.Commit + (*CommitLog)(nil), // 28: cstx.CommitLog + (*EntityChange)(nil), // 29: cstx.EntityChange + (*EntityHistory)(nil), // 30: cstx.EntityHistory + (*GraphSelection)(nil), // 31: cstx.GraphSelection + (*GraphDiff)(nil), // 32: cstx.GraphDiff + (*QueryWindow)(nil), // 33: cstx.QueryWindow + (*NodeFilter)(nil), // 34: cstx.NodeFilter + (*RelationshipFilter)(nil), // 35: cstx.RelationshipFilter + (*NodeQuery)(nil), // 36: cstx.NodeQuery + (*RelationshipQuery)(nil), // 37: cstx.RelationshipQuery + (*GraphProjection)(nil), // 38: cstx.GraphProjection + (*QueryOptions)(nil), // 39: cstx.QueryOptions + (*NodeTypeCatalog)(nil), // 40: cstx.NodeTypeCatalog + (*NeighborQuery)(nil), // 41: cstx.NeighborQuery + (*GraphQuery)(nil), // 42: cstx.GraphQuery + (*NodeAnnotationUpdate)(nil), // 43: cstx.NodeAnnotationUpdate + (*NodeFlagChange)(nil), // 44: cstx.NodeFlagChange + (*BfsAlgorithm)(nil), // 45: cstx.BfsAlgorithm + (*BetweennessAlgorithm)(nil), // 46: cstx.BetweennessAlgorithm + (*ClosenessAlgorithm)(nil), // 47: cstx.ClosenessAlgorithm + (*LeidenAlgorithm)(nil), // 48: cstx.LeidenAlgorithm + (*ShortestPathsAlgorithm)(nil), // 49: cstx.ShortestPathsAlgorithm + (*Algorithm)(nil), // 50: cstx.Algorithm + (*NodePage)(nil), // 51: cstx.NodePage + (*RelationshipPage)(nil), // 52: cstx.RelationshipPage + (*ComponentMembership)(nil), // 53: cstx.ComponentMembership + (*ComponentMembershipPage)(nil), // 54: cstx.ComponentMembershipPage + (*NodeScore)(nil), // 55: cstx.NodeScore + (*NodeScorePage)(nil), // 56: cstx.NodeScorePage + (*NodePair)(nil), // 57: cstx.NodePair + (*NodePairPage)(nil), // 58: cstx.NodePairPage + (*NodeCycle)(nil), // 59: cstx.NodeCycle + (*CyclePage)(nil), // 60: cstx.CyclePage + (*NodePath)(nil), // 61: cstx.NodePath + (*PathPage)(nil), // 62: cstx.PathPage + (*CommunityMembership)(nil), // 63: cstx.CommunityMembership + (*CommunityMembershipPage)(nil), // 64: cstx.CommunityMembershipPage + (*QuerySummary)(nil), // 65: cstx.QuerySummary + (*TraversalSummary)(nil), // 66: cstx.TraversalSummary + (*ComponentSummary)(nil), // 67: cstx.ComponentSummary + (*ScoreSummary)(nil), // 68: cstx.ScoreSummary + (*CommunitySummary)(nil), // 69: cstx.CommunitySummary + (*PathSummary)(nil), // 70: cstx.PathSummary + (*GraphResultPage)(nil), // 71: cstx.GraphResultPage + (*ParserPayload)(nil), // 72: cstx.ParserPayload + (*GraphIngestResult)(nil), // 73: cstx.GraphIngestResult + (*GraphLinkResult)(nil), // 74: cstx.GraphLinkResult + (*GraphAnchor)(nil), // 75: cstx.GraphAnchor + (*GraphAnchorCatalog)(nil), // 76: cstx.GraphAnchorCatalog + (*NodeFlagUpdate)(nil), // 77: cstx.NodeFlagUpdate + (*GraphProjectionReport)(nil), // 78: cstx.GraphProjectionReport + (*RepositoryObject)(nil), // 79: cstx.RepositoryObject + (*PublicationPlan)(nil), // 80: cstx.PublicationPlan + (*RepositoryState)(nil), // 81: cstx.RepositoryState + (*ObjectSelection)(nil), // 82: cstx.ObjectSelection + (*RepositoryObjectPlan)(nil), // 83: cstx.RepositoryObjectPlan + (*RagFilter)(nil), // 84: cstx.RagFilter + (*RagGraphChanges)(nil), // 85: cstx.RagGraphChanges + (*RagRecord)(nil), // 86: cstx.RagRecord + (*RagIndexResult)(nil), // 87: cstx.RagIndexResult + (*RagIndexPlan)(nil), // 88: cstx.RagIndexPlan + (*RagRecordPage)(nil), // 89: cstx.RagRecordPage + (*RecallQuery)(nil), // 90: cstx.RecallQuery + (*RecallHit)(nil), // 91: cstx.RecallHit + (*ExtensionRecallResult)(nil), // 92: cstx.ExtensionRecallResult + (*RecallResults)(nil), // 93: cstx.RecallResults + (*RecallPlan)(nil), // 94: cstx.RecallPlan + (*RagPolicy)(nil), // 95: cstx.RagPolicy + (*RagQuery)(nil), // 96: cstx.RagQuery + (*RankedNode)(nil), // 97: cstx.RankedNode + (*RankedRelationship)(nil), // 98: cstx.RankedRelationship + (*RagPath)(nil), // 99: cstx.RagPath + (*RagCommunityHit)(nil), // 100: cstx.RagCommunityHit + (*RagContextBlock)(nil), // 101: cstx.RagContextBlock + (*EvidenceProvenance)(nil), // 102: cstx.EvidenceProvenance + (*RagResult)(nil), // 103: cstx.RagResult + (*ExtensionContract)(nil), // 104: cstx.ExtensionContract + (*ExtensionDefinition)(nil), // 105: cstx.ExtensionDefinition + (*NodeType)(nil), // 106: cstx.NodeType + (*RelationshipType)(nil), // 107: cstx.RelationshipType + (*ParserType)(nil), // 108: cstx.ParserType + (*JoinRule)(nil), // 109: cstx.JoinRule + (*ExtensionInfo)(nil), // 110: cstx.ExtensionInfo + (*ExtensionCatalog)(nil), // 111: cstx.ExtensionCatalog + (*AnchorConcept)(nil), // 112: cstx.AnchorConcept + (*AnchorConceptCatalog)(nil), // 113: cstx.AnchorConceptCatalog + nil, // 114: cstx.GraphStats.NodesByTypeEntry + nil, // 115: cstx.GraphStats.RelationshipsByTypeEntry + nil, // 116: cstx.GraphStats.ObjectsBySourceEntry + nil, // 117: cstx.GraphStats.AnchorsByKindEntry + nil, // 118: cstx.QuerySummary.NodesByTypeEntry + nil, // 119: cstx.CommunitySummary.CommunitySizesEntry + nil, // 120: cstx.GraphIngestResult.NodesByTypeEntry + (*GraphProjectionReport_NodeExclusion)(nil), // 121: cstx.GraphProjectionReport.NodeExclusion + (*RepositoryState_Object)(nil), // 122: cstx.RepositoryState.Object + (*RepositoryState_Ref)(nil), // 123: cstx.RepositoryState.Ref + (*RepositoryState_Index)(nil), // 124: cstx.RepositoryState.Index + nil, // 125: cstx.ExtensionContract.ExtensionsEntry + nil, // 126: cstx.ExtensionDefinition.ParsersEntry + (*structpb.Struct)(nil), // 127: google.protobuf.Struct + (*descriptorpb.MessageOptions)(nil), // 128: google.protobuf.MessageOptions + (*descriptorpb.FieldOptions)(nil), // 129: google.protobuf.FieldOptions + (*descriptorpb.EnumValueOptions)(nil), // 130: google.protobuf.EnumValueOptions +} +var file_cstx_proto_depIdxs = []int32{ + 12, // 0: cstx.CstxFieldOptions.compute:type_name -> cstx.CstxComputeOptions + 17, // 1: cstx.EntityField.list:type_name -> cstx.StringList + 18, // 2: cstx.EntityValue.fields:type_name -> cstx.EntityField + 18, // 3: cstx.RelationshipValue.fields:type_name -> cstx.EntityField + 127, // 4: cstx.Node.annotations:type_name -> google.protobuf.Struct + 19, // 5: cstx.Node.value:type_name -> cstx.EntityValue + 127, // 6: cstx.Relationship.annotations:type_name -> google.protobuf.Struct + 20, // 7: cstx.Relationship.value:type_name -> cstx.RelationshipValue + 21, // 8: cstx.Graph.nodes:type_name -> cstx.Node + 22, // 9: cstx.Graph.relationships:type_name -> cstx.Relationship + 114, // 10: cstx.GraphStats.nodes_by_type:type_name -> cstx.GraphStats.NodesByTypeEntry + 115, // 11: cstx.GraphStats.relationships_by_type:type_name -> cstx.GraphStats.RelationshipsByTypeEntry + 116, // 12: cstx.GraphStats.objects_by_source:type_name -> cstx.GraphStats.ObjectsBySourceEntry + 117, // 13: cstx.GraphStats.anchors_by_kind:type_name -> cstx.GraphStats.AnchorsByKindEntry + 127, // 14: cstx.Commit.metadata:type_name -> google.protobuf.Struct + 25, // 15: cstx.Commit.stats:type_name -> cstx.GraphChangeSummary + 27, // 16: cstx.CommitLog.commits:type_name -> cstx.Commit + 0, // 17: cstx.EntityChange.operation:type_name -> cstx.ChangeOperation + 29, // 18: cstx.EntityHistory.changes:type_name -> cstx.EntityChange + 31, // 19: cstx.GraphDiff.added:type_name -> cstx.GraphSelection + 31, // 20: cstx.GraphDiff.removed:type_name -> cstx.GraphSelection + 31, // 21: cstx.GraphDiff.modified:type_name -> cstx.GraphSelection + 25, // 22: cstx.GraphDiff.stats:type_name -> cstx.GraphChangeSummary + 1, // 23: cstx.QueryWindow.order:type_name -> cstx.SortOrder + 34, // 24: cstx.NodeQuery.filter:type_name -> cstx.NodeFilter + 33, // 25: cstx.NodeQuery.window:type_name -> cstx.QueryWindow + 35, // 26: cstx.RelationshipQuery.filter:type_name -> cstx.RelationshipFilter + 33, // 27: cstx.RelationshipQuery.window:type_name -> cstx.QueryWindow + 34, // 28: cstx.GraphProjection.node_filter:type_name -> cstx.NodeFilter + 31, // 29: cstx.GraphProjection.excluded:type_name -> cstx.GraphSelection + 33, // 30: cstx.QueryOptions.window:type_name -> cstx.QueryWindow + 34, // 31: cstx.QueryOptions.result_filter:type_name -> cstx.NodeFilter + 38, // 32: cstx.QueryOptions.projection:type_name -> cstx.GraphProjection + 106, // 33: cstx.NodeTypeCatalog.schemas:type_name -> cstx.NodeType + 2, // 34: cstx.NeighborQuery.direction:type_name -> cstx.Direction + 33, // 35: cstx.NeighborQuery.window:type_name -> cstx.QueryWindow + 39, // 36: cstx.GraphQuery.options:type_name -> cstx.QueryOptions + 31, // 37: cstx.NodeAnnotationUpdate.selection:type_name -> cstx.GraphSelection + 127, // 38: cstx.NodeAnnotationUpdate.annotations:type_name -> google.protobuf.Struct + 31, // 39: cstx.NodeFlagChange.selection:type_name -> cstx.GraphSelection + 77, // 40: cstx.NodeFlagChange.update:type_name -> cstx.NodeFlagUpdate + 2, // 41: cstx.BfsAlgorithm.direction:type_name -> cstx.Direction + 2, // 42: cstx.ShortestPathsAlgorithm.direction:type_name -> cstx.Direction + 45, // 43: cstx.Algorithm.bfs:type_name -> cstx.BfsAlgorithm + 3, // 44: cstx.Algorithm.parameterless:type_name -> cstx.ParameterlessAlgorithm + 46, // 45: cstx.Algorithm.betweenness:type_name -> cstx.BetweennessAlgorithm + 47, // 46: cstx.Algorithm.closeness:type_name -> cstx.ClosenessAlgorithm + 48, // 47: cstx.Algorithm.leiden:type_name -> cstx.LeidenAlgorithm + 49, // 48: cstx.Algorithm.shortest_paths:type_name -> cstx.ShortestPathsAlgorithm + 21, // 49: cstx.NodePage.values:type_name -> cstx.Node + 22, // 50: cstx.RelationshipPage.values:type_name -> cstx.Relationship + 53, // 51: cstx.ComponentMembershipPage.values:type_name -> cstx.ComponentMembership + 55, // 52: cstx.NodeScorePage.values:type_name -> cstx.NodeScore + 57, // 53: cstx.NodePairPage.values:type_name -> cstx.NodePair + 59, // 54: cstx.CyclePage.values:type_name -> cstx.NodeCycle + 61, // 55: cstx.PathPage.values:type_name -> cstx.NodePath + 63, // 56: cstx.CommunityMembershipPage.values:type_name -> cstx.CommunityMembership + 118, // 57: cstx.QuerySummary.nodes_by_type:type_name -> cstx.QuerySummary.NodesByTypeEntry + 2, // 58: cstx.TraversalSummary.direction:type_name -> cstx.Direction + 119, // 59: cstx.CommunitySummary.community_sizes:type_name -> cstx.CommunitySummary.CommunitySizesEntry + 2, // 60: cstx.PathSummary.direction:type_name -> cstx.Direction + 51, // 61: cstx.GraphResultPage.nodes:type_name -> cstx.NodePage + 52, // 62: cstx.GraphResultPage.relationships:type_name -> cstx.RelationshipPage + 54, // 63: cstx.GraphResultPage.components:type_name -> cstx.ComponentMembershipPage + 56, // 64: cstx.GraphResultPage.scores:type_name -> cstx.NodeScorePage + 58, // 65: cstx.GraphResultPage.pairs:type_name -> cstx.NodePairPage + 60, // 66: cstx.GraphResultPage.cycles:type_name -> cstx.CyclePage + 62, // 67: cstx.GraphResultPage.paths:type_name -> cstx.PathPage + 64, // 68: cstx.GraphResultPage.communities:type_name -> cstx.CommunityMembershipPage + 65, // 69: cstx.GraphResultPage.query:type_name -> cstx.QuerySummary + 66, // 70: cstx.GraphResultPage.traversal:type_name -> cstx.TraversalSummary + 67, // 71: cstx.GraphResultPage.component:type_name -> cstx.ComponentSummary + 68, // 72: cstx.GraphResultPage.score:type_name -> cstx.ScoreSummary + 69, // 73: cstx.GraphResultPage.community:type_name -> cstx.CommunitySummary + 70, // 74: cstx.GraphResultPage.path:type_name -> cstx.PathSummary + 120, // 75: cstx.GraphIngestResult.nodes_by_type:type_name -> cstx.GraphIngestResult.NodesByTypeEntry + 75, // 76: cstx.GraphAnchorCatalog.anchors:type_name -> cstx.GraphAnchor + 4, // 77: cstx.NodeFlagUpdate.mode:type_name -> cstx.NodeFlagUpdateMode + 121, // 78: cstx.GraphProjectionReport.excluded_nodes:type_name -> cstx.GraphProjectionReport.NodeExclusion + 6, // 79: cstx.RepositoryObject.kind:type_name -> cstx.RepositoryObjectKind + 27, // 80: cstx.PublicationPlan.commit:type_name -> cstx.Commit + 79, // 81: cstx.PublicationPlan.objects:type_name -> cstx.RepositoryObject + 122, // 82: cstx.RepositoryState.objects:type_name -> cstx.RepositoryState.Object + 123, // 83: cstx.RepositoryState.refs:type_name -> cstx.RepositoryState.Ref + 124, // 84: cstx.RepositoryState.indexes:type_name -> cstx.RepositoryState.Index + 7, // 85: cstx.RepositoryObjectPlan.kind:type_name -> cstx.RepositoryPlanKind + 8, // 86: cstx.RepositoryObjectPlan.detail:type_name -> cstx.DiffDetail + 9, // 87: cstx.RagRecord.kind:type_name -> cstx.RagRecordKind + 10, // 88: cstx.RagIndexResult.mode:type_name -> cstx.RagIndexMode + 10, // 89: cstx.RagIndexPlan.mode:type_name -> cstx.RagIndexMode + 85, // 90: cstx.RagIndexPlan.changes:type_name -> cstx.RagGraphChanges + 86, // 91: cstx.RagRecordPage.records:type_name -> cstx.RagRecord + 9, // 92: cstx.RecallQuery.kind:type_name -> cstx.RagRecordKind + 84, // 93: cstx.RecallQuery.filter:type_name -> cstx.RagFilter + 91, // 94: cstx.ExtensionRecallResult.hits:type_name -> cstx.RecallHit + 92, // 95: cstx.RecallResults.results:type_name -> cstx.ExtensionRecallResult + 90, // 96: cstx.RecallPlan.queries:type_name -> cstx.RecallQuery + 84, // 97: cstx.RagQuery.filter:type_name -> cstx.RagFilter + 95, // 98: cstx.RagQuery.policy:type_name -> cstx.RagPolicy + 97, // 99: cstx.RagResult.nodes:type_name -> cstx.RankedNode + 98, // 100: cstx.RagResult.relationships:type_name -> cstx.RankedRelationship + 99, // 101: cstx.RagResult.paths:type_name -> cstx.RagPath + 100, // 102: cstx.RagResult.communities:type_name -> cstx.RagCommunityHit + 101, // 103: cstx.RagResult.context:type_name -> cstx.RagContextBlock + 102, // 104: cstx.RagResult.provenance:type_name -> cstx.EvidenceProvenance + 125, // 105: cstx.ExtensionContract.extensions:type_name -> cstx.ExtensionContract.ExtensionsEntry + 126, // 106: cstx.ExtensionDefinition.parsers:type_name -> cstx.ExtensionDefinition.ParsersEntry + 109, // 107: cstx.ExtensionDefinition.rules:type_name -> cstx.JoinRule + 127, // 108: cstx.NodeType.metadata:type_name -> google.protobuf.Struct + 127, // 109: cstx.RelationshipType.metadata:type_name -> google.protobuf.Struct + 127, // 110: cstx.ParserType.input_schema:type_name -> google.protobuf.Struct + 127, // 111: cstx.ParserType.metadata:type_name -> google.protobuf.Struct + 110, // 112: cstx.ExtensionCatalog.extensions:type_name -> cstx.ExtensionInfo + 112, // 113: cstx.AnchorConceptCatalog.concepts:type_name -> cstx.AnchorConcept + 105, // 114: cstx.ExtensionContract.ExtensionsEntry.value:type_name -> cstx.ExtensionDefinition + 108, // 115: cstx.ExtensionDefinition.ParsersEntry.value:type_name -> cstx.ParserType + 128, // 116: cstx.cstx_node:extendee -> google.protobuf.MessageOptions + 128, // 117: cstx.cstx_relationship:extendee -> google.protobuf.MessageOptions + 129, // 118: cstx.cstx_field:extendee -> google.protobuf.FieldOptions + 130, // 119: cstx.cstx_flag:extendee -> google.protobuf.EnumValueOptions + 11, // 120: cstx.cstx_node:type_name -> cstx.CstxNodeOptions + 14, // 121: cstx.cstx_relationship:type_name -> cstx.CstxRelationshipOptions + 13, // 122: cstx.cstx_field:type_name -> cstx.CstxFieldOptions + 15, // 123: cstx.cstx_flag:type_name -> cstx.CstxFlagOptions + 124, // [124:124] is the sub-list for method output_type + 124, // [124:124] is the sub-list for method input_type + 120, // [120:124] is the sub-list for extension type_name + 116, // [116:120] is the sub-list for extension extendee + 0, // [0:116] is the sub-list for field type_name +} + +func init() { file_cstx_proto_init() } +func file_cstx_proto_init() { + if File_cstx_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_cstx_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CstxNodeOptions); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CstxComputeOptions); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CstxFieldOptions); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CstxRelationshipOptions); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CstxFlagOptions); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RuntimeConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StringList); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EntityField); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EntityValue); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RelationshipValue); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Node); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Relationship); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Graph); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GraphChangeSet); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GraphChangeSummary); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GraphStats); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Commit); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CommitLog); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EntityChange); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EntityHistory); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GraphSelection); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GraphDiff); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryWindow); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodeFilter); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RelationshipFilter); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodeQuery); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RelationshipQuery); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GraphProjection); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryOptions); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodeTypeCatalog); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NeighborQuery); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GraphQuery); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodeAnnotationUpdate); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodeFlagChange); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BfsAlgorithm); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BetweennessAlgorithm); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ClosenessAlgorithm); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LeidenAlgorithm); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ShortestPathsAlgorithm); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Algorithm); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodePage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RelationshipPage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ComponentMembership); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ComponentMembershipPage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodeScore); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodeScorePage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodePair); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodePairPage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodeCycle); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CyclePage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodePath); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PathPage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CommunityMembership); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CommunityMembershipPage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QuerySummary); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TraversalSummary); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ComponentSummary); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ScoreSummary); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CommunitySummary); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PathSummary); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[60].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GraphResultPage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[61].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ParserPayload); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[62].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GraphIngestResult); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[63].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GraphLinkResult); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GraphAnchor); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[65].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GraphAnchorCatalog); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[66].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodeFlagUpdate); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[67].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GraphProjectionReport); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[68].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RepositoryObject); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[69].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PublicationPlan); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[70].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RepositoryState); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[71].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ObjectSelection); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[72].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RepositoryObjectPlan); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[73].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RagFilter); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[74].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RagGraphChanges); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[75].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RagRecord); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[76].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RagIndexResult); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[77].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RagIndexPlan); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[78].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RagRecordPage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[79].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RecallQuery); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[80].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RecallHit); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[81].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExtensionRecallResult); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[82].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RecallResults); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[83].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RecallPlan); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[84].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RagPolicy); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[85].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RagQuery); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[86].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RankedNode); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[87].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RankedRelationship); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[88].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RagPath); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[89].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RagCommunityHit); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[90].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RagContextBlock); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[91].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EvidenceProvenance); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[92].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RagResult); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[93].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExtensionContract); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[94].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExtensionDefinition); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[95].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NodeType); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[96].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RelationshipType); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[97].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ParserType); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[98].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*JoinRule); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[99].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExtensionInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[100].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExtensionCatalog); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[101].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AnchorConcept); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[102].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AnchorConceptCatalog); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[110].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GraphProjectionReport_NodeExclusion); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[111].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RepositoryState_Object); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[112].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RepositoryState_Ref); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cstx_proto_msgTypes[113].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RepositoryState_Index); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_cstx_proto_msgTypes[2].OneofWrappers = []interface{}{} + file_cstx_proto_msgTypes[7].OneofWrappers = []interface{}{ + (*EntityField_Text)(nil), + (*EntityField_Number)(nil), + (*EntityField_Flag)(nil), + (*EntityField_Real)(nil), + (*EntityField_List)(nil), + } + file_cstx_proto_msgTypes[10].OneofWrappers = []interface{}{} + file_cstx_proto_msgTypes[11].OneofWrappers = []interface{}{} + file_cstx_proto_msgTypes[18].OneofWrappers = []interface{}{} + file_cstx_proto_msgTypes[22].OneofWrappers = []interface{}{} + file_cstx_proto_msgTypes[23].OneofWrappers = []interface{}{} + file_cstx_proto_msgTypes[24].OneofWrappers = []interface{}{} + file_cstx_proto_msgTypes[34].OneofWrappers = []interface{}{} + file_cstx_proto_msgTypes[35].OneofWrappers = []interface{}{} + file_cstx_proto_msgTypes[36].OneofWrappers = []interface{}{} + file_cstx_proto_msgTypes[37].OneofWrappers = []interface{}{} + file_cstx_proto_msgTypes[38].OneofWrappers = []interface{}{} + file_cstx_proto_msgTypes[39].OneofWrappers = []interface{}{ + (*Algorithm_Bfs)(nil), + (*Algorithm_Parameterless)(nil), + (*Algorithm_Betweenness)(nil), + (*Algorithm_Closeness)(nil), + (*Algorithm_Leiden)(nil), + (*Algorithm_ShortestPaths)(nil), + } + file_cstx_proto_msgTypes[57].OneofWrappers = []interface{}{} + file_cstx_proto_msgTypes[58].OneofWrappers = []interface{}{} + file_cstx_proto_msgTypes[60].OneofWrappers = []interface{}{ + (*GraphResultPage_Nodes)(nil), + (*GraphResultPage_Relationships)(nil), + (*GraphResultPage_Components)(nil), + (*GraphResultPage_Scores)(nil), + (*GraphResultPage_Pairs)(nil), + (*GraphResultPage_Cycles)(nil), + (*GraphResultPage_Paths)(nil), + (*GraphResultPage_Communities)(nil), + (*GraphResultPage_Query)(nil), + (*GraphResultPage_Traversal)(nil), + (*GraphResultPage_Component)(nil), + (*GraphResultPage_Score)(nil), + (*GraphResultPage_Community)(nil), + (*GraphResultPage_Path)(nil), + } + file_cstx_proto_msgTypes[72].OneofWrappers = []interface{}{} + file_cstx_proto_msgTypes[75].OneofWrappers = []interface{}{} + file_cstx_proto_msgTypes[80].OneofWrappers = []interface{}{} + file_cstx_proto_msgTypes[85].OneofWrappers = []interface{}{} + file_cstx_proto_msgTypes[98].OneofWrappers = []interface{}{} + file_cstx_proto_msgTypes[112].OneofWrappers = []interface{}{} + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_cstx_proto_rawDesc, + NumEnums: 11, + NumMessages: 116, + NumExtensions: 4, + NumServices: 0, + }, + GoTypes: file_cstx_proto_goTypes, + DependencyIndexes: file_cstx_proto_depIdxs, + EnumInfos: file_cstx_proto_enumTypes, + MessageInfos: file_cstx_proto_msgTypes, + ExtensionInfos: file_cstx_proto_extTypes, + }.Build() + File_cstx_proto = out.File + file_cstx_proto_rawDesc = nil + file_cstx_proto_goTypes = nil + file_cstx_proto_depIdxs = nil +} diff --git a/go/proto/cstxproto/cstxproto_test.go b/go/proto/cstxproto/cstxproto_test.go new file mode 100644 index 0000000..be7dd36 --- /dev/null +++ b/go/proto/cstxproto/cstxproto_test.go @@ -0,0 +1,48 @@ +package cstxproto + +import ( + "testing" + + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/known/structpb" +) + +func TestRetiredPayloadSurfaceIsAbsent(t *testing.T) { + if File_cstx_proto.Enums().ByName(protoreflect.Name("PayloadFormat")) != nil { + t.Fatal("PayloadFormat is still present") + } + for message, field := range map[protoreflect.MessageDescriptor]protoreflect.Name{ + (&RuntimeConfig{}).ProtoReflect().Descriptor(): "payload_format", + (&Node{}).ProtoReflect().Descriptor(): "entity", + (&Relationship{}).ProtoReflect().Descriptor(): "relation", + } { + if message.Fields().ByName(field) != nil { + t.Fatalf("%s.%s is still present", message.Name(), field) + } + } +} + +func TestNodeRoundTrip(t *testing.T) { + extras, err := structpb.NewStruct(map[string]any{"source": "test"}) + if err != nil { + t.Fatal(err) + } + payload := &EntityValue{ + NodeType: "ip", + Fields: []*EntityField{{Name: "ip", Value: &EntityField_Text{Text: "1.1.1.1"}}}, + } + id := "ip:one" + want := &Node{Id: &id, Value: payload, Annotations: extras} + wire, err := proto.Marshal(want) + if err != nil { + t.Fatal(err) + } + var got Node + if err := proto.Unmarshal(wire, &got); err != nil { + t.Fatal(err) + } + if !proto.Equal(want, &got) { + t.Fatalf("round-trip changed node: %v", &got) + } +} diff --git a/go/proto_native.go b/go/proto_native.go new file mode 100644 index 0000000..8de1d73 --- /dev/null +++ b/go/proto_native.go @@ -0,0 +1,109 @@ +package cstx + +// The native adapter transports only generated protobuf messages across the +// C ABI. It intentionally contains no SDK-owned graph or repository models. + +/* +#include "cstx_ffi.h" +*/ +import "C" + +import ( + "context" + "fmt" + "runtime" + + "github.com/chainreactors/libcstx/go/proto/cstxproto" + "google.golang.org/protobuf/proto" +) + +func (e *nativeEngine) graphAddNodesWire(_ context.Context, graph *cstxproto.Graph) (uint64, error) { + payload, err := proto.Marshal(graph) + if err != nil { + return 0, err + } + return countResult("graph.add_nodes", func(out *C.uint64_t, errBuf *C.CstxBuffer) C.CstxStatusCode { + rc := C.cstx_graph_add_nodes(e.handle, byteSlice(payload), out, errBuf) + runtime.KeepAlive(payload) + return rc + }) +} + +func (e *nativeEngine) graphReplaceNodesWire(_ context.Context, graph *cstxproto.Graph) (uint64, error) { + payload, err := proto.Marshal(graph) + if err != nil { + return 0, err + } + return countResult("graph.replace_nodes", func(out *C.uint64_t, errBuf *C.CstxBuffer) C.CstxStatusCode { + rc := C.cstx_graph_replace_nodes(e.handle, byteSlice(payload), out, errBuf) + runtime.KeepAlive(payload) + return rc + }) +} + +func (e *nativeEngine) graphAddRelationshipsWire(_ context.Context, graph *cstxproto.Graph) (uint64, error) { + payload, err := proto.Marshal(graph) + if err != nil { + return 0, err + } + return countResult("graph.add_relationships", func(out *C.uint64_t, errBuf *C.CstxBuffer) C.CstxStatusCode { + rc := C.cstx_graph_add_relationships(e.handle, byteSlice(payload), out, errBuf) + runtime.KeepAlive(payload) + return rc + }) +} + +func (e *nativeEngine) graphAddRelationshipWire(_ context.Context, relationship *cstxproto.Relationship) (cstxproto.Relationship, error) { + if relationship == nil { + return cstxproto.Relationship{}, &Error{Code: CodeInvalidArgument, Operation: "graph.add_relationship", Message: "relationship must not be nil"} + } + payload, err := proto.Marshal(relationship) + if err != nil { + return cstxproto.Relationship{}, err + } + data, err := bufferResult("graph.add_relationship", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { + rc := C.cstx_graph_add_relationship(e.handle, byteSlice(payload), out, errBuf) + runtime.KeepAlive(payload) + return rc + }) + if err != nil { + return cstxproto.Relationship{}, err + } + var stored cstxproto.Relationship + if err := proto.Unmarshal(data, &stored); err != nil { + return cstxproto.Relationship{}, fmt.Errorf("cstx: decode relationship protobuf: %w", err) + } + return stored, nil +} + +func (e *nativeEngine) graphNodeWire(_ context.Context, nodeID string) (cstxproto.Node, error) { + data, err := bufferResult("graph.node", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { + rc := C.cstx_graph_node(e.handle, stringSlice(nodeID), out, errBuf) + runtime.KeepAlive(nodeID) + return rc + }) + if err != nil { + return cstxproto.Node{}, err + } + var node cstxproto.Node + if err := proto.Unmarshal(data, &node); err != nil { + return cstxproto.Node{}, fmt.Errorf("cstx: decode node protobuf: %w", err) + } + return node, nil +} + +func (e *nativeEngine) graphRelationshipWire(_ context.Context, relationshipID string) (cstxproto.Relationship, error) { + data, err := bufferResult("graph.relationship", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { + rc := C.cstx_graph_relationship(e.handle, stringSlice(relationshipID), out, errBuf) + runtime.KeepAlive(relationshipID) + return rc + }) + if err != nil { + return cstxproto.Relationship{}, err + } + var relationship cstxproto.Relationship + if err := proto.Unmarshal(data, &relationship); err != nil { + return cstxproto.Relationship{}, fmt.Errorf("cstx: decode relationship protobuf: %w", err) + } + return relationship, nil +} diff --git a/go/raw.go b/go/raw.go deleted file mode 100644 index 9a24549..0000000 --- a/go/raw.go +++ /dev/null @@ -1,243 +0,0 @@ -package cstx - -import ( - "context" - "encoding/json" - "runtime" - "sync" -) - -// Raw exposes advanced native operations without duplicating Rust DTOs in Go. -// Payloads use the JSON shapes documented by the C ABI. -type Raw struct{ eng rawEngine } - -type rawEngine interface { - rawSchemaRegisterJoinRule(context.Context, []byte) error - rawSchemaAnchorConcepts(context.Context) ([]byte, error) - rawGraphIngestNative(context.Context, string, string, []byte) ([]byte, error) - rawGraphAddNodes(context.Context, []byte) (uint64, error) - rawGraphAddEdges(context.Context, []byte) (uint64, error) - rawGraphFindNode(context.Context, string) ([]byte, error) - rawGraphNodeTypes(context.Context) ([]byte, error) - rawGraphNodesPage(context.Context, []byte) ([]byte, error) - rawGraphLink(context.Context, []byte, string) ([]byte, error) - rawRAGIndex(context.Context, []byte) (rawRAGIndexSession, error) - rawRAGRetrieve(context.Context, []byte) (rawRAGRetrieval, error) -} - -type rawRAGIndexSession interface { - metadata(context.Context) ([]byte, error) - pending(context.Context, int, int) ([]byte, error) - deletes(context.Context) ([]byte, error) - close() -} - -type rawRAGRetrieval interface { - requests(context.Context) ([]byte, error) - complete(context.Context, []byte) ([]byte, error) - close() -} - -func rawContext(ctx context.Context) error { return contextError(ctx) } - -// RegisterJoinRule registers one linker rule encoded as JSON. -func (r *Raw) RegisterJoinRule(ctx context.Context, request json.RawMessage) error { - if err := rawContext(ctx); err != nil { - return err - } - return r.eng.rawSchemaRegisterJoinRule(ctx, request) -} - -// AnchorConcepts returns native concept tuples as JSON. -func (r *Raw) AnchorConcepts(ctx context.Context) (json.RawMessage, error) { - if err := rawContext(ctx); err != nil { - return nil, err - } - return r.eng.rawSchemaAnchorConcepts(ctx) -} - -// IngestNative invokes a linked native plugin and returns mutation details as JSON. -func (r *Raw) IngestNative(ctx context.Context, plugin, artifact string, data []byte) (json.RawMessage, error) { - if err := rawContext(ctx); err != nil { - return nil, err - } - return r.eng.rawGraphIngestNative(ctx, plugin, artifact, data) -} - -// AddNodes submits the CSTX JSON node array without Go DTO conversion. -func (r *Raw) AddNodes(ctx context.Context, nodes json.RawMessage) (uint64, error) { - if err := rawContext(ctx); err != nil { - return 0, err - } - return r.eng.rawGraphAddNodes(ctx, nodes) -} - -// AddEdges submits the CSTX JSON edge array without Go DTO conversion. -func (r *Raw) AddEdges(ctx context.Context, edges json.RawMessage) (uint64, error) { - if err := rawContext(ctx); err != nil { - return 0, err - } - return r.eng.rawGraphAddEdges(ctx, edges) -} - -// FindNode returns a node or JSON null. -func (r *Raw) FindNode(ctx context.Context, identifier string) (json.RawMessage, error) { - if err := rawContext(ctx); err != nil { - return nil, err - } - return r.eng.rawGraphFindNode(ctx, identifier) -} - -// NodeTypes returns registered graph node types as JSON. -func (r *Raw) NodeTypes(ctx context.Context) (json.RawMessage, error) { - if err := rawContext(ctx); err != nil { - return nil, err - } - return r.eng.rawGraphNodeTypes(ctx) -} - -// NodesPage executes the raw node-page request and returns its JSON response. -func (r *Raw) NodesPage(ctx context.Context, request json.RawMessage) (json.RawMessage, error) { - if err := rawContext(ctx); err != nil { - return nil, err - } - return r.eng.rawGraphNodesPage(ctx, request) -} - -// Link runs native linker rules for the selected node IDs and returns the -// linker result as JSON. -func (r *Raw) Link(ctx context.Context, nodeIDs json.RawMessage, dataSource string) (json.RawMessage, error) { - if err := rawContext(ctx); err != nil { - return nil, err - } - return r.eng.rawGraphLink(ctx, nodeIDs, dataSource) -} - -// RAGIndex opens an opaque native projection session from a JSON request. -func (r *Raw) RAGIndex(ctx context.Context, request json.RawMessage) (*RawRAGIndexSession, error) { - if err := rawContext(ctx); err != nil { - return nil, err - } - inner, err := r.eng.rawRAGIndex(ctx, request) - if err != nil { - return nil, err - } - session := &RawRAGIndexSession{inner: inner} - runtime.SetFinalizer(session, (*RawRAGIndexSession).finalize) - return session, nil -} - -// RAGRetrieve opens an opaque native retrieval from a JSON query. -func (r *Raw) RAGRetrieve(ctx context.Context, query json.RawMessage) (*RawRAGRetrieval, error) { - if err := rawContext(ctx); err != nil { - return nil, err - } - inner, err := r.eng.rawRAGRetrieve(ctx, query) - if err != nil { - return nil, err - } - retrieval := &RawRAGRetrieval{inner: inner} - runtime.SetFinalizer(retrieval, (*RawRAGRetrieval).finalize) - return retrieval, nil -} - -// RawRAGIndexSession is an opaque native index-session handle. -type RawRAGIndexSession struct { - mu sync.Mutex - inner rawRAGIndexSession - closed bool -} - -func (s *RawRAGIndexSession) use(ctx context.Context, call func(rawRAGIndexSession) ([]byte, error)) (json.RawMessage, error) { - if err := rawContext(ctx); err != nil { - return nil, err - } - s.mu.Lock() - defer s.mu.Unlock() - if s.closed { - return nil, &Error{Code: CodeNotInitialized, Operation: "rag.index", Message: "RAG index session is closed"} - } - return call(s.inner) -} - -// Metadata returns operation, commit, mode, and counts as JSON. -func (s *RawRAGIndexSession) Metadata(ctx context.Context) (json.RawMessage, error) { - return s.use(ctx, func(inner rawRAGIndexSession) ([]byte, error) { return inner.metadata(ctx) }) -} - -// Pending returns one page of projected records as JSON. -func (s *RawRAGIndexSession) Pending(ctx context.Context, offset, limit int) (json.RawMessage, error) { - return s.use(ctx, func(inner rawRAGIndexSession) ([]byte, error) { return inner.pending(ctx, offset, limit) }) -} - -// Deletes returns projected deletion IDs as JSON. -func (s *RawRAGIndexSession) Deletes(ctx context.Context) (json.RawMessage, error) { - return s.use(ctx, func(inner rawRAGIndexSession) ([]byte, error) { return inner.deletes(ctx) }) -} - -// Close releases the native index session. Repeated calls are safe. -func (s *RawRAGIndexSession) Close() error { - s.mu.Lock() - defer s.mu.Unlock() - if !s.closed { - s.inner.close() - s.closed = true - runtime.SetFinalizer(s, nil) - } - return nil -} -func (s *RawRAGIndexSession) finalize() { _ = s.Close() } - -// RawRAGRetrieval is an opaque native retrieval handle that completes once. -type RawRAGRetrieval struct { - mu sync.Mutex - inner rawRAGRetrieval - closed, completed bool -} - -// Requests returns external recall requests as JSON. -func (r *RawRAGRetrieval) Requests(ctx context.Context) (json.RawMessage, error) { - if err := rawContext(ctx); err != nil { - return nil, err - } - r.mu.Lock() - defer r.mu.Unlock() - if r.closed || r.completed { - return nil, &Error{Code: CodeNotInitialized, Operation: "rag.retrieve.requests", Message: "RAG retrieval is closed or completed"} - } - return r.inner.requests(ctx) -} - -// Complete submits recall batches as JSON and returns the Rust-computed result. -func (r *RawRAGRetrieval) Complete(ctx context.Context, batches json.RawMessage) (json.RawMessage, error) { - if err := rawContext(ctx); err != nil { - return nil, err - } - r.mu.Lock() - defer r.mu.Unlock() - if r.closed { - return nil, &Error{Code: CodeNotInitialized, Operation: "rag.retrieve.complete", Message: "RAG retrieval is closed"} - } - if r.completed { - return nil, &Error{Code: CodeConflict, Operation: "rag.retrieve.complete", Message: "RAG retrieval is already completed"} - } - result, err := r.inner.complete(ctx, batches) - if err == nil { - r.completed = true - runtime.SetFinalizer(r, nil) - } - return result, err -} - -// Close releases an incomplete retrieval. Repeated calls are safe. -func (r *RawRAGRetrieval) Close() error { - r.mu.Lock() - defer r.mu.Unlock() - if !r.closed && !r.completed { - r.inner.close() - } - r.closed = true - runtime.SetFinalizer(r, nil) - return nil -} -func (r *RawRAGRetrieval) finalize() { _ = r.Close() } diff --git a/go/raw_native.go b/go/raw_native.go deleted file mode 100644 index 67ced24..0000000 --- a/go/raw_native.go +++ /dev/null @@ -1,168 +0,0 @@ -package cstx - -/* -#include "cstx_ffi.h" -*/ -import "C" - -import ( - "context" - "runtime" -) - -func (e *nativeEngine) rawSchemaRegisterJoinRule(_ context.Context, request []byte) error { - return statusCall("schemas.register_join_rule", func(errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_schema_register_join_rule(e.handle, byteSlice(request), errBuf) - runtime.KeepAlive(request) - return rc - }) -} - -func (e *nativeEngine) rawSchemaAnchorConcepts(_ context.Context) ([]byte, error) { - return bufferResult("schemas.anchor_concepts", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - return C.cstx_schema_anchor_concepts_json(e.handle, out, errBuf) - }) -} - -func (e *nativeEngine) rawGraphIngestNative(_ context.Context, plugin, artifact string, data []byte) ([]byte, error) { - return bufferResult("graph.ingest_native", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_graph_ingest_native_json(e.handle, stringSlice(plugin), stringSlice(artifact), byteSlice(data), out, errBuf) - runtime.KeepAlive(plugin) - runtime.KeepAlive(artifact) - runtime.KeepAlive(data) - return rc - }) -} - -func (e *nativeEngine) rawGraphAddNodes(_ context.Context, nodes []byte) (uint64, error) { - return countResult("graph.add_nodes_json", func(out *C.uint64_t, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_graph_add_nodes(e.handle, byteSlice(nodes), out, errBuf) - runtime.KeepAlive(nodes) - return rc - }) -} - -func (e *nativeEngine) rawGraphAddEdges(_ context.Context, edges []byte) (uint64, error) { - return countResult("graph.add_edges_json", func(out *C.uint64_t, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_graph_add_edges(e.handle, byteSlice(edges), out, errBuf) - runtime.KeepAlive(edges) - return rc - }) -} - -func (e *nativeEngine) rawGraphFindNode(_ context.Context, identifier string) ([]byte, error) { - return bufferResult("graph.find_node", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_graph_find_node_json(e.handle, stringSlice(identifier), out, errBuf) - runtime.KeepAlive(identifier) - return rc - }) -} - -func (e *nativeEngine) rawGraphNodeTypes(_ context.Context) ([]byte, error) { - return bufferResult("graph.node_types", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - return C.cstx_graph_node_types_json(e.handle, out, errBuf) - }) -} - -func (e *nativeEngine) rawGraphNodesPage(_ context.Context, request []byte) ([]byte, error) { - return bufferResult("graph.nodes_page", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_graph_nodes_page_json(e.handle, byteSlice(request), out, errBuf) - runtime.KeepAlive(request) - return rc - }) -} - -func (e *nativeEngine) rawGraphLink(_ context.Context, nodeIDs []byte, dataSource string) ([]byte, error) { - return bufferResult("graph.link", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_graph_link_json(e.handle, byteSlice(nodeIDs), stringSlice(dataSource), out, errBuf) - runtime.KeepAlive(nodeIDs) - runtime.KeepAlive(dataSource) - return rc - }) -} - -type nativeRawRAGIndexSession struct{ handle *C.CstxRagIndexSession } - -func (e *nativeEngine) rawRAGIndex(_ context.Context, request []byte) (rawRAGIndexSession, error) { - var handle *C.CstxRagIndexSession - err := statusCall("rag.index", func(errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_rag_index(e.handle, byteSlice(request), &handle, errBuf) - runtime.KeepAlive(request) - return rc - }) - if err != nil { - return nil, err - } - return &nativeRawRAGIndexSession{handle: handle}, nil -} - -func (s *nativeRawRAGIndexSession) metadata(_ context.Context) ([]byte, error) { - return bufferResult("rag.index.metadata", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - return C.cstx_rag_index_session_metadata_json(s.handle, out, errBuf) - }) -} - -func (s *nativeRawRAGIndexSession) pending(_ context.Context, offset, limit int) ([]byte, error) { - if offset < 0 || limit < 0 { - return nil, &Error{Code: CodeInvalidArgument, Operation: "rag.index.pending", Message: "offset and limit must be non-negative"} - } - return bufferResult("rag.index.pending", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - return C.cstx_rag_index_session_pending_json(s.handle, C.size_t(offset), C.size_t(limit), out, errBuf) - }) -} - -func (s *nativeRawRAGIndexSession) deletes(_ context.Context) ([]byte, error) { - return bufferResult("rag.index.deletes", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - return C.cstx_rag_index_session_deletes_json(s.handle, out, errBuf) - }) -} - -func (s *nativeRawRAGIndexSession) close() { - if s.handle != nil { - C.cstx_rag_index_session_close(s.handle) - C.cstx_rag_index_session_free(s.handle) - s.handle = nil - } -} - -type nativeRawRAGRetrieval struct{ handle *C.CstxRagRetrieval } - -func (e *nativeEngine) rawRAGRetrieve(_ context.Context, query []byte) (rawRAGRetrieval, error) { - var handle *C.CstxRagRetrieval - err := statusCall("rag.retrieve", func(errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_rag_retrieve(e.handle, byteSlice(query), &handle, errBuf) - runtime.KeepAlive(query) - return rc - }) - if err != nil { - return nil, err - } - return &nativeRawRAGRetrieval{handle: handle}, nil -} - -func (r *nativeRawRAGRetrieval) requests(_ context.Context) ([]byte, error) { - return bufferResult("rag.retrieve.requests", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - return C.cstx_rag_retrieval_requests_json(r.handle, out, errBuf) - }) -} - -func (r *nativeRawRAGRetrieval) complete(_ context.Context, batches []byte) ([]byte, error) { - result, err := bufferResult("rag.retrieve.complete", func(out, errBuf *C.CstxBuffer) C.CstxStatusCode { - rc := C.cstx_rag_retrieval_complete_json(r.handle, byteSlice(batches), out, errBuf) - runtime.KeepAlive(batches) - return rc - }) - if err == nil { - C.cstx_rag_retrieval_free(r.handle) - r.handle = nil - } - return result, err -} - -func (r *nativeRawRAGRetrieval) close() { - if r.handle != nil { - C.cstx_rag_retrieval_close(r.handle) - C.cstx_rag_retrieval_free(r.handle) - r.handle = nil - } -} diff --git a/go/raw_native_test.go b/go/raw_native_test.go deleted file mode 100644 index 156435e..0000000 --- a/go/raw_native_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package cstx - -import ( - "encoding/json" - "testing" -) - -func TestRawRAGCanDisableLexicalRecall(t *testing.T) { - rt := openRuntime(t) - addDomain(t, rt, "example.com") - payload := json.RawMessage(`{ - "text":"example domain", - "limit":5, - "filters":{"node_types":[],"relation_types":[],"exclude_flags":0,"include_flags":0}, - "policy":{"rrf_k":60,"candidate_multiplier":4,"damping":0.85,"propagation_iterations":20,"max_path_depth":4,"epsilon":0.000001,"communities":true,"use_lexical":false}, - "context_budget":null - }`) - retrieval, err := rt.Raw.RAGRetrieve(testContext, payload) - if err != nil { - t.Fatal(err) - } - defer retrieval.Close() - resultJSON, err := retrieval.Complete(testContext, json.RawMessage(`[]`)) - if err != nil { - t.Fatal(err) - } - var result struct { - Nodes []json.RawMessage `json:"nodes"` - Edges []json.RawMessage `json:"edges"` - Extensions []string `json:"extensions"` - } - if err := json.Unmarshal(resultJSON, &result); err != nil { - t.Fatal(err) - } - if len(result.Nodes) != 0 || len(result.Edges) != 0 || len(result.Extensions) != 0 { - t.Fatalf("vector-only retrieval without external batches must be empty: %s", resultJSON) - } -} - -func TestRawLinkAndTypedSubgraph(t *testing.T) { - rt := openRuntime(t) - addDomain(t, rt, "example.com") - addDomain(t, rt, "www.example.com") - if _, err := rt.Graph.AddEdges(testContext, []Edge{relatedEdge("domain:www.example.com", "domain:example.com")}); err != nil { - t.Fatal(err) - } - if _, err := rt.Raw.Link(testContext, json.RawMessage(`["domain:example.com"]`), "test"); err != nil { - t.Fatal(err) - } - derived, err := rt.Graph.Subgraph(testContext, []string{"domain:www.example.com"}, 1) - if err != nil { - t.Fatal(err) - } - defer derived.Close() - if count, err := derived.Graph.NodeCount(testContext); err != nil || count != 2 { - t.Fatalf("derived node count=%d err=%v", count, err) - } -} diff --git a/go/repository.go b/go/repository.go index 9a171ca..b2f7d01 100644 --- a/go/repository.go +++ b/go/repository.go @@ -1,6 +1,11 @@ package cstx -import "context" +import ( + "context" + + "github.com/chainreactors/libcstx/go/proto/cstxproto" + "google.golang.org/protobuf/types/known/structpb" +) // Repository is the Git-like version namespace of one CSTX working tree. type Repository struct{ eng engine } @@ -19,9 +24,9 @@ func (r *Repository) Head(ctx context.Context, refName string) (*string, error) return r.eng.repoHead(ctx, refName) } -func (r *Repository) Checkout(ctx context.Context, revision string, force bool) (Commit, error) { +func (r *Repository) Checkout(ctx context.Context, revision string, force bool) (*cstxproto.Commit, error) { if err := contextError(ctx); err != nil { - return Commit{}, err + return nil, err } return r.eng.repoCheckout(ctx, revision, force) } @@ -31,10 +36,10 @@ func (r *Repository) Commit( message string, refName string, expectedHead *string, - metadata any, -) (Commit, error) { + metadata *structpb.Struct, +) (*cstxproto.Commit, error) { if err := contextError(ctx); err != nil { - return Commit{}, err + return nil, err } return r.eng.repoCommit(ctx, message, refName, expectedHead, metadata) } @@ -47,11 +52,11 @@ func (r *Repository) Prepare( message string, refName string, expectedHead *string, - metadata any, + metadata *structpb.Struct, timestamp *int64, -) (PreparedCommit, error) { +) (*cstxproto.PublicationPlan, error) { if err := contextError(ctx); err != nil { - return PreparedCommit{}, err + return nil, err } return r.eng.repoPrepare(ctx, message, refName, expectedHead, metadata, timestamp) } @@ -74,7 +79,7 @@ func (r *Repository) Discard(ctx context.Context) error { // Synchronize loads externally persisted objects, refs, and index roots into // this computation session. -func (r *Repository) Synchronize(ctx context.Context, state RepositorySync) error { +func (r *Repository) Synchronize(ctx context.Context, state *cstxproto.RepositoryState) error { if err := contextError(ctx); err != nil { return err } @@ -88,89 +93,12 @@ func (r *Repository) Contains(ctx context.Context, object string) (bool, error) return r.eng.repoContains(ctx, object) } -// MissingTree plans immutable object reads required to materialize a commit. -func (r *Repository) MissingTree(ctx context.Context, commit string) ([]string, error) { - if err := contextError(ctx); err != nil { - return nil, err - } - return r.eng.repoMissingTree(ctx, commit) -} - -// ObjectClosure returns every object one commit and its ancestry are built -// from. Deleting whatever the union of this set over every ref does not name -// reclaims space without breaking any supported operation on those refs. -// -// It answers from stored bytes, so unlike the Missing* planners the result does -// not depend on what this process has already loaded. -func (r *Repository) ObjectClosure(ctx context.Context, commit string) ([]string, error) { - if err := contextError(ctx); err != nil { - return nil, err - } - return r.eng.repoObjectClosure(ctx, commit) -} - -// MissingPrepare plans index reads required before preparing a child commit. -func (r *Repository) MissingPrepare(ctx context.Context, commit string) ([]string, error) { +// Missing plans immutable object reads for one repository operation. +func (r *Repository) Missing(ctx context.Context, plan *cstxproto.RepositoryObjectPlan) (*cstxproto.ObjectSelection, error) { if err := contextError(ctx); err != nil { return nil, err } - return r.eng.repoMissingPrepare(ctx, commit) -} - -// MissingHistory plans the index reads required to answer History for one -// entity. A host that keeps objects outside the runtime resolves this to empty -// before calling History; the index only pages in the postings for that entity, -// so the walk costs what the entity changed, not what the range contains. -func (r *Repository) MissingHistory(ctx context.Context, commit, entity string) ([]string, error) { - if err := contextError(ctx); err != nil { - return nil, err - } - return r.eng.repoMissingHistory(ctx, commit, entity) -} - -// MissingStat plans the reads required to summarize a commit. -func (r *Repository) MissingStat(ctx context.Context, commit string) ([]string, error) { - if err := contextError(ctx); err != nil { - return nil, err - } - return r.eng.repoMissingStat(ctx, commit) -} - -// MissingCommits plans the reads required to walk a commit's ancestry. -func (r *Repository) MissingCommits(ctx context.Context, commit string, limit int) ([]string, error) { - if err := contextError(ctx); err != nil { - return nil, err - } - return r.eng.repoMissingCommits(ctx, commit, limit) -} - -// MissingDiff plans the reads required to diff two revisions at one detail -// level. A limit never narrows the plan, so it is not part of the request. -func (r *Repository) MissingDiff(ctx context.Context, base, head string, detail DiffDetail) ([]string, error) { - if err := contextError(ctx); err != nil { - return nil, err - } - if detail == "" { - detail = DiffEntities - } - return r.eng.repoMissingDiff(ctx, base, head, detail) -} - -// MissingDelta plans the reads required to count changes in a time range. -func (r *Repository) MissingDelta(ctx context.Context, commit string, start, end *int64) ([]string, error) { - if err := contextError(ctx); err != nil { - return nil, err - } - return r.eng.repoMissingDelta(ctx, commit, start, end) -} - -// MissingMerge plans the reads required to merge source into target. An empty -// target means the current head. -func (r *Repository) MissingMerge(ctx context.Context, source, target string) ([]string, error) { - if err := contextError(ctx); err != nil { - return nil, err - } - return r.eng.repoMissingMerge(ctx, source, target) + return r.eng.repoMissing(ctx, plan) } // ReleaseTransientObjects drops objects hydrated for one external operation. @@ -188,31 +116,39 @@ func (r *Repository) Diff( ctx context.Context, base string, head string, - options DiffOptions, -) (GraphDiff, error) { + limit *uint64, + detail cstxproto.DiffDetail, +) (*cstxproto.GraphDiff, error) { if err := contextError(ctx); err != nil { - return GraphDiff{}, err + return nil, err } - return r.eng.repoDiff(ctx, base, head, options) + return r.eng.repoDiff(ctx, base, head, limit, detail) } func (r *Repository) Log( ctx context.Context, revision string, limit int, -) ([]map[string]any, error) { +) (*cstxproto.CommitLog, error) { if err := contextError(ctx); err != nil { return nil, err } return r.eng.repoLog(ctx, revision, limit) } -// History is a structured, replayable result for one entity at a revision. -type History struct { - EntityID string - Revision string - Limit *int - Entries []map[string]any +// Entities reads the records of specific nodes and relationships at one +// revision. It bisects the revision's runs rather than checking it out, so the +// cost follows how many entities are asked for, not how many the graph holds. +// Entities that are not live at revision are absent from the returned graph. +func (r *Repository) Entities( + ctx context.Context, + revision string, + entityIDs []string, +) (*cstxproto.Graph, error) { + if err := contextError(ctx); err != nil { + return nil, err + } + return r.eng.repoEntities(ctx, revision, entityIDs) } func (r *Repository) History( @@ -220,17 +156,11 @@ func (r *Repository) History( entityID string, revision string, limit *int, -) (History, error) { +) (*cstxproto.EntityHistory, error) { if err := contextError(ctx); err != nil { - return History{}, err + return nil, err } - entries, err := r.eng.repoHistory(ctx, entityID, revision, limit) - return History{ - EntityID: entityID, - Revision: revision, - Limit: limit, - Entries: entries, - }, err + return r.eng.repoHistory(ctx, entityID, revision, limit) } func (r *Repository) Branch(ctx context.Context, name, startPoint string) (string, error) { @@ -246,9 +176,9 @@ func (r *Repository) Merge( target string, expectedHead *string, message *string, -) (Commit, error) { +) (*cstxproto.Commit, error) { if err := contextError(ctx); err != nil { - return Commit{}, err + return nil, err } return r.eng.repoMerge(ctx, source, target, expectedHead, message) } @@ -258,9 +188,9 @@ func (r *Repository) Stat( revision string, excludeMask uint64, includeMask uint64, -) (GraphStats, error) { +) (*cstxproto.GraphStats, error) { if err := contextError(ctx); err != nil { - return GraphStats{}, err + return nil, err } return r.eng.repoStat(ctx, revision, excludeMask, includeMask) } @@ -270,9 +200,9 @@ func (r *Repository) Delta( revision string, startTimestamp *int64, endTimestamp *int64, -) (Delta, error) { +) (*cstxproto.GraphChangeSummary, error) { if err := contextError(ctx); err != nil { - return Delta{}, err + return nil, err } return r.eng.repoDelta(ctx, revision, startTimestamp, endTimestamp) } diff --git a/go/repository_entities_test.go b/go/repository_entities_test.go new file mode 100644 index 0000000..ce4f87c --- /dev/null +++ b/go/repository_entities_test.go @@ -0,0 +1,132 @@ +package cstx + +import ( + "fmt" + "testing" + + "github.com/chainreactors/libcstx/go/proto/cstxproto" +) + +// Reading a few entities at a revision must not cost the revision. Before the +// entity plan existed the only way to get a payload back was Checkout, so a +// host that wanted the twenty nodes a diff named had to materialize the whole +// board — twice, for a two-sided diff. +// +// This runs the real external-storage loop (Missing -> fetch -> Synchronize) +// for both routes against the same stored objects and compares what each one +// had to fetch, then checks the point read agrees with the checkout field for +// field. +func TestRepositoryEntitiesHydratesLessThanACheckout(t *testing.T) { + const width = 400 + const wanted = "domain:tracked.example" + + writer := openRuntime(t) + nodes := make([]*cstxproto.Node, 0, width+1) + tracked := domainNode("tracked.example") + tracked.Id = stringPtr(wanted) + nodes = append(nodes, tracked) + for i := range width { + nodes = append(nodes, domainNode(fmt.Sprintf("filler-%d.example", i))) + } + if _, err := writer.Graph.AddNodes(testContext, nodes); err != nil { + t.Fatalf("add nodes: %v", err) + } + + prepared, err := writer.Repo.Prepare(testContext, "baseline", "main", nil, nil, nil) + if err != nil { + t.Fatalf("prepare: %v", err) + } + objects := map[string]*cstxproto.RepositoryState_Object{} + var commitObject *cstxproto.RepositoryState_Object + for _, object := range prepared.Objects { + stored := &cstxproto.RepositoryState_Object{ + Id: object.Id, + Payload: append([]byte(nil), object.Payload...), + } + objects[object.Id] = stored + if object.Id == prepared.Commit.Id { + commitObject = stored + } + } + if err := writer.Repo.Accept(testContext, prepared.Commit.Id); err != nil { + t.Fatalf("accept: %v", err) + } + head := prepared.Commit.Id + + // A fresh runtime holding only the commit envelope: everything a plan needs + // has to arrive through Synchronize, so what it asks for is observable. + seed := func() *CSTX { + reader := openRuntime(t) + if err := reader.Repo.Synchronize(testContext, &cstxproto.RepositoryState{ + Objects: []*cstxproto.RepositoryState_Object{commitObject}, + Refs: []*cstxproto.RepositoryState_Ref{{Name: "main", CommitId: &head}}, + }); err != nil { + t.Fatalf("synchronize frontier: %v", err) + } + return reader + } + + hydrate := func(reader *CSTX, plan *cstxproto.RepositoryObjectPlan) int { + read := 0 + for { + missing, err := reader.Repo.Missing(testContext, plan) + if err != nil { + t.Fatalf("plan: %v", err) + } + if len(missing.ObjectIds) == 0 { + return read + } + batch := make([]*cstxproto.RepositoryState_Object, 0, len(missing.ObjectIds)) + for _, id := range missing.ObjectIds { + object, ok := objects[id] + if !ok { + t.Fatalf("planner asked for an object that was never stored: %s", id) + } + batch = append(batch, object) + } + read += len(batch) + if err := reader.Repo.Synchronize(testContext, &cstxproto.RepositoryState{Objects: batch}); err != nil { + t.Fatalf("synchronize: %v", err) + } + } + } + + pointReader := seed() + pointObjects := hydrate(pointReader, &cstxproto.RepositoryObjectPlan{ + Kind: cstxproto.RepositoryPlanKind_REPOSITORY_PLAN_ENTITIES, + CommitId: head, + EntityIds: []string{wanted}, + }) + read, err := pointReader.Repo.Entities(testContext, head, []string{wanted}) + if err != nil { + t.Fatalf("entities: %v", err) + } + if len(read.Nodes) != 1 { + t.Fatalf("entities returned %d nodes, want 1", len(read.Nodes)) + } + + checkoutReader := seed() + checkoutObjects := hydrate(checkoutReader, &cstxproto.RepositoryObjectPlan{ + Kind: cstxproto.RepositoryPlanKind_REPOSITORY_PLAN_TREE, + CommitId: head, + }) + if _, err := checkoutReader.Repo.Checkout(testContext, head, true); err != nil { + t.Fatalf("checkout: %v", err) + } + resolved, err := checkoutReader.Graph.Node(testContext, wanted) + if err != nil { + t.Fatalf("graph node: %v", err) + } + + if read.Nodes[0].String() != resolved.String() { + t.Fatalf("point read %v disagrees with checkout %v", read.Nodes[0], resolved) + } + if pointObjects >= checkoutObjects { + t.Fatalf( + "entity read hydrated %d objects and the checkout hydrated %d over %d nodes; "+ + "the point read exists so the board does not have to be fetched", + pointObjects, checkoutObjects, width+1, + ) + } + t.Logf("entity read: %d objects; checkout of the same revision: %d", pointObjects, checkoutObjects) +} diff --git a/go/repository_history_test.go b/go/repository_history_test.go index 9c35c14..5a3f31c 100644 --- a/go/repository_history_test.go +++ b/go/repository_history_test.go @@ -3,11 +3,14 @@ package cstx import ( "fmt" "testing" + + "github.com/chainreactors/libcstx/go/proto/cstxproto" + "google.golang.org/protobuf/types/known/structpb" ) // A per-entity history is cheap because the index pages in the postings for that // one entity, not every object the range's snapshots contain. That property is -// only reachable from Go once MissingHistory exists: a host that keeps objects +// only reachable from Go once the history plan exists: a host that keeps objects // outside the runtime has no other way to learn which index pages to hand over, // and would have to fall back to materializing each snapshot and comparing // content hashes — the very cost the index exists to avoid. @@ -20,24 +23,22 @@ func TestRepositoryHistoryHydratesOnlyEntityPostings(t *testing.T) { const tracked = "domain:tracked.example" writer := openRuntime(t) - objects := map[string]RepositoryObject{} + objects := map[string]*cstxproto.RepositoryState_Object{} var head, indexRoot string var commits []string - var commitObject RepositoryObject + var commitObject *cstxproto.RepositoryState_Object for round := range rounds { // The tracked node changes every round... - if _, err := writer.Graph.AddNodes(testContext, []Node{{ - ID: tracked, Type: "domain", Value: "tracked.example", - Model: map[string]any{"domain": "tracked.example", "cstx_flags": 0}, - Sources: []string{"test"}, - Extras: map[string]any{"round": round}, - }}); err != nil { + trackedNode := domainNode("tracked.example") + trackedNode.Id = stringPtr(tracked) + trackedNode.Annotations = &structpb.Struct{Fields: map[string]*structpb.Value{"round": structpb.NewNumberValue(float64(round))}} + if _, err := writer.Graph.AddNodes(testContext, []*cstxproto.Node{trackedNode}); err != nil { t.Fatalf("round %d tracked node: %v", round, err) } // ...surrounded by nodes that do not, so the snapshot is wide while the // entity's own history stays short. - filler := make([]Node, 0, width) + filler := make([]*cstxproto.Node, 0, width) for i := range width { filler = append(filler, domainNode(fmt.Sprintf("filler-%d-%d.example", round, i))) } @@ -56,16 +57,16 @@ func TestRepositoryHistoryHydratesOnlyEntityPostings(t *testing.T) { t.Fatalf("prepare round %d: %v", round, err) } for _, object := range prepared.Objects { - stored := RepositoryObject{ID: object.ID, Envelope: append([]byte(nil), object.Envelope...)} - objects[object.ID] = stored - if object.Kind == "commit" && object.ID == prepared.Commit.ID { + stored := &cstxproto.RepositoryState_Object{Id: object.Id, Payload: append([]byte(nil), object.Payload...)} + objects[object.Id] = stored + if object.Kind == cstxproto.RepositoryObjectKind_REPOSITORY_OBJECT_KIND_COMMIT && object.Id == prepared.Commit.Id { commitObject = stored } } - if err := writer.Repo.Accept(testContext, prepared.Commit.ID); err != nil { + if err := writer.Repo.Accept(testContext, prepared.Commit.Id); err != nil { t.Fatalf("accept round %d: %v", round, err) } - head = prepared.Commit.ID + head = prepared.Commit.Id commits = append(commits, head) indexRoot = prepared.IndexRoot } @@ -79,32 +80,32 @@ func TestRepositoryHistoryHydratesOnlyEntityPostings(t *testing.T) { // postings, so everything a plan needs has to arrive through synchronize. seed := func() *CSTX { reader := openRuntime(t) - if err := reader.Repo.Synchronize(testContext, RepositorySync{ - Objects: []RepositoryObject{commitObject, rootObject}, + if err := reader.Repo.Synchronize(testContext, &cstxproto.RepositoryState{ + Objects: []*cstxproto.RepositoryState_Object{commitObject, rootObject}, }); err != nil { t.Fatalf("synchronize frontier objects: %v", err) } - if err := reader.Repo.Synchronize(testContext, RepositorySync{ - Refs: []RepositoryRef{{Name: "main", Commit: &head}}, - Indexes: []RepositoryIndex{{Commit: head, IndexRoot: indexRoot}}, + if err := reader.Repo.Synchronize(testContext, &cstxproto.RepositoryState{ + Refs: []*cstxproto.RepositoryState_Ref{{Name: "main", CommitId: &head}}, + Indexes: []*cstxproto.RepositoryState_Index{{CommitId: head, IndexRoot: indexRoot}}, }); err != nil { t.Fatalf("synchronize frontier refs: %v", err) } return reader } - hydrate := func(reader *CSTX, plan func() ([]string, error)) int { + hydrate := func(reader *CSTX, plan func() (*cstxproto.ObjectSelection, error)) int { read := 0 for { missing, err := plan() if err != nil { t.Fatalf("plan: %v", err) } - if len(missing) == 0 { + if len(missing.ObjectIds) == 0 { return read } - batch := make([]RepositoryObject, 0, len(missing)) - for _, id := range missing { + batch := make([]*cstxproto.RepositoryState_Object, 0, len(missing.ObjectIds)) + for _, id := range missing.ObjectIds { object, ok := objects[id] if !ok { t.Fatalf("planner requested an object that was never stored: %s", id) @@ -112,25 +113,25 @@ func TestRepositoryHistoryHydratesOnlyEntityPostings(t *testing.T) { batch = append(batch, object) } read += len(batch) - if err := reader.Repo.Synchronize(testContext, RepositorySync{Objects: batch}); err != nil { + if err := reader.Repo.Synchronize(testContext, &cstxproto.RepositoryState{Objects: batch}); err != nil { t.Fatalf("synchronize: %v", err) } } } historyReader := seed() - historyObjects := hydrate(historyReader, func() ([]string, error) { - return historyReader.Repo.MissingHistory(testContext, head, tracked) + historyObjects := hydrate(historyReader, func() (*cstxproto.ObjectSelection, error) { + return historyReader.Repo.Missing(testContext, &cstxproto.RepositoryObjectPlan{Kind: cstxproto.RepositoryPlanKind_REPOSITORY_PLAN_HISTORY, CommitId: head, EntityId: stringPtr(tracked)}) }) entries, err := historyReader.Repo.History(testContext, tracked, head, nil) if err != nil { t.Fatalf("history: %v", err) } - if len(entries.Entries) != rounds { - t.Fatalf("history returned %d entries, want %d (one per round)", len(entries.Entries), rounds) + if len(entries.Changes) != rounds { + t.Fatalf("history returned %d entries, want %d (one per round)", len(entries.Changes), rounds) } - // The fallback a host without MissingHistory is stuck with: materialize every + // The fallback without an indexed history plan is to materialize every // snapshot in the range and compare the entity's content hash across them. // One snapshot is cheap; the range is not, and it grows with history depth // while the entity's own change count does not. @@ -141,13 +142,13 @@ func TestRepositoryHistoryHydratesOnlyEntityPostings(t *testing.T) { if !ok { t.Fatalf("commit object %s was never published", commit) } - if err := reader.Repo.Synchronize(testContext, RepositorySync{ - Objects: []RepositoryObject{commitEnvelope}, + if err := reader.Repo.Synchronize(testContext, &cstxproto.RepositoryState{ + Objects: []*cstxproto.RepositoryState_Object{commitEnvelope}, }); err != nil { t.Fatalf("synchronize commit %s: %v", commit, err) } - walkObjects += 1 + hydrate(reader, func() ([]string, error) { - return reader.Repo.MissingTree(testContext, commit) + walkObjects += 1 + hydrate(reader, func() (*cstxproto.ObjectSelection, error) { + return reader.Repo.Missing(testContext, &cstxproto.RepositoryObjectPlan{Kind: cstxproto.RepositoryPlanKind_REPOSITORY_PLAN_TREE, CommitId: commit}) }) } @@ -160,6 +161,6 @@ func TestRepositoryHistoryHydratesOnlyEntityPostings(t *testing.T) { } t.Logf( "per-entity history: %d objects for %d changes; snapshot walk over %d commits: %d objects", - historyObjects, len(entries.Entries), len(commits), walkObjects, + historyObjects, len(entries.Changes), len(commits), walkObjects, ) } diff --git a/go/schemas.go b/go/schemas.go deleted file mode 100644 index 75468ac..0000000 --- a/go/schemas.go +++ /dev/null @@ -1,112 +0,0 @@ -package cstx - -import "context" - -// Schemas is the schema/plugin namespace of a CSTX runtime. -type Schemas struct{ eng engine } - -// Import atomically validates and registers a portable schema contract. -func (s *Schemas) Import(ctx context.Context, contract SchemaContract) error { - if err := contextError(ctx); err != nil { - return err - } - return s.eng.schemaImport(ctx, contract) -} - -// Export returns the complete portable schema contract. -func (s *Schemas) Export(ctx context.Context) (SchemaContract, error) { - if err := contextError(ctx); err != nil { - return SchemaContract{}, err - } - return s.eng.schemaExport(ctx) -} - -// Register adds CSTX validation metadata for one node type. An empty -// valueField means no designated value field. -func (s *Schemas) Register(ctx context.Context, nodeType string, schema map[string]any, valueField string) error { - if err := contextError(ctx); err != nil { - return err - } - return s.eng.schemaRegister(ctx, nodeType, schema, valueField) -} - -// RegisterJoinRule registers one declarative native linker rule. -func (s *Schemas) RegisterJoinRule(ctx context.Context, rule JoinRuleSpec) error { - if err := contextError(ctx); err != nil { - return err - } - return s.eng.schemaRegisterJoinRule(ctx, rule) -} - -// Contains reports whether a schema exists for the node type. -func (s *Schemas) Contains(ctx context.Context, nodeType string) (bool, error) { - if err := contextError(ctx); err != nil { - return false, err - } - return s.eng.schemaContains(ctx, nodeType) -} - -// Get returns one retained schema. -func (s *Schemas) Get(ctx context.Context, nodeType string) (map[string]any, error) { - if err := contextError(ctx); err != nil { - return nil, err - } - return s.eng.schemaGet(ctx, nodeType) -} - -// List returns retained schemas in deterministic node-type order. -func (s *Schemas) List(ctx context.Context) ([]map[string]any, error) { - if err := contextError(ctx); err != nil { - return nil, err - } - return s.eng.schemaList(ctx) -} - -// LoadPlugin loads one linked native plugin into the shared graph engine. -func (s *Schemas) LoadPlugin(ctx context.Context, name string) error { - if err := contextError(ctx); err != nil { - return err - } - return s.eng.schemaLoadPlugin(ctx, name) -} - -// LoadAllPlugins loads every linked native plugin. -func (s *Schemas) LoadAllPlugins(ctx context.Context) error { - if err := contextError(ctx); err != nil { - return err - } - return s.eng.schemaLoadAllPlugins(ctx) -} - -// AvailablePlugins lists linked plugins without changing runtime state. -func (s *Schemas) AvailablePlugins(ctx context.Context) ([]string, error) { - if err := contextError(ctx); err != nil { - return nil, err - } - return s.eng.schemaAvailablePlugins(ctx) -} - -// PluginArtifacts lists artifacts provided by one linked plugin without -// loading it into the runtime. -func (s *Schemas) PluginArtifacts(ctx context.Context, name string) ([]string, error) { - if err := contextError(ctx); err != nil { - return nil, err - } - return s.eng.schemaPluginArtifacts(ctx, name) -} - -// HasNativeArtifact reports whether a linked native parser supports an artifact. -func (s *Schemas) HasNativeArtifact(ctx context.Context, artifact string) (bool, error) { - if err := contextError(ctx); err != nil { - return false, err - } - return s.eng.schemaHasNativeArtifact(ctx, artifact) -} - -// AnchorConcepts lists native concepts and their member node types. -func (s *Schemas) AnchorConcepts(ctx context.Context) ([]AnchorConcept, error) { - if err := contextError(ctx); err != nil { - return nil, err - } - return s.eng.schemaAnchorConcepts(ctx) -} diff --git a/go/sco_easm.go b/go/sco_easm.go deleted file mode 100644 index a505d05..0000000 --- a/go/sco_easm.go +++ /dev/null @@ -1,331 +0,0 @@ -// @generated by cstx-codegen — DO NOT EDIT. - -package cstx - -import "encoding/json" - -type DomainNode struct { - nodeHeader - Host string `json:"host"` -} - -type SubdomainNode struct { - nodeHeader - Host string `json:"host"` - IsTld bool `json:"is_tld,omitempty"` - Ttl int64 `json:"ttl,omitempty"` - Resolver []string `json:"resolver,omitempty"` - A []string `json:"a,omitempty"` - Aaaa []string `json:"aaaa,omitempty"` - Cname []string `json:"cname,omitempty"` - Mx []string `json:"mx,omitempty"` - Ns []string `json:"ns,omitempty"` - Txt []string `json:"txt,omitempty"` -} - -type IpNode struct { - nodeHeader - Ip string `json:"ip"` - Country string `json:"country,omitempty"` - Area string `json:"area,omitempty"` - AsnNumber string `json:"asn_number,omitempty"` - AsName string `json:"as_name,omitempty"` - CdnName string `json:"cdn_name,omitempty"` - CloudName string `json:"cloud_name,omitempty"` - WafName string `json:"waf_name,omitempty"` - Cdn bool `json:"cdn,omitempty"` - Cloud bool `json:"cloud,omitempty"` - Waf bool `json:"waf,omitempty"` -} - -type CidrNode struct { - nodeHeader - Cidr string `json:"cidr"` -} - -type PortNode struct { - nodeHeader - Ip string `json:"ip"` - Port string `json:"port"` - Protocol string `json:"protocol"` -} - -type AppNode struct { - nodeHeader - AppId string `json:"app_id"` - Url string `json:"url,omitempty"` - Frameworks []string `json:"frameworks,omitempty"` - Title string `json:"title,omitempty"` - Midware string `json:"midware,omitempty"` - Status string `json:"status,omitempty"` - StatusCode int64 `json:"status_code,omitempty"` - Host string `json:"host,omitempty"` - ContentType string `json:"content_type,omitempty"` - BodyLength int64 `json:"body_length,omitempty"` - HeaderLength int64 `json:"header_length,omitempty"` - ScreenshotId string `json:"screenshot_id,omitempty"` - ScreenshotPath string `json:"screenshot_path,omitempty"` - Ip string `json:"ip,omitempty"` - Port string `json:"port,omitempty"` -} - -type UrlNode struct { - nodeHeader - Scheme string `json:"scheme"` - Host string `json:"host,omitempty"` - Port string `json:"port,omitempty"` - Path string `json:"path,omitempty"` - Ip string `json:"ip,omitempty"` - StatusCode int64 `json:"status_code,omitempty"` - Title string `json:"title,omitempty"` - BodyLength int64 `json:"body_length,omitempty"` - ContentType string `json:"content_type,omitempty"` - RedirectUrl string `json:"redirect_url,omitempty"` - Frameworks []string `json:"frameworks,omitempty"` -} - -type FrameworkNode struct { - nodeHeader - Name string `json:"name"` - Part string `json:"part,omitempty"` - Vendor string `json:"vendor,omitempty"` - Product string `json:"product,omitempty"` - Version string `json:"version,omitempty"` - Tags []string `json:"tags,omitempty"` - IsFocus bool `json:"is_focus,omitempty"` - Sources []string `json:"sources,omitempty"` -} - -type VulnNode struct { - nodeHeader - Value string `json:"value"` - VulnId string `json:"vuln_id,omitempty"` - Name string `json:"name,omitempty"` - AssetId string `json:"asset_id,omitempty"` - Severity string `json:"severity,omitempty"` - Tags []string `json:"tags,omitempty"` - Ip string `json:"ip,omitempty"` - Host string `json:"host,omitempty"` - Port string `json:"port,omitempty"` - Protocol string `json:"protocol,omitempty"` - Scheme string `json:"scheme,omitempty"` - Url string `json:"url,omitempty"` - Path string `json:"path,omitempty"` - Pocname string `json:"pocname,omitempty"` - Request string `json:"request,omitempty"` - Response string `json:"response,omitempty"` - Username string `json:"username,omitempty"` - Password string `json:"password,omitempty"` - Matched bool `json:"matched,omitempty"` - Extracted bool `json:"extracted,omitempty"` -} - -type SarifVulnNode struct { - nodeHeader - Value string `json:"value"` - VulnId string `json:"vuln_id,omitempty"` - Title string `json:"title,omitempty"` - Description string `json:"description,omitempty"` - Source string `json:"source,omitempty"` - Target string `json:"target,omitempty"` - Tags []string `json:"tags,omitempty"` - AssetCstxId string `json:"asset_cstx_id,omitempty"` - Kind string `json:"kind,omitempty"` - Level string `json:"level,omitempty"` - BaselineState string `json:"baseline_state,omitempty"` - RuleId string `json:"rule_id,omitempty"` - Evidence string `json:"evidence,omitempty"` -} - -type CertificateNode struct { - nodeHeader - Fingerprint string `json:"fingerprint"` - Serial string `json:"serial,omitempty"` - Issuer string `json:"issuer,omitempty"` - Subject string `json:"subject,omitempty"` - NotBefore string `json:"not_before,omitempty"` - NotAfter string `json:"not_after,omitempty"` - San []string `json:"san,omitempty"` - Host string `json:"host,omitempty"` - Ip string `json:"ip,omitempty"` -} - -type CompanyNode struct { - nodeHeader - Name string `json:"name"` - Perc string `json:"perc,omitempty"` - Tycid string `json:"tycid,omitempty"` - Icp string `json:"icp,omitempty"` - Parent string `json:"parent,omitempty"` -} - -type IcpNode struct { - nodeHeader - Icp string `json:"icp"` - Sub string `json:"sub,omitempty"` - Date string `json:"date,omitempty"` - Company string `json:"company,omitempty"` - Title string `json:"title,omitempty"` - Domain string `json:"domain,omitempty"` - Ip string `json:"ip,omitempty"` -} - -type BucketNode struct { - nodeHeader - Provider string `json:"provider,omitempty"` - Name string `json:"name,omitempty"` - Region string `json:"region,omitempty"` - Endpoint string `json:"endpoint"` - Acl string `json:"acl,omitempty"` - ObjectCount int64 `json:"object_count,omitempty"` - KnownPaths []string `json:"known_paths,omitempty"` - SourceUrl string `json:"source_url,omitempty"` -} - -type EndpointNode struct { - nodeHeader - Url string `json:"url"` - Method string `json:"method,omitempty"` - Path string `json:"path,omitempty"` - ContentType string `json:"content_type,omitempty"` - StatusCode int64 `json:"status_code,omitempty"` - Source string `json:"source,omitempty"` - SourceUrl string `json:"source_url,omitempty"` - Parameters []string `json:"parameters,omitempty"` - Tags []string `json:"tags,omitempty"` -} - -type HostNode struct { - nodeHeader - Hostname string `json:"hostname"` - LocalIps []string `json:"local_ips,omitempty"` - GatewayIps []string `json:"gateway_ips,omitempty"` - DnsServers []string `json:"dns_servers,omitempty"` - DomainName string `json:"domain_name,omitempty"` - DomainRole string `json:"domain_role,omitempty"` -} - -type RepositoryNode struct { - nodeHeader - Provider string `json:"provider,omitempty"` - Name string `json:"name,omitempty"` - Url string `json:"url"` - Owner string `json:"owner,omitempty"` - Description string `json:"description,omitempty"` - Stars int64 `json:"stars,omitempty"` - IsFork bool `json:"is_fork,omitempty"` - MatchedDorks []string `json:"matched_dorks,omitempty"` -} - -type SecretNode struct { - nodeHeader - Kind string `json:"kind,omitempty"` - Detector string `json:"detector,omitempty"` - Redacted string `json:"redacted,omitempty"` - Fingerprint string `json:"fingerprint"` - Source string `json:"source,omitempty"` - SourceUrl string `json:"source_url,omitempty"` - FilePath string `json:"file_path,omitempty"` - Line int64 `json:"line,omitempty"` - Commit string `json:"commit,omitempty"` - Verified bool `json:"verified,omitempty"` - Severity string `json:"severity,omitempty"` -} - -// SCONode is the common interface for all CSTX graph nodes. -type SCONode interface { - CstxType() string - CstxID() string -} - -type nodeHeader struct { - Type string `json:"cstx_type"` - ID string `json:"cstx_id"` -} - -func (h nodeHeader) CstxType() string { return h.Type } -func (h nodeHeader) CstxID() string { return h.ID } - -// ParseSCONode unmarshals a JSON node into the correct typed struct. -func ParseSCONode(data []byte) (SCONode, error) { - var h nodeHeader - if err := json.Unmarshal(data, &h); err != nil { - return nil, err - } - switch h.Type { - case "domain": - var v DomainNode - err := json.Unmarshal(data, &v) - return &v, err - case "subdomain": - var v SubdomainNode - err := json.Unmarshal(data, &v) - return &v, err - case "ip": - var v IpNode - err := json.Unmarshal(data, &v) - return &v, err - case "cidr": - var v CidrNode - err := json.Unmarshal(data, &v) - return &v, err - case "port": - var v PortNode - err := json.Unmarshal(data, &v) - return &v, err - case "app": - var v AppNode - err := json.Unmarshal(data, &v) - return &v, err - case "url": - var v UrlNode - err := json.Unmarshal(data, &v) - return &v, err - case "framework": - var v FrameworkNode - err := json.Unmarshal(data, &v) - return &v, err - case "vuln": - var v VulnNode - err := json.Unmarshal(data, &v) - return &v, err - case "sarif_vuln": - var v SarifVulnNode - err := json.Unmarshal(data, &v) - return &v, err - case "certificate": - var v CertificateNode - err := json.Unmarshal(data, &v) - return &v, err - case "company": - var v CompanyNode - err := json.Unmarshal(data, &v) - return &v, err - case "icp": - var v IcpNode - err := json.Unmarshal(data, &v) - return &v, err - case "bucket": - var v BucketNode - err := json.Unmarshal(data, &v) - return &v, err - case "endpoint": - var v EndpointNode - err := json.Unmarshal(data, &v) - return &v, err - case "host": - var v HostNode - err := json.Unmarshal(data, &v) - return &v, err - case "repository": - var v RepositoryNode - err := json.Unmarshal(data, &v) - return &v, err - case "secret": - var v SecretNode - err := json.Unmarshal(data, &v) - return &v, err - default: - return nil, nil - } -} diff --git a/go/sco_easm_test.go b/go/sco_easm_test.go deleted file mode 100644 index e8d45ea..0000000 --- a/go/sco_easm_test.go +++ /dev/null @@ -1,153 +0,0 @@ -package cstx - -import ( - "encoding/json" - "testing" -) - -func TestParseSCONode_Domain(t *testing.T) { - raw := `{"cstx_type":"domain","cstx_id":"domain:example.com","host":"example.com"}` - node, err := ParseSCONode([]byte(raw)) - if err != nil { - t.Fatal(err) - } - if node == nil { - t.Fatal("expected non-nil node") - } - if node.CstxType() != "domain" { - t.Errorf("expected type 'domain', got %q", node.CstxType()) - } - d := node.(*DomainNode) - if d.Host != "example.com" { - t.Errorf("expected host 'example.com', got %q", d.Host) - } -} - -func TestParseSCONode_Port(t *testing.T) { - raw := `{"cstx_type":"port","cstx_id":"port:1.2.3.4:80","ip":"1.2.3.4","port":"80","protocol":"tcp"}` - node, err := ParseSCONode([]byte(raw)) - if err != nil { - t.Fatal(err) - } - p := node.(*PortNode) - if p.Ip != "1.2.3.4" { - t.Errorf("ip: got %q", p.Ip) - } - if p.Port != "80" { - t.Errorf("port: got %q", p.Port) - } - if p.Protocol != "tcp" { - t.Errorf("protocol: got %q", p.Protocol) - } -} - -func TestParseSCONode_Ip(t *testing.T) { - raw := `{"cstx_type":"ip","cstx_id":"ip:10.0.0.1","ip":"10.0.0.1","country":"CN","cdn":true}` - node, err := ParseSCONode([]byte(raw)) - if err != nil { - t.Fatal(err) - } - ip := node.(*IpNode) - if ip.Ip != "10.0.0.1" { - t.Errorf("ip: got %q", ip.Ip) - } - if ip.Country != "CN" { - t.Errorf("country: got %q", ip.Country) - } - if !ip.Cdn { - t.Error("cdn should be true") - } -} - -func TestParseSCONode_Subdomain(t *testing.T) { - raw := `{"cstx_type":"subdomain","cstx_id":"subdomain:www.a.com","host":"www.a.com","a":["1.1.1.1","2.2.2.2"],"ttl":300}` - node, err := ParseSCONode([]byte(raw)) - if err != nil { - t.Fatal(err) - } - s := node.(*SubdomainNode) - if s.Host != "www.a.com" { - t.Errorf("host: got %q", s.Host) - } - if len(s.A) != 2 || s.A[0] != "1.1.1.1" { - t.Errorf("a records: got %v", s.A) - } - if s.Ttl != 300 { - t.Errorf("ttl: got %d", s.Ttl) - } -} - -func TestParseSCONode_UnknownType(t *testing.T) { - raw := `{"cstx_type":"unknown_type","cstx_id":"x"}` - node, err := ParseSCONode([]byte(raw)) - if err != nil { - t.Fatal(err) - } - if node != nil { - t.Error("unknown type should return nil node") - } -} - -func TestParseSCONode_AllTypes(t *testing.T) { - types := []string{ - "domain", "subdomain", "ip", "cidr", "port", "app", "url", - "framework", "vuln", "certificate", "company", "icp", - "bucket", "endpoint", "host", "repository", "secret", - } - for _, typ := range types { - raw, _ := json.Marshal(map[string]string{"cstx_type": typ, "cstx_id": typ + ":test"}) - node, err := ParseSCONode(raw) - if err != nil { - t.Errorf("type %q: parse error: %v", typ, err) - continue - } - if node == nil { - t.Errorf("type %q: got nil", typ) - continue - } - if node.CstxType() != typ { - t.Errorf("type %q: CstxType() = %q", typ, node.CstxType()) - } - } -} - -func TestRelationConstants(t *testing.T) { - expected := map[string]string{ - "RelResolve": RelResolve, - "RelOpen": RelOpen, - "RelHasSubdomain": RelHasSubdomain, - "RelContain": RelContain, - "RelHosts": RelHosts, - "RelUses": RelUses, - "RelRefers": RelRefers, - "RelSecuredBy": RelSecuredBy, - "RelExploit": RelExploit, - "RelAffect": RelAffect, - "RelInvest": RelInvest, - "RelOwn": RelOwn, - "RelFiledFor": RelFiledFor, - } - want := map[string]string{ - "RelResolve": "resolve", - "RelOpen": "open", - "RelHasSubdomain": "has-subdomain", - "RelContain": "contain", - "RelHosts": "hosts", - "RelUses": "uses", - "RelRefers": "refers", - "RelSecuredBy": "secured_by", - "RelExploit": "exploit", - "RelAffect": "affect", - "RelInvest": "invest", - "RelOwn": "own", - "RelFiledFor": "filed-for", - } - for name, got := range expected { - if got != want[name] { - t.Errorf("%s: want %q, got %q", name, want[name], got) - } - } - if len(RelationTypes) != len(want) { - t.Errorf("RelationTypes length: want %d, got %d", len(want), len(RelationTypes)) - } -} diff --git a/go/sro_easm.go b/go/sro_easm.go deleted file mode 100644 index b2590bc..0000000 --- a/go/sro_easm.go +++ /dev/null @@ -1,35 +0,0 @@ -// @generated by cstx-codegen — DO NOT EDIT. - -package cstx - -const ( - RelResolve = "resolve" - RelOpen = "open" - RelHasSubdomain = "has-subdomain" - RelContain = "contain" - RelHosts = "hosts" - RelUses = "uses" - RelRefers = "refers" - RelSecuredBy = "secured_by" - RelExploit = "exploit" - RelAffect = "affect" - RelInvest = "invest" - RelOwn = "own" - RelFiledFor = "filed-for" -) - -var RelationTypes = []string{ - RelResolve, - RelOpen, - RelHasSubdomain, - RelContain, - RelHosts, - RelUses, - RelRefers, - RelSecuredBy, - RelExploit, - RelAffect, - RelInvest, - RelOwn, - RelFiledFor, -} diff --git a/go/testdata/conformance.json b/go/testdata/conformance.json index 393f2b1..9c005c3 100644 --- a/go/testdata/conformance.json +++ b/go/testdata/conformance.json @@ -1,54 +1,228 @@ { - "schema": { - "node_type": "asset", - "json_schema": { - "properties": { - "name": { - "type": "string", - "x-semantic": true, - "x-semantic-label": "name" + "document": { + "schema_version": 1, + "extension": "conformance", + "nodes": { + "asset": { + "message": "conformance.Asset", + "value_field": "name", + "identity": { + "field": "name" }, - "status": { - "type": "string", - "x-semantic": false - } + "fields": [ + { + "name": "name", + "number": 1, + "type": "string", + "repeated": false, + "optional": false, + "semantic": false, + "semantic_label": "name" + }, + { + "name": "status", + "number": 2, + "type": "string", + "repeated": false, + "optional": true, + "semantic": true, + "semantic_label": "status" + } + ] } }, - "value_field": "name" + "relations": { + "related": { + "message": "conformance.Related" + } + } }, "nodes": [ { "id": "asset:beta", "type": "asset", "value": "beta", - "model": {"name": "beta", "status": "active"}, - "sources": ["fixture"], - "extras": {} + "model": { + "name": "beta", + "status": "active" + }, + "sources": [ + "fixture" + ], + "annotations": {} }, { "id": "asset:alpha", "type": "asset", "value": "alpha", - "model": {"name": "alpha", "status": "active"}, - "sources": ["fixture"], - "extras": {} + "model": { + "name": "alpha", + "status": "active" + }, + "sources": [ + "fixture" + ], + "annotations": {} } ], - "edges": [ + "relationships": [ { "id": "relationship:asset:alpha:related:asset:beta", "source_id": "asset:alpha", "target_id": "asset:beta", - "relation_type": "related", - "sources": ["fixture"], - "attrs": {} + "type": "related", + "sources": [ + "fixture" + ], + "model": {}, + "extra": {}, + "annotations": {} } ], "query": "asset", "expected": { - "node_ids": ["asset:beta", "asset:alpha"], + "node_ids": [ + "asset:beta", + "asset:alpha" + ], "node_count": 2, - "edge_count": 1, - "pending_embedding_ids": ["asset:alpha", "asset:beta"] + "relationship_count": 1, + "pending_embedding_ids": [ + "asset:alpha", + "asset:beta" + ] + }, + "dynamic_extension": { + "_comment": "One type declared at runtime, with no generated message class in any language. Every SDK writes it from field names and reads it back, and they must agree on the id the schema derives and on every value.", + "document": { + "schema_version": 1, + "extension": "acme", + "nodes": { + "acme_asset": { + "message": "acme.Asset", + "value_field": "asset_id", + "identity": { + "field": "asset_id" + }, + "fields": [ + { + "name": "asset_id", + "number": 1, + "type": "string", + "repeated": false, + "optional": false, + "semantic": false, + "semantic_label": "asset_id" + }, + { + "name": "owner", + "number": 2, + "type": "string", + "repeated": false, + "optional": true, + "semantic": true, + "semantic_label": "owner" + }, + { + "name": "port", + "number": 3, + "type": "int64", + "repeated": false, + "optional": true, + "semantic": false, + "semantic_label": "port" + }, + { + "name": "live", + "number": 4, + "type": "bool", + "repeated": false, + "optional": true, + "semantic": false, + "semantic_label": "live" + }, + { + "name": "tags", + "number": 5, + "type": "string", + "repeated": true, + "optional": false, + "semantic": true, + "semantic_label": "tags" + }, + { + "name": "weight", + "number": 6, + "type": "double", + "repeated": false, + "optional": true, + "semantic": false, + "semantic_label": "weight" + }, + { + "name": "rank", + "number": 7, + "type": "int32", + "repeated": false, + "optional": true, + "semantic": false, + "semantic_label": "rank" + }, + { + "name": "hits", + "number": 8, + "type": "uint32", + "repeated": false, + "optional": true, + "semantic": false, + "semantic_label": "hits" + }, + { + "name": "drift", + "number": 9, + "type": "sint32", + "repeated": false, + "optional": true, + "semantic": false, + "semantic_label": "drift" + }, + { + "name": "offset", + "number": 10, + "type": "sint64", + "repeated": false, + "optional": true, + "semantic": false, + "semantic_label": "offset" + } + ] + } + }, + "relations": { + "acme_owns": { + "message": "acme.Owns" + } + } + }, + "values": { + "asset_id": "a-1", + "owner": "ops", + "port": 8443, + "live": true, + "tags": [ + "edge", + "prod" + ], + "offset": -9007199254740993, + "weight": 0.5, + "rank": -2147483648, + "hits": 4294967295, + "drift": -12345 + }, + "expected_id": "acme_asset:a-1", + "relation": { + "type": "acme_owns", + "type_url": "type.googleapis.com/acme.Owns" + } } } diff --git a/go/types.go b/go/types.go index 21025bb..57ddfa2 100644 --- a/go/types.go +++ b/go/types.go @@ -1,304 +1,53 @@ package cstx -import ( - "encoding/json" - "fmt" -) - -// NodeFlags are engine-compatible bit constants. Graph APIs accept ordinary -// uint64 masks built from these values. -const ( - FlagNone uint64 = 0 - FlagHoneypot uint64 = 1 << 0 - FlagNoise uint64 = 1 << 1 - FlagFalsePositive uint64 = 1 << 2 - FlagManualIgnored uint64 = 1 << 3 - FlagThreatPresent uint64 = 1 << 4 - FlagHistoricVulnerable uint64 = 1 << 5 - FlagInternal uint64 = 1 << 6 -) - -// FlagsAllMask contains every currently defined node flag. -const FlagsAllMask uint64 = FlagHoneypot | FlagNoise | FlagFalsePositive | - FlagManualIgnored | FlagThreatPresent | FlagHistoricVulnerable | FlagInternal - -// FlagsDefaultExcludeMask is the engine's standard default-exclusion mask. -const FlagsDefaultExcludeMask uint64 = FlagHoneypot | FlagNoise | FlagFalsePositive | FlagManualIgnored - -// Order is the deterministic ordering applied to a collection cursor. -type Order string - -const ( - OrderUnspecified Order = "unspecified" - OrderIDAsc Order = "id_asc" - OrderIDDesc Order = "id_desc" -) - -// Node is the CSTX graph node exchanged with the Rust runtime. Model -// holds schema-typed fields plus the reserved keys "__node_type__" and -// "cstx_flags". -type Node struct { - ID string `json:"id"` - Type string `json:"type"` - Value any `json:"value"` - Model map[string]any `json:"model"` - Sources []string `json:"sources"` - Extras map[string]any `json:"extras"` -} - -// MarshalJSON keeps list fields as [] rather than null; the Rust contract -// requires every field to be present. -func (n Node) MarshalJSON() ([]byte, error) { - type wire Node - if n.Sources == nil { - n.Sources = []string{} - } - if n.Model == nil { - n.Model = map[string]any{} - } - if n.Extras == nil { - n.Extras = map[string]any{} - } - return json.Marshal(wire(n)) -} - -// Edge is the CSTX graph relationship exchanged with the Rust runtime. -type Edge struct { - ID string `json:"id"` - SourceID string `json:"source_id"` - TargetID string `json:"target_id"` - RelationType string `json:"relation_type"` - Sources []string `json:"sources"` - Attrs map[string]any `json:"attrs"` -} - -// MarshalJSON keeps list fields as [] rather than null. -func (e Edge) MarshalJSON() ([]byte, error) { - type wire Edge - if e.Sources == nil { - e.Sources = []string{} - } - if e.Attrs == nil { - e.Attrs = map[string]any{} - } - return json.Marshal(wire(e)) -} - -// GraphStats is a small aggregate count summary. -type GraphStats struct { - Nodes map[string]int64 `json:"nodes"` - Edges map[string]int64 `json:"edges"` - Sources map[string]int64 `json:"sources"` -} - -// Delta counts graph elements changed by commits in one time range. -type Delta struct { - AddedNodes uint64 `json:"added_nodes"` - UpdatedNodes uint64 `json:"updated_nodes"` - RemovedNodes uint64 `json:"removed_nodes"` - AddedEdges uint64 `json:"added_edges"` - UpdatedEdges uint64 `json:"updated_edges"` - RemovedEdges uint64 `json:"removed_edges"` -} - -// ChangeSet lists the IDs changed by one successfully committed mutation. -type ChangeSet struct { - AddedNodeIDs []string `json:"added_node_ids"` - UpdatedNodeIDs []string `json:"updated_node_ids"` - RemovedNodeIDs []string `json:"removed_node_ids"` - AddedEdgeIDs []string `json:"added_edge_ids"` - UpdatedEdgeIDs []string `json:"updated_edge_ids"` - RemovedEdgeIDs []string `json:"removed_edge_ids"` - Reset bool `json:"reset"` -} - -// Affected returns the total number of changed graph elements. -func (c ChangeSet) Affected() int { - return len(c.AddedNodeIDs) + len(c.UpdatedNodeIDs) + len(c.RemovedNodeIDs) + - len(c.AddedEdgeIDs) + len(c.UpdatedEdgeIDs) + len(c.RemovedEdgeIDs) -} - -// Commit describes one immutable repository revision. -type Commit struct { - ID string `json:"id"` - Parents []string `json:"parents"` - Message string `json:"message"` - Metadata any `json:"metadata"` - Stats Delta `json:"stats"` - CreatedAt int64 `json:"created_at"` -} - -// PreparedObject is one immutable CSTX object ready for external persistence. -// Envelope is the canonical encoded object and must be stored without changes. -type PreparedObject struct { - ID string - Kind string - Envelope []byte -} - -// PreparedCommit is the complete immutable portion of one external publish -// transaction. The ref must only be advanced after all Objects and IndexRoot -// are durably stored. -type PreparedCommit struct { - Commit Commit - IndexRoot string - Objects []PreparedObject -} - -// RepositoryObject hydrates one immutable object into a CSTX computation -// session. The ID is verified against Envelope by the runtime. -type RepositoryObject struct { - ID string - Envelope []byte -} - -// RepositoryRef synchronizes one mutable named reference. A nil Commit deletes -// the reference from the computation session. -type RepositoryRef struct { - Name string - Commit *string -} - -// RepositoryIndex binds a commit to its immutable history index root. -type RepositoryIndex struct { - Commit string - IndexRoot string -} - -// RepositorySync is one batch of externally persisted repository state. -type RepositorySync struct { - Objects []RepositoryObject - Refs []RepositoryRef - Indexes []RepositoryIndex -} - -// GraphDiff groups added, removed, and modified element IDs by element type. -type GraphDiff struct { - Added map[string][]string `json:"added"` - Removed map[string][]string `json:"removed"` - Modified map[string][]string `json:"modified"` - // Truncated reports whether a limit stopped the diff before the last - // change. An empty group is otherwise ambiguous between "nothing of that - // type changed" and "the limit ran out first". - Truncated bool `json:"truncated"` - // Stats counts the whole compared range, whatever a limit left out of the - // maps above. - Stats Delta `json:"stats"` -} - -// DiffDetail selects how much of a diff the caller needs back. -type DiffDetail string - -const ( - // DiffEntities lists every changed entity, and counts them. - DiffEntities DiffDetail = "entities" - // DiffCounts returns counts alone, which page summaries can often answer - // without reading the pages themselves. - DiffCounts DiffDetail = "counts" -) - -// DiffOptions is one diff request. The zero value lists entities without a -// limit. -type DiffOptions struct { - // Limit caps reported entity IDs. Counts stay exact whatever it drops. - Limit *int - // Detail selects the entity lists or counts alone. - Detail DiffDetail -} - -func (o DiffOptions) detail() DiffDetail { - if o.Detail == "" { - return DiffEntities - } - return o.Detail -} - -// JoinRuleSpec is the portable native-linker rule shared by all bindings. -type JoinRuleSpec struct { - LeftType string `json:"left_type"` - RightType string `json:"right_type"` - Relation string `json:"relation"` - LeftKey string `json:"left_key"` - RightKey string `json:"right_key"` - Predicted bool `json:"predicted"` - LeftTargetID *string `json:"left_target_id,omitempty"` - RightSourceID *string `json:"right_source_id,omitempty"` -} - -// SCOSchemaContract describes one portable node schema. -type SCOSchemaContract struct { - Schema any `json:"schema"` - ValueField *string `json:"value_field"` - Metadata map[string]any `json:"metadata"` -} - -// SROSchemaContract describes one portable relationship schema. -type SROSchemaContract struct { - Schema any `json:"schema"` - Metadata map[string]any `json:"metadata"` -} - -// ParserSchemaContract describes one portable parser input contract. -type ParserSchemaContract struct { - InputSchema any `json:"input_schema"` - Metadata map[string]any `json:"metadata"` -} - -// PluginSchemaContract groups schemas published by one CSTX plugin. -type PluginSchemaContract struct { - Version string `json:"version"` - SCO map[string]SCOSchemaContract `json:"sco"` - SRO map[string]SROSchemaContract `json:"sro"` - Parsers map[string]ParserSchemaContract `json:"parsers"` -} - -// SchemaContract is the atomic schema exchange unit shared by all bindings. -type SchemaContract struct { - Format string `json:"format"` - Plugins map[string]PluginSchemaContract `json:"plugins"` -} - -// AnchorConcept names one native concept and its member node types. -type AnchorConcept struct { - Name string - NodeTypes []string -} - -// UnmarshalJSON decodes the Rust (name, node_types) tuple transport. -func (c *AnchorConcept) UnmarshalJSON(data []byte) error { - var pair struct { - Name string - NodeTypes []string - } - var wire []json.RawMessage - if err := json.Unmarshal(data, &wire); err != nil { - return err - } - if len(wire) != 2 { - return fmt.Errorf("cstx: anchor concept must be a two-item tuple") - } - if err := json.Unmarshal(wire[0], &pair.Name); err != nil { - return err - } - if err := json.Unmarshal(wire[1], &pair.NodeTypes); err != nil { - return err - } - c.Name, c.NodeTypes = pair.Name, pair.NodeTypes - return nil -} - -// Ref is one named repository reference and its commit ID. -type Ref struct { - Name string - Head string -} - -// UnmarshalJSON decodes the Rust (name, head) tuple transport. -func (r *Ref) UnmarshalJSON(data []byte) error { - var pair [2]string - if err := json.Unmarshal(data, &pair); err != nil { - return err +import "github.com/chainreactors/libcstx/go/proto/cstxproto" + +// FlagNone is the empty mask. Every other flag bit is *declared by an +// extension*, not by this SDK: a bit's meaning lives in +// `.schema.json`, and hard-coding one product's seven security +// words here was the same violation the `NodeFlag` enum was on the wire. +// Read the declarations with FlagRegistry (flags.go). +const FlagNone uint64 = 0 + +// Affected returns the number of graph entities changed by a generated +// protobuf change set. It is a function instead of a shadow SDK struct method. +func Affected(change *cstxproto.GraphChangeSet) int { + if change == nil { + return 0 + } + return len(change.AddedNodeIds) + len(change.UpdatedNodeIds) + + len(change.RemovedNodeIds) + len(change.AddedRelationshipIds) + + len(change.UpdatedRelationshipIds) + len(change.RemovedRelationshipIds) +} + +func algorithmCursorKind(algorithm *cstxproto.Algorithm) CursorKind { + if algorithm == nil { + return CursorKindNodes + } + switch kind := algorithm.Kind.(type) { + case *cstxproto.Algorithm_Bfs: + return CursorKindNodes + case *cstxproto.Algorithm_Betweenness, *cstxproto.Algorithm_Closeness: + return CursorKindNodeScores + case *cstxproto.Algorithm_Leiden: + return CursorKindCommunities + case *cstxproto.Algorithm_ShortestPaths: + return CursorKindPaths + case *cstxproto.Algorithm_Parameterless: + switch kind.Parameterless { + case cstxproto.ParameterlessAlgorithm_PARAMETERLESS_WEAK_COMPONENTS, + cstxproto.ParameterlessAlgorithm_PARAMETERLESS_STRONG_COMPONENTS: + return CursorKindComponents + case cstxproto.ParameterlessAlgorithm_PARAMETERLESS_CYCLE_BASIS: + return CursorKindCycles + case cstxproto.ParameterlessAlgorithm_PARAMETERLESS_BRIDGES: + return CursorKindNodePairs + case cstxproto.ParameterlessAlgorithm_PARAMETERLESS_CORE_NUMBERS: + return CursorKindNodeScores + default: + return CursorKindNodes + } + default: + return CursorKindNodes } - r.Name, r.Head = pair[0], pair[1] - return nil } diff --git a/go/values.go b/go/values.go new file mode 100644 index 0000000..765b572 --- /dev/null +++ b/go/values.go @@ -0,0 +1,118 @@ +package cstx + +import ( + "context" + "fmt" + "sort" + + "github.com/chainreactors/libcstx/go/proto/cstxproto" +) + +// NodeValues is one node's payload as field names and Go values. +// +// The untyped shape, for a caller with no generated code for the node — which +// is every type an extension declares at runtime, since no code generator ran +// for it. `plugins/` carries the typed shape for extensions that did +// run one; both produce the same payload, and neither needs a field number. +type NodeValues map[string]any + +// AddNodeValues writes one node from field names and values. +// +// Identity comes from the schema document, so a node written this way lands on +// the same id as the same content written through a generated typed struct. +func (g *Graph) AddNodeValues(ctx context.Context, nodeType string, values NodeValues, options ...NodeValueOption) (uint64, error) { + node, err := ValueNode(nodeType, values, options...) + if err != nil { + return 0, err + } + return g.AddNodes(ctx, []*cstxproto.Node{node}) +} + +// NodeValueOption sets one non-payload field on a value-shaped node. +type NodeValueOption func(*cstxproto.Node) + +// WithNodeID sets the node's id explicitly, for a type whose schema declares +// its identity computed. +func WithNodeID(id string) NodeValueOption { + return func(node *cstxproto.Node) { node.Id = &id } +} + +// WithNodeSources records which artifacts observed the node. +func WithNodeSources(sources ...string) NodeValueOption { + return func(node *cstxproto.Node) { node.Sources = sources } +} + +// ValueNode builds a value-shaped node without writing it. +func ValueNode(nodeType string, values NodeValues, options ...NodeValueOption) (*cstxproto.Node, error) { + entity, err := EntityValue(nodeType, values) + if err != nil { + return nil, err + } + node := &cstxproto.Node{Value: entity} + for _, option := range options { + option(node) + } + return node, nil +} + +// EntityValue converts a field map into the wire payload. +// +// The branch is chosen by the Go type, and the runtime checks it against the +// column the schema declared. A mismatch is an error there rather than a +// silent coercion here: a number stored as text is a field the encoder cannot +// reproduce, which the runtime refuses at registration for the same reason. +func EntityValue(nodeType string, values NodeValues) (*cstxproto.EntityValue, error) { + fields := make([]*cstxproto.EntityField, 0, len(values)) + for name, value := range values { + field := &cstxproto.EntityField{Name: name} + switch typed := value.(type) { + case nil: + continue + case string: + field.Value = &cstxproto.EntityField_Text{Text: typed} + case bool: + field.Value = &cstxproto.EntityField_Flag{Flag: typed} + case int: + field.Value = &cstxproto.EntityField_Number{Number: int64(typed)} + case int32: + field.Value = &cstxproto.EntityField_Number{Number: int64(typed)} + case int64: + field.Value = &cstxproto.EntityField_Number{Number: typed} + case float64: + field.Value = &cstxproto.EntityField_Real{Real: typed} + case []string: + field.Value = &cstxproto.EntityField_List{List: &cstxproto.StringList{Values: typed}} + default: + return nil, fmt.Errorf("cstx: field %q has unsupported type %T", name, value) + } + fields = append(fields, field) + } + // Sorted so one map produces one message: Go randomizes map iteration, and + // the payload is content, not a bag. + sort.Slice(fields, func(i, j int) bool { return fields[i].Name < fields[j].Name }) + return &cstxproto.EntityValue{NodeType: nodeType, Fields: fields}, nil +} + +// FieldValues reads a payload back into a field map. +func FieldValues(node *cstxproto.Node) (string, NodeValues, error) { + entity := node.GetValue() + if entity == nil { + return "", nil, fmt.Errorf("cstx: node %q carries no payload", node.GetId()) + } + values := make(NodeValues, len(entity.GetFields())) + for _, field := range entity.GetFields() { + switch carried := field.GetValue().(type) { + case *cstxproto.EntityField_Text: + values[field.GetName()] = carried.Text + case *cstxproto.EntityField_Number: + values[field.GetName()] = carried.Number + case *cstxproto.EntityField_Flag: + values[field.GetName()] = carried.Flag + case *cstxproto.EntityField_Real: + values[field.GetName()] = carried.Real + case *cstxproto.EntityField_List: + values[field.GetName()] = carried.List.GetValues() + } + } + return entity.GetNodeType(), values, nil +} diff --git a/include/cstx_ffi.h b/include/cstx_ffi.h index 6c1e802..ae52695 100644 --- a/include/cstx_ffi.h +++ b/include/cstx_ffi.h @@ -60,120 +60,136 @@ typedef struct CstxSlice { */ void cstx_buffer_free(struct CstxBuffer *buffer); -CstxStatusCode cstx_open(struct CstxSlice config_json, +/** + * Open a runtime from the canonical protobuf configuration message. + */ +CstxStatusCode cstx_open(struct CstxSlice config, struct CstxHandle **output, struct CstxBuffer *error); void cstx_free(struct CstxHandle *handle); -CstxStatusCode cstx_last_change_json(struct CstxHandle *handle, - struct CstxBuffer *output, +/** + * Return the last graph mutation as a protobuf message. + */ +CstxStatusCode cstx_last_change(struct CstxHandle *handle, + struct CstxBuffer *output, + struct CstxBuffer *error); + +/** + * Register an extension contract encoded as protobuf. + */ +CstxStatusCode cstx_extension_register(struct CstxHandle *handle, + struct CstxSlice contract, + struct CstxBuffer *error); + +/** + * Explicitly enable one linked native Rust extension. + */ +CstxStatusCode cstx_extension_enable(struct CstxHandle *handle, + struct CstxSlice name, struct CstxBuffer *error); -CstxStatusCode cstx_schema_register(struct CstxHandle *handle, - struct CstxSlice node_type, - struct CstxSlice schema_json, - struct CstxSlice value_field, - struct CstxBuffer *error); +/** + * List extension metadata as protobuf. + */ +CstxStatusCode cstx_extension_list(struct CstxHandle *handle, + struct CstxBuffer *output, + struct CstxBuffer *error); -CstxStatusCode cstx_schema_import_schema(struct CstxHandle *handle, - struct CstxSlice contract_json, - struct CstxBuffer *error); +/** + * Return extension metadata as protobuf. + */ +CstxStatusCode cstx_extension_info(struct CstxHandle *handle, + struct CstxSlice name, + struct CstxBuffer *output, + struct CstxBuffer *error); -CstxStatusCode cstx_schema_export_schema_json(struct CstxHandle *handle, +/** + * Export the extension contract as protobuf for low-level synchronization. + */ +CstxStatusCode cstx_extension_export_contract(struct CstxHandle *handle, struct CstxBuffer *output, struct CstxBuffer *error); -CstxStatusCode cstx_schema_contains(struct CstxHandle *handle, - struct CstxSlice node_type, - uint8_t *output, - struct CstxBuffer *error); +/** + * Test whether an extension has registered a schema for a node type. + */ +CstxStatusCode cstx_extension_contains(struct CstxHandle *handle, + struct CstxSlice node_type, + uint8_t *output, + struct CstxBuffer *error); -CstxStatusCode cstx_schema_list_json(struct CstxHandle *handle, +CstxStatusCode cstx_extension_schema(struct CstxHandle *handle, + struct CstxSlice node_type, struct CstxBuffer *output, struct CstxBuffer *error); -CstxStatusCode cstx_schema_get_json(struct CstxHandle *handle, - struct CstxSlice node_type, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_schema_load_plugin(struct CstxHandle *handle, - struct CstxSlice name, - struct CstxBuffer *error); - -CstxStatusCode cstx_schema_load_all_plugins(struct CstxHandle *handle, struct CstxBuffer *error); - -CstxStatusCode cstx_schema_available_plugins_json(struct CstxHandle *handle, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_schema_plugin_artifacts_json(struct CstxHandle *handle, - struct CstxSlice name, - struct CstxBuffer *output, - struct CstxBuffer *error); +CstxStatusCode cstx_extension_schemas(struct CstxHandle *handle, + struct CstxBuffer *output, + struct CstxBuffer *error); -CstxStatusCode cstx_schema_register_join_rule(struct CstxHandle *handle, - struct CstxSlice rule_json, +/** + * Test whether an enabled native extension provides an artifact parser. + */ +CstxStatusCode cstx_extension_parses_artifact(struct CstxHandle *handle, + struct CstxSlice artifact, + uint8_t *output, struct CstxBuffer *error); -CstxStatusCode cstx_schema_has_native_artifact(struct CstxHandle *handle, - struct CstxSlice artifact, - uint8_t *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_schema_anchor_concepts_json(struct CstxHandle *handle, - struct CstxBuffer *output, - struct CstxBuffer *error); +CstxStatusCode cstx_extension_anchor_concepts(struct CstxHandle *handle, + struct CstxBuffer *output, + struct CstxBuffer *error); +/** + * Add or merge a protobuf graph aggregate at the Rust-owned semantic boundary. + */ CstxStatusCode cstx_graph_add_nodes(struct CstxHandle *handle, struct CstxSlice data, uint64_t *affected, struct CstxBuffer *error); /** - * Write each node as its current state, replacing the stored record. - * - * The merge path (`cstx_graph_add_nodes`) owns bulk ingest and keeps its JSON - * fast path. A replace batch is a caller restating records it already holds — - * a task's oracles, a document's current revision — so it goes through the - * shared `Value` path rather than earning a second parser. + * Replace the current graph content from a protobuf aggregate. */ CstxStatusCode cstx_graph_replace_nodes(struct CstxHandle *handle, struct CstxSlice data, uint64_t *affected, struct CstxBuffer *error); -CstxStatusCode cstx_graph_add_edges(struct CstxHandle *handle, - struct CstxSlice data, - uint64_t *affected, - struct CstxBuffer *error); +/** + * Add or merge relationships from a protobuf graph aggregate. + */ +CstxStatusCode cstx_graph_add_relationships(struct CstxHandle *handle, + struct CstxSlice data, + uint64_t *affected, + struct CstxBuffer *error); CstxStatusCode cstx_graph_delete_nodes(struct CstxHandle *handle, - struct CstxSlice node_ids_json, - uint64_t *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_graph_delete_edges(struct CstxHandle *handle, - struct CstxSlice edge_ids_json, + struct CstxSlice node_ids, uint64_t *output, struct CstxBuffer *error); -CstxStatusCode cstx_graph_ingest(struct CstxHandle *handle, - struct CstxSlice source, - struct CstxSlice data, - uint64_t *affected, - struct CstxBuffer *error); +CstxStatusCode cstx_graph_delete_relationships(struct CstxHandle *handle, + struct CstxSlice relationship_ids, + uint64_t *output, + struct CstxBuffer *error); +/** + * Return one node as a protobuf envelope. + */ CstxStatusCode cstx_graph_node(struct CstxHandle *handle, struct CstxSlice node_id, struct CstxBuffer *output, struct CstxBuffer *error); -CstxStatusCode cstx_graph_edge(struct CstxHandle *handle, - struct CstxSlice edge_id, - struct CstxBuffer *output, - struct CstxBuffer *error); +/** + * Return one relationship as a protobuf envelope. + */ +CstxStatusCode cstx_graph_relationship(struct CstxHandle *handle, + struct CstxSlice relationship_id, + struct CstxBuffer *output, + struct CstxBuffer *error); CstxStatusCode cstx_graph_contains(struct CstxHandle *handle, struct CstxSlice node_id, @@ -184,57 +200,59 @@ CstxStatusCode cstx_graph_node_count(struct CstxHandle *handle, uint64_t *output, struct CstxBuffer *error); -CstxStatusCode cstx_graph_edge_count(struct CstxHandle *handle, - uint64_t *output, - struct CstxBuffer *error); +CstxStatusCode cstx_graph_relationship_count(struct CstxHandle *handle, + uint64_t *output, + struct CstxBuffer *error); +/** + * Create a node cursor from a protobuf `NodeQuery` (filter + window). + */ CstxStatusCode cstx_graph_nodes(struct CstxHandle *handle, - struct CstxSlice filter_json, - struct CstxSlice options_json, + struct CstxSlice request, struct CstxGraphCursor **output, struct CstxBuffer *error); -CstxStatusCode cstx_graph_edges(struct CstxHandle *handle, - struct CstxSlice filter_json, - struct CstxSlice options_json, - struct CstxGraphCursor **output, - struct CstxBuffer *error); +/** + * Create a relationship cursor from a protobuf `RelationshipQuery` (filter + window). + */ +CstxStatusCode cstx_graph_relationships(struct CstxHandle *handle, + struct CstxSlice request, + struct CstxGraphCursor **output, + struct CstxBuffer *error); +/** + * Create a neighbor cursor from a semantic query. + */ CstxStatusCode cstx_graph_neighbors(struct CstxHandle *handle, - struct CstxSlice node_id, - struct CstxSlice direction, - struct CstxSlice options_json, + struct CstxSlice request, struct CstxGraphCursor **output, struct CstxBuffer *error); +/** + * Create a query cursor from a semantic query. + */ CstxStatusCode cstx_graph_query(struct CstxHandle *handle, - struct CstxSlice expression, - struct CstxSlice options_json, + struct CstxSlice request, struct CstxGraphCursor **output, struct CstxBuffer *error); -CstxStatusCode cstx_graph_ingest_native_json(struct CstxHandle *handle, - struct CstxSlice plugin, - struct CstxSlice artifact, - struct CstxSlice data, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_graph_find_node_json(struct CstxHandle *handle, - struct CstxSlice identifier, - struct CstxBuffer *output, - struct CstxBuffer *error); +/** + * Resolve an identifier and return the matching node as protobuf. + */ +CstxStatusCode cstx_graph_find_node(struct CstxHandle *handle, + struct CstxSlice identifier, + struct CstxBuffer *output, + struct CstxBuffer *error); -CstxStatusCode cstx_graph_patch_node_extras(struct CstxHandle *handle, - struct CstxSlice node_ids_json, - struct CstxSlice patch_json, - uint64_t *affected, - struct CstxBuffer *error); +CstxStatusCode cstx_graph_patch_node_annotations(struct CstxHandle *handle, + struct CstxSlice request, + uint64_t *affected, + struct CstxBuffer *error); -CstxStatusCode cstx_graph_create_relationship_json(struct CstxHandle *handle, - struct CstxSlice request_json, - struct CstxBuffer *output, - struct CstxBuffer *error); +CstxStatusCode cstx_graph_add_relationship(struct CstxHandle *handle, + struct CstxSlice request_bytes, + struct CstxBuffer *output, + struct CstxBuffer *error); CstxStatusCode cstx_is_path_expression(struct CstxSlice expression, uint8_t *output, @@ -256,23 +274,23 @@ CstxStatusCode cstx_graph_difference(struct CstxHandle *left, struct CstxHandle **output, struct CstxBuffer *error); -CstxStatusCode cstx_graph_node_types_json(struct CstxHandle *handle, - struct CstxBuffer *output, - struct CstxBuffer *error); +CstxStatusCode cstx_graph_node_types(struct CstxHandle *handle, + struct CstxBuffer *output, + struct CstxBuffer *error); -CstxStatusCode cstx_graph_link_json(struct CstxHandle *handle, - struct CstxSlice node_ids_json, - struct CstxSlice data_source, - struct CstxBuffer *output, - struct CstxBuffer *error); +CstxStatusCode cstx_graph_link(struct CstxHandle *handle, + struct CstxSlice node_ids, + struct CstxSlice data_source, + struct CstxBuffer *output, + struct CstxBuffer *error); CstxStatusCode cstx_graph_update_node_flags(struct CstxHandle *handle, - struct CstxSlice request_json, + struct CstxSlice request_bytes, uint64_t *affected, struct CstxBuffer *error); CstxStatusCode cstx_graph_analyze(struct CstxHandle *handle, - struct CstxSlice algorithm_json, + struct CstxSlice algorithm_bytes, struct CstxSlice selection, uint8_t *kind, uint8_t *boolean, @@ -286,36 +304,36 @@ CstxStatusCode cstx_graph_degree(struct CstxHandle *handle, struct CstxBuffer *error); CstxStatusCode cstx_graph_subgraph(struct CstxHandle *handle, - struct CstxSlice seed_ids_json, + struct CstxSlice seed_ids, uint32_t depth, struct CstxHandle **output, struct CstxBuffer *error); CstxStatusCode cstx_graph_query_subgraph(struct CstxHandle *handle, - struct CstxSlice request_json, + struct CstxSlice request_bytes, struct CstxHandle **output, struct CstxBuffer *error); CstxStatusCode cstx_graph_induced_subgraph(struct CstxHandle *handle, - struct CstxSlice request_json, + struct CstxSlice request_bytes, struct CstxHandle **output, struct CstxBuffer *error); CstxStatusCode cstx_graph_filter(struct CstxHandle *handle, - struct CstxSlice request_json, + struct CstxSlice request_bytes, struct CstxHandle **output, struct CstxBuffer *error); -CstxStatusCode cstx_graph_filter_with_reasons_json(struct CstxHandle *handle, - struct CstxSlice request_json, - struct CstxHandle **output, - struct CstxBuffer *details_json, - struct CstxBuffer *error); +CstxStatusCode cstx_graph_filter_with_reasons(struct CstxHandle *handle, + struct CstxSlice request_bytes, + struct CstxHandle **output, + struct CstxBuffer *details, + struct CstxBuffer *error); -CstxStatusCode cstx_graph_find_anchors_json(struct CstxHandle *handle, - struct CstxSlice concept_name, - struct CstxBuffer *output, - struct CstxBuffer *error); +CstxStatusCode cstx_graph_find_anchors(struct CstxHandle *handle, + struct CstxSlice concept_name, + struct CstxBuffer *output, + struct CstxBuffer *error); CstxStatusCode cstx_graph_elevate(struct CstxHandle *handle, struct CstxSlice concept_name, @@ -328,36 +346,9 @@ CstxStatusCode cstx_graph_stats(struct CstxHandle *handle, struct CstxBuffer *output, struct CstxBuffer *error); -CstxStatusCode cstx_graph_nodes_page_json(struct CstxHandle *handle, - struct CstxSlice request_json, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_graph_nodes_json(struct CstxHandle *handle, - struct CstxSlice node_type, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_graph_edges_json(struct CstxHandle *handle, - struct CstxSlice source_id, - struct CstxSlice target_id, - struct CstxSlice relation, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_graph_neighbors_json(struct CstxHandle *handle, - struct CstxSlice node_id, - struct CstxSlice direction, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_graph_query_json(struct CstxHandle *handle, - struct CstxSlice expression, - size_t limit, - uint8_t has_limit, - struct CstxBuffer *output, - struct CstxBuffer *error); - +/** + * Materialize one cursor page as protobuf bytes. + */ CstxStatusCode cstx_graph_cursor_page(struct CstxGraphCursor *cursor, size_t limit, size_t page, @@ -366,6 +357,9 @@ CstxStatusCode cstx_graph_cursor_page(struct CstxGraphCursor *cursor, void cstx_graph_cursor_free(struct CstxGraphCursor *cursor); +/** + * Resolve a revision and return its UTF-8 commit id in `output`. + */ CstxStatusCode cstx_repo_resolve(struct CstxHandle *handle, struct CstxSlice revision, struct CstxBuffer *output, @@ -381,7 +375,7 @@ CstxStatusCode cstx_repo_commit(struct CstxHandle *handle, struct CstxSlice message, struct CstxSlice ref_name, struct CstxSlice expected_head, - struct CstxSlice metadata_json, + struct CstxSlice metadata, struct CstxBuffer *output, struct CstxBuffer *error); @@ -389,7 +383,7 @@ CstxStatusCode cstx_repo_prepare(struct CstxHandle *handle, struct CstxSlice message, struct CstxSlice ref_name, struct CstxSlice expected_head, - struct CstxSlice metadata_json, + struct CstxSlice metadata, int64_t timestamp, uint8_t has_timestamp, struct CstxBuffer *output, @@ -402,7 +396,7 @@ CstxStatusCode cstx_repo_accept(struct CstxHandle *handle, CstxStatusCode cstx_repo_discard(struct CstxHandle *handle, struct CstxBuffer *error); CstxStatusCode cstx_repo_synchronize(struct CstxHandle *handle, - struct CstxSlice payload_json, + struct CstxSlice payload_bytes, struct CstxBuffer *error); CstxStatusCode cstx_repo_contains(struct CstxHandle *handle, @@ -410,59 +404,10 @@ CstxStatusCode cstx_repo_contains(struct CstxHandle *handle, uint8_t *output, struct CstxBuffer *error); -CstxStatusCode cstx_repo_missing_tree(struct CstxHandle *handle, - struct CstxSlice commit, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_repo_object_closure(struct CstxHandle *handle, - struct CstxSlice commit, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_repo_missing_prepare(struct CstxHandle *handle, - struct CstxSlice commit, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_repo_missing_history(struct CstxHandle *handle, - struct CstxSlice commit, - struct CstxSlice entity_id, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_repo_missing_stat(struct CstxHandle *handle, - struct CstxSlice commit, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_repo_missing_commits(struct CstxHandle *handle, - struct CstxSlice commit, - size_t limit, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_repo_missing_diff(struct CstxHandle *handle, - struct CstxSlice base, - struct CstxSlice head, - struct CstxSlice detail, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_repo_missing_delta(struct CstxHandle *handle, - struct CstxSlice commit, - int64_t start_timestamp, - uint8_t has_start, - int64_t end_timestamp, - uint8_t has_end, - struct CstxBuffer *output, - struct CstxBuffer *error); - -CstxStatusCode cstx_repo_missing_merge(struct CstxHandle *handle, - struct CstxSlice source, - struct CstxSlice target, - struct CstxBuffer *output, - struct CstxBuffer *error); +CstxStatusCode cstx_repo_missing(struct CstxHandle *handle, + struct CstxSlice request_bytes, + struct CstxBuffer *output, + struct CstxBuffer *error); CstxStatusCode cstx_repo_release_transient_objects(struct CstxHandle *handle, struct CstxBuffer *error); @@ -476,6 +421,9 @@ CstxStatusCode cstx_repo_diff(struct CstxHandle *handle, struct CstxBuffer *output, struct CstxBuffer *error); +/** + * Return the UTF-8 commit id at a ref, or an empty buffer when it is absent. + */ CstxStatusCode cstx_repo_head(struct CstxHandle *handle, struct CstxSlice ref_name, struct CstxBuffer *output, @@ -495,6 +443,22 @@ CstxStatusCode cstx_repo_history(struct CstxHandle *handle, struct CstxBuffer *output, struct CstxBuffer *error); +/** + * Read entity records at one revision and return a `Graph` in `output`. + * + * The selection's node and relationship ids are one set; the engine tells them + * apart by the `relationship:` prefix, as `history` does. Entities that are not + * live at `revision` are absent from the returned graph. + */ +CstxStatusCode cstx_repo_entities(struct CstxHandle *handle, + struct CstxSlice revision, + struct CstxSlice selection_bytes, + struct CstxBuffer *output, + struct CstxBuffer *error); + +/** + * Create a ref and return the target UTF-8 commit id in `output`. + */ CstxStatusCode cstx_repo_branch(struct CstxHandle *handle, struct CstxSlice name, struct CstxSlice start_point, @@ -526,23 +490,23 @@ CstxStatusCode cstx_repo_delta(struct CstxHandle *handle, struct CstxBuffer *error); CstxStatusCode cstx_rag_index(struct CstxHandle *handle, - struct CstxSlice request_json, + struct CstxSlice request_bytes, struct CstxRagIndexSession **output, struct CstxBuffer *error); -CstxStatusCode cstx_rag_index_session_metadata_json(struct CstxRagIndexSession *session, - struct CstxBuffer *output, - struct CstxBuffer *error); +CstxStatusCode cstx_rag_index_session_metadata(struct CstxRagIndexSession *session, + struct CstxBuffer *output, + struct CstxBuffer *error); -CstxStatusCode cstx_rag_index_session_pending_json(struct CstxRagIndexSession *session, - size_t offset, - size_t limit, - struct CstxBuffer *output, - struct CstxBuffer *error); +CstxStatusCode cstx_rag_index_session_pending(struct CstxRagIndexSession *session, + size_t offset, + size_t limit, + struct CstxBuffer *output, + struct CstxBuffer *error); -CstxStatusCode cstx_rag_index_session_deletes_json(struct CstxRagIndexSession *session, - struct CstxBuffer *output, - struct CstxBuffer *error); +CstxStatusCode cstx_rag_index_session_deletes(struct CstxRagIndexSession *session, + struct CstxBuffer *output, + struct CstxBuffer *error); CstxStatusCode cstx_rag_index_session_records(struct CstxRagIndexSession *session, struct CstxRagRecordIterator **output, @@ -562,18 +526,18 @@ void cstx_rag_index_session_close(struct CstxRagIndexSession *session); void cstx_rag_index_session_free(struct CstxRagIndexSession *session); CstxStatusCode cstx_rag_retrieve(struct CstxHandle *handle, - struct CstxSlice query_json, + struct CstxSlice query_bytes, struct CstxRagRetrieval **output, struct CstxBuffer *error); -CstxStatusCode cstx_rag_retrieval_requests_json(struct CstxRagRetrieval *retrieval, - struct CstxBuffer *output, - struct CstxBuffer *error); +CstxStatusCode cstx_rag_retrieval_requests(struct CstxRagRetrieval *retrieval, + struct CstxBuffer *output, + struct CstxBuffer *error); -CstxStatusCode cstx_rag_retrieval_complete_json(struct CstxRagRetrieval *retrieval, - struct CstxSlice batches_json, - struct CstxBuffer *output, - struct CstxBuffer *error); +CstxStatusCode cstx_rag_retrieval_complete(struct CstxRagRetrieval *retrieval, + struct CstxSlice batches_bytes, + struct CstxBuffer *output, + struct CstxBuffer *error); void cstx_rag_retrieval_close(struct CstxRagRetrieval *retrieval); diff --git a/python/pyproject.toml b/python/pyproject.toml index 7542b0b..da6a5fd 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -7,7 +7,11 @@ name = "cstxpy" requires-python = ">=3.10" description = "Native Python bindings for the CSTX unified runtime" dynamic = ["version"] -dependencies = ["pydantic>=2.0.0,<3.0.0"] +dependencies = [ + "protobuf>=6.33.0,<7.0.0", + "pydantic>=2.0.0,<3.0.0", +] + license = { text = "MIT" } classifiers = [ "Programming Language :: Rust", diff --git a/python/python/cstxpy/__init__.py b/python/python/cstxpy/__init__.py index d3cff9d..b01cfd7 100644 --- a/python/python/cstxpy/__init__.py +++ b/python/python/cstxpy/__init__.py @@ -9,17 +9,22 @@ RagRetrieval, RagIndexSession, RagRecordCursor, - NodeFlags, Repository, - Schemas, + Extensions, + Algorithm, + decode_object, __version__, is_path_expression, ) +from cstxpy.flags import NodeFlags +from . import proto __all__ = [ "CSTX", "CSTXError", - "Schemas", + "Extensions", + "Algorithm", + "decode_object", "CSTXGraph", "Rag", "RagRetrieval", @@ -30,4 +35,5 @@ "NodeFlags", "is_path_expression", "__version__", + "proto", ] diff --git a/python/python/cstxpy/_cstxpy.pyi b/python/python/cstxpy/_cstxpy.pyi index ea49289..84e59be 100644 --- a/python/python/cstxpy/_cstxpy.pyi +++ b/python/python/cstxpy/_cstxpy.pyi @@ -1,11 +1,4 @@ -"""Typed public surface for the low-level CSTX Rust runtime. - -The binding deliberately exposes ordinary ``dict``, ``list``, ``bytes``, -``int``, keyword arguments, and iterators. It does not introduce public node, -filter, or options wrapper classes. ``*_json`` methods are explicit transport -fast paths for data that is already JSON or must leave CSTX as JSON; they are -not replacements for the native Python APIs. -""" +"""Typed public surface for the low-level CSTX Rust runtime.""" from __future__ import annotations @@ -14,23 +7,32 @@ from typing import Any, Iterator __version__: str -def _object_id(envelope: bytes) -> bytes: - """Validate one internal object envelope and return its 32-byte ObjectId.""" +def decode_object(envelope: bytes) -> tuple[bytes, str]: + """Validate an object envelope once and return its ID and kind.""" ... -def _object_kind(envelope: bytes) -> str: - """Validate one internal object envelope and return its closed object kind.""" +def is_path_expression(expression: str) -> bool: + """Classify CSTX path syntax with the native parser.""" ... -def _verify_object(envelope: bytes) -> tuple[bytes, str]: - """Validate once and return the internal ObjectId and object kind.""" +def _normalize_semantic_text(text: str) -> str: + """Normalize one string the way semantic indexing compares them. + + Private because the name callers use is ``cstx.models.semantic``'s + re-export; the computation lives in Rust so one text normalizes the same + way here and inside the RAG index. + """ ... -def is_path_expression(expression: str) -> bool: - """Classify CSTX path syntax with the native parser.""" +def _readable_framework_terms(values: list[str | None] | None = None) -> list[str]: + """Split framework labels into the terms a reader would search for. + + Accepts ``None`` for the list and for any element, because the field it + reads is an optional repeated column. + """ ... @@ -51,7 +53,70 @@ class CSTXError(Exception): """Observed type or value description when available.""" -class GraphCursor(Iterator[dict[str, Any]]): +class Algorithm: + """Typed graph algorithm request built at the Python boundary.""" + + @staticmethod + def bfs(seed_id: str, depth: int = 0, direction: str = "out", + max_visited_nodes: int | None = None, timeout_ms: int | None = None) -> Algorithm: + """Build a breadth-first traversal request.""" + ... + @staticmethod + def weak_components() -> Algorithm: + """Build a weakly connected-components request.""" + ... + @staticmethod + def strong_components() -> Algorithm: + """Build a strongly connected-components request.""" + ... + @staticmethod + def cycle_basis() -> Algorithm: + """Build a cycle-basis request.""" + ... + @staticmethod + def bridges() -> Algorithm: + """Build a bridge-edge request.""" + ... + @staticmethod + def articulation_points() -> Algorithm: + """Build an articulation-point request.""" + ... + @staticmethod + def core_numbers() -> Algorithm: + """Build a core-number request.""" + ... + @staticmethod + def is_dag() -> Algorithm: + """Build a directed-acyclic-graph check request.""" + ... + @staticmethod + def topological_order() -> Algorithm: + """Build a topological-order request.""" + ... + @staticmethod + def betweenness(include_endpoints: bool = False, normalized: bool = True, + top_k: int | None = None) -> Algorithm: + """Build a betweenness-centrality request.""" + ... + @staticmethod + def closeness(wf_improved: bool = True, top_k: int | None = None) -> Algorithm: + """Build a closeness-centrality request.""" + ... + @staticmethod + def leiden(resolution: float = 1.0, min_community_size: int = 2, + top_k: int | None = None) -> Algorithm: + """Build a Leiden community-detection request.""" + ... + @staticmethod + def shortest_paths(start_id: str, end_id: str, direction: str = "out", + max_depth: int = 0, limit: int = 10, + max_visited_nodes: int | None = None, + timeout_ms: int | None = None) -> Algorithm: + """Build a shortest-path enumeration request.""" + ... + + +class GraphCursor(Iterator[bytes]): """Unified graph-result cursor with one-based ``limit + page`` pagination.""" @property @@ -59,8 +124,12 @@ class GraphCursor(Iterator[dict[str, Any]]): """Logical row shape emitted by this cursor.""" ... - def page(self, limit: int = 1024, page: int = 1) -> dict[str, Any]: - """Materialize one page without rerunning the originating operation.""" + def next(self) -> bytes | None: + """Return the next Node or Relationship protobuf row.""" + ... + + def page(self, limit: int = 1024, page: int = 1) -> bytes: + """Materialize one page as a typed ``GraphResultPage`` protobuf.""" ... @property @@ -81,96 +150,116 @@ class GraphCursor(Iterator[dict[str, Any]]): ... -class Schemas: - """Schema/plugin namespace sharing state with its owning ``CSTX`` runtime.""" +class Extensions: + """Unified extension lifecycle and schema namespace.""" - def import_schema(self, schema: dict[str, Any]) -> None: - """Atomically validate and register a portable schema contract.""" + def register(self, contract: bytes) -> None: + """Atomically register one serialized ExtensionContract protobuf.""" ... - def export_schema(self) -> dict[str, Any]: - """Export the complete portable schema contract.""" + def export_contract(self) -> bytes: + """Return what this runtime holds as an ``ExtensionContract`` protobuf. + + A read-only snapshot, not a second registry: it is how a caller + refreshes its own view from what the core accepted rather than from + the contract it sent. + """ ... - def register( - self, - node_type: str, - schema: dict[str, Any], - value_field: str | None = None, - ) -> None: - """Register CSTX validation metadata without a Python schema wrapper.""" + def enable(self, name: str) -> None: + """Explicitly enable one linked native Rust extension.""" ... - def register_join_rule(self, rule: dict[str, Any]) -> None: - """Register a native linker rule using the KeyExpr DSL.""" + def list(self) -> bytes: + """List metadata as an ``ExtensionCatalog`` protobuf.""" + ... + + def info(self, name: str) -> bytes: + """Return metadata as an ``ExtensionInfo`` protobuf.""" ... def contains(self, node_type: str) -> bool: - """Check schema existence without materializing the schema dictionary.""" + """Check schema existence.""" ... - def get(self, node_type: str) -> dict[str, Any]: - """Return one retained schema as an ordinary dictionary.""" + def schema(self, node_type: str) -> bytes: + """Return one retained schema as a ``NodeType`` protobuf.""" ... - def list(self) -> list[dict[str, Any]]: - """Return retained schemas in deterministic node-type order.""" + def schemas(self) -> bytes: + """Return retained schemas as a ``NodeTypeCatalog`` protobuf.""" ... - def load_plugin(self, name: str) -> None: - """Load one linked native plugin into the shared graph engine.""" + def parses_artifact(self, artifact: str) -> bool: + """Return whether an enabled native parser supports an artifact.""" ... - def load_all_plugins(self) -> None: - """Load every linked native plugin into the shared graph engine.""" + def anchor_concepts(self) -> bytes: + """List native concepts as an ``AnchorConceptCatalog`` protobuf.""" ... - def available_plugins(self) -> list[str]: - """List linked plugins without changing runtime state.""" + +class CSTXGraph: + """Rust-owned in-memory graph handle.""" + + def rag(self) -> Rag: + """Return the GraphRAG extension bound to this graph.""" ... - def plugin_artifacts(self, name: str) -> list[str]: - """List artifacts provided by one linked plugin.""" + def add_nodes(self, data: bytes) -> int: + """Add a serialized semantic ``Graph`` protobuf.""" ... - def has_native_artifact(self, artifact: str) -> bool: - """Return whether a linked native parser supports this artifact.""" + def replace_nodes(self, data: bytes) -> int: + """Replace graph contents from a serialized semantic ``Graph`` protobuf.""" ... - def anchor_concepts(self) -> list[tuple[str, list[str]]]: - """List native anchor concepts and member node types.""" + def add_relationships(self, data: bytes) -> int: + """Add relationships from a serialized semantic ``Graph`` protobuf.""" ... + def node(self, node_id: str) -> bytes: + """Return one semantic ``Node`` protobuf.""" + ... -class CSTXGraph: - """Rust-owned in-memory graph handle.""" + def relationship(self, relationship_id: str) -> bytes: + """Return one semantic ``Relationship`` protobuf.""" + ... - def rag(self) -> Rag: - """Return the GraphRAG extension bound to this graph.""" + def find_node(self, identifier: str) -> bytes: + """Resolve an identifier and return a semantic ``Node`` protobuf.""" ... - def ingest_native( - self, plugin: str, artifact: str, data: bytes - ) -> dict[str, Any]: - """Ingest plugin bytes and return detailed native mutation statistics.""" + def nodes(self, filter: bytes, window: bytes) -> GraphCursor: + """Create a cursor from serialized ``NodeFilter`` and ``QueryWindow``.""" ... - def link(self, node_ids: list[str], data_source: str) -> dict[str, Any]: - """Run native linker rules for selected nodes.""" + def relationships(self, filter: bytes, window: bytes) -> GraphCursor: + """Create a cursor from serialized ``RelationshipFilter`` and ``QueryWindow``.""" ... - def update_node_flags( - self, - node_ids: list[str], - add: int = 0, - remove: int = 0, - set_to: int | None = None, - ) -> int: - """Atomically update selected nodes' native flag bitsets.""" + def neighbors(self, data: bytes) -> GraphCursor: + """Create a cursor from serialized ``NeighborQuery``.""" + ... + + def query(self, data: bytes) -> GraphCursor: + """Create a cursor from serialized ``GraphQuery``.""" + ... + + def _parse(self, data: bytes) -> tuple[bytes, int]: + """Parse ``ParserPayload`` into serialized ``Graph`` bytes and a record count.""" + ... + + def link(self, selection: bytes, data_source: str) -> bytes: + """Run linker rules from a ``GraphSelection`` protobuf payload.""" + ... + + def update_node_flags(self, data: bytes) -> int: + """Atomically update selected nodes from a serialized ``NodeFlagChange``.""" ... def analyze( - self, algorithm: dict[str, Any], selection: str | None = None + self, algorithm: Algorithm, selection: str | None = None ) -> bool | GraphCursor | None: """Execute one typed graph algorithm.""" ... @@ -197,9 +286,9 @@ class CSTXGraph: ... def induced_subgraph( - self, node_ids: list[str], edge_ids: list[str] | None = None + self, node_ids: list[str], relationship_ids: list[str] | None = None ) -> CSTX: - """Materialize selected nodes and optional edges.""" + """Materialize selected nodes and optional relationships.""" ... def filter( @@ -220,62 +309,28 @@ class CSTXGraph: """Return a filtered graph, exclusions with reasons, and reuse status.""" ... - def find_anchors(self, concept_name: str) -> list[dict[str, Any]]: - """Find native anchor instances by concept name.""" + def find_anchors(self, concept_name: str) -> bytes: + """Find native anchors as a ``GraphAnchorCatalog`` protobuf.""" ... def elevate(self, concept_name: str) -> CSTX: """Return an elevated graph handle.""" ... - def add_nodes(self, nodes: list[dict[str, Any]]) -> int: - """Atomically mutate native dictionaries without a JSON round trip.""" - ... - - def replace_nodes(self, nodes: list[dict[str, Any]]) -> int: - """Atomically overwrite native dictionaries instead of merging them.""" - ... - - def add_edges(self, edges: list[dict[str, Any]]) -> int: - """Atomically mutate native relationship dictionaries.""" - ... - def delete_nodes(self, node_ids: list[str]) -> int: """Atomically remove nodes and their incident relationships.""" ... - def delete_edges(self, edge_ids: list[str]) -> int: + def delete_relationships(self, relationship_ids: list[str]) -> int: """Atomically remove relationships by stable CSTX ID.""" ... - def node(self, node_id: str) -> dict[str, Any]: - """Return one node dictionary or raise ``CSTXError(NOT_FOUND)``.""" - ... - - def edge(self, edge_id: str) -> dict[str, Any]: - """Return one relationship dictionary or raise ``CSTXError(NOT_FOUND)``.""" - ... - - def find_node(self, identifier: str) -> dict[str, Any] | None: - """Resolve a node by ID, value, or extras.name.""" + def patch_node_annotations(self, data: bytes) -> int: + """Merge annotations from a serialized ``NodeAnnotationUpdate``.""" ... - def patch_node_extras( - self, node_ids: list[str] | None, patch: dict[str, Any] - ) -> int: - """Merge contextual fields into selected node extras; None selects all.""" - ... - - def create_relationship( - self, - source_id: str, - target_id: str, - relation: str, - sources: list[str] = [], - attrs: dict[str, Any] | None = None, - identity_key: str | None = None, - ) -> dict[str, Any]: - """Create or merge a relationship with Rust-owned identity.""" + def add_relationship(self, data: bytes) -> bytes: + """Create or merge one relationship from a serialized protobuf.""" ... def union(self, other: CSTXGraph) -> CSTX: @@ -304,7 +359,7 @@ class CSTXGraph: """Return the current number of nodes.""" ... - def edge_count(self) -> int: + def relationship_count(self) -> int: """Return the current number of relationships.""" ... @@ -313,82 +368,10 @@ class CSTXGraph: exclude_mask: int = 0, include_mask: int = 0, selection: str | None = None, - ) -> dict[str, dict[str, int]]: - """Return aggregate counts for an optional query selection and flag masks.""" - ... - - def nodes( - self, - types: list[str] | None = None, - ids: list[str] | None = None, - sources: list[str] | None = None, - name_contains: str | None = None, - flags_all: int = 0, - flags_any: int = 0, - flags_none: int = 0, - limit: int | None = None, - page: int = 1, - order: str = "unspecified", - ) -> GraphCursor: - """Create a unified cursor over matching node dictionaries. - - Keyword filters avoid public filter/options wrapper objects. ``order`` - accepts ``unspecified``, ``id_asc``, or ``id_desc``. - """ - ... - - def nodes_page( - self, - node_type: str | None = None, - name_pattern: str | None = None, - exclude_mask: int = 0, - include_mask: int = 0, - limit: int = 500, - page: int = 1, - ) -> dict[str, Any]: - """Return one bounded node page with exact totals and type counts.""" - ... - - def edges( - self, - source_id: str | None = None, - target_id: str | None = None, - relations: list[str] | None = None, - sources: list[str] | None = None, - limit: int | None = None, - page: int = 1, - order: str = "unspecified", - ) -> GraphCursor: - """Create a unified cursor over matching relationship dictionaries.""" - ... - - def neighbors( - self, - node_id: str, - direction: str = "out", - limit: int | None = None, - page: int = 1, - order: str = "unspecified", - ) -> GraphCursor: - """Return a unified cursor over neighboring nodes.""" - ... - - def query( - self, - expression: str, - limit: int | None = None, - page: int = 1, - types: list[str] | None = None, - ids: list[str] | None = None, - name_contains: str | None = None, - exclude_mask: int = 0, - include_mask: int = 0, - order: str = "unspecified", - ) -> GraphCursor: - """Execute the graph DSL once and return a unified result cursor.""" + ) -> bytes: + """Return aggregate counts as a ``GraphStats`` protobuf payload.""" ... - class Repository: """Git-like repository over one shared working tree.""" @@ -405,10 +388,10 @@ class Repository: message: str, ref_name: str, expected_head: str | None = None, - metadata: dict[str, Any] | None = None, + metadata: bytes | None = None, timestamp: int | None = None, - ) -> tuple[dict[str, Any], bytes, list[tuple[bytes, str, bytes]]]: - """Prepare one complete commit payload for external publication.""" + ) -> bytes: + """Prepare a serialized ``PublicationPlan`` protobuf.""" ... def _accept(self, commit: bytes) -> None: @@ -425,79 +408,25 @@ class Repository: target: str = "main", expected_head: str | None = None, message: str | None = None, - metadata: dict[str, Any] | None = None, + metadata: bytes | None = None, timestamp: int | None = None, - ) -> tuple[dict[str, Any], bytes, list[tuple[bytes, str, bytes]]]: - """Prepare one complete merge payload for external publication.""" - ... - - def _synchronize( - self, - objects: list[tuple[bytes, bytes]], - refs: list[tuple[str, bytes | None]], - indexes: list[tuple[bytes, bytes]], - ) -> None: - """Synchronize externally persisted objects, refs, and indexes.""" - ... - - def _missing_tree(self, commit: bytes) -> list[bytes]: - """Return graph-tree objects missing from the native object set.""" - ... - - def _object_closure(self, commit: bytes) -> list[bytes]: - """Return every object this commit and its ancestry are built from.""" - ... - - def _missing_stat(self, commit: bytes) -> list[bytes]: - """Return the graph root needed for persisted statistics.""" - ... - - def _missing_merge( - self, - source: bytes, - target: bytes | None = None, - ) -> list[bytes]: - """Return the commit frontier or graph objects needed by merge.""" - ... - - def _missing_delta( - self, - commit: bytes, - start_timestamp: int | None = None, - end_timestamp: int | None = None, - ) -> list[bytes]: - """Return index nodes needed for a time-bounded delta.""" - ... - - def _missing_prepare(self, commit: bytes) -> list[bytes]: - """Return index nodes needed to prepare the working journal.""" + ) -> bytes: + """Prepare a serialized merge ``PublicationPlan`` protobuf.""" ... - def _missing_history(self, commit: bytes, entity: str) -> list[bytes]: - """Return index nodes needed for one entity history.""" + def _synchronize(self, data: bytes) -> None: + """Synchronize from a serialized ``RepositoryState`` protobuf.""" ... - def _missing_commits(self, commit: bytes, limit: int) -> list[bytes]: - """Return index nodes needed for a bounded commit log.""" - ... + def _missing(self, data: bytes) -> bytes: + """Return a serialized ``ObjectSelection`` protobuf for one plan. - def _missing_diff( - self, - base: bytes, - head: bytes, - detail: str = "entities", - ) -> list[bytes]: - """Return index or graph objects needed for a revision diff. - - A limit never narrows the plan, so the request carries only the detail - level: ``"counts"`` skips the pages a page summary already answers for. + The argument is a serialized ``RepositoryObjectPlan``. It is named + ``data`` because the binding names it that, and a keyword call has to + reach the binding, not the stub. """ ... - def _commits(self, commit: bytes, limit: int) -> list[bytes]: - """Return bounded first-parent commit objects for synchronization.""" - ... - def resolve(self, revision: str) -> str: """Resolve a branch or object ID to a commit ID.""" ... @@ -510,8 +439,8 @@ class Repository: self, revision: str = "main", force: bool = False, - ) -> dict[str, Any]: - """Replace the working tree with one committed graph.""" + ) -> bytes: + """Replace the working tree and return a serialized ``Commit`` protobuf.""" ... def commit( @@ -519,10 +448,10 @@ class Repository: message: str, ref_name: str = "main", expected_head: str | None = None, - metadata: Any | None = None, + metadata: bytes | None = None, timestamp: int | None = None, - ) -> dict[str, Any]: - """Commit the working tree and atomically advance one branch.""" + ) -> bytes: + """Commit the working tree and return a serialized ``Commit`` protobuf.""" ... def diff( @@ -531,8 +460,8 @@ class Repository: head: str, limit: int | None = None, detail: str = "entities", - ) -> dict[str, Any]: - """Compare two revisions. + ) -> bytes: + """Compare two revisions and return a serialized ``GraphDiff`` protobuf. ``limit`` bounds the reported entity IDs; ``detail="counts"`` drops them entirely. ``stats`` counts the whole range either way. @@ -543,8 +472,16 @@ class Repository: self, revision: str = "main", limit: int = 50, - ) -> list[dict[str, Any]]: - """Return first-parent commits newest first.""" + ) -> bytes: + """Return a serialized ``CommitLog`` protobuf.""" + ... + + def entities( + self, + entity_ids: list[str], + revision: str = "main", + ) -> bytes: + """Return a serialized ``Graph`` protobuf of the entities that are live.""" ... def history( @@ -552,8 +489,8 @@ class Repository: entity_id: str, revision: str = "main", limit: int | None = None, - ) -> list[dict[str, Any]]: - """Return indexed changes for one node or relationship.""" + ) -> bytes: + """Return a serialized ``EntityHistory`` protobuf.""" ... def branch(self, name: str, start_point: str = "main") -> str: @@ -566,10 +503,10 @@ class Repository: target: str = "main", expected_head: str | None = None, message: str | None = None, - metadata: Any | None = None, + metadata: bytes | None = None, timestamp: int | None = None, - ) -> dict[str, Any]: - """Merge one branch or commit into a target branch.""" + ) -> bytes: + """Merge one branch and return a serialized ``Commit`` protobuf.""" ... def stat( @@ -577,8 +514,8 @@ class Repository: revision: str = "main", exclude_mask: int = 0, include_mask: int = 0, - ) -> dict[str, dict[str, int]]: - """Return persisted graph aggregates without loading graph state.""" + ) -> bytes: + """Return persisted aggregates as a serialized ``GraphStats`` protobuf.""" ... def delta( @@ -586,20 +523,20 @@ class Repository: revision: str = "main", start_timestamp: int | None = None, end_timestamp: int | None = None, - ) -> dict[str, Any]: - """Return a time-bounded commit-index delta without loading graph state.""" + ) -> bytes: + """Return a time-bounded delta as a serialized ``GraphChangeSummary`` protobuf.""" ... class Rag: """Graph-owned projection and retrieval planner.""" - def index(self, request: dict[str, Any]) -> RagIndexSession: - """Project graph changes into a retained deterministic index session.""" + def index(self, data: bytes) -> RagIndexSession: + """Project a serialized ``RagIndexPlan`` protobuf into a retained session.""" ... - def retrieve(self, query: dict[str, Any]) -> RagRetrieval: - """Suspend retrieval until external recall batches are supplied.""" + def retrieve(self, data: bytes) -> RagRetrieval: + """Suspend retrieval from a serialized ``RagQuery`` protobuf.""" ... @@ -638,18 +575,9 @@ class RagIndexSession: """Stream projected records through a bounded native cursor.""" ... - def pending_json( - self, - _model_revision: str, - batch_size: int = 512, - ) -> bytes: - """Return one projected-record batch as JSON bytes.""" + def deletes(self) -> list[str]: + """Return deleted record IDs.""" ... - - def deletes_json(self) -> bytes: - """Return deleted record IDs as JSON bytes.""" - ... - def close(self) -> None: """Release the retained projection.""" ... @@ -660,15 +588,15 @@ class RagIndexSession: ... -class RagRecordCursor(Iterator[dict[str, Any]]): - """Bounded iterator over projected record dictionaries.""" +class RagRecordCursor(Iterator[bytes]): + """Bounded iterator over serialized ``RagRecord`` protobuf messages.""" def __iter__(self) -> RagRecordCursor: """Return this cursor as its iterator.""" ... - def __next__(self) -> dict[str, Any]: - """Return the next projected record or raise StopIteration.""" + def __next__(self) -> bytes: + """Return the next projected record protobuf or raise StopIteration.""" ... def close(self) -> None: @@ -684,20 +612,12 @@ class RagRecordCursor(Iterator[dict[str, Any]]): class RagRetrieval: """Suspended retrieval bound to one graph generation and checkpoint.""" - def requests(self) -> list[dict[str, Any]]: - """Return recall requests required to complete this retrieval.""" + def requests(self) -> bytes: + """Return a serialized ``RecallPlan`` protobuf.""" ... - def requests_json(self) -> bytes: - """Return recall requests as JSON bytes.""" - ... - - def complete(self, batches: list[dict[str, Any]]) -> dict[str, Any]: - """Fuse recall batches and build the structured graph context.""" - ... - - def complete_json(self, batches: bytes) -> bytes: - """Fuse JSON batches and return the result as JSON bytes.""" + def complete(self, data: bytes) -> bytes: + """Fuse serialized ``RecallResults`` and return a ``RagResult`` protobuf.""" ... @@ -713,8 +633,8 @@ class CSTX: ... @property - def schemas(self) -> Schemas: - """Return the lightweight schema namespace for this runtime.""" + def extensions(self) -> Extensions: + """Return the unified extension namespace for this runtime.""" ... @property @@ -741,8 +661,8 @@ class CSTX: """Close shared state and invalidate retained services/cursors.""" ... - def last_change(self) -> dict[str, Any]: - """Return IDs changed by the most recent committed mutation.""" + def last_change(self) -> bytes: + """Return the most recent mutation as serialized GraphChangeSet protobuf.""" ... def __enter__(self) -> CSTX: @@ -752,30 +672,3 @@ class CSTX: def __exit__(self, *args: Any) -> None: """Close the shared runtime when its context exits.""" ... - - -class NodeFlags: - """Discoverable namespace of engine-compatible integer bit constants. - - Graph APIs still accept ordinary ``int`` values; this class is not a node - flag wrapper and cannot create instances. - """ - - NONE: int - HONEYPOT: int - NOISE: int - FALSE_POSITIVE: int - MANUAL_IGNORED: int - THREAT_PRESENT: int - HISTORIC_VULNERABLE: int - INTERNAL: int - - @staticmethod - def all_mask() -> int: - """Return a mask containing every currently defined node flag.""" - ... - - @staticmethod - def default_exclude_mask() -> int: - """Return the engine's standard default-exclusion mask.""" - ... diff --git a/python/python/cstxpy/flags.py b/python/python/cstxpy/flags.py new file mode 100644 index 0000000..9c2d20f --- /dev/null +++ b/python/python/cstxpy/flags.py @@ -0,0 +1,113 @@ +"""Node flags, read from the schemas the runtime has loaded. + +A flag is a bit on `Node.flags_mask`, and which bits exist is declared by +extensions in their schema documents — `easm` declares `honeypot`, `noise` and +the rest, because they are its judgements about an asset, not the graph +store's. The runtime holds the mechanism (a 64-bit mask) and never the +vocabulary. + +This class used to be eight constants compiled into the native binding, which +is why no extension but the built-in one could ever have a flag. The names and +values are unchanged; only the place they are declared moved. + +Names resolve in either spelling, so `NodeFlags.HONEYPOT` and +`NodeFlags.bit("honeypot")` are the same question. +""" + +from __future__ import annotations + +from typing import Dict, Iterator, Tuple + +from cstxpy.schema import registry + +__all__ = ("NodeFlags",) + +#: Bits 56-63 belong to the runtime; extensions declare 0-55. +EXTENSION_FLAG_BITS = 56 + + +def _declared() -> Dict[str, Tuple[int, bool]]: + """`name -> (bit, default_exclude)` across every loaded extension. + + Read through the registry on each call rather than cached: an extension + registered at runtime gets its flags answered on the same terms as a + bundled one, which is the whole point of declaring them. + """ + flags: Dict[str, Tuple[int, bool]] = {} + claimed: Dict[int, str] = {} + for name in registry.extensions(): + schema = registry.extension(name) + if schema is None: + continue + for flag, declaration in schema.flags.items(): + # First claimant of a bit keeps it: a bit is what a stored mask + # means, so a second claim would make one stored value ambiguous. + # The core refuses the same way at registration. + if claimed.setdefault(declaration.bit, flag) != flag: + continue + flags[flag] = (declaration.bit, declaration.default_exclude) + return flags + + +class _NodeFlagsMeta(type): + """Resolves `NodeFlags.HONEYPOT` against what extensions declared.""" + + def __getattr__(cls, name: str) -> int: + if name.startswith("_"): + raise AttributeError(name) + bit = cls.bit(name) + if bit is None: + raise AttributeError( + f"no loaded extension declares a node flag named {name.lower()!r}; " + f"declared: {', '.join(sorted(_declared())) or 'none'}" + ) + return 1 << bit + + def __dir__(cls) -> list: + return [*type.__dir__(cls), *(name.upper() for name in _declared())] + + +class NodeFlags(metaclass=_NodeFlagsMeta): + """Node flag bits, as declared by the loaded extensions. + + A namespace, not a wrapper: graph APIs take ordinary ``int`` masks. Names + resolve in either spelling — ``NodeFlags.HONEYPOT`` and + ``NodeFlags.bit("honeypot")`` ask the same question. + """ + + NONE = 0 + + @staticmethod + def bit(name: str) -> "int | None": + """The bit one declared flag occupies, or ``None`` if undeclared.""" + declaration = _declared().get(str(name).lower()) + return None if declaration is None else declaration[0] + + @staticmethod + def mask(name: str) -> int: + """The single-bit mask for one declared flag name; 0 if undeclared.""" + bit = NodeFlags.bit(name) + return 0 if bit is None else 1 << bit + + @staticmethod + def all_mask() -> int: + """Every bit any loaded extension declared.""" + return sum(1 << bit for bit, _ in _declared().values()) + + @staticmethod + def default_exclude_mask() -> int: + """The bits extensions advise hiding from an ordinary view. + + Advice, not enforcement — nothing applies it on its own. A caller asks + for it and passes it back as a filter, which is where the policy + belongs: the same flag is noise on an inventory page and the whole + point on a threat page. + """ + return sum(1 << bit for bit, exclude in _declared().values() if exclude) + + @staticmethod + def names() -> Iterator[Tuple[str, int]]: + """Declared ``(name, bit)`` pairs, lowest bit first.""" + declared = _declared() + for name in sorted(declared, key=lambda key: declared[key][0]): + yield name, declared[name][0] diff --git a/python/python/cstxpy/model.py b/python/python/cstxpy/model.py new file mode 100644 index 0000000..b1bfe49 --- /dev/null +++ b/python/python/cstxpy/model.py @@ -0,0 +1,153 @@ +"""Pydantic model bases built from the runtime schema. + +The high-level ``cstx`` package mixes its runtime model (``Element``/``SCO``) +into these bases. They are derived from :mod:`cstxpy.schema` at import time +rather than emitted by a per-extension code generator, so an extension that +registers a schema at runtime gets model bases on exactly the same terms as +the built-in one — and, since a node's payload crosses the boundary named by +that same schema, its models serialize on the same terms too. + +:func:`base_model` is the only place a base is built. An extension that ran +``make codegen`` additionally ships two generated files — a module binding its +names and a ``.pyi`` declaring what they hold — but neither declares a class: +the module calls straight back into here, and the stub is a static shadow with +no runtime existence. That is the difference between giving a checker something +to read and having two producers of one class. ``cstx``'s +``test_stub_matches_the_runtime_model`` compares the shadow to what this module +builds, field by field. + +protobuf is not involved here. ``cstxpy.proto`` carries the generated messages +used to serialize, and nothing in this module imports them. +""" + +from __future__ import annotations + +from typing import Any, Dict, List, Optional, Tuple, Type + +from pydantic import BaseModel, ConfigDict, Field, create_model + +from cstxpy.schema import FieldSchema, NodeSchema, registry + +__all__ = ("base_model", "base_model_name", "python_type", "annotation_for") + +_INT_TYPES = frozenset( + {"int64", "sint64", "sfixed64", "int32", "uint32", "sint32", "fixed32", "sfixed32"} +) +_FLOAT_TYPES = frozenset({"double", "float"}) + +# One shared config for every derived base: extensions may send fields the +# schema does not declare, and scanner output routinely types numbers as text. +_MODEL_CONFIG = ConfigDict(extra="allow", coerce_numbers_to_str=True) + +# Keyed by node type, but the schema it was built from is kept alongside: an +# extension re-registering a changed schema must not keep handing out a base +# built from the old one. NodeSchema is frozen and replaced wholesale, so an +# identity check is enough. +_cache: Dict[str, "Tuple[NodeSchema, Type[BaseModel]]"] = {} + + +#: Column kinds a document may declare, and the Python type each arrives as. +#: Read, not derived: the document is where a type says what it stores. +_DECLARED_COLUMNS = {"json": dict} + + +def python_type(field: FieldSchema) -> type: + """The Python type one schema field arrives as. + + A field that declares its column is read, not guessed — `column: "json"` + is text on the wire and a document in the column, and only the document + knows that. Everything else follows protobuf's own type table: `int32` is + an integer because protobuf says so. + + The column a field lands in is decided in exactly one place, Rust's + ``FieldSchema::column_type``. Deciding it a second time here is what let + ``int32``/``uint32``/``sint32``/``double`` fields be built as strings that + the core then refused, so this mirrors that decision and + ``test_derived_annotation_survives_the_column_it_lands_in`` walks every + declarable type through the real path to keep the two honest. + """ + declared = _DECLARED_COLUMNS.get(getattr(field, "column", "") or "") + if declared is not None: + return declared + if field.type in _INT_TYPES: + return int + if field.type in _FLOAT_TYPES: + return float + if field.type == "bool": + return bool + return str + + +def annotation_for(field: FieldSchema) -> Tuple[Any, Any]: + """``(annotation, default)`` for one schema field. + + proto3 scalar semantics: a field that carries no presence is always + populated, so it defaults to its zero value rather than to ``None``. Only + repeated fields distinguish "absent" from "empty". + """ + if field.repeated: + # Repeated fields of any element type are stored as string lists; + # registration refuses a repeated non-string for that reason. + return (Optional[List[str]], Field(default=None)) + if python_type(field) is dict: + # A declared bag is absent until something goes in it. Unlike a proto3 + # scalar it has no zero value that means "unset" — `{}` would claim the + # producer sent an empty bag. + return (Optional[Dict[str, Any]], Field(default=None)) + annotation = python_type(field) + if not field.optional: + return (annotation, ...) + return (annotation, Field(default=annotation())) + + +def base_model_name(node: NodeSchema) -> str: + """``easm.Subdomain`` -> ``SubdomainBase``.""" + return f"{node.message.rsplit('.', 1)[-1]}Base" + + +def base_model(node_type: str) -> Type[BaseModel]: + """Return (and memoize) the pydantic base for one node type.""" + node = registry.node(node_type) + if node is None: + raise KeyError(f"unknown node type: {node_type}") + cached = _cache.get(node_type) + if cached is not None and cached[0] is node: + return cached[1] + model = create_model( + base_model_name(node), + __config__=_MODEL_CONFIG, + __doc__=f"Schema base for the {node.node_type!r} node type.", + **{field.name: annotation_for(field) for field in node.fields}, + ) + _cache[node_type] = (node, model) + return model + + +_by_class_name: Dict[str, str] = {} + + +def _index() -> Dict[str, str]: + """``SubdomainBase`` -> ``subdomain``, refreshed as extensions register.""" + for node_type in registry.node_types(): + node = registry.node(node_type) + if node is not None: + _by_class_name[base_model_name(node)] = node_type + return _by_class_name + + +def __getattr__(name: str) -> Type[BaseModel]: + """Resolve ``DomainBase`` and friends for an extension with no generated module. + + A dynamic name, so a static checker sees nothing here — which is why an + extension that runs codegen imports from its own generated module instead. + Both spellings end at :func:`base_model`; this one is what an extension that + registered its schema at runtime has, and it must keep working. + """ + node_type = _index().get(name) + if node_type is None: + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") + return base_model(node_type) + + +def __dir__() -> List[str]: + return [*__all__, *_index()] diff --git a/python/python/cstxpy/proto/README.md b/python/python/cstxpy/proto/README.md new file mode 100644 index 0000000..7739fb2 --- /dev/null +++ b/python/python/cstxpy/proto/README.md @@ -0,0 +1,29 @@ +# CSTX protobuf package + +The generated Python module is the native wire model. `cstxpy.proto` carries the +transport — nodes, relationships, graphs, filters, pages and repository +messages — and nothing else. Extension types are generated by `make codegen` +as a separate typed layer over schema-named values. Runtime-declared types use +the same value shape without requiring generated code. + +The C ABI accepts and returns these messages as protobuf bytes. `make proto` +generates the Python package with the official protobuf compiler from the same +source used by Rust and Go. `GraphCursor.page()` returns the generated +`GraphResultPage` directly; iterator methods are the explicit opt-in +semantic/domain adapter. + +At the low-level `cstxpy` package a node carries its payload as `Node.value`, +an `EntityValue` naming its fields from the extension's registered schema +document. A relationship carries `Relationship.value` the same way. These are +the sole payload fields; retired field numbers stay `reserved` and cannot be +reused. + +The high-level `cstx` package installs convenience properties on these same +generated classes. There, `node.value` is the semantic identity string, +`node.payload` is the raw `EntityValue`, and both nodes and relationships expose +`type`, `model`, `extra` and `annotations` directly. Relationship endpoints +remain `source_id` and `target_id`. No wrapper object is introduced. + +Open-ended annotations are represented by `google.protobuf.Struct`, and +repository metadata uses that same `Struct` wire. No legacy envelope +compatibility path is provided. diff --git a/python/python/cstxpy/proto/__init__.py b/python/python/cstxpy/proto/__init__.py new file mode 100644 index 0000000..508d609 --- /dev/null +++ b/python/python/cstxpy/proto/__init__.py @@ -0,0 +1 @@ +"""Official protobuf generated modules.""" diff --git a/python/python/cstxpy/proto/cstx_pb2.py b/python/python/cstxpy/proto/cstx_pb2.py new file mode 100644 index 0000000..c456ef4 --- /dev/null +++ b/python/python/cstxpy/proto/cstx_pb2.py @@ -0,0 +1,309 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: cstx.proto +# Protobuf Python Version: 6.33.0 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 33, + 0, + '', + 'cstx.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2 +from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\ncstx.proto\x12\x04\x63stx\x1a google/protobuf/descriptor.proto\x1a\x1cgoogle/protobuf/struct.proto\"o\n\x0f\x43stxNodeOptions\x12\x11\n\tnode_type\x18\x01 \x01(\t\x12\x13\n\x0bvalue_field\x18\x02 \x01(\t\x12\x19\n\x11identity_computed\x18\x04 \x01(\x08\x12\x13\n\x0blabel_field\x18\x05 \x01(\tJ\x04\x08\x03\x10\x04\"1\n\x12\x43stxComputeOptions\x12\x0c\n\x04\x66rom\x18\x01 \x01(\t\x12\r\n\x05\x61pply\x18\x02 \x01(\t\"\xcc\x01\n\x10\x43stxFieldOptions\x12\x10\n\x08identity\x18\x01 \x01(\x08\x12\x17\n\x0fidentity_format\x18\x02 \x01(\t\x12\x15\n\x08semantic\x18\x03 \x01(\x08H\x00\x88\x01\x01\x12\x16\n\x0esemantic_label\x18\x04 \x01(\t\x12\x0e\n\x06\x63olumn\x18\x06 \x01(\t\x12\x16\n\x0eordered_values\x18\x05 \x03(\t\x12)\n\x07\x63ompute\x18\x07 \x01(\x0b\x32\x18.cstx.CstxComputeOptionsB\x0b\n\t_semantic\"4\n\x17\x43stxRelationshipOptions\x12\x19\n\x11relationship_type\x18\x01 \x01(\t\"F\n\x0f\x43stxFlagOptions\x12\x0b\n\x03\x62it\x18\x01 \x01(\r\x12\x17\n\x0f\x64\x65\x66\x61ult_exclude\x18\x02 \x01(\x08\x12\r\n\x05label\x18\x03 \x01(\t\"S\n\rRuntimeConfig\x12\x12\n\nproject_id\x18\x01 \x01(\t\x12\x18\n\x10\x63ursor_page_size\x18\x02 \x01(\x04J\x04\x08\x03\x10\x04R\x0epayload_format\"\x1c\n\nStringList\x12\x0e\n\x06values\x18\x01 \x03(\t\"\x88\x01\n\x0b\x45ntityField\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0e\n\x04text\x18\x02 \x01(\tH\x00\x12\x10\n\x06number\x18\x03 \x01(\x03H\x00\x12\x0e\n\x04\x66lag\x18\x04 \x01(\x08H\x00\x12\x0e\n\x04real\x18\x05 \x01(\x01H\x00\x12 \n\x04list\x18\x06 \x01(\x0b\x32\x10.cstx.StringListH\x00\x42\x07\n\x05value\"C\n\x0b\x45ntityValue\x12\x11\n\tnode_type\x18\x01 \x01(\t\x12!\n\x06\x66ields\x18\x02 \x03(\x0b\x32\x11.cstx.EntityField\"Q\n\x11RelationshipValue\x12\x19\n\x11relationship_type\x18\x01 \x01(\t\x12!\n\x06\x66ields\x18\x02 \x03(\x0b\x32\x11.cstx.EntityField\"\xae\x01\n\x04Node\x12\x0f\n\x02id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x0f\n\x07sources\x18\x03 \x03(\t\x12,\n\x0b\x61nnotations\x18\x04 \x01(\x0b\x32\x17.google.protobuf.Struct\x12 \n\x05value\x18\x06 \x01(\x0b\x32\x11.cstx.EntityValue\x12\x12\n\nflags_mask\x18\x07 \x01(\x04\x42\x05\n\x03_idJ\x04\x08\x05\x10\x06J\x04\x08\x02\x10\x03R\x05\x66lagsR\x06\x65ntity\"\xc3\x01\n\x0cRelationship\x12\x0f\n\x02id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x11\n\tsource_id\x18\x02 \x01(\t\x12\x11\n\ttarget_id\x18\x03 \x01(\t\x12\x0f\n\x07sources\x18\x05 \x03(\t\x12,\n\x0b\x61nnotations\x18\x06 \x01(\x0b\x32\x17.google.protobuf.Struct\x12&\n\x05value\x18\x07 \x01(\x0b\x32\x17.cstx.RelationshipValueB\x05\n\x03_idJ\x04\x08\x04\x10\x05R\x08relation\"M\n\x05Graph\x12\x19\n\x05nodes\x18\x01 \x03(\x0b\x32\n.cstx.Node\x12)\n\rrelationships\x18\x02 \x03(\x0b\x32\x12.cstx.Relationship\"\xcf\x01\n\x0eGraphChangeSet\x12\x16\n\x0e\x61\x64\x64\x65\x64_node_ids\x18\x01 \x03(\t\x12\x18\n\x10updated_node_ids\x18\x02 \x03(\t\x12\x18\n\x10removed_node_ids\x18\x03 \x03(\t\x12\x1e\n\x16\x61\x64\x64\x65\x64_relationship_ids\x18\x04 \x03(\t\x12 \n\x18updated_relationship_ids\x18\x05 \x03(\t\x12 \n\x18removed_relationship_ids\x18\x06 \x03(\t\x12\r\n\x05reset\x18\x07 \x01(\x08\"\xb2\x01\n\x12GraphChangeSummary\x12\x13\n\x0b\x61\x64\x64\x65\x64_nodes\x18\x01 \x01(\x04\x12\x15\n\rupdated_nodes\x18\x02 \x01(\x04\x12\x15\n\rremoved_nodes\x18\x03 \x01(\x04\x12\x1b\n\x13\x61\x64\x64\x65\x64_relationships\x18\x04 \x01(\x04\x12\x1d\n\x15updated_relationships\x18\x05 \x01(\x04\x12\x1d\n\x15removed_relationships\x18\x06 \x01(\x04\"\xee\x03\n\nGraphStats\x12\x38\n\rnodes_by_type\x18\x01 \x03(\x0b\x32!.cstx.GraphStats.NodesByTypeEntry\x12H\n\x15relationships_by_type\x18\x02 \x03(\x0b\x32).cstx.GraphStats.RelationshipsByTypeEntry\x12@\n\x11objects_by_source\x18\x03 \x03(\x0b\x32%.cstx.GraphStats.ObjectsBySourceEntry\x12<\n\x0f\x61nchors_by_kind\x18\x04 \x03(\x0b\x32#.cstx.GraphStats.AnchorsByKindEntry\x1a\x32\n\x10NodesByTypeEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a:\n\x18RelationshipsByTypeEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x36\n\x14ObjectsBySourceEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x1a\x34\n\x12\x41nchorsByKindEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\"\x9e\x01\n\x06\x43ommit\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0f\n\x07parents\x18\x02 \x03(\t\x12\x0f\n\x07message\x18\x03 \x01(\t\x12)\n\x08metadata\x18\x04 \x01(\x0b\x32\x17.google.protobuf.Struct\x12\'\n\x05stats\x18\x05 \x01(\x0b\x32\x18.cstx.GraphChangeSummary\x12\x12\n\ncreated_at\x18\x06 \x01(\x03\"*\n\tCommitLog\x12\x1d\n\x07\x63ommits\x18\x01 \x03(\x0b\x32\x0c.cstx.Commit\"\xd5\x01\n\x0c\x45ntityChange\x12\x11\n\tcommit_id\x18\x01 \x01(\t\x12\x0f\n\x07ordinal\x18\x02 \x01(\x04\x12\x11\n\ttimestamp\x18\x03 \x01(\x03\x12(\n\toperation\x18\x04 \x01(\x0e\x32\x15.cstx.ChangeOperation\x12\x1d\n\x10\x62\x65\x66ore_object_id\x18\x05 \x01(\tH\x00\x88\x01\x01\x12\x1c\n\x0f\x61\x66ter_object_id\x18\x06 \x01(\tH\x01\x88\x01\x01\x42\x13\n\x11_before_object_idB\x12\n\x10_after_object_id\"4\n\rEntityHistory\x12#\n\x07\x63hanges\x18\x01 \x03(\x0b\x32\x12.cstx.EntityChange\"O\n\x0eGraphSelection\x12\x10\n\x08node_ids\x18\x01 \x03(\t\x12\x18\n\x10relationship_ids\x18\x02 \x03(\t\x12\x11\n\tall_nodes\x18\x03 \x01(\x08\"\xbb\x01\n\tGraphDiff\x12#\n\x05\x61\x64\x64\x65\x64\x18\x01 \x01(\x0b\x32\x14.cstx.GraphSelection\x12%\n\x07removed\x18\x02 \x01(\x0b\x32\x14.cstx.GraphSelection\x12&\n\x08modified\x18\x03 \x01(\x0b\x32\x14.cstx.GraphSelection\x12\x11\n\ttruncated\x18\x04 \x01(\x08\x12\'\n\x05stats\x18\x05 \x01(\x0b\x32\x18.cstx.GraphChangeSummary\"Y\n\x0bQueryWindow\x12\x12\n\x05limit\x18\x01 \x01(\x04H\x00\x88\x01\x01\x12\x0c\n\x04page\x18\x02 \x01(\x04\x12\x1e\n\x05order\x18\x03 \x01(\x0e\x32\x0f.cstx.SortOrderB\x08\n\x06_limit\"\xee\x01\n\nNodeFilter\x12\x12\n\nnode_types\x18\x01 \x03(\t\x12\x10\n\x08node_ids\x18\x02 \x03(\t\x12\x0f\n\x07sources\x18\x03 \x03(\t\x12\x1a\n\rname_contains\x18\x04 \x01(\tH\x00\x88\x01\x01\x12\x16\n\x0e\x66lags_all_mask\x18\x08 \x01(\x04\x12\x16\n\x0e\x66lags_any_mask\x18\t \x01(\x04\x12\x17\n\x0f\x66lags_none_mask\x18\n \x01(\x04\x42\x10\n\x0e_name_containsJ\x04\x08\x05\x10\x06J\x04\x08\x06\x10\x07J\x04\x08\x07\x10\x08R\tflags_allR\tflags_anyR\nflags_none\"\x8d\x01\n\x12RelationshipFilter\x12\x16\n\tsource_id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x16\n\ttarget_id\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x1a\n\x12relationship_types\x18\x03 \x03(\t\x12\x0f\n\x07sources\x18\x04 \x03(\tB\x0c\n\n_source_idB\x0c\n\n_target_id\"P\n\tNodeQuery\x12 \n\x06\x66ilter\x18\x01 \x01(\x0b\x32\x10.cstx.NodeFilter\x12!\n\x06window\x18\x02 \x01(\x0b\x32\x11.cstx.QueryWindow\"`\n\x11RelationshipQuery\x12(\n\x06\x66ilter\x18\x01 \x01(\x0b\x32\x18.cstx.RelationshipFilter\x12!\n\x06window\x18\x02 \x01(\x0b\x32\x11.cstx.QueryWindow\"`\n\x0fGraphProjection\x12%\n\x0bnode_filter\x18\x01 \x01(\x0b\x32\x10.cstx.NodeFilter\x12&\n\x08\x65xcluded\x18\x02 \x01(\x0b\x32\x14.cstx.GraphSelection\"\x85\x01\n\x0cQueryOptions\x12!\n\x06window\x18\x01 \x01(\x0b\x32\x11.cstx.QueryWindow\x12\'\n\rresult_filter\x18\x02 \x01(\x0b\x32\x10.cstx.NodeFilter\x12)\n\nprojection\x18\x03 \x01(\x0b\x32\x15.cstx.GraphProjection\"F\n\x0fNodeTypeCatalog\x12\x12\n\nnode_types\x18\x01 \x03(\t\x12\x1f\n\x07schemas\x18\x02 \x03(\x0b\x32\x0e.cstx.NodeType\"g\n\rNeighborQuery\x12\x0f\n\x07node_id\x18\x01 \x01(\t\x12\"\n\tdirection\x18\x02 \x01(\x0e\x32\x0f.cstx.Direction\x12!\n\x06window\x18\x03 \x01(\x0b\x32\x11.cstx.QueryWindow\"E\n\nGraphQuery\x12\x12\n\nexpression\x18\x01 \x01(\t\x12#\n\x07options\x18\x02 \x01(\x0b\x32\x12.cstx.QueryOptions\"m\n\x14NodeAnnotationUpdate\x12\'\n\tselection\x18\x01 \x01(\x0b\x32\x14.cstx.GraphSelection\x12,\n\x0b\x61nnotations\x18\x02 \x01(\x0b\x32\x17.google.protobuf.Struct\"_\n\x0eNodeFlagChange\x12\'\n\tselection\x18\x01 \x01(\x0b\x32\x14.cstx.GraphSelection\x12$\n\x06update\x18\x02 \x01(\x0b\x32\x14.cstx.NodeFlagUpdate\"\xb0\x01\n\x0c\x42\x66sAlgorithm\x12\x0f\n\x07seed_id\x18\x01 \x01(\t\x12\r\n\x05\x64\x65pth\x18\x02 \x01(\r\x12\"\n\tdirection\x18\x03 \x01(\x0e\x32\x0f.cstx.Direction\x12\x1e\n\x11max_visited_nodes\x18\x04 \x01(\x04H\x00\x88\x01\x01\x12\x17\n\ntimeout_ms\x18\x05 \x01(\x04H\x01\x88\x01\x01\x42\x14\n\x12_max_visited_nodesB\r\n\x0b_timeout_ms\"c\n\x14\x42\x65tweennessAlgorithm\x12\x19\n\x11include_endpoints\x18\x01 \x01(\x08\x12\x12\n\nnormalized\x18\x02 \x01(\x08\x12\x12\n\x05top_k\x18\x03 \x01(\x04H\x00\x88\x01\x01\x42\x08\n\x06_top_k\"G\n\x12\x43losenessAlgorithm\x12\x13\n\x0bwf_improved\x18\x01 \x01(\x08\x12\x12\n\x05top_k\x18\x02 \x01(\x04H\x00\x88\x01\x01\x42\x08\n\x06_top_k\"_\n\x0fLeidenAlgorithm\x12\x12\n\nresolution\x18\x01 \x01(\x01\x12\x1a\n\x12min_community_size\x18\x02 \x01(\x04\x12\x12\n\x05top_k\x18\x03 \x01(\x04H\x00\x88\x01\x01\x42\x08\n\x06_top_k\"\xde\x01\n\x16ShortestPathsAlgorithm\x12\x10\n\x08start_id\x18\x01 \x01(\t\x12\x0e\n\x06\x65nd_id\x18\x02 \x01(\t\x12\"\n\tdirection\x18\x03 \x01(\x0e\x32\x0f.cstx.Direction\x12\x11\n\tmax_depth\x18\x04 \x01(\r\x12\r\n\x05limit\x18\x05 \x01(\x04\x12\x1e\n\x11max_visited_nodes\x18\x06 \x01(\x04H\x00\x88\x01\x01\x12\x17\n\ntimeout_ms\x18\x07 \x01(\x04H\x01\x88\x01\x01\x42\x14\n\x12_max_visited_nodesB\r\n\x0b_timeout_ms\"\xb0\x02\n\tAlgorithm\x12!\n\x03\x62\x66s\x18\x01 \x01(\x0b\x32\x12.cstx.BfsAlgorithmH\x00\x12\x35\n\rparameterless\x18\x02 \x01(\x0e\x32\x1c.cstx.ParameterlessAlgorithmH\x00\x12\x31\n\x0b\x62\x65tweenness\x18\x03 \x01(\x0b\x32\x1a.cstx.BetweennessAlgorithmH\x00\x12-\n\tcloseness\x18\x04 \x01(\x0b\x32\x18.cstx.ClosenessAlgorithmH\x00\x12\'\n\x06leiden\x18\x05 \x01(\x0b\x32\x15.cstx.LeidenAlgorithmH\x00\x12\x36\n\x0eshortest_paths\x18\x06 \x01(\x0b\x32\x1c.cstx.ShortestPathsAlgorithmH\x00\x42\x06\n\x04kind\"&\n\x08NodePage\x12\x1a\n\x06values\x18\x01 \x03(\x0b\x32\n.cstx.Node\"6\n\x10RelationshipPage\x12\"\n\x06values\x18\x01 \x03(\x0b\x32\x12.cstx.Relationship\"<\n\x13\x43omponentMembership\x12\x0f\n\x07node_id\x18\x01 \x01(\t\x12\x14\n\x0c\x63omponent_id\x18\x02 \x01(\x04\"D\n\x17\x43omponentMembershipPage\x12)\n\x06values\x18\x01 \x03(\x0b\x32\x19.cstx.ComponentMembership\";\n\tNodeScore\x12\x0f\n\x07node_id\x18\x01 \x01(\t\x12\x0e\n\x06metric\x18\x02 \x01(\t\x12\r\n\x05score\x18\x03 \x01(\x01\"0\n\rNodeScorePage\x12\x1f\n\x06values\x18\x01 \x03(\x0b\x32\x0f.cstx.NodeScore\"0\n\x08NodePair\x12\x11\n\tsource_id\x18\x01 \x01(\t\x12\x11\n\ttarget_id\x18\x02 \x01(\t\".\n\x0cNodePairPage\x12\x1e\n\x06values\x18\x01 \x03(\x0b\x32\x0e.cstx.NodePair\"\x1d\n\tNodeCycle\x12\x10\n\x08node_ids\x18\x01 \x03(\t\",\n\tCyclePage\x12\x1f\n\x06values\x18\x01 \x03(\x0b\x32\x0f.cstx.NodeCycle\"\x1c\n\x08NodePath\x12\x10\n\x08node_ids\x18\x01 \x03(\t\"*\n\x08PathPage\x12\x1e\n\x06values\x18\x01 \x03(\x0b\x32\x0e.cstx.NodePath\"<\n\x13\x43ommunityMembership\x12\x0f\n\x07node_id\x18\x01 \x01(\t\x12\x14\n\x0c\x63ommunity_id\x18\x02 \x01(\x04\"D\n\x17\x43ommunityMembershipPage\x12)\n\x06values\x18\x01 \x03(\x0b\x32\x19.cstx.CommunityMembership\"~\n\x0cQuerySummary\x12:\n\rnodes_by_type\x18\x01 \x03(\x0b\x32#.cstx.QuerySummary.NodesByTypeEntry\x1a\x32\n\x10NodesByTypeEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\"p\n\x10TraversalSummary\x12\x11\n\talgorithm\x18\x01 \x01(\t\x12\"\n\tdirection\x18\x02 \x01(\x0e\x32\x0f.cstx.Direction\x12\x11\n\ttruncated\x18\x03 \x01(\x08\x12\x12\n\nprojection\x18\x04 \x01(\t\"R\n\x10\x43omponentSummary\x12\x11\n\talgorithm\x18\x01 \x01(\t\x12\x17\n\x0f\x63omponent_count\x18\x02 \x01(\x04\x12\x12\n\nprojection\x18\x03 \x01(\t\"\x94\x01\n\x0cScoreSummary\x12\x0e\n\x06metric\x18\x01 \x01(\t\x12\x19\n\x11include_endpoints\x18\x02 \x01(\x08\x12\x12\n\nnormalized\x18\x03 \x01(\x08\x12\x13\n\x0bwf_improved\x18\x04 \x01(\x08\x12\x12\n\x05top_k\x18\x05 \x01(\x04H\x00\x88\x01\x01\x12\x12\n\nprojection\x18\x06 \x01(\tB\x08\n\x06_top_k\"\xea\x02\n\x10\x43ommunitySummary\x12\x17\n\x0fnum_communities\x18\x01 \x01(\x04\x12\x19\n\x11total_communities\x18\x02 \x01(\x04\x12\x1d\n\x15\x63ommunities_truncated\x18\x03 \x01(\x08\x12\x12\n\nmodularity\x18\x04 \x01(\x01\x12\x12\n\nresolution\x18\x05 \x01(\x01\x12\x1a\n\x12min_community_size\x18\x06 \x01(\x04\x12\x12\n\x05top_k\x18\x07 \x01(\x04H\x00\x88\x01\x01\x12\x43\n\x0f\x63ommunity_sizes\x18\x08 \x03(\x0b\x32*.cstx.CommunitySummary.CommunitySizesEntry\x12\x12\n\nprojection\x18\t \x01(\t\x12\x11\n\talgorithm\x18\n \x01(\t\x1a\x35\n\x13\x43ommunitySizesEntry\x12\x0b\n\x03key\x18\x01 \x01(\x04\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\x42\x08\n\x06_top_k\"\x88\x01\n\x0bPathSummary\x12\x11\n\talgorithm\x18\x01 \x01(\t\x12\x10\n\x08start_id\x18\x02 \x01(\t\x12\x0e\n\x06\x65nd_id\x18\x03 \x01(\t\x12\"\n\tdirection\x18\x04 \x01(\x0e\x32\x0f.cstx.Direction\x12\x11\n\tmax_depth\x18\x05 \x01(\r\x12\r\n\x05limit\x18\x06 \x01(\x04\"\xb4\x05\n\x0fGraphResultPage\x12\x0c\n\x04page\x18\x01 \x01(\x04\x12\r\n\x05limit\x18\x02 \x01(\x04\x12\x10\n\x08has_next\x18\x03 \x01(\x08\x12\x12\n\x05total\x18\x04 \x01(\x04H\x02\x88\x01\x01\x12\x1f\n\x05nodes\x18\x05 \x01(\x0b\x32\x0e.cstx.NodePageH\x00\x12/\n\rrelationships\x18\x06 \x01(\x0b\x32\x16.cstx.RelationshipPageH\x00\x12\x33\n\ncomponents\x18\x07 \x01(\x0b\x32\x1d.cstx.ComponentMembershipPageH\x00\x12%\n\x06scores\x18\x08 \x01(\x0b\x32\x13.cstx.NodeScorePageH\x00\x12#\n\x05pairs\x18\t \x01(\x0b\x32\x12.cstx.NodePairPageH\x00\x12!\n\x06\x63ycles\x18\n \x01(\x0b\x32\x0f.cstx.CyclePageH\x00\x12\x1f\n\x05paths\x18\x0b \x01(\x0b\x32\x0e.cstx.PathPageH\x00\x12\x34\n\x0b\x63ommunities\x18\x0c \x01(\x0b\x32\x1d.cstx.CommunityMembershipPageH\x00\x12#\n\x05query\x18\r \x01(\x0b\x32\x12.cstx.QuerySummaryH\x01\x12+\n\ttraversal\x18\x0e \x01(\x0b\x32\x16.cstx.TraversalSummaryH\x01\x12+\n\tcomponent\x18\x0f \x01(\x0b\x32\x16.cstx.ComponentSummaryH\x01\x12#\n\x05score\x18\x10 \x01(\x0b\x32\x12.cstx.ScoreSummaryH\x01\x12+\n\tcommunity\x18\x11 \x01(\x0b\x32\x16.cstx.CommunitySummaryH\x01\x12!\n\x04path\x18\x12 \x01(\x0b\x32\x11.cstx.PathSummaryH\x01\x42\x08\n\x06resultB\t\n\x07summaryB\x08\n\x06_total\"U\n\rParserPayload\x12\x0e\n\x06plugin\x18\x01 \x01(\t\x12\x10\n\x08\x61rtifact\x18\x02 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c\x12\x14\n\x0c\x63ontent_type\x18\x04 \x01(\t\"\xa7\x02\n\x11GraphIngestResult\x12\x16\n\x0erecords_parsed\x18\x01 \x01(\x04\x12\x11\n\tnew_nodes\x18\x02 \x01(\x04\x12\x15\n\rupdated_nodes\x18\x03 \x01(\x04\x12\x19\n\x11new_relationships\x18\x04 \x01(\x04\x12\x10\n\x08node_ids\x18\x05 \x03(\t\x12\x12\n\nnode_count\x18\x06 \x01(\x04\x12\x1a\n\x12relationship_count\x18\x07 \x01(\x04\x12?\n\rnodes_by_type\x18\x08 \x03(\x0b\x32(.cstx.GraphIngestResult.NodesByTypeEntry\x1a\x32\n\x10NodesByTypeEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x04:\x02\x38\x01\"p\n\x0fGraphLinkResult\x12\x11\n\tnew_nodes\x18\x01 \x01(\x04\x12\x15\n\rupdated_nodes\x18\x02 \x01(\x04\x12\x19\n\x11new_relationships\x18\x03 \x01(\x04\x12\x18\n\x10relationship_ids\x18\x04 \x03(\t\"\xaf\x01\n\x0bGraphAnchor\x12\x0f\n\x07\x63oncept\x18\x01 \x01(\t\x12\x11\n\tanchor_id\x18\x02 \x01(\t\x12\x13\n\x0b\x61nchor_type\x18\x03 \x01(\t\x12\x11\n\tsource_id\x18\x04 \x01(\t\x12\x11\n\ttarget_id\x18\x05 \x01(\t\x12\x1f\n\x17inbound_relationship_id\x18\x06 \x01(\t\x12 \n\x18outbound_relationship_id\x18\x07 \x01(\t\"8\n\x12GraphAnchorCatalog\x12\"\n\x07\x61nchors\x18\x01 \x03(\x0b\x32\x11.cstx.GraphAnchor\"\x9d\x01\n\x0eNodeFlagUpdate\x12&\n\x04mode\x18\x01 \x01(\x0e\x32\x18.cstx.NodeFlagUpdateMode\x12\x10\n\x08\x61\x64\x64_mask\x18\x05 \x01(\x04\x12\x13\n\x0bremove_mask\x18\x06 \x01(\x04\x12\x14\n\x0creplace_mask\x18\x07 \x01(\x04J\x04\x08\x02\x10\x03J\x04\x08\x03\x10\x04J\x04\x08\x04\x10\x05R\x03\x61\x64\x64R\x06removeR\x07replace\"\x9c\x01\n\x15GraphProjectionReport\x12\x41\n\x0e\x65xcluded_nodes\x18\x01 \x03(\x0b\x32).cstx.GraphProjectionReport.NodeExclusion\x12\x0e\n\x06reused\x18\x02 \x01(\x08\x1a\x30\n\rNodeExclusion\x12\x0f\n\x07node_id\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\"Y\n\x10RepositoryObject\x12\n\n\x02id\x18\x01 \x01(\t\x12(\n\x04kind\x18\x02 \x01(\x0e\x32\x1a.cstx.RepositoryObjectKind\x12\x0f\n\x07payload\x18\x03 \x01(\x0c\"l\n\x0fPublicationPlan\x12\x1c\n\x06\x63ommit\x18\x01 \x01(\x0b\x32\x0c.cstx.Commit\x12\x12\n\nindex_root\x18\x02 \x01(\t\x12\'\n\x07objects\x18\x03 \x03(\x0b\x32\x16.cstx.RepositoryObject\"\xa9\x02\n\x0fRepositoryState\x12-\n\x07objects\x18\x01 \x03(\x0b\x32\x1c.cstx.RepositoryState.Object\x12\'\n\x04refs\x18\x02 \x03(\x0b\x32\x19.cstx.RepositoryState.Ref\x12,\n\x07indexes\x18\x03 \x03(\x0b\x32\x1b.cstx.RepositoryState.Index\x1a%\n\x06Object\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0f\n\x07payload\x18\x02 \x01(\x0c\x1a\x39\n\x03Ref\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\tcommit_id\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0c\n\n_commit_id\x1a.\n\x05Index\x12\x11\n\tcommit_id\x18\x01 \x01(\t\x12\x12\n\nindex_root\x18\x02 \x01(\t\"%\n\x0fObjectSelection\x12\x12\n\nobject_ids\x18\x01 \x03(\t\"\xf7\x02\n\x14RepositoryObjectPlan\x12&\n\x04kind\x18\x01 \x01(\x0e\x32\x18.cstx.RepositoryPlanKind\x12\x11\n\tcommit_id\x18\x02 \x01(\t\x12\x12\n\x05limit\x18\x03 \x01(\x04H\x00\x88\x01\x01\x12\x1c\n\x0fstart_timestamp\x18\x04 \x01(\x03H\x01\x88\x01\x01\x12\x1a\n\rend_timestamp\x18\x05 \x01(\x03H\x02\x88\x01\x01\x12\x16\n\tentity_id\x18\x06 \x01(\tH\x03\x88\x01\x01\x12\x16\n\tsource_id\x18\x07 \x01(\tH\x04\x88\x01\x01\x12\x16\n\ttarget_id\x18\x08 \x01(\tH\x05\x88\x01\x01\x12 \n\x06\x64\x65tail\x18\t \x01(\x0e\x32\x10.cstx.DiffDetail\x12\x12\n\nentity_ids\x18\n \x03(\tB\x08\n\x06_limitB\x12\n\x10_start_timestampB\x10\n\x0e_end_timestampB\x0c\n\n_entity_idB\x0c\n\n_source_idB\x0c\n\n_target_id\"\x9d\x01\n\tRagFilter\x12\x12\n\nnode_types\x18\x01 \x03(\t\x12\x1a\n\x12relationship_types\x18\x02 \x03(\t\x12\x1a\n\x12\x65xclude_flags_mask\x18\x05 \x01(\x04\x12\x1a\n\x12include_flags_mask\x18\x06 \x01(\x04J\x04\x08\x03\x10\x04J\x04\x08\x04\x10\x05R\rexclude_flagsR\rinclude_flags\"\x89\x01\n\x0fRagGraphChanges\x12\x18\n\x10\x63hanged_node_ids\x18\x01 \x03(\t\x12\x18\n\x10\x64\x65leted_node_ids\x18\x02 \x03(\t\x12 \n\x18\x63hanged_relationship_ids\x18\x03 \x03(\t\x12 \n\x18\x64\x65leted_relationship_ids\x18\x04 \x03(\t\"\xe6\x01\n\tRagRecord\x12\n\n\x02id\x18\x01 \x01(\t\x12!\n\x04kind\x18\x02 \x01(\x0e\x32\x13.cstx.RagRecordKind\x12\x0c\n\x04text\x18\x03 \x01(\t\x12\x14\n\x0c\x63ontent_hash\x18\x04 \x01(\t\x12\x10\n\x08node_ids\x18\x05 \x03(\t\x12\x18\n\x10relationship_ids\x18\x06 \x03(\t\x12\x16\n\tnode_type\x18\x07 \x01(\tH\x00\x88\x01\x01\x12\x1e\n\x11relationship_type\x18\x08 \x01(\tH\x01\x88\x01\x01\x42\x0c\n\n_node_typeB\x14\n\x12_relationship_type\"\x84\x01\n\x0eRagIndexResult\x12\x14\n\x0coperation_id\x18\x01 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x02 \x01(\t\x12 \n\x04mode\x18\x03 \x01(\x0e\x32\x12.cstx.RagIndexMode\x12\x14\n\x0cupsert_count\x18\x04 \x01(\x04\x12\x14\n\x0c\x64\x65lete_count\x18\x05 \x01(\x04\"h\n\x0cRagIndexPlan\x12\x0e\n\x06\x63ommit\x18\x01 \x01(\t\x12 \n\x04mode\x18\x02 \x01(\x0e\x32\x12.cstx.RagIndexMode\x12&\n\x07\x63hanges\x18\x03 \x01(\x0b\x32\x15.cstx.RagGraphChanges\"`\n\rRagRecordPage\x12 \n\x07records\x18\x01 \x03(\x0b\x32\x0f.cstx.RagRecord\x12\x0c\n\x04page\x18\x02 \x01(\x04\x12\r\n\x05limit\x18\x03 \x01(\x04\x12\x10\n\x08has_next\x18\x04 \x01(\x08\"z\n\x0bRecallQuery\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04text\x18\x02 \x01(\t\x12!\n\x04kind\x18\x03 \x01(\x0e\x32\x13.cstx.RagRecordKind\x12\r\n\x05limit\x18\x04 \x01(\x04\x12\x1f\n\x06\x66ilter\x18\x05 \x01(\x0b\x32\x0f.cstx.RagFilter\"J\n\tRecallHit\x12\x11\n\trecord_id\x18\x01 \x01(\t\x12\x0c\n\x04rank\x18\x02 \x01(\x04\x12\x12\n\x05score\x18\x03 \x01(\x02H\x00\x88\x01\x01\x42\x08\n\x06_score\"[\n\x15\x45xtensionRecallResult\x12\x10\n\x08query_id\x18\x01 \x01(\t\x12\x11\n\textension\x18\x02 \x01(\t\x12\x1d\n\x04hits\x18\x03 \x03(\x0b\x32\x0f.cstx.RecallHit\"=\n\rRecallResults\x12,\n\x07results\x18\x01 \x03(\x0b\x32\x1b.cstx.ExtensionRecallResult\"0\n\nRecallPlan\x12\"\n\x07queries\x18\x01 \x03(\x0b\x32\x11.cstx.RecallQuery\"\xbc\x01\n\tRagPolicy\x12\r\n\x05rrf_k\x18\x01 \x01(\x02\x12\x1c\n\x14\x63\x61ndidate_multiplier\x18\x02 \x01(\x04\x12\x0f\n\x07\x64\x61mping\x18\x03 \x01(\x02\x12\x1e\n\x16propagation_iterations\x18\x04 \x01(\x04\x12\x16\n\x0emax_path_depth\x18\x05 \x01(\x04\x12\x0f\n\x07\x65psilon\x18\x06 \x01(\x02\x12\x13\n\x0b\x63ommunities\x18\x07 \x01(\x08\x12\x13\n\x0buse_lexical\x18\x08 \x01(\x08\"\x99\x01\n\x08RagQuery\x12\x0c\n\x04text\x18\x01 \x01(\t\x12\r\n\x05limit\x18\x02 \x01(\x04\x12\x1f\n\x06\x66ilter\x18\x03 \x01(\x0b\x32\x0f.cstx.RagFilter\x12\x1f\n\x06policy\x18\x04 \x01(\x0b\x32\x0f.cstx.RagPolicy\x12\x1b\n\x0e\x63ontext_budget\x18\x05 \x01(\x04H\x00\x88\x01\x01\x42\x11\n\x0f_context_budget\"P\n\nRankedNode\x12\x0f\n\x07node_id\x18\x01 \x01(\t\x12\r\n\x05score\x18\x02 \x01(\x02\x12\x0e\n\x06\x64irect\x18\x03 \x01(\x08\x12\x12\n\nprovenance\x18\x04 \x03(\t\"`\n\x12RankedRelationship\x12\x17\n\x0frelationship_id\x18\x01 \x01(\t\x12\r\n\x05score\x18\x02 \x01(\x02\x12\x0e\n\x06\x64irect\x18\x03 \x01(\x08\x12\x12\n\nprovenance\x18\x04 \x03(\t\"D\n\x07RagPath\x12\x10\n\x08node_ids\x18\x01 \x03(\t\x12\x18\n\x10relationship_ids\x18\x02 \x03(\t\x12\r\n\x05score\x18\x03 \x01(\x02\"T\n\x0fRagCommunityHit\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05level\x18\x02 \x01(\x04\x12\x17\n\x0fmember_node_ids\x18\x03 \x03(\t\x12\r\n\x05score\x18\x04 \x01(\x02\"M\n\x0fRagContextBlock\x12\x0c\n\x04text\x18\x01 \x01(\t\x12\x12\n\nrecord_ids\x18\x02 \x03(\t\x12\x18\n\x10\x65stimated_tokens\x18\x03 \x01(\x04\";\n\x12\x45videnceProvenance\x12\x11\n\tresult_id\x18\x01 \x01(\t\x12\x12\n\nrecord_ids\x18\x02 \x03(\t\"\xba\x02\n\tRagResult\x12\x0e\n\x06\x63ommit\x18\x01 \x01(\t\x12\x1f\n\x05nodes\x18\x02 \x03(\x0b\x32\x10.cstx.RankedNode\x12/\n\rrelationships\x18\x03 \x03(\x0b\x32\x18.cstx.RankedRelationship\x12\x1c\n\x05paths\x18\x04 \x03(\x0b\x32\r.cstx.RagPath\x12*\n\x0b\x63ommunities\x18\x05 \x03(\x0b\x32\x15.cstx.RagCommunityHit\x12&\n\x07\x63ontext\x18\x06 \x03(\x0b\x32\x15.cstx.RagContextBlock\x12,\n\nprovenance\x18\x07 \x03(\x0b\x32\x18.cstx.EvidenceProvenance\x12\x17\n\x0f\x64ropped_records\x18\x08 \x03(\t\x12\x12\n\nextensions\x18\t \x03(\t\"\xbe\x01\n\x11\x45xtensionContract\x12\x18\n\x10\x63ontract_version\x18\x01 \x01(\r\x12;\n\nextensions\x18\x02 \x03(\x0b\x32\'.cstx.ExtensionContract.ExtensionsEntry\x1aL\n\x0f\x45xtensionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12(\n\x05value\x18\x02 \x01(\x0b\x32\x19.cstx.ExtensionDefinition:\x02\x38\x01J\x04\x08\x03\x10\x04\"\xea\x01\n\x13\x45xtensionDefinition\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\t\x12\x37\n\x07parsers\x18\x05 \x03(\x0b\x32&.cstx.ExtensionDefinition.ParsersEntry\x12\x1d\n\x05rules\x18\x06 \x03(\x0b\x32\x0e.cstx.JoinRule\x12\x0e\n\x06schema\x18\x07 \x01(\t\x1a@\n\x0cParsersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1f\n\x05value\x18\x02 \x01(\x0b\x32\x10.cstx.ParserType:\x02\x38\x01J\x04\x08\x03\x10\x04J\x04\x08\x04\x10\x05\"G\n\x08NodeType\x12\x10\n\x08type_url\x18\x01 \x01(\t\x12)\n\x08metadata\x18\x02 \x01(\x0b\x32\x17.google.protobuf.Struct\"O\n\x10RelationshipType\x12\x10\n\x08type_url\x18\x01 \x01(\t\x12)\n\x08metadata\x18\x02 \x01(\x0b\x32\x17.google.protobuf.Struct\"x\n\nParserType\x12\x10\n\x08\x61rtifact\x18\x01 \x01(\t\x12-\n\x0cinput_schema\x18\x02 \x01(\x0b\x32\x17.google.protobuf.Struct\x12)\n\x08metadata\x18\x03 \x01(\x0b\x32\x17.google.protobuf.Struct\"\xf2\x01\n\x08JoinRule\x12\x15\n\rleft_type_url\x18\x01 \x01(\t\x12\x16\n\x0eright_type_url\x18\x02 \x01(\t\x12\x1d\n\x15relationship_type_url\x18\x03 \x01(\t\x12\x10\n\x08left_key\x18\x04 \x01(\t\x12\x11\n\tright_key\x18\x05 \x01(\t\x12\x11\n\tpredicted\x18\x06 \x01(\x08\x12\x1b\n\x0eleft_target_id\x18\x07 \x01(\tH\x00\x88\x01\x01\x12\x1c\n\x0fright_source_id\x18\x08 \x01(\tH\x01\x88\x01\x01\x42\x11\n\x0f_left_target_idB\x12\n\x10_right_source_id\"`\n\rExtensionInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\t\x12\x0c\n\x04kind\x18\x03 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x04 \x01(\x08\x12\x11\n\tartifacts\x18\x05 \x03(\t\";\n\x10\x45xtensionCatalog\x12\'\n\nextensions\x18\x01 \x03(\x0b\x32\x13.cstx.ExtensionInfo\"1\n\rAnchorConcept\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x12\n\nnode_types\x18\x02 \x03(\t\"=\n\x14\x41nchorConceptCatalog\x12%\n\x08\x63oncepts\x18\x01 \x03(\x0b\x32\x13.cstx.AnchorConcept*\x8b\x01\n\x0f\x43hangeOperation\x12 \n\x1c\x43HANGE_OPERATION_UNSPECIFIED\x10\x00\x12\x1a\n\x16\x43HANGE_OPERATION_ADDED\x10\x01\x12\x1c\n\x18\x43HANGE_OPERATION_UPDATED\x10\x02\x12\x1c\n\x18\x43HANGE_OPERATION_REMOVED\x10\x03*V\n\tSortOrder\x12\x1a\n\x16SORT_ORDER_UNSPECIFIED\x10\x00\x12\x15\n\x11SORT_ORDER_ID_ASC\x10\x01\x12\x16\n\x12SORT_ORDER_ID_DESC\x10\x02*_\n\tDirection\x12\x19\n\x15\x44IRECTION_UNSPECIFIED\x10\x00\x12\x11\n\rDIRECTION_OUT\x10\x01\x12\x10\n\x0c\x44IRECTION_IN\x10\x02\x12\x12\n\x0e\x44IRECTION_BOTH\x10\x03*\xc9\x02\n\x16ParameterlessAlgorithm\x12\'\n#PARAMETERLESS_ALGORITHM_UNSPECIFIED\x10\x00\x12!\n\x1dPARAMETERLESS_WEAK_COMPONENTS\x10\x01\x12#\n\x1fPARAMETERLESS_STRONG_COMPONENTS\x10\x02\x12\x1d\n\x19PARAMETERLESS_CYCLE_BASIS\x10\x03\x12\x19\n\x15PARAMETERLESS_BRIDGES\x10\x04\x12%\n!PARAMETERLESS_ARTICULATION_POINTS\x10\x05\x12\x1e\n\x1aPARAMETERLESS_CORE_NUMBERS\x10\x06\x12\x18\n\x14PARAMETERLESS_IS_DAG\x10\x07\x12#\n\x1fPARAMETERLESS_TOPOLOGICAL_ORDER\x10\x08*p\n\x12NodeFlagUpdateMode\x12 \n\x1cNODE_FLAG_UPDATE_UNSPECIFIED\x10\x00\x12\x1a\n\x16NODE_FLAG_UPDATE_MERGE\x10\x01\x12\x1c\n\x18NODE_FLAG_UPDATE_REPLACE\x10\x02*\xfd\x01\n\nObjectKind\x12\x1b\n\x17OBJECT_KIND_UNSPECIFIED\x10\x00\x12\x14\n\x10OBJECT_KIND_TREE\x10\x01\x12\x14\n\x10OBJECT_KIND_STAT\x10\x02\x12\x15\n\x11OBJECT_KIND_MERGE\x10\x03\x12\x15\n\x11OBJECT_KIND_DELTA\x10\x04\x12\x17\n\x13OBJECT_KIND_PREPARE\x10\x05\x12\x17\n\x13OBJECT_KIND_HISTORY\x10\x06\x12\x17\n\x13OBJECT_KIND_COMMITS\x10\x07\x12\x14\n\x10OBJECT_KIND_DIFF\x10\x08\x12\x17\n\x13OBJECT_KIND_CLOSURE\x10\t*\xc5\x01\n\x14RepositoryObjectKind\x12&\n\"REPOSITORY_OBJECT_KIND_UNSPECIFIED\x10\x00\x12\x1f\n\x1bREPOSITORY_OBJECT_KIND_TREE\x10\x01\x12!\n\x1dREPOSITORY_OBJECT_KIND_COMMIT\x10\x02\x12 \n\x1cREPOSITORY_OBJECT_KIND_INDEX\x10\x03\x12\x1f\n\x1bREPOSITORY_OBJECT_KIND_BLOB\x10\x04*\xcb\x02\n\x12RepositoryPlanKind\x12\x1f\n\x1bREPOSITORY_PLAN_UNSPECIFIED\x10\x00\x12\x18\n\x14REPOSITORY_PLAN_TREE\x10\x01\x12\x18\n\x14REPOSITORY_PLAN_STAT\x10\x02\x12\x1b\n\x17REPOSITORY_PLAN_PREPARE\x10\x03\x12\x1b\n\x17REPOSITORY_PLAN_COMMITS\x10\x04\x12\x19\n\x15REPOSITORY_PLAN_DELTA\x10\x05\x12\x1b\n\x17REPOSITORY_PLAN_CLOSURE\x10\x06\x12\x1b\n\x17REPOSITORY_PLAN_HISTORY\x10\x07\x12\x19\n\x15REPOSITORY_PLAN_MERGE\x10\x08\x12\x18\n\x14REPOSITORY_PLAN_DIFF\x10\t\x12\x1c\n\x18REPOSITORY_PLAN_ENTITIES\x10\n*[\n\nDiffDetail\x12\x1b\n\x17\x44IFF_DETAIL_UNSPECIFIED\x10\x00\x12\x18\n\x14\x44IFF_DETAIL_ENTITIES\x10\x01\x12\x16\n\x12\x44IFF_DETAIL_COUNTS\x10\x02*b\n\rRagRecordKind\x12\x1f\n\x1bRAG_RECORD_KIND_UNSPECIFIED\x10\x00\x12\x13\n\x0fRAG_RECORD_NODE\x10\x01\x12\x1b\n\x17RAG_RECORD_RELATIONSHIP\x10\x02*]\n\x0cRagIndexMode\x12\x1e\n\x1aRAG_INDEX_MODE_UNSPECIFIED\x10\x00\x12\x19\n\x15RAG_INDEX_INCREMENTAL\x10\x01\x12\x12\n\x0eRAG_INDEX_FULL\x10\x02:K\n\tcstx_node\x12\x1f.google.protobuf.MessageOptions\x18\xd0\x86\x03 \x01(\x0b\x32\x15.cstx.CstxNodeOptions:[\n\x11\x63stx_relationship\x12\x1f.google.protobuf.MessageOptions\x18\xd2\x86\x03 \x01(\x0b\x32\x1d.cstx.CstxRelationshipOptions:K\n\ncstx_field\x12\x1d.google.protobuf.FieldOptions\x18\xd1\x86\x03 \x01(\x0b\x32\x16.cstx.CstxFieldOptions:M\n\tcstx_flag\x12!.google.protobuf.EnumValueOptions\x18\xd3\x86\x03 \x01(\x0b\x32\x15.cstx.CstxFlagOptionsB?Z=github.com/chainreactors/libcstx/go/proto/cstxproto;cstxprotob\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'cstx_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'Z=github.com/chainreactors/libcstx/go/proto/cstxproto;cstxproto' + _globals['_GRAPHSTATS_NODESBYTYPEENTRY']._loaded_options = None + _globals['_GRAPHSTATS_NODESBYTYPEENTRY']._serialized_options = b'8\001' + _globals['_GRAPHSTATS_RELATIONSHIPSBYTYPEENTRY']._loaded_options = None + _globals['_GRAPHSTATS_RELATIONSHIPSBYTYPEENTRY']._serialized_options = b'8\001' + _globals['_GRAPHSTATS_OBJECTSBYSOURCEENTRY']._loaded_options = None + _globals['_GRAPHSTATS_OBJECTSBYSOURCEENTRY']._serialized_options = b'8\001' + _globals['_GRAPHSTATS_ANCHORSBYKINDENTRY']._loaded_options = None + _globals['_GRAPHSTATS_ANCHORSBYKINDENTRY']._serialized_options = b'8\001' + _globals['_QUERYSUMMARY_NODESBYTYPEENTRY']._loaded_options = None + _globals['_QUERYSUMMARY_NODESBYTYPEENTRY']._serialized_options = b'8\001' + _globals['_COMMUNITYSUMMARY_COMMUNITYSIZESENTRY']._loaded_options = None + _globals['_COMMUNITYSUMMARY_COMMUNITYSIZESENTRY']._serialized_options = b'8\001' + _globals['_GRAPHINGESTRESULT_NODESBYTYPEENTRY']._loaded_options = None + _globals['_GRAPHINGESTRESULT_NODESBYTYPEENTRY']._serialized_options = b'8\001' + _globals['_EXTENSIONCONTRACT_EXTENSIONSENTRY']._loaded_options = None + _globals['_EXTENSIONCONTRACT_EXTENSIONSENTRY']._serialized_options = b'8\001' + _globals['_EXTENSIONDEFINITION_PARSERSENTRY']._loaded_options = None + _globals['_EXTENSIONDEFINITION_PARSERSENTRY']._serialized_options = b'8\001' + _globals['_CHANGEOPERATION']._serialized_start=13414 + _globals['_CHANGEOPERATION']._serialized_end=13553 + _globals['_SORTORDER']._serialized_start=13555 + _globals['_SORTORDER']._serialized_end=13641 + _globals['_DIRECTION']._serialized_start=13643 + _globals['_DIRECTION']._serialized_end=13738 + _globals['_PARAMETERLESSALGORITHM']._serialized_start=13741 + _globals['_PARAMETERLESSALGORITHM']._serialized_end=14070 + _globals['_NODEFLAGUPDATEMODE']._serialized_start=14072 + _globals['_NODEFLAGUPDATEMODE']._serialized_end=14184 + _globals['_OBJECTKIND']._serialized_start=14187 + _globals['_OBJECTKIND']._serialized_end=14440 + _globals['_REPOSITORYOBJECTKIND']._serialized_start=14443 + _globals['_REPOSITORYOBJECTKIND']._serialized_end=14640 + _globals['_REPOSITORYPLANKIND']._serialized_start=14643 + _globals['_REPOSITORYPLANKIND']._serialized_end=14974 + _globals['_DIFFDETAIL']._serialized_start=14976 + _globals['_DIFFDETAIL']._serialized_end=15067 + _globals['_RAGRECORDKIND']._serialized_start=15069 + _globals['_RAGRECORDKIND']._serialized_end=15167 + _globals['_RAGINDEXMODE']._serialized_start=15169 + _globals['_RAGINDEXMODE']._serialized_end=15262 + _globals['_CSTXNODEOPTIONS']._serialized_start=84 + _globals['_CSTXNODEOPTIONS']._serialized_end=195 + _globals['_CSTXCOMPUTEOPTIONS']._serialized_start=197 + _globals['_CSTXCOMPUTEOPTIONS']._serialized_end=246 + _globals['_CSTXFIELDOPTIONS']._serialized_start=249 + _globals['_CSTXFIELDOPTIONS']._serialized_end=453 + _globals['_CSTXRELATIONSHIPOPTIONS']._serialized_start=455 + _globals['_CSTXRELATIONSHIPOPTIONS']._serialized_end=507 + _globals['_CSTXFLAGOPTIONS']._serialized_start=509 + _globals['_CSTXFLAGOPTIONS']._serialized_end=579 + _globals['_RUNTIMECONFIG']._serialized_start=581 + _globals['_RUNTIMECONFIG']._serialized_end=664 + _globals['_STRINGLIST']._serialized_start=666 + _globals['_STRINGLIST']._serialized_end=694 + _globals['_ENTITYFIELD']._serialized_start=697 + _globals['_ENTITYFIELD']._serialized_end=833 + _globals['_ENTITYVALUE']._serialized_start=835 + _globals['_ENTITYVALUE']._serialized_end=902 + _globals['_RELATIONSHIPVALUE']._serialized_start=904 + _globals['_RELATIONSHIPVALUE']._serialized_end=985 + _globals['_NODE']._serialized_start=988 + _globals['_NODE']._serialized_end=1162 + _globals['_RELATIONSHIP']._serialized_start=1165 + _globals['_RELATIONSHIP']._serialized_end=1360 + _globals['_GRAPH']._serialized_start=1362 + _globals['_GRAPH']._serialized_end=1439 + _globals['_GRAPHCHANGESET']._serialized_start=1442 + _globals['_GRAPHCHANGESET']._serialized_end=1649 + _globals['_GRAPHCHANGESUMMARY']._serialized_start=1652 + _globals['_GRAPHCHANGESUMMARY']._serialized_end=1830 + _globals['_GRAPHSTATS']._serialized_start=1833 + _globals['_GRAPHSTATS']._serialized_end=2327 + _globals['_GRAPHSTATS_NODESBYTYPEENTRY']._serialized_start=2107 + _globals['_GRAPHSTATS_NODESBYTYPEENTRY']._serialized_end=2157 + _globals['_GRAPHSTATS_RELATIONSHIPSBYTYPEENTRY']._serialized_start=2159 + _globals['_GRAPHSTATS_RELATIONSHIPSBYTYPEENTRY']._serialized_end=2217 + _globals['_GRAPHSTATS_OBJECTSBYSOURCEENTRY']._serialized_start=2219 + _globals['_GRAPHSTATS_OBJECTSBYSOURCEENTRY']._serialized_end=2273 + _globals['_GRAPHSTATS_ANCHORSBYKINDENTRY']._serialized_start=2275 + _globals['_GRAPHSTATS_ANCHORSBYKINDENTRY']._serialized_end=2327 + _globals['_COMMIT']._serialized_start=2330 + _globals['_COMMIT']._serialized_end=2488 + _globals['_COMMITLOG']._serialized_start=2490 + _globals['_COMMITLOG']._serialized_end=2532 + _globals['_ENTITYCHANGE']._serialized_start=2535 + _globals['_ENTITYCHANGE']._serialized_end=2748 + _globals['_ENTITYHISTORY']._serialized_start=2750 + _globals['_ENTITYHISTORY']._serialized_end=2802 + _globals['_GRAPHSELECTION']._serialized_start=2804 + _globals['_GRAPHSELECTION']._serialized_end=2883 + _globals['_GRAPHDIFF']._serialized_start=2886 + _globals['_GRAPHDIFF']._serialized_end=3073 + _globals['_QUERYWINDOW']._serialized_start=3075 + _globals['_QUERYWINDOW']._serialized_end=3164 + _globals['_NODEFILTER']._serialized_start=3167 + _globals['_NODEFILTER']._serialized_end=3405 + _globals['_RELATIONSHIPFILTER']._serialized_start=3408 + _globals['_RELATIONSHIPFILTER']._serialized_end=3549 + _globals['_NODEQUERY']._serialized_start=3551 + _globals['_NODEQUERY']._serialized_end=3631 + _globals['_RELATIONSHIPQUERY']._serialized_start=3633 + _globals['_RELATIONSHIPQUERY']._serialized_end=3729 + _globals['_GRAPHPROJECTION']._serialized_start=3731 + _globals['_GRAPHPROJECTION']._serialized_end=3827 + _globals['_QUERYOPTIONS']._serialized_start=3830 + _globals['_QUERYOPTIONS']._serialized_end=3963 + _globals['_NODETYPECATALOG']._serialized_start=3965 + _globals['_NODETYPECATALOG']._serialized_end=4035 + _globals['_NEIGHBORQUERY']._serialized_start=4037 + _globals['_NEIGHBORQUERY']._serialized_end=4140 + _globals['_GRAPHQUERY']._serialized_start=4142 + _globals['_GRAPHQUERY']._serialized_end=4211 + _globals['_NODEANNOTATIONUPDATE']._serialized_start=4213 + _globals['_NODEANNOTATIONUPDATE']._serialized_end=4322 + _globals['_NODEFLAGCHANGE']._serialized_start=4324 + _globals['_NODEFLAGCHANGE']._serialized_end=4419 + _globals['_BFSALGORITHM']._serialized_start=4422 + _globals['_BFSALGORITHM']._serialized_end=4598 + _globals['_BETWEENNESSALGORITHM']._serialized_start=4600 + _globals['_BETWEENNESSALGORITHM']._serialized_end=4699 + _globals['_CLOSENESSALGORITHM']._serialized_start=4701 + _globals['_CLOSENESSALGORITHM']._serialized_end=4772 + _globals['_LEIDENALGORITHM']._serialized_start=4774 + _globals['_LEIDENALGORITHM']._serialized_end=4869 + _globals['_SHORTESTPATHSALGORITHM']._serialized_start=4872 + _globals['_SHORTESTPATHSALGORITHM']._serialized_end=5094 + _globals['_ALGORITHM']._serialized_start=5097 + _globals['_ALGORITHM']._serialized_end=5401 + _globals['_NODEPAGE']._serialized_start=5403 + _globals['_NODEPAGE']._serialized_end=5441 + _globals['_RELATIONSHIPPAGE']._serialized_start=5443 + _globals['_RELATIONSHIPPAGE']._serialized_end=5497 + _globals['_COMPONENTMEMBERSHIP']._serialized_start=5499 + _globals['_COMPONENTMEMBERSHIP']._serialized_end=5559 + _globals['_COMPONENTMEMBERSHIPPAGE']._serialized_start=5561 + _globals['_COMPONENTMEMBERSHIPPAGE']._serialized_end=5629 + _globals['_NODESCORE']._serialized_start=5631 + _globals['_NODESCORE']._serialized_end=5690 + _globals['_NODESCOREPAGE']._serialized_start=5692 + _globals['_NODESCOREPAGE']._serialized_end=5740 + _globals['_NODEPAIR']._serialized_start=5742 + _globals['_NODEPAIR']._serialized_end=5790 + _globals['_NODEPAIRPAGE']._serialized_start=5792 + _globals['_NODEPAIRPAGE']._serialized_end=5838 + _globals['_NODECYCLE']._serialized_start=5840 + _globals['_NODECYCLE']._serialized_end=5869 + _globals['_CYCLEPAGE']._serialized_start=5871 + _globals['_CYCLEPAGE']._serialized_end=5915 + _globals['_NODEPATH']._serialized_start=5917 + _globals['_NODEPATH']._serialized_end=5945 + _globals['_PATHPAGE']._serialized_start=5947 + _globals['_PATHPAGE']._serialized_end=5989 + _globals['_COMMUNITYMEMBERSHIP']._serialized_start=5991 + _globals['_COMMUNITYMEMBERSHIP']._serialized_end=6051 + _globals['_COMMUNITYMEMBERSHIPPAGE']._serialized_start=6053 + _globals['_COMMUNITYMEMBERSHIPPAGE']._serialized_end=6121 + _globals['_QUERYSUMMARY']._serialized_start=6123 + _globals['_QUERYSUMMARY']._serialized_end=6249 + _globals['_QUERYSUMMARY_NODESBYTYPEENTRY']._serialized_start=2107 + _globals['_QUERYSUMMARY_NODESBYTYPEENTRY']._serialized_end=2157 + _globals['_TRAVERSALSUMMARY']._serialized_start=6251 + _globals['_TRAVERSALSUMMARY']._serialized_end=6363 + _globals['_COMPONENTSUMMARY']._serialized_start=6365 + _globals['_COMPONENTSUMMARY']._serialized_end=6447 + _globals['_SCORESUMMARY']._serialized_start=6450 + _globals['_SCORESUMMARY']._serialized_end=6598 + _globals['_COMMUNITYSUMMARY']._serialized_start=6601 + _globals['_COMMUNITYSUMMARY']._serialized_end=6963 + _globals['_COMMUNITYSUMMARY_COMMUNITYSIZESENTRY']._serialized_start=6900 + _globals['_COMMUNITYSUMMARY_COMMUNITYSIZESENTRY']._serialized_end=6953 + _globals['_PATHSUMMARY']._serialized_start=6966 + _globals['_PATHSUMMARY']._serialized_end=7102 + _globals['_GRAPHRESULTPAGE']._serialized_start=7105 + _globals['_GRAPHRESULTPAGE']._serialized_end=7797 + _globals['_PARSERPAYLOAD']._serialized_start=7799 + _globals['_PARSERPAYLOAD']._serialized_end=7884 + _globals['_GRAPHINGESTRESULT']._serialized_start=7887 + _globals['_GRAPHINGESTRESULT']._serialized_end=8182 + _globals['_GRAPHINGESTRESULT_NODESBYTYPEENTRY']._serialized_start=2107 + _globals['_GRAPHINGESTRESULT_NODESBYTYPEENTRY']._serialized_end=2157 + _globals['_GRAPHLINKRESULT']._serialized_start=8184 + _globals['_GRAPHLINKRESULT']._serialized_end=8296 + _globals['_GRAPHANCHOR']._serialized_start=8299 + _globals['_GRAPHANCHOR']._serialized_end=8474 + _globals['_GRAPHANCHORCATALOG']._serialized_start=8476 + _globals['_GRAPHANCHORCATALOG']._serialized_end=8532 + _globals['_NODEFLAGUPDATE']._serialized_start=8535 + _globals['_NODEFLAGUPDATE']._serialized_end=8692 + _globals['_GRAPHPROJECTIONREPORT']._serialized_start=8695 + _globals['_GRAPHPROJECTIONREPORT']._serialized_end=8851 + _globals['_GRAPHPROJECTIONREPORT_NODEEXCLUSION']._serialized_start=8803 + _globals['_GRAPHPROJECTIONREPORT_NODEEXCLUSION']._serialized_end=8851 + _globals['_REPOSITORYOBJECT']._serialized_start=8853 + _globals['_REPOSITORYOBJECT']._serialized_end=8942 + _globals['_PUBLICATIONPLAN']._serialized_start=8944 + _globals['_PUBLICATIONPLAN']._serialized_end=9052 + _globals['_REPOSITORYSTATE']._serialized_start=9055 + _globals['_REPOSITORYSTATE']._serialized_end=9352 + _globals['_REPOSITORYSTATE_OBJECT']._serialized_start=9208 + _globals['_REPOSITORYSTATE_OBJECT']._serialized_end=9245 + _globals['_REPOSITORYSTATE_REF']._serialized_start=9247 + _globals['_REPOSITORYSTATE_REF']._serialized_end=9304 + _globals['_REPOSITORYSTATE_INDEX']._serialized_start=9306 + _globals['_REPOSITORYSTATE_INDEX']._serialized_end=9352 + _globals['_OBJECTSELECTION']._serialized_start=9354 + _globals['_OBJECTSELECTION']._serialized_end=9391 + _globals['_REPOSITORYOBJECTPLAN']._serialized_start=9394 + _globals['_REPOSITORYOBJECTPLAN']._serialized_end=9769 + _globals['_RAGFILTER']._serialized_start=9772 + _globals['_RAGFILTER']._serialized_end=9929 + _globals['_RAGGRAPHCHANGES']._serialized_start=9932 + _globals['_RAGGRAPHCHANGES']._serialized_end=10069 + _globals['_RAGRECORD']._serialized_start=10072 + _globals['_RAGRECORD']._serialized_end=10302 + _globals['_RAGINDEXRESULT']._serialized_start=10305 + _globals['_RAGINDEXRESULT']._serialized_end=10437 + _globals['_RAGINDEXPLAN']._serialized_start=10439 + _globals['_RAGINDEXPLAN']._serialized_end=10543 + _globals['_RAGRECORDPAGE']._serialized_start=10545 + _globals['_RAGRECORDPAGE']._serialized_end=10641 + _globals['_RECALLQUERY']._serialized_start=10643 + _globals['_RECALLQUERY']._serialized_end=10765 + _globals['_RECALLHIT']._serialized_start=10767 + _globals['_RECALLHIT']._serialized_end=10841 + _globals['_EXTENSIONRECALLRESULT']._serialized_start=10843 + _globals['_EXTENSIONRECALLRESULT']._serialized_end=10934 + _globals['_RECALLRESULTS']._serialized_start=10936 + _globals['_RECALLRESULTS']._serialized_end=10997 + _globals['_RECALLPLAN']._serialized_start=10999 + _globals['_RECALLPLAN']._serialized_end=11047 + _globals['_RAGPOLICY']._serialized_start=11050 + _globals['_RAGPOLICY']._serialized_end=11238 + _globals['_RAGQUERY']._serialized_start=11241 + _globals['_RAGQUERY']._serialized_end=11394 + _globals['_RANKEDNODE']._serialized_start=11396 + _globals['_RANKEDNODE']._serialized_end=11476 + _globals['_RANKEDRELATIONSHIP']._serialized_start=11478 + _globals['_RANKEDRELATIONSHIP']._serialized_end=11574 + _globals['_RAGPATH']._serialized_start=11576 + _globals['_RAGPATH']._serialized_end=11644 + _globals['_RAGCOMMUNITYHIT']._serialized_start=11646 + _globals['_RAGCOMMUNITYHIT']._serialized_end=11730 + _globals['_RAGCONTEXTBLOCK']._serialized_start=11732 + _globals['_RAGCONTEXTBLOCK']._serialized_end=11809 + _globals['_EVIDENCEPROVENANCE']._serialized_start=11811 + _globals['_EVIDENCEPROVENANCE']._serialized_end=11870 + _globals['_RAGRESULT']._serialized_start=11873 + _globals['_RAGRESULT']._serialized_end=12187 + _globals['_EXTENSIONCONTRACT']._serialized_start=12190 + _globals['_EXTENSIONCONTRACT']._serialized_end=12380 + _globals['_EXTENSIONCONTRACT_EXTENSIONSENTRY']._serialized_start=12298 + _globals['_EXTENSIONCONTRACT_EXTENSIONSENTRY']._serialized_end=12374 + _globals['_EXTENSIONDEFINITION']._serialized_start=12383 + _globals['_EXTENSIONDEFINITION']._serialized_end=12617 + _globals['_EXTENSIONDEFINITION_PARSERSENTRY']._serialized_start=12541 + _globals['_EXTENSIONDEFINITION_PARSERSENTRY']._serialized_end=12605 + _globals['_NODETYPE']._serialized_start=12619 + _globals['_NODETYPE']._serialized_end=12690 + _globals['_RELATIONSHIPTYPE']._serialized_start=12692 + _globals['_RELATIONSHIPTYPE']._serialized_end=12771 + _globals['_PARSERTYPE']._serialized_start=12773 + _globals['_PARSERTYPE']._serialized_end=12893 + _globals['_JOINRULE']._serialized_start=12896 + _globals['_JOINRULE']._serialized_end=13138 + _globals['_EXTENSIONINFO']._serialized_start=13140 + _globals['_EXTENSIONINFO']._serialized_end=13236 + _globals['_EXTENSIONCATALOG']._serialized_start=13238 + _globals['_EXTENSIONCATALOG']._serialized_end=13297 + _globals['_ANCHORCONCEPT']._serialized_start=13299 + _globals['_ANCHORCONCEPT']._serialized_end=13348 + _globals['_ANCHORCONCEPTCATALOG']._serialized_start=13350 + _globals['_ANCHORCONCEPTCATALOG']._serialized_end=13411 +# @@protoc_insertion_point(module_scope) diff --git a/python/python/cstxpy/proto/cstx_pb2.pyi b/python/python/cstxpy/proto/cstx_pb2.pyi new file mode 100644 index 0000000..0cc7104 --- /dev/null +++ b/python/python/cstxpy/proto/cstx_pb2.pyi @@ -0,0 +1,1415 @@ +from google.protobuf import descriptor_pb2 as _descriptor_pb2 +from google.protobuf import struct_pb2 as _struct_pb2 +from google.protobuf.internal import containers as _containers +from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from collections.abc import Iterable as _Iterable, Mapping as _Mapping +from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union + +DESCRIPTOR: _descriptor.FileDescriptor + +class ChangeOperation(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + CHANGE_OPERATION_UNSPECIFIED: _ClassVar[ChangeOperation] + CHANGE_OPERATION_ADDED: _ClassVar[ChangeOperation] + CHANGE_OPERATION_UPDATED: _ClassVar[ChangeOperation] + CHANGE_OPERATION_REMOVED: _ClassVar[ChangeOperation] + +class SortOrder(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + SORT_ORDER_UNSPECIFIED: _ClassVar[SortOrder] + SORT_ORDER_ID_ASC: _ClassVar[SortOrder] + SORT_ORDER_ID_DESC: _ClassVar[SortOrder] + +class Direction(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + DIRECTION_UNSPECIFIED: _ClassVar[Direction] + DIRECTION_OUT: _ClassVar[Direction] + DIRECTION_IN: _ClassVar[Direction] + DIRECTION_BOTH: _ClassVar[Direction] + +class ParameterlessAlgorithm(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + PARAMETERLESS_ALGORITHM_UNSPECIFIED: _ClassVar[ParameterlessAlgorithm] + PARAMETERLESS_WEAK_COMPONENTS: _ClassVar[ParameterlessAlgorithm] + PARAMETERLESS_STRONG_COMPONENTS: _ClassVar[ParameterlessAlgorithm] + PARAMETERLESS_CYCLE_BASIS: _ClassVar[ParameterlessAlgorithm] + PARAMETERLESS_BRIDGES: _ClassVar[ParameterlessAlgorithm] + PARAMETERLESS_ARTICULATION_POINTS: _ClassVar[ParameterlessAlgorithm] + PARAMETERLESS_CORE_NUMBERS: _ClassVar[ParameterlessAlgorithm] + PARAMETERLESS_IS_DAG: _ClassVar[ParameterlessAlgorithm] + PARAMETERLESS_TOPOLOGICAL_ORDER: _ClassVar[ParameterlessAlgorithm] + +class NodeFlagUpdateMode(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + NODE_FLAG_UPDATE_UNSPECIFIED: _ClassVar[NodeFlagUpdateMode] + NODE_FLAG_UPDATE_MERGE: _ClassVar[NodeFlagUpdateMode] + NODE_FLAG_UPDATE_REPLACE: _ClassVar[NodeFlagUpdateMode] + +class ObjectKind(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + OBJECT_KIND_UNSPECIFIED: _ClassVar[ObjectKind] + OBJECT_KIND_TREE: _ClassVar[ObjectKind] + OBJECT_KIND_STAT: _ClassVar[ObjectKind] + OBJECT_KIND_MERGE: _ClassVar[ObjectKind] + OBJECT_KIND_DELTA: _ClassVar[ObjectKind] + OBJECT_KIND_PREPARE: _ClassVar[ObjectKind] + OBJECT_KIND_HISTORY: _ClassVar[ObjectKind] + OBJECT_KIND_COMMITS: _ClassVar[ObjectKind] + OBJECT_KIND_DIFF: _ClassVar[ObjectKind] + OBJECT_KIND_CLOSURE: _ClassVar[ObjectKind] + +class RepositoryObjectKind(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + REPOSITORY_OBJECT_KIND_UNSPECIFIED: _ClassVar[RepositoryObjectKind] + REPOSITORY_OBJECT_KIND_TREE: _ClassVar[RepositoryObjectKind] + REPOSITORY_OBJECT_KIND_COMMIT: _ClassVar[RepositoryObjectKind] + REPOSITORY_OBJECT_KIND_INDEX: _ClassVar[RepositoryObjectKind] + REPOSITORY_OBJECT_KIND_BLOB: _ClassVar[RepositoryObjectKind] + +class RepositoryPlanKind(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + REPOSITORY_PLAN_UNSPECIFIED: _ClassVar[RepositoryPlanKind] + REPOSITORY_PLAN_TREE: _ClassVar[RepositoryPlanKind] + REPOSITORY_PLAN_STAT: _ClassVar[RepositoryPlanKind] + REPOSITORY_PLAN_PREPARE: _ClassVar[RepositoryPlanKind] + REPOSITORY_PLAN_COMMITS: _ClassVar[RepositoryPlanKind] + REPOSITORY_PLAN_DELTA: _ClassVar[RepositoryPlanKind] + REPOSITORY_PLAN_CLOSURE: _ClassVar[RepositoryPlanKind] + REPOSITORY_PLAN_HISTORY: _ClassVar[RepositoryPlanKind] + REPOSITORY_PLAN_MERGE: _ClassVar[RepositoryPlanKind] + REPOSITORY_PLAN_DIFF: _ClassVar[RepositoryPlanKind] + REPOSITORY_PLAN_ENTITIES: _ClassVar[RepositoryPlanKind] + +class DiffDetail(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + DIFF_DETAIL_UNSPECIFIED: _ClassVar[DiffDetail] + DIFF_DETAIL_ENTITIES: _ClassVar[DiffDetail] + DIFF_DETAIL_COUNTS: _ClassVar[DiffDetail] + +class RagRecordKind(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + RAG_RECORD_KIND_UNSPECIFIED: _ClassVar[RagRecordKind] + RAG_RECORD_NODE: _ClassVar[RagRecordKind] + RAG_RECORD_RELATIONSHIP: _ClassVar[RagRecordKind] + +class RagIndexMode(int, metaclass=_enum_type_wrapper.EnumTypeWrapper): + __slots__ = () + RAG_INDEX_MODE_UNSPECIFIED: _ClassVar[RagIndexMode] + RAG_INDEX_INCREMENTAL: _ClassVar[RagIndexMode] + RAG_INDEX_FULL: _ClassVar[RagIndexMode] +CHANGE_OPERATION_UNSPECIFIED: ChangeOperation +CHANGE_OPERATION_ADDED: ChangeOperation +CHANGE_OPERATION_UPDATED: ChangeOperation +CHANGE_OPERATION_REMOVED: ChangeOperation +SORT_ORDER_UNSPECIFIED: SortOrder +SORT_ORDER_ID_ASC: SortOrder +SORT_ORDER_ID_DESC: SortOrder +DIRECTION_UNSPECIFIED: Direction +DIRECTION_OUT: Direction +DIRECTION_IN: Direction +DIRECTION_BOTH: Direction +PARAMETERLESS_ALGORITHM_UNSPECIFIED: ParameterlessAlgorithm +PARAMETERLESS_WEAK_COMPONENTS: ParameterlessAlgorithm +PARAMETERLESS_STRONG_COMPONENTS: ParameterlessAlgorithm +PARAMETERLESS_CYCLE_BASIS: ParameterlessAlgorithm +PARAMETERLESS_BRIDGES: ParameterlessAlgorithm +PARAMETERLESS_ARTICULATION_POINTS: ParameterlessAlgorithm +PARAMETERLESS_CORE_NUMBERS: ParameterlessAlgorithm +PARAMETERLESS_IS_DAG: ParameterlessAlgorithm +PARAMETERLESS_TOPOLOGICAL_ORDER: ParameterlessAlgorithm +NODE_FLAG_UPDATE_UNSPECIFIED: NodeFlagUpdateMode +NODE_FLAG_UPDATE_MERGE: NodeFlagUpdateMode +NODE_FLAG_UPDATE_REPLACE: NodeFlagUpdateMode +OBJECT_KIND_UNSPECIFIED: ObjectKind +OBJECT_KIND_TREE: ObjectKind +OBJECT_KIND_STAT: ObjectKind +OBJECT_KIND_MERGE: ObjectKind +OBJECT_KIND_DELTA: ObjectKind +OBJECT_KIND_PREPARE: ObjectKind +OBJECT_KIND_HISTORY: ObjectKind +OBJECT_KIND_COMMITS: ObjectKind +OBJECT_KIND_DIFF: ObjectKind +OBJECT_KIND_CLOSURE: ObjectKind +REPOSITORY_OBJECT_KIND_UNSPECIFIED: RepositoryObjectKind +REPOSITORY_OBJECT_KIND_TREE: RepositoryObjectKind +REPOSITORY_OBJECT_KIND_COMMIT: RepositoryObjectKind +REPOSITORY_OBJECT_KIND_INDEX: RepositoryObjectKind +REPOSITORY_OBJECT_KIND_BLOB: RepositoryObjectKind +REPOSITORY_PLAN_UNSPECIFIED: RepositoryPlanKind +REPOSITORY_PLAN_TREE: RepositoryPlanKind +REPOSITORY_PLAN_STAT: RepositoryPlanKind +REPOSITORY_PLAN_PREPARE: RepositoryPlanKind +REPOSITORY_PLAN_COMMITS: RepositoryPlanKind +REPOSITORY_PLAN_DELTA: RepositoryPlanKind +REPOSITORY_PLAN_CLOSURE: RepositoryPlanKind +REPOSITORY_PLAN_HISTORY: RepositoryPlanKind +REPOSITORY_PLAN_MERGE: RepositoryPlanKind +REPOSITORY_PLAN_DIFF: RepositoryPlanKind +REPOSITORY_PLAN_ENTITIES: RepositoryPlanKind +DIFF_DETAIL_UNSPECIFIED: DiffDetail +DIFF_DETAIL_ENTITIES: DiffDetail +DIFF_DETAIL_COUNTS: DiffDetail +RAG_RECORD_KIND_UNSPECIFIED: RagRecordKind +RAG_RECORD_NODE: RagRecordKind +RAG_RECORD_RELATIONSHIP: RagRecordKind +RAG_INDEX_MODE_UNSPECIFIED: RagIndexMode +RAG_INDEX_INCREMENTAL: RagIndexMode +RAG_INDEX_FULL: RagIndexMode +CSTX_NODE_FIELD_NUMBER: _ClassVar[int] +cstx_node: _descriptor.FieldDescriptor +CSTX_RELATIONSHIP_FIELD_NUMBER: _ClassVar[int] +cstx_relationship: _descriptor.FieldDescriptor +CSTX_FIELD_FIELD_NUMBER: _ClassVar[int] +cstx_field: _descriptor.FieldDescriptor +CSTX_FLAG_FIELD_NUMBER: _ClassVar[int] +cstx_flag: _descriptor.FieldDescriptor + +class CstxNodeOptions(_message.Message): + __slots__ = () + NODE_TYPE_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_FIELD_NUMBER: _ClassVar[int] + IDENTITY_COMPUTED_FIELD_NUMBER: _ClassVar[int] + LABEL_FIELD_FIELD_NUMBER: _ClassVar[int] + node_type: str + value_field: str + identity_computed: bool + label_field: str + def __init__(self, node_type: _Optional[str] = ..., value_field: _Optional[str] = ..., identity_computed: _Optional[bool] = ..., label_field: _Optional[str] = ...) -> None: ... + +class CstxComputeOptions(_message.Message): + __slots__ = () + FROM_FIELD_NUMBER: _ClassVar[int] + APPLY_FIELD_NUMBER: _ClassVar[int] + apply: str + def __init__(self, apply: _Optional[str] = ..., **kwargs) -> None: ... + +class CstxFieldOptions(_message.Message): + __slots__ = () + IDENTITY_FIELD_NUMBER: _ClassVar[int] + IDENTITY_FORMAT_FIELD_NUMBER: _ClassVar[int] + SEMANTIC_FIELD_NUMBER: _ClassVar[int] + SEMANTIC_LABEL_FIELD_NUMBER: _ClassVar[int] + COLUMN_FIELD_NUMBER: _ClassVar[int] + ORDERED_VALUES_FIELD_NUMBER: _ClassVar[int] + COMPUTE_FIELD_NUMBER: _ClassVar[int] + identity: bool + identity_format: str + semantic: bool + semantic_label: str + column: str + ordered_values: _containers.RepeatedScalarFieldContainer[str] + compute: CstxComputeOptions + def __init__(self, identity: _Optional[bool] = ..., identity_format: _Optional[str] = ..., semantic: _Optional[bool] = ..., semantic_label: _Optional[str] = ..., column: _Optional[str] = ..., ordered_values: _Optional[_Iterable[str]] = ..., compute: _Optional[_Union[CstxComputeOptions, _Mapping]] = ...) -> None: ... + +class CstxRelationshipOptions(_message.Message): + __slots__ = () + RELATIONSHIP_TYPE_FIELD_NUMBER: _ClassVar[int] + relationship_type: str + def __init__(self, relationship_type: _Optional[str] = ...) -> None: ... + +class CstxFlagOptions(_message.Message): + __slots__ = () + BIT_FIELD_NUMBER: _ClassVar[int] + DEFAULT_EXCLUDE_FIELD_NUMBER: _ClassVar[int] + LABEL_FIELD_NUMBER: _ClassVar[int] + bit: int + default_exclude: bool + label: str + def __init__(self, bit: _Optional[int] = ..., default_exclude: _Optional[bool] = ..., label: _Optional[str] = ...) -> None: ... + +class RuntimeConfig(_message.Message): + __slots__ = () + PROJECT_ID_FIELD_NUMBER: _ClassVar[int] + CURSOR_PAGE_SIZE_FIELD_NUMBER: _ClassVar[int] + project_id: str + cursor_page_size: int + def __init__(self, project_id: _Optional[str] = ..., cursor_page_size: _Optional[int] = ...) -> None: ... + +class StringList(_message.Message): + __slots__ = () + VALUES_FIELD_NUMBER: _ClassVar[int] + values: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, values: _Optional[_Iterable[str]] = ...) -> None: ... + +class EntityField(_message.Message): + __slots__ = () + NAME_FIELD_NUMBER: _ClassVar[int] + TEXT_FIELD_NUMBER: _ClassVar[int] + NUMBER_FIELD_NUMBER: _ClassVar[int] + FLAG_FIELD_NUMBER: _ClassVar[int] + REAL_FIELD_NUMBER: _ClassVar[int] + LIST_FIELD_NUMBER: _ClassVar[int] + name: str + text: str + number: int + flag: bool + real: float + list: StringList + def __init__(self, name: _Optional[str] = ..., text: _Optional[str] = ..., number: _Optional[int] = ..., flag: _Optional[bool] = ..., real: _Optional[float] = ..., list: _Optional[_Union[StringList, _Mapping]] = ...) -> None: ... + +class EntityValue(_message.Message): + __slots__ = () + NODE_TYPE_FIELD_NUMBER: _ClassVar[int] + FIELDS_FIELD_NUMBER: _ClassVar[int] + node_type: str + fields: _containers.RepeatedCompositeFieldContainer[EntityField] + def __init__(self, node_type: _Optional[str] = ..., fields: _Optional[_Iterable[_Union[EntityField, _Mapping]]] = ...) -> None: ... + +class RelationshipValue(_message.Message): + __slots__ = () + RELATIONSHIP_TYPE_FIELD_NUMBER: _ClassVar[int] + FIELDS_FIELD_NUMBER: _ClassVar[int] + relationship_type: str + fields: _containers.RepeatedCompositeFieldContainer[EntityField] + def __init__(self, relationship_type: _Optional[str] = ..., fields: _Optional[_Iterable[_Union[EntityField, _Mapping]]] = ...) -> None: ... + +class Node(_message.Message): + __slots__ = () + ID_FIELD_NUMBER: _ClassVar[int] + SOURCES_FIELD_NUMBER: _ClassVar[int] + ANNOTATIONS_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + FLAGS_MASK_FIELD_NUMBER: _ClassVar[int] + id: str + sources: _containers.RepeatedScalarFieldContainer[str] + annotations: _struct_pb2.Struct + value: EntityValue + flags_mask: int + def __init__(self, id: _Optional[str] = ..., sources: _Optional[_Iterable[str]] = ..., annotations: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., value: _Optional[_Union[EntityValue, _Mapping]] = ..., flags_mask: _Optional[int] = ...) -> None: ... + +class Relationship(_message.Message): + __slots__ = () + ID_FIELD_NUMBER: _ClassVar[int] + SOURCE_ID_FIELD_NUMBER: _ClassVar[int] + TARGET_ID_FIELD_NUMBER: _ClassVar[int] + SOURCES_FIELD_NUMBER: _ClassVar[int] + ANNOTATIONS_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + id: str + source_id: str + target_id: str + sources: _containers.RepeatedScalarFieldContainer[str] + annotations: _struct_pb2.Struct + value: RelationshipValue + def __init__(self, id: _Optional[str] = ..., source_id: _Optional[str] = ..., target_id: _Optional[str] = ..., sources: _Optional[_Iterable[str]] = ..., annotations: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., value: _Optional[_Union[RelationshipValue, _Mapping]] = ...) -> None: ... + +class Graph(_message.Message): + __slots__ = () + NODES_FIELD_NUMBER: _ClassVar[int] + RELATIONSHIPS_FIELD_NUMBER: _ClassVar[int] + nodes: _containers.RepeatedCompositeFieldContainer[Node] + relationships: _containers.RepeatedCompositeFieldContainer[Relationship] + def __init__(self, nodes: _Optional[_Iterable[_Union[Node, _Mapping]]] = ..., relationships: _Optional[_Iterable[_Union[Relationship, _Mapping]]] = ...) -> None: ... + +class GraphChangeSet(_message.Message): + __slots__ = () + ADDED_NODE_IDS_FIELD_NUMBER: _ClassVar[int] + UPDATED_NODE_IDS_FIELD_NUMBER: _ClassVar[int] + REMOVED_NODE_IDS_FIELD_NUMBER: _ClassVar[int] + ADDED_RELATIONSHIP_IDS_FIELD_NUMBER: _ClassVar[int] + UPDATED_RELATIONSHIP_IDS_FIELD_NUMBER: _ClassVar[int] + REMOVED_RELATIONSHIP_IDS_FIELD_NUMBER: _ClassVar[int] + RESET_FIELD_NUMBER: _ClassVar[int] + added_node_ids: _containers.RepeatedScalarFieldContainer[str] + updated_node_ids: _containers.RepeatedScalarFieldContainer[str] + removed_node_ids: _containers.RepeatedScalarFieldContainer[str] + added_relationship_ids: _containers.RepeatedScalarFieldContainer[str] + updated_relationship_ids: _containers.RepeatedScalarFieldContainer[str] + removed_relationship_ids: _containers.RepeatedScalarFieldContainer[str] + reset: bool + def __init__(self, added_node_ids: _Optional[_Iterable[str]] = ..., updated_node_ids: _Optional[_Iterable[str]] = ..., removed_node_ids: _Optional[_Iterable[str]] = ..., added_relationship_ids: _Optional[_Iterable[str]] = ..., updated_relationship_ids: _Optional[_Iterable[str]] = ..., removed_relationship_ids: _Optional[_Iterable[str]] = ..., reset: _Optional[bool] = ...) -> None: ... + +class GraphChangeSummary(_message.Message): + __slots__ = () + ADDED_NODES_FIELD_NUMBER: _ClassVar[int] + UPDATED_NODES_FIELD_NUMBER: _ClassVar[int] + REMOVED_NODES_FIELD_NUMBER: _ClassVar[int] + ADDED_RELATIONSHIPS_FIELD_NUMBER: _ClassVar[int] + UPDATED_RELATIONSHIPS_FIELD_NUMBER: _ClassVar[int] + REMOVED_RELATIONSHIPS_FIELD_NUMBER: _ClassVar[int] + added_nodes: int + updated_nodes: int + removed_nodes: int + added_relationships: int + updated_relationships: int + removed_relationships: int + def __init__(self, added_nodes: _Optional[int] = ..., updated_nodes: _Optional[int] = ..., removed_nodes: _Optional[int] = ..., added_relationships: _Optional[int] = ..., updated_relationships: _Optional[int] = ..., removed_relationships: _Optional[int] = ...) -> None: ... + +class GraphStats(_message.Message): + __slots__ = () + class NodesByTypeEntry(_message.Message): + __slots__ = () + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: int + def __init__(self, key: _Optional[str] = ..., value: _Optional[int] = ...) -> None: ... + class RelationshipsByTypeEntry(_message.Message): + __slots__ = () + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: int + def __init__(self, key: _Optional[str] = ..., value: _Optional[int] = ...) -> None: ... + class ObjectsBySourceEntry(_message.Message): + __slots__ = () + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: int + def __init__(self, key: _Optional[str] = ..., value: _Optional[int] = ...) -> None: ... + class AnchorsByKindEntry(_message.Message): + __slots__ = () + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: int + def __init__(self, key: _Optional[str] = ..., value: _Optional[int] = ...) -> None: ... + NODES_BY_TYPE_FIELD_NUMBER: _ClassVar[int] + RELATIONSHIPS_BY_TYPE_FIELD_NUMBER: _ClassVar[int] + OBJECTS_BY_SOURCE_FIELD_NUMBER: _ClassVar[int] + ANCHORS_BY_KIND_FIELD_NUMBER: _ClassVar[int] + nodes_by_type: _containers.ScalarMap[str, int] + relationships_by_type: _containers.ScalarMap[str, int] + objects_by_source: _containers.ScalarMap[str, int] + anchors_by_kind: _containers.ScalarMap[str, int] + def __init__(self, nodes_by_type: _Optional[_Mapping[str, int]] = ..., relationships_by_type: _Optional[_Mapping[str, int]] = ..., objects_by_source: _Optional[_Mapping[str, int]] = ..., anchors_by_kind: _Optional[_Mapping[str, int]] = ...) -> None: ... + +class Commit(_message.Message): + __slots__ = () + ID_FIELD_NUMBER: _ClassVar[int] + PARENTS_FIELD_NUMBER: _ClassVar[int] + MESSAGE_FIELD_NUMBER: _ClassVar[int] + METADATA_FIELD_NUMBER: _ClassVar[int] + STATS_FIELD_NUMBER: _ClassVar[int] + CREATED_AT_FIELD_NUMBER: _ClassVar[int] + id: str + parents: _containers.RepeatedScalarFieldContainer[str] + message: str + metadata: _struct_pb2.Struct + stats: GraphChangeSummary + created_at: int + def __init__(self, id: _Optional[str] = ..., parents: _Optional[_Iterable[str]] = ..., message: _Optional[str] = ..., metadata: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., stats: _Optional[_Union[GraphChangeSummary, _Mapping]] = ..., created_at: _Optional[int] = ...) -> None: ... + +class CommitLog(_message.Message): + __slots__ = () + COMMITS_FIELD_NUMBER: _ClassVar[int] + commits: _containers.RepeatedCompositeFieldContainer[Commit] + def __init__(self, commits: _Optional[_Iterable[_Union[Commit, _Mapping]]] = ...) -> None: ... + +class EntityChange(_message.Message): + __slots__ = () + COMMIT_ID_FIELD_NUMBER: _ClassVar[int] + ORDINAL_FIELD_NUMBER: _ClassVar[int] + TIMESTAMP_FIELD_NUMBER: _ClassVar[int] + OPERATION_FIELD_NUMBER: _ClassVar[int] + BEFORE_OBJECT_ID_FIELD_NUMBER: _ClassVar[int] + AFTER_OBJECT_ID_FIELD_NUMBER: _ClassVar[int] + commit_id: str + ordinal: int + timestamp: int + operation: ChangeOperation + before_object_id: str + after_object_id: str + def __init__(self, commit_id: _Optional[str] = ..., ordinal: _Optional[int] = ..., timestamp: _Optional[int] = ..., operation: _Optional[_Union[ChangeOperation, str]] = ..., before_object_id: _Optional[str] = ..., after_object_id: _Optional[str] = ...) -> None: ... + +class EntityHistory(_message.Message): + __slots__ = () + CHANGES_FIELD_NUMBER: _ClassVar[int] + changes: _containers.RepeatedCompositeFieldContainer[EntityChange] + def __init__(self, changes: _Optional[_Iterable[_Union[EntityChange, _Mapping]]] = ...) -> None: ... + +class GraphSelection(_message.Message): + __slots__ = () + NODE_IDS_FIELD_NUMBER: _ClassVar[int] + RELATIONSHIP_IDS_FIELD_NUMBER: _ClassVar[int] + ALL_NODES_FIELD_NUMBER: _ClassVar[int] + node_ids: _containers.RepeatedScalarFieldContainer[str] + relationship_ids: _containers.RepeatedScalarFieldContainer[str] + all_nodes: bool + def __init__(self, node_ids: _Optional[_Iterable[str]] = ..., relationship_ids: _Optional[_Iterable[str]] = ..., all_nodes: _Optional[bool] = ...) -> None: ... + +class GraphDiff(_message.Message): + __slots__ = () + ADDED_FIELD_NUMBER: _ClassVar[int] + REMOVED_FIELD_NUMBER: _ClassVar[int] + MODIFIED_FIELD_NUMBER: _ClassVar[int] + TRUNCATED_FIELD_NUMBER: _ClassVar[int] + STATS_FIELD_NUMBER: _ClassVar[int] + added: GraphSelection + removed: GraphSelection + modified: GraphSelection + truncated: bool + stats: GraphChangeSummary + def __init__(self, added: _Optional[_Union[GraphSelection, _Mapping]] = ..., removed: _Optional[_Union[GraphSelection, _Mapping]] = ..., modified: _Optional[_Union[GraphSelection, _Mapping]] = ..., truncated: _Optional[bool] = ..., stats: _Optional[_Union[GraphChangeSummary, _Mapping]] = ...) -> None: ... + +class QueryWindow(_message.Message): + __slots__ = () + LIMIT_FIELD_NUMBER: _ClassVar[int] + PAGE_FIELD_NUMBER: _ClassVar[int] + ORDER_FIELD_NUMBER: _ClassVar[int] + limit: int + page: int + order: SortOrder + def __init__(self, limit: _Optional[int] = ..., page: _Optional[int] = ..., order: _Optional[_Union[SortOrder, str]] = ...) -> None: ... + +class NodeFilter(_message.Message): + __slots__ = () + NODE_TYPES_FIELD_NUMBER: _ClassVar[int] + NODE_IDS_FIELD_NUMBER: _ClassVar[int] + SOURCES_FIELD_NUMBER: _ClassVar[int] + NAME_CONTAINS_FIELD_NUMBER: _ClassVar[int] + FLAGS_ALL_MASK_FIELD_NUMBER: _ClassVar[int] + FLAGS_ANY_MASK_FIELD_NUMBER: _ClassVar[int] + FLAGS_NONE_MASK_FIELD_NUMBER: _ClassVar[int] + node_types: _containers.RepeatedScalarFieldContainer[str] + node_ids: _containers.RepeatedScalarFieldContainer[str] + sources: _containers.RepeatedScalarFieldContainer[str] + name_contains: str + flags_all_mask: int + flags_any_mask: int + flags_none_mask: int + def __init__(self, node_types: _Optional[_Iterable[str]] = ..., node_ids: _Optional[_Iterable[str]] = ..., sources: _Optional[_Iterable[str]] = ..., name_contains: _Optional[str] = ..., flags_all_mask: _Optional[int] = ..., flags_any_mask: _Optional[int] = ..., flags_none_mask: _Optional[int] = ...) -> None: ... + +class RelationshipFilter(_message.Message): + __slots__ = () + SOURCE_ID_FIELD_NUMBER: _ClassVar[int] + TARGET_ID_FIELD_NUMBER: _ClassVar[int] + RELATIONSHIP_TYPES_FIELD_NUMBER: _ClassVar[int] + SOURCES_FIELD_NUMBER: _ClassVar[int] + source_id: str + target_id: str + relationship_types: _containers.RepeatedScalarFieldContainer[str] + sources: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, source_id: _Optional[str] = ..., target_id: _Optional[str] = ..., relationship_types: _Optional[_Iterable[str]] = ..., sources: _Optional[_Iterable[str]] = ...) -> None: ... + +class NodeQuery(_message.Message): + __slots__ = () + FILTER_FIELD_NUMBER: _ClassVar[int] + WINDOW_FIELD_NUMBER: _ClassVar[int] + filter: NodeFilter + window: QueryWindow + def __init__(self, filter: _Optional[_Union[NodeFilter, _Mapping]] = ..., window: _Optional[_Union[QueryWindow, _Mapping]] = ...) -> None: ... + +class RelationshipQuery(_message.Message): + __slots__ = () + FILTER_FIELD_NUMBER: _ClassVar[int] + WINDOW_FIELD_NUMBER: _ClassVar[int] + filter: RelationshipFilter + window: QueryWindow + def __init__(self, filter: _Optional[_Union[RelationshipFilter, _Mapping]] = ..., window: _Optional[_Union[QueryWindow, _Mapping]] = ...) -> None: ... + +class GraphProjection(_message.Message): + __slots__ = () + NODE_FILTER_FIELD_NUMBER: _ClassVar[int] + EXCLUDED_FIELD_NUMBER: _ClassVar[int] + node_filter: NodeFilter + excluded: GraphSelection + def __init__(self, node_filter: _Optional[_Union[NodeFilter, _Mapping]] = ..., excluded: _Optional[_Union[GraphSelection, _Mapping]] = ...) -> None: ... + +class QueryOptions(_message.Message): + __slots__ = () + WINDOW_FIELD_NUMBER: _ClassVar[int] + RESULT_FILTER_FIELD_NUMBER: _ClassVar[int] + PROJECTION_FIELD_NUMBER: _ClassVar[int] + window: QueryWindow + result_filter: NodeFilter + projection: GraphProjection + def __init__(self, window: _Optional[_Union[QueryWindow, _Mapping]] = ..., result_filter: _Optional[_Union[NodeFilter, _Mapping]] = ..., projection: _Optional[_Union[GraphProjection, _Mapping]] = ...) -> None: ... + +class NodeTypeCatalog(_message.Message): + __slots__ = () + NODE_TYPES_FIELD_NUMBER: _ClassVar[int] + SCHEMAS_FIELD_NUMBER: _ClassVar[int] + node_types: _containers.RepeatedScalarFieldContainer[str] + schemas: _containers.RepeatedCompositeFieldContainer[NodeType] + def __init__(self, node_types: _Optional[_Iterable[str]] = ..., schemas: _Optional[_Iterable[_Union[NodeType, _Mapping]]] = ...) -> None: ... + +class NeighborQuery(_message.Message): + __slots__ = () + NODE_ID_FIELD_NUMBER: _ClassVar[int] + DIRECTION_FIELD_NUMBER: _ClassVar[int] + WINDOW_FIELD_NUMBER: _ClassVar[int] + node_id: str + direction: Direction + window: QueryWindow + def __init__(self, node_id: _Optional[str] = ..., direction: _Optional[_Union[Direction, str]] = ..., window: _Optional[_Union[QueryWindow, _Mapping]] = ...) -> None: ... + +class GraphQuery(_message.Message): + __slots__ = () + EXPRESSION_FIELD_NUMBER: _ClassVar[int] + OPTIONS_FIELD_NUMBER: _ClassVar[int] + expression: str + options: QueryOptions + def __init__(self, expression: _Optional[str] = ..., options: _Optional[_Union[QueryOptions, _Mapping]] = ...) -> None: ... + +class NodeAnnotationUpdate(_message.Message): + __slots__ = () + SELECTION_FIELD_NUMBER: _ClassVar[int] + ANNOTATIONS_FIELD_NUMBER: _ClassVar[int] + selection: GraphSelection + annotations: _struct_pb2.Struct + def __init__(self, selection: _Optional[_Union[GraphSelection, _Mapping]] = ..., annotations: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ... + +class NodeFlagChange(_message.Message): + __slots__ = () + SELECTION_FIELD_NUMBER: _ClassVar[int] + UPDATE_FIELD_NUMBER: _ClassVar[int] + selection: GraphSelection + update: NodeFlagUpdate + def __init__(self, selection: _Optional[_Union[GraphSelection, _Mapping]] = ..., update: _Optional[_Union[NodeFlagUpdate, _Mapping]] = ...) -> None: ... + +class BfsAlgorithm(_message.Message): + __slots__ = () + SEED_ID_FIELD_NUMBER: _ClassVar[int] + DEPTH_FIELD_NUMBER: _ClassVar[int] + DIRECTION_FIELD_NUMBER: _ClassVar[int] + MAX_VISITED_NODES_FIELD_NUMBER: _ClassVar[int] + TIMEOUT_MS_FIELD_NUMBER: _ClassVar[int] + seed_id: str + depth: int + direction: Direction + max_visited_nodes: int + timeout_ms: int + def __init__(self, seed_id: _Optional[str] = ..., depth: _Optional[int] = ..., direction: _Optional[_Union[Direction, str]] = ..., max_visited_nodes: _Optional[int] = ..., timeout_ms: _Optional[int] = ...) -> None: ... + +class BetweennessAlgorithm(_message.Message): + __slots__ = () + INCLUDE_ENDPOINTS_FIELD_NUMBER: _ClassVar[int] + NORMALIZED_FIELD_NUMBER: _ClassVar[int] + TOP_K_FIELD_NUMBER: _ClassVar[int] + include_endpoints: bool + normalized: bool + top_k: int + def __init__(self, include_endpoints: _Optional[bool] = ..., normalized: _Optional[bool] = ..., top_k: _Optional[int] = ...) -> None: ... + +class ClosenessAlgorithm(_message.Message): + __slots__ = () + WF_IMPROVED_FIELD_NUMBER: _ClassVar[int] + TOP_K_FIELD_NUMBER: _ClassVar[int] + wf_improved: bool + top_k: int + def __init__(self, wf_improved: _Optional[bool] = ..., top_k: _Optional[int] = ...) -> None: ... + +class LeidenAlgorithm(_message.Message): + __slots__ = () + RESOLUTION_FIELD_NUMBER: _ClassVar[int] + MIN_COMMUNITY_SIZE_FIELD_NUMBER: _ClassVar[int] + TOP_K_FIELD_NUMBER: _ClassVar[int] + resolution: float + min_community_size: int + top_k: int + def __init__(self, resolution: _Optional[float] = ..., min_community_size: _Optional[int] = ..., top_k: _Optional[int] = ...) -> None: ... + +class ShortestPathsAlgorithm(_message.Message): + __slots__ = () + START_ID_FIELD_NUMBER: _ClassVar[int] + END_ID_FIELD_NUMBER: _ClassVar[int] + DIRECTION_FIELD_NUMBER: _ClassVar[int] + MAX_DEPTH_FIELD_NUMBER: _ClassVar[int] + LIMIT_FIELD_NUMBER: _ClassVar[int] + MAX_VISITED_NODES_FIELD_NUMBER: _ClassVar[int] + TIMEOUT_MS_FIELD_NUMBER: _ClassVar[int] + start_id: str + end_id: str + direction: Direction + max_depth: int + limit: int + max_visited_nodes: int + timeout_ms: int + def __init__(self, start_id: _Optional[str] = ..., end_id: _Optional[str] = ..., direction: _Optional[_Union[Direction, str]] = ..., max_depth: _Optional[int] = ..., limit: _Optional[int] = ..., max_visited_nodes: _Optional[int] = ..., timeout_ms: _Optional[int] = ...) -> None: ... + +class Algorithm(_message.Message): + __slots__ = () + BFS_FIELD_NUMBER: _ClassVar[int] + PARAMETERLESS_FIELD_NUMBER: _ClassVar[int] + BETWEENNESS_FIELD_NUMBER: _ClassVar[int] + CLOSENESS_FIELD_NUMBER: _ClassVar[int] + LEIDEN_FIELD_NUMBER: _ClassVar[int] + SHORTEST_PATHS_FIELD_NUMBER: _ClassVar[int] + bfs: BfsAlgorithm + parameterless: ParameterlessAlgorithm + betweenness: BetweennessAlgorithm + closeness: ClosenessAlgorithm + leiden: LeidenAlgorithm + shortest_paths: ShortestPathsAlgorithm + def __init__(self, bfs: _Optional[_Union[BfsAlgorithm, _Mapping]] = ..., parameterless: _Optional[_Union[ParameterlessAlgorithm, str]] = ..., betweenness: _Optional[_Union[BetweennessAlgorithm, _Mapping]] = ..., closeness: _Optional[_Union[ClosenessAlgorithm, _Mapping]] = ..., leiden: _Optional[_Union[LeidenAlgorithm, _Mapping]] = ..., shortest_paths: _Optional[_Union[ShortestPathsAlgorithm, _Mapping]] = ...) -> None: ... + +class NodePage(_message.Message): + __slots__ = () + VALUES_FIELD_NUMBER: _ClassVar[int] + values: _containers.RepeatedCompositeFieldContainer[Node] + def __init__(self, values: _Optional[_Iterable[_Union[Node, _Mapping]]] = ...) -> None: ... + +class RelationshipPage(_message.Message): + __slots__ = () + VALUES_FIELD_NUMBER: _ClassVar[int] + values: _containers.RepeatedCompositeFieldContainer[Relationship] + def __init__(self, values: _Optional[_Iterable[_Union[Relationship, _Mapping]]] = ...) -> None: ... + +class ComponentMembership(_message.Message): + __slots__ = () + NODE_ID_FIELD_NUMBER: _ClassVar[int] + COMPONENT_ID_FIELD_NUMBER: _ClassVar[int] + node_id: str + component_id: int + def __init__(self, node_id: _Optional[str] = ..., component_id: _Optional[int] = ...) -> None: ... + +class ComponentMembershipPage(_message.Message): + __slots__ = () + VALUES_FIELD_NUMBER: _ClassVar[int] + values: _containers.RepeatedCompositeFieldContainer[ComponentMembership] + def __init__(self, values: _Optional[_Iterable[_Union[ComponentMembership, _Mapping]]] = ...) -> None: ... + +class NodeScore(_message.Message): + __slots__ = () + NODE_ID_FIELD_NUMBER: _ClassVar[int] + METRIC_FIELD_NUMBER: _ClassVar[int] + SCORE_FIELD_NUMBER: _ClassVar[int] + node_id: str + metric: str + score: float + def __init__(self, node_id: _Optional[str] = ..., metric: _Optional[str] = ..., score: _Optional[float] = ...) -> None: ... + +class NodeScorePage(_message.Message): + __slots__ = () + VALUES_FIELD_NUMBER: _ClassVar[int] + values: _containers.RepeatedCompositeFieldContainer[NodeScore] + def __init__(self, values: _Optional[_Iterable[_Union[NodeScore, _Mapping]]] = ...) -> None: ... + +class NodePair(_message.Message): + __slots__ = () + SOURCE_ID_FIELD_NUMBER: _ClassVar[int] + TARGET_ID_FIELD_NUMBER: _ClassVar[int] + source_id: str + target_id: str + def __init__(self, source_id: _Optional[str] = ..., target_id: _Optional[str] = ...) -> None: ... + +class NodePairPage(_message.Message): + __slots__ = () + VALUES_FIELD_NUMBER: _ClassVar[int] + values: _containers.RepeatedCompositeFieldContainer[NodePair] + def __init__(self, values: _Optional[_Iterable[_Union[NodePair, _Mapping]]] = ...) -> None: ... + +class NodeCycle(_message.Message): + __slots__ = () + NODE_IDS_FIELD_NUMBER: _ClassVar[int] + node_ids: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, node_ids: _Optional[_Iterable[str]] = ...) -> None: ... + +class CyclePage(_message.Message): + __slots__ = () + VALUES_FIELD_NUMBER: _ClassVar[int] + values: _containers.RepeatedCompositeFieldContainer[NodeCycle] + def __init__(self, values: _Optional[_Iterable[_Union[NodeCycle, _Mapping]]] = ...) -> None: ... + +class NodePath(_message.Message): + __slots__ = () + NODE_IDS_FIELD_NUMBER: _ClassVar[int] + node_ids: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, node_ids: _Optional[_Iterable[str]] = ...) -> None: ... + +class PathPage(_message.Message): + __slots__ = () + VALUES_FIELD_NUMBER: _ClassVar[int] + values: _containers.RepeatedCompositeFieldContainer[NodePath] + def __init__(self, values: _Optional[_Iterable[_Union[NodePath, _Mapping]]] = ...) -> None: ... + +class CommunityMembership(_message.Message): + __slots__ = () + NODE_ID_FIELD_NUMBER: _ClassVar[int] + COMMUNITY_ID_FIELD_NUMBER: _ClassVar[int] + node_id: str + community_id: int + def __init__(self, node_id: _Optional[str] = ..., community_id: _Optional[int] = ...) -> None: ... + +class CommunityMembershipPage(_message.Message): + __slots__ = () + VALUES_FIELD_NUMBER: _ClassVar[int] + values: _containers.RepeatedCompositeFieldContainer[CommunityMembership] + def __init__(self, values: _Optional[_Iterable[_Union[CommunityMembership, _Mapping]]] = ...) -> None: ... + +class QuerySummary(_message.Message): + __slots__ = () + class NodesByTypeEntry(_message.Message): + __slots__ = () + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: int + def __init__(self, key: _Optional[str] = ..., value: _Optional[int] = ...) -> None: ... + NODES_BY_TYPE_FIELD_NUMBER: _ClassVar[int] + nodes_by_type: _containers.ScalarMap[str, int] + def __init__(self, nodes_by_type: _Optional[_Mapping[str, int]] = ...) -> None: ... + +class TraversalSummary(_message.Message): + __slots__ = () + ALGORITHM_FIELD_NUMBER: _ClassVar[int] + DIRECTION_FIELD_NUMBER: _ClassVar[int] + TRUNCATED_FIELD_NUMBER: _ClassVar[int] + PROJECTION_FIELD_NUMBER: _ClassVar[int] + algorithm: str + direction: Direction + truncated: bool + projection: str + def __init__(self, algorithm: _Optional[str] = ..., direction: _Optional[_Union[Direction, str]] = ..., truncated: _Optional[bool] = ..., projection: _Optional[str] = ...) -> None: ... + +class ComponentSummary(_message.Message): + __slots__ = () + ALGORITHM_FIELD_NUMBER: _ClassVar[int] + COMPONENT_COUNT_FIELD_NUMBER: _ClassVar[int] + PROJECTION_FIELD_NUMBER: _ClassVar[int] + algorithm: str + component_count: int + projection: str + def __init__(self, algorithm: _Optional[str] = ..., component_count: _Optional[int] = ..., projection: _Optional[str] = ...) -> None: ... + +class ScoreSummary(_message.Message): + __slots__ = () + METRIC_FIELD_NUMBER: _ClassVar[int] + INCLUDE_ENDPOINTS_FIELD_NUMBER: _ClassVar[int] + NORMALIZED_FIELD_NUMBER: _ClassVar[int] + WF_IMPROVED_FIELD_NUMBER: _ClassVar[int] + TOP_K_FIELD_NUMBER: _ClassVar[int] + PROJECTION_FIELD_NUMBER: _ClassVar[int] + metric: str + include_endpoints: bool + normalized: bool + wf_improved: bool + top_k: int + projection: str + def __init__(self, metric: _Optional[str] = ..., include_endpoints: _Optional[bool] = ..., normalized: _Optional[bool] = ..., wf_improved: _Optional[bool] = ..., top_k: _Optional[int] = ..., projection: _Optional[str] = ...) -> None: ... + +class CommunitySummary(_message.Message): + __slots__ = () + class CommunitySizesEntry(_message.Message): + __slots__ = () + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: int + value: int + def __init__(self, key: _Optional[int] = ..., value: _Optional[int] = ...) -> None: ... + NUM_COMMUNITIES_FIELD_NUMBER: _ClassVar[int] + TOTAL_COMMUNITIES_FIELD_NUMBER: _ClassVar[int] + COMMUNITIES_TRUNCATED_FIELD_NUMBER: _ClassVar[int] + MODULARITY_FIELD_NUMBER: _ClassVar[int] + RESOLUTION_FIELD_NUMBER: _ClassVar[int] + MIN_COMMUNITY_SIZE_FIELD_NUMBER: _ClassVar[int] + TOP_K_FIELD_NUMBER: _ClassVar[int] + COMMUNITY_SIZES_FIELD_NUMBER: _ClassVar[int] + PROJECTION_FIELD_NUMBER: _ClassVar[int] + ALGORITHM_FIELD_NUMBER: _ClassVar[int] + num_communities: int + total_communities: int + communities_truncated: bool + modularity: float + resolution: float + min_community_size: int + top_k: int + community_sizes: _containers.ScalarMap[int, int] + projection: str + algorithm: str + def __init__(self, num_communities: _Optional[int] = ..., total_communities: _Optional[int] = ..., communities_truncated: _Optional[bool] = ..., modularity: _Optional[float] = ..., resolution: _Optional[float] = ..., min_community_size: _Optional[int] = ..., top_k: _Optional[int] = ..., community_sizes: _Optional[_Mapping[int, int]] = ..., projection: _Optional[str] = ..., algorithm: _Optional[str] = ...) -> None: ... + +class PathSummary(_message.Message): + __slots__ = () + ALGORITHM_FIELD_NUMBER: _ClassVar[int] + START_ID_FIELD_NUMBER: _ClassVar[int] + END_ID_FIELD_NUMBER: _ClassVar[int] + DIRECTION_FIELD_NUMBER: _ClassVar[int] + MAX_DEPTH_FIELD_NUMBER: _ClassVar[int] + LIMIT_FIELD_NUMBER: _ClassVar[int] + algorithm: str + start_id: str + end_id: str + direction: Direction + max_depth: int + limit: int + def __init__(self, algorithm: _Optional[str] = ..., start_id: _Optional[str] = ..., end_id: _Optional[str] = ..., direction: _Optional[_Union[Direction, str]] = ..., max_depth: _Optional[int] = ..., limit: _Optional[int] = ...) -> None: ... + +class GraphResultPage(_message.Message): + __slots__ = () + PAGE_FIELD_NUMBER: _ClassVar[int] + LIMIT_FIELD_NUMBER: _ClassVar[int] + HAS_NEXT_FIELD_NUMBER: _ClassVar[int] + TOTAL_FIELD_NUMBER: _ClassVar[int] + NODES_FIELD_NUMBER: _ClassVar[int] + RELATIONSHIPS_FIELD_NUMBER: _ClassVar[int] + COMPONENTS_FIELD_NUMBER: _ClassVar[int] + SCORES_FIELD_NUMBER: _ClassVar[int] + PAIRS_FIELD_NUMBER: _ClassVar[int] + CYCLES_FIELD_NUMBER: _ClassVar[int] + PATHS_FIELD_NUMBER: _ClassVar[int] + COMMUNITIES_FIELD_NUMBER: _ClassVar[int] + QUERY_FIELD_NUMBER: _ClassVar[int] + TRAVERSAL_FIELD_NUMBER: _ClassVar[int] + COMPONENT_FIELD_NUMBER: _ClassVar[int] + SCORE_FIELD_NUMBER: _ClassVar[int] + COMMUNITY_FIELD_NUMBER: _ClassVar[int] + PATH_FIELD_NUMBER: _ClassVar[int] + page: int + limit: int + has_next: bool + total: int + nodes: NodePage + relationships: RelationshipPage + components: ComponentMembershipPage + scores: NodeScorePage + pairs: NodePairPage + cycles: CyclePage + paths: PathPage + communities: CommunityMembershipPage + query: QuerySummary + traversal: TraversalSummary + component: ComponentSummary + score: ScoreSummary + community: CommunitySummary + path: PathSummary + def __init__(self, page: _Optional[int] = ..., limit: _Optional[int] = ..., has_next: _Optional[bool] = ..., total: _Optional[int] = ..., nodes: _Optional[_Union[NodePage, _Mapping]] = ..., relationships: _Optional[_Union[RelationshipPage, _Mapping]] = ..., components: _Optional[_Union[ComponentMembershipPage, _Mapping]] = ..., scores: _Optional[_Union[NodeScorePage, _Mapping]] = ..., pairs: _Optional[_Union[NodePairPage, _Mapping]] = ..., cycles: _Optional[_Union[CyclePage, _Mapping]] = ..., paths: _Optional[_Union[PathPage, _Mapping]] = ..., communities: _Optional[_Union[CommunityMembershipPage, _Mapping]] = ..., query: _Optional[_Union[QuerySummary, _Mapping]] = ..., traversal: _Optional[_Union[TraversalSummary, _Mapping]] = ..., component: _Optional[_Union[ComponentSummary, _Mapping]] = ..., score: _Optional[_Union[ScoreSummary, _Mapping]] = ..., community: _Optional[_Union[CommunitySummary, _Mapping]] = ..., path: _Optional[_Union[PathSummary, _Mapping]] = ...) -> None: ... + +class ParserPayload(_message.Message): + __slots__ = () + PLUGIN_FIELD_NUMBER: _ClassVar[int] + ARTIFACT_FIELD_NUMBER: _ClassVar[int] + DATA_FIELD_NUMBER: _ClassVar[int] + CONTENT_TYPE_FIELD_NUMBER: _ClassVar[int] + plugin: str + artifact: str + data: bytes + content_type: str + def __init__(self, plugin: _Optional[str] = ..., artifact: _Optional[str] = ..., data: _Optional[bytes] = ..., content_type: _Optional[str] = ...) -> None: ... + +class GraphIngestResult(_message.Message): + __slots__ = () + class NodesByTypeEntry(_message.Message): + __slots__ = () + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: int + def __init__(self, key: _Optional[str] = ..., value: _Optional[int] = ...) -> None: ... + RECORDS_PARSED_FIELD_NUMBER: _ClassVar[int] + NEW_NODES_FIELD_NUMBER: _ClassVar[int] + UPDATED_NODES_FIELD_NUMBER: _ClassVar[int] + NEW_RELATIONSHIPS_FIELD_NUMBER: _ClassVar[int] + NODE_IDS_FIELD_NUMBER: _ClassVar[int] + NODE_COUNT_FIELD_NUMBER: _ClassVar[int] + RELATIONSHIP_COUNT_FIELD_NUMBER: _ClassVar[int] + NODES_BY_TYPE_FIELD_NUMBER: _ClassVar[int] + records_parsed: int + new_nodes: int + updated_nodes: int + new_relationships: int + node_ids: _containers.RepeatedScalarFieldContainer[str] + node_count: int + relationship_count: int + nodes_by_type: _containers.ScalarMap[str, int] + def __init__(self, records_parsed: _Optional[int] = ..., new_nodes: _Optional[int] = ..., updated_nodes: _Optional[int] = ..., new_relationships: _Optional[int] = ..., node_ids: _Optional[_Iterable[str]] = ..., node_count: _Optional[int] = ..., relationship_count: _Optional[int] = ..., nodes_by_type: _Optional[_Mapping[str, int]] = ...) -> None: ... + +class GraphLinkResult(_message.Message): + __slots__ = () + NEW_NODES_FIELD_NUMBER: _ClassVar[int] + UPDATED_NODES_FIELD_NUMBER: _ClassVar[int] + NEW_RELATIONSHIPS_FIELD_NUMBER: _ClassVar[int] + RELATIONSHIP_IDS_FIELD_NUMBER: _ClassVar[int] + new_nodes: int + updated_nodes: int + new_relationships: int + relationship_ids: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, new_nodes: _Optional[int] = ..., updated_nodes: _Optional[int] = ..., new_relationships: _Optional[int] = ..., relationship_ids: _Optional[_Iterable[str]] = ...) -> None: ... + +class GraphAnchor(_message.Message): + __slots__ = () + CONCEPT_FIELD_NUMBER: _ClassVar[int] + ANCHOR_ID_FIELD_NUMBER: _ClassVar[int] + ANCHOR_TYPE_FIELD_NUMBER: _ClassVar[int] + SOURCE_ID_FIELD_NUMBER: _ClassVar[int] + TARGET_ID_FIELD_NUMBER: _ClassVar[int] + INBOUND_RELATIONSHIP_ID_FIELD_NUMBER: _ClassVar[int] + OUTBOUND_RELATIONSHIP_ID_FIELD_NUMBER: _ClassVar[int] + concept: str + anchor_id: str + anchor_type: str + source_id: str + target_id: str + inbound_relationship_id: str + outbound_relationship_id: str + def __init__(self, concept: _Optional[str] = ..., anchor_id: _Optional[str] = ..., anchor_type: _Optional[str] = ..., source_id: _Optional[str] = ..., target_id: _Optional[str] = ..., inbound_relationship_id: _Optional[str] = ..., outbound_relationship_id: _Optional[str] = ...) -> None: ... + +class GraphAnchorCatalog(_message.Message): + __slots__ = () + ANCHORS_FIELD_NUMBER: _ClassVar[int] + anchors: _containers.RepeatedCompositeFieldContainer[GraphAnchor] + def __init__(self, anchors: _Optional[_Iterable[_Union[GraphAnchor, _Mapping]]] = ...) -> None: ... + +class NodeFlagUpdate(_message.Message): + __slots__ = () + MODE_FIELD_NUMBER: _ClassVar[int] + ADD_MASK_FIELD_NUMBER: _ClassVar[int] + REMOVE_MASK_FIELD_NUMBER: _ClassVar[int] + REPLACE_MASK_FIELD_NUMBER: _ClassVar[int] + mode: NodeFlagUpdateMode + add_mask: int + remove_mask: int + replace_mask: int + def __init__(self, mode: _Optional[_Union[NodeFlagUpdateMode, str]] = ..., add_mask: _Optional[int] = ..., remove_mask: _Optional[int] = ..., replace_mask: _Optional[int] = ...) -> None: ... + +class GraphProjectionReport(_message.Message): + __slots__ = () + class NodeExclusion(_message.Message): + __slots__ = () + NODE_ID_FIELD_NUMBER: _ClassVar[int] + REASON_FIELD_NUMBER: _ClassVar[int] + node_id: str + reason: str + def __init__(self, node_id: _Optional[str] = ..., reason: _Optional[str] = ...) -> None: ... + EXCLUDED_NODES_FIELD_NUMBER: _ClassVar[int] + REUSED_FIELD_NUMBER: _ClassVar[int] + excluded_nodes: _containers.RepeatedCompositeFieldContainer[GraphProjectionReport.NodeExclusion] + reused: bool + def __init__(self, excluded_nodes: _Optional[_Iterable[_Union[GraphProjectionReport.NodeExclusion, _Mapping]]] = ..., reused: _Optional[bool] = ...) -> None: ... + +class RepositoryObject(_message.Message): + __slots__ = () + ID_FIELD_NUMBER: _ClassVar[int] + KIND_FIELD_NUMBER: _ClassVar[int] + PAYLOAD_FIELD_NUMBER: _ClassVar[int] + id: str + kind: RepositoryObjectKind + payload: bytes + def __init__(self, id: _Optional[str] = ..., kind: _Optional[_Union[RepositoryObjectKind, str]] = ..., payload: _Optional[bytes] = ...) -> None: ... + +class PublicationPlan(_message.Message): + __slots__ = () + COMMIT_FIELD_NUMBER: _ClassVar[int] + INDEX_ROOT_FIELD_NUMBER: _ClassVar[int] + OBJECTS_FIELD_NUMBER: _ClassVar[int] + commit: Commit + index_root: str + objects: _containers.RepeatedCompositeFieldContainer[RepositoryObject] + def __init__(self, commit: _Optional[_Union[Commit, _Mapping]] = ..., index_root: _Optional[str] = ..., objects: _Optional[_Iterable[_Union[RepositoryObject, _Mapping]]] = ...) -> None: ... + +class RepositoryState(_message.Message): + __slots__ = () + class Object(_message.Message): + __slots__ = () + ID_FIELD_NUMBER: _ClassVar[int] + PAYLOAD_FIELD_NUMBER: _ClassVar[int] + id: str + payload: bytes + def __init__(self, id: _Optional[str] = ..., payload: _Optional[bytes] = ...) -> None: ... + class Ref(_message.Message): + __slots__ = () + NAME_FIELD_NUMBER: _ClassVar[int] + COMMIT_ID_FIELD_NUMBER: _ClassVar[int] + name: str + commit_id: str + def __init__(self, name: _Optional[str] = ..., commit_id: _Optional[str] = ...) -> None: ... + class Index(_message.Message): + __slots__ = () + COMMIT_ID_FIELD_NUMBER: _ClassVar[int] + INDEX_ROOT_FIELD_NUMBER: _ClassVar[int] + commit_id: str + index_root: str + def __init__(self, commit_id: _Optional[str] = ..., index_root: _Optional[str] = ...) -> None: ... + OBJECTS_FIELD_NUMBER: _ClassVar[int] + REFS_FIELD_NUMBER: _ClassVar[int] + INDEXES_FIELD_NUMBER: _ClassVar[int] + objects: _containers.RepeatedCompositeFieldContainer[RepositoryState.Object] + refs: _containers.RepeatedCompositeFieldContainer[RepositoryState.Ref] + indexes: _containers.RepeatedCompositeFieldContainer[RepositoryState.Index] + def __init__(self, objects: _Optional[_Iterable[_Union[RepositoryState.Object, _Mapping]]] = ..., refs: _Optional[_Iterable[_Union[RepositoryState.Ref, _Mapping]]] = ..., indexes: _Optional[_Iterable[_Union[RepositoryState.Index, _Mapping]]] = ...) -> None: ... + +class ObjectSelection(_message.Message): + __slots__ = () + OBJECT_IDS_FIELD_NUMBER: _ClassVar[int] + object_ids: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, object_ids: _Optional[_Iterable[str]] = ...) -> None: ... + +class RepositoryObjectPlan(_message.Message): + __slots__ = () + KIND_FIELD_NUMBER: _ClassVar[int] + COMMIT_ID_FIELD_NUMBER: _ClassVar[int] + LIMIT_FIELD_NUMBER: _ClassVar[int] + START_TIMESTAMP_FIELD_NUMBER: _ClassVar[int] + END_TIMESTAMP_FIELD_NUMBER: _ClassVar[int] + ENTITY_ID_FIELD_NUMBER: _ClassVar[int] + SOURCE_ID_FIELD_NUMBER: _ClassVar[int] + TARGET_ID_FIELD_NUMBER: _ClassVar[int] + DETAIL_FIELD_NUMBER: _ClassVar[int] + ENTITY_IDS_FIELD_NUMBER: _ClassVar[int] + kind: RepositoryPlanKind + commit_id: str + limit: int + start_timestamp: int + end_timestamp: int + entity_id: str + source_id: str + target_id: str + detail: DiffDetail + entity_ids: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, kind: _Optional[_Union[RepositoryPlanKind, str]] = ..., commit_id: _Optional[str] = ..., limit: _Optional[int] = ..., start_timestamp: _Optional[int] = ..., end_timestamp: _Optional[int] = ..., entity_id: _Optional[str] = ..., source_id: _Optional[str] = ..., target_id: _Optional[str] = ..., detail: _Optional[_Union[DiffDetail, str]] = ..., entity_ids: _Optional[_Iterable[str]] = ...) -> None: ... + +class RagFilter(_message.Message): + __slots__ = () + NODE_TYPES_FIELD_NUMBER: _ClassVar[int] + RELATIONSHIP_TYPES_FIELD_NUMBER: _ClassVar[int] + EXCLUDE_FLAGS_MASK_FIELD_NUMBER: _ClassVar[int] + INCLUDE_FLAGS_MASK_FIELD_NUMBER: _ClassVar[int] + node_types: _containers.RepeatedScalarFieldContainer[str] + relationship_types: _containers.RepeatedScalarFieldContainer[str] + exclude_flags_mask: int + include_flags_mask: int + def __init__(self, node_types: _Optional[_Iterable[str]] = ..., relationship_types: _Optional[_Iterable[str]] = ..., exclude_flags_mask: _Optional[int] = ..., include_flags_mask: _Optional[int] = ...) -> None: ... + +class RagGraphChanges(_message.Message): + __slots__ = () + CHANGED_NODE_IDS_FIELD_NUMBER: _ClassVar[int] + DELETED_NODE_IDS_FIELD_NUMBER: _ClassVar[int] + CHANGED_RELATIONSHIP_IDS_FIELD_NUMBER: _ClassVar[int] + DELETED_RELATIONSHIP_IDS_FIELD_NUMBER: _ClassVar[int] + changed_node_ids: _containers.RepeatedScalarFieldContainer[str] + deleted_node_ids: _containers.RepeatedScalarFieldContainer[str] + changed_relationship_ids: _containers.RepeatedScalarFieldContainer[str] + deleted_relationship_ids: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, changed_node_ids: _Optional[_Iterable[str]] = ..., deleted_node_ids: _Optional[_Iterable[str]] = ..., changed_relationship_ids: _Optional[_Iterable[str]] = ..., deleted_relationship_ids: _Optional[_Iterable[str]] = ...) -> None: ... + +class RagRecord(_message.Message): + __slots__ = () + ID_FIELD_NUMBER: _ClassVar[int] + KIND_FIELD_NUMBER: _ClassVar[int] + TEXT_FIELD_NUMBER: _ClassVar[int] + CONTENT_HASH_FIELD_NUMBER: _ClassVar[int] + NODE_IDS_FIELD_NUMBER: _ClassVar[int] + RELATIONSHIP_IDS_FIELD_NUMBER: _ClassVar[int] + NODE_TYPE_FIELD_NUMBER: _ClassVar[int] + RELATIONSHIP_TYPE_FIELD_NUMBER: _ClassVar[int] + id: str + kind: RagRecordKind + text: str + content_hash: str + node_ids: _containers.RepeatedScalarFieldContainer[str] + relationship_ids: _containers.RepeatedScalarFieldContainer[str] + node_type: str + relationship_type: str + def __init__(self, id: _Optional[str] = ..., kind: _Optional[_Union[RagRecordKind, str]] = ..., text: _Optional[str] = ..., content_hash: _Optional[str] = ..., node_ids: _Optional[_Iterable[str]] = ..., relationship_ids: _Optional[_Iterable[str]] = ..., node_type: _Optional[str] = ..., relationship_type: _Optional[str] = ...) -> None: ... + +class RagIndexResult(_message.Message): + __slots__ = () + OPERATION_ID_FIELD_NUMBER: _ClassVar[int] + COMMIT_FIELD_NUMBER: _ClassVar[int] + MODE_FIELD_NUMBER: _ClassVar[int] + UPSERT_COUNT_FIELD_NUMBER: _ClassVar[int] + DELETE_COUNT_FIELD_NUMBER: _ClassVar[int] + operation_id: str + commit: str + mode: RagIndexMode + upsert_count: int + delete_count: int + def __init__(self, operation_id: _Optional[str] = ..., commit: _Optional[str] = ..., mode: _Optional[_Union[RagIndexMode, str]] = ..., upsert_count: _Optional[int] = ..., delete_count: _Optional[int] = ...) -> None: ... + +class RagIndexPlan(_message.Message): + __slots__ = () + COMMIT_FIELD_NUMBER: _ClassVar[int] + MODE_FIELD_NUMBER: _ClassVar[int] + CHANGES_FIELD_NUMBER: _ClassVar[int] + commit: str + mode: RagIndexMode + changes: RagGraphChanges + def __init__(self, commit: _Optional[str] = ..., mode: _Optional[_Union[RagIndexMode, str]] = ..., changes: _Optional[_Union[RagGraphChanges, _Mapping]] = ...) -> None: ... + +class RagRecordPage(_message.Message): + __slots__ = () + RECORDS_FIELD_NUMBER: _ClassVar[int] + PAGE_FIELD_NUMBER: _ClassVar[int] + LIMIT_FIELD_NUMBER: _ClassVar[int] + HAS_NEXT_FIELD_NUMBER: _ClassVar[int] + records: _containers.RepeatedCompositeFieldContainer[RagRecord] + page: int + limit: int + has_next: bool + def __init__(self, records: _Optional[_Iterable[_Union[RagRecord, _Mapping]]] = ..., page: _Optional[int] = ..., limit: _Optional[int] = ..., has_next: _Optional[bool] = ...) -> None: ... + +class RecallQuery(_message.Message): + __slots__ = () + ID_FIELD_NUMBER: _ClassVar[int] + TEXT_FIELD_NUMBER: _ClassVar[int] + KIND_FIELD_NUMBER: _ClassVar[int] + LIMIT_FIELD_NUMBER: _ClassVar[int] + FILTER_FIELD_NUMBER: _ClassVar[int] + id: str + text: str + kind: RagRecordKind + limit: int + filter: RagFilter + def __init__(self, id: _Optional[str] = ..., text: _Optional[str] = ..., kind: _Optional[_Union[RagRecordKind, str]] = ..., limit: _Optional[int] = ..., filter: _Optional[_Union[RagFilter, _Mapping]] = ...) -> None: ... + +class RecallHit(_message.Message): + __slots__ = () + RECORD_ID_FIELD_NUMBER: _ClassVar[int] + RANK_FIELD_NUMBER: _ClassVar[int] + SCORE_FIELD_NUMBER: _ClassVar[int] + record_id: str + rank: int + score: float + def __init__(self, record_id: _Optional[str] = ..., rank: _Optional[int] = ..., score: _Optional[float] = ...) -> None: ... + +class ExtensionRecallResult(_message.Message): + __slots__ = () + QUERY_ID_FIELD_NUMBER: _ClassVar[int] + EXTENSION_FIELD_NUMBER: _ClassVar[int] + HITS_FIELD_NUMBER: _ClassVar[int] + query_id: str + extension: str + hits: _containers.RepeatedCompositeFieldContainer[RecallHit] + def __init__(self, query_id: _Optional[str] = ..., extension: _Optional[str] = ..., hits: _Optional[_Iterable[_Union[RecallHit, _Mapping]]] = ...) -> None: ... + +class RecallResults(_message.Message): + __slots__ = () + RESULTS_FIELD_NUMBER: _ClassVar[int] + results: _containers.RepeatedCompositeFieldContainer[ExtensionRecallResult] + def __init__(self, results: _Optional[_Iterable[_Union[ExtensionRecallResult, _Mapping]]] = ...) -> None: ... + +class RecallPlan(_message.Message): + __slots__ = () + QUERIES_FIELD_NUMBER: _ClassVar[int] + queries: _containers.RepeatedCompositeFieldContainer[RecallQuery] + def __init__(self, queries: _Optional[_Iterable[_Union[RecallQuery, _Mapping]]] = ...) -> None: ... + +class RagPolicy(_message.Message): + __slots__ = () + RRF_K_FIELD_NUMBER: _ClassVar[int] + CANDIDATE_MULTIPLIER_FIELD_NUMBER: _ClassVar[int] + DAMPING_FIELD_NUMBER: _ClassVar[int] + PROPAGATION_ITERATIONS_FIELD_NUMBER: _ClassVar[int] + MAX_PATH_DEPTH_FIELD_NUMBER: _ClassVar[int] + EPSILON_FIELD_NUMBER: _ClassVar[int] + COMMUNITIES_FIELD_NUMBER: _ClassVar[int] + USE_LEXICAL_FIELD_NUMBER: _ClassVar[int] + rrf_k: float + candidate_multiplier: int + damping: float + propagation_iterations: int + max_path_depth: int + epsilon: float + communities: bool + use_lexical: bool + def __init__(self, rrf_k: _Optional[float] = ..., candidate_multiplier: _Optional[int] = ..., damping: _Optional[float] = ..., propagation_iterations: _Optional[int] = ..., max_path_depth: _Optional[int] = ..., epsilon: _Optional[float] = ..., communities: _Optional[bool] = ..., use_lexical: _Optional[bool] = ...) -> None: ... + +class RagQuery(_message.Message): + __slots__ = () + TEXT_FIELD_NUMBER: _ClassVar[int] + LIMIT_FIELD_NUMBER: _ClassVar[int] + FILTER_FIELD_NUMBER: _ClassVar[int] + POLICY_FIELD_NUMBER: _ClassVar[int] + CONTEXT_BUDGET_FIELD_NUMBER: _ClassVar[int] + text: str + limit: int + filter: RagFilter + policy: RagPolicy + context_budget: int + def __init__(self, text: _Optional[str] = ..., limit: _Optional[int] = ..., filter: _Optional[_Union[RagFilter, _Mapping]] = ..., policy: _Optional[_Union[RagPolicy, _Mapping]] = ..., context_budget: _Optional[int] = ...) -> None: ... + +class RankedNode(_message.Message): + __slots__ = () + NODE_ID_FIELD_NUMBER: _ClassVar[int] + SCORE_FIELD_NUMBER: _ClassVar[int] + DIRECT_FIELD_NUMBER: _ClassVar[int] + PROVENANCE_FIELD_NUMBER: _ClassVar[int] + node_id: str + score: float + direct: bool + provenance: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, node_id: _Optional[str] = ..., score: _Optional[float] = ..., direct: _Optional[bool] = ..., provenance: _Optional[_Iterable[str]] = ...) -> None: ... + +class RankedRelationship(_message.Message): + __slots__ = () + RELATIONSHIP_ID_FIELD_NUMBER: _ClassVar[int] + SCORE_FIELD_NUMBER: _ClassVar[int] + DIRECT_FIELD_NUMBER: _ClassVar[int] + PROVENANCE_FIELD_NUMBER: _ClassVar[int] + relationship_id: str + score: float + direct: bool + provenance: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, relationship_id: _Optional[str] = ..., score: _Optional[float] = ..., direct: _Optional[bool] = ..., provenance: _Optional[_Iterable[str]] = ...) -> None: ... + +class RagPath(_message.Message): + __slots__ = () + NODE_IDS_FIELD_NUMBER: _ClassVar[int] + RELATIONSHIP_IDS_FIELD_NUMBER: _ClassVar[int] + SCORE_FIELD_NUMBER: _ClassVar[int] + node_ids: _containers.RepeatedScalarFieldContainer[str] + relationship_ids: _containers.RepeatedScalarFieldContainer[str] + score: float + def __init__(self, node_ids: _Optional[_Iterable[str]] = ..., relationship_ids: _Optional[_Iterable[str]] = ..., score: _Optional[float] = ...) -> None: ... + +class RagCommunityHit(_message.Message): + __slots__ = () + ID_FIELD_NUMBER: _ClassVar[int] + LEVEL_FIELD_NUMBER: _ClassVar[int] + MEMBER_NODE_IDS_FIELD_NUMBER: _ClassVar[int] + SCORE_FIELD_NUMBER: _ClassVar[int] + id: str + level: int + member_node_ids: _containers.RepeatedScalarFieldContainer[str] + score: float + def __init__(self, id: _Optional[str] = ..., level: _Optional[int] = ..., member_node_ids: _Optional[_Iterable[str]] = ..., score: _Optional[float] = ...) -> None: ... + +class RagContextBlock(_message.Message): + __slots__ = () + TEXT_FIELD_NUMBER: _ClassVar[int] + RECORD_IDS_FIELD_NUMBER: _ClassVar[int] + ESTIMATED_TOKENS_FIELD_NUMBER: _ClassVar[int] + text: str + record_ids: _containers.RepeatedScalarFieldContainer[str] + estimated_tokens: int + def __init__(self, text: _Optional[str] = ..., record_ids: _Optional[_Iterable[str]] = ..., estimated_tokens: _Optional[int] = ...) -> None: ... + +class EvidenceProvenance(_message.Message): + __slots__ = () + RESULT_ID_FIELD_NUMBER: _ClassVar[int] + RECORD_IDS_FIELD_NUMBER: _ClassVar[int] + result_id: str + record_ids: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, result_id: _Optional[str] = ..., record_ids: _Optional[_Iterable[str]] = ...) -> None: ... + +class RagResult(_message.Message): + __slots__ = () + COMMIT_FIELD_NUMBER: _ClassVar[int] + NODES_FIELD_NUMBER: _ClassVar[int] + RELATIONSHIPS_FIELD_NUMBER: _ClassVar[int] + PATHS_FIELD_NUMBER: _ClassVar[int] + COMMUNITIES_FIELD_NUMBER: _ClassVar[int] + CONTEXT_FIELD_NUMBER: _ClassVar[int] + PROVENANCE_FIELD_NUMBER: _ClassVar[int] + DROPPED_RECORDS_FIELD_NUMBER: _ClassVar[int] + EXTENSIONS_FIELD_NUMBER: _ClassVar[int] + commit: str + nodes: _containers.RepeatedCompositeFieldContainer[RankedNode] + relationships: _containers.RepeatedCompositeFieldContainer[RankedRelationship] + paths: _containers.RepeatedCompositeFieldContainer[RagPath] + communities: _containers.RepeatedCompositeFieldContainer[RagCommunityHit] + context: _containers.RepeatedCompositeFieldContainer[RagContextBlock] + provenance: _containers.RepeatedCompositeFieldContainer[EvidenceProvenance] + dropped_records: _containers.RepeatedScalarFieldContainer[str] + extensions: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, commit: _Optional[str] = ..., nodes: _Optional[_Iterable[_Union[RankedNode, _Mapping]]] = ..., relationships: _Optional[_Iterable[_Union[RankedRelationship, _Mapping]]] = ..., paths: _Optional[_Iterable[_Union[RagPath, _Mapping]]] = ..., communities: _Optional[_Iterable[_Union[RagCommunityHit, _Mapping]]] = ..., context: _Optional[_Iterable[_Union[RagContextBlock, _Mapping]]] = ..., provenance: _Optional[_Iterable[_Union[EvidenceProvenance, _Mapping]]] = ..., dropped_records: _Optional[_Iterable[str]] = ..., extensions: _Optional[_Iterable[str]] = ...) -> None: ... + +class ExtensionContract(_message.Message): + __slots__ = () + class ExtensionsEntry(_message.Message): + __slots__ = () + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: ExtensionDefinition + def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[ExtensionDefinition, _Mapping]] = ...) -> None: ... + CONTRACT_VERSION_FIELD_NUMBER: _ClassVar[int] + EXTENSIONS_FIELD_NUMBER: _ClassVar[int] + contract_version: int + extensions: _containers.MessageMap[str, ExtensionDefinition] + def __init__(self, contract_version: _Optional[int] = ..., extensions: _Optional[_Mapping[str, ExtensionDefinition]] = ...) -> None: ... + +class ExtensionDefinition(_message.Message): + __slots__ = () + class ParsersEntry(_message.Message): + __slots__ = () + KEY_FIELD_NUMBER: _ClassVar[int] + VALUE_FIELD_NUMBER: _ClassVar[int] + key: str + value: ParserType + def __init__(self, key: _Optional[str] = ..., value: _Optional[_Union[ParserType, _Mapping]] = ...) -> None: ... + NAME_FIELD_NUMBER: _ClassVar[int] + VERSION_FIELD_NUMBER: _ClassVar[int] + PARSERS_FIELD_NUMBER: _ClassVar[int] + RULES_FIELD_NUMBER: _ClassVar[int] + SCHEMA_FIELD_NUMBER: _ClassVar[int] + name: str + version: str + parsers: _containers.MessageMap[str, ParserType] + rules: _containers.RepeatedCompositeFieldContainer[JoinRule] + schema: str + def __init__(self, name: _Optional[str] = ..., version: _Optional[str] = ..., parsers: _Optional[_Mapping[str, ParserType]] = ..., rules: _Optional[_Iterable[_Union[JoinRule, _Mapping]]] = ..., schema: _Optional[str] = ...) -> None: ... + +class NodeType(_message.Message): + __slots__ = () + TYPE_URL_FIELD_NUMBER: _ClassVar[int] + METADATA_FIELD_NUMBER: _ClassVar[int] + type_url: str + metadata: _struct_pb2.Struct + def __init__(self, type_url: _Optional[str] = ..., metadata: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ... + +class RelationshipType(_message.Message): + __slots__ = () + TYPE_URL_FIELD_NUMBER: _ClassVar[int] + METADATA_FIELD_NUMBER: _ClassVar[int] + type_url: str + metadata: _struct_pb2.Struct + def __init__(self, type_url: _Optional[str] = ..., metadata: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ... + +class ParserType(_message.Message): + __slots__ = () + ARTIFACT_FIELD_NUMBER: _ClassVar[int] + INPUT_SCHEMA_FIELD_NUMBER: _ClassVar[int] + METADATA_FIELD_NUMBER: _ClassVar[int] + artifact: str + input_schema: _struct_pb2.Struct + metadata: _struct_pb2.Struct + def __init__(self, artifact: _Optional[str] = ..., input_schema: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ..., metadata: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ... + +class JoinRule(_message.Message): + __slots__ = () + LEFT_TYPE_URL_FIELD_NUMBER: _ClassVar[int] + RIGHT_TYPE_URL_FIELD_NUMBER: _ClassVar[int] + RELATIONSHIP_TYPE_URL_FIELD_NUMBER: _ClassVar[int] + LEFT_KEY_FIELD_NUMBER: _ClassVar[int] + RIGHT_KEY_FIELD_NUMBER: _ClassVar[int] + PREDICTED_FIELD_NUMBER: _ClassVar[int] + LEFT_TARGET_ID_FIELD_NUMBER: _ClassVar[int] + RIGHT_SOURCE_ID_FIELD_NUMBER: _ClassVar[int] + left_type_url: str + right_type_url: str + relationship_type_url: str + left_key: str + right_key: str + predicted: bool + left_target_id: str + right_source_id: str + def __init__(self, left_type_url: _Optional[str] = ..., right_type_url: _Optional[str] = ..., relationship_type_url: _Optional[str] = ..., left_key: _Optional[str] = ..., right_key: _Optional[str] = ..., predicted: _Optional[bool] = ..., left_target_id: _Optional[str] = ..., right_source_id: _Optional[str] = ...) -> None: ... + +class ExtensionInfo(_message.Message): + __slots__ = () + NAME_FIELD_NUMBER: _ClassVar[int] + VERSION_FIELD_NUMBER: _ClassVar[int] + KIND_FIELD_NUMBER: _ClassVar[int] + ENABLED_FIELD_NUMBER: _ClassVar[int] + ARTIFACTS_FIELD_NUMBER: _ClassVar[int] + name: str + version: str + kind: str + enabled: bool + artifacts: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, name: _Optional[str] = ..., version: _Optional[str] = ..., kind: _Optional[str] = ..., enabled: _Optional[bool] = ..., artifacts: _Optional[_Iterable[str]] = ...) -> None: ... + +class ExtensionCatalog(_message.Message): + __slots__ = () + EXTENSIONS_FIELD_NUMBER: _ClassVar[int] + extensions: _containers.RepeatedCompositeFieldContainer[ExtensionInfo] + def __init__(self, extensions: _Optional[_Iterable[_Union[ExtensionInfo, _Mapping]]] = ...) -> None: ... + +class AnchorConcept(_message.Message): + __slots__ = () + NAME_FIELD_NUMBER: _ClassVar[int] + NODE_TYPES_FIELD_NUMBER: _ClassVar[int] + name: str + node_types: _containers.RepeatedScalarFieldContainer[str] + def __init__(self, name: _Optional[str] = ..., node_types: _Optional[_Iterable[str]] = ...) -> None: ... + +class AnchorConceptCatalog(_message.Message): + __slots__ = () + CONCEPTS_FIELD_NUMBER: _ClassVar[int] + concepts: _containers.RepeatedCompositeFieldContainer[AnchorConcept] + def __init__(self, concepts: _Optional[_Iterable[_Union[AnchorConcept, _Mapping]]] = ...) -> None: ... diff --git a/python/python/cstxpy/proto/py.typed b/python/python/cstxpy/proto/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/python/python/cstxpy/py.typed b/python/python/cstxpy/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/python/python/cstxpy/schema.py b/python/python/cstxpy/schema.py new file mode 100644 index 0000000..2d1424e --- /dev/null +++ b/python/python/cstxpy/schema.py @@ -0,0 +1,418 @@ +"""Runtime schema — the single structure contract shared by every extension. + +`make codegen` projects each ``.proto`` into one ``.schema.json`` +describing node types, their identity, their columns and the relation types +that connect them. That JSON is what this module loads. + +protobuf stays on the serialization boundary: nothing here needs ``protoc``, +a descriptor pool, or a per-extension generated lookup table. The built-in +EASM extension and a third-party one are loaded by the same two calls, so +neither is privileged. +""" + +from __future__ import annotations + +import json +from pathlib import Path +from typing import Any, Dict, Mapping, Optional, Tuple + +from pydantic import BaseModel, ConfigDict, Field + +__all__ = ( + "FieldSchema", + "NodeSchema", + "RelationSchema", + "FlagSchema", + "ExtensionSchema", + "registry", + "node_type_url", + "node_type_from_url", + "relation_type_url", + "relation_type_from_url", + "relation_types", +) + +TYPE_URL_PREFIX = "type.googleapis.com/" +_SCHEMA_DIR = Path(__file__).resolve().parent / "schemas" +_SUPPORTED_SCHEMA_VERSION = 1 + + +def _message_short_name(type_url: str) -> str: + """Bare message name from a type URL, a full name, or a short name.""" + return type_url.rsplit("/", 1)[-1].rsplit(".", 1)[-1] + + +class FieldSchema(BaseModel): + """One column, described exactly as the source ``.proto`` declared it.""" + + model_config = ConfigDict(frozen=True) + + name: str + number: int + type: str + repeated: bool = False + optional: bool = False + semantic: bool = True + semantic_label: str = "" + #: The field's value domain in order, lowest first; empty when it declares + #: none. Carried so a caller sees the same contract the runtime compares + #: by — the words belong to the extension, not to whoever reads them. + ordered_values: Tuple[str, ...] = () + #: The column this field lands in when the proto type does not imply it. + #: Only ``"json"``: text on the wire, a document in the column — a type's + #: declared bag for values it has no column for. + column: str = "" + + @classmethod + def parse(cls, data: Mapping[str, Any]) -> "FieldSchema": + name = str(data["name"]) + return cls( + name=name, + number=int(data["number"]), + type=str(data["type"]), + repeated=bool(data.get("repeated", False)), + optional=bool(data.get("optional", False)), + semantic=bool(data.get("semantic", True)), + semantic_label=str(data.get("semantic_label") or name), + ordered_values=tuple(str(value) for value in data.get("ordered_values", ())), + column=str(data.get("column") or ""), + ) + + +class NodeSchema(BaseModel): + """One node type: its message, identity contract and columns.""" + + model_config = ConfigDict(frozen=True) + + node_type: str + message: str + value_field: Optional[str] = None + #: The column carrying this type's display label, when it declares one. + label_field: Optional[str] = None + identity_field: Optional[str] = None + identity_format: Optional[str] = None + fields: Tuple[FieldSchema, ...] = () + + @classmethod + def parse(cls, node_type: str, data: Mapping[str, Any]) -> "NodeSchema": + identity = data.get("identity") or {} + return cls( + node_type=node_type, + message=str(data["message"]), + value_field=data.get("value_field"), + label_field=data.get("label_field"), + identity_field=identity.get("field"), + identity_format=identity.get("format"), + fields=tuple(FieldSchema.parse(item) for item in data.get("fields", ())), + ) + + @property + def type_url(self) -> str: + return f"{TYPE_URL_PREFIX}{self.message}" + + def field(self, name: str) -> Optional[FieldSchema]: + for item in self.fields: + if item.name == name: + return item + return None + + +class RelationSchema(BaseModel): + """One relation type and the message that carries its edge payload.""" + + model_config = ConfigDict(frozen=True) + + relation_type: str + message: str + fields: Tuple[FieldSchema, ...] + + @classmethod + def parse(cls, relation_type: str, data: Mapping[str, Any]) -> "RelationSchema": + return cls( + relation_type=relation_type, + message=str(data["message"]), + fields=tuple(FieldSchema.parse(item) for item in data.get("fields", ())), + ) + + @property + def type_url(self) -> str: + return f"{TYPE_URL_PREFIX}{self.message}" + + def field(self, name: str) -> Optional[FieldSchema]: + for item in self.fields: + if item.name == name: + return item + return None + + +class FlagSchema(BaseModel): + """One flag an extension declares, and the bit it owns. + + The bit is identity, like a field number: it is what a stored mask means. + A runtime holds the mechanism — a 64-bit mask — and never the vocabulary, + so `honeypot` is EASM's word and lives in EASM's document. + """ + + model_config = ConfigDict(frozen=True) + + bit: int + default_exclude: bool = False + + @classmethod + def parse(cls, data: Mapping[str, Any]) -> "FlagSchema": + return cls( + bit=int(data["bit"]), + default_exclude=bool(data.get("default_exclude", False)), + ) + + +class ExtensionSchema(BaseModel): + """Every node and relation type contributed by one extension.""" + + model_config = ConfigDict(frozen=True) + + extension: str + nodes: Dict[str, NodeSchema] = Field(default_factory=dict) + relations: Dict[str, RelationSchema] = Field(default_factory=dict) + #: Named judgements this extension makes about a node, keyed by name. + flags: Dict[str, FlagSchema] = Field(default_factory=dict) + + @classmethod + def parse(cls, data: Mapping[str, Any]) -> "ExtensionSchema": + version = int(data.get("schema_version", 0)) + if version != _SUPPORTED_SCHEMA_VERSION: + raise ValueError( + f"unsupported schema_version {version}; " + f"cstxpy understands {_SUPPORTED_SCHEMA_VERSION}" + ) + return cls( + extension=str(data["extension"]), + nodes={ + name: NodeSchema.parse(name, item) + for name, item in (data.get("nodes") or {}).items() + }, + relations={ + name: RelationSchema.parse(name, item) + for name, item in (data.get("relations") or {}).items() + }, + flags={ + name: FlagSchema.parse(item) + for name, item in (data.get("flags") or {}).items() + }, + ) + + @classmethod + def from_json(cls, text: str) -> "ExtensionSchema": + return cls.parse(json.loads(text)) + + +class SchemaRegistry: + """A read view of the schemas a runtime holds. + + This is a projection, not an authority. Which extension may claim a node + type, how a short message name resolves when two packages spell it the + same way, which proto types a document may declare — every one of those + is decided in Rust, and a document that reaches this class has already + been accepted there. Deciding any of it a second time here is how the two + ended up disagreeing about the same document. + + Lookups are flat on purpose: a caller asking for ``node_type_url("domain")`` + should not have to know whether ``domain`` came from the built-in extension + or from one registered at runtime. + """ + + def __init__(self) -> None: + self._extensions: Dict[str, ExtensionSchema] = {} + self._nodes: Dict[str, NodeSchema] = {} + self._relations: Dict[str, RelationSchema] = {} + self._nodes_by_message: Dict[str, NodeSchema] = {} + self._relations_by_message: Dict[str, RelationSchema] = {} + + def _install(self, schema: ExtensionSchema) -> ExtensionSchema: + """Record one extension, replacing any earlier version of itself.""" + self._extensions[schema.extension] = schema + self._reindex() + return schema + + def _remove(self, extension: str) -> None: + """Drop one extension from the view.""" + if self._extensions.pop(extension, None) is not None: + self._reindex() + + def _reindex(self) -> None: + self._nodes.clear() + self._relations.clear() + self._nodes_by_message.clear() + self._relations_by_message.clear() + # Short names are built only where they are unambiguous. Rust resolves + # a bare message name to nothing when two packages both spell it that + # way; answering with whichever landed first would be a different + # answer to the same question. + node_short: Dict[str, list] = {} + relation_short: Dict[str, list] = {} + for schema in self._extensions.values(): + for node in schema.nodes.values(): + self._nodes[node.node_type] = node + self._nodes_by_message[node.message] = node + node_short.setdefault(_message_short_name(node.message), []).append(node) + for relation in schema.relations.values(): + self._relations[relation.relation_type] = relation + self._relations_by_message[relation.message] = relation + relation_short.setdefault( + _message_short_name(relation.message), [] + ).append(relation) + for short, nodes in node_short.items(): + if len(nodes) == 1 and short not in self._nodes_by_message: + self._nodes_by_message[short] = nodes[0] + for short, relations in relation_short.items(): + if len(relations) == 1 and short not in self._relations_by_message: + self._relations_by_message[short] = relations[0] + + # ── extensions ── + + def extensions(self) -> Tuple[str, ...]: + return tuple(self._extensions) + + def extension(self, name: str) -> Optional[ExtensionSchema]: + return self._extensions.get(name) + + # ── nodes ── + + def node(self, node_type: str) -> Optional[NodeSchema]: + return self._nodes.get(node_type) + + def node_types(self) -> Tuple[str, ...]: + return tuple(self._nodes) + + def node_type_url(self, node_type: str) -> Optional[str]: + node = self._nodes.get(node_type) + return node.type_url if node else None + + def node_type_from_url(self, type_url: str) -> Optional[str]: + node = self._by_message(self._nodes_by_message, type_url) + return node.node_type if node else None + + # ── relations ── + + def relation(self, relation_type: str) -> Optional[RelationSchema]: + return self._relations.get(relation_type) + + def relation_types(self) -> Tuple[str, ...]: + return tuple(self._relations) + + def relation_type_url(self, relation_type: str) -> Optional[str]: + relation = self._relations.get(relation_type) + return relation.type_url if relation else None + + def relation_type_from_url(self, type_url: str) -> Optional[str]: + relation = self._by_message(self._relations_by_message, type_url) + return relation.relation_type if relation else None + + @staticmethod + def _by_message(index: Dict[str, Any], type_url: str) -> Any: + """Exact message name first, bare name only as a fallback. + + The index carries both spellings, but the bare name is present only + when it is unambiguous. Shortening the query before looking made the + fully-qualified entries unreachable, so `acme.Asset` and `easm.Asset` + answered as one. + """ + full = str(type_url or "").rsplit("/", 1)[-1] + return index.get(full) or index.get(_message_short_name(type_url)) + + +registry = SchemaRegistry() + + +def load_schema(source: "str | Path | Mapping[str, Any]") -> ExtensionSchema: + """Read one schema document into the view. + + Internal. This is not a registration entry: it validates nothing about + whether the document may be registered, and a runtime that rejects a + document will never call it. The one public way to declare types is + ``runtime.extensions.register`` — a second entry here is how a type became + visible to Python and unknown to the core. + + Accepts a path to a ``.schema.json``, its raw text, or an already-parsed + mapping — whichever an extension has on hand. + """ + if isinstance(source, Mapping): + schema = ExtensionSchema.parse(source) + else: + text = str(source) + # A document's own text is not a path, and asking the filesystem about + # it raises rather than answering: a JSON document is longer than any + # filename a kernel will accept. Decide by shape, not by stat. + if not text.lstrip().startswith("{"): + path = Path(text) + if path.is_file(): + text = path.read_text(encoding="utf-8") + schema = ExtensionSchema.from_json(text) + return registry._install(schema) + + +def load_bundled(name: str) -> ExtensionSchema: + """Read a schema shipped inside cstxpy (the built-in extensions). + + Internal, and the one thing that has to happen before any runtime exists: + the EASM model classes are built from this document at import time, when + there is nothing to project from. The file is byte-identical to the one + the core compiles in, pinned by `tests/test_schema_document_copies_agree`. + """ + return load_schema(_SCHEMA_DIR / f"{name}.schema.json") + + +def bundled_names() -> Tuple[str, ...]: + if not _SCHEMA_DIR.is_dir(): + return () + return tuple(sorted(p.name[: -len(".schema.json")] for p in _SCHEMA_DIR.glob("*.schema.json"))) + + +# ── module-level facade over the registry ── +# +# These mirror the queries call sites make. They read through the registry, so +# a schema registered at runtime answers them exactly like a bundled one. + + +def node_type_url(node_type: str) -> Optional[str]: + return registry.node_type_url(node_type) + + +def node_type_from_url(type_url: str) -> Optional[str]: + return registry.node_type_from_url(type_url) + + +def relation_type_url(relation_type: str) -> Optional[str]: + return registry.relation_type_url(relation_type) + + +def relation_type_from_url(type_url: str) -> Optional[str]: + return registry.relation_type_from_url(type_url) + + +def relation_types() -> Tuple[str, ...]: + return registry.relation_types() + + +def project(contract: "Any") -> None: + """Replace the view with the schemas a runtime holds. + + Takes the documents out of an ``ExtensionContract`` the runtime handed + back, so what Python can see is exactly what the core accepted. Rejected + registrations never reach here, which is why this class needs no conflict + policy of its own. + + Bundled extensions the contract does not mention are kept: they were read + at import time, before any runtime existed. + """ + for name, definition in contract.extensions.items(): + document = definition.schema + if document: + load_schema(document) + + +# The built-in extensions are read once, at import, because the model bases +# are built from them at class-definition time. Everything else arrives by +# projection from a runtime. +for _bundled in bundled_names(): + load_bundled(_bundled) diff --git a/python/python/cstxpy/schemas/easm.schema.json b/python/python/cstxpy/schemas/easm.schema.json new file mode 100644 index 0000000..0e43846 --- /dev/null +++ b/python/python/cstxpy/schemas/easm.schema.json @@ -0,0 +1,424 @@ +{ + "schema_version": 1, + "extension": "easm", + "nodes": { + "domain": { + "message": "easm.Domain", + "value_field": "host", + "identity": { "field": "host" }, + "fields": [ + { "name": "host", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": false, "semantic_label": "host" }, + { "name": "extra", "number": 2, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "extra", "column": "json" } + ] + }, + "subdomain": { + "message": "easm.Subdomain", + "value_field": "host", + "identity": { "field": "host" }, + "fields": [ + { "name": "host", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": false, "semantic_label": "host" }, + { "name": "is_tld", "number": 2, "type": "bool", "repeated": false, "optional": true, "semantic": false, "semantic_label": "is_tld" }, + { "name": "ttl", "number": 3, "type": "int64", "repeated": false, "optional": true, "semantic": false, "semantic_label": "ttl" }, + { "name": "resolver", "number": 4, "type": "string", "repeated": true, "optional": false, "semantic": false, "semantic_label": "resolver" }, + { "name": "a", "number": 5, "type": "string", "repeated": true, "optional": false, "semantic": false, "semantic_label": "a" }, + { "name": "aaaa", "number": 6, "type": "string", "repeated": true, "optional": false, "semantic": false, "semantic_label": "aaaa" }, + { "name": "cname", "number": 7, "type": "string", "repeated": true, "optional": false, "semantic": false, "semantic_label": "cname" }, + { "name": "mx", "number": 8, "type": "string", "repeated": true, "optional": false, "semantic": false, "semantic_label": "mx" }, + { "name": "ns", "number": 9, "type": "string", "repeated": true, "optional": false, "semantic": false, "semantic_label": "ns" }, + { "name": "txt", "number": 10, "type": "string", "repeated": true, "optional": false, "semantic": false, "semantic_label": "txt" }, + { "name": "extra", "number": 11, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "extra", "column": "json" }, + { "name": "root_domain", "number": 12, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "root_domain", "compute": { "from": "host", "apply": "root_domain" } } + ] + }, + "ip": { + "message": "easm.Ip", + "value_field": "ip", + "identity": { "field": "ip" }, + "fields": [ + { "name": "ip", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": false, "semantic_label": "ip" }, + { "name": "country", "number": 2, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "country" }, + { "name": "area", "number": 3, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "area" }, + { "name": "asn_number", "number": 4, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "asn_number" }, + { "name": "as_name", "number": 5, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "as_name" }, + { "name": "cdn_name", "number": 6, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "cdn_name" }, + { "name": "cloud_name", "number": 7, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "cloud_name" }, + { "name": "waf_name", "number": 8, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "waf_name" }, + { "name": "cdn", "number": 9, "type": "bool", "repeated": false, "optional": true, "semantic": false, "semantic_label": "cdn" }, + { "name": "cloud", "number": 10, "type": "bool", "repeated": false, "optional": true, "semantic": false, "semantic_label": "cloud" }, + { "name": "waf", "number": 11, "type": "bool", "repeated": false, "optional": true, "semantic": false, "semantic_label": "waf" }, + { "name": "extra", "number": 12, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "extra", "column": "json" }, + { "name": "cidr", "number": 13, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "cidr", "compute": { "from": "ip", "apply": "cidr" } } + ] + }, + "cidr": { + "message": "easm.Cidr", + "value_field": "cidr", + "identity": { "field": "cidr" }, + "fields": [ + { "name": "cidr", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": false, "semantic_label": "cidr" }, + { "name": "extra", "number": 2, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "extra", "column": "json" } + ] + }, + "port": { + "message": "easm.Port", + "identity": { "format": "{ip}:{port}" }, + "fields": [ + { "name": "ip", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": false, "semantic_label": "ip" }, + { "name": "port", "number": 2, "type": "string", "repeated": false, "optional": false, "semantic": false, "semantic_label": "port" }, + { "name": "protocol", "number": 3, "type": "string", "repeated": false, "optional": false, "semantic": false, "semantic_label": "protocol" }, + { "name": "extra", "number": 4, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "extra", "column": "json" } + ] + }, + "app": { + "message": "easm.App", + "value_field": "app_id", + "identity": { "field": "app_id" }, + "fields": [ + { "name": "app_id", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": false, "semantic_label": "app_id" }, + { "name": "url", "number": 2, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "url" }, + { "name": "frameworks", "number": 3, "type": "string", "repeated": true, "optional": false, "semantic": true, "semantic_label": "frameworks" }, + { "name": "title", "number": 4, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "title" }, + { "name": "midware", "number": 5, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "midware" }, + { "name": "status", "number": 6, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "status" }, + { "name": "status_code", "number": 7, "type": "int64", "repeated": false, "optional": true, "semantic": false, "semantic_label": "status_code" }, + { "name": "host", "number": 8, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "host" }, + { "name": "content_type", "number": 9, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "content_type" }, + { "name": "body_length", "number": 10, "type": "int64", "repeated": false, "optional": true, "semantic": false, "semantic_label": "body_length" }, + { "name": "header_length", "number": 11, "type": "int64", "repeated": false, "optional": true, "semantic": false, "semantic_label": "header_length" }, + { "name": "screenshot_id", "number": 12, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "screenshot_id" }, + { "name": "screenshot_path", "number": 13, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "screenshot_path" }, + { "name": "ip", "number": 14, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "ip" }, + { "name": "port", "number": 15, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "port" }, + { "name": "extra", "number": 16, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "extra", "column": "json" } + ] + }, + "url": { + "message": "easm.Url", + "value_field": "url", + "identity": { "field": "url" }, + "fields": [ + { "name": "scheme", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": false, "semantic_label": "scheme" }, + { "name": "host", "number": 2, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "host" }, + { "name": "port", "number": 3, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "port" }, + { "name": "path", "number": 4, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "path" }, + { "name": "ip", "number": 5, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "ip" }, + { "name": "status_code", "number": 6, "type": "int64", "repeated": false, "optional": true, "semantic": false, "semantic_label": "status_code" }, + { "name": "title", "number": 9, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "title" }, + { "name": "body_length", "number": 10, "type": "int64", "repeated": false, "optional": true, "semantic": false, "semantic_label": "body_length" }, + { "name": "content_type", "number": 11, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "content_type" }, + { "name": "redirect_url", "number": 12, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "redirect_url" }, + { "name": "frameworks", "number": 13, "type": "string", "repeated": true, "optional": false, "semantic": true, "semantic_label": "frameworks" }, + { "name": "url", "number": 14, "type": "string", "repeated": false, "optional": false, "semantic": false, "semantic_label": "url" }, + { "name": "extra", "number": 15, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "extra", "column": "json" } + ] + }, + "framework": { + "message": "easm.Framework", + "value_field": "name", + "identity": { "field": "name" }, + "fields": [ + { "name": "name", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": true, "semantic_label": "name" }, + { "name": "part", "number": 2, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "part" }, + { "name": "vendor", "number": 3, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "vendor" }, + { "name": "product", "number": 4, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "product" }, + { "name": "version", "number": 5, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "version" }, + { "name": "tags", "number": 6, "type": "string", "repeated": true, "optional": false, "semantic": true, "semantic_label": "tags" }, + { "name": "is_focus", "number": 7, "type": "bool", "repeated": false, "optional": true, "semantic": false, "semantic_label": "is_focus" }, + { "name": "sources", "number": 8, "type": "string", "repeated": true, "optional": false, "semantic": false, "semantic_label": "sources" }, + { "name": "extra", "number": 9, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "extra", "column": "json" } + ] + }, + "vuln": { + "message": "easm.Vuln", + "label_field": "name", + "value_field": "value", + "identity": { "field": "value" }, + "fields": [ + { "name": "value", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": false, "semantic_label": "value" }, + { "name": "vuln_id", "number": 2, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "vuln_id" }, + { "name": "name", "number": 3, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "name" }, + { "name": "asset_id", "number": 4, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "asset_id" }, + { "name": "severity", "number": 5, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "severity", "ordered_values": ["unknown", "info", "low", "medium", "high", "critical"] }, + { "name": "tags", "number": 6, "type": "string", "repeated": true, "optional": false, "semantic": true, "semantic_label": "tags" }, + { "name": "ip", "number": 7, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "ip" }, + { "name": "host", "number": 8, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "host" }, + { "name": "port", "number": 9, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "port" }, + { "name": "protocol", "number": 10, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "protocol" }, + { "name": "scheme", "number": 11, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "scheme" }, + { "name": "url", "number": 12, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "url" }, + { "name": "path", "number": 13, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "path" }, + { "name": "pocname", "number": 14, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "pocname" }, + { "name": "request", "number": 15, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "request" }, + { "name": "response", "number": 16, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "response" }, + { "name": "username", "number": 17, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "username" }, + { "name": "password", "number": 18, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "password" }, + { "name": "matched", "number": 19, "type": "bool", "repeated": false, "optional": true, "semantic": false, "semantic_label": "matched" }, + { "name": "extracted", "number": 20, "type": "bool", "repeated": false, "optional": true, "semantic": false, "semantic_label": "extracted" }, + { "name": "extra", "number": 21, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "extra", "column": "json" } + ] + }, + "sarif_vuln": { + "message": "easm.SarifVuln", + "value_field": "value", + "identity": { "field": "value" }, + "fields": [ + { "name": "value", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": false, "semantic_label": "value" }, + { "name": "vuln_id", "number": 2, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "vuln_id" }, + { "name": "title", "number": 3, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "title" }, + { "name": "description", "number": 4, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "description" }, + { "name": "source", "number": 5, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "source" }, + { "name": "target", "number": 6, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "target" }, + { "name": "tags", "number": 7, "type": "string", "repeated": true, "optional": false, "semantic": true, "semantic_label": "tags" }, + { "name": "asset_cstx_id", "number": 8, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "asset_cstx_id" }, + { "name": "kind", "number": 9, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "kind" }, + { "name": "level", "number": 10, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "level" }, + { "name": "baseline_state", "number": 11, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "baseline_state" }, + { "name": "rule_id", "number": 12, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "rule_id" }, + { "name": "evidence", "number": 13, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "evidence" }, + { "name": "extra", "number": 14, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "extra", "column": "json" } + ] + }, + "certificate": { + "message": "easm.Certificate", + "value_field": "fingerprint", + "identity": { "field": "fingerprint" }, + "fields": [ + { "name": "fingerprint", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": false, "semantic_label": "fingerprint" }, + { "name": "serial", "number": 2, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "serial" }, + { "name": "issuer", "number": 3, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "issuer" }, + { "name": "subject", "number": 4, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "subject" }, + { "name": "not_before", "number": 5, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "not_before" }, + { "name": "not_after", "number": 6, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "not_after" }, + { "name": "san", "number": 7, "type": "string", "repeated": true, "optional": false, "semantic": false, "semantic_label": "san" }, + { "name": "host", "number": 8, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "host" }, + { "name": "ip", "number": 9, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "ip" }, + { "name": "extra", "number": 10, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "extra", "column": "json" } + ] + }, + "company": { + "message": "easm.Company", + "value_field": "name", + "identity": { "field": "name" }, + "fields": [ + { "name": "name", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": true, "semantic_label": "name" }, + { "name": "perc", "number": 2, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "perc" }, + { "name": "tycid", "number": 3, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "tycid" }, + { "name": "icp", "number": 4, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "icp" }, + { "name": "parent", "number": 5, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "parent" }, + { "name": "extra", "number": 6, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "extra", "column": "json" } + ] + }, + "icp": { + "message": "easm.Icp", + "value_field": "icp", + "identity": { "field": "icp" }, + "fields": [ + { "name": "icp", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": false, "semantic_label": "icp" }, + { "name": "sub", "number": 2, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "sub" }, + { "name": "date", "number": 3, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "date" }, + { "name": "company", "number": 4, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "company" }, + { "name": "title", "number": 5, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "title" }, + { "name": "domain", "number": 6, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "domain" }, + { "name": "ip", "number": 7, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "ip" }, + { "name": "extra", "number": 8, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "extra", "column": "json" } + ] + }, + "bucket": { + "message": "easm.Bucket", + "value_field": "endpoint", + "identity": { "field": "endpoint" }, + "fields": [ + { "name": "provider", "number": 1, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "provider" }, + { "name": "name", "number": 2, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "name" }, + { "name": "region", "number": 3, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "region" }, + { "name": "endpoint", "number": 4, "type": "string", "repeated": false, "optional": false, "semantic": false, "semantic_label": "endpoint" }, + { "name": "acl", "number": 5, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "acl" }, + { "name": "object_count", "number": 6, "type": "int64", "repeated": false, "optional": true, "semantic": false, "semantic_label": "object_count" }, + { "name": "known_paths", "number": 7, "type": "string", "repeated": true, "optional": false, "semantic": false, "semantic_label": "known_paths" }, + { "name": "source_url", "number": 8, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "source_url" }, + { "name": "extra", "number": 9, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "extra", "column": "json" } + ] + }, + "endpoint": { + "message": "easm.Endpoint", + "value_field": "url", + "identity": { "field": "url" }, + "fields": [ + { "name": "url", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": false, "semantic_label": "url" }, + { "name": "method", "number": 2, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "method" }, + { "name": "path", "number": 3, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "path" }, + { "name": "content_type", "number": 4, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "content_type" }, + { "name": "status_code", "number": 5, "type": "int64", "repeated": false, "optional": true, "semantic": false, "semantic_label": "status_code" }, + { "name": "source", "number": 8, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "source" }, + { "name": "source_url", "number": 9, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "source_url" }, + { "name": "parameters", "number": 10, "type": "string", "repeated": true, "optional": false, "semantic": true, "semantic_label": "parameters" }, + { "name": "tags", "number": 11, "type": "string", "repeated": true, "optional": false, "semantic": true, "semantic_label": "tags" }, + { "name": "extra", "number": 12, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "extra", "column": "json" } + ] + }, + "host": { + "message": "easm.Host", + "value_field": "hostname", + "identity": { "field": "hostname" }, + "fields": [ + { "name": "hostname", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": false, "semantic_label": "hostname" }, + { "name": "local_ips", "number": 2, "type": "string", "repeated": true, "optional": false, "semantic": false, "semantic_label": "local_ips" }, + { "name": "gateway_ips", "number": 3, "type": "string", "repeated": true, "optional": false, "semantic": false, "semantic_label": "gateway_ips" }, + { "name": "dns_servers", "number": 4, "type": "string", "repeated": true, "optional": false, "semantic": false, "semantic_label": "dns_servers" }, + { "name": "domain_name", "number": 5, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "domain_name" }, + { "name": "domain_role", "number": 6, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "domain_role" }, + { "name": "extra", "number": 7, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "extra", "column": "json" } + ] + }, + "repository": { + "message": "easm.Repository", + "value_field": "url", + "identity": { "field": "url" }, + "fields": [ + { "name": "provider", "number": 1, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "provider" }, + { "name": "name", "number": 2, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "name" }, + { "name": "url", "number": 3, "type": "string", "repeated": false, "optional": false, "semantic": false, "semantic_label": "url" }, + { "name": "owner", "number": 4, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "owner" }, + { "name": "description", "number": 5, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "description" }, + { "name": "stars", "number": 6, "type": "int64", "repeated": false, "optional": true, "semantic": false, "semantic_label": "stars" }, + { "name": "is_fork", "number": 7, "type": "bool", "repeated": false, "optional": true, "semantic": false, "semantic_label": "is_fork" }, + { "name": "matched_dorks", "number": 8, "type": "string", "repeated": true, "optional": false, "semantic": true, "semantic_label": "matched_dorks" }, + { "name": "extra", "number": 9, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "extra", "column": "json" } + ] + }, + "secret": { + "message": "easm.Secret", + "value_field": "fingerprint", + "identity": { "field": "fingerprint" }, + "fields": [ + { "name": "kind", "number": 1, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "kind" }, + { "name": "detector", "number": 2, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "detector" }, + { "name": "redacted", "number": 3, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "redacted" }, + { "name": "fingerprint", "number": 4, "type": "string", "repeated": false, "optional": false, "semantic": false, "semantic_label": "fingerprint" }, + { "name": "source", "number": 5, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "source" }, + { "name": "source_url", "number": 6, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "source_url" }, + { "name": "file_path", "number": 7, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "file_path" }, + { "name": "line", "number": 8, "type": "int64", "repeated": false, "optional": true, "semantic": false, "semantic_label": "line" }, + { "name": "commit", "number": 9, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "commit" }, + { "name": "verified", "number": 10, "type": "bool", "repeated": false, "optional": true, "semantic": false, "semantic_label": "verified" }, + { "name": "severity", "number": 11, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "severity", "ordered_values": ["unknown", "info", "low", "medium", "high", "critical"] }, + { "name": "extra", "number": 12, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "extra", "column": "json" } + ] + } + }, + "relations": { + "vuln": { + "message": "easm.Vuln", + "fields": [ + { "name": "value", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": false, "semantic_label": "value" }, + { "name": "vuln_id", "number": 2, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "vuln_id" }, + { "name": "name", "number": 3, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "name" }, + { "name": "asset_id", "number": 4, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "asset_id" }, + { "name": "severity", "number": 5, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "severity", "ordered_values": ["unknown", "info", "low", "medium", "high", "critical"] }, + { "name": "tags", "number": 6, "type": "string", "repeated": true, "optional": false, "semantic": true, "semantic_label": "tags" }, + { "name": "ip", "number": 7, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "ip" }, + { "name": "host", "number": 8, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "host" }, + { "name": "port", "number": 9, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "port" }, + { "name": "protocol", "number": 10, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "protocol" }, + { "name": "scheme", "number": 11, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "scheme" }, + { "name": "url", "number": 12, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "url" }, + { "name": "path", "number": 13, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "path" }, + { "name": "pocname", "number": 14, "type": "string", "repeated": false, "optional": true, "semantic": true, "semantic_label": "pocname" }, + { "name": "request", "number": 15, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "request" }, + { "name": "response", "number": 16, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "response" }, + { "name": "username", "number": 17, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "username" }, + { "name": "password", "number": 18, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "password" }, + { "name": "matched", "number": 19, "type": "bool", "repeated": false, "optional": true, "semantic": false, "semantic_label": "matched" }, + { "name": "extracted", "number": 20, "type": "bool", "repeated": false, "optional": true, "semantic": false, "semantic_label": "extracted" }, + { "name": "extra", "number": 21, "type": "string", "repeated": false, "optional": true, "semantic": false, "semantic_label": "extra", "column": "json" } + ] + }, + "resolve": { + "message": "easm.Resolve", + "fields": [ + { "name": "extra", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": true, "semantic_label": "extra", "column": "json" } + ] + }, + "open": { + "message": "easm.Open", + "fields": [ + { "name": "extra", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": true, "semantic_label": "extra", "column": "json" } + ] + }, + "has-subdomain": { + "message": "easm.HasSubdomain", + "fields": [ + { "name": "extra", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": true, "semantic_label": "extra", "column": "json" } + ] + }, + "contain": { + "message": "easm.Contain", + "fields": [ + { "name": "extra", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": true, "semantic_label": "extra", "column": "json" } + ] + }, + "hosts": { + "message": "easm.Hosts", + "fields": [ + { "name": "extra", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": true, "semantic_label": "extra", "column": "json" } + ] + }, + "uses": { + "message": "easm.Uses", + "fields": [ + { "name": "extra", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": true, "semantic_label": "extra", "column": "json" } + ] + }, + "refers": { + "message": "easm.Refers", + "fields": [ + { "name": "extra", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": true, "semantic_label": "extra", "column": "json" } + ] + }, + "secured_by": { + "message": "easm.SecuredBy", + "fields": [ + { "name": "extra", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": true, "semantic_label": "extra", "column": "json" } + ] + }, + "exploit": { + "message": "easm.Exploit", + "fields": [ + { "name": "extra", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": true, "semantic_label": "extra", "column": "json" } + ] + }, + "affect": { + "message": "easm.Affect", + "fields": [ + { "name": "extra", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": true, "semantic_label": "extra", "column": "json" } + ] + }, + "invest": { + "message": "easm.Invest", + "fields": [ + { "name": "extra", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": true, "semantic_label": "extra", "column": "json" } + ] + }, + "own": { + "message": "easm.Own", + "fields": [ + { "name": "extra", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": true, "semantic_label": "extra", "column": "json" } + ] + }, + "filed-for": { + "message": "easm.FiledFor", + "fields": [ + { "name": "extra", "number": 1, "type": "string", "repeated": false, "optional": false, "semantic": true, "semantic_label": "extra", "column": "json" } + ] + } + }, + "flags": { + "honeypot": { "bit": 0, "default_exclude": true }, + "noise": { "bit": 1, "default_exclude": true }, + "false_positive": { "bit": 2, "default_exclude": true }, + "manual_ignored": { "bit": 3, "default_exclude": true }, + "threat_present": { "bit": 4, "default_exclude": false }, + "historic_vulnerable": { "bit": 5, "default_exclude": false }, + "internal": { "bit": 6, "default_exclude": false } + } +} diff --git a/python/python/cstxpy/sco_easm.py b/python/python/cstxpy/sco_easm.py deleted file mode 100644 index 58380f5..0000000 --- a/python/python/cstxpy/sco_easm.py +++ /dev/null @@ -1,296 +0,0 @@ -# @generated by cstx-codegen — DO NOT EDIT MANUALLY - -# Schema-only shapes: the high-level cstx SDK mixes in its runtime -# model base (Element/SCO) at the wrapper layer. This module must stay -# free of cstx imports so cstxpy never depends on the high-level package. - -from __future__ import annotations - -from typing import List, Optional - -from pydantic import BaseModel, Field, ConfigDict - -class DomainBase(BaseModel): - """Generated schema for 'domain' node type.""" - - model_config = ConfigDict(extra="allow", coerce_numbers_to_str=True) - - host: str - -class SubdomainBase(BaseModel): - """Generated schema for 'subdomain' node type.""" - - model_config = ConfigDict(extra="allow", coerce_numbers_to_str=True) - - host: str - is_tld: bool = Field(default=False) - ttl: int = Field(default=0) - resolver: Optional[List[str]] = Field(default=None) - a: Optional[List[str]] = Field(default=None) - aaaa: Optional[List[str]] = Field(default=None) - cname: Optional[List[str]] = Field(default=None) - mx: Optional[List[str]] = Field(default=None) - ns: Optional[List[str]] = Field(default=None) - txt: Optional[List[str]] = Field(default=None) - -class IpBase(BaseModel): - """Generated schema for 'ip' node type.""" - - model_config = ConfigDict(extra="allow", coerce_numbers_to_str=True) - - ip: str - country: str = Field(default="") - area: str = Field(default="") - asn_number: str = Field(default="") - as_name: str = Field(default="") - cdn_name: str = Field(default="") - cloud_name: str = Field(default="") - waf_name: str = Field(default="") - cdn: bool = Field(default=False) - cloud: bool = Field(default=False) - waf: bool = Field(default=False) - -class CidrBase(BaseModel): - """Generated schema for 'cidr' node type.""" - - model_config = ConfigDict(extra="allow", coerce_numbers_to_str=True) - - cidr: str - -class PortBase(BaseModel): - """Generated schema for 'port' node type.""" - - model_config = ConfigDict(extra="allow", coerce_numbers_to_str=True) - - ip: str - port: str - protocol: str - -class AppBase(BaseModel): - """Generated schema for 'app' node type.""" - - model_config = ConfigDict(extra="allow", coerce_numbers_to_str=True) - - app_id: str - url: str = Field(default="") - frameworks: Optional[List[str]] = Field(default=None) - title: str = Field(default="") - midware: str = Field(default="") - status: str = Field(default="") - status_code: int = Field(default=0) - host: str = Field(default="") - content_type: str = Field(default="") - body_length: int = Field(default=0) - header_length: int = Field(default=0) - screenshot_id: str = Field(default="") - screenshot_path: str = Field(default="") - ip: str = Field(default="") - port: str = Field(default="") - -class UrlBase(BaseModel): - """Generated schema for 'url' node type.""" - - model_config = ConfigDict(extra="allow", coerce_numbers_to_str=True) - - scheme: str - host: str = Field(default="") - port: str = Field(default="") - path: str = Field(default="") - ip: str = Field(default="") - status_code: int = Field(default=0) - title: str = Field(default="") - body_length: int = Field(default=0) - content_type: str = Field(default="") - redirect_url: str = Field(default="") - frameworks: Optional[List[str]] = Field(default=None) - -class FrameworkBase(BaseModel): - """Generated schema for 'framework' node type.""" - - model_config = ConfigDict(extra="allow", coerce_numbers_to_str=True) - - name: str - part: str = Field(default="") - vendor: str = Field(default="") - product: str = Field(default="") - version: str = Field(default="") - tags: Optional[List[str]] = Field(default=None) - is_focus: bool = Field(default=False) - sources: Optional[List[str]] = Field(default=None) - -class VulnBase(BaseModel): - """Generated schema for 'vuln' node type.""" - - model_config = ConfigDict(extra="allow", coerce_numbers_to_str=True) - - value: str - vuln_id: str = Field(default="") - name: str = Field(default="") - asset_id: str = Field(default="") - severity: str = Field(default="") - tags: Optional[List[str]] = Field(default=None) - ip: str = Field(default="") - host: str = Field(default="") - port: str = Field(default="") - protocol: str = Field(default="") - scheme: str = Field(default="") - url: str = Field(default="") - path: str = Field(default="") - pocname: str = Field(default="") - request: str = Field(default="") - response: str = Field(default="") - username: str = Field(default="") - password: str = Field(default="") - matched: bool = Field(default=False) - extracted: bool = Field(default=False) - -class SarifVulnBase(BaseModel): - """Generated schema for 'sarif_vuln' node type.""" - - model_config = ConfigDict(extra="allow", coerce_numbers_to_str=True) - - value: str - vuln_id: str = Field(default="") - title: str = Field(default="") - description: str = Field(default="") - source: str = Field(default="") - target: str = Field(default="") - tags: Optional[List[str]] = Field(default=None) - asset_cstx_id: str = Field(default="") - kind: str = Field(default="") - level: str = Field(default="") - baseline_state: str = Field(default="") - rule_id: str = Field(default="") - evidence: str = Field(default="") - -class CertificateBase(BaseModel): - """Generated schema for 'certificate' node type.""" - - model_config = ConfigDict(extra="allow", coerce_numbers_to_str=True) - - fingerprint: str - serial: str = Field(default="") - issuer: str = Field(default="") - subject: str = Field(default="") - not_before: str = Field(default="") - not_after: str = Field(default="") - san: Optional[List[str]] = Field(default=None) - host: str = Field(default="") - ip: str = Field(default="") - -class CompanyBase(BaseModel): - """Generated schema for 'company' node type.""" - - model_config = ConfigDict(extra="allow", coerce_numbers_to_str=True) - - name: str - perc: str = Field(default="") - tycid: str = Field(default="") - icp: str = Field(default="") - parent: str = Field(default="") - -class IcpBase(BaseModel): - """Generated schema for 'icp' node type.""" - - model_config = ConfigDict(extra="allow", coerce_numbers_to_str=True) - - icp: str - sub: str = Field(default="") - date: str = Field(default="") - company: str = Field(default="") - title: str = Field(default="") - domain: str = Field(default="") - ip: str = Field(default="") - -class BucketBase(BaseModel): - """Generated schema for 'bucket' node type.""" - - model_config = ConfigDict(extra="allow", coerce_numbers_to_str=True) - - provider: str = Field(default="") - name: str = Field(default="") - region: str = Field(default="") - endpoint: str - acl: str = Field(default="") - object_count: int = Field(default=0) - known_paths: Optional[List[str]] = Field(default=None) - source_url: str = Field(default="") - -class EndpointBase(BaseModel): - """Generated schema for 'endpoint' node type.""" - - model_config = ConfigDict(extra="allow", coerce_numbers_to_str=True) - - url: str - method: str = Field(default="") - path: str = Field(default="") - content_type: str = Field(default="") - status_code: int = Field(default=0) - source: str = Field(default="") - source_url: str = Field(default="") - parameters: Optional[List[str]] = Field(default=None) - tags: Optional[List[str]] = Field(default=None) - -class HostBase(BaseModel): - """Generated schema for 'host' node type.""" - - model_config = ConfigDict(extra="allow", coerce_numbers_to_str=True) - - hostname: str - local_ips: Optional[List[str]] = Field(default=None) - gateway_ips: Optional[List[str]] = Field(default=None) - dns_servers: Optional[List[str]] = Field(default=None) - domain_name: str = Field(default="") - domain_role: str = Field(default="") - -class RepositoryBase(BaseModel): - """Generated schema for 'repository' node type.""" - - model_config = ConfigDict(extra="allow", coerce_numbers_to_str=True) - - provider: str = Field(default="") - name: str = Field(default="") - url: str - owner: str = Field(default="") - description: str = Field(default="") - stars: int = Field(default=0) - is_fork: bool = Field(default=False) - matched_dorks: Optional[List[str]] = Field(default=None) - -class SecretBase(BaseModel): - """Generated schema for 'secret' node type.""" - - model_config = ConfigDict(extra="allow", coerce_numbers_to_str=True) - - kind: str = Field(default="") - detector: str = Field(default="") - redacted: str = Field(default="") - fingerprint: str - source: str = Field(default="") - source_url: str = Field(default="") - file_path: str = Field(default="") - line: int = Field(default=0) - commit: str = Field(default="") - verified: bool = Field(default=False) - severity: str = Field(default="") - -__all__ = [ - "DomainBase", - "SubdomainBase", - "IpBase", - "CidrBase", - "PortBase", - "AppBase", - "UrlBase", - "FrameworkBase", - "VulnBase", - "SarifVulnBase", - "CertificateBase", - "CompanyBase", - "IcpBase", - "BucketBase", - "EndpointBase", - "HostBase", - "RepositoryBase", - "SecretBase", -] diff --git a/python/python/cstxpy/sro_easm.py b/python/python/cstxpy/sro_easm.py deleted file mode 100644 index a8b4444..0000000 --- a/python/python/cstxpy/sro_easm.py +++ /dev/null @@ -1,9 +0,0 @@ -# @generated by cstx-codegen — DO NOT EDIT MANUALLY - -from __future__ import annotations - -from typing import List, Literal, Optional - -RelationType = Literal["resolve", "open", "has-subdomain", "contain", "hosts", "uses", "refers", "secured_by", "exploit", "affect", "invest", "own", "filed-for"] - -RELATION_TYPES: List[RelationType] = ["resolve", "open", "has-subdomain", "contain", "hosts", "uses", "refers", "secured_by", "exploit", "affect", "invest", "own", "filed-for"] diff --git a/python/tests/test_concurrency.py b/python/tests/test_concurrency.py new file mode 100644 index 0000000..9141b40 --- /dev/null +++ b/python/tests/test_concurrency.py @@ -0,0 +1,87 @@ +from __future__ import annotations + + +from concurrent.futures import ThreadPoolExecutor + +from cstxpy import CSTX +from cstxpy.proto import cstx_pb2 as cstx +from google.protobuf.struct_pb2 import Struct + + +_SCHEMA = """{ + "schema_version": 1, + "extension": "test", + "nodes": { + "ip": { + "message": "test.Ip", + "value_field": "ip", + "identity": { "field": "ip" }, + "fields": [ + { "name": "ip", "number": 1, "type": "string", "repeated": false, + "optional": false, "semantic": false, "semantic_label": "ip" } + ] + } + }, + "relations": {} +}""" + + +def _node(value: str) -> cstx.Node: + return cstx.Node( + id=f"ip:{value}", + sources=["concurrency"], + value=cstx.EntityValue( + node_type="ip", + fields=[cstx.EntityField(name="ip", text=value)], + ), + ) + + +def _graph(nodes: list[cstx.Node]) -> bytes: + return (cstx.Graph(nodes=nodes)).SerializeToString() + + +def _runtime() -> CSTX: + runtime = CSTX() + contract = cstx.ExtensionContract(contract_version=1) + # Fill the definition in place: a protobuf map hands back the stored + # message, so mutating a copy after inserting it would drop the schema. + definition = contract.extensions["test"] + definition.name = "test" + definition.schema = _SCHEMA + runtime.extensions.register((contract).SerializeToString()) + runtime.graph.add_nodes(_graph([_node(str(index)) for index in range(100)])) + return runtime + + +def test_reads_run_concurrently_with_writes_without_corruption() -> None: + runtime = _runtime() + + def read(index: int) -> tuple[int, int, bool]: + return ( + runtime.graph.node_count(), + runtime.graph.relationship_count(), + runtime.graph.contains(f"ip:{index % 100}"), + ) + + with ThreadPoolExecutor(max_workers=4) as pool: + futures = [pool.submit(read, index) for index in range(100)] + for index in range(20): + runtime.graph.add_nodes(_graph([_node(f"write-{index}")])) + results = [future.result() for future in futures] + + assert all(nodes >= 100 and edges == 0 and present for nodes, edges, present in results) + assert runtime.graph.node_count() == 120 + + +def test_writes_are_atomic_when_called_from_multiple_threads() -> None: + runtime = _runtime() + + def write(worker: int) -> None: + for index in range(25): + runtime.graph.add_nodes(_graph([_node(f"{worker}-{index}")])) + + with ThreadPoolExecutor(max_workers=4) as pool: + list(pool.map(write, range(4))) + + assert runtime.graph.node_count() == 200 diff --git a/python/tests/test_conformance_fixture.py b/python/tests/test_conformance_fixture.py index 1e1ae40..cba2ff8 100644 --- a/python/tests/test_conformance_fixture.py +++ b/python/tests/test_conformance_fixture.py @@ -1,26 +1,71 @@ -"""Cross-language checks backed by the CSTX conformance fixture.""" +"""Cross-language checks backed by the canonical protobuf graph fixture. + +Rust and Go run this same file through their own bindings and assert the same +ids, counts and query result. That claim only means something if all three use +the fixture as written: this test used to remap every record onto `easm.Ip` +and `easm.Contain` before handing it over, which made it a test of easm rather +than of the fixture, and left the three languages agreeing with nobody. + +The fixture declares its own type in a schema document, so there is nothing to +remap — and no generated class for `conformance.Asset` in any language. +""" import json from pathlib import Path import cstxpy +from cstxpy.proto import cstx_pb2 as cstx + +FIXTURE = json.loads( + ( + Path(__file__).resolve().parents[3] / "tests/fixtures/conformance.json" + ).read_text(encoding="utf-8") +) + + +def _graph(fixture: dict) -> bytes: + """The fixture's records as the boundary takes them, named by the document.""" + nodes = [] + for item in fixture["nodes"]: + entity = cstx.EntityValue(node_type=item["type"]) + for name, value in item["model"].items(): + entity.fields.add(name=name, text=value) + nodes.append(cstx.Node(id=item["id"], sources=item["sources"], value=entity)) + relationships = [ + cstx.Relationship( + id=item["id"], + source_id=item["source_id"], + target_id=item["target_id"], + sources=item["sources"], + # A relation type is a field-less marker: the document names it and + # the payload carries nothing else. + value=cstx.RelationshipValue(relationship_type=item["type"]), + ) + for item in fixture["relationships"] + ] + return (cstx.Graph(nodes=nodes, relationships=relationships)).SerializeToString() -def test_conformance_fixture_matches_python_contract() -> None: - fixture_path = Path(__file__).resolve().parents[3] / "tests/fixtures/conformance.json" - fixture = json.loads(fixture_path.read_text(encoding="utf-8")) + +def _register(runtime: cstxpy.CSTX) -> None: + contract = cstx.ExtensionContract(contract_version=1) + definition = contract.extensions["conformance"] + definition.name = "conformance" + definition.schema = json.dumps(FIXTURE["document"]) + runtime.extensions.register(contract.SerializeToString()) + + +def test_conformance_fixture_uses_typed_protobuf_transport() -> None: runtime = cstxpy.CSTX() - schema = fixture["schema"] - runtime.schemas.register( - schema["node_type"], - schema["json_schema"], - schema["value_field"], - ) - runtime.graph.add_nodes(fixture["nodes"]) - runtime.graph.add_edges(fixture["edges"]) + _register(runtime) + runtime.graph.add_nodes(_graph(FIXTURE)) - expected = fixture["expected"] - assert [node["id"] for node in runtime.graph.nodes()] == expected["node_ids"] + expected = FIXTURE["expected"] assert runtime.graph.node_count() == expected["node_count"] - assert runtime.graph.edge_count() == expected["edge_count"] - assert [node["id"] for node in runtime.graph.query(fixture["query"])] == expected["node_ids"] + assert runtime.graph.relationship_count() == expected["relationship_count"] + page = cstx.GraphResultPage.FromString( + runtime.graph.query( + (cstx.GraphQuery(expression=FIXTURE["query"])).SerializeToString() + ).page(limit=100, page=1) + ) + assert [item.id for item in page.nodes.values] == expected["node_ids"] diff --git a/python/tests/test_graph.py b/python/tests/test_graph.py index ef1e602..e9055e2 100644 --- a/python/tests/test_graph.py +++ b/python/tests/test_graph.py @@ -1,617 +1,297 @@ +"""Python binding checks for the protobuf-only graph boundary.""" + import ast import inspect -import json from pathlib import Path import cstxpy import pytest +from cstxpy import CSTX, CSTXError, CSTXGraph, Extensions, GraphCursor, NodeFlags, Repository +from cstxpy.proto import cstx_pb2 as cstx +from google.protobuf.json_format import ParseDict +from google.protobuf.struct_pb2 import Struct -from cstxpy import ( - CSTX, - CSTXGraph, - CSTXError, - GraphCursor, - NodeFlags, - Repository, - Schemas, -) +def _value(node_type: str, **fields: str) -> cstx.EntityValue: + """A payload named from the schema document — the only spelling there is.""" + return cstx.EntityValue( + node_type=node_type, + fields=[cstx.EntityField(name=name, text=text) for name, text in sorted(fields.items())], + ) -SCHEMA = {"properties": {"ip": {"type": "string"}}} +def _ip(value: str, *, flags: int = 0, annotations: dict | None = None) -> cstx.Node: + node = cstx.Node( + id=f"ip:{value}", sources=["test"], + value=_value("ip", ip=value), + ) + node.flags_mask = flags + if annotations: + ParseDict(annotations, node.annotations) + return node + + +def _contain(source: str, target: str) -> cstx.Relationship: + relation = cstx.Relationship( + id=f"relationship:{source}:contain:{target}", + source_id=source, + target_id=target, + sources=["test"], + ) + relation.value.relationship_type = "contain" + return relation -def node(value: str, *, flags: int = 0) -> dict: - return { - "id": f"ip:{value}", - "type": "ip", - "value": value, - "model": {"ip": value, "cstx_flags": flags}, - "sources": ["test"], - "extras": {}, - } +def _graph(nodes=(), relationships=()) -> bytes: + return (cstx.Graph( + nodes=list(nodes), relationships=list(relationships) + )).SerializeToString() -def edge(source: str, target: str) -> dict: - return { - "id": f"relationship:{source}:related:{target}", - "source_id": source, - "target_id": target, - "relation_type": "related", - "sources": ["test"], - "attrs": {}, - } +def _window(limit: int = 1024, page: int = 1, order: int = 0) -> bytes: + return (cstx.QueryWindow(limit=limit, page=page, order=order)).SerializeToString() -def db() -> CSTX: - value = CSTX() - value.schemas.register("ip", SCHEMA, "ip") - return value +def _node_rows(cursor: GraphCursor) -> list[cstx.Node]: + return [cstx.Node.FromString(payload) for payload in cursor] -def test_root_services_and_native_values(): - value = db() - assert value.graph.add_nodes([node("1.1.1.1")]) == 1 - assert value.graph.add_nodes([node("1.1.1.1")]) == 0 - assert value.graph.node_count() == 1 - assert value.graph.node("ip:1.1.1.1")["model"]["ip"] == "1.1.1.1" - assert value.last_change()["updated_node_ids"] == [] +def _register(runtime: CSTX) -> None: + # The built-in extension ships its own schema document; enabling it is + # the whole registration step. + runtime.extensions.enable("easm") -def test_easm_metadata_requires_explicit_loading(): - value = CSTX() - assert "easm" in value.schemas.available_plugins() - assert "gogo" in value.schemas.plugin_artifacts("easm") - assert not value.schemas.has_native_artifact("gogo") - value.schemas.load_plugin("easm") - assert value.schemas.has_native_artifact("gogo") +def test_graph_methods_accept_and_return_only_protobuf() -> None: + runtime = CSTX() + _register(runtime) + assert runtime.graph.add_nodes(_graph([_ip("1.1.1.1")])) == 1 + assert runtime.graph.add_nodes(_graph([_ip("1.1.1.1")])) == 0 + node = cstx.Node.FromString(runtime.graph.node("ip:1.1.1.1")) + carried = {field.name: field.text for field in node.value.fields} + assert carried["ip"] == "1.1.1.1" -def test_cursor_filter_order_close_and_invalidation(): - value = db() - value.graph.add_nodes([node("2.2.2.2"), node("1.1.1.1", flags=NodeFlags.HONEYPOT)]) - cursor = value.graph.nodes(order="id_asc") - assert next(cursor)["id"] == "ip:1.1.1.1" - value.graph.add_nodes([node("3.3.3.3")]) + assert runtime.graph.add_nodes( + _graph([_ip("2.2.2.2")]) + ) == 1 + assert runtime.graph.add_relationships( + _graph(relationships=[_contain("ip:1.1.1.1", "ip:2.2.2.2")]) + ) == 1 + edge = cstx.Relationship.FromString( + runtime.graph.relationship("relationship:ip:1.1.1.1:contain:ip:2.2.2.2") + ) + assert edge.source_id == "ip:1.1.1.1" + + stats = cstx.GraphStats.FromString(runtime.graph.stats()) + assert stats.nodes_by_type["ip"] == 2 + assert stats.relationships_by_type["contain"] == 1 + change = cstx.GraphChangeSet.FromString(runtime.last_change()) + assert list(change.added_relationship_ids) == [edge.id] + + +def test_typed_cursor_page_and_next_share_one_transport() -> None: + runtime = CSTX() + _register(runtime) + runtime.graph.add_nodes(_graph([_ip("2.2.2.2"), _ip("1.1.1.1", flags=NodeFlags.HONEYPOT)])) + cursor = runtime.graph.nodes( + (cstx.NodeFilter(flags_any_mask=1 << 0)).SerializeToString(), # easm: `honeypot` + _window(order=cstx.SortOrder.SORT_ORDER_ID_ASC), + ) + row = cstx.Node.FromString(next(cursor)) + assert row.id == "ip:1.1.1.1" + assert cursor.next() is None + + all_rows = runtime.graph.nodes(b"", _window(order=cstx.SortOrder.SORT_ORDER_ID_ASC)) + page = cstx.GraphResultPage.FromString(all_rows.page(limit=10, page=1)) + assert [item.id for item in page.nodes.values] == ["ip:1.1.1.1", "ip:2.2.2.2"] + + +def test_cursor_invalidation_and_typed_stats() -> None: + runtime = CSTX() + _register(runtime) + runtime.graph.add_nodes(_graph([_ip("1.1.1.1"), _ip("2.2.2.2")])) + cursor = runtime.graph.nodes(b"", _window()) + assert cstx.Node.FromString(next(cursor)).id == "ip:1.1.1.1" + runtime.graph.add_nodes(_graph([_ip("3.3.3.3")])) with pytest.raises(CSTXError) as error: - next(cursor) + cursor.next() assert error.value.code == "CURSOR_INVALIDATED" - selected = list(value.graph.nodes(flags_any=NodeFlags.HONEYPOT)) - assert [item["id"] for item in selected] == ["ip:1.1.1.1"] - selected_cursor = value.graph.nodes(limit=1) - selected_cursor.close() - assert selected_cursor.closed - assert list(selected_cursor) == [] - -def test_noop_cstx_flag_filter_does_not_materialize_snapshot(): - value = db() - value.graph.add_nodes([node("1.1.1.1"), node("2.2.2.2", flags=NodeFlags.INTERNAL)]) - - result = value.graph.filter(exclude_mask=NodeFlags.HONEYPOT) - - assert isinstance(result, CSTX) - assert result.graph.node_count() == 2 - - -def test_stats_and_query_subgraph_accept_cstx_flag_masks_without_parallel_apis(): - value = db() - value.graph.add_nodes( - [ - node("1.1.1.1"), - node("2.2.2.2", flags=NodeFlags.HONEYPOT), - ] + filtered = cstx.GraphStats.FromString( + runtime.graph.stats(exclude_mask=NodeFlags.HONEYPOT) ) + assert filtered.nodes_by_type["ip"] == 3 - assert value.graph.stats()["nodes"] == {"ip": 2} - assert value.graph.stats(exclude_mask=NodeFlags.HONEYPOT)["nodes"] == {"ip": 1} - - all_matches = value.graph.query_subgraph("ip") - assert all_matches.graph.node_count() == 2 - assert all_matches.graph.edge_count() == 0 - - filtered = value.graph.query_subgraph("ip", exclude_mask=NodeFlags.HONEYPOT) - assert filtered.graph.node_count() == 1 - assert filtered.graph.find_node("ip:1.1.1.1") is not None - - assert not hasattr(value.graph, "stats_filtered") - assert not hasattr(value.graph, "query_trace_ids_filtered") - for internal_name in ( - "node_ids", - "nodes_by_ids", - "link_nodes", - "subgraph_ids", - "query_node_ids", - "query_trace_ids", - "induced_snapshot", - "_node_ids", - "_nodes_by_ids", - "_link_nodes", - "_subgraph_ids", - "_query_node_ids", - "_query_trace_ids", - "_induced_snapshot", - ): - assert not hasattr(value.graph, internal_name) - - -def test_stats_selection_counts_induced_edges_without_materializing_a_subgraph(): - value = db() - selected_a = node("1.1.1.1") - selected_a["extras"] = {"flow_ids": ["flow-a"]} - selected_b = node("2.2.2.2") - selected_b["extras"] = {"flow_ids": ["flow-a"]} - outside = node("3.3.3.3") - outside["extras"] = {"flow_ids": ["flow-b"]} - value.graph.add_nodes([selected_a, selected_b, outside]) - value.graph.add_edges( - [ - edge("ip:1.1.1.1", "ip:2.2.2.2"), - edge("ip:2.2.2.2", "ip:3.3.3.3"), - ] - ) - stats = value.graph.stats(selection='*[flow_ids=="flow-a"]') - - assert stats["nodes"] == {"ip": 2} - assert stats["edges"] == {"related": 1} - assert stats["sources"] == {"test": 2} - - -def test_analyze_leiden_returns_complete_selected_partition(): - value = db() - node_ids = ["ip:a1", "ip:a2", "ip:a3", "ip:b1", "ip:b2", "ip:b3"] - value.graph.add_nodes([node(node_id.removeprefix("ip:")) for node_id in node_ids]) - value.graph.add_edges( - [ - edge("ip:a1", "ip:a2"), - edge("ip:a2", "ip:a3"), - edge("ip:a3", "ip:a1"), - edge("ip:b1", "ip:b2"), - edge("ip:b2", "ip:b3"), - edge("ip:b3", "ip:b1"), - ] +def test_algorithms_return_typed_pages() -> None: + runtime = CSTX() + _register(runtime) + runtime.graph.add_nodes(_graph([_ip("a"), _ip("b")])) + runtime.graph.add_relationships(_graph(relationships=[_contain("ip:a", "ip:b")])) + assert runtime.graph.analyze(cstxpy.Algorithm.is_dag()) is True + paths = runtime.graph.analyze( + cstxpy.Algorithm.shortest_paths("ip:a", "ip:b", direction="both") ) - - result = value.graph.analyze({"name": "leiden", "resolution": 1.0}) - assignment_page = result.page(limit=100, page=1) - summary = assignment_page["summary"] - - assert summary["algorithm"] == "leiden" - assert summary["projection"] == "undirected" - assert summary["resolution"] == 1.0 - assert summary["num_communities"] >= 2 - assert summary["total_communities"] == summary["num_communities"] - assert summary["communities_truncated"] is False - assert sum(summary["community_sizes"].values()) == len(node_ids) - assignments = { - item["node_id"]: item["community"] for item in assignment_page["items"] - } - assert set(assignments) == set(node_ids) - assert assignments["ip:a1"] != assignments["ip:b1"] - - limited = value.graph.analyze( - {"name": "leiden", "resolution": 1.0, "top_k": 1}, - 'ip[ip!="a1"]', + page = cstx.GraphResultPage.FromString(paths.page(limit=10, page=1)) + assert [list(item.node_ids) for item in page.paths.values] == [["ip:a", "ip:b"]] + + +def test_extension_introspection_is_protobuf() -> None: + runtime = CSTX() + _register(runtime) + catalog = cstx.ExtensionCatalog.FromString(runtime.extensions.list()) + assert any(item.name == "easm" for item in catalog.extensions) + schema = cstx.NodeType.FromString(runtime.extensions.schema("ip")) + assert schema.type_url + + +def test_rag_uses_protobuf_plan_and_results() -> None: + runtime = CSTX() + _register(runtime) + runtime.graph.add_nodes(_graph([_ip("1.1.1.1")])) + # The document marks `ip` as non-semantic — an identity value is not useful + # for semantic recall — so the record needs a field that is indexed. + runtime.graph.add_nodes(_graph([ + cstx.Node( + id="ip:1.1.1.1", sources=["test"], + value=_value("ip", ip="1.1.1.1", as_name="Example Networks"), + ) + ])) + session = runtime.graph.rag().index( + (cstx.RagIndexPlan( + commit="working", + mode=cstx.RagIndexMode.RAG_INDEX_FULL, + )).SerializeToString() ) - limited_page = limited.page(limit=100, page=1) - limited_summary = limited_page["summary"] - assert limited_summary["num_communities"] == 1 - assert limited_summary["communities_truncated"] is True - assert len(limited_summary["community_sizes"]) == 1 - assert all(item["node_id"] != "ip:a1" for item in limited_page["items"]) - - with pytest.raises(CSTXError): - value.graph.analyze({"name": "leiden", "resolution": 0.0}) - with pytest.raises(CSTXError): - value.graph.analyze({"name": "leiden", "top_k": 0}) - - -def test_analyze_is_the_single_typed_algorithm_atom(): - value = db() - value.graph.add_nodes([node(name) for name in ("a", "b", "c", "d")]) - value.graph.add_edges( - [ - edge("ip:a", "ip:b"), - edge("ip:a", "ip:c"), - edge("ip:b", "ip:d"), - edge("ip:c", "ip:d"), - ] + record = cstx.RagRecord.FromString(next(session.pending("v1"))) + assert record.id == "node/ip:1.1.1.1" + retrieval = runtime.graph.rag().retrieve( + (cstx.RagQuery(text="1.1.1.1", limit=5)).SerializeToString() ) - - assert value.graph.analyze({"name": "is_dag"}) is True - weak = value.graph.analyze({"name": "weak_components"}) - assert weak.page(limit=10, page=1)["summary"]["projection"] == "undirected" - strong = value.graph.analyze({"name": "strong_components"}) - assert "projection" not in strong.page(limit=10, page=1)["summary"] - paths = value.graph.analyze( - { - "name": "shortest_paths", - "start_id": "ip:a", - "end_id": "ip:d", - "direction": "both", - "limit": 10, - } + plan = cstx.RecallPlan.FromString(retrieval.requests()) + assert len(plan.queries) == 2 + result = cstx.RagResult.FromString( + retrieval.complete((cstx.RecallResults()).SerializeToString()) ) - assert isinstance(paths, GraphCursor) - assert paths.kind == "paths" - assert paths.page(limit=10, page=1)["items"] == [ - {"node_ids": ["ip:a", "ip:b", "ip:d"]}, - {"node_ids": ["ip:a", "ip:c", "ip:d"]}, - ] - - with pytest.raises(ValueError): - value.graph.analyze({"name": "is_dag", "unexpected": True}) - + assert result is not None -def test_prefetched_cursor_page_is_invalidated_before_returning_stale_items(): - value = db() - value.graph.add_nodes([node("1.1.1.1"), node("2.2.2.2"), node("3.3.3.3")]) - cursor = value.graph.nodes(order="id_asc") - assert next(cursor)["id"] == "ip:1.1.1.1" - assert next(cursor)["id"] == "ip:2.2.2.2" - value.graph.add_nodes([node("4.4.4.4")]) - with pytest.raises(CSTXError) as error: - next(cursor) - assert error.value.code == "CURSOR_INVALIDATED" +def test_every_exported_binding_has_documentation() -> None: + """Every member the stub declares is documented on the live object. + The member list is read out of `_cstxpy.pyi` rather than restated here. + It used to be a hand-written tuple per class, and it drifted twice -- + `Extensions.export_contract` and `CSTXGraph.add_relationship` were both + absent, so neither was ever checked for a docstring. What makes reading + the stub sound is `python_stub_declares_every_binding_member` in + cstx-abi's `runtime_contract` test: it fails when the stub omits a member + the binding exposes, so the stub is the complete list by construction. + """ + stub = Path(cstxpy.__file__).with_name("_cstxpy.pyi") + tree = ast.parse(stub.read_text(encoding="utf-8"), filename=str(stub)) -def test_unchanged_edge_does_not_invalidate_live_cursor(): - value = db() - value.graph.add_nodes([node("1.1.1.1"), node("2.2.2.2"), node("3.3.3.3")]) - relation = edge("ip:1.1.1.1", "ip:2.2.2.2") - value.graph.add_edges([relation]) - cursor = value.graph.nodes() - next(cursor) - assert value.graph.add_edges([relation]) == 0 - - assert next(cursor)["id"] == "ip:2.2.2.2" - - -def test_edges_neighbors_and_direct_json(): - value = db() - value.graph.add_nodes([node("1.1.1.1"), node("2.2.2.2")]) - relation = edge("ip:1.1.1.1", "ip:2.2.2.2") - assert value.graph.add_edges([relation]) == 1 - assert value.graph.edge_count() == 1 - assert list(value.graph.edges())[0]["id"] == relation["id"] - assert list(value.graph.neighbors("ip:1.1.1.1"))[0]["id"] == "ip:2.2.2.2" - assert json.loads(value.graph._edges_json()) == list(value.graph.edges()) - assert json.loads(value.graph._neighbors_json("ip:1.1.1.1")) == list( - value.graph.neighbors("ip:1.1.1.1") - ) + assert inspect.getdoc(cstxpy.CSTXError) + checked = 0 + for node in tree.body: + if not isinstance(node, ast.ClassDef): + continue + api_type = getattr(cstxpy, node.name, None) + if api_type is None or node.name == "CSTXError": + continue + assert inspect.getdoc(api_type), node.name + for member in node.body: + if not isinstance(member, (ast.FunctionDef, ast.AsyncFunctionDef)): + continue + # `__init__` documentation belongs to the class for a pyclass, and + # `__exit__` is plumbing pyo3 generates no docstring for. + if member.name in {"__init__", "__enter__", "__exit__"}: + continue + attribute = getattr(api_type, member.name, None) + assert attribute is not None, f"{node.name}.{member.name} missing from binding" + assert inspect.getdoc(attribute), f"{node.name}.{member.name}" + checked += 1 + + # NodeFlags is pure Python and has no stub of its own. + for member in ("all_mask", "default_exclude_mask", "bit", "mask", "names"): + assert inspect.getdoc(getattr(NodeFlags, member)), f"NodeFlags.{member}" + + assert checked > 80, f"stub walk only reached {checked} members" + + +def test_type_stub_documents_every_exported_class_and_method() -> None: + stub = Path(cstxpy.__file__).with_name("_cstxpy.pyi") + tree = ast.parse(stub.read_text(encoding="utf-8"), filename=str(stub)) + for node in ast.walk(tree): + if isinstance(node, (ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef)): + assert ast.get_docstring(node), f"missing stub documentation: {node.name}" -def test_native_graph_semantics_own_lookup_context_and_relationship_identity(): - value = db() - first = node("2.2.2.2") - first["extras"] = {"name": "shared", "scope": "old"} - second = node("1.1.1.1") - second["extras"] = {"name": "shared"} - duplicate_value = node("3.3.3.3") - duplicate_value["value"] = "1.1.1.1" - value.graph.add_nodes([first, second, duplicate_value]) - - assert value.graph.find_node("ip:2.2.2.2")["id"] == "ip:2.2.2.2" - assert value.graph.find_node("1.1.1.1")["id"] == "ip:1.1.1.1" - assert value.graph.find_node("shared")["id"] == "ip:1.1.1.1" - assert ( - value.graph.patch_node_extras(["ip:2.2.2.2"], {"scope": "new", "run": "r1"}) - == 1 - ) - assert value.graph.node("ip:2.2.2.2")["extras"] == { - "name": "shared", - "scope": ["old", "new"], - "run": "r1", - } - - relation = value.graph.create_relationship( - "ip:1.1.1.1", - "ip:2.2.2.2", - "related", - ["test"], - {"weight": 1}, - "qualified", - ) - assert relation["id"] == ("relationship:ip:1.1.1.1:related:ip:2.2.2.2:qualified") - assert cstxpy.is_path_expression("ip -> ip") - assert cstxpy.is_path_expression('ip[country="CN"]') - - -def test_patch_node_extras_none_selects_all_nodes(): - value = db() - value.graph.add_nodes([node("1.1.1.1"), node("2.2.2.2")]) - - assert value.graph.patch_node_extras(None, {"task_ids": ["task-1"]}) == 2 - assert value.graph.node("ip:1.1.1.1")["extras"]["task_ids"] == ["task-1"] - assert value.graph.node("ip:2.2.2.2")["extras"]["task_ids"] == ["task-1"] - - -def test_native_graph_union_and_difference_are_deterministic(): - left = db() - right = db() - left.graph.add_nodes([node("1.1.1.1"), node("2.2.2.2")]) - right.graph.add_nodes([node("2.2.2.2"), node("3.3.3.3")]) - - union = left.graph.union(right.graph) - assert sorted(item["id"] for item in union.graph.nodes()) == [ - "ip:1.1.1.1", - "ip:2.2.2.2", - "ip:3.3.3.3", - ] - difference = left.graph.difference(right.graph) - assert [item["id"] for item in difference.graph.nodes()] == ["ip:1.1.1.1"] - assert list(difference.graph.edges()) == [] - - -def test_native_graph_merge_is_in_place_and_reports_exact_changes(): - target = db() - source = db() - first = node("1.1.1.1") - second = node("2.2.2.2") - first["sources"] = ["target"] - target.graph.add_nodes([first]) - merged_first = node("1.1.1.1") - merged_first["sources"] = ["source-a", "source-b"] - merged_first["extras"] = {"scope": "source"} - second["sources"] = ["source-b"] - source.graph.add_nodes([merged_first, second]) - relationship = edge(merged_first["id"], second["id"]) - relationship["sources"] = ["source-a", "source-b"] - relationship["attrs"] = {"confidence": 90} - source.graph.add_edges([relationship]) - - assert target.graph.merge(source.graph) == 3 - assert target.graph.node_count() == 2 - assert target.graph.edge_count() == 1 - assert source.graph.node_count() == 2 - assert source.graph.edge_count() == 1 - assert set(target.graph.node(first["id"])["sources"]) == { - "target", - "source-a", - "source-b", - } - merged_edge = target.graph.edge(relationship["id"]) - assert merged_edge["source_id"] == first["id"] - assert merged_edge["target_id"] == second["id"] - assert set(merged_edge["sources"]) == {"source-a", "source-b"} - assert merged_edge["attrs"] == {"confidence": 90} - assert target.last_change() == { - "added_node_ids": [second["id"]], - "updated_node_ids": [first["id"]], - "removed_node_ids": [], - "added_edge_ids": [relationship["id"]], - "updated_edge_ids": [], - "removed_edge_ids": [], - "reset": False, - } - assert target.graph.merge(target.graph) == 0 - - -def test_direct_dict_cursor_matches_cstx_json_for_all_column_types(): - value = CSTX(cursor_page_size=2) - value.schemas.register( - "mixed", - { - "properties": { - "name": {"type": "string"}, - "optional": {"type": "string"}, - "count": {"type": "integer"}, - "ratio": {"type": "number"}, - "active": {"type": "boolean"}, - "tags": {"type": "array", "items": {"type": "string"}}, - "ports": {"type": "array", "items": {"type": "integer"}}, - "details": {"type": "object"}, +def test_flag_declared_above_bit_six_round_trips_through_protobuf() -> None: + """An extension's flag at bit 40 survives the boundary, filter included. + + This is the regression the `uint64` mask exists for. `Node.flags` used to + be a seven-value enum, and the Python encoder derived its bit positions + from that enum, so a flag any extension declared above bit 6 was dropped + in silence -- written, accepted, and simply not there on read. The schema + contract has always said extensions own bits 0-55. + """ + import json + + document = { + "schema_version": 1, + "extension": "acme", + "nodes": { + "acme_asset": { + "message": "acme.Asset", + "value_field": "asset_id", + "identity": {"field": "asset_id"}, + "fields": [{"name": "asset_id", "number": 1, "type": "string"}], } }, - "name", - ) - item = { - "id": "mixed:one", - "type": "mixed", - "value": "one", - "model": { - "name": "one", - "optional": None, - "count": 7, - "ratio": 1.5, - "active": True, - "tags": ["a", "b"], - "ports": [80, 443], - "details": {"nested": [1, 2]}, - }, - "sources": ["test"], - "extras": {"scope": "unit"}, + "flags": {"quarantined": {"bit": 40, "default_exclude": True}}, } - value.graph.add_nodes([item]) - - assert list(value.graph.nodes()) == json.loads(value.graph._nodes_json()) - + high = 1 << 40 -def test_repo_checkout_and_close(): - value = db() - value.graph.add_nodes([node("1.1.1.1")]) - commit = value.repo.commit("initial") - value.graph.add_nodes([node("2.2.2.2")]) - value.repo.checkout(commit["id"], force=True) - assert value.graph.node("ip:1.1.1.1")["id"] == "ip:1.1.1.1" - assert value.graph.node_count() == 1 - value.close() - with pytest.raises(CSTXError) as error: - value.graph.node_count() - assert error.value.code == "NOT_INITIALIZED" - - -def test_repo_prepare_uses_bytes_for_object_transport(): - value = db() - value.graph.add_nodes([node("1.1.1.1")]) + db = cstxpy.CSTX("flag-bit-40", 1024) try: - commit, index_root, objects = value.repo._prepare( - "transport", "main", None, {}, 1 - ) - assert isinstance(commit, dict) - assert isinstance(index_root, bytes) - assert objects - assert all( - isinstance(object_id, bytes) and isinstance(envelope, bytes) - for object_id, _kind, envelope in objects + contract = cstx.ExtensionContract(contract_version=1) + definition = contract.extensions["acme"] + definition.name = "acme" + definition.schema = json.dumps(document) + db.extensions.register(contract.SerializeToString()) + + node = cstx.Node( + id="acme_asset:a1", + flags_mask=high, + value=cstx.EntityValue( + node_type="acme_asset", + fields=[cstx.EntityField(name="asset_id", text="a1")], + ), ) - finally: - value.repo._discard() - value.close() - - -def test_repo_stats_is_one_time_range_delta(): - value = db() - value.graph.add_nodes([node("1.1.1.1")]) - value.repo.commit("first", timestamp=100) - value.graph.add_nodes([node("2.2.2.2")]) - value.repo.commit("second", timestamp=200) - - assert value.repo.delta(start_timestamp=100, end_timestamp=199)["added_nodes"] == 1 - assert value.repo.delta(start_timestamp=101, end_timestamp=200)["added_nodes"] == 1 - assert "bucket" not in inspect.signature(value.repo.delta).parameters - with pytest.raises(CSTXError, match="start_timestamp"): - value.repo.delta(start_timestamp=201, end_timestamp=200) + db.graph.add_nodes(cstx.Graph(nodes=[node]).SerializeToString()) + stored = cstx.Node.FromString(db.graph.node("acme_asset:a1")) + assert stored.flags_mask == high -def test_not_found_has_stable_error_context(): - value = db() - with pytest.raises(CSTXError) as error: - value.graph.node("ip:missing") - assert error.value.code == "NOT_FOUND" - assert error.value.operation == "graph.node" - - -def test_repository_errors_have_stable_context(): - value = db() - - with pytest.raises(CSTXError) as error: - value.repo.checkout("missing") - assert error.value.code == "NOT_FOUND" - assert error.value.operation == "repo.checkout" - - -def test_every_supported_api_has_runtime_documentation(): - """Keep newly exported APIs explainable through Python help(), not only source.""" - public_members = { - CSTX: ( - "schemas", - "graph", - "repo", - "closed", - "project_id", - "close", - "last_change", - "__enter__", - "__exit__", - ), - Schemas: ( - "register", - "register_join_rule", - "import_schema", - "export_schema", - "contains", - "get", - "list", - "load_plugin", - "load_all_plugins", - "available_plugins", - "plugin_artifacts", - "has_native_artifact", - "anchor_concepts", - ), - CSTXGraph: ( - "rag", - "analyze", - "add_nodes", - "add_edges", - "replace_nodes", - "delete_nodes", - "delete_edges", - "node", - "edge", - "create_relationship", - "union", - "merge", - "difference", - "contains", - "node_count", - "edge_count", - "stats", - "nodes", - "nodes_page", - "edges", - "neighbors", - "query", - "ingest_native", - "find_node", - "patch_node_extras", - "node_types", - "link", - "update_node_flags", - "analyze", - "degree", - "subgraph", - "query_subgraph", - "induced_subgraph", - "filter", - "filter_with_reasons", - "find_anchors", - "elevate", - ), - Repository: ( - "resolve", - "head", - "checkout", - "commit", - "diff", - "log", - "history", - "branch", - "merge", - "stat", - "delta", - ), - GraphCursor: ( - "kind", - "page", - "closed", - "close", - "__iter__", - "__next__", - "__enter__", - "__exit__", - ), - NodeFlags: ("all_mask", "default_exclude_mask"), - } - - assert inspect.getdoc(CSTXError) - for api_type, members in public_members.items(): - assert inspect.getdoc(api_type), api_type.__name__ - for member in members: - assert inspect.getdoc(getattr(api_type, member)), ( - f"{api_type.__name__}.{member}" - ) - discovered = { - name - for name, value in api_type.__dict__.items() - if not name.startswith("_") - and ( - callable(getattr(api_type, name, None)) - or inspect.isdatadescriptor(value) - ) - } - assert discovered <= set(members), ( - f"undocumented API added to {api_type.__name__}: {discovered - set(members)}" + cursor = db.graph.nodes( + (cstx.NodeFilter(flags_any_mask=high)).SerializeToString(), + (cstx.QueryWindow(page=1)).SerializeToString(), ) - - -def test_type_stub_documents_every_exported_class_and_method(): - """IDE-visible signatures must carry the same explanation as runtime help().""" - stub = Path(cstxpy.__file__).with_name("_cstxpy.pyi") - tree = ast.parse(stub.read_text(encoding="utf-8"), filename=str(stub)) - for node in ast.walk(tree): - if isinstance(node, (ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef)): - assert ast.get_docstring(node), f"missing stub documentation: {node.name}" + page = cstx.GraphResultPage.FromString(cursor.page(limit=10, page=1)) + assert [row.id for row in page.nodes.values] == ["acme_asset:a1"] + + # And a bit nobody declared passes through untouched: the registry + # decides what a bit means, so the boundary has nothing to reject. + undeclared = cstx.Node( + id="acme_asset:a2", + flags_mask=1 << 55, + value=cstx.EntityValue( + node_type="acme_asset", + fields=[cstx.EntityField(name="asset_id", text="a2")], + ), + ) + db.graph.add_nodes(cstx.Graph(nodes=[undeclared]).SerializeToString()) + assert cstx.Node.FromString(db.graph.node("acme_asset:a2")).flags_mask == 1 << 55 + finally: + db.close() diff --git a/python/tests/test_json_native.py b/python/tests/test_json_native.py deleted file mode 100644 index 1e4f9fd..0000000 --- a/python/tests/test_json_native.py +++ /dev/null @@ -1,59 +0,0 @@ -import json - -import pytest - -from cstxpy import CSTX, CSTXError - - -SCHEMA = {"properties": {"ip": {"type": "string"}}} - - -def node(value: str) -> dict: - return { - "id": f"ip:{value}", - "type": "ip", - "value": value, - "model": {"ip": value}, - "sources": ["json"], - "extras": {}, - } - - -def db() -> CSTX: - value = CSTX() - value.schemas.register("ip", SCHEMA, "ip") - return value - - -def test_json_batch_and_direct_nodes_match_native_cursor(): - value = db() - nodes = [node("1.1.1.1"), node("2.2.2.2")] - assert value.graph._add_nodes_json(json.dumps(nodes).encode()) == 2 - assert json.loads(value.graph._nodes_json()) == list(value.graph.nodes()) - - -def test_json_edges_query_neighbors_and_snapshot(): - value = db() - value.graph.add_nodes([node("1.1.1.1"), node("2.2.2.2")]) - relation = { - "id": "relationship:ip:1.1.1.1:related:ip:2.2.2.2", - "source_id": "ip:1.1.1.1", - "target_id": "ip:2.2.2.2", - "relation_type": "related", - "sources": ["json"], - "attrs": {}, - } - assert value.graph._add_edges_json(json.dumps([relation]).encode()) == 1 - assert json.loads(value.graph._edges_json()) == list(value.graph.edges()) - assert json.loads(value.graph._neighbors_json("ip:1.1.1.1")) == list( - value.graph.neighbors("ip:1.1.1.1") - ) - assert json.loads(value.graph._query_json("ip")) == list(value.graph.query("ip")) - - -def test_invalid_batch_is_atomic(): - value = db() - bad = [node("1.1.1.1"), {**node("2.2.2.2"), "model": []}] - with pytest.raises(CSTXError): - value.graph._add_nodes_json(json.dumps(bad).encode()) - assert value.graph.node_count() == 0 diff --git a/python/tests/test_proto_schema_feasibility.py b/python/tests/test_proto_schema_feasibility.py new file mode 100644 index 0000000..52b2129 --- /dev/null +++ b/python/tests/test_proto_schema_feasibility.py @@ -0,0 +1,100 @@ +"""The transport messages exercise every schema feature at the wire edge.""" + +from cstxpy.proto import cstx_pb2 as cstx +from google.protobuf.json_format import MessageToDict, ParseDict +from google.protobuf.struct_pb2 import Struct + + +def test_retired_payload_surface_is_absent() -> None: + assert not hasattr(cstx, "PayloadFormat") + assert "payload_format" not in cstx.RuntimeConfig.DESCRIPTOR.fields_by_name + assert "entity" not in cstx.Node.DESCRIPTOR.fields_by_name + assert "relation" not in cstx.Relationship.DESCRIPTOR.fields_by_name + + +def test_graph_page_oneofs_optional_map_repeated_and_enum_round_trip() -> None: + node = cstx.Node( + id="app:app-1", + value=cstx.EntityValue( + node_type="app", + fields=[ + cstx.EntityField(name="app_id", text="app-1"), + cstx.EntityField(name="frameworks", list=cstx.StringList(values=["react", "nginx"])), + cstx.EntityField(name="status_code", number=200), + cstx.EntityField(name="url", text="https://example.test"), + ], + ), + sources=["fixture", "scanner"], + # easm declares `threat_present` at bit 4 and `internal` at bit 6. + flags_mask=(1 << 4) | (1 << 6), + annotations=ParseDict( + {"nested": {"enabled": True}, "labels": ["a", "b"]}, Struct() + ), + ) + page = cstx.GraphResultPage( + page=2, + limit=10, + total=11, + has_next=True, + nodes=cstx.NodePage(values=[node]), + query=cstx.QuerySummary(nodes_by_type={"app": 11}), + ) + + encoded = (page).SerializeToString() + decoded = cstx.GraphResultPage.FromString(encoded) + result_kind = decoded.WhichOneof("result") + summary_kind = decoded.WhichOneof("summary") + + assert result_kind == "nodes" + assert summary_kind == "query" + assert decoded.nodes.values[0].flags_mask == (1 << 4) | (1 << 6) + assert dict(decoded.query.nodes_by_type) == {"app": 11} + annotations = MessageToDict( + decoded.nodes.values[0].annotations, preserving_proto_field_name=True + ) + assert annotations["nested"]["enabled"] is True + carried = {field.name: field for field in decoded.nodes.values[0].value.fields} + assert carried["url"].text == "https://example.test" + assert list(carried["frameworks"].list.values) == ["react", "nginx"] + assert carried["status_code"].number == 200 + # Message equality, not byte equality: this page carries map fields + # (`nodes_by_type`, and the Struct's own), and protobuf does not promise a + # stable order for those. Round-tripping the message is the claim; making + # it about bytes would be a claim the format does not support. + assert cstx.GraphResultPage.FromString(encoded) == decoded + assert cstx.GraphResultPage.FromString( + (decoded).SerializeToString() + ) == decoded + + +def test_absence_and_zero_are_distinguishable_in_a_payload() -> None: + """A payload says which fields the producer sent, not which are non-zero. + + proto3 gives a scalar no presence, which is why a generated per-type message + needed `optional` on every field that could legitimately be zero. A payload + names its fields, so a field the producer set to zero is in the list and a + field it never set is not — the distinction is structural. + """ + unset = cstx.EntityValue( + node_type="app", fields=[cstx.EntityField(name="app_id", text="app-2")] + ) + zero = cstx.EntityValue( + node_type="app", + fields=[ + cstx.EntityField(name="app_id", text="app-2"), + cstx.EntityField(name="status_code", number=0), + ], + ) + + assert [field.name for field in unset.fields] == ["app_id"] + assert [field.name for field in zero.fields] == ["app_id", "status_code"] + restored = cstx.EntityValue.FromString((zero).SerializeToString()) + assert restored.fields[1].WhichOneof("value") == "number" + assert restored.fields[1].number == 0 + + # Field 99 (varint) is unknown to EntityValue. The parser must skip it while + # preserving every field it does know, which is what keeps a payload written + # by a newer build readable by an older one. + decoded = cstx.EntityValue.FromString((zero).SerializeToString() + b"\x98\x06\x01") + assert decoded.node_type == "app" + assert [field.name for field in decoded.fields] == ["app_id", "status_code"] diff --git a/python/tests/test_protobuf_boundary.py b/python/tests/test_protobuf_boundary.py new file mode 100644 index 0000000..dafde93 --- /dev/null +++ b/python/tests/test_protobuf_boundary.py @@ -0,0 +1,68 @@ +"""The generated core messages are the complete protobuf boundary. + +Plugin structure is carried by the registered schema document and by the +schema-named ``EntityValue`` fields. No generated plugin message or +``google.protobuf.Any`` participates in these round trips. +""" + +import cstxpy +from cstxpy.proto import cstx_pb2 as cstx + + +def _ip_graph(value: str) -> bytes: + node = cstx.Node( + id=f"ip:{value}", + sources=["test"], + value=cstx.EntityValue( + node_type="ip", + fields=[cstx.EntityField(name="ip", text=value)], + ), + ) + return cstx.Graph(nodes=[node]).SerializeToString() + + +def test_generated_messages_are_the_wire_contract() -> None: + payload = cstx.ParserPayload( + plugin="easm", + artifact="gogo", + data=b'{"ip":"1.1.1.1"}', + content_type="application/json", + ) + + decoded = cstx.ParserPayload.FromString(payload.SerializeToString()) + + assert decoded.plugin == "easm" + assert decoded.artifact == "gogo" + assert decoded.data == b'{"ip":"1.1.1.1"}' + assert decoded.content_type == "application/json" + + +def test_python_runtime_reads_the_schema_named_payload() -> None: + runtime = cstxpy.CSTX() + runtime.extensions.enable("easm") + runtime.graph.add_nodes(_ip_graph("typed")) + + node = cstx.Node.FromString(runtime.graph.node("ip:typed")) + fields = {field.name: field for field in node.value.fields} + + assert node.value.node_type == "ip" + assert fields["ip"].text == "typed" + + +def test_python_runtime_exposes_typed_graph_stats() -> None: + runtime = cstxpy.CSTX() + runtime.extensions.enable("easm") + runtime.graph.add_nodes(_ip_graph("stats")) + + stats = cstx.GraphStats.FromString(runtime.graph.stats()) + + assert stats.nodes_by_type["ip"] == 1 + + +def test_python_runtime_exposes_anchor_catalog_proto() -> None: + runtime = cstxpy.CSTX() + runtime.extensions.enable("easm") + + catalog = cstx.GraphAnchorCatalog.FromString(runtime.graph.find_anchors("threat")) + + assert catalog.anchors == [] diff --git a/python/tests/test_runtime_schema.py b/python/tests/test_runtime_schema.py new file mode 100644 index 0000000..cffa13c --- /dev/null +++ b/python/tests/test_runtime_schema.py @@ -0,0 +1,428 @@ +"""The runtime schema is the only structure contract, and it is the same one +for a built-in extension and for one registered at runtime. + +These tests pin the two properties that make that true: + +* every lookup a caller can make is answered from the schema, not from a + generated per-extension lookup table or a protobuf descriptor; +* an extension that registers a schema at runtime gets identical treatment — + same registry, same derived pydantic bases, same queries. +""" + +import json +from pathlib import Path + +import pytest +from cstxpy import model as cstx_model +from cstxpy import schema as cstx_schema +from cstxpy.schema import ExtensionSchema, NodeSchema, SchemaRegistry +from pydantic import BaseModel + +SCHEMA_DIR = Path(cstx_schema.__file__).resolve().parent / "schemas" + + +@pytest.fixture +def easm_schema() -> ExtensionSchema: + schema = cstx_schema.registry.extension("easm") + assert schema is not None, "the built-in EASM schema ships with cstxpy" + return schema + + +# ── the schema artifact itself ── + + +def test_bundled_schema_is_loaded_for_every_shipped_extension(): + shipped = {path.name[: -len(".schema.json")] for path in SCHEMA_DIR.glob("*.schema.json")} + assert shipped, "at least the built-in EASM schema must ship" + assert shipped <= set(cstx_schema.registry.extensions()) + + +def test_schema_describes_identity_and_columns(easm_schema): + subdomain = easm_schema.nodes["subdomain"] + assert subdomain.message == "easm.Subdomain" + assert subdomain.type_url == "type.googleapis.com/easm.Subdomain" + assert subdomain.identity_field == "host" + assert subdomain.identity_format is None + + host = subdomain.field("host") + assert host is not None + assert (host.number, host.type, host.repeated, host.semantic) == (1, "string", False, False) + + a_records = subdomain.field("a") + assert a_records is not None and a_records.repeated + + +def test_schema_carries_composite_identity(easm_schema): + """A JSON-Schema style contract cannot express this; the schema can.""" + port = easm_schema.nodes["port"] + assert port.identity_format == "{ip}:{port}" + assert port.identity_field is None + + +def test_unsupported_schema_version_is_rejected(): + with pytest.raises(ValueError, match="unsupported schema_version"): + ExtensionSchema.parse({"schema_version": 999, "extension": "x"}) + + +# ── derived pydantic bases ── + + +def test_derived_base_matches_the_schema_field_for_field(easm_schema): + for node_type, node in easm_schema.nodes.items(): + base = cstx_model.base_model(node_type) + assert issubclass(base, BaseModel) + assert set(base.model_fields) == {field.name for field in node.fields} + for field in node.fields: + info = base.model_fields[field.name] + required = not field.optional and not field.repeated + assert info.is_required() is required, f"{node_type}.{field.name}" + + +def test_derived_base_keeps_proto3_zero_value_semantics(): + """A scalar without presence is always populated; only repeated fields + distinguish absent from empty.""" + app = cstx_model.base_model("app")(app_id="https://a/") + assert app.url == "" + assert app.status_code == 0 + assert app.frameworks is None + + +def test_derived_base_accepts_unknown_fields(): + domain = cstx_model.base_model("domain")(host="a.com", scanner_tag="x") + assert domain.model_dump()["scanner_tag"] == "x" + + +def test_base_attribute_access_matches_message_name(easm_schema): + assert cstx_model.SubdomainBase is cstx_model.base_model("subdomain") + with pytest.raises(AttributeError): + _ = cstx_model.NoSuchThingBase + + +# ── a runtime-registered extension is not a second-class citizen ── + + +THIRD_PARTY = { + "schema_version": 1, + "extension": "acme", + "nodes": { + "acme_asset": { + "message": "acme.Asset", + "value_field": "asset_id", + "identity": {"field": "asset_id"}, + "fields": [ + {"name": "asset_id", "number": 1, "type": "string", "semantic": False}, + {"name": "owner", "number": 2, "type": "string", "optional": True}, + {"name": "score", "number": 3, "type": "int64", "optional": True}, + {"name": "tags", "number": 4, "type": "string", "repeated": True}, + ], + } + }, + "relations": {"acme_owns": {"message": "acme.Owns"}}, +} + + +@pytest.fixture +def isolated_registry() -> SchemaRegistry: + """A private view so cross-test state cannot leak into the global one. + + `_install` rather than a public entry: the view has no registration API, + because registering is the core's decision and this class only mirrors it. + """ + registry = SchemaRegistry() + registry._install(ExtensionSchema.parse(THIRD_PARTY)) + return registry + + +def test_runtime_extension_answers_every_builtin_query(isolated_registry): + assert isolated_registry.node_type_url("acme_asset") == "type.googleapis.com/acme.Asset" + assert isolated_registry.node_type_from_url("type.googleapis.com/acme.Asset") == "acme_asset" + assert isolated_registry.relation_type_url("acme_owns") == "type.googleapis.com/acme.Owns" + assert isolated_registry.relation_type_from_url("type.googleapis.com/acme.Owns") == "acme_owns" + + +def test_runtime_schema_carries_no_export_format_metadata(): + """The runtime schema describes columns and identity — nothing else. + + STIX spellings used to ride along here; they belong to the exporter that + needs them, not to the contract every extension has to satisfy. + """ + assert "stix_type" not in set(NodeSchema.model_fields) + assert not hasattr(cstx_schema, "stix_type_for") + assert not hasattr(cstx_schema, "node_type_from_stix") + assert not hasattr(SchemaRegistry, "stix_type_for") + for path in SCHEMA_DIR.glob("*.schema.json"): + assert "stix" not in path.read_text(encoding="utf-8").lower(), path + + +def register(document: dict) -> "cstxpy.CSTX": + """Declare a type the one way a caller can: through a runtime. + + The core validates and accepts, then the view is refreshed from what the + core holds. `cstxpy.schema` has no registration entry of its own — these + tests used to reach for one, which is exactly the second declaration path + the boundary is supposed to have removed. + """ + import cstxpy + from cstxpy.proto import cstx_pb2 as cstx_proto + + runtime = cstxpy.CSTX() + contract = cstx_proto.ExtensionContract(contract_version=1) + definition = contract.extensions[document["extension"]] + definition.name = document["extension"] + definition.schema = json.dumps(document) + runtime.extensions.register(contract.SerializeToString()) + cstx_schema.project( + cstx_proto.ExtensionContract.FromString(runtime.extensions.export_contract()) + ) + return runtime + + +def test_runtime_extension_gets_the_same_derived_base(): + """Registering a schema is the whole story: no codegen step, no descriptor.""" + runtime = register(THIRD_PARTY) + try: + base = cstx_model.base_model("acme_asset") + assert base.__name__ == "AssetBase" + assert set(base.model_fields) == {"asset_id", "owner", "score", "tags"} + assert base.model_fields["asset_id"].is_required() + assert not base.model_fields["owner"].is_required() + + instance = base(asset_id="a-1", owner="ops", score=7, tags=["x"]) + assert instance.model_dump() == { + "asset_id": "a-1", + "owner": "ops", + "score": 7, + "tags": ["x"], + } + # reached through the same attribute protocol as the built-in bases + assert cstx_model.AssetBase is base + finally: + runtime.close() + cstx_schema.registry._remove("acme") + cstx_model._cache.pop("acme_asset", None) # noqa: SLF001 + cstx_model._by_class_name.pop("AssetBase", None) + + +def test_rebuilt_base_follows_a_replaced_schema(): + """Re-registering an extension must not keep serving the stale base.""" + runtime = register(THIRD_PARTY) + try: + first = cstx_model.base_model("acme_asset") + + changed = json.loads(json.dumps(THIRD_PARTY)) + changed["nodes"]["acme_asset"]["fields"].append( + {"name": "region", "number": 5, "type": "string", "optional": True} + ) + register(changed).close() + second = cstx_model.base_model("acme_asset") + + assert second is not first + assert "region" in second.model_fields + finally: + runtime.close() + cstx_schema.registry._remove("acme") + cstx_model._cache.pop("acme_asset", None) + cstx_model._by_class_name.pop("AssetBase", None) + + +def test_builtin_and_runtime_extensions_share_one_registry(isolated_registry, easm_schema): + """Nothing in the lookup path branches on where a node type came from.""" + both = SchemaRegistry() + both._install(easm_schema) + both._install(ExtensionSchema.parse(THIRD_PARTY)) + + assert set(both.extensions()) == {"easm", "acme"} + for node_type in ("subdomain", "acme_asset"): + node = both.node(node_type) + assert node is not None + assert both.node_type_url(node_type) == node.type_url + assert both.node_type_from_url(node.type_url) == node_type + + +# ── the core decides; this module mirrors ── + + +def test_the_view_has_no_registration_entry(): + """Declaring a type is `runtime.extensions.register`, and only that. + + A public `register`/`load_schema` here was a second declaration entry: it + could put a type into Python that the core had never accepted, and it + carried its own opinion about conflicts and ambiguous names — an opinion + that disagreed with the core's. + """ + assert not hasattr(cstx_schema.registry, "register") + for retired in ("SchemaRegistry", "load_schema", "load_bundled"): + assert retired not in cstx_schema.__all__ + + +def test_a_conflict_the_core_refuses_leaves_no_half_in_the_view(): + """Two extensions claiming one node type is refused, and refused wholly.""" + import cstxpy + from cstxpy.proto import cstx_pb2 as cstx_proto + + def contract(extension: str) -> bytes: + document = dict(THIRD_PARTY, extension=extension) + message = cstx_proto.ExtensionContract(contract_version=1) + definition = message.extensions[extension] + definition.name = extension + definition.schema = json.dumps(document) + return message.SerializeToString() + + runtime = cstxpy.CSTX() + try: + runtime.extensions.register(contract("acme")) + with pytest.raises(cstxpy.CSTXError): + # `squatter` declares `acme_asset` too. The core owns that call. + runtime.extensions.register(contract("squatter")) + cstx_schema.project( + cstx_proto.ExtensionContract.FromString( + runtime.extensions.export_contract() + ) + ) + assert "squatter" not in cstx_schema.registry.extensions() + assert cstx_schema.registry.node("acme_asset") is not None + finally: + runtime.close() + cstx_schema.registry._remove("acme") + cstx_schema.registry._remove("squatter") + + +def test_an_ambiguous_short_message_name_resolves_to_nothing(): + """Two packages spelling one message the same way has no answer. + + Picking whichever landed first is an answer, and it is the wrong one half + the time. The core returns nothing here; so does this. + """ + view = SchemaRegistry() + view._install(ExtensionSchema.parse(dict(THIRD_PARTY, extension="one"))) + view._install( + ExtensionSchema.parse( + { + "schema_version": 1, + "extension": "two", + "nodes": { + "other_asset": { + "message": "other.Asset", + "value_field": "asset_id", + "identity": {"field": "asset_id"}, + "fields": [ + {"name": "asset_id", "number": 1, "type": "string"} + ], + } + }, + "relations": {}, + } + ) + ) + # Fully qualified still answers; the bare name no longer does. + assert view.node_type_from_url("type.googleapis.com/acme.Asset") == "acme_asset" + assert view.node_type_from_url("type.googleapis.com/other.Asset") == "other_asset" + assert view.node_type_from_url("Asset") is None + + +# ── the derived annotation and the column it lands in ── + +# One sample per type a schema document may declare. `ENCODABLE_PROTO_TYPES` +# in `cstx-graph/src/schema_def.rs` is the same list; a type added there and +# not here simply is not covered, which the first assertion below catches. +ENCODABLE_SAMPLES = { + "string": "probe-value", + "bool": True, + "int64": 7, + "int32": 7, + "uint32": 7, + "sint64": 7, + "sint32": 7, + "double": 1.5, +} + + +def _probe_document() -> dict: + fields = [{"name": "key", "number": 1, "type": "string", "semantic": False}] + for index, proto_type in enumerate(sorted(ENCODABLE_SAMPLES), start=2): + fields.append( + { + "name": f"f_{proto_type}", + "number": index, + "type": proto_type, + "optional": True, + "semantic": False, + } + ) + return { + "schema_version": 1, + "extension": "probe", + "nodes": { + "probe_node": { + "message": "probe.Node", + "value_field": "key", + "identity": {"field": "key"}, + "fields": fields, + } + }, + } + + +def _entity_field(name: str, value): + """Pick the payload branch from the Python value, as every SDK does. + + `cstx/core/values.py` and `sdk/go/values.go` choose the same way: the + branch follows the value's own type and the runtime checks it against the + column the schema declared. That is precisely why the annotation this + module derives has to agree with `FieldSchema::column_type` — a field + built as the wrong Python type picks the wrong branch and the write is + refused. bool before int: in Python `bool` is a subclass of `int`. + """ + from cstxpy.proto import cstx_pb2 as cstx_proto + + field = cstx_proto.EntityField(name=name) + if isinstance(value, bool): + field.flag = value + elif isinstance(value, int): + field.number = value + elif isinstance(value, float): + field.real = value + else: + field.text = str(value) + return field + + +def test_derived_annotation_survives_the_column_it_lands_in(): + """The derived model must type a field as what its column stores. + + `python_type` is a second copy of a decision Rust owns + (`FieldSchema::column_type`), written in a different vocabulary, and Rust + pins its own three copies together (`every_encodable_field_type_round_trips + _through_its_column`). This copy sat outside that net, which is how + `int32` / `uint32` / `sint32` / `double` came to be built as strings the + core then refused. So: build the value through the derived base, send it + the way an SDK does, read it back. + """ + from cstxpy.proto import cstx_pb2 as cstx_proto + + document = _probe_document() + runtime = register(document) + try: + base = cstx_model.base_model("probe_node") + declared = {f"f_{name}" for name in ENCODABLE_SAMPLES} + assert declared <= set(base.model_fields) + + instance = base(key="k-1", **{f"f_{k}": v for k, v in ENCODABLE_SAMPLES.items()}) + payload = instance.model_dump() + + value = cstx_proto.EntityValue(node_type="probe_node") + value.fields.extend( + _entity_field(name, payload[name]) for name in sorted(payload) + ) + graph = cstx_proto.Graph(nodes=[cstx_proto.Node(id="probe_node:k-1", value=value)]) + runtime.graph.add_nodes(graph.SerializeToString()) + + stored = cstx_proto.Node.FromString(runtime.graph.node("probe_node:k-1")) + read_back = { + field.name: getattr(field, field.WhichOneof("value")) + for field in stored.value.fields + } + for proto_type, sample in ENCODABLE_SAMPLES.items(): + assert read_back[f"f_{proto_type}"] == sample, proto_type + finally: + runtime.close() diff --git a/ts/wasm/cstx_wasm.d.ts b/ts/wasm/cstx_wasm.d.ts index 414f00c..fbc2776 100644 --- a/ts/wasm/cstx_wasm.d.ts +++ b/ts/wasm/cstx_wasm.d.ts @@ -7,39 +7,46 @@ export class CSTX { close(): void; constructor(config?: any | null); readonly closed: boolean; + readonly extensions: Extensions; readonly graph: Graph; readonly repository: Repository; - readonly schemas: Schemas; +} + +export class Extensions { + private constructor(); + free(): void; + [Symbol.dispose](): void; + anchorConcepts(): any; + contains(node_type: string): boolean; + enable(name: string): void; + info(name: string): any; + list(): any; + parsesArtifact(artifact: string): boolean; + register(contract: any): void; + schema(node_type: string): any; + schemas(): any; } export class Graph { private constructor(); free(): void; [Symbol.dispose](): void; - addEdge(edge: any): bigint; - addEdges(edges: any): bigint; - addEdgesJson(data: Uint8Array): bigint; addNode(node: any): bigint; addNodes(nodes: any): bigint; - addNodesJson(data: Uint8Array): bigint; + addRelationship(source_id: string, target_id: string, relation: string, sources?: string[] | null, model?: any | null, identity_key?: string | null): any; + addRelationships(relationships: any): bigint; /** * Execute the single typed graph algorithm atom. */ analyze(algorithm: any, selection?: string | null): any; contains(node_id: string): boolean; - createRelationship(source_id: string, target_id: string, relation: string, sources?: string[] | null, attrs?: any | null, identity_key?: string | null): any; degree(node_id: string, direction?: string | null): bigint; difference(other: Graph, node_type?: string | null): CSTX; - edge(edge_id: string): any; - edgeCount(): bigint; - edges(options?: any | null): GraphCursor; elevate(concept_name: string): CSTX; filter(exclude_mask?: bigint | null, include_mask?: bigint | null, excluded_ids?: string[] | null): CSTX; findAnchors(concept_name: string): any; findNode(identifier: string): any; inducedSubgraph(node_ids: string[], edge_ids?: string[] | null): CSTX; - ingest(source: string, data: Uint8Array): bigint; - ingestNative(plugin: string, artifact: string, data: Uint8Array): any; link(node_ids: string[], data_source: string): any; merge(other: Graph): bigint; neighbors(node_id: string, direction?: string | null, options?: any | null): GraphCursor; @@ -47,10 +54,12 @@ export class Graph { nodeCount(): bigint; nodeTypes(): any; nodes(options?: any | null): GraphCursor; - nodesPage(node_type?: string | null, name_pattern?: string | null, exclude_mask?: bigint | null, include_mask?: bigint | null, limit?: number | null, page?: number | null): any; - patchNodeExtras(node_ids: string[] | null | undefined, patch: any): bigint; + patchNodeAnnotations(node_ids: string[] | null | undefined, patch: any): bigint; query(expression: string, options?: any | null): GraphCursor; querySubgraph(expression: string, limit?: number | null, page?: number | null, exclude_mask?: bigint | null, include_mask?: bigint | null): CSTX; + relationship(relationship_id: string): any; + relationshipCount(): bigint; + relationships(options?: any | null): GraphCursor; stats(selection?: string | null, exclude_mask?: bigint | null, include_mask?: bigint | null): any; subgraph(seed_ids?: string[] | null, depth?: number | null): CSTX; union(other: Graph): CSTX; @@ -88,25 +97,6 @@ export class Repository { stat(revision?: string | null, exclude_mask?: bigint | null, include_mask?: bigint | null): any; } -export class Schemas { - private constructor(); - free(): void; - [Symbol.dispose](): void; - anchorConcepts(): any; - availablePlugins(): any; - contains(node_type: string): boolean; - exportSchema(): any; - get(node_type: string): any; - hasNativeArtifact(artifact: string): boolean; - importSchema(schema: any): void; - list(): any; - loadAllPlugins(): void; - loadPlugin(name: string): void; - pluginArtifacts(name: string): any; - register(node_type: string, schema: any, value_field?: string | null): void; - registerJoinRule(rule: any): void; -} - export function version(): string; export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; @@ -115,36 +105,27 @@ export interface InitOutput { readonly memory: WebAssembly.Memory; readonly __wbg_cstx_free: (a: number, b: number) => void; readonly cstx_new: (a: number, b: number) => void; - readonly cstx_graph: (a: number) => number; + readonly cstx_extensions: (a: number) => number; readonly cstx_closed: (a: number) => number; readonly cstx_close: (a: number) => void; - readonly schemas_importSchema: (a: number, b: number, c: number) => void; - readonly schemas_exportSchema: (a: number, b: number) => void; - readonly schemas_register: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void; - readonly schemas_registerJoinRule: (a: number, b: number, c: number) => void; - readonly schemas_contains: (a: number, b: number, c: number, d: number) => void; - readonly schemas_get: (a: number, b: number, c: number, d: number) => void; - readonly schemas_list: (a: number, b: number) => void; - readonly schemas_loadPlugin: (a: number, b: number, c: number, d: number) => void; - readonly schemas_loadAllPlugins: (a: number, b: number) => void; - readonly schemas_availablePlugins: (a: number, b: number) => void; - readonly schemas_pluginArtifacts: (a: number, b: number, c: number, d: number) => void; - readonly schemas_hasNativeArtifact: (a: number, b: number, c: number, d: number) => void; - readonly schemas_anchorConcepts: (a: number, b: number) => void; - readonly __wbg_graph_free: (a: number, b: number) => void; + readonly __wbg_extensions_free: (a: number, b: number) => void; + readonly extensions_register: (a: number, b: number, c: number) => void; + readonly extensions_enable: (a: number, b: number, c: number, d: number) => void; + readonly extensions_list: (a: number, b: number) => void; + readonly extensions_info: (a: number, b: number, c: number, d: number) => void; + readonly extensions_contains: (a: number, b: number, c: number, d: number) => void; + readonly extensions_schema: (a: number, b: number, c: number, d: number) => void; + readonly extensions_schemas: (a: number, b: number) => void; + readonly extensions_parsesArtifact: (a: number, b: number, c: number, d: number) => void; + readonly extensions_anchorConcepts: (a: number, b: number) => void; readonly graph_addNode: (a: number, b: number, c: number) => void; readonly graph_addNodes: (a: number, b: number, c: number) => void; - readonly graph_addEdge: (a: number, b: number, c: number) => void; - readonly graph_addEdges: (a: number, b: number, c: number) => void; - readonly graph_addNodesJson: (a: number, b: number, c: number, d: number) => void; - readonly graph_addEdgesJson: (a: number, b: number, c: number, d: number) => void; - readonly graph_ingest: (a: number, b: number, c: number, d: number, e: number, f: number) => void; - readonly graph_ingestNative: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => void; + readonly graph_addRelationships: (a: number, b: number, c: number) => void; readonly graph_node: (a: number, b: number, c: number, d: number) => void; - readonly graph_edge: (a: number, b: number, c: number, d: number) => void; + readonly graph_relationship: (a: number, b: number, c: number, d: number) => void; readonly graph_findNode: (a: number, b: number, c: number, d: number) => void; - readonly graph_patchNodeExtras: (a: number, b: number, c: number, d: number, e: number) => void; - readonly graph_createRelationship: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number) => void; + readonly graph_addRelationship: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number) => void; + readonly graph_patchNodeAnnotations: (a: number, b: number, c: number, d: number, e: number) => void; readonly graph_union: (a: number, b: number, c: number) => void; readonly graph_merge: (a: number, b: number, c: number) => void; readonly graph_difference: (a: number, b: number, c: number, d: number, e: number) => void; @@ -153,13 +134,12 @@ export interface InitOutput { readonly graph_updateNodeFlags: (a: number, b: number, c: number, d: number, e: number, f: bigint, g: number, h: bigint, i: number, j: bigint) => void; readonly graph_contains: (a: number, b: number, c: number, d: number) => void; readonly graph_nodeCount: (a: number, b: number) => void; - readonly graph_edgeCount: (a: number, b: number) => void; + readonly graph_relationshipCount: (a: number, b: number) => void; readonly graph_stats: (a: number, b: number, c: number, d: number, e: number, f: bigint, g: number, h: bigint) => void; readonly graph_degree: (a: number, b: number, c: number, d: number, e: number, f: number) => void; readonly graph_nodes: (a: number, b: number, c: number) => void; - readonly graph_edges: (a: number, b: number, c: number) => void; + readonly graph_relationships: (a: number, b: number, c: number) => void; readonly graph_neighbors: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void; - readonly graph_nodesPage: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: bigint, i: number, j: bigint, k: number, l: number) => void; readonly graph_query: (a: number, b: number, c: number, d: number, e: number) => void; readonly graph_analyze: (a: number, b: number, c: number, d: number, e: number) => void; readonly graph_subgraph: (a: number, b: number, c: number, d: number, e: number) => void; @@ -195,8 +175,8 @@ export interface InitOutput { readonly rust_zstd_wasm_shim_memmove: (a: number, b: number, c: number) => number; readonly rust_zstd_wasm_shim_memset: (a: number, b: number, c: number) => number; readonly __wbg_repository_free: (a: number, b: number) => void; - readonly __wbg_schemas_free: (a: number, b: number) => void; - readonly cstx_schemas: (a: number) => number; + readonly __wbg_graph_free: (a: number, b: number) => void; + readonly cstx_graph: (a: number) => number; readonly cstx_repository: (a: number) => number; readonly __wbindgen_export: (a: number, b: number) => number; readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number; diff --git a/ts/wasm/cstx_wasm.js b/ts/wasm/cstx_wasm.js index b72729d..4c6ad1b 100644 --- a/ts/wasm/cstx_wasm.js +++ b/ts/wasm/cstx_wasm.js @@ -27,6 +27,13 @@ export class CSTX { const ret = wasm.cstx_closed(this.__wbg_ptr); return ret !== 0; } + /** + * @returns {Extensions} + */ + get extensions() { + const ret = wasm.cstx_extensions(this.__wbg_ptr); + return Extensions.__wrap(ret); + } /** * @returns {Graph} */ @@ -61,163 +68,169 @@ export class CSTX { const ret = wasm.cstx_repository(this.__wbg_ptr); return Repository.__wrap(ret); } - /** - * @returns {Schemas} - */ - get schemas() { - const ret = wasm.cstx_schemas(this.__wbg_ptr); - return Schemas.__wrap(ret); - } } if (Symbol.dispose) CSTX.prototype[Symbol.dispose] = CSTX.prototype.free; -export class Graph { +export class Extensions { static __wrap(ptr) { - const obj = Object.create(Graph.prototype); + const obj = Object.create(Extensions.prototype); obj.__wbg_ptr = ptr; - GraphFinalization.register(obj, obj.__wbg_ptr, obj); + ExtensionsFinalization.register(obj, obj.__wbg_ptr, obj); return obj; } __destroy_into_raw() { const ptr = this.__wbg_ptr; this.__wbg_ptr = 0; - GraphFinalization.unregister(this); + ExtensionsFinalization.unregister(this); return ptr; } free() { const ptr = this.__destroy_into_raw(); - wasm.__wbg_graph_free(ptr, 0); + wasm.__wbg_extensions_free(ptr, 0); } /** - * @param {any} edge - * @returns {bigint} + * @returns {any} */ - addEdge(edge) { + anchorConcepts() { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.graph_addEdge(retptr, this.__wbg_ptr, addHeapObject(edge)); - var r0 = getDataViewMemory0().getBigInt64(retptr + 8 * 0, true); + wasm.extensions_anchorConcepts(retptr, this.__wbg_ptr); + var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); + var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); - var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true); - if (r3) { - throw takeObject(r2); + if (r2) { + throw takeObject(r1); } - return BigInt.asUintN(64, r0); + return takeObject(r0); } finally { wasm.__wbindgen_add_to_stack_pointer(16); } } /** - * @param {any} edges - * @returns {bigint} + * @param {string} node_type + * @returns {boolean} */ - addEdges(edges) { + contains(node_type) { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.graph_addEdges(retptr, this.__wbg_ptr, addHeapObject(edges)); - var r0 = getDataViewMemory0().getBigInt64(retptr + 8 * 0, true); + const ptr0 = passStringToWasm0(node_type, wasm.__wbindgen_export, wasm.__wbindgen_export2); + const len0 = WASM_VECTOR_LEN; + wasm.extensions_contains(retptr, this.__wbg_ptr, ptr0, len0); + var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); + var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); - var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true); - if (r3) { - throw takeObject(r2); + if (r2) { + throw takeObject(r1); } - return BigInt.asUintN(64, r0); + return r0 !== 0; } finally { wasm.__wbindgen_add_to_stack_pointer(16); } } /** - * @param {Uint8Array} data - * @returns {bigint} + * @param {string} name */ - addEdgesJson(data) { + enable(name) { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - const ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_export); + const ptr0 = passStringToWasm0(name, wasm.__wbindgen_export, wasm.__wbindgen_export2); const len0 = WASM_VECTOR_LEN; - wasm.graph_addEdgesJson(retptr, this.__wbg_ptr, ptr0, len0); - var r0 = getDataViewMemory0().getBigInt64(retptr + 8 * 0, true); - var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); - var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true); - if (r3) { - throw takeObject(r2); + wasm.extensions_enable(retptr, this.__wbg_ptr, ptr0, len0); + var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); + var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); + if (r1) { + throw takeObject(r0); } - return BigInt.asUintN(64, r0); } finally { wasm.__wbindgen_add_to_stack_pointer(16); } } /** - * @param {any} node - * @returns {bigint} + * @param {string} name + * @returns {any} */ - addNode(node) { + info(name) { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.graph_addNode(retptr, this.__wbg_ptr, addHeapObject(node)); - var r0 = getDataViewMemory0().getBigInt64(retptr + 8 * 0, true); + const ptr0 = passStringToWasm0(name, wasm.__wbindgen_export, wasm.__wbindgen_export2); + const len0 = WASM_VECTOR_LEN; + wasm.extensions_info(retptr, this.__wbg_ptr, ptr0, len0); + var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); + var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); - var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true); - if (r3) { - throw takeObject(r2); + if (r2) { + throw takeObject(r1); } - return BigInt.asUintN(64, r0); + return takeObject(r0); } finally { wasm.__wbindgen_add_to_stack_pointer(16); } } /** - * @param {any} nodes - * @returns {bigint} + * @returns {any} */ - addNodes(nodes) { + list() { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.graph_addNodes(retptr, this.__wbg_ptr, addHeapObject(nodes)); - var r0 = getDataViewMemory0().getBigInt64(retptr + 8 * 0, true); + wasm.extensions_list(retptr, this.__wbg_ptr); + var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); + var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); - var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true); - if (r3) { - throw takeObject(r2); + if (r2) { + throw takeObject(r1); } - return BigInt.asUintN(64, r0); + return takeObject(r0); } finally { wasm.__wbindgen_add_to_stack_pointer(16); } } /** - * @param {Uint8Array} data - * @returns {bigint} + * @param {string} artifact + * @returns {boolean} */ - addNodesJson(data) { + parsesArtifact(artifact) { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - const ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_export); + const ptr0 = passStringToWasm0(artifact, wasm.__wbindgen_export, wasm.__wbindgen_export2); const len0 = WASM_VECTOR_LEN; - wasm.graph_addNodesJson(retptr, this.__wbg_ptr, ptr0, len0); - var r0 = getDataViewMemory0().getBigInt64(retptr + 8 * 0, true); + wasm.extensions_parsesArtifact(retptr, this.__wbg_ptr, ptr0, len0); + var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); + var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); - var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true); - if (r3) { - throw takeObject(r2); + if (r2) { + throw takeObject(r1); } - return BigInt.asUintN(64, r0); + return r0 !== 0; } finally { wasm.__wbindgen_add_to_stack_pointer(16); } } /** - * Execute the single typed graph algorithm atom. - * @param {any} algorithm - * @param {string | null} [selection] + * @param {any} contract + */ + register(contract) { + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + wasm.extensions_register(retptr, this.__wbg_ptr, addHeapObject(contract)); + var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); + var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); + if (r1) { + throw takeObject(r0); + } + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + } + } + /** + * @param {string} node_type * @returns {any} */ - analyze(algorithm, selection) { + schema(node_type) { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - var ptr0 = isLikeNone(selection) ? 0 : passStringToWasm0(selection, wasm.__wbindgen_export, wasm.__wbindgen_export2); - var len0 = WASM_VECTOR_LEN; - wasm.graph_analyze(retptr, this.__wbg_ptr, addHeapObject(algorithm), ptr0, len0); + const ptr0 = passStringToWasm0(node_type, wasm.__wbindgen_export, wasm.__wbindgen_export2); + const len0 = WASM_VECTOR_LEN; + wasm.extensions_schema(retptr, this.__wbg_ptr, ptr0, len0); var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); @@ -230,22 +243,77 @@ export class Graph { } } /** - * @param {string} node_id - * @returns {boolean} + * @returns {any} */ - contains(node_id) { + schemas() { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - const ptr0 = passStringToWasm0(node_id, wasm.__wbindgen_export, wasm.__wbindgen_export2); - const len0 = WASM_VECTOR_LEN; - wasm.graph_contains(retptr, this.__wbg_ptr, ptr0, len0); + wasm.extensions_schemas(retptr, this.__wbg_ptr); var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); if (r2) { throw takeObject(r1); } - return r0 !== 0; + return takeObject(r0); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + } + } +} +if (Symbol.dispose) Extensions.prototype[Symbol.dispose] = Extensions.prototype.free; + +export class Graph { + static __wrap(ptr) { + const obj = Object.create(Graph.prototype); + obj.__wbg_ptr = ptr; + GraphFinalization.register(obj, obj.__wbg_ptr, obj); + return obj; + } + __destroy_into_raw() { + const ptr = this.__wbg_ptr; + this.__wbg_ptr = 0; + GraphFinalization.unregister(this); + return ptr; + } + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_graph_free(ptr, 0); + } + /** + * @param {any} node + * @returns {bigint} + */ + addNode(node) { + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + wasm.graph_addNode(retptr, this.__wbg_ptr, addHeapObject(node)); + var r0 = getDataViewMemory0().getBigInt64(retptr + 8 * 0, true); + var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); + var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true); + if (r3) { + throw takeObject(r2); + } + return BigInt.asUintN(64, r0); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + } + } + /** + * @param {any} nodes + * @returns {bigint} + */ + addNodes(nodes) { + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + wasm.graph_addNodes(retptr, this.__wbg_ptr, addHeapObject(nodes)); + var r0 = getDataViewMemory0().getBigInt64(retptr + 8 * 0, true); + var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); + var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true); + if (r3) { + throw takeObject(r2); + } + return BigInt.asUintN(64, r0); } finally { wasm.__wbindgen_add_to_stack_pointer(16); } @@ -255,11 +323,11 @@ export class Graph { * @param {string} target_id * @param {string} relation * @param {string[] | null} [sources] - * @param {any | null} [attrs] + * @param {any | null} [model] * @param {string | null} [identity_key] * @returns {any} */ - createRelationship(source_id, target_id, relation, sources, attrs, identity_key) { + addRelationship(source_id, target_id, relation, sources, model, identity_key) { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); const ptr0 = passStringToWasm0(source_id, wasm.__wbindgen_export, wasm.__wbindgen_export2); @@ -272,7 +340,7 @@ export class Graph { var len3 = WASM_VECTOR_LEN; var ptr4 = isLikeNone(identity_key) ? 0 : passStringToWasm0(identity_key, wasm.__wbindgen_export, wasm.__wbindgen_export2); var len4 = WASM_VECTOR_LEN; - wasm.graph_createRelationship(retptr, this.__wbg_ptr, ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3, isLikeNone(attrs) ? 0 : addHeapObject(attrs), ptr4, len4); + wasm.graph_addRelationship(retptr, this.__wbg_ptr, ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3, isLikeNone(model) ? 0 : addHeapObject(model), ptr4, len4); var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); @@ -285,18 +353,13 @@ export class Graph { } } /** - * @param {string} node_id - * @param {string | null} [direction] + * @param {any} relationships * @returns {bigint} */ - degree(node_id, direction) { + addRelationships(relationships) { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - const ptr0 = passStringToWasm0(node_id, wasm.__wbindgen_export, wasm.__wbindgen_export2); - const len0 = WASM_VECTOR_LEN; - var ptr1 = isLikeNone(direction) ? 0 : passStringToWasm0(direction, wasm.__wbindgen_export, wasm.__wbindgen_export2); - var len1 = WASM_VECTOR_LEN; - wasm.graph_degree(retptr, this.__wbg_ptr, ptr0, len0, ptr1, len1); + wasm.graph_addRelationships(retptr, this.__wbg_ptr, addHeapObject(relationships)); var r0 = getDataViewMemory0().getBigInt64(retptr + 8 * 0, true); var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true); @@ -309,56 +372,62 @@ export class Graph { } } /** - * @param {Graph} other - * @param {string | null} [node_type] - * @returns {CSTX} + * Execute the single typed graph algorithm atom. + * @param {any} algorithm + * @param {string | null} [selection] + * @returns {any} */ - difference(other, node_type) { + analyze(algorithm, selection) { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - _assertClass(other, Graph); - var ptr0 = isLikeNone(node_type) ? 0 : passStringToWasm0(node_type, wasm.__wbindgen_export, wasm.__wbindgen_export2); + var ptr0 = isLikeNone(selection) ? 0 : passStringToWasm0(selection, wasm.__wbindgen_export, wasm.__wbindgen_export2); var len0 = WASM_VECTOR_LEN; - wasm.graph_difference(retptr, this.__wbg_ptr, other.__wbg_ptr, ptr0, len0); + wasm.graph_analyze(retptr, this.__wbg_ptr, addHeapObject(algorithm), ptr0, len0); var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); if (r2) { throw takeObject(r1); } - return CSTX.__wrap(r0); + return takeObject(r0); } finally { wasm.__wbindgen_add_to_stack_pointer(16); } } /** - * @param {string} edge_id - * @returns {any} + * @param {string} node_id + * @returns {boolean} */ - edge(edge_id) { + contains(node_id) { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - const ptr0 = passStringToWasm0(edge_id, wasm.__wbindgen_export, wasm.__wbindgen_export2); + const ptr0 = passStringToWasm0(node_id, wasm.__wbindgen_export, wasm.__wbindgen_export2); const len0 = WASM_VECTOR_LEN; - wasm.graph_edge(retptr, this.__wbg_ptr, ptr0, len0); + wasm.graph_contains(retptr, this.__wbg_ptr, ptr0, len0); var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); if (r2) { throw takeObject(r1); } - return takeObject(r0); + return r0 !== 0; } finally { wasm.__wbindgen_add_to_stack_pointer(16); } } /** + * @param {string} node_id + * @param {string | null} [direction] * @returns {bigint} */ - edgeCount() { + degree(node_id, direction) { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.graph_edgeCount(retptr, this.__wbg_ptr); + const ptr0 = passStringToWasm0(node_id, wasm.__wbindgen_export, wasm.__wbindgen_export2); + const len0 = WASM_VECTOR_LEN; + var ptr1 = isLikeNone(direction) ? 0 : passStringToWasm0(direction, wasm.__wbindgen_export, wasm.__wbindgen_export2); + var len1 = WASM_VECTOR_LEN; + wasm.graph_degree(retptr, this.__wbg_ptr, ptr0, len0, ptr1, len1); var r0 = getDataViewMemory0().getBigInt64(retptr + 8 * 0, true); var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true); @@ -371,20 +440,24 @@ export class Graph { } } /** - * @param {any | null} [options] - * @returns {GraphCursor} + * @param {Graph} other + * @param {string | null} [node_type] + * @returns {CSTX} */ - edges(options) { + difference(other, node_type) { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.graph_edges(retptr, this.__wbg_ptr, isLikeNone(options) ? 0 : addHeapObject(options)); + _assertClass(other, Graph); + var ptr0 = isLikeNone(node_type) ? 0 : passStringToWasm0(node_type, wasm.__wbindgen_export, wasm.__wbindgen_export2); + var len0 = WASM_VECTOR_LEN; + wasm.graph_difference(retptr, this.__wbg_ptr, other.__wbg_ptr, ptr0, len0); var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); if (r2) { throw takeObject(r1); } - return GraphCursor.__wrap(r0); + return CSTX.__wrap(r0); } finally { wasm.__wbindgen_add_to_stack_pointer(16); } @@ -499,57 +572,6 @@ export class Graph { wasm.__wbindgen_add_to_stack_pointer(16); } } - /** - * @param {string} source - * @param {Uint8Array} data - * @returns {bigint} - */ - ingest(source, data) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - const ptr0 = passStringToWasm0(source, wasm.__wbindgen_export, wasm.__wbindgen_export2); - const len0 = WASM_VECTOR_LEN; - const ptr1 = passArray8ToWasm0(data, wasm.__wbindgen_export); - const len1 = WASM_VECTOR_LEN; - wasm.graph_ingest(retptr, this.__wbg_ptr, ptr0, len0, ptr1, len1); - var r0 = getDataViewMemory0().getBigInt64(retptr + 8 * 0, true); - var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); - var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true); - if (r3) { - throw takeObject(r2); - } - return BigInt.asUintN(64, r0); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } - } - /** - * @param {string} plugin - * @param {string} artifact - * @param {Uint8Array} data - * @returns {any} - */ - ingestNative(plugin, artifact, data) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - const ptr0 = passStringToWasm0(plugin, wasm.__wbindgen_export, wasm.__wbindgen_export2); - const len0 = WASM_VECTOR_LEN; - const ptr1 = passStringToWasm0(artifact, wasm.__wbindgen_export, wasm.__wbindgen_export2); - const len1 = WASM_VECTOR_LEN; - const ptr2 = passArray8ToWasm0(data, wasm.__wbindgen_export); - const len2 = WASM_VECTOR_LEN; - wasm.graph_ingestNative(retptr, this.__wbg_ptr, ptr0, len0, ptr1, len1, ptr2, len2); - var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); - var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); - var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); - if (r2) { - throw takeObject(r1); - } - return takeObject(r0); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } - } /** * @param {string[]} node_ids * @param {string} data_source @@ -695,45 +717,17 @@ export class Graph { wasm.__wbindgen_add_to_stack_pointer(16); } } - /** - * @param {string | null} [node_type] - * @param {string | null} [name_pattern] - * @param {bigint | null} [exclude_mask] - * @param {bigint | null} [include_mask] - * @param {number | null} [limit] - * @param {number | null} [page] - * @returns {any} - */ - nodesPage(node_type, name_pattern, exclude_mask, include_mask, limit, page) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - var ptr0 = isLikeNone(node_type) ? 0 : passStringToWasm0(node_type, wasm.__wbindgen_export, wasm.__wbindgen_export2); - var len0 = WASM_VECTOR_LEN; - var ptr1 = isLikeNone(name_pattern) ? 0 : passStringToWasm0(name_pattern, wasm.__wbindgen_export, wasm.__wbindgen_export2); - var len1 = WASM_VECTOR_LEN; - wasm.graph_nodesPage(retptr, this.__wbg_ptr, ptr0, len0, ptr1, len1, !isLikeNone(exclude_mask), isLikeNone(exclude_mask) ? BigInt(0) : exclude_mask, !isLikeNone(include_mask), isLikeNone(include_mask) ? BigInt(0) : include_mask, isLikeNone(limit) ? Number.MAX_SAFE_INTEGER : (limit) >>> 0, isLikeNone(page) ? Number.MAX_SAFE_INTEGER : (page) >>> 0); - var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); - var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); - var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); - if (r2) { - throw takeObject(r1); - } - return takeObject(r0); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } - } /** * @param {string[] | null | undefined} node_ids * @param {any} patch * @returns {bigint} */ - patchNodeExtras(node_ids, patch) { + patchNodeAnnotations(node_ids, patch) { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); var ptr0 = isLikeNone(node_ids) ? 0 : passArrayJsValueToWasm0(node_ids, wasm.__wbindgen_export); var len0 = WASM_VECTOR_LEN; - wasm.graph_patchNodeExtras(retptr, this.__wbg_ptr, ptr0, len0, addHeapObject(patch)); + wasm.graph_patchNodeAnnotations(retptr, this.__wbg_ptr, ptr0, len0, addHeapObject(patch)); var r0 = getDataViewMemory0().getBigInt64(retptr + 8 * 0, true); var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true); @@ -759,35 +753,93 @@ export class Graph { var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); - if (r2) { - throw takeObject(r1); + if (r2) { + throw takeObject(r1); + } + return GraphCursor.__wrap(r0); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + } + } + /** + * @param {string} expression + * @param {number | null} [limit] + * @param {number | null} [page] + * @param {bigint | null} [exclude_mask] + * @param {bigint | null} [include_mask] + * @returns {CSTX} + */ + querySubgraph(expression, limit, page, exclude_mask, include_mask) { + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(expression, wasm.__wbindgen_export, wasm.__wbindgen_export2); + const len0 = WASM_VECTOR_LEN; + wasm.graph_querySubgraph(retptr, this.__wbg_ptr, ptr0, len0, isLikeNone(limit) ? Number.MAX_SAFE_INTEGER : (limit) >>> 0, isLikeNone(page) ? Number.MAX_SAFE_INTEGER : (page) >>> 0, !isLikeNone(exclude_mask), isLikeNone(exclude_mask) ? BigInt(0) : exclude_mask, !isLikeNone(include_mask), isLikeNone(include_mask) ? BigInt(0) : include_mask); + var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); + var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); + var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); + if (r2) { + throw takeObject(r1); + } + return CSTX.__wrap(r0); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + } + } + /** + * @param {string} relationship_id + * @returns {any} + */ + relationship(relationship_id) { + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + const ptr0 = passStringToWasm0(relationship_id, wasm.__wbindgen_export, wasm.__wbindgen_export2); + const len0 = WASM_VECTOR_LEN; + wasm.graph_relationship(retptr, this.__wbg_ptr, ptr0, len0); + var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); + var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); + var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); + if (r2) { + throw takeObject(r1); + } + return takeObject(r0); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + } + } + /** + * @returns {bigint} + */ + relationshipCount() { + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + wasm.graph_relationshipCount(retptr, this.__wbg_ptr); + var r0 = getDataViewMemory0().getBigInt64(retptr + 8 * 0, true); + var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); + var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true); + if (r3) { + throw takeObject(r2); } - return GraphCursor.__wrap(r0); + return BigInt.asUintN(64, r0); } finally { wasm.__wbindgen_add_to_stack_pointer(16); } } /** - * @param {string} expression - * @param {number | null} [limit] - * @param {number | null} [page] - * @param {bigint | null} [exclude_mask] - * @param {bigint | null} [include_mask] - * @returns {CSTX} + * @param {any | null} [options] + * @returns {GraphCursor} */ - querySubgraph(expression, limit, page, exclude_mask, include_mask) { + relationships(options) { try { const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - const ptr0 = passStringToWasm0(expression, wasm.__wbindgen_export, wasm.__wbindgen_export2); - const len0 = WASM_VECTOR_LEN; - wasm.graph_querySubgraph(retptr, this.__wbg_ptr, ptr0, len0, isLikeNone(limit) ? Number.MAX_SAFE_INTEGER : (limit) >>> 0, isLikeNone(page) ? Number.MAX_SAFE_INTEGER : (page) >>> 0, !isLikeNone(exclude_mask), isLikeNone(exclude_mask) ? BigInt(0) : exclude_mask, !isLikeNone(include_mask), isLikeNone(include_mask) ? BigInt(0) : include_mask); + wasm.graph_relationships(retptr, this.__wbg_ptr, isLikeNone(options) ? 0 : addHeapObject(options)); var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); if (r2) { throw takeObject(r1); } - return CSTX.__wrap(r0); + return GraphCursor.__wrap(r0); } finally { wasm.__wbindgen_add_to_stack_pointer(16); } @@ -1278,267 +1330,6 @@ export class Repository { } if (Symbol.dispose) Repository.prototype[Symbol.dispose] = Repository.prototype.free; -export class Schemas { - static __wrap(ptr) { - const obj = Object.create(Schemas.prototype); - obj.__wbg_ptr = ptr; - SchemasFinalization.register(obj, obj.__wbg_ptr, obj); - return obj; - } - __destroy_into_raw() { - const ptr = this.__wbg_ptr; - this.__wbg_ptr = 0; - SchemasFinalization.unregister(this); - return ptr; - } - free() { - const ptr = this.__destroy_into_raw(); - wasm.__wbg_schemas_free(ptr, 0); - } - /** - * @returns {any} - */ - anchorConcepts() { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.schemas_anchorConcepts(retptr, this.__wbg_ptr); - var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); - var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); - var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); - if (r2) { - throw takeObject(r1); - } - return takeObject(r0); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } - } - /** - * @returns {any} - */ - availablePlugins() { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.schemas_availablePlugins(retptr, this.__wbg_ptr); - var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); - var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); - var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); - if (r2) { - throw takeObject(r1); - } - return takeObject(r0); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } - } - /** - * @param {string} node_type - * @returns {boolean} - */ - contains(node_type) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - const ptr0 = passStringToWasm0(node_type, wasm.__wbindgen_export, wasm.__wbindgen_export2); - const len0 = WASM_VECTOR_LEN; - wasm.schemas_contains(retptr, this.__wbg_ptr, ptr0, len0); - var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); - var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); - var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); - if (r2) { - throw takeObject(r1); - } - return r0 !== 0; - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } - } - /** - * @returns {any} - */ - exportSchema() { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.schemas_exportSchema(retptr, this.__wbg_ptr); - var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); - var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); - var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); - if (r2) { - throw takeObject(r1); - } - return takeObject(r0); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } - } - /** - * @param {string} node_type - * @returns {any} - */ - get(node_type) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - const ptr0 = passStringToWasm0(node_type, wasm.__wbindgen_export, wasm.__wbindgen_export2); - const len0 = WASM_VECTOR_LEN; - wasm.schemas_get(retptr, this.__wbg_ptr, ptr0, len0); - var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); - var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); - var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); - if (r2) { - throw takeObject(r1); - } - return takeObject(r0); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } - } - /** - * @param {string} artifact - * @returns {boolean} - */ - hasNativeArtifact(artifact) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - const ptr0 = passStringToWasm0(artifact, wasm.__wbindgen_export, wasm.__wbindgen_export2); - const len0 = WASM_VECTOR_LEN; - wasm.schemas_hasNativeArtifact(retptr, this.__wbg_ptr, ptr0, len0); - var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); - var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); - var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); - if (r2) { - throw takeObject(r1); - } - return r0 !== 0; - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } - } - /** - * @param {any} schema - */ - importSchema(schema) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.schemas_importSchema(retptr, this.__wbg_ptr, addHeapObject(schema)); - var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); - var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); - if (r1) { - throw takeObject(r0); - } - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } - } - /** - * @returns {any} - */ - list() { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.schemas_list(retptr, this.__wbg_ptr); - var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); - var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); - var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); - if (r2) { - throw takeObject(r1); - } - return takeObject(r0); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } - } - loadAllPlugins() { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.schemas_loadAllPlugins(retptr, this.__wbg_ptr); - var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); - var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); - if (r1) { - throw takeObject(r0); - } - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } - } - /** - * @param {string} name - */ - loadPlugin(name) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - const ptr0 = passStringToWasm0(name, wasm.__wbindgen_export, wasm.__wbindgen_export2); - const len0 = WASM_VECTOR_LEN; - wasm.schemas_loadPlugin(retptr, this.__wbg_ptr, ptr0, len0); - var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); - var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); - if (r1) { - throw takeObject(r0); - } - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } - } - /** - * @param {string} name - * @returns {any} - */ - pluginArtifacts(name) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - const ptr0 = passStringToWasm0(name, wasm.__wbindgen_export, wasm.__wbindgen_export2); - const len0 = WASM_VECTOR_LEN; - wasm.schemas_pluginArtifacts(retptr, this.__wbg_ptr, ptr0, len0); - var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); - var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); - var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true); - if (r2) { - throw takeObject(r1); - } - return takeObject(r0); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } - } - /** - * @param {string} node_type - * @param {any} schema - * @param {string | null} [value_field] - */ - register(node_type, schema, value_field) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - const ptr0 = passStringToWasm0(node_type, wasm.__wbindgen_export, wasm.__wbindgen_export2); - const len0 = WASM_VECTOR_LEN; - var ptr1 = isLikeNone(value_field) ? 0 : passStringToWasm0(value_field, wasm.__wbindgen_export, wasm.__wbindgen_export2); - var len1 = WASM_VECTOR_LEN; - wasm.schemas_register(retptr, this.__wbg_ptr, ptr0, len0, addHeapObject(schema), ptr1, len1); - var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); - var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); - if (r1) { - throw takeObject(r0); - } - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } - } - /** - * @param {any} rule - */ - registerJoinRule(rule) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.schemas_registerJoinRule(retptr, this.__wbg_ptr, addHeapObject(rule)); - var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true); - var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true); - if (r1) { - throw takeObject(r0); - } - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } - } -} -if (Symbol.dispose) Schemas.prototype[Symbol.dispose] = Schemas.prototype.free; - /** * @returns {string} */ @@ -1816,6 +1607,9 @@ function __wbg_get_imports() { const CSTXFinalization = (typeof FinalizationRegistry === 'undefined') ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry(ptr => wasm.__wbg_cstx_free(ptr, 1)); +const ExtensionsFinalization = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(ptr => wasm.__wbg_extensions_free(ptr, 1)); const GraphFinalization = (typeof FinalizationRegistry === 'undefined') ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry(ptr => wasm.__wbg_graph_free(ptr, 1)); @@ -1825,9 +1619,6 @@ const GraphCursorFinalization = (typeof FinalizationRegistry === 'undefined') const RepositoryFinalization = (typeof FinalizationRegistry === 'undefined') ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry(ptr => wasm.__wbg_repository_free(ptr, 1)); -const SchemasFinalization = (typeof FinalizationRegistry === 'undefined') - ? { register: () => {}, unregister: () => {} } - : new FinalizationRegistry(ptr => wasm.__wbg_schemas_free(ptr, 1)); function addHeapObject(obj) { if (heap_next === heap.length) heap.push(heap.length + 1); @@ -1959,13 +1750,6 @@ function isLikeNone(x) { return x === undefined || x === null; } -function passArray8ToWasm0(arg, malloc) { - const ptr = malloc(arg.length * 1, 1) >>> 0; - getUint8ArrayMemory0().set(arg, ptr / 1); - WASM_VECTOR_LEN = arg.length; - return ptr; -} - function passArrayJsValueToWasm0(array, malloc) { const ptr = malloc(array.length * 4, 4) >>> 0; const mem = getDataViewMemory0(); diff --git a/ts/wasm/cstx_wasm_bg.wasm b/ts/wasm/cstx_wasm_bg.wasm index 1a31bbc..f8c31d0 100644 Binary files a/ts/wasm/cstx_wasm_bg.wasm and b/ts/wasm/cstx_wasm_bg.wasm differ diff --git a/ts/wasm/cstx_wasm_bg.wasm.d.ts b/ts/wasm/cstx_wasm_bg.wasm.d.ts index 642ed87..0d6a70b 100644 --- a/ts/wasm/cstx_wasm_bg.wasm.d.ts +++ b/ts/wasm/cstx_wasm_bg.wasm.d.ts @@ -3,36 +3,27 @@ export const memory: WebAssembly.Memory; export const __wbg_cstx_free: (a: number, b: number) => void; export const cstx_new: (a: number, b: number) => void; -export const cstx_graph: (a: number) => number; +export const cstx_extensions: (a: number) => number; export const cstx_closed: (a: number) => number; export const cstx_close: (a: number) => void; -export const schemas_importSchema: (a: number, b: number, c: number) => void; -export const schemas_exportSchema: (a: number, b: number) => void; -export const schemas_register: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void; -export const schemas_registerJoinRule: (a: number, b: number, c: number) => void; -export const schemas_contains: (a: number, b: number, c: number, d: number) => void; -export const schemas_get: (a: number, b: number, c: number, d: number) => void; -export const schemas_list: (a: number, b: number) => void; -export const schemas_loadPlugin: (a: number, b: number, c: number, d: number) => void; -export const schemas_loadAllPlugins: (a: number, b: number) => void; -export const schemas_availablePlugins: (a: number, b: number) => void; -export const schemas_pluginArtifacts: (a: number, b: number, c: number, d: number) => void; -export const schemas_hasNativeArtifact: (a: number, b: number, c: number, d: number) => void; -export const schemas_anchorConcepts: (a: number, b: number) => void; -export const __wbg_graph_free: (a: number, b: number) => void; +export const __wbg_extensions_free: (a: number, b: number) => void; +export const extensions_register: (a: number, b: number, c: number) => void; +export const extensions_enable: (a: number, b: number, c: number, d: number) => void; +export const extensions_list: (a: number, b: number) => void; +export const extensions_info: (a: number, b: number, c: number, d: number) => void; +export const extensions_contains: (a: number, b: number, c: number, d: number) => void; +export const extensions_schema: (a: number, b: number, c: number, d: number) => void; +export const extensions_schemas: (a: number, b: number) => void; +export const extensions_parsesArtifact: (a: number, b: number, c: number, d: number) => void; +export const extensions_anchorConcepts: (a: number, b: number) => void; export const graph_addNode: (a: number, b: number, c: number) => void; export const graph_addNodes: (a: number, b: number, c: number) => void; -export const graph_addEdge: (a: number, b: number, c: number) => void; -export const graph_addEdges: (a: number, b: number, c: number) => void; -export const graph_addNodesJson: (a: number, b: number, c: number, d: number) => void; -export const graph_addEdgesJson: (a: number, b: number, c: number, d: number) => void; -export const graph_ingest: (a: number, b: number, c: number, d: number, e: number, f: number) => void; -export const graph_ingestNative: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => void; +export const graph_addRelationships: (a: number, b: number, c: number) => void; export const graph_node: (a: number, b: number, c: number, d: number) => void; -export const graph_edge: (a: number, b: number, c: number, d: number) => void; +export const graph_relationship: (a: number, b: number, c: number, d: number) => void; export const graph_findNode: (a: number, b: number, c: number, d: number) => void; -export const graph_patchNodeExtras: (a: number, b: number, c: number, d: number, e: number) => void; -export const graph_createRelationship: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number) => void; +export const graph_addRelationship: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number) => void; +export const graph_patchNodeAnnotations: (a: number, b: number, c: number, d: number, e: number) => void; export const graph_union: (a: number, b: number, c: number) => void; export const graph_merge: (a: number, b: number, c: number) => void; export const graph_difference: (a: number, b: number, c: number, d: number, e: number) => void; @@ -41,13 +32,12 @@ export const graph_link: (a: number, b: number, c: number, d: number, e: number, export const graph_updateNodeFlags: (a: number, b: number, c: number, d: number, e: number, f: bigint, g: number, h: bigint, i: number, j: bigint) => void; export const graph_contains: (a: number, b: number, c: number, d: number) => void; export const graph_nodeCount: (a: number, b: number) => void; -export const graph_edgeCount: (a: number, b: number) => void; +export const graph_relationshipCount: (a: number, b: number) => void; export const graph_stats: (a: number, b: number, c: number, d: number, e: number, f: bigint, g: number, h: bigint) => void; export const graph_degree: (a: number, b: number, c: number, d: number, e: number, f: number) => void; export const graph_nodes: (a: number, b: number, c: number) => void; -export const graph_edges: (a: number, b: number, c: number) => void; +export const graph_relationships: (a: number, b: number, c: number) => void; export const graph_neighbors: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void; -export const graph_nodesPage: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: bigint, i: number, j: bigint, k: number, l: number) => void; export const graph_query: (a: number, b: number, c: number, d: number, e: number) => void; export const graph_analyze: (a: number, b: number, c: number, d: number, e: number) => void; export const graph_subgraph: (a: number, b: number, c: number, d: number, e: number) => void; @@ -83,8 +73,8 @@ export const rust_zstd_wasm_shim_memcpy: (a: number, b: number, c: number) => nu export const rust_zstd_wasm_shim_memmove: (a: number, b: number, c: number) => number; export const rust_zstd_wasm_shim_memset: (a: number, b: number, c: number) => number; export const __wbg_repository_free: (a: number, b: number) => void; -export const __wbg_schemas_free: (a: number, b: number) => void; -export const cstx_schemas: (a: number) => number; +export const __wbg_graph_free: (a: number, b: number) => void; +export const cstx_graph: (a: number) => number; export const cstx_repository: (a: number) => number; export const __wbindgen_export: (a: number, b: number) => number; export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;