@rcrsr/rill-ext-gemini 0.9.0 → 0.16.0

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.
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  // Generated by dts-bundle-generator v9.5.1
2
2
 
3
- import { ExtensionConfigSchema, ExtensionResult } from '@rcrsr/rill';
3
+ import { ExtensionConfigSchema, ExtensionManifest, ExtensionResult } from '@rcrsr/rill';
4
4
 
5
5
  /**
6
6
  * Base configuration for LLM extensions
@@ -73,8 +73,9 @@ export type GeminiExtensionConfig = LLMProviderConfig;
73
73
  * ```
74
74
  */
75
75
  export declare function createGeminiExtension(config: GeminiExtensionConfig): ExtensionResult;
76
- export declare const VERSION = "0.0.1";
76
+ export declare const VERSION: string;
77
77
  export declare const configSchema: ExtensionConfigSchema;
78
+ export declare const extensionManifest: ExtensionManifest;
78
79
 
79
80
  export {
80
81
  LLMProviderConfig as LLMExtensionConfig,
package/dist/index.js CHANGED
@@ -1,14 +1,18 @@
1
+ // src/index.ts
2
+ import { createRequire } from "module";
3
+
1
4
  // src/factory.ts
2
5
  import {
3
6
  GoogleGenAI,
4
7
  Type
5
8
  } from "@google/genai";
6
9
  import {
7
- RuntimeError as RuntimeError5,
10
+ RuntimeError as RuntimeError6,
8
11
  emitExtensionEvent,
9
12
  createVector,
10
13
  isVector,
11
- isDict as isDict2
14
+ isDict as isDict2,
15
+ rillTypeToTypeValue
12
16
  } from "@rcrsr/rill";
13
17
 
14
18
  // ../../shared/ext-llm/dist/validation.js
@@ -99,6 +103,52 @@ function mapRillType(rillType) {
99
103
  }
100
104
  return jsonType;
101
105
  }
106
+ function buildPropertyFromStructuralType(rillType) {
107
+ if (rillType.type === "closure" || rillType.type === "tuple") {
108
+ throw new RuntimeError3("RILL-R004", `unsupported type for JSON Schema: ${rillType.type}`);
109
+ }
110
+ if (rillType.type === "any") {
111
+ return {};
112
+ }
113
+ if (rillType.type === "list") {
114
+ const property = { type: "array" };
115
+ if (rillType.element !== void 0) {
116
+ property.items = buildPropertyFromStructuralType(rillType.element);
117
+ }
118
+ return property;
119
+ }
120
+ if (rillType.type === "dict") {
121
+ return { type: "object" };
122
+ }
123
+ return { type: mapRillType(rillType.type) };
124
+ }
125
+ function buildJsonSchemaFromStructuralType(type, params) {
126
+ const properties = {};
127
+ const required = [];
128
+ if (type.type === "closure") {
129
+ const closureParams = type.params ?? [];
130
+ for (let i = 0; i < closureParams.length; i++) {
131
+ const fieldDef = closureParams[i];
132
+ const paramName = fieldDef.name ?? `param${i}`;
133
+ const paramType = fieldDef.type;
134
+ const rillParam = params?.[i];
135
+ const property = buildPropertyFromStructuralType(paramType);
136
+ const description = rillParam?.annotations["description"];
137
+ if (typeof description === "string") {
138
+ property.description = description;
139
+ }
140
+ const enumAnnotation = rillParam?.annotations["enum"];
141
+ if (Array.isArray(enumAnnotation)) {
142
+ property.enum = enumAnnotation;
143
+ }
144
+ properties[paramName] = property;
145
+ if (rillParam === void 0 || rillParam.defaultValue === void 0) {
146
+ required.push(paramName);
147
+ }
148
+ }
149
+ }
150
+ return { type: "object", properties, required, additionalProperties: false };
151
+ }
102
152
  function buildJsonSchema(rillSchema) {
103
153
  const properties = {};
104
154
  const required = [];
@@ -179,21 +229,20 @@ async function executeToolCall(toolName, toolInput, tools, context) {
179
229
  throw new RuntimeError4("RILL-R004", `Invalid tool input for ${toolName}: tool must be application, runtime, or script callable`);
180
230
  }
181
231
  try {
182
- let args;
183
- if ((callable.kind === "application" || callable.kind === "script") && callable.params && callable.params.length > 0) {
184
- const params = callable.params;
185
- const inputDict = toolInput;
186
- args = params.map((param) => {
187
- const value = inputDict[param.name];
188
- return value !== void 0 ? value : void 0;
189
- });
190
- } else {
191
- args = [toolInput];
192
- }
232
+ const inputDict = toolInput;
193
233
  if (callable.kind === "script") {
194
234
  if (!context) {
195
235
  throw new RuntimeError4("RILL-R004", `Invalid tool input for ${toolName}: script callable requires a runtime context`);
196
236
  }
237
+ let args;
238
+ if (callable.params && callable.params.length > 0) {
239
+ args = callable.params.map((param) => {
240
+ const value = inputDict[param.name];
241
+ return value !== void 0 ? value : void 0;
242
+ });
243
+ } else {
244
+ args = [inputDict];
245
+ }
197
246
  return await invokeCallable(callable, args, context);
198
247
  }
199
248
  const ctx = context ?? {
@@ -201,7 +250,7 @@ async function executeToolCall(toolName, toolInput, tools, context) {
201
250
  variables: /* @__PURE__ */ new Map(),
202
251
  pipeValue: null
203
252
  };
204
- const result = callable.fn(args, ctx);
253
+ const result = callable.fn(inputDict, ctx);
205
254
  return result instanceof Promise ? await result : result;
206
255
  } catch (error) {
207
256
  if (error instanceof RuntimeError4) {
@@ -294,48 +343,19 @@ async function executeToolLoop(messages, tools, maxErrors, callbacks, emitEvent,
294
343
  throw new RuntimeError4("RILL-R004", `tool_loop: tool "${name}" is not a callable`);
295
344
  }
296
345
  const callable = fnValue;
297
- let description;
298
- if (callable.kind === "script") {
299
- description = callable.annotations["description"] ?? "";
300
- } else {
301
- description = callable.description ?? "";
302
- }
346
+ const description = callable.annotations?.["description"] ?? "";
303
347
  let inputSchema;
304
348
  const params = callable.kind === "application" ? callable.params ?? [] : callable.kind === "script" ? callable.params : [];
305
349
  if (params.length > 0) {
306
- const properties = {};
307
- const required = [];
308
- for (const param of params) {
309
- const property = {};
310
- if (param.typeName !== null) {
311
- const descriptor = {
312
- [param.name]: { type: param.typeName }
313
- };
314
- const schema = buildJsonSchema(descriptor);
315
- const built = schema.properties[param.name];
316
- if (built !== void 0) {
317
- Object.assign(property, built);
318
- }
319
- }
320
- let paramDesc;
321
- if (callable.kind === "script") {
322
- const annot = callable.paramAnnotations[param.name];
323
- paramDesc = annot?.["description"] ?? "";
324
- } else {
325
- paramDesc = param.description ?? "";
326
- }
327
- if (paramDesc) {
328
- property["description"] = paramDesc;
329
- }
330
- properties[param.name] = property;
331
- if (param.defaultValue === null) {
332
- required.push(param.name);
333
- }
334
- }
350
+ const closureType = {
351
+ type: "closure",
352
+ params: params.map((p2) => ({ name: p2.name, type: p2.type ?? { type: "any" } }))
353
+ };
354
+ const builtSchema = buildJsonSchemaFromStructuralType(closureType, [...params]);
335
355
  inputSchema = {
336
356
  type: "object",
337
- properties,
338
- required
357
+ properties: builtSchema.properties,
358
+ required: builtSchema.required
339
359
  };
340
360
  } else {
341
361
  inputSchema = { type: "object", properties: {}, required: [] };
@@ -455,6 +475,128 @@ async function executeToolLoop(messages, tools, maxErrors, callbacks, emitEvent,
455
475
  };
456
476
  }
457
477
 
478
+ // ../../shared/ext-param/dist/param.js
479
+ import { RuntimeError as RuntimeError5 } from "@rcrsr/rill";
480
+ function validateParamName(name) {
481
+ if (name === "") {
482
+ throw new RuntimeError5("RILL-R001", "param name must not be empty");
483
+ }
484
+ if (/\s/.test(name)) {
485
+ throw new RuntimeError5("RILL-R001", "param name must be a valid identifier");
486
+ }
487
+ }
488
+ function buildAnnotations(desc) {
489
+ if (desc !== void 0) {
490
+ return { description: desc };
491
+ }
492
+ return {};
493
+ }
494
+ var p = {
495
+ /**
496
+ * IR-1: Creates a string parameter descriptor.
497
+ *
498
+ * @param name - Parameter name (must be a valid identifier)
499
+ * @param desc - Optional description
500
+ * @returns RillParam with type 'string'
501
+ */
502
+ str(name, desc) {
503
+ validateParamName(name);
504
+ return {
505
+ name,
506
+ type: { type: "string" },
507
+ defaultValue: void 0,
508
+ annotations: buildAnnotations(desc)
509
+ };
510
+ },
511
+ /**
512
+ * IR-2: Creates a number parameter descriptor.
513
+ *
514
+ * @param name - Parameter name (must be a valid identifier)
515
+ * @param desc - Optional description
516
+ * @param def - Optional default value
517
+ * @returns RillParam with type 'number'
518
+ */
519
+ num(name, desc, def) {
520
+ validateParamName(name);
521
+ return {
522
+ name,
523
+ type: { type: "number" },
524
+ defaultValue: def,
525
+ annotations: buildAnnotations(desc)
526
+ };
527
+ },
528
+ /**
529
+ * IR-3: Creates a boolean parameter descriptor.
530
+ *
531
+ * @param name - Parameter name (must be a valid identifier)
532
+ * @param desc - Optional description
533
+ * @param def - Optional default value
534
+ * @returns RillParam with type 'bool'
535
+ */
536
+ bool(name, desc, def) {
537
+ validateParamName(name);
538
+ return {
539
+ name,
540
+ type: { type: "bool" },
541
+ defaultValue: def,
542
+ annotations: buildAnnotations(desc)
543
+ };
544
+ },
545
+ /**
546
+ * IR-4: Creates a dict parameter descriptor.
547
+ *
548
+ * @param name - Parameter name (must be a valid identifier)
549
+ * @param desc - Optional description
550
+ * @param def - Optional default value
551
+ * @param fields - Optional structural field definitions (RillFieldDef with type and optional defaultValue)
552
+ * @returns RillParam with type 'dict' (with fields if provided)
553
+ */
554
+ dict(name, desc, def, fields) {
555
+ validateParamName(name);
556
+ const type = fields !== void 0 ? { type: "dict", fields } : { type: "dict" };
557
+ return {
558
+ name,
559
+ type,
560
+ defaultValue: def,
561
+ annotations: buildAnnotations(desc)
562
+ };
563
+ },
564
+ /**
565
+ * IR-5: Creates a list parameter descriptor.
566
+ *
567
+ * @param name - Parameter name (must be a valid identifier)
568
+ * @param itemType - Optional element type; omitted when not provided
569
+ * @param desc - Optional description
570
+ * @returns RillParam with type 'list' (with element if itemType provided)
571
+ */
572
+ list(name, itemType, desc) {
573
+ validateParamName(name);
574
+ const type = itemType !== void 0 ? { type: "list", element: itemType } : { type: "list" };
575
+ return {
576
+ name,
577
+ type,
578
+ defaultValue: void 0,
579
+ annotations: buildAnnotations(desc)
580
+ };
581
+ },
582
+ /**
583
+ * IR-6: Creates a callable parameter descriptor.
584
+ *
585
+ * @param name - Parameter name (must be a valid identifier)
586
+ * @param desc - Optional description
587
+ * @returns RillParam with type 'closure'
588
+ */
589
+ callable(name, desc) {
590
+ validateParamName(name);
591
+ return {
592
+ name,
593
+ type: { type: "closure" },
594
+ defaultValue: void 0,
595
+ annotations: buildAnnotations(desc)
596
+ };
597
+ }
598
+ };
599
+
458
600
  // src/factory.ts
459
601
  var DEFAULT_MAX_TOKENS = 8192;
460
602
  var detectGeminiError = (error) => {
@@ -535,16 +677,19 @@ function createGeminiExtension(config) {
535
677
  // IR-4: gemini::message
536
678
  message: {
537
679
  params: [
538
- { name: "text", type: "string" },
539
- { name: "options", type: "dict", defaultValue: {} }
680
+ p.str("text"),
681
+ p.dict("options", void 0, {}, {
682
+ system: { type: { type: "string" }, defaultValue: "" },
683
+ max_tokens: { type: { type: "number" }, defaultValue: 0 }
684
+ })
540
685
  ],
541
686
  fn: async (args, ctx) => {
542
687
  const startTime = Date.now();
543
688
  try {
544
- const text = args[0];
545
- const options = args[1] ?? {};
689
+ const text = args["text"];
690
+ const options = args["options"] ?? {};
546
691
  if (text.trim().length === 0) {
547
- throw new RuntimeError5("RILL-R004", "prompt text cannot be empty");
692
+ throw new RuntimeError6("RILL-R004", "prompt text cannot be empty");
548
693
  }
549
694
  const system = typeof options["system"] === "string" ? options["system"] : factorySystem;
550
695
  const maxTokens = typeof options["max_tokens"] === "number" ? options["max_tokens"] : factoryMaxTokens;
@@ -600,7 +745,7 @@ function createGeminiExtension(config) {
600
745
  return result2;
601
746
  } catch (error) {
602
747
  const duration = Date.now() - startTime;
603
- const rillError = error instanceof RuntimeError5 ? error : mapProviderError("Gemini", error, detectGeminiError);
748
+ const rillError = error instanceof RuntimeError6 ? error : mapProviderError("Gemini", error, detectGeminiError);
604
749
  emitExtensionEvent(ctx, {
605
750
  event: "gemini:error",
606
751
  subsystem: "extension:gemini",
@@ -610,22 +755,35 @@ function createGeminiExtension(config) {
610
755
  throw rillError;
611
756
  }
612
757
  },
613
- description: "Send single message to Gemini API",
614
- returnType: "dict"
758
+ annotations: { description: "Send single message to Gemini API" },
759
+ returnType: rillTypeToTypeValue({
760
+ type: "dict",
761
+ fields: {
762
+ content: { type: { type: "string" } },
763
+ model: { type: { type: "string" } },
764
+ usage: { type: { type: "dict", fields: { input: { type: { type: "number" } }, output: { type: { type: "number" } } } } },
765
+ stop_reason: { type: { type: "string" } },
766
+ id: { type: { type: "string" } },
767
+ messages: { type: { type: "list", element: { type: "dict" } } }
768
+ }
769
+ })
615
770
  },
616
771
  // IR-5: gemini::messages
617
772
  messages: {
618
773
  params: [
619
- { name: "messages", type: "list" },
620
- { name: "options", type: "dict", defaultValue: {} }
774
+ p.list("messages", { type: "dict", fields: { role: { type: { type: "string" } }, content: { type: { type: "string" } } } }),
775
+ p.dict("options", void 0, {}, {
776
+ system: { type: { type: "string" }, defaultValue: "" },
777
+ max_tokens: { type: { type: "number" }, defaultValue: 0 }
778
+ })
621
779
  ],
622
780
  fn: async (args, ctx) => {
623
781
  const startTime = Date.now();
624
782
  try {
625
- const messages = args[0];
626
- const options = args[1] ?? {};
783
+ const messages = args["messages"];
784
+ const options = args["options"] ?? {};
627
785
  if (messages.length === 0) {
628
- throw new RuntimeError5(
786
+ throw new RuntimeError6(
629
787
  "RILL-R004",
630
788
  "messages list cannot be empty"
631
789
  );
@@ -636,18 +794,18 @@ function createGeminiExtension(config) {
636
794
  for (let i = 0; i < messages.length; i++) {
637
795
  const msg = messages[i];
638
796
  if (!msg || typeof msg !== "object" || !("role" in msg)) {
639
- throw new RuntimeError5(
797
+ throw new RuntimeError6(
640
798
  "RILL-R004",
641
799
  "message missing required 'role' field"
642
800
  );
643
801
  }
644
802
  const role = msg["role"];
645
803
  if (role !== "user" && role !== "assistant" && role !== "tool") {
646
- throw new RuntimeError5("RILL-R004", `invalid role '${role}'`);
804
+ throw new RuntimeError6("RILL-R004", `invalid role '${role}'`);
647
805
  }
648
806
  if (role === "user" || role === "tool") {
649
807
  if (!("content" in msg) || typeof msg["content"] !== "string") {
650
- throw new RuntimeError5(
808
+ throw new RuntimeError6(
651
809
  "RILL-R004",
652
810
  `${role} message requires 'content'`
653
811
  );
@@ -660,7 +818,7 @@ function createGeminiExtension(config) {
660
818
  const hasContent = "content" in msg && msg["content"];
661
819
  const hasToolCalls = "tool_calls" in msg && msg["tool_calls"];
662
820
  if (!hasContent && !hasToolCalls) {
663
- throw new RuntimeError5(
821
+ throw new RuntimeError6(
664
822
  "RILL-R004",
665
823
  "assistant message requires 'content' or 'tool_calls'"
666
824
  );
@@ -724,7 +882,7 @@ function createGeminiExtension(config) {
724
882
  return result2;
725
883
  } catch (error) {
726
884
  const duration = Date.now() - startTime;
727
- const rillError = error instanceof RuntimeError5 ? error : mapProviderError("Gemini", error, detectGeminiError);
885
+ const rillError = error instanceof RuntimeError6 ? error : mapProviderError("Gemini", error, detectGeminiError);
728
886
  emitExtensionEvent(ctx, {
729
887
  event: "gemini:error",
730
888
  subsystem: "extension:gemini",
@@ -734,16 +892,26 @@ function createGeminiExtension(config) {
734
892
  throw rillError;
735
893
  }
736
894
  },
737
- description: "Send multi-turn conversation to Gemini API",
738
- returnType: "dict"
895
+ annotations: { description: "Send multi-turn conversation to Gemini API" },
896
+ returnType: rillTypeToTypeValue({
897
+ type: "dict",
898
+ fields: {
899
+ content: { type: { type: "string" } },
900
+ model: { type: { type: "string" } },
901
+ usage: { type: { type: "dict", fields: { input: { type: { type: "number" } }, output: { type: { type: "number" } } } } },
902
+ stop_reason: { type: { type: "string" } },
903
+ id: { type: { type: "string" } },
904
+ messages: { type: { type: "list", element: { type: "dict" } } }
905
+ }
906
+ })
739
907
  },
740
908
  // IR-6: gemini::embed
741
909
  embed: {
742
- params: [{ name: "text", type: "string" }],
910
+ params: [p.str("text")],
743
911
  fn: async (args, ctx) => {
744
912
  const startTime = Date.now();
745
913
  try {
746
- const text = args[0];
914
+ const text = args["text"];
747
915
  validateEmbedText(text);
748
916
  validateEmbedModel(factoryEmbedModel);
749
917
  const response = await client.models.embedContent({
@@ -752,7 +920,7 @@ function createGeminiExtension(config) {
752
920
  });
753
921
  const embedding = response.embeddings?.[0];
754
922
  if (!embedding || !embedding.values || embedding.values.length === 0) {
755
- throw new RuntimeError5(
923
+ throw new RuntimeError6(
756
924
  "RILL-R004",
757
925
  "Gemini: empty embedding returned"
758
926
  );
@@ -770,7 +938,7 @@ function createGeminiExtension(config) {
770
938
  return vector;
771
939
  } catch (error) {
772
940
  const duration = Date.now() - startTime;
773
- const rillError = error instanceof RuntimeError5 ? error : mapProviderError("Gemini", error, detectGeminiError);
941
+ const rillError = error instanceof RuntimeError6 ? error : mapProviderError("Gemini", error, detectGeminiError);
774
942
  emitExtensionEvent(ctx, {
775
943
  event: "gemini:error",
776
944
  subsystem: "extension:gemini",
@@ -780,16 +948,16 @@ function createGeminiExtension(config) {
780
948
  throw rillError;
781
949
  }
782
950
  },
783
- description: "Generate embedding vector for text",
784
- returnType: "vector"
951
+ annotations: { description: "Generate embedding vector for text" },
952
+ returnType: rillTypeToTypeValue({ type: "vector" })
785
953
  },
786
954
  // IR-7: gemini::embed_batch
787
955
  embed_batch: {
788
- params: [{ name: "texts", type: "list" }],
956
+ params: [p.list("texts")],
789
957
  fn: async (args, ctx) => {
790
958
  const startTime = Date.now();
791
959
  try {
792
- const texts = args[0];
960
+ const texts = args["texts"];
793
961
  if (texts.length === 0) {
794
962
  return [];
795
963
  }
@@ -801,14 +969,14 @@ function createGeminiExtension(config) {
801
969
  });
802
970
  const vectors = [];
803
971
  if (!response.embeddings || response.embeddings.length === 0) {
804
- throw new RuntimeError5(
972
+ throw new RuntimeError6(
805
973
  "RILL-R004",
806
974
  "Gemini: empty embeddings returned"
807
975
  );
808
976
  }
809
977
  for (const embedding of response.embeddings) {
810
978
  if (!embedding || !embedding.values || embedding.values.length === 0) {
811
- throw new RuntimeError5(
979
+ throw new RuntimeError6(
812
980
  "RILL-R004",
813
981
  "Gemini: empty embedding returned"
814
982
  );
@@ -831,7 +999,7 @@ function createGeminiExtension(config) {
831
999
  return vectors;
832
1000
  } catch (error) {
833
1001
  const duration = Date.now() - startTime;
834
- const rillError = error instanceof RuntimeError5 ? error : mapProviderError("Gemini", error, detectGeminiError);
1002
+ const rillError = error instanceof RuntimeError6 ? error : mapProviderError("Gemini", error, detectGeminiError);
835
1003
  emitExtensionEvent(ctx, {
836
1004
  event: "gemini:error",
837
1005
  subsystem: "extension:gemini",
@@ -841,25 +1009,32 @@ function createGeminiExtension(config) {
841
1009
  throw rillError;
842
1010
  }
843
1011
  },
844
- description: "Generate embedding vectors for multiple texts",
845
- returnType: "list"
1012
+ annotations: { description: "Generate embedding vectors for multiple texts" },
1013
+ returnType: rillTypeToTypeValue({ type: "list", element: { type: "vector" } })
846
1014
  },
847
1015
  // IR-8: gemini::tool_loop
848
1016
  tool_loop: {
849
1017
  params: [
850
- { name: "prompt", type: "string" },
851
- { name: "options", type: "dict", defaultValue: {} }
1018
+ p.str("prompt"),
1019
+ p.dict("options", void 0, {}, {
1020
+ tools: { type: { type: "dict" } },
1021
+ system: { type: { type: "string" }, defaultValue: "" },
1022
+ max_tokens: { type: { type: "number" }, defaultValue: 0 },
1023
+ max_errors: { type: { type: "number" }, defaultValue: 3 },
1024
+ max_turns: { type: { type: "number" }, defaultValue: 10 },
1025
+ messages: { type: { type: "list", element: { type: "dict", fields: { role: { type: { type: "string" } }, content: { type: { type: "string" } } } } }, defaultValue: [] }
1026
+ })
852
1027
  ],
853
1028
  fn: async (args, ctx) => {
854
1029
  const startTime = Date.now();
855
1030
  try {
856
- const prompt = args[0];
857
- const options = args[1] ?? {};
1031
+ const prompt = args["prompt"];
1032
+ const options = args["options"] ?? {};
858
1033
  if (prompt.trim().length === 0) {
859
- throw new RuntimeError5("RILL-R004", "prompt text cannot be empty");
1034
+ throw new RuntimeError6("RILL-R004", "prompt text cannot be empty");
860
1035
  }
861
1036
  if (!("tools" in options) || !isDict2(options["tools"])) {
862
- throw new RuntimeError5(
1037
+ throw new RuntimeError6(
863
1038
  "RILL-R004",
864
1039
  "tool_loop requires 'tools' option"
865
1040
  );
@@ -1036,7 +1211,7 @@ function createGeminiExtension(config) {
1036
1211
  return result2;
1037
1212
  } catch (error) {
1038
1213
  const duration = Date.now() - startTime;
1039
- const rillError = error instanceof RuntimeError5 ? error : mapProviderError("Gemini", error, detectGeminiError);
1214
+ const rillError = error instanceof RuntimeError6 ? error : mapProviderError("Gemini", error, detectGeminiError);
1040
1215
  emitExtensionEvent(ctx, {
1041
1216
  event: "gemini:error",
1042
1217
  subsystem: "extension:gemini",
@@ -1046,22 +1221,37 @@ function createGeminiExtension(config) {
1046
1221
  throw rillError;
1047
1222
  }
1048
1223
  },
1049
- description: "Execute tool-use loop with Gemini API",
1050
- returnType: "dict"
1224
+ annotations: { description: "Execute tool-use loop with Gemini API" },
1225
+ returnType: rillTypeToTypeValue({
1226
+ type: "dict",
1227
+ fields: {
1228
+ content: { type: { type: "string" } },
1229
+ model: { type: { type: "string" } },
1230
+ usage: { type: { type: "dict", fields: { input: { type: { type: "number" } }, output: { type: { type: "number" } } } } },
1231
+ stop_reason: { type: { type: "string" } },
1232
+ turns: { type: { type: "number" } },
1233
+ messages: { type: { type: "list", element: { type: "dict" } } }
1234
+ }
1235
+ })
1051
1236
  },
1052
1237
  // IR-3: gemini::generate
1053
1238
  generate: {
1054
1239
  params: [
1055
- { name: "prompt", type: "string" },
1056
- { name: "options", type: "dict" }
1240
+ p.str("prompt"),
1241
+ p.dict("options", void 0, {}, {
1242
+ schema: { type: { type: "dict" } },
1243
+ system: { type: { type: "string" }, defaultValue: "" },
1244
+ max_tokens: { type: { type: "number" }, defaultValue: 0 },
1245
+ messages: { type: { type: "list", element: { type: "dict", fields: { role: { type: { type: "string" } }, content: { type: { type: "string" } } } } }, defaultValue: [] }
1246
+ })
1057
1247
  ],
1058
1248
  fn: async (args, ctx) => {
1059
1249
  const startTime = Date.now();
1060
1250
  try {
1061
- const prompt = args[0];
1062
- const options = args[1] ?? {};
1251
+ const prompt = args["prompt"];
1252
+ const options = args["options"] ?? {};
1063
1253
  if (!("schema" in options) || options["schema"] === null || options["schema"] === void 0) {
1064
- throw new RuntimeError5(
1254
+ throw new RuntimeError6(
1065
1255
  "RILL-R004",
1066
1256
  "generate requires 'schema' option"
1067
1257
  );
@@ -1127,7 +1317,7 @@ function createGeminiExtension(config) {
1127
1317
  data = JSON.parse(raw);
1128
1318
  } catch (parseError) {
1129
1319
  const detail = parseError instanceof Error ? parseError.message : String(parseError);
1130
- throw new RuntimeError5(
1320
+ throw new RuntimeError6(
1131
1321
  "RILL-R004",
1132
1322
  `generate: failed to parse response JSON: ${detail}`
1133
1323
  );
@@ -1160,7 +1350,7 @@ function createGeminiExtension(config) {
1160
1350
  return generateResult;
1161
1351
  } catch (error) {
1162
1352
  const duration = Date.now() - startTime;
1163
- const rillError = error instanceof RuntimeError5 ? error : mapProviderError("Gemini", error, detectGeminiError);
1353
+ const rillError = error instanceof RuntimeError6 ? error : mapProviderError("Gemini", error, detectGeminiError);
1164
1354
  emitExtensionEvent(ctx, {
1165
1355
  event: "gemini:error",
1166
1356
  subsystem: "extension:gemini",
@@ -1170,8 +1360,18 @@ function createGeminiExtension(config) {
1170
1360
  throw rillError;
1171
1361
  }
1172
1362
  },
1173
- description: "Generate structured output from Gemini API",
1174
- returnType: "dict"
1363
+ annotations: { description: "Generate structured output from Gemini API" },
1364
+ returnType: rillTypeToTypeValue({
1365
+ type: "dict",
1366
+ fields: {
1367
+ data: { type: { type: "any" } },
1368
+ raw: { type: { type: "string" } },
1369
+ model: { type: { type: "string" } },
1370
+ usage: { type: { type: "dict", fields: { input: { type: { type: "number" } }, output: { type: { type: "number" } } } } },
1371
+ stop_reason: { type: { type: "string" } },
1372
+ id: { type: { type: "string" } }
1373
+ }
1374
+ })
1175
1375
  }
1176
1376
  };
1177
1377
  result.dispose = dispose;
@@ -1179,7 +1379,9 @@ function createGeminiExtension(config) {
1179
1379
  }
1180
1380
 
1181
1381
  // src/index.ts
1182
- var VERSION = "0.0.1";
1382
+ var _require = createRequire(import.meta.url);
1383
+ var _pkg = _require("../package.json");
1384
+ var VERSION = _pkg.version;
1183
1385
  var configSchema = {
1184
1386
  api_key: { type: "string", required: true, secret: true },
1185
1387
  model: { type: "string", required: true },
@@ -1191,8 +1393,14 @@ var configSchema = {
1191
1393
  system: { type: "string" },
1192
1394
  embed_model: { type: "string" }
1193
1395
  };
1396
+ var extensionManifest = {
1397
+ factory: createGeminiExtension,
1398
+ configSchema,
1399
+ version: VERSION
1400
+ };
1194
1401
  export {
1195
1402
  VERSION,
1196
1403
  configSchema,
1197
- createGeminiExtension
1404
+ createGeminiExtension,
1405
+ extensionManifest
1198
1406
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rcrsr/rill-ext-gemini",
3
- "version": "0.9.0",
3
+ "version": "0.16.0",
4
4
  "description": "rill extension for Google Gemini API integration",
5
5
  "license": "MIT",
6
6
  "author": "Andre Bremer",
@@ -17,10 +17,10 @@
17
17
  "scripting"
18
18
  ],
19
19
  "peerDependencies": {
20
- "@rcrsr/rill": "^0.9.0"
20
+ "@rcrsr/rill": "~0.16.0"
21
21
  },
22
22
  "devDependencies": {
23
- "@rcrsr/rill": "^0.9.0",
23
+ "@rcrsr/rill": "~0.16.0",
24
24
  "@types/node": "^25.3.0",
25
25
  "dts-bundle-generator": "^9.5.1",
26
26
  "tsup": "^8.5.1",
@@ -43,7 +43,8 @@
43
43
  "access": "public"
44
44
  },
45
45
  "dependencies": {
46
- "@google/genai": "^1.42.0"
46
+ "@google/genai": "^1.42.0",
47
+ "@rcrsr/rill-ext-param-shared": "0.0.1"
47
48
  },
48
49
  "scripts": {
49
50
  "build": "tsup && dts-bundle-generator --config dts-bundle-generator.config.cjs",