@rcrsr/rill-ext-gemini 0.18.3 → 0.19.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.
Files changed (2) hide show
  1. package/dist/index.js +223 -88
  2. package/package.json +8 -8
package/dist/index.js CHANGED
@@ -7,11 +7,13 @@ import {
7
7
  Type
8
8
  } from "@google/genai";
9
9
  import {
10
- RuntimeError as RuntimeError6,
10
+ RuntimeError as RuntimeError5,
11
+ RuntimeHaltSignal as RuntimeHaltSignal3,
11
12
  emitExtensionEvent,
12
13
  createRillStream,
13
14
  createVector,
14
15
  isVector,
16
+ getStatus as getStatus2,
15
17
  structureToTypeValue,
16
18
  toCallable
17
19
  } from "@rcrsr/rill";
@@ -67,27 +69,133 @@ function validateEmbedModel(model) {
67
69
  }
68
70
 
69
71
  // ../../shared/ext-llm/dist/errors.js
70
- import { RuntimeError as RuntimeError2 } from "@rcrsr/rill";
71
- function mapProviderError(providerName, error, detect) {
72
+ import { RuntimeHaltSignal } from "@rcrsr/rill";
73
+ function atomForStatus(status) {
74
+ if (status === 401)
75
+ return "AUTH";
76
+ if (status === 403)
77
+ return "FORBIDDEN";
78
+ if (status === 404)
79
+ return "NOT_FOUND";
80
+ if (status === 408)
81
+ return "TIMEOUT";
82
+ if (status === 409 || status === 412)
83
+ return "CONFLICT";
84
+ if (status === 429)
85
+ return "RATE_LIMIT";
86
+ if (status === 402)
87
+ return "QUOTA_EXCEEDED";
88
+ if (status >= 500 && status <= 599)
89
+ return "UNAVAILABLE";
90
+ if (status >= 400 && status <= 499)
91
+ return "INVALID_INPUT";
92
+ return "UNAVAILABLE";
93
+ }
94
+ function kindForStatus(status) {
95
+ if (status === 401)
96
+ return "authentication_failed";
97
+ if (status === 403)
98
+ return "forbidden";
99
+ if (status === 404)
100
+ return "not_found";
101
+ if (status === 408)
102
+ return "request_timeout";
103
+ if (status === 409 || status === 412)
104
+ return "conflict";
105
+ if (status === 429)
106
+ return "rate_limit_exceeded";
107
+ if (status === 402)
108
+ return "quota_exceeded";
109
+ if (status >= 500 && status <= 599)
110
+ return "server_error";
111
+ return "http_error";
112
+ }
113
+ function mapProviderError(ctx, provider, error, detect) {
114
+ if (error instanceof RuntimeHaltSignal) {
115
+ return ctx.invalidate(error, {
116
+ code: "TIMEOUT",
117
+ provider,
118
+ raw: { kind: "request_cancelled", message: `${provider}: request cancelled` }
119
+ });
120
+ }
121
+ if (error instanceof Error && error.name === "AbortError") {
122
+ return ctx.invalidate(error, {
123
+ code: "TIMEOUT",
124
+ provider,
125
+ raw: {
126
+ kind: "request_timeout",
127
+ message: `${provider} error: ${error.message}`
128
+ }
129
+ });
130
+ }
72
131
  const detected = detect(error);
73
132
  if (detected !== null) {
74
133
  const { status, message } = detected;
75
134
  if (status !== void 0) {
76
- return new RuntimeError2("RILL-R004", `${providerName} API error (HTTP ${status}): ${message}`, void 0, { cause: error });
135
+ return ctx.invalidate(error, {
136
+ code: atomForStatus(status),
137
+ provider,
138
+ raw: {
139
+ kind: kindForStatus(status),
140
+ status,
141
+ message: `${provider} API error (HTTP ${status}): ${message}`
142
+ }
143
+ });
77
144
  }
78
- return new RuntimeError2("RILL-R004", `${providerName} API error: ${message}`, void 0, { cause: error });
145
+ return ctx.invalidate(error, {
146
+ code: "UNAVAILABLE",
147
+ provider,
148
+ raw: {
149
+ kind: "provider_error",
150
+ message: `${provider} API error: ${message}`
151
+ }
152
+ });
153
+ }
154
+ if (error instanceof TypeError) {
155
+ return ctx.invalidate(error, {
156
+ code: "UNAVAILABLE",
157
+ provider,
158
+ raw: {
159
+ kind: "connection_failed",
160
+ message: `${provider} error: ${error.message}`
161
+ }
162
+ });
163
+ }
164
+ if (error instanceof SyntaxError) {
165
+ return ctx.invalidate(error, {
166
+ code: "PROTOCOL",
167
+ provider,
168
+ raw: {
169
+ kind: "unexpected_response_format",
170
+ message: `${provider} error: ${error.message}`
171
+ }
172
+ });
79
173
  }
80
174
  if (error instanceof Error) {
81
- return new RuntimeError2("RILL-R004", `${providerName} error: ${error.message}`, void 0, { cause: error });
175
+ return ctx.invalidate(error, {
176
+ code: "UNAVAILABLE",
177
+ provider,
178
+ raw: {
179
+ kind: "unknown_error",
180
+ message: `${provider} error: ${error.message}`
181
+ }
182
+ });
82
183
  }
83
- return new RuntimeError2("RILL-R004", `${providerName} error: Unknown error`, void 0, { cause: error });
184
+ return ctx.invalidate(error, {
185
+ code: "UNAVAILABLE",
186
+ provider,
187
+ raw: {
188
+ kind: "unknown_error",
189
+ message: `${provider} error: Unknown error`
190
+ }
191
+ });
84
192
  }
85
193
 
86
194
  // ../../shared/ext-llm/dist/tool-loop.js
87
- import { invokeCallable, isCallable, isDict, isRuntimeCallable, RuntimeError as RuntimeError4 } from "@rcrsr/rill";
195
+ import { getStatus, invokeCallable, isCallable, isDict, isRuntimeCallable, RuntimeError as RuntimeError3, RuntimeHaltSignal as RuntimeHaltSignal2 } from "@rcrsr/rill";
88
196
 
89
197
  // ../../shared/ext-llm/dist/schema.js
90
- import { RuntimeError as RuntimeError3 } from "@rcrsr/rill";
198
+ import { RuntimeError as RuntimeError2 } from "@rcrsr/rill";
91
199
  var RILL_TYPE_MAP = {
92
200
  string: "string",
93
201
  number: "number",
@@ -100,13 +208,13 @@ var RILL_TYPE_MAP = {
100
208
  function mapRillType(rillType) {
101
209
  const jsonType = RILL_TYPE_MAP[rillType];
102
210
  if (jsonType === void 0) {
103
- throw new RuntimeError3("RILL-R004", `unsupported type: ${rillType}`);
211
+ throw new RuntimeError2("RILL-R005", `unsupported type: ${rillType}`);
104
212
  }
105
213
  return jsonType;
106
214
  }
107
215
  function buildPropertyFromStructuralType(rillType) {
108
216
  if (rillType.kind === "closure" || rillType.kind === "tuple") {
109
- throw new RuntimeError3("RILL-R004", `unsupported type for JSON Schema: ${rillType.kind}`);
217
+ throw new RuntimeError2("RILL-R005", `unsupported type for JSON Schema: ${rillType.kind}`);
110
218
  }
111
219
  if (rillType.kind === "any") {
112
220
  return {};
@@ -156,7 +264,7 @@ function buildJsonSchemaFromStructuralType(type, params) {
156
264
  return buildDictSchema(type);
157
265
  }
158
266
  if (type.kind !== "closure") {
159
- throw new RuntimeError3("RILL-R004", `unsupported schema kind: ${type.kind} (expected dict or closure)`);
267
+ throw new RuntimeError2("RILL-R005", `unsupported schema kind: ${type.kind} (expected dict or closure)`);
160
268
  }
161
269
  const properties = {};
162
270
  const required = [];
@@ -184,30 +292,51 @@ function buildJsonSchemaFromStructuralType(type, params) {
184
292
  }
185
293
 
186
294
  // ../../shared/ext-llm/dist/tool-loop.js
295
+ function readHaltMessage(halt) {
296
+ const status = getStatus(halt.value);
297
+ if (typeof status.message === "string" && status.message.length > 0) {
298
+ return status.message;
299
+ }
300
+ return halt.message;
301
+ }
302
+ function throwToolLoopHalt(ctx, code, kind, message) {
303
+ if (ctx !== void 0) {
304
+ const hostCtx = ctx;
305
+ if (typeof hostCtx.invalidate === "function") {
306
+ const invalid = hostCtx.invalidate(new Error(message), {
307
+ code,
308
+ provider: "tool_loop",
309
+ raw: { kind, message }
310
+ });
311
+ throw new RuntimeHaltSignal2(invalid, true);
312
+ }
313
+ }
314
+ throw new RuntimeError3("RILL-R005", message);
315
+ }
187
316
  async function executeToolCall(toolName, toolInput, tools, context) {
188
317
  if (!isDict(tools)) {
189
- throw new RuntimeError4("RILL-R004", "tool_loop: tools must be a dict of name \u2192 callable");
318
+ throwToolLoopHalt(context, "INVALID_INPUT", "tools_not_dict", "tool_loop: tools must be a dict of name \u2192 callable");
190
319
  }
191
320
  const toolsDict = tools;
192
321
  const toolFn = toolsDict[toolName];
193
322
  if (toolFn === void 0 || toolFn === null) {
194
- throw new RuntimeError4("RILL-R004", `Unknown tool: ${toolName}`);
323
+ throwToolLoopHalt(context, "NOT_FOUND", "unknown_tool", `Unknown tool: ${toolName}`);
195
324
  }
196
325
  if (!isCallable(toolFn)) {
197
- throw new RuntimeError4("RILL-R004", `Invalid tool input for ${toolName}: tool must be callable`);
326
+ throwToolLoopHalt(context, "INVALID_INPUT", "tool_not_callable", `Invalid tool input for ${toolName}: tool must be callable`);
198
327
  }
199
328
  if (typeof toolInput !== "object" || toolInput === null) {
200
- throw new RuntimeError4("RILL-R004", `Invalid tool input for ${toolName}: input must be an object`);
329
+ throwToolLoopHalt(context, "INVALID_INPUT", "invalid_tool_input", `Invalid tool input for ${toolName}: input must be an object`);
201
330
  }
202
331
  const callable = toolFn;
203
332
  if (callable.kind !== "runtime" && callable.kind !== "application" && callable.kind !== "script") {
204
- throw new RuntimeError4("RILL-R004", `Invalid tool input for ${toolName}: tool must be application, runtime, or script callable`);
333
+ throwToolLoopHalt(context, "INVALID_INPUT", "tool_kind_unsupported", `Invalid tool input for ${toolName}: tool must be application, runtime, or script callable`);
205
334
  }
206
335
  try {
207
336
  const inputDict = toolInput;
208
337
  if (callable.kind === "script") {
209
338
  if (!context) {
210
- throw new RuntimeError4("RILL-R004", `Invalid tool input for ${toolName}: script callable requires a runtime context`);
339
+ throw new RuntimeError3("RILL-R005", `Invalid tool input for ${toolName}: script callable requires a runtime context`);
211
340
  }
212
341
  let args;
213
342
  if (callable.params && callable.params.length > 0) {
@@ -223,16 +352,17 @@ async function executeToolCall(toolName, toolInput, tools, context) {
223
352
  const ctx = context ?? {
224
353
  parent: void 0,
225
354
  variables: /* @__PURE__ */ new Map(),
226
- pipeValue: null
355
+ pipeValue: null,
356
+ hostContext: {}
227
357
  };
228
358
  const result = callable.fn(inputDict, ctx);
229
359
  return result instanceof Promise ? await result : result;
230
360
  } catch (error) {
231
- if (error instanceof RuntimeError4) {
361
+ if (error instanceof RuntimeError3) {
232
362
  throw error;
233
363
  }
234
364
  const message = error instanceof Error ? error.message : "Unknown error";
235
- throw new RuntimeError4("RILL-R004", `Invalid tool input for ${toolName}: ${message}`);
365
+ throw new RuntimeError3("RILL-R005", `Invalid tool input for ${toolName}: ${message}`);
236
366
  }
237
367
  }
238
368
  function sanitizeToolName(name) {
@@ -303,19 +433,19 @@ function patchResponseToolCallNames(response, nameMap) {
303
433
  }
304
434
  async function executeToolLoop(messages, tools, maxErrors, callbacks, emitEvent, maxTurns = 10, context, yieldChunk, signal) {
305
435
  if (tools === void 0) {
306
- throw new RuntimeError4("RILL-R004", "tools parameter is required");
436
+ throwToolLoopHalt(context, "INVALID_INPUT", "tools_required", "tools parameter is required");
307
437
  }
308
438
  if (!isDict(tools)) {
309
- throw new RuntimeError4("RILL-R004", "tool_loop: tools must be a dict of name \u2192 callable");
439
+ throwToolLoopHalt(context, "INVALID_INPUT", "tools_not_dict", "tool_loop: tools must be a dict of name \u2192 callable");
310
440
  }
311
441
  const toolsDict = tools;
312
442
  const toolDescriptors = Object.entries(toolsDict).map(([name, fn]) => {
313
443
  const fnValue = fn;
314
444
  if (isRuntimeCallable(fnValue)) {
315
- throw new RuntimeError4("RILL-R004", `tool_loop: builtin "${name}" cannot be used as a tool \u2014 wrap in a closure`);
445
+ throwToolLoopHalt(context, "INVALID_INPUT", "builtin_tool_unsupported", `tool_loop: builtin "${name}" cannot be used as a tool \u2014 wrap in a closure`);
316
446
  }
317
447
  if (!isCallable(fnValue)) {
318
- throw new RuntimeError4("RILL-R004", `tool_loop: tool "${name}" is not a callable`);
448
+ throwToolLoopHalt(context, "INVALID_INPUT", "tool_not_callable", `tool_loop: tool "${name}" is not a callable`);
319
449
  }
320
450
  const callable = fnValue;
321
451
  const description = callable.annotations?.["description"] ?? "";
@@ -350,7 +480,7 @@ async function executeToolLoop(messages, tools, maxErrors, callbacks, emitEvent,
350
480
  let turnCount = 0;
351
481
  while (turnCount < maxTurns) {
352
482
  if (signal?.aborted) {
353
- throw new RuntimeError4("RILL-R004", "tool_loop cancelled");
483
+ throwToolLoopHalt(context, "TIMEOUT", "tool_loop_cancelled", "tool_loop cancelled");
354
484
  }
355
485
  turnCount++;
356
486
  let response;
@@ -364,8 +494,18 @@ async function executeToolLoop(messages, tools, maxErrors, callbacks, emitEvent,
364
494
  response = await callbacks.callAPI(currentMessages, providerTools, signal);
365
495
  }
366
496
  } catch (error) {
497
+ if (error instanceof RuntimeHaltSignal2) {
498
+ throw error;
499
+ }
500
+ if (context !== void 0 && callbacks.detectError !== void 0) {
501
+ const hostCtx = context;
502
+ if (typeof hostCtx.invalidate === "function") {
503
+ const invalid = mapProviderError(hostCtx, "tool_loop", error, callbacks.detectError);
504
+ throw new RuntimeHaltSignal2(invalid, true);
505
+ }
506
+ }
367
507
  const message = error instanceof Error ? error.message : "Unknown error";
368
- throw new RuntimeError4("RILL-R004", `Provider API error: ${message}`, void 0, { cause: error });
508
+ throw new RuntimeError3("RILL-R005", `Provider API error: ${message}`, void 0, { cause: error });
369
509
  }
370
510
  if (typeof response === "object" && response !== null && "usage" in response) {
371
511
  const usage = response["usage"];
@@ -422,7 +562,11 @@ async function executeToolLoop(messages, tools, maxErrors, callbacks, emitEvent,
422
562
  const duration = Date.now() - toolStartTime;
423
563
  consecutiveErrors++;
424
564
  let originalError;
425
- if (error instanceof RuntimeError4) {
565
+ if (error instanceof RuntimeHaltSignal2) {
566
+ const haltMessage = readHaltMessage(error);
567
+ const prefix = `Invalid tool input for ${name}: `;
568
+ originalError = haltMessage.startsWith(prefix) ? haltMessage.slice(prefix.length) : haltMessage;
569
+ } else if (error instanceof RuntimeError3) {
426
570
  const prefix = `Invalid tool input for ${name}: `;
427
571
  if (error.message.startsWith(prefix)) {
428
572
  originalError = error.message.slice(prefix.length);
@@ -447,7 +591,7 @@ async function executeToolLoop(messages, tools, maxErrors, callbacks, emitEvent,
447
591
  duration
448
592
  });
449
593
  if (consecutiveErrors >= maxErrors) {
450
- throw new RuntimeError4("RILL-R004", `Tool execution failed: ${maxErrors} consecutive errors (last: ${name}: ${originalError})`);
594
+ throwToolLoopHalt(context, "UNAVAILABLE", "consecutive_tool_errors", `Tool execution failed: ${maxErrors} consecutive errors (last: ${name}: ${originalError})`);
451
595
  }
452
596
  }
453
597
  }
@@ -474,13 +618,13 @@ function buildResponseMessages(inputMessages, assistantContent) {
474
618
  }
475
619
 
476
620
  // ../../shared/ext-param/dist/param.js
477
- import { RuntimeError as RuntimeError5 } from "@rcrsr/rill";
621
+ import { RuntimeError as RuntimeError4 } from "@rcrsr/rill";
478
622
  function validateParamName(name) {
479
623
  if (name === "") {
480
- throw new RuntimeError5("RILL-R001", "param name must not be empty");
624
+ throw new RuntimeError4("RILL-R001", "param name must not be empty");
481
625
  }
482
626
  if (/\s/.test(name)) {
483
- throw new RuntimeError5("RILL-R001", "param name must be a valid identifier");
627
+ throw new RuntimeError4("RILL-R001", "param name must be a valid identifier");
484
628
  }
485
629
  }
486
630
  function buildAnnotations(desc) {
@@ -597,6 +741,27 @@ var p = {
597
741
 
598
742
  // src/factory.ts
599
743
  var DEFAULT_MAX_TOKENS = 8192;
744
+ function mapToHalt(ctx, error) {
745
+ const invalid = mapProviderError(ctx, "Gemini", error, detectGeminiError);
746
+ return new RuntimeHaltSignal3(invalid, true);
747
+ }
748
+ function haltInvalid(ctx, code, rawKind, message) {
749
+ return new RuntimeHaltSignal3(
750
+ ctx.invalidate(new Error(message), {
751
+ code,
752
+ provider: "gemini",
753
+ raw: { kind: rawKind, message }
754
+ }),
755
+ true
756
+ );
757
+ }
758
+ function streamErrorMessage(err) {
759
+ if (err === void 0) return "";
760
+ if (err instanceof RuntimeHaltSignal3) {
761
+ return getStatus2(err.value).message || err.message;
762
+ }
763
+ return err.message;
764
+ }
600
765
  var detectGeminiError = (error) => {
601
766
  if (error instanceof Error) {
602
767
  const message = error.message;
@@ -685,7 +850,7 @@ function createGeminiExtension(config) {
685
850
  const text = args["text"];
686
851
  const options = args["options"] ?? {};
687
852
  if (text.trim().length === 0) {
688
- throw new RuntimeError6("RILL-R004", "prompt text cannot be empty");
853
+ throw haltInvalid(ctx, "INVALID_INPUT", "empty_prompt", "prompt text cannot be empty");
689
854
  }
690
855
  const system = typeof options["system"] === "string" ? options["system"] : factorySystem;
691
856
  const maxTokens = typeof options["max_tokens"] === "number" && options["max_tokens"] > 0 ? options["max_tokens"] : factoryMaxTokens;
@@ -724,12 +889,12 @@ function createGeminiExtension(config) {
724
889
  }
725
890
  }
726
891
  } catch (error) {
727
- streamError = error instanceof RuntimeError6 ? error : mapProviderError("Gemini", error, detectGeminiError);
892
+ streamError = error instanceof RuntimeError5 || error instanceof RuntimeHaltSignal3 ? error : mapToHalt(ctx, error);
728
893
  const duration = Date.now() - messageStartTime;
729
894
  emitExtensionEvent(ctx, {
730
895
  event: "gemini:error",
731
896
  subsystem: "extension:gemini",
732
- error: streamError.message,
897
+ error: streamErrorMessage(streamError),
733
898
  duration
734
899
  });
735
900
  throw streamError;
@@ -820,10 +985,7 @@ function createGeminiExtension(config) {
820
985
  const inputMessages = args["messages"];
821
986
  const options = args["options"] ?? {};
822
987
  if (inputMessages.length === 0) {
823
- throw new RuntimeError6(
824
- "RILL-R004",
825
- "messages list cannot be empty"
826
- );
988
+ throw haltInvalid(ctx, "INVALID_INPUT", "empty_messages", "messages list cannot be empty");
827
989
  }
828
990
  const system = typeof options["system"] === "string" ? options["system"] : factorySystem;
829
991
  const maxTokens = typeof options["max_tokens"] === "number" && options["max_tokens"] > 0 ? options["max_tokens"] : factoryMaxTokens;
@@ -831,21 +993,15 @@ function createGeminiExtension(config) {
831
993
  for (let i = 0; i < inputMessages.length; i++) {
832
994
  const msg = inputMessages[i];
833
995
  if (!msg || typeof msg !== "object" || !("role" in msg)) {
834
- throw new RuntimeError6(
835
- "RILL-R004",
836
- "message missing required 'role' field"
837
- );
996
+ throw haltInvalid(ctx, "INVALID_INPUT", "invalid_message_format", "message missing required 'role' field");
838
997
  }
839
998
  const role = msg["role"];
840
999
  if (role !== "user" && role !== "assistant" && role !== "tool") {
841
- throw new RuntimeError6("RILL-R004", `invalid role '${role}'`);
1000
+ throw haltInvalid(ctx, "INVALID_INPUT", "invalid_role", `invalid role '${String(role)}'`);
842
1001
  }
843
1002
  if (role === "user" || role === "tool") {
844
1003
  if (!("content" in msg) || typeof msg["content"] !== "string") {
845
- throw new RuntimeError6(
846
- "RILL-R004",
847
- `${role} message requires 'content'`
848
- );
1004
+ throw haltInvalid(ctx, "INVALID_INPUT", "missing_message_content", `${role} message requires 'content'`);
849
1005
  }
850
1006
  contents.push({
851
1007
  role: "user",
@@ -855,10 +1011,7 @@ function createGeminiExtension(config) {
855
1011
  const hasContent = "content" in msg && msg["content"];
856
1012
  const hasToolCalls = "tool_calls" in msg && msg["tool_calls"];
857
1013
  if (!hasContent && !hasToolCalls) {
858
- throw new RuntimeError6(
859
- "RILL-R004",
860
- "assistant message requires 'content' or 'tool_calls'"
861
- );
1014
+ throw haltInvalid(ctx, "INVALID_INPUT", "invalid_assistant_message", "assistant message requires 'content' or 'tool_calls'");
862
1015
  }
863
1016
  if (hasContent) {
864
1017
  contents.push({
@@ -897,12 +1050,12 @@ function createGeminiExtension(config) {
897
1050
  }
898
1051
  }
899
1052
  } catch (error) {
900
- streamError = error instanceof RuntimeError6 ? error : mapProviderError("Gemini", error, detectGeminiError);
1053
+ streamError = error instanceof RuntimeError5 || error instanceof RuntimeHaltSignal3 ? error : mapToHalt(ctx, error);
901
1054
  const duration = Date.now() - messagesStartTime;
902
1055
  emitExtensionEvent(ctx, {
903
1056
  event: "gemini:error",
904
1057
  subsystem: "extension:gemini",
905
- error: streamError.message,
1058
+ error: streamErrorMessage(streamError),
906
1059
  duration
907
1060
  });
908
1061
  throw streamError;
@@ -995,10 +1148,7 @@ function createGeminiExtension(config) {
995
1148
  });
996
1149
  const embedding = response.embeddings?.[0];
997
1150
  if (!embedding || !embedding.values || embedding.values.length === 0) {
998
- throw new RuntimeError6(
999
- "RILL-R004",
1000
- "Gemini: empty embedding returned"
1001
- );
1151
+ throw haltInvalid(ctx, "PROTOCOL", "empty_embedding_response", "Gemini: empty embedding returned");
1002
1152
  }
1003
1153
  const float32Data = new Float32Array(embedding.values);
1004
1154
  const vector = createVector(float32Data, factoryEmbedModel);
@@ -1013,11 +1163,11 @@ function createGeminiExtension(config) {
1013
1163
  return vector;
1014
1164
  } catch (error) {
1015
1165
  const duration = Date.now() - startTime;
1016
- const rillError = error instanceof RuntimeError6 ? error : mapProviderError("Gemini", error, detectGeminiError);
1166
+ const rillError = error instanceof RuntimeError5 || error instanceof RuntimeHaltSignal3 ? error : mapToHalt(ctx, error);
1017
1167
  emitExtensionEvent(ctx, {
1018
1168
  event: "gemini:error",
1019
1169
  subsystem: "extension:gemini",
1020
- error: rillError.message,
1170
+ error: streamErrorMessage(rillError),
1021
1171
  duration
1022
1172
  });
1023
1173
  throw rillError;
@@ -1044,17 +1194,11 @@ function createGeminiExtension(config) {
1044
1194
  });
1045
1195
  const vectors = [];
1046
1196
  if (!response.embeddings || response.embeddings.length === 0) {
1047
- throw new RuntimeError6(
1048
- "RILL-R004",
1049
- "Gemini: empty embeddings returned"
1050
- );
1197
+ throw haltInvalid(ctx, "PROTOCOL", "empty_embeddings_response", "Gemini: empty embeddings returned");
1051
1198
  }
1052
1199
  for (const embedding of response.embeddings) {
1053
1200
  if (!embedding || !embedding.values || embedding.values.length === 0) {
1054
- throw new RuntimeError6(
1055
- "RILL-R004",
1056
- "Gemini: empty embedding returned"
1057
- );
1201
+ throw haltInvalid(ctx, "PROTOCOL", "empty_embedding_response", "Gemini: empty embedding returned");
1058
1202
  }
1059
1203
  const float32Data = new Float32Array(embedding.values);
1060
1204
  const vector = createVector(float32Data, factoryEmbedModel);
@@ -1074,11 +1218,11 @@ function createGeminiExtension(config) {
1074
1218
  return vectors;
1075
1219
  } catch (error) {
1076
1220
  const duration = Date.now() - startTime;
1077
- const rillError = error instanceof RuntimeError6 ? error : mapProviderError("Gemini", error, detectGeminiError);
1221
+ const rillError = error instanceof RuntimeError5 || error instanceof RuntimeHaltSignal3 ? error : mapToHalt(ctx, error);
1078
1222
  emitExtensionEvent(ctx, {
1079
1223
  event: "gemini:error",
1080
1224
  subsystem: "extension:gemini",
1081
- error: rillError.message,
1225
+ error: streamErrorMessage(rillError),
1082
1226
  duration
1083
1227
  });
1084
1228
  throw rillError;
@@ -1110,7 +1254,7 @@ function createGeminiExtension(config) {
1110
1254
  const toolsDict = args["tools"];
1111
1255
  const options = args["options"] ?? {};
1112
1256
  if (prompt.trim().length === 0) {
1113
- throw new RuntimeError6("RILL-R004", "prompt text cannot be empty");
1257
+ throw haltInvalid(ctx, "INVALID_INPUT", "empty_prompt", "prompt text cannot be empty");
1114
1258
  }
1115
1259
  const system = typeof options["system"] === "string" ? options["system"] : factorySystem;
1116
1260
  const maxTokens = typeof options["max_tokens"] === "number" && options["max_tokens"] > 0 ? options["max_tokens"] : factoryMaxTokens;
@@ -1309,7 +1453,7 @@ function createGeminiExtension(config) {
1309
1453
  r();
1310
1454
  }
1311
1455
  }).catch((error) => {
1312
- streamError = error instanceof RuntimeError6 ? error : mapProviderError("Gemini", error, detectGeminiError);
1456
+ streamError = error instanceof RuntimeError5 || error instanceof RuntimeHaltSignal3 ? error : mapToHalt(ctx, error);
1313
1457
  streamDone = true;
1314
1458
  if (resolveNext) {
1315
1459
  const r = resolveNext;
@@ -1358,7 +1502,7 @@ function createGeminiExtension(config) {
1358
1502
  emitExtensionEvent(ctx, {
1359
1503
  event: "gemini:error",
1360
1504
  subsystem: "extension:gemini",
1361
- error: streamError.message,
1505
+ error: streamErrorMessage(streamError),
1362
1506
  duration: Date.now()
1363
1507
  });
1364
1508
  return {
@@ -1374,7 +1518,7 @@ function createGeminiExtension(config) {
1374
1518
  emitExtensionEvent(ctx, {
1375
1519
  event: "gemini:error",
1376
1520
  subsystem: "extension:gemini",
1377
- error: streamError.message,
1521
+ error: streamErrorMessage(streamError),
1378
1522
  duration
1379
1523
  });
1380
1524
  throw streamError;
@@ -1447,16 +1591,10 @@ function createGeminiExtension(config) {
1447
1591
  const schemaArg = args["schema"];
1448
1592
  const options = args["options"] ?? {};
1449
1593
  if (!schemaArg || !schemaArg.__rill_type || !schemaArg.structure) {
1450
- throw new RuntimeError6(
1451
- "RILL-R004",
1452
- "generate requires a type expression as schema"
1453
- );
1594
+ throw haltInvalid(ctx, "INVALID_INPUT", "invalid_schema", "generate requires a type expression as schema");
1454
1595
  }
1455
1596
  if (schemaArg.structure.kind !== "dict") {
1456
- throw new RuntimeError6(
1457
- "RILL-R004",
1458
- `generate requires a dict type as schema, got ${schemaArg.structure.kind}`
1459
- );
1597
+ throw haltInvalid(ctx, "INVALID_INPUT", "invalid_schema_type", `generate requires a dict type as schema, got ${schemaArg.structure.kind}`);
1460
1598
  }
1461
1599
  const jsonSchema = buildJsonSchemaFromStructuralType(schemaArg.structure);
1462
1600
  const geminiProperties = {};
@@ -1518,10 +1656,7 @@ function createGeminiExtension(config) {
1518
1656
  data = JSON.parse(raw);
1519
1657
  } catch (parseError) {
1520
1658
  const detail = parseError instanceof Error ? parseError.message : String(parseError);
1521
- throw new RuntimeError6(
1522
- "RILL-R004",
1523
- `generate: failed to parse response JSON: ${detail}`
1524
- );
1659
+ throw haltInvalid(ctx, "PROTOCOL", "json_parse_failed", `generate: failed to parse response JSON: ${detail}`);
1525
1660
  }
1526
1661
  const inputTokens = response.usageMetadata?.promptTokenCount ?? 0;
1527
1662
  const outputTokens = response.usageMetadata?.candidatesTokenCount ?? 0;
@@ -1551,11 +1686,11 @@ function createGeminiExtension(config) {
1551
1686
  return generateResult;
1552
1687
  } catch (error) {
1553
1688
  const duration = Date.now() - startTime;
1554
- const rillError = error instanceof RuntimeError6 ? error : mapProviderError("Gemini", error, detectGeminiError);
1689
+ const rillError = error instanceof RuntimeError5 || error instanceof RuntimeHaltSignal3 ? error : mapToHalt(ctx, error);
1555
1690
  emitExtensionEvent(ctx, {
1556
1691
  event: "gemini:error",
1557
1692
  subsystem: "extension:gemini",
1558
- error: rillError.message,
1693
+ error: streamErrorMessage(rillError),
1559
1694
  duration
1560
1695
  });
1561
1696
  throw rillError;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rcrsr/rill-ext-gemini",
3
- "version": "0.18.3",
3
+ "version": "0.19.0",
4
4
  "description": "rill extension for Google Gemini API integration",
5
5
  "license": "MIT",
6
6
  "author": "Andre Bremer",
@@ -17,16 +17,16 @@
17
17
  "scripting"
18
18
  ],
19
19
  "peerDependencies": {
20
- "@rcrsr/rill": "~0.18.0"
20
+ "@rcrsr/rill": "~0.19.0"
21
21
  },
22
22
  "devDependencies": {
23
- "@rcrsr/rill": "~0.18.0",
24
- "@types/node": "^25.3.0",
23
+ "@rcrsr/rill": "~0.19.0",
24
+ "@types/node": "^25.5.2",
25
25
  "dts-bundle-generator": "^9.5.1",
26
26
  "tsup": "^8.5.1",
27
- "undici-types": "^7.22.0",
28
- "@rcrsr/rill-ext-llm-shared": "^0.18.3",
29
- "@rcrsr/rill-ext-param-shared": "0.18.1"
27
+ "undici-types": "^8.0.2",
28
+ "@rcrsr/rill-ext-param-shared": "0.19.0",
29
+ "@rcrsr/rill-ext-llm-shared": "^0.19.0"
30
30
  },
31
31
  "files": [
32
32
  "dist"
@@ -44,7 +44,7 @@
44
44
  "access": "public"
45
45
  },
46
46
  "dependencies": {
47
- "@google/genai": "^1.42.0"
47
+ "@google/genai": "^1.48.0"
48
48
  },
49
49
  "scripts": {
50
50
  "build": "tsup && dts-bundle-generator --config dts-bundle-generator.config.cjs",