@opengeni/db 3.2.0-canary.0 → 3.4.0-canary.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/dist/canonical-human-identities.js +3 -3
- package/dist/{chunk-SIBYBA2D.js → chunk-6DPJA36C.js} +30 -11
- package/dist/chunk-6DPJA36C.js.map +1 -0
- package/dist/{chunk-KRLPEMLH.js → chunk-C2AFP7SB.js} +184 -6
- package/dist/chunk-C2AFP7SB.js.map +1 -0
- package/dist/{chunk-AZHW7R5V.js → chunk-H7MXYG7R.js} +12 -8
- package/dist/chunk-H7MXYG7R.js.map +1 -0
- package/dist/{chunk-2PRS4J5Q.js → chunk-HY3F5Q4E.js} +3 -3
- package/dist/{chunk-NAB6FKFN.js → chunk-O6FTELKH.js} +3 -3
- package/dist/{chunk-UZNXG44K.js → chunk-PYMY3AJW.js} +324 -8
- package/dist/chunk-PYMY3AJW.js.map +1 -0
- package/dist/{chunk-6HMM2R5T.js → chunk-TRBOWUG3.js} +98 -4
- package/dist/chunk-TRBOWUG3.js.map +1 -0
- package/dist/{chunk-E6CLMKEE.js → chunk-V3TRUXFJ.js} +2 -2
- package/dist/{chunk-2EH4WRHL.js → chunk-ZWRIPCTR.js} +2 -2
- package/dist/editable-artifact-durable-export.js +2 -2
- package/dist/editable-artifacts.js +3 -3
- package/dist/governed-learning-activation.d.ts +16 -0
- package/dist/index.d.ts +108 -7
- package/dist/index.js +3605 -1417
- package/dist/index.js.map +1 -1
- package/dist/insights-model-bundle.d.ts +30 -0
- package/dist/insights-usage-bundle.d.ts +32 -0
- package/dist/insights.d.ts +10 -2
- package/dist/lossless-json.d.ts +1 -1
- package/dist/managed-user-setup.d.ts +82 -0
- package/dist/memory-domain.d.ts +2 -2
- package/dist/migrate.d.ts +3 -1
- package/dist/migrate.js +1 -1
- package/dist/new-session-drafts.d.ts +4 -4
- package/dist/organization-membership-lifecycle.d.ts +60 -1
- package/dist/pr-review.d.ts +44 -3
- package/dist/provision-roles.js +1 -1
- package/dist/runtime-posture.d.ts +12 -7
- package/dist/schema.d.ts +839 -101
- package/dist/schema.js +9 -1
- package/dist/session-background-commands.js +3 -3
- package/dist/session-tenancy.d.ts +12 -1
- package/dist/session-tenancy.js +3 -3
- package/dist/video-generation.js +3 -3
- package/drizzle/0348_named_signup_and_user_setup.sql +838 -0
- package/drizzle/0349_greenfield_session_tenancy_activation.sql +792 -0
- package/drizzle/0350_organization_shared_workspace_administration.sql +889 -0
- package/drizzle/0351_organization_user_setup_delivery.sql +978 -0
- package/drizzle/0352_session_variable_set_attachments.sql +1661 -0
- package/drizzle/0353_automatic_session_title_policy_fence.sql +476 -0
- package/drizzle/0354_automatic_session_title_quarantine_index.sql +9 -0
- package/drizzle/0355_automatic_session_title_quarantine.sql +92 -0
- package/drizzle/0356_set_based_insights_session_visibility.sql +237 -0
- package/drizzle/0357_rig_platform_base_only.sql +44 -0
- package/drizzle/0358_pr_review_managed_github_app.sql +108 -0
- package/drizzle/0359_insights_force_rls_read_capability.sql +936 -0
- package/drizzle/0360_organization_identity_confirmation_prompt.sql +103 -0
- package/drizzle/0361_remember_knowledge_memory_materialization.sql +249 -0
- package/package.json +6 -6
- package/src/database.ts +12 -8
- package/src/governed-learning-activation.ts +74 -2
- package/src/index.ts +879 -92
- package/src/insights-model-bundle.ts +681 -0
- package/src/insights-usage-bundle.ts +240 -0
- package/src/insights.ts +265 -152
- package/src/lossless-json.ts +2 -1
- package/src/managed-user-setup.ts +316 -0
- package/src/memory-domain.ts +3 -3
- package/src/migrate.ts +38 -14
- package/src/new-session-drafts.ts +22 -15
- package/src/organization-membership-lifecycle.ts +253 -1
- package/src/pr-review.ts +449 -6
- package/src/provision-roles.ts +92 -0
- package/src/runtime-posture.ts +247 -4
- package/src/schema.ts +210 -4
- package/src/session-tenancy.ts +120 -2
- package/dist/chunk-6HMM2R5T.js.map +0 -1
- package/dist/chunk-AZHW7R5V.js.map +0 -1
- package/dist/chunk-KRLPEMLH.js.map +0 -1
- package/dist/chunk-SIBYBA2D.js.map +0 -1
- package/dist/chunk-UZNXG44K.js.map +0 -1
- /package/dist/{chunk-2PRS4J5Q.js.map → chunk-HY3F5Q4E.js.map} +0 -0
- /package/dist/{chunk-NAB6FKFN.js.map → chunk-O6FTELKH.js.map} +0 -0
- /package/dist/{chunk-E6CLMKEE.js.map → chunk-V3TRUXFJ.js.map} +0 -0
- /package/dist/{chunk-2EH4WRHL.js.map → chunk-ZWRIPCTR.js.map} +0 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { sql } from "drizzle-orm";
|
|
2
|
+
|
|
3
|
+
import type { Database } from "./database";
|
|
4
|
+
import { rlsContextForWorkspace, withRlsContext } from "./database";
|
|
5
|
+
import { INSIGHTS_WARM_GROUP_UUID_RE, type WarmGroupAggregate } from "./insights";
|
|
6
|
+
|
|
7
|
+
export type WorkspaceInsightsUsageBundleInput = {
|
|
8
|
+
workspaceId: string;
|
|
9
|
+
since: Date;
|
|
10
|
+
until: Date;
|
|
11
|
+
priorSince: Date;
|
|
12
|
+
priorUntil: Date;
|
|
13
|
+
monthSince: Date;
|
|
14
|
+
granularity: "day" | "hour";
|
|
15
|
+
warmGroupLimit?: number;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type WorkspaceInsightsUsageBucket = {
|
|
19
|
+
costMicros: number | null;
|
|
20
|
+
warmSeconds: number;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type WorkspaceInsightsUsageBundle = {
|
|
24
|
+
workspaceCreditMicros: number;
|
|
25
|
+
priorWorkspaceCreditMicros: number;
|
|
26
|
+
warmSeconds: number;
|
|
27
|
+
priorWarmSeconds: number;
|
|
28
|
+
buckets: Map<string, WorkspaceInsightsUsageBucket>;
|
|
29
|
+
warmGroups: WarmGroupAggregate[];
|
|
30
|
+
billableTokensUsed: number;
|
|
31
|
+
agentRunsUsed: number;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
type RawUsageBundleRow = {
|
|
35
|
+
workspace_credit_micros: unknown;
|
|
36
|
+
prior_workspace_credit_micros: unknown;
|
|
37
|
+
warm_seconds: unknown;
|
|
38
|
+
prior_warm_seconds: unknown;
|
|
39
|
+
billable_tokens_used: unknown;
|
|
40
|
+
agent_runs_used: unknown;
|
|
41
|
+
buckets: unknown;
|
|
42
|
+
warm_groups: unknown;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
type JsonRecord = Record<string, unknown>;
|
|
46
|
+
|
|
47
|
+
function numberValue(value: unknown, label: string): number {
|
|
48
|
+
if (
|
|
49
|
+
(typeof value !== "number" && typeof value !== "string") ||
|
|
50
|
+
(typeof value === "string" && value.trim().length === 0)
|
|
51
|
+
) {
|
|
52
|
+
throw new Error(`Insights usage bundle ${label} is not numeric`);
|
|
53
|
+
}
|
|
54
|
+
const parsed = Number(value);
|
|
55
|
+
if (!Number.isFinite(parsed)) {
|
|
56
|
+
throw new Error(`Insights usage bundle ${label} is not numeric`);
|
|
57
|
+
}
|
|
58
|
+
return parsed;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function nullableNumberValue(value: unknown, label: string): number | null {
|
|
62
|
+
return value === null || value === undefined ? null : numberValue(value, label);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function records(value: unknown, label: string): JsonRecord[] {
|
|
66
|
+
if (!Array.isArray(value)) {
|
|
67
|
+
throw new Error(`Insights usage bundle ${label} is not an array`);
|
|
68
|
+
}
|
|
69
|
+
return value.map((item, index) => {
|
|
70
|
+
if (item === null || typeof item !== "object" || Array.isArray(item)) {
|
|
71
|
+
throw new Error(`Insights usage bundle ${label}[${index}] is not an object`);
|
|
72
|
+
}
|
|
73
|
+
return item as JsonRecord;
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function stringValue(row: JsonRecord, key: string): string {
|
|
78
|
+
const value = row[key];
|
|
79
|
+
if (typeof value !== "string") {
|
|
80
|
+
throw new Error(`Insights usage bundle ${key} is not a string`);
|
|
81
|
+
}
|
|
82
|
+
return value;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* One read for the three existing usage windows. The event-type arrays are
|
|
87
|
+
* deliberately closed so the authority function can keep selective predicates
|
|
88
|
+
* inside its scan while all rollup math remains outside the billing path.
|
|
89
|
+
*/
|
|
90
|
+
export async function readWorkspaceInsightsUsageBundle(
|
|
91
|
+
db: Database,
|
|
92
|
+
input: WorkspaceInsightsUsageBundleInput,
|
|
93
|
+
): Promise<WorkspaceInsightsUsageBundle> {
|
|
94
|
+
const context = await rlsContextForWorkspace(db, input.workspaceId);
|
|
95
|
+
const bucket =
|
|
96
|
+
input.granularity === "hour"
|
|
97
|
+
? sql`to_char(date_trunc('hour', usage_row.occurred_at at time zone 'UTC'), 'YYYY-MM-DD"T"HH24:00')`
|
|
98
|
+
: sql`to_char(date_trunc('day', usage_row.occurred_at at time zone 'UTC'), 'YYYY-MM-DD')`;
|
|
99
|
+
const warmGroupLimit = Math.max(1, Math.min(input.warmGroupLimit ?? 24, 100));
|
|
100
|
+
|
|
101
|
+
return await withRlsContext(db, context, async (scopedDb) => {
|
|
102
|
+
const [row] = await scopedDb.execute<RawUsageBundleRow>(sql`
|
|
103
|
+
with current_visible as materialized (
|
|
104
|
+
select usage_row.event_type, usage_row.quantity, usage_row.occurred_at,
|
|
105
|
+
usage_row.source_resource_id
|
|
106
|
+
from opengeni_private.visible_workspace_insights_usage_events(
|
|
107
|
+
${input.workspaceId},
|
|
108
|
+
${input.since.toISOString()}::timestamp with time zone,
|
|
109
|
+
${input.until.toISOString()}::timestamp with time zone,
|
|
110
|
+
array['model.cost', 'sandbox.warm_seconds']::text[]
|
|
111
|
+
) usage_row
|
|
112
|
+
), prior_visible as materialized (
|
|
113
|
+
select usage_row.event_type, usage_row.quantity
|
|
114
|
+
from opengeni_private.visible_workspace_insights_usage_events(
|
|
115
|
+
${input.workspaceId},
|
|
116
|
+
${input.priorSince.toISOString()}::timestamp with time zone,
|
|
117
|
+
${input.priorUntil.toISOString()}::timestamp with time zone,
|
|
118
|
+
array['model.cost', 'sandbox.warm_seconds']::text[]
|
|
119
|
+
) usage_row
|
|
120
|
+
), month_visible as materialized (
|
|
121
|
+
select usage_row.event_type, usage_row.quantity, usage_row.occurred_at
|
|
122
|
+
from opengeni_private.visible_workspace_insights_usage_events(
|
|
123
|
+
${input.workspaceId},
|
|
124
|
+
${input.monthSince.toISOString()}::timestamp with time zone,
|
|
125
|
+
'infinity'::timestamp with time zone,
|
|
126
|
+
array['model.tokens', 'agent_run.created']::text[]
|
|
127
|
+
) usage_row
|
|
128
|
+
), current_totals as (
|
|
129
|
+
select
|
|
130
|
+
coalesce(sum(usage_row.quantity) filter (
|
|
131
|
+
where usage_row.event_type = 'model.cost'
|
|
132
|
+
), 0) as workspace_credit_micros,
|
|
133
|
+
coalesce(sum(usage_row.quantity) filter (
|
|
134
|
+
where usage_row.event_type = 'sandbox.warm_seconds'
|
|
135
|
+
), 0) as warm_seconds
|
|
136
|
+
from current_visible usage_row
|
|
137
|
+
), prior_totals as (
|
|
138
|
+
select
|
|
139
|
+
coalesce(sum(usage_row.quantity) filter (
|
|
140
|
+
where usage_row.event_type = 'model.cost'
|
|
141
|
+
), 0) as prior_workspace_credit_micros,
|
|
142
|
+
coalesce(sum(usage_row.quantity) filter (
|
|
143
|
+
where usage_row.event_type = 'sandbox.warm_seconds'
|
|
144
|
+
), 0) as prior_warm_seconds
|
|
145
|
+
from prior_visible usage_row
|
|
146
|
+
), month_totals as (
|
|
147
|
+
select
|
|
148
|
+
coalesce(sum(usage_row.quantity) filter (
|
|
149
|
+
where usage_row.event_type = 'model.tokens'
|
|
150
|
+
and usage_row.occurred_at > ${input.monthSince.toISOString()}::timestamp with time zone
|
|
151
|
+
), 0) as billable_tokens_used,
|
|
152
|
+
coalesce(sum(usage_row.quantity) filter (
|
|
153
|
+
where usage_row.event_type = 'agent_run.created'
|
|
154
|
+
and usage_row.occurred_at > ${input.monthSince.toISOString()}::timestamp with time zone
|
|
155
|
+
), 0) as agent_runs_used
|
|
156
|
+
from month_visible usage_row
|
|
157
|
+
), bucket_rows as (
|
|
158
|
+
select
|
|
159
|
+
${bucket} as bucket,
|
|
160
|
+
sum(usage_row.quantity) filter (
|
|
161
|
+
where usage_row.event_type = 'model.cost'
|
|
162
|
+
) as cost_micros,
|
|
163
|
+
coalesce(sum(usage_row.quantity) filter (
|
|
164
|
+
where usage_row.event_type = 'sandbox.warm_seconds'
|
|
165
|
+
), 0) as warm_seconds
|
|
166
|
+
from current_visible usage_row
|
|
167
|
+
group by ${bucket}
|
|
168
|
+
), warm_group_rows as (
|
|
169
|
+
select
|
|
170
|
+
split_part(usage_row.source_resource_id, ':', 1) as group_id,
|
|
171
|
+
coalesce(sum(usage_row.quantity), 0) as warm_seconds
|
|
172
|
+
from current_visible usage_row
|
|
173
|
+
where usage_row.event_type = 'sandbox.warm_seconds'
|
|
174
|
+
and usage_row.source_resource_id is not null
|
|
175
|
+
group by split_part(usage_row.source_resource_id, ':', 1)
|
|
176
|
+
order by coalesce(sum(usage_row.quantity), 0) desc
|
|
177
|
+
limit ${Math.max(warmGroupLimit * 4, warmGroupLimit)}
|
|
178
|
+
)
|
|
179
|
+
select
|
|
180
|
+
current_totals.workspace_credit_micros,
|
|
181
|
+
prior_totals.prior_workspace_credit_micros,
|
|
182
|
+
current_totals.warm_seconds,
|
|
183
|
+
prior_totals.prior_warm_seconds,
|
|
184
|
+
month_totals.billable_tokens_used,
|
|
185
|
+
month_totals.agent_runs_used,
|
|
186
|
+
coalesce((
|
|
187
|
+
select jsonb_agg(jsonb_build_object(
|
|
188
|
+
'bucket', bucket,
|
|
189
|
+
'costMicros', cost_micros,
|
|
190
|
+
'warmSeconds', warm_seconds
|
|
191
|
+
) order by bucket)
|
|
192
|
+
from bucket_rows
|
|
193
|
+
), '[]'::jsonb) as buckets,
|
|
194
|
+
coalesce((
|
|
195
|
+
select jsonb_agg(jsonb_build_object(
|
|
196
|
+
'groupId', group_id,
|
|
197
|
+
'warmSeconds', warm_seconds
|
|
198
|
+
) order by warm_seconds desc, group_id)
|
|
199
|
+
from warm_group_rows
|
|
200
|
+
), '[]'::jsonb) as warm_groups
|
|
201
|
+
from current_totals
|
|
202
|
+
cross join prior_totals
|
|
203
|
+
cross join month_totals
|
|
204
|
+
`);
|
|
205
|
+
if (!row) {
|
|
206
|
+
throw new Error("Insights usage bundle query returned no row");
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const buckets = new Map(
|
|
210
|
+
records(row.buckets, "buckets").map((bucketRow) => [
|
|
211
|
+
stringValue(bucketRow, "bucket"),
|
|
212
|
+
{
|
|
213
|
+
costMicros: nullableNumberValue(bucketRow.costMicros, "costMicros"),
|
|
214
|
+
warmSeconds: numberValue(bucketRow.warmSeconds, "warmSeconds"),
|
|
215
|
+
},
|
|
216
|
+
]),
|
|
217
|
+
);
|
|
218
|
+
const warmGroups = records(row.warm_groups, "warmGroups")
|
|
219
|
+
.filter((groupRow) => INSIGHTS_WARM_GROUP_UUID_RE.test(stringValue(groupRow, "groupId")))
|
|
220
|
+
.slice(0, warmGroupLimit)
|
|
221
|
+
.map((groupRow) => ({
|
|
222
|
+
groupId: stringValue(groupRow, "groupId"),
|
|
223
|
+
warmSeconds: numberValue(groupRow.warmSeconds, "warmSeconds"),
|
|
224
|
+
}));
|
|
225
|
+
|
|
226
|
+
return {
|
|
227
|
+
workspaceCreditMicros: numberValue(row.workspace_credit_micros, "workspaceCreditMicros"),
|
|
228
|
+
priorWorkspaceCreditMicros: numberValue(
|
|
229
|
+
row.prior_workspace_credit_micros,
|
|
230
|
+
"priorWorkspaceCreditMicros",
|
|
231
|
+
),
|
|
232
|
+
warmSeconds: numberValue(row.warm_seconds, "warmSeconds"),
|
|
233
|
+
priorWarmSeconds: numberValue(row.prior_warm_seconds, "priorWarmSeconds"),
|
|
234
|
+
buckets,
|
|
235
|
+
warmGroups,
|
|
236
|
+
billableTokensUsed: numberValue(row.billable_tokens_used, "billableTokensUsed"),
|
|
237
|
+
agentRunsUsed: numberValue(row.agent_runs_used, "agentRunsUsed"),
|
|
238
|
+
};
|
|
239
|
+
});
|
|
240
|
+
}
|