prefix-safe-json 0.4.4 → 0.4.5
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/providers/anthropic.d.ts +1 -0
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +89 -8
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/gemini.d.ts +122 -0
- package/dist/providers/gemini.d.ts.map +1 -1
- package/dist/providers/gemini.js +442 -25
- package/dist/providers/gemini.js.map +1 -1
- package/dist/providers/openai-compatible.d.ts +47 -1
- package/dist/providers/openai-compatible.d.ts.map +1 -1
- package/dist/providers/openai-compatible.js +381 -84
- package/dist/providers/openai-compatible.js.map +1 -1
- package/dist/providers/openai.d.ts +7 -1
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +459 -67
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/openrouter.d.ts.map +1 -1
- package/dist/providers/openrouter.js +14 -2
- package/dist/providers/openrouter.js.map +1 -1
- package/package.json +4 -1
|
@@ -35,6 +35,7 @@ export declare class AnthropicStreamAdapter implements ProviderStreamAdapter<unk
|
|
|
35
35
|
readonly provider: ProviderName;
|
|
36
36
|
private sequence;
|
|
37
37
|
private finished;
|
|
38
|
+
private terminatedBlockIndices;
|
|
38
39
|
push(rawEvent: unknown): readonly NormalizedToolStreamEvent[];
|
|
39
40
|
finish(meta?: {
|
|
40
41
|
reason?: StreamEndReason;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AACtG,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AACtG,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAMrD,UAAU,+BAA+B;IACvC,IAAI,EAAE,qBAAqB,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE;QACL,IAAI,EAAE,kBAAkB,CAAC;QACzB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED,UAAU,+BAA+B;IACvC,IAAI,EAAE,qBAAqB,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE;QACb,IAAI,EAAE,UAAU,CAAC;QACjB,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED,UAAU,8BAA8B;IACtC,IAAI,EAAE,oBAAoB,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,UAAU,0BAA0B;IAClC,IAAI,EAAE,eAAe,CAAC;IACtB,KAAK,EAAE;QACL,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC7B,CAAC;CACH;AAED,MAAM,MAAM,cAAc,GACtB,+BAA+B,GAC/B,+BAA+B,GAC/B,8BAA8B,GAC9B,0BAA0B,GAC1B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC;AAE7C,qBAAa,sBAAuB,YAAW,qBAAqB,CAAC,OAAO,CAAC;IAC3E,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAe;IAC9C,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,QAAQ,CAAS;IAgBzB,OAAO,CAAC,sBAAsB,CAA0B;IAExD,IAAI,CAAC,QAAQ,EAAE,OAAO,GAAG,SAAS,yBAAyB,EAAE;IAwK7D,MAAM,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,eAAe,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,yBAAyB,EAAE;CAW3G"}
|
|
@@ -1,10 +1,38 @@
|
|
|
1
|
+
import { TOOL_ARGUMENTS_AFTER_END_DIAGNOSTIC_CODE, DUPLICATE_TOOL_END_DIAGNOSTIC_CODE, } from "../coordinator/diagnostic-codes.js";
|
|
1
2
|
export class AnthropicStreamAdapter {
|
|
2
3
|
provider = "anthropic";
|
|
3
4
|
sequence = 0;
|
|
4
5
|
finished = false;
|
|
6
|
+
// Block-local terminal state (P4.2 / F-1): every content-block index that
|
|
7
|
+
// has already received its own content_block_stop. Uses the adapter's
|
|
8
|
+
// existing `content-block:{index}` sourceKey identity - no second
|
|
9
|
+
// identity system. content_block_stop closes the block's argument stream
|
|
10
|
+
// (tool_call_end), but that alone does not stop the coordinator from
|
|
11
|
+
// silently merging a LATER, real content_block_delta for the SAME index
|
|
12
|
+
// into the same still-"collecting" call (handleCallEnd never changes
|
|
13
|
+
// call.status - only finishCall(), called solely from the stream-wide
|
|
14
|
+
// handleStreamEnd(), does that - see coordinator.ts). Recognized argument
|
|
15
|
+
// evidence, and a duplicate content_block_stop itself, for an index
|
|
16
|
+
// already in this set are therefore hardened below instead of merged/
|
|
17
|
+
// silently repeated. Tracks every stopped index regardless of whether it
|
|
18
|
+
// was ever a real tool_use block - content_block_stop carries no
|
|
19
|
+
// content_block field to distinguish that, matching the adapter's own
|
|
20
|
+
// existing behavior of never discriminating by type at stop time.
|
|
21
|
+
terminatedBlockIndices = new Set();
|
|
5
22
|
push(rawEvent) {
|
|
6
|
-
|
|
7
|
-
|
|
23
|
+
// No `finished` early return here: silently dropping every event after
|
|
24
|
+
// the first terminal meant a late argument delta, a conflicting or
|
|
25
|
+
// duplicate `message_delta` terminal, or a late `error` event that
|
|
26
|
+
// arrived even one raw event late never reached the coordinator at all -
|
|
27
|
+
// not even as a diagnostic - so an already-decided call's authority
|
|
28
|
+
// could never be revoked by it. Every case below that has ITS OWN
|
|
29
|
+
// meaningful post-terminal handling (a genuine argument delta, a second
|
|
30
|
+
// content_block_start/_stop, a second stream-terminal) still fires
|
|
31
|
+
// exactly as if the stream were open; the coordinator's own `isFinished`
|
|
32
|
+
// gate (coordinator.ts's `push()`) is what turns each of those into a
|
|
33
|
+
// sticky, stream-wide AUTHORITY_PROTOCOL_VIOLATION_CODES diagnostic once
|
|
34
|
+
// it actually receives them. Mirrors the fix already applied to
|
|
35
|
+
// AiSdkStreamAdapter for the same invariant (GHSA-3xpw-9694-2xxp).
|
|
8
36
|
const events = [];
|
|
9
37
|
if (!rawEvent || typeof rawEvent !== "object") {
|
|
10
38
|
events.push({
|
|
@@ -37,18 +65,71 @@ export class AnthropicStreamAdapter {
|
|
|
37
65
|
case "content_block_delta": {
|
|
38
66
|
if (chunk.delta?.type === "input_json_delta" && typeof chunk.delta.partial_json === "string") {
|
|
39
67
|
const sourceKey = `content-block:${chunk.index}`;
|
|
68
|
+
if (this.terminatedBlockIndices.has(chunk.index)) {
|
|
69
|
+
// Block-local post-terminal evidence (P4.2 / F-1): this exact
|
|
70
|
+
// block already recorded its own content_block_stop. Never
|
|
71
|
+
// merge further argument evidence as normal - that would
|
|
72
|
+
// silently mutate (and, if left structurally unclosed at stop
|
|
73
|
+
// time, silently CLOSE) an already-ended block's value with no
|
|
74
|
+
// record of the anomaly. Same diagnostic code
|
|
75
|
+
// AiSdkStreamAdapter/OpenAICompatibleStreamAdapter/
|
|
76
|
+
// OpenAIStreamAdapter already use for materially identical
|
|
77
|
+
// semantics ("tool argument evidence arrived after that call's
|
|
78
|
+
// end"), attributed to the block's own real, already-
|
|
79
|
+
// tool_call_start'd sourceKey so the coordinator resolves it to
|
|
80
|
+
// the actual call, not a phantom identity.
|
|
81
|
+
events.push({
|
|
82
|
+
type: "provider_diagnostic",
|
|
83
|
+
sequence: ++this.sequence,
|
|
84
|
+
provider: this.provider,
|
|
85
|
+
callRef: { sourceKey },
|
|
86
|
+
code: TOOL_ARGUMENTS_AFTER_END_DIAGNOSTIC_CODE,
|
|
87
|
+
severity: "error",
|
|
88
|
+
message: `Tool call argument evidence for content block ${chunk.index} arrived after that block's own content_block_stop`,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
events.push({
|
|
93
|
+
type: "tool_call_arguments_delta",
|
|
94
|
+
sequence: ++this.sequence,
|
|
95
|
+
provider: this.provider,
|
|
96
|
+
callRef: { sourceKey },
|
|
97
|
+
delta: chunk.delta.partial_json,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
case "content_block_stop": {
|
|
104
|
+
const sourceKey = `content-block:${chunk.index}`;
|
|
105
|
+
if (this.terminatedBlockIndices.has(chunk.index)) {
|
|
106
|
+
// Duplicate content_block_stop for the same index (P4.2 / Phase
|
|
107
|
+
// 7): pre-fix this silently re-emitted a second tool_call_end,
|
|
108
|
+
// which coordinator.ts's handleCallEnd() tolerates idempotently
|
|
109
|
+
// (it only sets two already-true booleans again) - authority-safe
|
|
110
|
+
// but tolerated: the duplicate did not create or increase
|
|
111
|
+
// execution authority, but it was silently accepted and did not
|
|
112
|
+
// itself disqualify the call, so an otherwise-valid call could
|
|
113
|
+
// still execute once a later, genuine terminal arrived. The
|
|
114
|
+
// adapter now records the duplicate as DUPLICATE_TOOL_END and
|
|
115
|
+
// therefore fails that call closed instead - genuinely a
|
|
116
|
+
// repeated end signal for the same call, exactly
|
|
117
|
+
// DUPLICATE_TOOL_END_DIAGNOSTIC_CODE's own documented meaning
|
|
118
|
+
// ("more than one end part for the same call") and
|
|
119
|
+
// AUTHORITY_PROTOCOL_VIOLATION_CODES membership - reused rather
|
|
120
|
+
// than inventing a new code.
|
|
40
121
|
events.push({
|
|
41
|
-
type: "
|
|
122
|
+
type: "provider_diagnostic",
|
|
42
123
|
sequence: ++this.sequence,
|
|
43
124
|
provider: this.provider,
|
|
44
125
|
callRef: { sourceKey },
|
|
45
|
-
|
|
126
|
+
code: DUPLICATE_TOOL_END_DIAGNOSTIC_CODE,
|
|
127
|
+
severity: "error",
|
|
128
|
+
message: `content block ${chunk.index} received a second content_block_stop`,
|
|
46
129
|
});
|
|
130
|
+
break;
|
|
47
131
|
}
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
case "content_block_stop": {
|
|
51
|
-
const sourceKey = `content-block:${chunk.index}`;
|
|
132
|
+
this.terminatedBlockIndices.add(chunk.index);
|
|
52
133
|
events.push({
|
|
53
134
|
type: "tool_call_end",
|
|
54
135
|
sequence: ++this.sequence,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ import { ProviderStreamAdapter } from "./adapter.js";
|
|
|
3
3
|
interface GeminiFunctionCall {
|
|
4
4
|
name?: string;
|
|
5
5
|
args?: unknown;
|
|
6
|
+
id?: string;
|
|
6
7
|
}
|
|
7
8
|
interface GeminiPart {
|
|
8
9
|
functionCall?: GeminiFunctionCall;
|
|
@@ -13,19 +14,140 @@ interface GeminiContent {
|
|
|
13
14
|
interface GeminiCandidate {
|
|
14
15
|
content?: GeminiContent;
|
|
15
16
|
finishReason?: string;
|
|
17
|
+
index?: number;
|
|
16
18
|
}
|
|
17
19
|
export interface GeminiEvent {
|
|
18
20
|
candidates?: GeminiCandidate[];
|
|
19
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Gemini `generateContentStream`-shaped streaming adapter.
|
|
24
|
+
*
|
|
25
|
+
* Terminal-ownership fix (Phase B hardening sweep, corrected in Phase B.1-
|
|
26
|
+
* B.7 after an identity-premise error was found in raw review):
|
|
27
|
+
* `candidate.finishReason` is candidate-LOCAL evidence only - a genuine
|
|
28
|
+
* multi-candidate (n>1) stream has one finishReason per candidate, each
|
|
29
|
+
* reporting only that candidate's own completion, never the whole provider
|
|
30
|
+
* stream's. Pre-fix, ANY candidate's finishReason directly emitted
|
|
31
|
+
* `provider_stream_end` and set this adapter's own global `finished` flag -
|
|
32
|
+
* the same "first choice to finish wrongly ends every choice" defect
|
|
33
|
+
* already found and fixed for OpenAI (Chat Completions plural and legacy
|
|
34
|
+
* singular) and Anthropic this session.
|
|
35
|
+
*
|
|
36
|
+
* Candidate IDENTITY correction (Phase B.1/B.2, the raw-review finding):
|
|
37
|
+
* this adapter used to key all candidate-local state by array POSITION
|
|
38
|
+
* within each chunk's own `candidates` list. The real wire field
|
|
39
|
+
* `candidate.index` ("Output only. The 0-based index of this candidate...
|
|
40
|
+
* useful for distinguishing between multiple candidates when
|
|
41
|
+
* candidate_count > 1" - confirmed against the installed
|
|
42
|
+
* `@google/genai@2.21.0` SDK's own types AND its real SSE parser, see
|
|
43
|
+
* test/integration/gemini-official-sdk-lifecycle.test.ts) is the
|
|
44
|
+
* authoritative identity instead. Array position silently breaks the
|
|
45
|
+
* moment a chunk omits an already-finished candidate (entirely normal - a
|
|
46
|
+
* provider has no reason to keep re-sending a candidate with nothing new
|
|
47
|
+
* to say) or reorders candidates within one chunk: real candidate 1's
|
|
48
|
+
* evidence arriving alone, at array position 0, was silently misattributed
|
|
49
|
+
* to candidate 0's own (already-terminal) identity - captured as genuine
|
|
50
|
+
* RED against real SDK-parsed chunks before this fix, not merely inferred.
|
|
51
|
+
*
|
|
52
|
+
* Fixed the same way as OpenAI's legacy path (P4.3) and Anthropic (P4.2):
|
|
53
|
+
* candidate.finishReason
|
|
54
|
+
* -> records that candidate's own terminal StreamEndReason
|
|
55
|
+
* -> does NOT emit provider_stream_end
|
|
56
|
+
* -> does NOT set this adapter's global `finished` flag
|
|
57
|
+
* finish(meta?)
|
|
58
|
+
* -> the ONE provider_stream_end for this adapter's whole lifetime,
|
|
59
|
+
* aggregating every recorded candidate-local reason (worst wins -
|
|
60
|
+
* see REASON_PRIORITY above) with meta.reason.
|
|
61
|
+
*
|
|
62
|
+
* Post-provider-terminal handling (Phase B.6): the top-of-push()
|
|
63
|
+
* `if (this.finished) return [];` guard, previously the only adapter in
|
|
64
|
+
* this codebase deliberately retaining the pre-P0 silent-drop pattern, is
|
|
65
|
+
* REMOVED here too - normalization continues after adapter.finish(), and
|
|
66
|
+
* coordinator.ts's own `isFinished` gate provides the canonical
|
|
67
|
+
* post-provider-terminal handling, exactly like every other adapter. This
|
|
68
|
+
* is future-proofing / architectural consistency, NOT the closing of a
|
|
69
|
+
* demonstrated execution-authority gap: independently re-verified, not
|
|
70
|
+
* merely trusted, that no Gemini call can ever reach `execute` -
|
|
71
|
+
* PROJECTION_ONLY_ARGUMENTS_DIAGNOSTIC_CODE is unconditional on every
|
|
72
|
+
* functionCall and checked by decide.ts before status is even considered;
|
|
73
|
+
* gate.ts's takeDecision() re-derives fresh and only ever returns
|
|
74
|
+
* something for action==="execute". See the two-part epistemic
|
|
75
|
+
* distinction in this program's own final report: CORRECTNESS/
|
|
76
|
+
* architecture-consistency, never claimed as an execution-integrity fix.
|
|
77
|
+
*
|
|
78
|
+
* Call IDENTITY correction (P4.5, a genuine RED confirmed against real
|
|
79
|
+
* @google/genai@2.21.0-parsed chunks, not merely inferred): within one
|
|
80
|
+
* candidate, this adapter used to key each functionCall's own sourceKey by
|
|
81
|
+
* PART ARRAY POSITION (`candidate:{i}/part:{j}`). Each Gemini functionCall
|
|
82
|
+
* is object-level final delivery, never incrementally streamed (no
|
|
83
|
+
* position needs to stay stable WITHIN one call's own lifetime) - but
|
|
84
|
+
* array position is NOT stable ACROSS separate, unrelated calls delivered
|
|
85
|
+
* in separate chunks: two genuinely independent functionCalls (confirmed
|
|
86
|
+
* via the real SDK parser to carry distinct `id`s, distinct names, and
|
|
87
|
+
* distinct args) that happen to land at the same part-array-position in
|
|
88
|
+
* their own respective chunks were silently treated as the SAME call - the
|
|
89
|
+
* second's evidence colliding with and corrupting the first's
|
|
90
|
+
* already-closed identity (coordinator.ts's own E_DUPLICATE_TOOL_CALL_START
|
|
91
|
+
* plus a parser E_TRAILING_DATA), with the second call never surfacing as
|
|
92
|
+
* its own decision at all. This is the same class of identity-loss defect
|
|
93
|
+
* already found and fixed for candidate identity itself (P4.4) and for
|
|
94
|
+
* every other provider's own call/item/block identity this session - now
|
|
95
|
+
* closed at the function-call level too.
|
|
96
|
+
*
|
|
97
|
+
* Fixed by preferring the official wire field `functionCall.id` ("Optional.
|
|
98
|
+
* The unique id of the function call...") as the call identity when a
|
|
99
|
+
* valid non-empty string is present:
|
|
100
|
+
* `candidate:{candidateIndex}/function-call-id:{id}`
|
|
101
|
+
* `id` is explicitly OPTIONAL per its own doc comment, and confirmed
|
|
102
|
+
* empirically (real SDK-parsed evidence) that the SDK passes through a
|
|
103
|
+
* functionCall with no `id` at all without complaint - never assumed
|
|
104
|
+
* present, never required, never a fail-closed precondition. When absent
|
|
105
|
+
* (or an empty string, treated identically to absent), this adapter falls
|
|
106
|
+
* back to a per-candidate, per-adapter-instance MONOTONIC OCCURRENCE
|
|
107
|
+
* COUNTER (`candidate:{candidateIndex}/function-call:{n}`) - deliberately
|
|
108
|
+
* NOT part array position: the counter is advanced by THIS adapter's own
|
|
109
|
+
* processing order, never by anything the provider could reorder or omit
|
|
110
|
+
* across chunks, so it remains genuinely unique for the adapter's whole
|
|
111
|
+
* lifetime regardless of where in a `parts[]` array a later, unrelated
|
|
112
|
+
* no-id call happens to land. This is real, forensically-traceable
|
|
113
|
+
* identity - never a claim of continuity between separate observations,
|
|
114
|
+
* and never a byte-level/positional reconstruction.
|
|
115
|
+
*
|
|
116
|
+
* A REPEATED identical `functionCall.id` under the same candidate (or a
|
|
117
|
+
* no-id counter value, which can never repeat by construction) is treated
|
|
118
|
+
* as late/duplicate evidence for the one already-delivered call that
|
|
119
|
+
* sourceKey names - exactly TOOL_ARGUMENTS_AFTER_END_DIAGNOSTIC_CODE's own
|
|
120
|
+
* existing meaning, reusing `candidateSourceKeys`'s own existing
|
|
121
|
+
* "every sourceKey ever started, never cleared" tracking rather than a new
|
|
122
|
+
* mechanism (see push()). Official Gemini semantics document no supported
|
|
123
|
+
* continuation/streaming mechanism for a single function call at all
|
|
124
|
+
* (`partialArgs`, `willContinue`, `FunctionCallingConfig.
|
|
125
|
+
* streamFunctionCallArguments` are all explicitly "not supported in Gemini
|
|
126
|
+
* API" per the installed SDK's own doc comments) - so a repeated id is
|
|
127
|
+
* never treated as a legitimate multi-chunk continuation of the same call,
|
|
128
|
+
* only as suspect duplicate evidence disqualifying the real call it names.
|
|
129
|
+
* A different `id` under a DIFFERENT candidate is never merged with this
|
|
130
|
+
* one: identity is candidate-scoped first, exactly as P4.4 already
|
|
131
|
+
* established - official semantics document `id` only as a response-
|
|
132
|
+
* correlation mechanism (implying uniqueness where populated) and never
|
|
133
|
+
* claim a cross-candidate-global uniqueness scope, so candidate-scoping
|
|
134
|
+
* remains the conservative, evidence-supported default.
|
|
135
|
+
*/
|
|
20
136
|
export declare class GeminiStreamAdapter implements ProviderStreamAdapter<unknown> {
|
|
21
137
|
readonly provider: ProviderName;
|
|
22
138
|
private sequence;
|
|
23
139
|
private finished;
|
|
140
|
+
private candidateTerminalReasons;
|
|
141
|
+
private candidateTerminalProviderReasons;
|
|
142
|
+
private candidateSourceKeys;
|
|
143
|
+
private noIdFunctionCallCounters;
|
|
144
|
+
private callSourceKey;
|
|
24
145
|
push(rawEvent: unknown): readonly NormalizedToolStreamEvent[];
|
|
25
146
|
finish(meta?: {
|
|
26
147
|
reason?: StreamEndReason;
|
|
27
148
|
providerReason?: string;
|
|
28
149
|
}): readonly NormalizedToolStreamEvent[];
|
|
150
|
+
private aggregateTermination;
|
|
29
151
|
}
|
|
30
152
|
export {};
|
|
31
153
|
//# sourceMappingURL=gemini.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/providers/gemini.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AACtG,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/providers/gemini.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AACtG,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAUrD,UAAU,kBAAkB;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IAQf,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,UAAU,UAAU;IAClB,YAAY,CAAC,EAAE,kBAAkB,CAAC;CAGnC;AAED,UAAU,aAAa;IACrB,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;CACtB;AAED,UAAU,eAAe;IACvB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IAatB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;CAChC;AAqCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiHG;AACH,qBAAa,mBAAoB,YAAW,qBAAqB,CAAC,OAAO,CAAC;IACxE,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAY;IAC3C,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,QAAQ,CAAS;IAQzB,OAAO,CAAC,wBAAwB,CAA2C;IAI3E,OAAO,CAAC,gCAAgC,CAAkC;IAW1E,OAAO,CAAC,mBAAmB,CAAuC;IAQlE,OAAO,CAAC,wBAAwB,CAAkC;IASlE,OAAO,CAAC,aAAa;IASrB,IAAI,CAAC,QAAQ,EAAE,OAAO,GAAG,SAAS,yBAAyB,EAAE;IAiT7D,MAAM,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,eAAe,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,yBAAyB,EAAE;IAmB1G,OAAO,CAAC,oBAAoB;CA6B7B"}
|