@opengeni/core 0.21.10 → 0.24.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/access/index.d.ts +1 -1
- package/dist/application/new-session-drafts.d.ts +1 -1
- package/dist/application/session-commands.d.ts +2 -2
- package/dist/billing/limits.d.ts +1 -1
- package/dist/chunk-6WKPWE5S.js +2380 -0
- package/dist/chunk-6WKPWE5S.js.map +1 -0
- package/dist/chunk-JJU6I5XD.js +2713 -0
- package/dist/chunk-JJU6I5XD.js.map +1 -0
- package/dist/chunk-NYPMQ7NO.js +2270 -0
- package/dist/chunk-NYPMQ7NO.js.map +1 -0
- package/dist/dependencies.d.ts +26 -6
- package/dist/domain/capabilities.d.ts +28 -3
- package/dist/domain/company-profile-durable-learning-adapter.d.ts +39 -0
- package/dist/domain/durable-learning-slack-publication.d.ts +72 -0
- package/dist/domain/editable-artifacts/agent-application.d.ts +192 -0
- package/dist/domain/editable-artifacts/durable-export-postgres.d.ts +4 -0
- package/dist/domain/editable-artifacts/durable-export.d.ts +212 -0
- package/dist/domain/editable-artifacts/errors.d.ts +47 -0
- package/dist/domain/editable-artifacts/hash.d.ts +11 -0
- package/dist/domain/editable-artifacts/in-memory.d.ts +99 -0
- package/dist/domain/editable-artifacts/index.d.ts +14 -0
- package/dist/domain/editable-artifacts/ports.d.ts +341 -0
- package/dist/domain/editable-artifacts/postgres-adapters.d.ts +13 -0
- package/dist/domain/editable-artifacts/service.d.ts +105 -0
- package/dist/domain/editable-artifacts/snapshot-compaction.d.ts +44 -0
- package/dist/domain/editable-artifacts/snapshot-verifier-genesis.d.ts +50 -0
- package/dist/domain/editable-artifacts/snapshot-verifier-materialization.d.ts +21 -0
- package/dist/domain/editable-artifacts/snapshot-verifier.d.ts +118 -0
- package/dist/domain/editable-artifacts/types.d.ts +410 -0
- package/dist/domain/memory-slack-delivery.d.ts +19 -0
- package/dist/domain/packs.d.ts +29 -1
- package/dist/domain/personal-connection-delegations.d.ts +9 -1
- package/dist/domain/scheduled-tasks.d.ts +2 -2
- package/dist/domain/session-tool-policy.d.ts +2 -2
- package/dist/domain/sessions.d.ts +14 -6
- package/dist/domain/skill-imports.d.ts +32 -0
- package/dist/domain/slack-publication-secret-safety.d.ts +8 -0
- package/dist/domain/timeline-annotations.d.ts +5 -0
- package/dist/domain/video-generation-capabilities.d.ts +9 -0
- package/dist/domain/video-generation.d.ts +47 -0
- package/dist/editable-artifact-live/application.d.ts +69 -0
- package/dist/editable-artifact-live/errors.d.ts +1 -0
- package/dist/editable-artifact-live/index.d.ts +8 -0
- package/dist/editable-artifact-live/outbox-dispatcher.d.ts +162 -0
- package/dist/editable-artifact-live/ports.d.ts +100 -0
- package/dist/editable-artifact-live/server.d.ts +71 -0
- package/dist/editable-artifact-live/ticket.d.ts +40 -0
- package/dist/editable-artifact-live/types.d.ts +213 -0
- package/dist/editable-artifact-live/wire.d.ts +34 -0
- package/dist/editable-artifact-live.d.ts +2 -0
- package/dist/editable-artifact-live.js +58 -0
- package/dist/editable-artifact-live.js.map +1 -0
- package/dist/editable-artifacts.d.ts +2 -0
- package/dist/editable-artifacts.js +179 -0
- package/dist/editable-artifacts.js.map +1 -0
- package/dist/index.d.ts +35 -26
- package/dist/index.js +2792 -609
- package/dist/index.js.map +1 -1
- package/dist/managed-session.d.ts +1 -1
- package/dist/rigs/index.d.ts +1 -1
- package/dist/rigs/provider-images.d.ts +31 -0
- package/dist/sandbox/routing.d.ts +1 -0
- package/dist/session-authorization.d.ts +1 -1
- package/dist/workflow-wake-contract.d.ts +7 -0
- package/package.json +18 -10
- package/src/application/new-session-drafts.ts +2 -0
- package/src/application/session-commands.ts +188 -107
- package/src/dependencies.ts +30 -2
- package/src/domain/capabilities.ts +604 -220
- package/src/domain/company-profile-durable-learning-adapter.ts +221 -0
- package/src/domain/durable-learning-slack-publication.ts +202 -0
- package/src/domain/editable-artifacts/agent-application.ts +687 -0
- package/src/domain/editable-artifacts/durable-export-postgres.ts +139 -0
- package/src/domain/editable-artifacts/durable-export.ts +734 -0
- package/src/domain/editable-artifacts/errors.ts +115 -0
- package/src/domain/editable-artifacts/hash.ts +131 -0
- package/src/domain/editable-artifacts/in-memory.ts +1662 -0
- package/src/domain/editable-artifacts/index.ts +14 -0
- package/src/domain/editable-artifacts/ports.ts +462 -0
- package/src/domain/editable-artifacts/postgres-adapters.ts +49 -0
- package/src/domain/editable-artifacts/service.ts +2402 -0
- package/src/domain/editable-artifacts/snapshot-compaction.ts +246 -0
- package/src/domain/editable-artifacts/snapshot-verifier-genesis.ts +235 -0
- package/src/domain/editable-artifacts/snapshot-verifier-materialization.ts +74 -0
- package/src/domain/editable-artifacts/snapshot-verifier.ts +687 -0
- package/src/domain/editable-artifacts/types.ts +835 -0
- package/src/domain/insights.ts +136 -33
- package/src/domain/memory-slack-delivery.ts +204 -0
- package/src/domain/memory-slack-publication.ts +5 -2
- package/src/domain/packs.ts +266 -5
- package/src/domain/personal-connection-delegations.ts +97 -6
- package/src/domain/scheduled-tasks.ts +155 -29
- package/src/domain/session-tool-policy.ts +8 -2
- package/src/domain/sessions.ts +274 -131
- package/src/domain/skill-imports.ts +350 -0
- package/src/domain/slack-publication-secret-safety.ts +42 -0
- package/src/domain/timeline-annotations.ts +204 -0
- package/src/domain/video-generation-capabilities.ts +69 -0
- package/src/domain/video-generation.ts +249 -0
- package/src/editable-artifact-live/application.ts +182 -0
- package/src/editable-artifact-live/errors.ts +4 -0
- package/src/editable-artifact-live/index.ts +8 -0
- package/src/editable-artifact-live/outbox-dispatcher.ts +916 -0
- package/src/editable-artifact-live/ports.ts +139 -0
- package/src/editable-artifact-live/server.ts +1707 -0
- package/src/editable-artifact-live/ticket.ts +217 -0
- package/src/editable-artifact-live/types.ts +286 -0
- package/src/editable-artifact-live/wire.ts +95 -0
- package/src/editable-artifact-live.ts +2 -0
- package/src/editable-artifacts.ts +2 -0
- package/src/index.ts +13 -0
- package/src/rigs/index.ts +26 -19
- package/src/rigs/provider-images.ts +110 -0
- package/src/sandbox/routing.ts +6 -3
- package/src/session-authorization.ts +3 -0
- package/src/workflow-wake-contract.ts +8 -0
package/src/domain/insights.ts
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
listFloorSessions,
|
|
19
19
|
listLiveWarmLeases,
|
|
20
20
|
listModelCallFacets,
|
|
21
|
+
listRecentModelCalls,
|
|
21
22
|
listScheduledTasks,
|
|
22
23
|
requireWorkspace,
|
|
23
24
|
sumUsageQuantity,
|
|
@@ -37,7 +38,7 @@ export type GetWorkspaceInsightsInput = {
|
|
|
37
38
|
};
|
|
38
39
|
|
|
39
40
|
function microsToUsd(micros: number): number {
|
|
40
|
-
return
|
|
41
|
+
return micros / 1_000_000;
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
function cacheHitPct(cached: number, input: number): number {
|
|
@@ -163,6 +164,12 @@ function billingPathOf(value: string): "opengeni_credits" | "external" {
|
|
|
163
164
|
return value === "external" ? "external" : "opengeni_credits";
|
|
164
165
|
}
|
|
165
166
|
|
|
167
|
+
function pricingSourceOf(
|
|
168
|
+
value: string | null,
|
|
169
|
+
): "configured_list_price" | "gateway_reported" | null {
|
|
170
|
+
return value === "configured_list_price" || value === "gateway_reported" ? value : null;
|
|
171
|
+
}
|
|
172
|
+
|
|
166
173
|
export async function getWorkspaceInsights(
|
|
167
174
|
db: Database,
|
|
168
175
|
settings: Settings,
|
|
@@ -197,6 +204,7 @@ export async function getWorkspaceInsights(
|
|
|
197
204
|
billableTokensUsed,
|
|
198
205
|
agentRunsUsed,
|
|
199
206
|
facets,
|
|
207
|
+
recentCalls,
|
|
200
208
|
] = await Promise.all([
|
|
201
209
|
sumUsageQuantityInRange(db, {
|
|
202
210
|
workspaceId: input.workspaceId,
|
|
@@ -276,7 +284,7 @@ export async function getWorkspaceInsights(
|
|
|
276
284
|
aggregateSessionDepth(db, input.workspaceId),
|
|
277
285
|
listFloorSessions(db, input.workspaceId, 24),
|
|
278
286
|
settings.sandboxSelfhostedEnabled
|
|
279
|
-
? countOnlineMachines(db, input.workspaceId, MACHINE_HEARTBEAT_FRESH_MS)
|
|
287
|
+
? countOnlineMachines(db, input.workspaceId, MACHINE_HEARTBEAT_FRESH_MS, now)
|
|
280
288
|
: Promise.resolve(0),
|
|
281
289
|
sumUsageQuantity(db, {
|
|
282
290
|
workspaceId: input.workspaceId,
|
|
@@ -293,23 +301,37 @@ export async function getWorkspaceInsights(
|
|
|
293
301
|
since: window.since,
|
|
294
302
|
until: window.until,
|
|
295
303
|
}),
|
|
304
|
+
listRecentModelCalls(db, {
|
|
305
|
+
workspaceId: input.workspaceId,
|
|
306
|
+
since: window.since,
|
|
307
|
+
until: window.until,
|
|
308
|
+
...filter,
|
|
309
|
+
limit: 50,
|
|
310
|
+
}),
|
|
296
311
|
]);
|
|
297
312
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
+
const [priorRootDrivers, attached, fireCounts] = await Promise.all([
|
|
314
|
+
// Exact prior costs for the current top drivers — never a separate top-N page that
|
|
315
|
+
// drops roots and invents +$full as "new" spend.
|
|
316
|
+
aggregateRootSessionDrivers(db, {
|
|
317
|
+
workspaceId: input.workspaceId,
|
|
318
|
+
since: window.priorSince,
|
|
319
|
+
until: window.priorUntil,
|
|
320
|
+
...filter,
|
|
321
|
+
rootSessionIds: rootDrivers.map((row) => row.rootSessionId),
|
|
322
|
+
}),
|
|
323
|
+
countSessionsAttachedToGroups(
|
|
324
|
+
db,
|
|
325
|
+
input.workspaceId,
|
|
326
|
+
warmGroups.map((group) => group.groupId),
|
|
327
|
+
),
|
|
328
|
+
countScheduledTaskFires(db, {
|
|
329
|
+
workspaceId: input.workspaceId,
|
|
330
|
+
since: window.since,
|
|
331
|
+
until: window.until,
|
|
332
|
+
taskIds: tasks.map((task) => task.id),
|
|
333
|
+
}),
|
|
334
|
+
]);
|
|
313
335
|
const backendByGroup = new Map(liveWarm.map((lease) => [lease.groupId, lease.backend]));
|
|
314
336
|
const warmSecondsByGroup = new Map(warmGroups.map((group) => [group.groupId, group.warmSeconds]));
|
|
315
337
|
|
|
@@ -323,24 +345,58 @@ export async function getWorkspaceInsights(
|
|
|
323
345
|
inputTokens: row.inputTokens,
|
|
324
346
|
outputTokens: row.outputTokens,
|
|
325
347
|
cachedTokens: row.cachedTokens,
|
|
348
|
+
cacheInputTokens: row.cacheInputTokens,
|
|
326
349
|
cacheWriteTokens: row.cacheWriteTokens,
|
|
327
350
|
reasoningTokens: row.reasoningTokens,
|
|
351
|
+
totalTokens: row.totalTokens,
|
|
352
|
+
tokenKnownCalls: row.tokenKnownCalls,
|
|
353
|
+
cacheKnownCalls: row.cacheKnownCalls,
|
|
328
354
|
creditUsd: microsToUsd(row.pricedCostMicros),
|
|
355
|
+
estimatedProviderUsd: microsToUsd(row.estimatedProviderCostMicros),
|
|
356
|
+
estimatedProviderCostKnownCalls: row.estimatedProviderCostKnownCalls,
|
|
329
357
|
}))
|
|
330
|
-
.sort((a, b) => b.
|
|
358
|
+
.sort((a, b) => b.totalTokens - a.totalTokens);
|
|
331
359
|
|
|
332
360
|
const creditMicros = modelRows.reduce((sum, row) => sum + row.pricedCostMicros, 0);
|
|
333
361
|
const priorCreditMicros = priorModelRows.reduce((sum, row) => sum + row.pricedCostMicros, 0);
|
|
362
|
+
const estimatedProviderCostMicros = modelRows.reduce(
|
|
363
|
+
(sum, row) => sum + row.estimatedProviderCostMicros,
|
|
364
|
+
0,
|
|
365
|
+
);
|
|
366
|
+
const priorEstimatedProviderCostMicros = priorModelRows.reduce(
|
|
367
|
+
(sum, row) => sum + row.estimatedProviderCostMicros,
|
|
368
|
+
0,
|
|
369
|
+
);
|
|
370
|
+
const estimatedProviderCostKnownCalls = modelRows.reduce(
|
|
371
|
+
(sum, row) => sum + row.estimatedProviderCostKnownCalls,
|
|
372
|
+
0,
|
|
373
|
+
);
|
|
374
|
+
const priorEstimatedProviderCostKnownCalls = priorModelRows.reduce(
|
|
375
|
+
(sum, row) => sum + row.estimatedProviderCostKnownCalls,
|
|
376
|
+
0,
|
|
377
|
+
);
|
|
378
|
+
const modelCalls = modelRows.reduce((sum, row) => sum + row.calls, 0);
|
|
334
379
|
const priorInputTokens = priorModelRows.reduce((sum, row) => sum + row.inputTokens, 0);
|
|
380
|
+
const priorTotalTokens = priorModelRows.reduce((sum, row) => sum + row.totalTokens, 0);
|
|
335
381
|
const priorCachedTokens = priorModelRows.reduce((sum, row) => sum + row.cachedTokens, 0);
|
|
382
|
+
const priorCacheInputTokens = priorModelRows.reduce((sum, row) => sum + row.cacheInputTokens, 0);
|
|
336
383
|
const priorCalls = priorModelRows.reduce((sum, row) => sum + row.calls, 0);
|
|
337
384
|
|
|
338
385
|
const days = enumerateUtcDays(window.since, window.until);
|
|
339
386
|
const series = days.map((day) => {
|
|
340
387
|
const facts = factDays.get(day) ?? {
|
|
341
388
|
costMicros: 0,
|
|
389
|
+
estimatedProviderCostMicros: 0,
|
|
390
|
+
estimatedProviderCostKnownCalls: 0,
|
|
342
391
|
inputTokens: 0,
|
|
392
|
+
outputTokens: 0,
|
|
343
393
|
cachedTokens: 0,
|
|
394
|
+
cacheInputTokens: 0,
|
|
395
|
+
cacheWriteTokens: 0,
|
|
396
|
+
reasoningTokens: 0,
|
|
397
|
+
totalTokens: 0,
|
|
398
|
+
tokenKnownCalls: 0,
|
|
399
|
+
cacheKnownCalls: 0,
|
|
344
400
|
calls: 0,
|
|
345
401
|
};
|
|
346
402
|
const modelCostMicros = modelFilterActive
|
|
@@ -349,10 +405,19 @@ export async function getWorkspaceInsights(
|
|
|
349
405
|
return {
|
|
350
406
|
label: day.slice(5),
|
|
351
407
|
modelCostUsd: microsToUsd(modelCostMicros),
|
|
408
|
+
estimatedProviderUsd: microsToUsd(facts.estimatedProviderCostMicros),
|
|
409
|
+
estimatedProviderCostKnownCalls: facts.estimatedProviderCostKnownCalls,
|
|
352
410
|
warmSeconds: warmDays.get(day) ?? 0,
|
|
353
411
|
inputTokens: facts.inputTokens,
|
|
412
|
+
outputTokens: facts.outputTokens,
|
|
354
413
|
cachedTokens: facts.cachedTokens,
|
|
355
|
-
|
|
414
|
+
cacheInputTokens: facts.cacheInputTokens,
|
|
415
|
+
cacheWriteTokens: facts.cacheWriteTokens,
|
|
416
|
+
reasoningTokens: facts.reasoningTokens,
|
|
417
|
+
totalTokens: facts.totalTokens,
|
|
418
|
+
tokenKnownCalls: facts.tokenKnownCalls,
|
|
419
|
+
cacheKnownCalls: facts.cacheKnownCalls,
|
|
420
|
+
cacheHitPct: cacheHitPct(facts.cachedTokens, facts.cacheInputTokens),
|
|
356
421
|
calls: facts.calls,
|
|
357
422
|
};
|
|
358
423
|
});
|
|
@@ -360,7 +425,10 @@ export async function getWorkspaceInsights(
|
|
|
360
425
|
const priorDriverByRoot = new Map(
|
|
361
426
|
priorRootDrivers.map((row) => [row.rootSessionId, row.pricedCostMicros]),
|
|
362
427
|
);
|
|
363
|
-
const
|
|
428
|
+
const totalTokensForPct = Math.max(
|
|
429
|
+
rootDrivers.reduce((sum, row) => sum + row.totalTokens, 0),
|
|
430
|
+
1,
|
|
431
|
+
);
|
|
364
432
|
const drivers = rootDrivers.map((row) => {
|
|
365
433
|
const creditUsd = microsToUsd(row.pricedCostMicros);
|
|
366
434
|
const priorUsd = microsToUsd(priorDriverByRoot.get(row.rootSessionId) ?? 0);
|
|
@@ -369,19 +437,19 @@ export async function getWorkspaceInsights(
|
|
|
369
437
|
groupBy: "root_session" as const,
|
|
370
438
|
label: row.title?.trim() || row.rootSessionId.slice(0, 8),
|
|
371
439
|
creditUsd,
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
440
|
+
estimatedProviderUsd: microsToUsd(row.estimatedProviderCostMicros),
|
|
441
|
+
estimatedProviderCostKnownCalls: row.estimatedProviderCostKnownCalls,
|
|
442
|
+
tokens: row.totalTokens,
|
|
443
|
+
cacheHitPct: cacheHitPct(row.cachedTokens, row.cacheInputTokens),
|
|
444
|
+
pctOfCreditUsd:
|
|
445
|
+
creditMicros > 0
|
|
446
|
+
? Math.min(100, Math.round((row.pricedCostMicros / creditMicros) * 100))
|
|
447
|
+
: 0,
|
|
448
|
+
pctOfTokens: Math.min(100, Math.round((row.totalTokens / totalTokensForPct) * 100)),
|
|
449
|
+
deltaUsdVsPrior: creditUsd - priorUsd,
|
|
376
450
|
};
|
|
377
451
|
});
|
|
378
452
|
|
|
379
|
-
const fireCounts = await countScheduledTaskFires(db, {
|
|
380
|
-
workspaceId: input.workspaceId,
|
|
381
|
-
since: window.since,
|
|
382
|
-
until: window.until,
|
|
383
|
-
taskIds: tasks.map((task) => task.id),
|
|
384
|
-
});
|
|
385
453
|
const scheduleFactById = new Map(scheduleFacts.map((row) => [row.scheduledTaskId, row] as const));
|
|
386
454
|
const schedules = tasks.map((task) => {
|
|
387
455
|
const fact = scheduleFactById.get(task.id);
|
|
@@ -390,8 +458,10 @@ export async function getWorkspaceInsights(
|
|
|
390
458
|
name: task.name,
|
|
391
459
|
fires: fireCounts.get(task.id) ?? 0,
|
|
392
460
|
creditUsd: fact ? microsToUsd(fact.pricedCostMicros) : null,
|
|
393
|
-
|
|
394
|
-
|
|
461
|
+
estimatedProviderUsd: fact ? microsToUsd(fact.estimatedProviderCostMicros) : null,
|
|
462
|
+
estimatedProviderCostKnownCalls: fact ? fact.estimatedProviderCostKnownCalls : null,
|
|
463
|
+
tokens: fact ? fact.totalTokens : null,
|
|
464
|
+
cacheHitPct: fact ? cacheHitPct(fact.cachedTokens, fact.cacheInputTokens) : null,
|
|
395
465
|
billing: fact ? billingPathOf(fact.billingPath) : null,
|
|
396
466
|
};
|
|
397
467
|
});
|
|
@@ -422,6 +492,9 @@ export async function getWorkspaceInsights(
|
|
|
422
492
|
priorLabel: window.priorLabel,
|
|
423
493
|
seriesLabel: window.seriesLabel,
|
|
424
494
|
cacheSeriesLabel: window.cacheSeriesLabel,
|
|
495
|
+
windowStart: window.since.toISOString(),
|
|
496
|
+
windowEnd: window.until.toISOString(),
|
|
497
|
+
generatedAt: now.toISOString(),
|
|
425
498
|
timezone: "UTC",
|
|
426
499
|
models,
|
|
427
500
|
facets,
|
|
@@ -432,6 +505,30 @@ export async function getWorkspaceInsights(
|
|
|
432
505
|
})),
|
|
433
506
|
drivers,
|
|
434
507
|
schedules,
|
|
508
|
+
recentCalls: recentCalls.map((row) => ({
|
|
509
|
+
id: row.id,
|
|
510
|
+
occurredAt: row.occurredAt.toISOString(),
|
|
511
|
+
recordedAt: row.recordedAt.toISOString(),
|
|
512
|
+
sessionId: row.sessionId,
|
|
513
|
+
sessionTitle: row.sessionTitle?.trim() || "Untitled session",
|
|
514
|
+
turnId: row.turnId,
|
|
515
|
+
provider: row.provider,
|
|
516
|
+
providerApi: row.providerApi,
|
|
517
|
+
model: row.model,
|
|
518
|
+
billing: billingPathOf(row.billingPath),
|
|
519
|
+
inputTokens: row.inputTokens,
|
|
520
|
+
outputTokens: row.outputTokens,
|
|
521
|
+
cachedTokens: row.cachedTokens,
|
|
522
|
+
cacheWriteTokens: row.cacheWriteTokens,
|
|
523
|
+
reasoningTokens: row.reasoningTokens,
|
|
524
|
+
totalTokens: row.totalTokens,
|
|
525
|
+
creditUsd: microsToUsd(row.pricedCostMicros),
|
|
526
|
+
estimatedProviderUsd:
|
|
527
|
+
row.estimatedProviderCostMicros == null
|
|
528
|
+
? null
|
|
529
|
+
: microsToUsd(row.estimatedProviderCostMicros),
|
|
530
|
+
pricingSource: pricingSourceOf(row.pricingSource),
|
|
531
|
+
})),
|
|
435
532
|
warmSeconds,
|
|
436
533
|
priorWarmSeconds,
|
|
437
534
|
warmGroups: warmGroups.map((group) => ({
|
|
@@ -458,8 +555,14 @@ export async function getWorkspaceInsights(
|
|
|
458
555
|
priorWorkspaceCreditUsd: microsToUsd(priorWorkspaceCreditMicros),
|
|
459
556
|
creditUsd: microsToUsd(creditMicros),
|
|
460
557
|
priorCreditUsd: microsToUsd(priorCreditMicros),
|
|
558
|
+
estimatedProviderUsd: microsToUsd(estimatedProviderCostMicros),
|
|
559
|
+
priorEstimatedProviderUsd: microsToUsd(priorEstimatedProviderCostMicros),
|
|
560
|
+
estimatedProviderCostKnownCalls,
|
|
561
|
+
priorEstimatedProviderCostKnownCalls,
|
|
562
|
+
modelCalls,
|
|
461
563
|
priorInputTokens,
|
|
462
|
-
|
|
564
|
+
priorTotalTokens,
|
|
565
|
+
priorCacheHitPct: cacheHitPct(priorCachedTokens, priorCacheInputTokens),
|
|
463
566
|
priorCalls,
|
|
464
567
|
goalsActive: depth.goalsActive,
|
|
465
568
|
goalsCompleted: depth.goalsCompleted,
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import type { MemorySlackPublicationDistribution } from "@opengeni/contracts";
|
|
2
|
+
import {
|
|
3
|
+
correctWorkspaceMemory,
|
|
4
|
+
enqueueMemorySlackPublication,
|
|
5
|
+
getCurrentMemorySlackPublicationConfiguration,
|
|
6
|
+
getWorkspaceMemorySlackPublicationSnapshot,
|
|
7
|
+
saveWorkspaceMemory,
|
|
8
|
+
withWorkspaceRls,
|
|
9
|
+
type CorrectWorkspaceMemoryInput,
|
|
10
|
+
type CorrectWorkspaceMemoryResult,
|
|
11
|
+
type Database,
|
|
12
|
+
type EnqueueMemorySlackPublicationResult,
|
|
13
|
+
type MemoryEmbedder,
|
|
14
|
+
type MemorySlackPublicationActor,
|
|
15
|
+
type SaveWorkspaceMemoryInput,
|
|
16
|
+
type SaveWorkspaceMemoryResult,
|
|
17
|
+
type WorkspaceMemorySlackPublicationSnapshot,
|
|
18
|
+
} from "@opengeni/db";
|
|
19
|
+
import {
|
|
20
|
+
evaluateMemorySlackPublication,
|
|
21
|
+
type MemorySlackOrigin,
|
|
22
|
+
type MemorySlackPublicationDecision,
|
|
23
|
+
} from "./memory-slack-publication";
|
|
24
|
+
|
|
25
|
+
export type MemorySlackPublicationCommitRequest = {
|
|
26
|
+
distribution: MemorySlackPublicationDistribution;
|
|
27
|
+
actor: MemorySlackPublicationActor;
|
|
28
|
+
ownerLabel?: string | null;
|
|
29
|
+
origin?: MemorySlackOrigin;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type MemorySlackPublicationCommitResult = {
|
|
33
|
+
decision: MemorySlackPublicationDecision | null;
|
|
34
|
+
enqueue: EnqueueMemorySlackPublicationResult | null;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export async function saveWorkspaceMemoryWithSlackPublication(
|
|
38
|
+
db: Database,
|
|
39
|
+
input: SaveWorkspaceMemoryInput,
|
|
40
|
+
publication: MemorySlackPublicationCommitRequest | null,
|
|
41
|
+
embedder?: MemoryEmbedder,
|
|
42
|
+
): Promise<SaveWorkspaceMemoryResult & { slackPublication: MemorySlackPublicationCommitResult }> {
|
|
43
|
+
return await withWorkspaceRls(db, input.workspaceId, async (scopedDb) => {
|
|
44
|
+
const result = await saveWorkspaceMemory(scopedDb, input, embedder);
|
|
45
|
+
const slackPublication = publication
|
|
46
|
+
? await publishSavedMemoryMutation(scopedDb, input, result, publication)
|
|
47
|
+
: { decision: null, enqueue: null };
|
|
48
|
+
return { ...result, slackPublication };
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export async function correctWorkspaceMemoryWithSlackPublication(
|
|
53
|
+
db: Database,
|
|
54
|
+
input: CorrectWorkspaceMemoryInput,
|
|
55
|
+
publication: MemorySlackPublicationCommitRequest | null,
|
|
56
|
+
embedder?: MemoryEmbedder,
|
|
57
|
+
): Promise<
|
|
58
|
+
CorrectWorkspaceMemoryResult & { slackPublication: MemorySlackPublicationCommitResult }
|
|
59
|
+
> {
|
|
60
|
+
return await withWorkspaceRls(db, input.workspaceId, async (scopedDb) => {
|
|
61
|
+
const result = await correctWorkspaceMemory(scopedDb, input, embedder);
|
|
62
|
+
if (!publication || result.action !== "superseded" || !result.replacement) {
|
|
63
|
+
return { ...result, slackPublication: { decision: null, enqueue: null } };
|
|
64
|
+
}
|
|
65
|
+
const replacement = await requiredSnapshot(scopedDb, input.workspaceId, result.replacement.id);
|
|
66
|
+
const slackPublication = await evaluateAndEnqueue(scopedDb, {
|
|
67
|
+
accountId: input.accountId,
|
|
68
|
+
workspaceId: input.workspaceId,
|
|
69
|
+
snapshot: replacement,
|
|
70
|
+
changeKind: "corrected",
|
|
71
|
+
relatedMemoryId: result.memory.id,
|
|
72
|
+
occurredAt: result.replacement.updatedAt,
|
|
73
|
+
publication,
|
|
74
|
+
});
|
|
75
|
+
return { ...result, slackPublication };
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async function publishSavedMemoryMutation(
|
|
80
|
+
db: Database,
|
|
81
|
+
input: SaveWorkspaceMemoryInput,
|
|
82
|
+
result: SaveWorkspaceMemoryResult,
|
|
83
|
+
publication: MemorySlackPublicationCommitRequest,
|
|
84
|
+
): Promise<MemorySlackPublicationCommitResult> {
|
|
85
|
+
if (result.updated || (result.deduped && !result.superseded)) {
|
|
86
|
+
return { decision: null, enqueue: null };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (result.superseded) {
|
|
90
|
+
const replacement = await requiredSnapshot(db, input.workspaceId, result.memory.id);
|
|
91
|
+
if (replacement.supersedesId === result.superseded.id) {
|
|
92
|
+
return await evaluateAndEnqueue(db, {
|
|
93
|
+
accountId: input.accountId,
|
|
94
|
+
workspaceId: input.workspaceId,
|
|
95
|
+
snapshot: replacement,
|
|
96
|
+
changeKind: "corrected",
|
|
97
|
+
relatedMemoryId: result.superseded.id,
|
|
98
|
+
occurredAt: result.memory.updatedAt,
|
|
99
|
+
publication,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
const retired = await requiredSnapshot(db, input.workspaceId, result.superseded.id);
|
|
103
|
+
return await evaluateAndEnqueue(db, {
|
|
104
|
+
accountId: input.accountId,
|
|
105
|
+
workspaceId: input.workspaceId,
|
|
106
|
+
snapshot: retired,
|
|
107
|
+
changeKind: "superseded",
|
|
108
|
+
relatedMemoryId: result.memory.id,
|
|
109
|
+
occurredAt: result.superseded.updatedAt,
|
|
110
|
+
publication,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const created = await requiredSnapshot(db, input.workspaceId, result.memory.id);
|
|
115
|
+
return await evaluateAndEnqueue(db, {
|
|
116
|
+
accountId: input.accountId,
|
|
117
|
+
workspaceId: input.workspaceId,
|
|
118
|
+
snapshot: created,
|
|
119
|
+
changeKind: "created",
|
|
120
|
+
relatedMemoryId: null,
|
|
121
|
+
occurredAt: result.memory.createdAt,
|
|
122
|
+
publication,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async function evaluateAndEnqueue(
|
|
127
|
+
db: Database,
|
|
128
|
+
input: {
|
|
129
|
+
accountId: string;
|
|
130
|
+
workspaceId: string;
|
|
131
|
+
snapshot: WorkspaceMemorySlackPublicationSnapshot;
|
|
132
|
+
changeKind: "created" | "corrected" | "superseded";
|
|
133
|
+
relatedMemoryId: string | null;
|
|
134
|
+
occurredAt: string;
|
|
135
|
+
publication: MemorySlackPublicationCommitRequest;
|
|
136
|
+
},
|
|
137
|
+
): Promise<MemorySlackPublicationCommitResult> {
|
|
138
|
+
const configuration = await getCurrentMemorySlackPublicationConfiguration(db, input.workspaceId);
|
|
139
|
+
const decision = evaluateMemorySlackPublication({
|
|
140
|
+
context: {
|
|
141
|
+
accountId: input.accountId,
|
|
142
|
+
workspaceId: input.workspaceId,
|
|
143
|
+
now: input.occurredAt,
|
|
144
|
+
},
|
|
145
|
+
policy: configuration
|
|
146
|
+
? {
|
|
147
|
+
enabled: configuration.enabled,
|
|
148
|
+
autoImportances: configuration.autoImportances,
|
|
149
|
+
reviewImportances: configuration.reviewImportances,
|
|
150
|
+
}
|
|
151
|
+
: undefined,
|
|
152
|
+
memory: {
|
|
153
|
+
sourceType: "workspace_memory",
|
|
154
|
+
accountId: input.snapshot.accountId,
|
|
155
|
+
workspaceId: input.snapshot.workspaceId,
|
|
156
|
+
id: input.snapshot.id,
|
|
157
|
+
version: input.snapshot.version,
|
|
158
|
+
status: input.snapshot.status as Parameters<
|
|
159
|
+
typeof evaluateMemorySlackPublication
|
|
160
|
+
>[0]["memory"]["status"],
|
|
161
|
+
kind: input.snapshot.kind as Parameters<
|
|
162
|
+
typeof evaluateMemorySlackPublication
|
|
163
|
+
>[0]["memory"]["kind"],
|
|
164
|
+
scopeType: input.snapshot.scopeType as Parameters<
|
|
165
|
+
typeof evaluateMemorySlackPublication
|
|
166
|
+
>[0]["memory"]["scopeType"],
|
|
167
|
+
namespace: input.snapshot.namespace,
|
|
168
|
+
labels: input.snapshot.labels,
|
|
169
|
+
validFrom: input.snapshot.validFrom,
|
|
170
|
+
validUntil: input.snapshot.validUntil,
|
|
171
|
+
supersedesId: input.snapshot.supersedesId,
|
|
172
|
+
supersededById: input.snapshot.supersededById,
|
|
173
|
+
},
|
|
174
|
+
change: {
|
|
175
|
+
kind: input.changeKind,
|
|
176
|
+
relatedMemoryId: input.relatedMemoryId,
|
|
177
|
+
occurredAt: input.occurredAt,
|
|
178
|
+
origin: input.publication.origin ?? "native",
|
|
179
|
+
ownerLabel: input.publication.ownerLabel ?? null,
|
|
180
|
+
},
|
|
181
|
+
distribution: input.publication.distribution,
|
|
182
|
+
});
|
|
183
|
+
if (!decision.eligible) return { decision, enqueue: null };
|
|
184
|
+
|
|
185
|
+
const enqueue = await enqueueMemorySlackPublication(db, {
|
|
186
|
+
accountId: input.accountId,
|
|
187
|
+
workspaceId: input.workspaceId,
|
|
188
|
+
sourceType: "workspace_memory",
|
|
189
|
+
sourceId: input.snapshot.id,
|
|
190
|
+
sourceVersion: String(input.snapshot.version),
|
|
191
|
+
sourceIdempotencyKey: decision.idempotencyKey,
|
|
192
|
+
projection: decision.projection,
|
|
193
|
+
importance: decision.projection.importance,
|
|
194
|
+
deliveryMode: decision.deliveryMode,
|
|
195
|
+
actor: input.publication.actor,
|
|
196
|
+
});
|
|
197
|
+
return { decision, enqueue };
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
async function requiredSnapshot(db: Database, workspaceId: string, memoryId: string) {
|
|
201
|
+
const snapshot = await getWorkspaceMemorySlackPublicationSnapshot(db, workspaceId, memoryId);
|
|
202
|
+
if (!snapshot) throw new Error("Memory Slack publication source disappeared before commit");
|
|
203
|
+
return snapshot;
|
|
204
|
+
}
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
type KnowledgeMemoryKind,
|
|
5
5
|
type KnowledgeMemoryStatus,
|
|
6
6
|
} from "@opengeni/contracts";
|
|
7
|
+
import { sanitizeSlackPublicationText } from "./slack-publication-secret-safety";
|
|
7
8
|
|
|
8
9
|
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
9
10
|
const SELECTOR_SEGMENT_PATTERN = /^[a-z0-9](?:[a-z0-9._-]{0,62}[a-z0-9])?$/;
|
|
@@ -197,7 +198,9 @@ export function evaluateMemorySlackPublication(
|
|
|
197
198
|
const deliveryMode = effectiveDeliveryMode(policy, input.distribution);
|
|
198
199
|
if (!deliveryMode) return denied("below_noise_policy");
|
|
199
200
|
|
|
200
|
-
const collapsedSummary =
|
|
201
|
+
const collapsedSummary = sanitizeSlackPublicationText(
|
|
202
|
+
collapseText(input.distribution.shareSummary),
|
|
203
|
+
);
|
|
201
204
|
if (!collapsedSummary) return denied("missing_summary");
|
|
202
205
|
const summary = truncateUtf8(collapsedSummary, MEMORY_SLACK_SUMMARY_MAX_UTF8_BYTES);
|
|
203
206
|
|
|
@@ -397,7 +400,7 @@ function boundedOptionalText(
|
|
|
397
400
|
value: string | null | undefined,
|
|
398
401
|
maxBytes: number,
|
|
399
402
|
): { value: string | null; truncated: boolean } {
|
|
400
|
-
const collapsed = collapseText(value ?? "");
|
|
403
|
+
const collapsed = sanitizeSlackPublicationText(collapseText(value ?? ""));
|
|
401
404
|
if (!collapsed) return { value: null, truncated: false };
|
|
402
405
|
const bounded = truncateUtf8(collapsed, maxBytes);
|
|
403
406
|
return {
|