@tuturuuu/ai 0.0.10
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/README.md +76 -0
- package/package.json +106 -0
- package/src/api-key-hash.ts +28 -0
- package/src/calendar/events.ts +34 -0
- package/src/calendar/route.ts +114 -0
- package/src/chat/credit-source.ts +1 -0
- package/src/chat/google/chat-request-schema.ts +150 -0
- package/src/chat/google/default-system-instruction.ts +198 -0
- package/src/chat/google/message-file-processing.ts +212 -0
- package/src/chat/google/mira-step-preparation.ts +221 -0
- package/src/chat/google/new/route.ts +368 -0
- package/src/chat/google/route-auth.ts +81 -0
- package/src/chat/google/route-chat-resolution.ts +98 -0
- package/src/chat/google/route-credits.ts +61 -0
- package/src/chat/google/route-message-preparation.ts +331 -0
- package/src/chat/google/route-mira-runtime.ts +206 -0
- package/src/chat/google/route.ts +632 -0
- package/src/chat/google/stream-finish-persistence.ts +722 -0
- package/src/chat/google/summary/route.ts +153 -0
- package/src/chat/mira-render-ui-policy.ts +540 -0
- package/src/chat/mira-system-instruction.ts +484 -0
- package/src/chat-sdk/adapters.ts +389 -0
- package/src/chat-sdk/registry.ts +197 -0
- package/src/chat-sdk.ts +33 -0
- package/src/core.ts +3 -0
- package/src/credits/cap-output-tokens.ts +90 -0
- package/src/credits/check-credits.ts +232 -0
- package/src/credits/constants.ts +30 -0
- package/src/credits/index.ts +46 -0
- package/src/credits/model-mapping.ts +92 -0
- package/src/credits/reservations.ts +514 -0
- package/src/credits/resolve-plan-model.ts +219 -0
- package/src/credits/sync-gateway-models.ts +351 -0
- package/src/credits/types.ts +109 -0
- package/src/credits/use-ai-credits.ts +3 -0
- package/src/embeddings/metered.ts +283 -0
- package/src/executions/route.ts +137 -0
- package/src/generate/route.ts +411 -0
- package/src/hooks.ts +7 -0
- package/src/meetings/summary/route.ts +7 -0
- package/src/meetings/transcription/route.ts +134 -0
- package/src/memory/client.ts +158 -0
- package/src/memory/config.ts +38 -0
- package/src/memory/index.ts +32 -0
- package/src/memory/ingest.ts +51 -0
- package/src/memory/middleware.ts +35 -0
- package/src/memory/operations.ts +480 -0
- package/src/memory/scope.ts +102 -0
- package/src/memory/settings.ts +121 -0
- package/src/memory/types.ts +101 -0
- package/src/memory/workspace.ts +36 -0
- package/src/memory.ts +1 -0
- package/src/mind/patch.ts +146 -0
- package/src/mind/route.ts +687 -0
- package/src/mind/tools.ts +1500 -0
- package/src/mind/types.ts +20 -0
- package/src/object/core.ts +3 -0
- package/src/object/flashcards/route.ts +140 -0
- package/src/object/quizzes/explanation/route.ts +145 -0
- package/src/object/quizzes/route.ts +142 -0
- package/src/object/types.ts +187 -0
- package/src/object/year-plan/route.ts +196 -0
- package/src/react.ts +1 -0
- package/src/scheduling/algorithm.ts +791 -0
- package/src/scheduling/default.ts +36 -0
- package/src/scheduling/duration-optimizer.ts +689 -0
- package/src/scheduling/index.ts +79 -0
- package/src/scheduling/priority-calculator.ts +187 -0
- package/src/scheduling/recurrence-calculator.ts +621 -0
- package/src/scheduling/templates.ts +892 -0
- package/src/scheduling/types.ts +136 -0
- package/src/scheduling/web-adapter.ts +308 -0
- package/src/scheduling.ts +6 -0
- package/src/supported-actions.ts +1 -0
- package/src/supported-providers.ts +6 -0
- package/src/tools/context-builder.ts +372 -0
- package/src/tools/core.ts +1 -0
- package/src/tools/definitions/calendar.ts +106 -0
- package/src/tools/definitions/finance.ts +197 -0
- package/src/tools/definitions/image.ts +74 -0
- package/src/tools/definitions/memory.ts +83 -0
- package/src/tools/definitions/meta.ts +154 -0
- package/src/tools/definitions/render-ui.ts +81 -0
- package/src/tools/definitions/tasks.ts +343 -0
- package/src/tools/definitions/time-tracking.ts +381 -0
- package/src/tools/definitions/workspace-context.ts +45 -0
- package/src/tools/definitions/workspace-user-chat.ts +111 -0
- package/src/tools/executors/calendar.ts +371 -0
- package/src/tools/executors/chat.ts +15 -0
- package/src/tools/executors/finance.ts +638 -0
- package/src/tools/executors/helpers/encryption.ts +107 -0
- package/src/tools/executors/image.ts +247 -0
- package/src/tools/executors/markitdown.ts +684 -0
- package/src/tools/executors/memory.ts +277 -0
- package/src/tools/executors/parallel-checks.ts +176 -0
- package/src/tools/executors/qr.ts +170 -0
- package/src/tools/executors/scope-helpers.ts +192 -0
- package/src/tools/executors/search.ts +149 -0
- package/src/tools/executors/settings.ts +40 -0
- package/src/tools/executors/tasks.ts +1087 -0
- package/src/tools/executors/theme.ts +23 -0
- package/src/tools/executors/timer/timer-categories-executor.ts +110 -0
- package/src/tools/executors/timer/timer-category-mutations.ts +240 -0
- package/src/tools/executors/timer/timer-goal-mutations.ts +323 -0
- package/src/tools/executors/timer/timer-goals-executor.ts +272 -0
- package/src/tools/executors/timer/timer-helpers.ts +372 -0
- package/src/tools/executors/timer/timer-mutation-schemas.ts +160 -0
- package/src/tools/executors/timer/timer-mutation-types.ts +212 -0
- package/src/tools/executors/timer/timer-mutations.ts +19 -0
- package/src/tools/executors/timer/timer-queries.ts +18 -0
- package/src/tools/executors/timer/timer-session-lifecycle.ts +299 -0
- package/src/tools/executors/timer/timer-session-mutations.ts +10 -0
- package/src/tools/executors/timer/timer-session-queries.ts +153 -0
- package/src/tools/executors/timer/timer-session-updates.ts +200 -0
- package/src/tools/executors/timer/timer-sessions-executor.ts +91 -0
- package/src/tools/executors/timer/timer-stats-executor.ts +157 -0
- package/src/tools/executors/timer.ts +22 -0
- package/src/tools/executors/user.ts +60 -0
- package/src/tools/executors/workspace.ts +135 -0
- package/src/tools/json-render-catalog.ts +875 -0
- package/src/tools/mira-tool-definitions.ts +55 -0
- package/src/tools/mira-tool-dispatcher.ts +265 -0
- package/src/tools/mira-tool-metadata.ts +164 -0
- package/src/tools/mira-tool-names.ts +95 -0
- package/src/tools/mira-tool-render-ui.ts +54 -0
- package/src/tools/mira-tool-types.ts +17 -0
- package/src/tools/mira-tools.ts +167 -0
- package/src/tools/normalize-render-ui-input.ts +321 -0
- package/src/tools/workspace-context.ts +233 -0
- package/src/types.ts +38 -0
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
import type { AiFeature } from '@tuturuuu/ai/credits/constants';
|
|
2
|
+
import { resolveGatewayModelId } from '@tuturuuu/ai/credits/model-mapping';
|
|
3
|
+
import type {
|
|
4
|
+
CreditReservationCommitResult,
|
|
5
|
+
CreditReservationReleaseResult,
|
|
6
|
+
CreditReservationResult,
|
|
7
|
+
MeteredEmbeddingReservationResult,
|
|
8
|
+
} from '@tuturuuu/ai/credits/types';
|
|
9
|
+
import { createAdminClient } from '@tuturuuu/supabase/next/server';
|
|
10
|
+
import type { Json } from '@tuturuuu/types';
|
|
11
|
+
import {
|
|
12
|
+
decrementAiCreditChargeInFlight,
|
|
13
|
+
incrementAiCreditChargeInFlight,
|
|
14
|
+
invalidateAiCreditSnapshot,
|
|
15
|
+
} from '@tuturuuu/utils/ai-temp-auth';
|
|
16
|
+
|
|
17
|
+
type ReserveFixedCreditsRpcParams = {
|
|
18
|
+
p_ws_id: string;
|
|
19
|
+
p_user_id?: string | null;
|
|
20
|
+
p_amount: number;
|
|
21
|
+
p_model_id: string;
|
|
22
|
+
p_feature: string;
|
|
23
|
+
p_metadata: Json;
|
|
24
|
+
p_expires_in_seconds?: number;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
type ReserveFixedCreditsRpcRow = {
|
|
28
|
+
success?: boolean;
|
|
29
|
+
reservation_id?: string | null;
|
|
30
|
+
remaining_credits?: number | string;
|
|
31
|
+
error_code?: string | null;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
type CommitFixedCreditReservationRpcParams = {
|
|
35
|
+
p_reservation_id: string;
|
|
36
|
+
p_metadata: Json;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
type CommitFixedCreditReservationRpcRow = {
|
|
40
|
+
success?: boolean;
|
|
41
|
+
credits_deducted?: number | string;
|
|
42
|
+
remaining_credits?: number | string;
|
|
43
|
+
error_code?: string | null;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
type ReleaseFixedCreditReservationRpcParams = {
|
|
47
|
+
p_reservation_id: string;
|
|
48
|
+
p_metadata: Json;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
type ReleaseFixedCreditReservationRpcRow = {
|
|
52
|
+
success?: boolean;
|
|
53
|
+
remaining_credits?: number | string;
|
|
54
|
+
error_code?: string | null;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
type ReserveMeteredEmbeddingCreditsRpcParams = {
|
|
58
|
+
p_ws_id: string;
|
|
59
|
+
p_user_id?: string | null;
|
|
60
|
+
p_model_id: string;
|
|
61
|
+
p_input_tokens: number;
|
|
62
|
+
p_feature?: string;
|
|
63
|
+
p_metadata: Json;
|
|
64
|
+
p_expires_in_seconds?: number;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
type ReserveMeteredEmbeddingCreditsRpcRow = {
|
|
68
|
+
success?: boolean;
|
|
69
|
+
reservation_id?: string | null;
|
|
70
|
+
credits_reserved?: number | string;
|
|
71
|
+
cost_usd?: number | string;
|
|
72
|
+
remaining_credits?: number | string;
|
|
73
|
+
error_code?: string | null;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
type CommitMeteredEmbeddingCreditsRpcParams = {
|
|
77
|
+
p_reservation_id: string;
|
|
78
|
+
p_metadata: Json;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
type ReleaseMeteredEmbeddingCreditsRpcParams = {
|
|
82
|
+
p_reservation_id: string;
|
|
83
|
+
p_metadata: Json;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
type RpcError = { message: string } | null;
|
|
87
|
+
|
|
88
|
+
type CreditReservationRpcCaller = {
|
|
89
|
+
rpc: unknown;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
async function getRpcCaller(
|
|
93
|
+
rpcCaller?: CreditReservationRpcCaller
|
|
94
|
+
): Promise<CreditReservationRpcCaller> {
|
|
95
|
+
if (rpcCaller) {
|
|
96
|
+
return rpcCaller;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return createAdminClient();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function rpcErrorFromUnknown(error: unknown): RpcError {
|
|
103
|
+
return {
|
|
104
|
+
message: error instanceof Error ? error.message : 'Unknown RPC failure',
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export async function reserveFixedAiCredits(
|
|
109
|
+
params: {
|
|
110
|
+
wsId: string;
|
|
111
|
+
userId?: string;
|
|
112
|
+
amount: number;
|
|
113
|
+
modelId: string;
|
|
114
|
+
feature: AiFeature;
|
|
115
|
+
metadata?: Record<string, unknown>;
|
|
116
|
+
expiresInSeconds?: number;
|
|
117
|
+
},
|
|
118
|
+
rpcCaller?: CreditReservationRpcCaller
|
|
119
|
+
): Promise<CreditReservationResult> {
|
|
120
|
+
const sbAdmin = await getRpcCaller(rpcCaller);
|
|
121
|
+
const gatewayModelId = resolveGatewayModelId(params.modelId);
|
|
122
|
+
let inFlightMarked = false;
|
|
123
|
+
const rpc = (sbAdmin.rpc as (...args: unknown[]) => unknown).bind(
|
|
124
|
+
sbAdmin
|
|
125
|
+
) as (
|
|
126
|
+
fn: 'reserve_fixed_ai_credits',
|
|
127
|
+
args: ReserveFixedCreditsRpcParams
|
|
128
|
+
) => Promise<{
|
|
129
|
+
data: ReserveFixedCreditsRpcRow[] | null;
|
|
130
|
+
error: RpcError;
|
|
131
|
+
}>;
|
|
132
|
+
|
|
133
|
+
if (params.userId) {
|
|
134
|
+
inFlightMarked = await incrementAiCreditChargeInFlight({
|
|
135
|
+
wsId: params.wsId,
|
|
136
|
+
userId: params.userId,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
let data: ReserveFixedCreditsRpcRow[] | null = null;
|
|
141
|
+
let error: RpcError = null;
|
|
142
|
+
try {
|
|
143
|
+
const result = await rpc('reserve_fixed_ai_credits', {
|
|
144
|
+
p_ws_id: params.wsId,
|
|
145
|
+
p_user_id: params.userId ?? null,
|
|
146
|
+
p_amount: params.amount,
|
|
147
|
+
p_model_id: gatewayModelId,
|
|
148
|
+
p_feature: params.feature,
|
|
149
|
+
p_metadata: (params.metadata ?? {}) as Json,
|
|
150
|
+
...((params.expiresInSeconds ?? 0) > 0
|
|
151
|
+
? { p_expires_in_seconds: params.expiresInSeconds }
|
|
152
|
+
: {}),
|
|
153
|
+
});
|
|
154
|
+
data = result.data;
|
|
155
|
+
error = result.error;
|
|
156
|
+
} catch (caughtError) {
|
|
157
|
+
data = null;
|
|
158
|
+
error = rpcErrorFromUnknown(caughtError);
|
|
159
|
+
} finally {
|
|
160
|
+
if (inFlightMarked && params.userId) {
|
|
161
|
+
await decrementAiCreditChargeInFlight({
|
|
162
|
+
wsId: params.wsId,
|
|
163
|
+
userId: params.userId,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (error) {
|
|
169
|
+
console.error('Error reserving AI credits:', error);
|
|
170
|
+
return {
|
|
171
|
+
success: false,
|
|
172
|
+
reservationId: null,
|
|
173
|
+
remainingCredits: 0,
|
|
174
|
+
errorCode: 'RESERVATION_FAILED',
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const row = Array.isArray(data) ? data[0] : data;
|
|
179
|
+
if (!row) {
|
|
180
|
+
return {
|
|
181
|
+
success: false,
|
|
182
|
+
reservationId: null,
|
|
183
|
+
remainingCredits: 0,
|
|
184
|
+
errorCode: 'NO_RESULT',
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return {
|
|
189
|
+
success: row.success ?? false,
|
|
190
|
+
reservationId: row.reservation_id ?? null,
|
|
191
|
+
remainingCredits: Number(row.remaining_credits ?? 0),
|
|
192
|
+
errorCode: row.error_code ?? null,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export async function reserveMeteredEmbeddingCredits(
|
|
197
|
+
params: {
|
|
198
|
+
expiresInSeconds?: number;
|
|
199
|
+
inputTokens: number;
|
|
200
|
+
metadata?: Record<string, unknown>;
|
|
201
|
+
modelId: string;
|
|
202
|
+
userId?: string | null;
|
|
203
|
+
wsId: string;
|
|
204
|
+
},
|
|
205
|
+
rpcCaller?: CreditReservationRpcCaller
|
|
206
|
+
): Promise<MeteredEmbeddingReservationResult> {
|
|
207
|
+
const sbAdmin = await getRpcCaller(rpcCaller);
|
|
208
|
+
const gatewayModelId = resolveGatewayModelId(params.modelId);
|
|
209
|
+
const rpc = (sbAdmin.rpc as (...args: unknown[]) => unknown).bind(
|
|
210
|
+
sbAdmin
|
|
211
|
+
) as (
|
|
212
|
+
fn: 'reserve_metered_embedding_credits',
|
|
213
|
+
args: ReserveMeteredEmbeddingCreditsRpcParams
|
|
214
|
+
) => Promise<{
|
|
215
|
+
data: ReserveMeteredEmbeddingCreditsRpcRow[] | null;
|
|
216
|
+
error: RpcError;
|
|
217
|
+
}>;
|
|
218
|
+
|
|
219
|
+
let data: ReserveMeteredEmbeddingCreditsRpcRow[] | null = null;
|
|
220
|
+
let error: RpcError = null;
|
|
221
|
+
try {
|
|
222
|
+
const result = await rpc('reserve_metered_embedding_credits', {
|
|
223
|
+
p_ws_id: params.wsId,
|
|
224
|
+
p_user_id: params.userId ?? null,
|
|
225
|
+
p_model_id: gatewayModelId,
|
|
226
|
+
p_input_tokens: params.inputTokens,
|
|
227
|
+
p_feature: 'embeddings',
|
|
228
|
+
p_metadata: (params.metadata ?? {}) as Json,
|
|
229
|
+
...((params.expiresInSeconds ?? 0) > 0
|
|
230
|
+
? { p_expires_in_seconds: params.expiresInSeconds }
|
|
231
|
+
: {}),
|
|
232
|
+
});
|
|
233
|
+
data = result.data;
|
|
234
|
+
error = result.error;
|
|
235
|
+
} catch (caughtError) {
|
|
236
|
+
data = null;
|
|
237
|
+
error = rpcErrorFromUnknown(caughtError);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (error) {
|
|
241
|
+
console.error('Error reserving metered embedding credits:', error);
|
|
242
|
+
return {
|
|
243
|
+
success: false,
|
|
244
|
+
reservationId: null,
|
|
245
|
+
creditsReserved: 0,
|
|
246
|
+
costUsd: 0,
|
|
247
|
+
remainingCredits: 0,
|
|
248
|
+
errorCode: 'RESERVATION_FAILED',
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const row = Array.isArray(data) ? data[0] : data;
|
|
253
|
+
if (!row) {
|
|
254
|
+
return {
|
|
255
|
+
success: false,
|
|
256
|
+
reservationId: null,
|
|
257
|
+
creditsReserved: 0,
|
|
258
|
+
costUsd: 0,
|
|
259
|
+
remainingCredits: 0,
|
|
260
|
+
errorCode: 'NO_RESULT',
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return {
|
|
265
|
+
success: row.success ?? false,
|
|
266
|
+
reservationId: row.reservation_id ?? null,
|
|
267
|
+
creditsReserved: Number(row.credits_reserved ?? 0),
|
|
268
|
+
costUsd: Number(row.cost_usd ?? 0),
|
|
269
|
+
remainingCredits: Number(row.remaining_credits ?? 0),
|
|
270
|
+
errorCode: row.error_code ?? null,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
export async function commitMeteredEmbeddingCredits(
|
|
275
|
+
reservationId: string,
|
|
276
|
+
metadata?: Record<string, unknown>,
|
|
277
|
+
rpcCaller?: CreditReservationRpcCaller
|
|
278
|
+
): Promise<CreditReservationCommitResult> {
|
|
279
|
+
const sbAdmin = await getRpcCaller(rpcCaller);
|
|
280
|
+
const wsId = typeof metadata?.wsId === 'string' ? metadata.wsId : null;
|
|
281
|
+
const userId = typeof metadata?.userId === 'string' ? metadata.userId : null;
|
|
282
|
+
const rpc = (sbAdmin.rpc as (...args: unknown[]) => unknown).bind(
|
|
283
|
+
sbAdmin
|
|
284
|
+
) as (
|
|
285
|
+
fn: 'commit_metered_embedding_credits',
|
|
286
|
+
args: CommitMeteredEmbeddingCreditsRpcParams
|
|
287
|
+
) => Promise<{
|
|
288
|
+
data: CommitFixedCreditReservationRpcRow[] | null;
|
|
289
|
+
error: RpcError;
|
|
290
|
+
}>;
|
|
291
|
+
|
|
292
|
+
let data: CommitFixedCreditReservationRpcRow[] | null = null;
|
|
293
|
+
let error: RpcError = null;
|
|
294
|
+
try {
|
|
295
|
+
const result = await rpc('commit_metered_embedding_credits', {
|
|
296
|
+
p_reservation_id: reservationId,
|
|
297
|
+
p_metadata: (metadata ?? {}) as Json,
|
|
298
|
+
});
|
|
299
|
+
data = result.data;
|
|
300
|
+
error = result.error;
|
|
301
|
+
} catch (caughtError) {
|
|
302
|
+
data = null;
|
|
303
|
+
error = rpcErrorFromUnknown(caughtError);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (error) {
|
|
307
|
+
console.error('Error committing metered embedding credits:', error);
|
|
308
|
+
return {
|
|
309
|
+
success: false,
|
|
310
|
+
creditsDeducted: 0,
|
|
311
|
+
remainingCredits: 0,
|
|
312
|
+
errorCode: 'COMMIT_FAILED',
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const row = Array.isArray(data) ? data[0] : data;
|
|
317
|
+
if (!row) {
|
|
318
|
+
return {
|
|
319
|
+
success: false,
|
|
320
|
+
creditsDeducted: 0,
|
|
321
|
+
remainingCredits: 0,
|
|
322
|
+
errorCode: 'NO_RESULT',
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const result = {
|
|
327
|
+
success: row.success ?? false,
|
|
328
|
+
creditsDeducted: Number(row.credits_deducted ?? 0),
|
|
329
|
+
remainingCredits: Number(row.remaining_credits ?? 0),
|
|
330
|
+
errorCode: row.error_code ?? null,
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
if (result.success && wsId && userId) {
|
|
334
|
+
await invalidateAiCreditSnapshot({ wsId, userId });
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return result;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
export async function releaseMeteredEmbeddingCredits(
|
|
341
|
+
reservationId: string,
|
|
342
|
+
metadata?: Record<string, unknown>,
|
|
343
|
+
rpcCaller?: CreditReservationRpcCaller
|
|
344
|
+
): Promise<CreditReservationReleaseResult> {
|
|
345
|
+
const sbAdmin = await getRpcCaller(rpcCaller);
|
|
346
|
+
const rpc = (sbAdmin.rpc as (...args: unknown[]) => unknown).bind(
|
|
347
|
+
sbAdmin
|
|
348
|
+
) as (
|
|
349
|
+
fn: 'release_metered_embedding_credits',
|
|
350
|
+
args: ReleaseMeteredEmbeddingCreditsRpcParams
|
|
351
|
+
) => Promise<{
|
|
352
|
+
data: ReleaseFixedCreditReservationRpcRow[] | null;
|
|
353
|
+
error: RpcError;
|
|
354
|
+
}>;
|
|
355
|
+
|
|
356
|
+
let data: ReleaseFixedCreditReservationRpcRow[] | null = null;
|
|
357
|
+
let error: RpcError = null;
|
|
358
|
+
try {
|
|
359
|
+
const result = await rpc('release_metered_embedding_credits', {
|
|
360
|
+
p_reservation_id: reservationId,
|
|
361
|
+
p_metadata: (metadata ?? {}) as Json,
|
|
362
|
+
});
|
|
363
|
+
data = result.data;
|
|
364
|
+
error = result.error;
|
|
365
|
+
} catch (caughtError) {
|
|
366
|
+
data = null;
|
|
367
|
+
error = rpcErrorFromUnknown(caughtError);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (error) {
|
|
371
|
+
console.error('Error releasing metered embedding credits:', error);
|
|
372
|
+
return {
|
|
373
|
+
success: false,
|
|
374
|
+
remainingCredits: 0,
|
|
375
|
+
errorCode: 'RELEASE_FAILED',
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
const row = Array.isArray(data) ? data[0] : data;
|
|
380
|
+
if (!row) {
|
|
381
|
+
return {
|
|
382
|
+
success: false,
|
|
383
|
+
remainingCredits: 0,
|
|
384
|
+
errorCode: 'NO_RESULT',
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
return {
|
|
389
|
+
success: row.success ?? false,
|
|
390
|
+
remainingCredits: Number(row.remaining_credits ?? 0),
|
|
391
|
+
errorCode: row.error_code ?? null,
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
export async function commitFixedAiCreditReservation(
|
|
396
|
+
reservationId: string,
|
|
397
|
+
metadata?: Record<string, unknown>,
|
|
398
|
+
rpcCaller?: CreditReservationRpcCaller
|
|
399
|
+
): Promise<CreditReservationCommitResult> {
|
|
400
|
+
const sbAdmin = await getRpcCaller(rpcCaller);
|
|
401
|
+
const wsId = typeof metadata?.wsId === 'string' ? metadata.wsId : null;
|
|
402
|
+
const userId = typeof metadata?.userId === 'string' ? metadata.userId : null;
|
|
403
|
+
let inFlightMarked = false;
|
|
404
|
+
const rpc = (sbAdmin.rpc as (...args: unknown[]) => unknown).bind(
|
|
405
|
+
sbAdmin
|
|
406
|
+
) as (
|
|
407
|
+
fn: 'commit_fixed_ai_credit_reservation',
|
|
408
|
+
args: CommitFixedCreditReservationRpcParams
|
|
409
|
+
) => Promise<{
|
|
410
|
+
data: CommitFixedCreditReservationRpcRow[] | null;
|
|
411
|
+
error: RpcError;
|
|
412
|
+
}>;
|
|
413
|
+
|
|
414
|
+
if (wsId && userId) {
|
|
415
|
+
inFlightMarked = await incrementAiCreditChargeInFlight({ wsId, userId });
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
let data: CommitFixedCreditReservationRpcRow[] | null = null;
|
|
419
|
+
let error: RpcError = null;
|
|
420
|
+
try {
|
|
421
|
+
const result = await rpc('commit_fixed_ai_credit_reservation', {
|
|
422
|
+
p_reservation_id: reservationId,
|
|
423
|
+
p_metadata: (metadata ?? {}) as Json,
|
|
424
|
+
});
|
|
425
|
+
data = result.data;
|
|
426
|
+
error = result.error;
|
|
427
|
+
} catch (caughtError) {
|
|
428
|
+
data = null;
|
|
429
|
+
error = rpcErrorFromUnknown(caughtError);
|
|
430
|
+
} finally {
|
|
431
|
+
if (inFlightMarked && wsId && userId) {
|
|
432
|
+
await decrementAiCreditChargeInFlight({ wsId, userId });
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
if (error) {
|
|
437
|
+
console.error('Error committing AI credit reservation:', error);
|
|
438
|
+
return {
|
|
439
|
+
success: false,
|
|
440
|
+
creditsDeducted: 0,
|
|
441
|
+
remainingCredits: 0,
|
|
442
|
+
errorCode: 'COMMIT_FAILED',
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const row = Array.isArray(data) ? data[0] : data;
|
|
447
|
+
if (!row) {
|
|
448
|
+
return {
|
|
449
|
+
success: false,
|
|
450
|
+
creditsDeducted: 0,
|
|
451
|
+
remainingCredits: 0,
|
|
452
|
+
errorCode: 'NO_RESULT',
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
const result = {
|
|
457
|
+
success: row.success ?? false,
|
|
458
|
+
creditsDeducted: Number(row.credits_deducted ?? 0),
|
|
459
|
+
remainingCredits: Number(row.remaining_credits ?? 0),
|
|
460
|
+
errorCode: row.error_code ?? null,
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
if (result.success && wsId && userId) {
|
|
464
|
+
await invalidateAiCreditSnapshot({ wsId, userId });
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
return result;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
export async function releaseFixedAiCreditReservation(
|
|
471
|
+
reservationId: string,
|
|
472
|
+
metadata?: Record<string, unknown>,
|
|
473
|
+
rpcCaller?: CreditReservationRpcCaller
|
|
474
|
+
): Promise<CreditReservationReleaseResult> {
|
|
475
|
+
const sbAdmin = await getRpcCaller(rpcCaller);
|
|
476
|
+
const rpc = (sbAdmin.rpc as (...args: unknown[]) => unknown).bind(
|
|
477
|
+
sbAdmin
|
|
478
|
+
) as (
|
|
479
|
+
fn: 'release_fixed_ai_credit_reservation',
|
|
480
|
+
args: ReleaseFixedCreditReservationRpcParams
|
|
481
|
+
) => Promise<{
|
|
482
|
+
data: ReleaseFixedCreditReservationRpcRow[] | null;
|
|
483
|
+
error: RpcError;
|
|
484
|
+
}>;
|
|
485
|
+
|
|
486
|
+
const { data, error } = await rpc('release_fixed_ai_credit_reservation', {
|
|
487
|
+
p_reservation_id: reservationId,
|
|
488
|
+
p_metadata: (metadata ?? {}) as Json,
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
if (error) {
|
|
492
|
+
console.error('Error releasing AI credit reservation:', error);
|
|
493
|
+
return {
|
|
494
|
+
success: false,
|
|
495
|
+
remainingCredits: 0,
|
|
496
|
+
errorCode: 'RELEASE_FAILED',
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
const row = Array.isArray(data) ? data[0] : data;
|
|
501
|
+
if (!row) {
|
|
502
|
+
return {
|
|
503
|
+
success: false,
|
|
504
|
+
remainingCredits: 0,
|
|
505
|
+
errorCode: 'NO_RESULT',
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
return {
|
|
510
|
+
success: row.success ?? false,
|
|
511
|
+
remainingCredits: Number(row.remaining_credits ?? 0),
|
|
512
|
+
errorCode: row.error_code ?? null,
|
|
513
|
+
};
|
|
514
|
+
}
|