@opengeni/api-router 0.4.0 → 0.4.1
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/app.js +1 -1
- package/dist/{chunk-I2EDWHVF.js → chunk-2JL5OXRE.js} +76 -4
- package/dist/chunk-2JL5OXRE.js.map +1 -0
- package/dist/index.js +38 -3
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
- package/src/app.ts +67 -1
- package/src/http/auth.ts +1 -1
- package/src/index.ts +9 -4
- package/src/observability.ts +31 -0
- package/src/routes/billing.ts +19 -1
- package/src/sandbox/auth-callout.ts +5 -1
- package/dist/chunk-I2EDWHVF.js.map +0 -1
package/dist/app.js
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
} from "@opengeni/config";
|
|
7
7
|
import { ClientConfig } from "@opengeni/contracts";
|
|
8
8
|
import { createDocumentServices, indexDocumentNow } from "@opengeni/documents";
|
|
9
|
+
import { dbSql } from "@opengeni/db";
|
|
9
10
|
import { createObservability } from "@opengeni/observability";
|
|
10
11
|
import { createObjectStorage } from "@opengeni/storage";
|
|
11
12
|
import { WebStandardStreamableHTTPServerTransport as WebStandardStreamableHTTPServerTransport2 } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
|
|
@@ -1367,7 +1368,7 @@ function isAuthExempt(c, settings) {
|
|
|
1367
1368
|
if (installExactPaths.has(path) || isInstallRedirectPath(path)) {
|
|
1368
1369
|
return true;
|
|
1369
1370
|
}
|
|
1370
|
-
if (settings.authAllowHealth && path === "/healthz") {
|
|
1371
|
+
if (settings.authAllowHealth && (path === "/healthz" || path === "/readyz")) {
|
|
1371
1372
|
return true;
|
|
1372
1373
|
}
|
|
1373
1374
|
if (settings.authAllowMetrics && path === "/metrics") {
|
|
@@ -3394,6 +3395,7 @@ async function handleCheckoutSessionCompleted(deps, event) {
|
|
|
3394
3395
|
stripeCreditAmountUsd: credit.amountUsd
|
|
3395
3396
|
}
|
|
3396
3397
|
});
|
|
3398
|
+
recordCreditMicrosMetric(deps, "topup", credit.amountMicros);
|
|
3397
3399
|
}
|
|
3398
3400
|
async function mirrorPaymentIntentCustomer(deps, event) {
|
|
3399
3401
|
const intent = event.data.object;
|
|
@@ -3426,18 +3428,23 @@ async function applyRefundDebit(deps, stripe, refund) {
|
|
|
3426
3428
|
if (!accountId) {
|
|
3427
3429
|
return;
|
|
3428
3430
|
}
|
|
3431
|
+
const idempotencyKey = `stripe:refund:${refund.id}`;
|
|
3432
|
+
if (await hasCreditLedgerEntry(deps.db, accountId, idempotencyKey)) {
|
|
3433
|
+
return;
|
|
3434
|
+
}
|
|
3429
3435
|
await applyCreditLedgerEntry(deps.db, {
|
|
3430
3436
|
accountId,
|
|
3431
3437
|
type: "credit_refund",
|
|
3432
3438
|
amountMicros: -centsToMicros(refund.amount),
|
|
3433
3439
|
sourceType: "stripe_refund",
|
|
3434
3440
|
sourceId: refund.id,
|
|
3435
|
-
idempotencyKey
|
|
3441
|
+
idempotencyKey,
|
|
3436
3442
|
metadata: {
|
|
3437
3443
|
stripeRefundId: refund.id,
|
|
3438
3444
|
stripePaymentIntentId: paymentIntentId(refund.payment_intent)
|
|
3439
3445
|
}
|
|
3440
3446
|
});
|
|
3447
|
+
recordCreditMicrosMetric(deps, "refund", centsToMicros(refund.amount));
|
|
3441
3448
|
}
|
|
3442
3449
|
async function holdDisputedCredits(deps, stripe, event) {
|
|
3443
3450
|
const dispute = event.data.object;
|
|
@@ -3492,6 +3499,17 @@ async function mirrorCustomer(deps, event, customer) {
|
|
|
3492
3499
|
email: typeof customer.email === "string" ? customer.email : null
|
|
3493
3500
|
});
|
|
3494
3501
|
}
|
|
3502
|
+
function recordCreditMicrosMetric(deps, kind, amountMicros) {
|
|
3503
|
+
if (amountMicros <= 0) {
|
|
3504
|
+
return;
|
|
3505
|
+
}
|
|
3506
|
+
deps.observability?.incrementCounter({
|
|
3507
|
+
name: "opengeni_credit_micros_total",
|
|
3508
|
+
help: "Total credit micros recorded by kind.",
|
|
3509
|
+
labels: { kind },
|
|
3510
|
+
amount: amountMicros
|
|
3511
|
+
});
|
|
3512
|
+
}
|
|
3495
3513
|
async function metadataForRefund(stripe, refund) {
|
|
3496
3514
|
if (Object.keys(refund.metadata ?? {}).length > 0) {
|
|
3497
3515
|
return refund.metadata;
|
|
@@ -6194,13 +6212,19 @@ function createApp(deps) {
|
|
|
6194
6212
|
service: deps.settings.serviceName,
|
|
6195
6213
|
environment: deps.settings.environment,
|
|
6196
6214
|
deploymentRevision: deps.settings.deploymentRevision,
|
|
6215
|
+
...deps.settings.serverVersion ? { serverVersion: deps.settings.serverVersion } : {},
|
|
6197
6216
|
ok: true
|
|
6198
6217
|
}));
|
|
6199
|
-
app.get("/
|
|
6218
|
+
app.get("/readyz", async (c) => {
|
|
6219
|
+
const result = await runReadinessChecks(readinessChecks(deps), 2e3);
|
|
6220
|
+
return c.json(result, result.ok ? 200 : 503);
|
|
6221
|
+
});
|
|
6222
|
+
app.get("/metrics", async (c) => c.text(await observability.prometheusMetrics(), 200, {
|
|
6200
6223
|
"content-type": "text/plain; version=0.0.4; charset=utf-8"
|
|
6201
6224
|
}));
|
|
6202
6225
|
app.get("/v1/config/client", (c) => c.json(ClientConfig.parse({
|
|
6203
6226
|
deploymentRevision: deps.settings.deploymentRevision,
|
|
6227
|
+
...deps.settings.serverVersion ? { serverVersion: deps.settings.serverVersion } : {},
|
|
6204
6228
|
defaultModel: deps.settings.openaiModel,
|
|
6205
6229
|
allowedModels: configuredAllowedModels(deps.settings),
|
|
6206
6230
|
// Provider-grouped model list for the picker. configuredModels() carries the
|
|
@@ -6283,8 +6307,56 @@ function httpStatusForError(error) {
|
|
|
6283
6307
|
}
|
|
6284
6308
|
return 500;
|
|
6285
6309
|
}
|
|
6310
|
+
function readinessChecks(deps) {
|
|
6311
|
+
return {
|
|
6312
|
+
db: deps.readinessChecks?.db ?? (async () => {
|
|
6313
|
+
await deps.db.execute(dbSql`select 1`);
|
|
6314
|
+
}),
|
|
6315
|
+
nats: deps.readinessChecks?.nats ?? (() => {
|
|
6316
|
+
if (deps.bus.isConnected && !deps.bus.isConnected()) {
|
|
6317
|
+
throw new Error("NATS is not connected");
|
|
6318
|
+
}
|
|
6319
|
+
}),
|
|
6320
|
+
temporal: deps.readinessChecks?.temporal ?? deps.workflowClient.check ?? (() => {
|
|
6321
|
+
throw new Error("Temporal readiness check unavailable");
|
|
6322
|
+
})
|
|
6323
|
+
};
|
|
6324
|
+
}
|
|
6325
|
+
async function runReadinessChecks(checks, timeoutMs) {
|
|
6326
|
+
const entries = await Promise.all(
|
|
6327
|
+
Object.entries(checks).map(async ([name, check]) => {
|
|
6328
|
+
try {
|
|
6329
|
+
await withTimeout(Promise.resolve().then(check), timeoutMs);
|
|
6330
|
+
return [name, { ok: true }];
|
|
6331
|
+
} catch (error) {
|
|
6332
|
+
return [name, { ok: false, error: error instanceof Error ? error.message : String(error) }];
|
|
6333
|
+
}
|
|
6334
|
+
})
|
|
6335
|
+
);
|
|
6336
|
+
const result = Object.fromEntries(entries);
|
|
6337
|
+
return {
|
|
6338
|
+
ok: Object.values(result).every((check) => check.ok),
|
|
6339
|
+
checks: result
|
|
6340
|
+
};
|
|
6341
|
+
}
|
|
6342
|
+
async function withTimeout(promise, timeoutMs) {
|
|
6343
|
+
let timer;
|
|
6344
|
+
try {
|
|
6345
|
+
return await Promise.race([
|
|
6346
|
+
promise,
|
|
6347
|
+
new Promise((_, reject) => {
|
|
6348
|
+
timer = setTimeout(() => reject(new Error(`readiness check timed out after ${timeoutMs}ms`)), timeoutMs);
|
|
6349
|
+
})
|
|
6350
|
+
]);
|
|
6351
|
+
} finally {
|
|
6352
|
+
if (timer) {
|
|
6353
|
+
clearTimeout(timer);
|
|
6354
|
+
}
|
|
6355
|
+
}
|
|
6356
|
+
}
|
|
6286
6357
|
var routeLabelPatterns = [
|
|
6287
6358
|
{ pattern: /^\/healthz$/, label: "/healthz" },
|
|
6359
|
+
{ pattern: /^\/readyz$/, label: "/readyz" },
|
|
6288
6360
|
{ pattern: /^\/v1\/workspaces\/[^/]+\/codex\/connect\/start$/, label: "/v1/workspaces/:workspaceId/codex/connect/start" },
|
|
6289
6361
|
{ pattern: /^\/v1\/workspaces\/[^/]+\/codex\/connect\/poll$/, label: "/v1/workspaces/:workspaceId/codex/connect/poll" },
|
|
6290
6362
|
{ pattern: /^\/v1\/workspaces\/[^/]+\/codex\/status$/, label: "/v1/workspaces/:workspaceId/codex/status" },
|
|
@@ -6384,4 +6456,4 @@ export {
|
|
|
6384
6456
|
withDefaultEnabledCapabilityMcpTools,
|
|
6385
6457
|
workflowIdForSession3 as workflowIdForSession
|
|
6386
6458
|
};
|
|
6387
|
-
//# sourceMappingURL=chunk-
|
|
6459
|
+
//# sourceMappingURL=chunk-2JL5OXRE.js.map
|