From f745892ed2800927bbcba009288e379a80ef57d9 Mon Sep 17 00:00:00 2001 From: Alexander Polyankin Date: Thu, 2 Apr 2026 15:44:26 -0400 Subject: [PATCH 1/2] metabot and channel --- core-spec/v1/schemas/channel.yaml | 109 ++++++++++++++++++++- core-spec/v1/schemas/metabot.yaml | 63 +++++++++++- examples/v1/channels/email_channel.yaml | 10 ++ examples/v1/channels/http_channel.yaml | 9 ++ examples/v1/metabots/embedded_metabot.yaml | 9 ++ examples/v1/metabots/metabot.yaml | 9 ++ examples/v1/metabots/slack_metabot.yaml | 9 ++ src/validate-schema.js | 2 + 8 files changed, 212 insertions(+), 8 deletions(-) create mode 100644 examples/v1/channels/email_channel.yaml create mode 100644 examples/v1/channels/http_channel.yaml create mode 100644 examples/v1/metabots/embedded_metabot.yaml create mode 100644 examples/v1/metabots/metabot.yaml create mode 100644 examples/v1/metabots/slack_metabot.yaml diff --git a/core-spec/v1/schemas/channel.yaml b/core-spec/v1/schemas/channel.yaml index d721342..2915cfe 100644 --- a/core-spec/v1/schemas/channel.yaml +++ b/core-spec/v1/schemas/channel.yaml @@ -1,7 +1,9 @@ $schema: https://json-schema.org/draft/2020-12/schema title: Channel description: > - A notification channel (e.g., HTTP webhook). + A notification channel (e.g., email or HTTP webhook). + Channels are serialized to the top-level channels/ directory. + The channel name is used as the entity identifier (no entity_id column). type: object required: - name @@ -10,19 +12,33 @@ required: properties: name: type: string - description: Channel name + description: Channel name (unique, used as entity identifier) + description: + type: + - string + - "null" + description: Human-readable description type: type: string - description: "Channel type (e.g., channel/http)" + description: Channel type + enum: + - channel/email + - channel/http details: type: object - description: Channel-specific configuration + description: Channel-specific configuration (encrypted in the database) additionalProperties: true + active: + type: boolean + description: Whether the channel is active + default: true created_at: type: string + description: ISO 8601 timestamp format: date-time serdes/meta: type: array + description: Identity path for serialization items: type: object required: @@ -31,8 +47,93 @@ properties: properties: id: type: string + description: Entity identifier (matches name) label: type: string + description: Slugified name model: type: string const: Channel +allOf: + - if: + properties: + type: { const: channel/http } + then: + properties: + details: + type: object + required: + - url + - auth-method + properties: + url: + type: string + description: Webhook URL + format: uri + auth-method: + type: string + description: Authentication method + enum: + - none + - header + - query-param + - request-body + auth-info: + type: object + description: Authentication details (keys depend on auth-method) + additionalProperties: true + fe-form-type: + type: string + description: Frontend form type for auth display + enum: + - api-key + - bearer + - basic + - none + method: + type: string + description: HTTP method + enum: + - get + - post + - put + additionalProperties: false + - if: + properties: + type: { const: channel/email } + then: + properties: + details: + type: object + description: Email channel SMTP configuration + properties: + host: + type: string + description: SMTP server hostname + port: + type: integer + description: SMTP server port + security: + type: string + description: Connection security + enum: + - none + - ssl + - tls + - starttls + username: + type: string + description: SMTP username + password: + type: string + description: SMTP password + from-address: + type: string + description: Sender email address + from-name: + type: string + description: Sender display name + reply-to: + type: string + description: Reply-to email address + additionalProperties: true diff --git a/core-spec/v1/schemas/metabot.yaml b/core-spec/v1/schemas/metabot.yaml index 2e63287..9d5f87d 100644 --- a/core-spec/v1/schemas/metabot.yaml +++ b/core-spec/v1/schemas/metabot.yaml @@ -1,7 +1,9 @@ $schema: https://json-schema.org/draft/2020-12/schema title: Metabot description: > - A Metabot instance configuration. + A Metabot instance configuration. Metabots are AI assistants that can answer + questions using configured prompts and model cards. Serialized to the + top-level metabots/ directory. type: object required: - entity_id @@ -18,21 +20,72 @@ properties: - string - "null" description: Human-readable description + collection_id: + description: Collection FK, null for root collection + type: + - string + - "null" + if: { type: string } + then: { $ref: "common/id.yaml#/$defs/entity_id" } + use_verified_content: + type: boolean + description: Whether to restrict prompts to verified content only + default: false prompts: type: array - description: Metabot prompts + description: Metabot prompts (inlined MetabotPrompt entities) + default: [] items: type: object - additionalProperties: true - default: [] + required: + - entity_id + - prompt + - model + - card_id + properties: + entity_id: + $ref: "common/id.yaml#/$defs/entity_id" + prompt: + type: string + description: The prompt text + model: + type: string + description: The type of card this prompt targets + enum: + - model + - question + - metric + card_id: + description: Card FK (entity_id of the referenced card) + $ref: "common/id.yaml#/$defs/entity_id" + created_at: + type: string + format: date-time + updated_at: + type: string + format: date-time + serdes/meta: + type: array + description: Identity path including parent Metabot + items: + type: object + required: [id, model] + properties: + id: { type: string } + model: + type: string + enum: [Metabot, MetabotPrompt] created_at: type: string + description: ISO 8601 timestamp format: date-time updated_at: type: string + description: ISO 8601 timestamp format: date-time serdes/meta: type: array + description: Identity path for serialization items: type: object required: @@ -41,8 +94,10 @@ properties: properties: id: type: string + description: Entity identifier (matches entity_id) label: type: string + description: Slugified name model: type: string const: Metabot diff --git a/examples/v1/channels/email_channel.yaml b/examples/v1/channels/email_channel.yaml new file mode 100644 index 0000000..88101db --- /dev/null +++ b/examples/v1/channels/email_channel.yaml @@ -0,0 +1,10 @@ +created_at: '2024-09-11T15:36:01.845352Z' +description: Email notification channel +details: + host: smtp.example.com + port: 587 +name: Email Channel +type: channel/email +serdes/meta: +- id: Email Channel + model: Channel diff --git a/examples/v1/channels/http_channel.yaml b/examples/v1/channels/http_channel.yaml new file mode 100644 index 0000000..8b9f0db --- /dev/null +++ b/examples/v1/channels/http_channel.yaml @@ -0,0 +1,9 @@ +created_at: '2024-09-11T15:36:01.845352Z' +details: + auth-method: none + url: http://example.com +name: HTTP Channel +type: channel/http +serdes/meta: +- id: HTTP Channel + model: Channel diff --git a/examples/v1/metabots/embedded_metabot.yaml b/examples/v1/metabots/embedded_metabot.yaml new file mode 100644 index 0000000..d46863d --- /dev/null +++ b/examples/v1/metabots/embedded_metabot.yaml @@ -0,0 +1,9 @@ +name: Embedded Metabot +description: Metabot instance for embedded metabase users. +created_at: '2026-04-02T02:59:01.370515Z' +entity_id: embeddedmetabotmetabo +updated_at: '2026-04-02T02:59:01.370515Z' +serdes/meta: +- id: embeddedmetabotmetabo + model: Metabot +prompts: [] diff --git a/examples/v1/metabots/metabot.yaml b/examples/v1/metabots/metabot.yaml new file mode 100644 index 0000000..8739866 --- /dev/null +++ b/examples/v1/metabots/metabot.yaml @@ -0,0 +1,9 @@ +name: Metabot +description: Metabot instance for internal users. +created_at: '2025-05-28T17:49:20.649159Z' +entity_id: metabotmetabotmetabot +updated_at: '2025-05-28T17:49:20.649159Z' +serdes/meta: +- id: metabotmetabotmetabot + model: Metabot +prompts: [] diff --git a/examples/v1/metabots/slack_metabot.yaml b/examples/v1/metabots/slack_metabot.yaml new file mode 100644 index 0000000..7ea7acf --- /dev/null +++ b/examples/v1/metabots/slack_metabot.yaml @@ -0,0 +1,9 @@ +name: Slack Metabot +description: Metabot instance for Slack users. +created_at: '2026-04-02T02:59:01.71366Z' +entity_id: slackbotmetabotmetabo +updated_at: '2026-04-02T02:59:01.71366Z' +serdes/meta: +- id: slackbotmetabotmetabo + model: Metabot +prompts: [] diff --git a/src/validate-schema.js b/src/validate-schema.js index 73e4c85..319a8f5 100644 --- a/src/validate-schema.js +++ b/src/validate-schema.js @@ -8,9 +8,11 @@ import addFormats from "ajv-formats"; const PACKAGE_ROOT = resolve(import.meta.dirname, ".."); const IMPORT_PATHS = [ + "channels/**/*.yaml", "collections/**/*.yaml", "databases/**/segments/**/*.yaml", "databases/**/measures/**/*.yaml", + "metabots/**/*.yaml", "python_libraries/**/*.yaml", "python-libraries/**/*.yaml", "transforms/**/*.yaml", From 566b0c5516e28dfc2678f29cc039c4e1017ec570 Mon Sep 17 00:00:00 2001 From: Alexander Polyankin Date: Thu, 2 Apr 2026 15:53:50 -0400 Subject: [PATCH 2/2] fixes --- core-spec/v1/schemas/database.yaml | 22 ++++++- core-spec/v1/schemas/field.yaml | 83 +++++++++++++++++++++++++- core-spec/v1/schemas/field_values.yaml | 50 ++++++++++++++-- core-spec/v1/schemas/table.yaml | 38 +++++++++++- 4 files changed, 180 insertions(+), 13 deletions(-) diff --git a/core-spec/v1/schemas/database.yaml b/core-spec/v1/schemas/database.yaml index b0f8c1c..1bcc8a0 100644 --- a/core-spec/v1/schemas/database.yaml +++ b/core-spec/v1/schemas/database.yaml @@ -1,6 +1,8 @@ $schema: https://json-schema.org/draft/2020-12/schema title: Database -description: A database connection definition. +description: > + A database connection definition. Databases are the root of the data model + hierarchy: Database → Table → Field. Serialized to databases/{name}/{name}.yaml. type: object required: - name @@ -8,12 +10,26 @@ required: properties: name: type: string + description: Database name (unique, used as entity identifier) + engine: + type: string + description: Database engine type (e.g., postgres, mysql, h2, bigquery-cloud-sdk) + description: + type: + - string + - "null" + description: Human-readable description serdes/meta: type: array + description: Identity path for serialization items: type: object required: [id, model] properties: - id: { type: string } - model: { type: string, const: Database } + id: + type: string + description: Entity identifier (matches name) + model: + type: string + const: Database additionalProperties: true diff --git a/core-spec/v1/schemas/field.yaml b/core-spec/v1/schemas/field.yaml index e146ab3..711790c 100644 --- a/core-spec/v1/schemas/field.yaml +++ b/core-spec/v1/schemas/field.yaml @@ -1,19 +1,96 @@ $schema: https://json-schema.org/draft/2020-12/schema title: Field -description: A table field (column) definition. +description: > + A table field (column) definition. Fields belong to tables and describe + individual columns. Serialized to databases/{db}/…/tables/{table}/fields/{field}.yaml. type: object required: - name + - base_type + - database_type + - table_id - serdes/meta properties: name: type: string + description: Column name in the database + display_name: + type: + - string + - "null" + description: Human-readable display name + description: + type: + - string + - "null" + description: Human-readable description + base_type: + type: string + description: "Metabase base type (e.g., type/Integer, type/Text)" + effective_type: + type: + - string + - "null" + description: Effective type after coercion + database_type: + type: string + description: Native database type (e.g., INTEGER, VARCHAR) + semantic_type: + type: + - string + - "null" + description: "Semantic type (e.g., type/PK, type/FK, type/Category)" + coercion_strategy: + type: + - string + - "null" + description: Type coercion strategy + table_id: + description: Table FK [database, schema, table] + $ref: "common/id.yaml#/$defs/table_id" + fk_target_field_id: + description: FK target field [database, schema, table, field] + type: + - array + - "null" + if: { type: array } + then: { $ref: "common/id.yaml#/$defs/field_id" } + parent_id: + description: Parent field FK for nested/JSON-unfolded fields + type: + - array + - "null" + if: { type: array } + then: { $ref: "common/id.yaml#/$defs/field_id" } + active: + type: boolean + description: Whether the field is active + default: true + settings: + type: + - object + - "null" + description: Field-level settings + additionalProperties: true + dimensions: + type: array + description: Inlined Dimension entities for remapping + items: + type: object + additionalProperties: true + default: [] serdes/meta: type: array + description: > + Identity path for serialization. Contains Database, optional Schema, + Table, and one or more Field entries (for nested fields). items: type: object required: [id, model] properties: - id: { type: string } - model: { type: string, enum: [Database, Schema, Table, Field] } + id: + type: string + model: + type: string + enum: [Database, Schema, Table, Field] additionalProperties: true diff --git a/core-spec/v1/schemas/field_values.yaml b/core-spec/v1/schemas/field_values.yaml index c2eade3..e1fbf8b 100644 --- a/core-spec/v1/schemas/field_values.yaml +++ b/core-spec/v1/schemas/field_values.yaml @@ -1,16 +1,58 @@ $schema: https://json-schema.org/draft/2020-12/schema title: FieldValues -description: Cached distinct values for a field. +description: > + Cached distinct values for a field, used for filter dropdowns and auto-complete. + Serialized alongside the parent field as {field}___fieldvalues.yaml. type: object required: + - values - serdes/meta properties: + values: + type: array + description: List of distinct field values + items: {} + human_readable_values: + type: array + description: Human-readable labels for remapped values (parallel to values array) + items: {} + default: [] + has_more_values: + type: boolean + description: Whether there are more values than cached + default: false + type: + type: string + description: Type of field values cache + enum: + - full + - sandbox + hash_key: + type: + - string + - "null" + description: Hash key for sandbox-scoped field values + created_at: + type: string + description: ISO 8601 timestamp + format: date-time + last_used_at: + type: + - string + - "null" + description: ISO 8601 timestamp of last use + format: date-time serdes/meta: type: array + description: > + Identity path for serialization. Contains Database, optional Schema, + Table, Field, and FieldValues entries. items: type: object required: [id, model] properties: - id: { type: string } - model: { type: string, enum: [Database, Schema, Table, Field, FieldValues] } -additionalProperties: true + id: + type: string + model: + type: string + enum: [Database, Schema, Table, Field, FieldValues] diff --git a/core-spec/v1/schemas/table.yaml b/core-spec/v1/schemas/table.yaml index d0bfbec..5a78c7a 100644 --- a/core-spec/v1/schemas/table.yaml +++ b/core-spec/v1/schemas/table.yaml @@ -1,19 +1,51 @@ $schema: https://json-schema.org/draft/2020-12/schema title: Table -description: A database table definition. +description: > + A database table definition. Tables belong to databases and contain fields. + Serialized to databases/{db}/schemas/{schema}/tables/{table}/{table}.yaml. type: object required: - name + - db_id - serdes/meta properties: name: type: string + description: Table name in the database + display_name: + type: + - string + - "null" + description: Human-readable display name + description: + type: + - string + - "null" + description: Human-readable description + db_id: + type: string + description: Database FK (database name) + schema: + type: + - string + - "null" + description: Database schema name (null for schemaless databases) + active: + type: boolean + description: Whether the table is active + default: true serdes/meta: type: array + description: > + Identity path for serialization. Contains Database, optional Schema, + and Table entries. items: type: object required: [id, model] properties: - id: { type: string } - model: { type: string, enum: [Database, Schema, Table] } + id: + type: string + model: + type: string + enum: [Database, Schema, Table] additionalProperties: true