@opengeni/db 1.3.0 → 1.4.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 (70) hide show
  1. package/dist/canonical-human-identities.js +3 -3
  2. package/dist/capability-reconciliation.js +2 -2
  3. package/dist/{chunk-LRSIODCQ.js → chunk-27T4AP25.js} +2 -2
  4. package/dist/{chunk-VQX54TK3.js → chunk-3WUCM7YF.js} +3 -3
  5. package/dist/{chunk-BRVBLQAL.js → chunk-AMK3FNOW.js} +4 -4
  6. package/dist/{chunk-AQMH2ZEH.js → chunk-BA52ITIY.js} +2 -2
  7. package/dist/{chunk-6S5T6FSP.js → chunk-CKDHKQS4.js} +5 -5
  8. package/dist/{chunk-HYBQABBJ.js → chunk-EFANLEWI.js} +2 -2
  9. package/dist/{chunk-PNWWNEDM.js → chunk-EMYA6XNE.js} +2 -2
  10. package/dist/{chunk-6UKNJ43T.js → chunk-GC5GUTV3.js} +2 -2
  11. package/dist/{chunk-DSNEIW5E.js → chunk-JL6TBB76.js} +2 -1
  12. package/dist/chunk-JL6TBB76.js.map +1 -0
  13. package/dist/{chunk-OEFNTGR3.js → chunk-NT7OGKYX.js} +4 -4
  14. package/dist/{chunk-BID3CNN3.js → chunk-T3CYF3DH.js} +3 -3
  15. package/dist/{chunk-3XHC5KC5.js → chunk-TRUEH4I2.js} +2 -2
  16. package/dist/{chunk-7S3O33NM.js → chunk-UQELJ6OM.js} +2 -2
  17. package/dist/{chunk-OI6YZXTU.js → chunk-VCHK4D6S.js} +2 -2
  18. package/dist/connect-attempts.js +3 -3
  19. package/dist/connection-metadata.d.ts +416 -0
  20. package/dist/editable-artifact-durable-export.js +2 -2
  21. package/dist/editable-artifacts.js +3 -3
  22. package/dist/index.d.ts +28 -7
  23. package/dist/index.js +10304 -9877
  24. package/dist/index.js.map +1 -1
  25. package/dist/legacy-tool-action-reviews.d.ts +75 -0
  26. package/dist/managed-auth-session-sets.js +3 -3
  27. package/dist/mcp-operations.js +2 -2
  28. package/dist/organization-integration-policy.js +3 -3
  29. package/dist/organization-slack-bots.d.ts +1 -1
  30. package/dist/retained-provider-commands.js +6 -6
  31. package/dist/schema.js +1 -1
  32. package/dist/session-background-commands.js +4 -4
  33. package/dist/session-command-output.js +5 -5
  34. package/dist/session-event-slices.js +3 -3
  35. package/dist/session-mcp-credential-rotation.js +5 -5
  36. package/dist/session-realtime-billing.d.ts +48 -0
  37. package/dist/session-realtime.d.ts +8 -2
  38. package/dist/session-tenancy.js +3 -3
  39. package/dist/video-generation.js +3 -3
  40. package/dist/voice-transcription-settlement.d.ts +36 -0
  41. package/dist/workspace-tool-defaults.js +4 -4
  42. package/drizzle/0623_voice_transcription_attribution.sql +128 -0
  43. package/drizzle/0624_azure_live_realtime_model.sql +30 -0
  44. package/drizzle/0625_transcription_billing_refusal_codes.sql +29 -0
  45. package/package.json +7 -7
  46. package/src/connection-metadata.ts +166 -0
  47. package/src/index.ts +98 -165
  48. package/src/insights-unified.ts +2 -1
  49. package/src/legacy-tool-action-reviews.ts +242 -0
  50. package/src/organization-slack-bots.ts +1 -1
  51. package/src/schema.ts +1 -0
  52. package/src/session-realtime-billing.ts +135 -0
  53. package/src/session-realtime-ledger.ts +9 -4
  54. package/src/session-realtime.ts +20 -2
  55. package/src/tool-action-reviews.ts +129 -18
  56. package/src/voice-transcription-settlement.ts +94 -0
  57. package/dist/chunk-DSNEIW5E.js.map +0 -1
  58. /package/dist/{chunk-LRSIODCQ.js.map → chunk-27T4AP25.js.map} +0 -0
  59. /package/dist/{chunk-VQX54TK3.js.map → chunk-3WUCM7YF.js.map} +0 -0
  60. /package/dist/{chunk-BRVBLQAL.js.map → chunk-AMK3FNOW.js.map} +0 -0
  61. /package/dist/{chunk-AQMH2ZEH.js.map → chunk-BA52ITIY.js.map} +0 -0
  62. /package/dist/{chunk-6S5T6FSP.js.map → chunk-CKDHKQS4.js.map} +0 -0
  63. /package/dist/{chunk-HYBQABBJ.js.map → chunk-EFANLEWI.js.map} +0 -0
  64. /package/dist/{chunk-PNWWNEDM.js.map → chunk-EMYA6XNE.js.map} +0 -0
  65. /package/dist/{chunk-6UKNJ43T.js.map → chunk-GC5GUTV3.js.map} +0 -0
  66. /package/dist/{chunk-OEFNTGR3.js.map → chunk-NT7OGKYX.js.map} +0 -0
  67. /package/dist/{chunk-BID3CNN3.js.map → chunk-T3CYF3DH.js.map} +0 -0
  68. /package/dist/{chunk-3XHC5KC5.js.map → chunk-TRUEH4I2.js.map} +0 -0
  69. /package/dist/{chunk-7S3O33NM.js.map → chunk-UQELJ6OM.js.map} +0 -0
  70. /package/dist/{chunk-OI6YZXTU.js.map → chunk-VCHK4D6S.js.map} +0 -0
@@ -0,0 +1,94 @@
1
+ import { sql } from "drizzle-orm";
2
+ import { CreditDebitAttribution } from "./credit-debit-attribution";
3
+ import type { Database } from "./database";
4
+ import { rawRows, withRlsContext } from "./database";
5
+
6
+ /** Usage source and credit debit type of deployment-funded voice transcription. */
7
+ export const VOICE_TRANSCRIPTION_SOURCE_TYPE = "voice_transcription";
8
+ export const VOICE_TRANSCRIPTION_DEBIT_TYPE = "voice_transcription_debit";
9
+
10
+ /**
11
+ * Idempotency keys for one settled voice-transcription unit. Both derive from
12
+ * the workspace and the server-built unit id only, so an inline settlement, its
13
+ * in-process retry, and a later reconciliation converge on the same rows.
14
+ */
15
+ export function voiceTranscriptionSettlementKeys(input: {
16
+ workspaceId: string;
17
+ sourceId: string;
18
+ }): { usageIdempotencyKey: string; debitIdempotencyKey: string } {
19
+ return {
20
+ usageIdempotencyKey: `voice.transcription_cost:${input.sourceId}`,
21
+ debitIdempotencyKey: `credit:${VOICE_TRANSCRIPTION_DEBIT_TYPE}:voice_input:${input.workspaceId}:${input.sourceId}`,
22
+ };
23
+ }
24
+
25
+ export type UnsettledVoiceTranscriptionCharge = {
26
+ sourceId: string;
27
+ amountMicros: number;
28
+ attribution: CreditDebitAttribution;
29
+ };
30
+
31
+ /**
32
+ * Voice usage receipts in one workspace whose credit debit never committed
33
+ * (the debit transaction failed after the receipt was durable). Bounded and
34
+ * ordered oldest first; `minAgeMilliseconds` leaves an in-flight inline
35
+ * settlement to finish with its full ledger metadata first. The scan walks the
36
+ * workspace's `model.cost` index range, so the window is short (3 days) and
37
+ * the statement is capped at 2 s; a timeout only defers reconciliation.
38
+ */
39
+ export async function listUnsettledVoiceTranscriptionCharges(
40
+ db: Database,
41
+ input: {
42
+ accountId: string;
43
+ workspaceId: string;
44
+ limit?: number;
45
+ minAgeMilliseconds?: number;
46
+ },
47
+ ): Promise<UnsettledVoiceTranscriptionCharge[]> {
48
+ const limit = Math.max(1, Math.min(input.limit ?? 20, 100));
49
+ const minAgeSeconds = Math.max(0, Math.floor((input.minAgeMilliseconds ?? 60_000) / 1_000));
50
+ return await withRlsContext(
51
+ db,
52
+ { accountId: input.accountId, workspaceId: input.workspaceId },
53
+ async (scopedDb) => {
54
+ await scopedDb.execute(sql`select set_config('statement_timeout', '2000ms', true)`);
55
+ const rows = await rawRows<{
56
+ source_id: string;
57
+ quantity: string | number;
58
+ attribution: unknown;
59
+ }>(
60
+ scopedDb,
61
+ sql`
62
+ select usage_row.source_resource_id as source_id,
63
+ usage_row.quantity,
64
+ usage_row.initiator_context -> 'creditDebitAttribution' as attribution
65
+ from usage_events usage_row
66
+ where usage_row.account_id = ${input.accountId}::uuid
67
+ and usage_row.workspace_id = ${input.workspaceId}::uuid
68
+ and usage_row.event_type = 'model.cost'
69
+ and usage_row.source_resource_type = ${VOICE_TRANSCRIPTION_SOURCE_TYPE}
70
+ and usage_row.source_resource_id is not null
71
+ and usage_row.quantity > 0
72
+ and usage_row.idempotency_key = 'voice.transcription_cost:' || usage_row.source_resource_id
73
+ and usage_row.occurred_at >= now() - interval '3 days'
74
+ and usage_row.occurred_at <= now() - make_interval(secs => ${minAgeSeconds})
75
+ and not exists (
76
+ select 1 from credit_ledger_entries ledger
77
+ where ledger.idempotency_key = ${`credit:${VOICE_TRANSCRIPTION_DEBIT_TYPE}:voice_input:`}
78
+ || usage_row.workspace_id::text || ':' || usage_row.source_resource_id
79
+ )
80
+ order by usage_row.occurred_at asc
81
+ limit ${limit}
82
+ `,
83
+ );
84
+ return rows.map((row) => {
85
+ const attribution = CreditDebitAttribution.safeParse(row.attribution);
86
+ return {
87
+ sourceId: row.source_id,
88
+ amountMicros: Number(row.quantity),
89
+ attribution: attribution.success ? attribution.data : { kind: "unknown" as const },
90
+ };
91
+ });
92
+ },
93
+ );
94
+ }