@tuturuuu/ai 0.12.0 → 0.13.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/package.json +2 -2
- package/src/studio/metering.ts +17 -2
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tuturuuu/ai",
|
|
3
3
|
"license": "MIT",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.13.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "https://github.com/tutur3u/platform",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"@streamdown/math": "^1.0.2",
|
|
77
77
|
"@streamdown/mermaid": "^1.0.2",
|
|
78
78
|
"@tuturuuu/google": "0.1.0",
|
|
79
|
-
"@tuturuuu/internal-api": "0.38.
|
|
79
|
+
"@tuturuuu/internal-api": "0.38.1",
|
|
80
80
|
"@tuturuuu/supabase": "0.5.1",
|
|
81
81
|
"@tuturuuu/utils": "0.28.0",
|
|
82
82
|
"@vercel/sandbox": "^3.2.1",
|
package/src/studio/metering.ts
CHANGED
|
@@ -115,8 +115,9 @@ export async function calculateAiStudioUsageCost(
|
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
export type BeginAiStudioRunInput = {
|
|
118
|
+
rejectExisting?: boolean;
|
|
118
119
|
actorId: string;
|
|
119
|
-
apiKeyId
|
|
120
|
+
apiKeyId?: string;
|
|
120
121
|
feature: string;
|
|
121
122
|
idempotencyKey?: string | null;
|
|
122
123
|
metadata?: Json;
|
|
@@ -165,7 +166,8 @@ export async function beginAiStudioRun(
|
|
|
165
166
|
const { data, error } = await sbAdmin
|
|
166
167
|
.schema('private')
|
|
167
168
|
.rpc('begin_ai_studio_run', {
|
|
168
|
-
|
|
169
|
+
// SQL accepts NULL for first-party workspace reservations; generated RPC types do not express nullable arguments.
|
|
170
|
+
p_api_key_id: input.apiKeyId ?? (null as unknown as string),
|
|
169
171
|
p_feature: input.feature,
|
|
170
172
|
p_idempotency_key: input.idempotencyKey ?? undefined,
|
|
171
173
|
p_metadata: input.metadata,
|
|
@@ -177,6 +179,19 @@ export async function beginAiStudioRun(
|
|
|
177
179
|
});
|
|
178
180
|
|
|
179
181
|
const result = data?.[0];
|
|
182
|
+
// The transactional RPC returns NULL remaining_credits for an existing run;
|
|
183
|
+
// a concurrent insert loses the unique idempotency constraint and rolls back.
|
|
184
|
+
// Fence before provider execution without a second, fallible claim update.
|
|
185
|
+
if (
|
|
186
|
+
input.rejectExisting &&
|
|
187
|
+
(error?.code === '23505' ||
|
|
188
|
+
(result?.success && result.remaining_credits === null))
|
|
189
|
+
) {
|
|
190
|
+
throw new AiStudioError(
|
|
191
|
+
'This sponsored request is already running or completed.',
|
|
192
|
+
{ code: 'invalid_request_error', status: 409 }
|
|
193
|
+
);
|
|
194
|
+
}
|
|
180
195
|
if (error || !result?.success || !result.run_id || !result.reservation_id) {
|
|
181
196
|
throw reservationError(result?.error_code ?? null);
|
|
182
197
|
}
|