@liquidmetal-ai/drizzle 0.4.13 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,133 @@
1
+ // @generated by protoc-gen-es v2.2.5 with parameter "target=ts,import_extension=.js"
2
+ // @generated from file liquidmetal/v1alpha1/smartsql.proto (package liquidmetal.v1alpha1, syntax proto3)
3
+ /* eslint-disable */
4
+ import { enumDesc, fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv1";
5
+ import { file_google_protobuf_timestamp } from "@bufbuild/protobuf/wkt";
6
+ import { file_liquidmetal_v1alpha1_smartsql_name } from "./smartsql_name_pb.js";
7
+ /**
8
+ * Describes the file liquidmetal/v1alpha1/smartsql.proto.
9
+ */
10
+ export const file_liquidmetal_v1alpha1_smartsql = /*@__PURE__*/ fileDesc("CiNsaXF1aWRtZXRhbC92MWFscGhhMS9zbWFydHNxbC5wcm90bxIUbGlxdWlkbWV0YWwudjFhbHBoYTEilAIKE0V4ZWN1dGVRdWVyeVJlcXVlc3QSQQoSc21hcnRfc3FsX2xvY2F0aW9uGAEgASgLMiUubGlxdWlkbWV0YWwudjFhbHBoYTEuU21hcnRTcWxMb2NhdG9yEhYKCXNxbF9xdWVyeRgCIAEoCUgAiAEBEhcKCnRleHRfcXVlcnkYAyABKAlIAYgBARI3CgZmb3JtYXQYBCABKA4yIi5saXF1aWRtZXRhbC52MWFscGhhMS5PdXRwdXRGb3JtYXRIAogBARIPCgd1c2VyX2lkGAUgASgJEhcKD29yZ2FuaXphdGlvbl9pZBgGIAEoCUIMCgpfc3FsX3F1ZXJ5Qg0KC190ZXh0X3F1ZXJ5QgkKB19mb3JtYXQitQEKFEV4ZWN1dGVRdWVyeVJlc3BvbnNlEg8KB21lc3NhZ2UYASABKAkSFgoManNvbl9yZXN1bHRzGAIgASgJSAASFQoLY3N2X3Jlc3VsdHMYAyABKAlIABIOCgZzdGF0dXMYBCABKAUSFgoOcXVlcnlfZXhlY3V0ZWQYBSABKAkSGQoMYWlfcmVhc29uaW5nGAYgASgJSAGIAQFCCQoHcmVzdWx0c0IPCg1fYWlfcmVhc29uaW5nIqkBChJHZXRNZXRhZGF0YVJlcXVlc3QSQQoSc21hcnRfc3FsX2xvY2F0aW9uGAEgASgLMiUubGlxdWlkbWV0YWwudjFhbHBoYTEuU21hcnRTcWxMb2NhdG9yEhcKCnRhYmxlX25hbWUYAiABKAlIAIgBARIPCgd1c2VyX2lkGAMgASgJEhcKD29yZ2FuaXphdGlvbl9pZBgEIAEoCUINCgtfdGFibGVfbmFtZSKSAQoTR2V0TWV0YWRhdGFSZXNwb25zZRIzCgZ0YWJsZXMYASADKAsyIy5saXF1aWRtZXRhbC52MWFscGhhMS5UYWJsZU1ldGFkYXRhEjUKDGxhc3RfdXBkYXRlZBgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBIAIgBAUIPCg1fbGFzdF91cGRhdGVkIvcBChVVcGRhdGVNZXRhZGF0YVJlcXVlc3QSQQoSc21hcnRfc3FsX2xvY2F0aW9uGAEgASgLMiUubGlxdWlkbWV0YWwudjFhbHBoYTEuU21hcnRTcWxMb2NhdG9yEjMKBnRhYmxlcxgCIAMoCzIjLmxpcXVpZG1ldGFsLnYxYWxwaGExLlRhYmxlTWV0YWRhdGESMwoEbW9kZRgDIAEoDjIgLmxpcXVpZG1ldGFsLnYxYWxwaGExLlVwZGF0ZU1vZGVIAIgBARIPCgd1c2VyX2lkGAQgASgJEhcKD29yZ2FuaXphdGlvbl9pZBgFIAEoCUIHCgVfbW9kZSJSChZVcGRhdGVNZXRhZGF0YVJlc3BvbnNlEg8KB3N1Y2Nlc3MYASABKAgSFgoOdGFibGVzX3VwZGF0ZWQYAiABKAUSDwoHbWVzc2FnZRgDIAEoCSK6AQoRR2V0UGlpRGF0YVJlcXVlc3QSQQoSc21hcnRfc3FsX2xvY2F0aW9uGAEgASgLMiUubGlxdWlkbWV0YWwudjFhbHBoYTEuU21hcnRTcWxMb2NhdG9yEhIKCnRhYmxlX25hbWUYAiABKAkSFgoJcmVjb3JkX2lkGAMgASgJSACIAQESDwoHdXNlcl9pZBgEIAEoCRIXCg9vcmdhbml6YXRpb25faWQYBSABKAlCDAoKX3JlY29yZF9pZCJQChJHZXRQaWlEYXRhUmVzcG9uc2USOgoOcGlpX2RldGVjdGlvbnMYASADKAsyIi5saXF1aWRtZXRhbC52MWFscGhhMS5QaWlEZXRlY3Rpb24i4gEKDVRhYmxlTWV0YWRhdGESEgoKdGFibGVfbmFtZRgBIAEoCRI1Cgdjb2x1bW5zGAIgAygLMiQubGlxdWlkbWV0YWwudjFhbHBoYTEuQ29sdW1uTWV0YWRhdGESMwoKY3JlYXRlZF9hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBIAIgBARIzCgp1cGRhdGVkX2F0GAQgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcEgBiAEBQg0KC19jcmVhdGVkX2F0Qg0KC191cGRhdGVkX2F0IowBCg5Db2x1bW5NZXRhZGF0YRITCgtjb2x1bW5fbmFtZRgBIAEoCRIRCglkYXRhX3R5cGUYAiABKAkSGAoLc2FtcGxlX2RhdGEYAyABKAlIAIgBARIQCghudWxsYWJsZRgEIAEoCBIWCg5pc19wcmltYXJ5X2tleRgFIAEoCEIOCgxfc2FtcGxlX2RhdGEirwEKDFBpaURldGVjdGlvbhIUCgxkZXRlY3Rpb25faWQYASABKAkSEgoKdGFibGVfbmFtZRgCIAEoCRIRCglyZWNvcmRfaWQYAyABKAkSMQoIZW50aXRpZXMYBCADKAsyHy5saXF1aWRtZXRhbC52MWFscGhhMS5QaWlFbnRpdHkSLwoLZGV0ZWN0ZWRfYXQYBSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wIpQBCglQaWlFbnRpdHkSEwoLZW50aXR5X3R5cGUYASABKAkSGAoQY29uZmlkZW5jZV9zY29yZRgCIAEoAhIVCg1kZXRlY3RlZF90ZXh0GAMgASgJEhYKDnN0YXJ0X3Bvc2l0aW9uGAQgASgFEhQKDGVuZF9wb3NpdGlvbhgFIAEoBRITCgt0b2tlbl9pbmRleBgGIAEoBSpcCgxPdXRwdXRGb3JtYXQSHQoZT1VUUFVUX0ZPUk1BVF9VTlNQRUNJRklFRBAAEhYKEk9VVFBVVF9GT1JNQVRfSlNPThABEhUKEU9VVFBVVF9GT1JNQVRfQ1NWEAIqcQoKVXBkYXRlTW9kZRIbChdVUERBVEVfTU9ERV9VTlNQRUNJRklFRBAAEhcKE1VQREFURV9NT0RFX1JFUExBQ0UQARIVChFVUERBVEVfTU9ERV9NRVJHRRACEhYKElVQREFURV9NT0RFX0FQUEVORBADMqoDCg9TbWFydFNxbFNlcnZpY2USZQoMRXhlY3V0ZVF1ZXJ5EikubGlxdWlkbWV0YWwudjFhbHBoYTEuRXhlY3V0ZVF1ZXJ5UmVxdWVzdBoqLmxpcXVpZG1ldGFsLnYxYWxwaGExLkV4ZWN1dGVRdWVyeVJlc3BvbnNlEmIKC0dldE1ldGFkYXRhEigubGlxdWlkbWV0YWwudjFhbHBoYTEuR2V0TWV0YWRhdGFSZXF1ZXN0GikubGlxdWlkbWV0YWwudjFhbHBoYTEuR2V0TWV0YWRhdGFSZXNwb25zZRJrCg5VcGRhdGVNZXRhZGF0YRIrLmxpcXVpZG1ldGFsLnYxYWxwaGExLlVwZGF0ZU1ldGFkYXRhUmVxdWVzdBosLmxpcXVpZG1ldGFsLnYxYWxwaGExLlVwZGF0ZU1ldGFkYXRhUmVzcG9uc2USXwoKR2V0UGlpRGF0YRInLmxpcXVpZG1ldGFsLnYxYWxwaGExLkdldFBpaURhdGFSZXF1ZXN0GigubGlxdWlkbWV0YWwudjFhbHBoYTEuR2V0UGlpRGF0YVJlc3BvbnNlQugBChhjb20ubGlxdWlkbWV0YWwudjFhbHBoYTFCDVNtYXJ0c3FsUHJvdG9QAVpMZ2l0aHViLmNvbS9saXF1aWRtZXRhbC1haS9wcm90b2dlbjIvbGlxdWlkbWV0YWwvdjFhbHBoYTE7bGlxdWlkbWV0YWx2MWFscGhhMaICA0xYWKoCFExpcXVpZG1ldGFsLlYxYWxwaGExygIUTGlxdWlkbWV0YWxcVjFhbHBoYTHiAiBMaXF1aWRtZXRhbFxWMWFscGhhMVxHUEJNZXRhZGF0YeoCFUxpcXVpZG1ldGFsOjpWMWFscGhhMWIGcHJvdG8z", [file_google_protobuf_timestamp, file_liquidmetal_v1alpha1_smartsql_name]);
11
+ /**
12
+ * Describes the message liquidmetal.v1alpha1.ExecuteQueryRequest.
13
+ * Use `create(ExecuteQueryRequestSchema)` to create a new message.
14
+ */
15
+ export const ExecuteQueryRequestSchema = /*@__PURE__*/ messageDesc(file_liquidmetal_v1alpha1_smartsql, 0);
16
+ /**
17
+ * Describes the message liquidmetal.v1alpha1.ExecuteQueryResponse.
18
+ * Use `create(ExecuteQueryResponseSchema)` to create a new message.
19
+ */
20
+ export const ExecuteQueryResponseSchema = /*@__PURE__*/ messageDesc(file_liquidmetal_v1alpha1_smartsql, 1);
21
+ /**
22
+ * Describes the message liquidmetal.v1alpha1.GetMetadataRequest.
23
+ * Use `create(GetMetadataRequestSchema)` to create a new message.
24
+ */
25
+ export const GetMetadataRequestSchema = /*@__PURE__*/ messageDesc(file_liquidmetal_v1alpha1_smartsql, 2);
26
+ /**
27
+ * Describes the message liquidmetal.v1alpha1.GetMetadataResponse.
28
+ * Use `create(GetMetadataResponseSchema)` to create a new message.
29
+ */
30
+ export const GetMetadataResponseSchema = /*@__PURE__*/ messageDesc(file_liquidmetal_v1alpha1_smartsql, 3);
31
+ /**
32
+ * Describes the message liquidmetal.v1alpha1.UpdateMetadataRequest.
33
+ * Use `create(UpdateMetadataRequestSchema)` to create a new message.
34
+ */
35
+ export const UpdateMetadataRequestSchema = /*@__PURE__*/ messageDesc(file_liquidmetal_v1alpha1_smartsql, 4);
36
+ /**
37
+ * Describes the message liquidmetal.v1alpha1.UpdateMetadataResponse.
38
+ * Use `create(UpdateMetadataResponseSchema)` to create a new message.
39
+ */
40
+ export const UpdateMetadataResponseSchema = /*@__PURE__*/ messageDesc(file_liquidmetal_v1alpha1_smartsql, 5);
41
+ /**
42
+ * Describes the message liquidmetal.v1alpha1.GetPiiDataRequest.
43
+ * Use `create(GetPiiDataRequestSchema)` to create a new message.
44
+ */
45
+ export const GetPiiDataRequestSchema = /*@__PURE__*/ messageDesc(file_liquidmetal_v1alpha1_smartsql, 6);
46
+ /**
47
+ * Describes the message liquidmetal.v1alpha1.GetPiiDataResponse.
48
+ * Use `create(GetPiiDataResponseSchema)` to create a new message.
49
+ */
50
+ export const GetPiiDataResponseSchema = /*@__PURE__*/ messageDesc(file_liquidmetal_v1alpha1_smartsql, 7);
51
+ /**
52
+ * Describes the message liquidmetal.v1alpha1.TableMetadata.
53
+ * Use `create(TableMetadataSchema)` to create a new message.
54
+ */
55
+ export const TableMetadataSchema = /*@__PURE__*/ messageDesc(file_liquidmetal_v1alpha1_smartsql, 8);
56
+ /**
57
+ * Describes the message liquidmetal.v1alpha1.ColumnMetadata.
58
+ * Use `create(ColumnMetadataSchema)` to create a new message.
59
+ */
60
+ export const ColumnMetadataSchema = /*@__PURE__*/ messageDesc(file_liquidmetal_v1alpha1_smartsql, 9);
61
+ /**
62
+ * Describes the message liquidmetal.v1alpha1.PiiDetection.
63
+ * Use `create(PiiDetectionSchema)` to create a new message.
64
+ */
65
+ export const PiiDetectionSchema = /*@__PURE__*/ messageDesc(file_liquidmetal_v1alpha1_smartsql, 10);
66
+ /**
67
+ * Describes the message liquidmetal.v1alpha1.PiiEntity.
68
+ * Use `create(PiiEntitySchema)` to create a new message.
69
+ */
70
+ export const PiiEntitySchema = /*@__PURE__*/ messageDesc(file_liquidmetal_v1alpha1_smartsql, 11);
71
+ /**
72
+ * @generated from enum liquidmetal.v1alpha1.OutputFormat
73
+ */
74
+ export var OutputFormat;
75
+ (function (OutputFormat) {
76
+ /**
77
+ * @generated from enum value: OUTPUT_FORMAT_UNSPECIFIED = 0;
78
+ */
79
+ OutputFormat[OutputFormat["UNSPECIFIED"] = 0] = "UNSPECIFIED";
80
+ /**
81
+ * @generated from enum value: OUTPUT_FORMAT_JSON = 1;
82
+ */
83
+ OutputFormat[OutputFormat["JSON"] = 1] = "JSON";
84
+ /**
85
+ * @generated from enum value: OUTPUT_FORMAT_CSV = 2;
86
+ */
87
+ OutputFormat[OutputFormat["CSV"] = 2] = "CSV";
88
+ })(OutputFormat || (OutputFormat = {}));
89
+ /**
90
+ * Describes the enum liquidmetal.v1alpha1.OutputFormat.
91
+ */
92
+ export const OutputFormatSchema = /*@__PURE__*/ enumDesc(file_liquidmetal_v1alpha1_smartsql, 0);
93
+ /**
94
+ * @generated from enum liquidmetal.v1alpha1.UpdateMode
95
+ */
96
+ export var UpdateMode;
97
+ (function (UpdateMode) {
98
+ /**
99
+ * @generated from enum value: UPDATE_MODE_UNSPECIFIED = 0;
100
+ */
101
+ UpdateMode[UpdateMode["UNSPECIFIED"] = 0] = "UNSPECIFIED";
102
+ /**
103
+ * Replace mode: completely overwrites existing metadata (current behavior)
104
+ *
105
+ * @generated from enum value: UPDATE_MODE_REPLACE = 1;
106
+ */
107
+ UpdateMode[UpdateMode["REPLACE"] = 1] = "REPLACE";
108
+ /**
109
+ * Merge mode: preserves existing fields, updates only provided fields
110
+ *
111
+ * @generated from enum value: UPDATE_MODE_MERGE = 2;
112
+ */
113
+ UpdateMode[UpdateMode["MERGE"] = 2] = "MERGE";
114
+ /**
115
+ * Append mode: only adds new entries, never updates existing ones
116
+ *
117
+ * @generated from enum value: UPDATE_MODE_APPEND = 3;
118
+ */
119
+ UpdateMode[UpdateMode["APPEND"] = 3] = "APPEND";
120
+ })(UpdateMode || (UpdateMode = {}));
121
+ /**
122
+ * Describes the enum liquidmetal.v1alpha1.UpdateMode.
123
+ */
124
+ export const UpdateModeSchema = /*@__PURE__*/ enumDesc(file_liquidmetal_v1alpha1_smartsql, 1);
125
+ /**
126
+ * __TITLE__ Smart SQL
127
+ * The Smart SQL service provides intelligent SQL query execution capabilities with natural language
128
+ * to SQL conversion and automatic metadata management. It enables users to interact
129
+ * with databases using both direct SQL queries and natural language descriptions.
130
+ *
131
+ * @generated from service liquidmetal.v1alpha1.SmartSqlService
132
+ */
133
+ export const SmartSqlService = /*@__PURE__*/ serviceDesc(file_liquidmetal_v1alpha1_smartsql, 0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liquidmetal-ai/drizzle",
3
- "version": "0.4.13",
3
+ "version": "0.5.1",
4
4
  "description": "Raindrop core operational libraries",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -21,7 +21,7 @@
21
21
  "vitest": "^2.1.1",
22
22
  "@liquidmetal-ai/eslint-config": "0.0.0",
23
23
  "@liquidmetal-ai/typescript-config": "0.0.0",
24
- "@liquidmetal-ai/raindrop-framework": "0.4.13"
24
+ "@liquidmetal-ai/raindrop-framework": "0.5.1"
25
25
  },
26
26
  "dependencies": {
27
27
  "fflate": "^0.8.2"
@@ -40,6 +40,10 @@ application "my-app" {
40
40
  location_hint = "enam"
41
41
  }
42
42
 
43
+ smartsql "my-smart-sql" {
44
+ location_hint = "enam"
45
+ }
46
+
43
47
  observer "my-observer" {
44
48
  env "API_KEY" {}
45
49
  source {
@@ -195,6 +199,94 @@ application "foo" {
195
199
  ]);
196
200
  });
197
201
 
202
+ test('smartsql basic parsing', () => {
203
+ const CONFIG = `
204
+ application "my-app" {
205
+ smartsql "smartsql-basic-parsing" {}
206
+ }
207
+ `;
208
+ const tokenizer = new Tokenizer(CONFIG);
209
+ const parser = new Parser(tokenizer);
210
+ const ast = parser.parse();
211
+ expect(parser.errors).toEqual([]);
212
+
213
+ const [apps, errors] = buildManifest(ast);
214
+ expect(errors).toEqual([]);
215
+
216
+ // Check that we have exactly one application
217
+ expect(apps.length).toBe(1);
218
+
219
+ // Check that we have exactly one smartsql
220
+ expect(apps[0]!.smartSql.length).toBe(1);
221
+
222
+ // Check the smartsql properties
223
+ const smartSql = apps[0]!.smartSql[0]!;
224
+ expect(valueOf(smartSql.name)).toBe('smartsql-basic-parsing');
225
+ });
226
+
227
+ test('smartsql with invalid properties', () => {
228
+ const CONFIG = `
229
+ application "my-app" {
230
+ smartsql "smartsql-invalid-props" {
231
+ invalid_property = "should fail"
232
+ }
233
+ }
234
+ `;
235
+ const tokenizer = new Tokenizer(CONFIG);
236
+ const parser = new Parser(tokenizer);
237
+ const ast = parser.parse();
238
+ expect(parser.errors).toEqual([]);
239
+
240
+ const [, errors] = buildManifest(ast);
241
+
242
+ // Should have one error for the invalid property
243
+ expect(errors.length).toBe(1);
244
+ expect(errors[0]!.message).toContain('unexpected');
245
+ });
246
+
247
+ test('smartsql integration with other modules', () => {
248
+ const CONFIG = `
249
+ application "my-app" {
250
+ smartsql "smartsql-integration" {}
251
+
252
+ actor "actor-integration" {}
253
+
254
+ service "service-integration" {}
255
+
256
+ bucket "bucket-integration" {}
257
+
258
+ smartbucket "smartbucket-integration" {}
259
+ }
260
+ `;
261
+ const tokenizer = new Tokenizer(CONFIG);
262
+ const parser = new Parser(tokenizer);
263
+ const ast = parser.parse();
264
+ expect(parser.errors).toEqual([]);
265
+
266
+ const [apps, errors] = buildManifest(ast);
267
+ expect(errors).toEqual([]);
268
+
269
+ // Check that we have exactly one application
270
+ expect(apps.length).toBe(1);
271
+ const app = apps[0]!;
272
+
273
+ // Verify all module types are parsed correctly
274
+ expect(app.smartSql.length).toBe(1);
275
+ expect(app.actor.length).toBe(1);
276
+ expect(app.service.length).toBe(1);
277
+ expect(app.bucket.length).toBe(1);
278
+ expect(app.smartBucket.length).toBe(1);
279
+
280
+ // Verify smartsql properties
281
+ expect(valueOf(app.smartSql[0]!.name)).toBe('smartsql-integration');
282
+
283
+ // Verify the other modules still work correctly
284
+ expect(valueOf(app.actor[0]!.name)).toBe('actor-integration');
285
+ expect(valueOf(app.service[0]!.name)).toBe('service-integration');
286
+ expect(valueOf(app.bucket[0]!.name)).toBe('bucket-integration');
287
+ expect(valueOf(app.smartBucket[0]!.name)).toBe('smartbucket-integration');
288
+ });
289
+
198
290
  test('service with labels', () => {
199
291
  const CONFIG = `
200
292
  application "my-app" {
@@ -111,20 +111,20 @@ function buildName1(node: StanzaNode): [TokenString, ConfigError[]] {
111
111
  // node arguments. Returns undefined if no name is provided.
112
112
  function buildOptionalName(node: StanzaNode): [TokenString | undefined, ConfigError[]] {
113
113
  const errors: ConfigError[] = [];
114
-
114
+
115
115
  if (node.args.length === 0) {
116
116
  return [undefined, errors];
117
117
  }
118
-
118
+
119
119
  if (node.args.length > 1) {
120
120
  errors.push({ message: 'unexpected additional args', ...node });
121
121
  }
122
-
122
+
123
123
  if (node.args[0]?.type !== 'string') {
124
124
  errors.push({ message: 'expected string', ...node.args[0]! });
125
125
  return [undefined, errors];
126
126
  }
127
-
127
+
128
128
  return [node.args[0], errors];
129
129
  }
130
130
 
@@ -210,6 +210,9 @@ export function buildApplication(node: StanzaNode): [Application | undefined, Co
210
210
  case 'service':
211
211
  buildStanza(buildService, child, app.service, errors);
212
212
  break;
213
+ case 'mcp_service':
214
+ buildStanza(buildMcpService, child, app.mcpService, errors);
215
+ break;
213
216
  case 'env':
214
217
  buildStanza(buildEnv, child, app.env, errors);
215
218
  break;
@@ -240,6 +243,9 @@ export function buildApplication(node: StanzaNode): [Application | undefined, Co
240
243
  case 'smartbucket':
241
244
  buildStanza(buildSmartBucket, child, app.smartBucket, errors);
242
245
  break;
246
+ case 'smartsql':
247
+ buildStanza(buildSmartSql, child, app.smartSql, errors);
248
+ break;
243
249
  case 'smartmemory':
244
250
  buildStanza(buildSmartMemory, child, app.smartMemory, errors);
245
251
  break;
@@ -316,6 +322,61 @@ function buildService(stanza: StanzaNode): [Service, ConfigError[]] {
316
322
  return [service, errors];
317
323
  }
318
324
 
325
+ function buildMcpService(stanza: StanzaNode): [McpService, ConfigError[]] {
326
+ const errors: ConfigError[] = [];
327
+ const [name, nameErrors] = buildName1(stanza);
328
+ errors.push(...nameErrors);
329
+ const service = new McpService(name, stanza);
330
+ const children = stanza.block ? stanza.block.children : [];
331
+
332
+ for (const child of children) {
333
+ switch (child.type) {
334
+ case 'stanza':
335
+ switch (child.name) {
336
+ case 'route':
337
+ buildStanza(buildRoute, child, service.routes, errors);
338
+ break;
339
+ case 'domain':
340
+ buildStanza(buildDomain, child, service.domains, errors);
341
+ break;
342
+ case 'binding':
343
+ buildStanza(buildBinding, child, service.bindings, errors);
344
+ break;
345
+ case 'env':
346
+ buildStanza(buildEnv, child, service.env, errors);
347
+ break;
348
+ default:
349
+ errors.push({ message: 'unexpected stanza', ...child });
350
+ }
351
+ break;
352
+ case 'assignment':
353
+ switch (child.key.value) {
354
+ case 'visibility':
355
+ buildAssignment(service, 'visibility', 'string', child, errors);
356
+ break;
357
+ case 'authorization_server':
358
+ buildAssignment(service, 'authorizationServer', 'string', child, errors);
359
+ break;
360
+ case 'jwks_url':
361
+ buildAssignment(service, 'jwksUrl', 'string', child, errors);
362
+ break;
363
+ case 'labels':
364
+ buildLabelset(service, 'labels', child, errors);
365
+ break;
366
+ default:
367
+ errors.push({ message: 'unexpected assignment', ...child });
368
+ }
369
+ break;
370
+ case 'comment':
371
+ case 'newline':
372
+ break;
373
+ default:
374
+ errors.push({ message: 'unexpected node', ...child });
375
+ }
376
+ }
377
+ return [service, errors];
378
+ }
379
+
319
380
  function buildBucket(stanza: StanzaNode): [Bucket, ConfigError[]] {
320
381
  const errors: ConfigError[] = [];
321
382
  const [name, nameErrors] = buildName1(stanza);
@@ -424,6 +485,9 @@ function buildSqlDatabase(stanza: StanzaNode): [SqlDatabase, ConfigError[]] {
424
485
  break;
425
486
  case 'assignment':
426
487
  switch (child.key.value) {
488
+ case 'disable_prisma':
489
+ buildAssignment(sqlDatabase, 'disable_prisma', 'boolean', child, errors);
490
+ break;
427
491
  case 'visibility':
428
492
  buildAssignment(sqlDatabase, 'visibility', 'string', child, errors);
429
493
  break;
@@ -497,6 +561,27 @@ function buildSmartBucket(stanza: StanzaNode): [SmartBucket, ConfigError[]] {
497
561
  return [smartBucket, errors];
498
562
  }
499
563
 
564
+ function buildSmartSql(stanza: StanzaNode): [SmartSql, ConfigError[]] {
565
+ const errors: ConfigError[] = [];
566
+ const [name, nameErrors] = buildName1(stanza);
567
+ errors.push(...nameErrors);
568
+ const smartSql = new SmartSql(name, stanza);
569
+ for (const child of stanza.block?.children ?? []) {
570
+ switch (child.type) {
571
+ case 'assignment':
572
+ switch (child.key.value) {
573
+ case 'location_hint':
574
+ buildAssignment(smartSql, 'locationHint', 'string', child, errors);
575
+ break;
576
+ default:
577
+ errors.push({ message: 'unexpected assignment', ...child });
578
+ }
579
+ break;
580
+ }
581
+ }
582
+ return [smartSql, errors];
583
+ }
584
+
500
585
  function buildSmartMemory(stanza: StanzaNode): [SmartMemory, ConfigError[]] {
501
586
  const errors: ConfigError[] = [];
502
587
  const [name, nameErrors] = buildName1(stanza);
@@ -823,8 +908,10 @@ export class Application {
823
908
  vectorIndex: VectorIndex[] = [];
824
909
  kvStore: KvStore[] = [];
825
910
  smartBucket: SmartBucket[] = [];
911
+ smartSql: SmartSql[] = [];
826
912
  smartMemory: SmartMemory[] = [];
827
913
  labels: Record<string, string> = {};
914
+ mcpService: McpService[] = [];
828
915
 
829
916
  constructor(name: TokenString, obj: ConfigObject) {
830
917
  this.name = name;
@@ -833,7 +920,7 @@ export class Application {
833
920
 
834
921
  // Return all objects that require code handlers.
835
922
  handlers(): (Service | Observer | Actor | Task)[] {
836
- return [...this.service, ...this.observer, ...this.actor, ...this.task];
923
+ return [...this.service, ...this.observer, ...this.actor, ...this.task, ...this.mcpService];
837
924
  }
838
925
  }
839
926
 
@@ -869,6 +956,24 @@ export class Actor {
869
956
  }
870
957
  }
871
958
 
959
+ export class McpService {
960
+ obj: ConfigObject;
961
+ name: TokenString;
962
+ visibility?: TokenString;
963
+ routes: Route[] = [];
964
+ domains: Domain[] = [];
965
+ bindings: Binding[] = [];
966
+ env: Env[] = [];
967
+ authorizationServer?: TokenString;
968
+ jwksUrl?: TokenString;
969
+ labels: Record<string, string> = {};
970
+
971
+ constructor(name: TokenString, obj: ConfigObject) {
972
+ this.name = name;
973
+ this.obj = obj;
974
+ }
975
+ }
976
+
872
977
  export class Task {
873
978
  obj: ConfigObject;
874
979
  name: TokenString;
@@ -1025,6 +1130,7 @@ export class SqlDatabase {
1025
1130
  name: TokenString;
1026
1131
  schema?: TokenString;
1027
1132
  visibility?: TokenString;
1133
+ disable_prisma?: TokenBoolean;
1028
1134
  obj: ConfigObject;
1029
1135
 
1030
1136
  constructor(name: TokenString, obj: ConfigObject) {
@@ -1044,6 +1150,17 @@ export class SmartBucket {
1044
1150
  }
1045
1151
  }
1046
1152
 
1153
+ export class SmartSql {
1154
+ name: TokenString;
1155
+ locationHint?: TokenString;
1156
+ obj: ConfigObject;
1157
+
1158
+ constructor(name: TokenString, obj: ConfigObject) {
1159
+ this.name = name;
1160
+ this.obj = obj;
1161
+ }
1162
+ }
1163
+
1047
1164
  export class SmartMemory {
1048
1165
  name: TokenString;
1049
1166
  obj: ConfigObject;