mirror of
https://github.com/hanzoai/insights.git
synced 2026-11-03 00:52:32 +00:00
716 files rewritten, 30 renamed, same family mapping as the frontend pass.
Held back, and each for a reason rather than by oversight:
db_table values insights_hogfunction, insights_hogflow,
insights_hogfunctiontemplate, hogflow_templates.
Renaming a table is ALTER TABLE, so it ships as a
migration with the raw SQL in nodejs that names it.
hog_invocation_results a Datastore table with Kafka engine tables on it
products/review_hog the module path is the Django app path; moving it
moves app_label and every migration is recorded under
(app_label, name). That is the same history break as
renaming a migration file, one level up.
*/migrations/* five files, untouched
whogho an integration vendor
Checked: 395 of 397 changed Python files compile. The two that do not —
insightsql/database/database.py and temporal/schedule.py — fail identically at
origin/main under the same interpreter, because they use `type X = ...` and
`except*`, which need the 3.13 this repo pins and not the 3.9 doing the check.
Running the check against the original is what told those apart from a real
break.
Co-authored-by: Hanzo Dev <[email protected]>
50 lines
2.0 KiB
TypeScript
50 lines
2.0 KiB
TypeScript
import { EnrichedTraceTreeNode } from './aiObservabilityTraceDataLogic'
|
|
import { computeBillingTotals } from './useInsightsAIBillingCalculations'
|
|
|
|
function makeNode(properties: Record<string, any>, children?: EnrichedTraceTreeNode[]): EnrichedTraceTreeNode {
|
|
return {
|
|
event: {
|
|
id: `event-${Math.random()}`,
|
|
event: '$ai_generation',
|
|
properties,
|
|
createdAt: '2026-01-01T00:00:00Z',
|
|
},
|
|
children,
|
|
displayTotalCost: 0,
|
|
displayLatency: 0,
|
|
displayUsage: null,
|
|
attachedFeedback: [],
|
|
}
|
|
}
|
|
|
|
describe('computeBillingTotals', () => {
|
|
it('applies markup per event, skipping pass-through products', () => {
|
|
const tree = [
|
|
makeNode({ $ai_billable: true, $ai_total_cost_usd: 10, ai_product: 'insights_ai' }, [
|
|
// Nested pass-through generation must still be summed, without markup
|
|
makeNode({ $ai_billable: true, $ai_total_cost_usd: 5, ai_product: 'insights_code' }),
|
|
]),
|
|
]
|
|
|
|
expect(computeBillingTotals(tree)).toEqual({ totalCostUsd: 15, markupUsd: 2 })
|
|
})
|
|
|
|
it('excludes billable generations outside the billing whitelist', () => {
|
|
// The usage reporter whitelists on ai_product — events with a missing or unknown
|
|
// product never bill, even when tagged $ai_billable, so they must not display as billed.
|
|
const tree = [
|
|
makeNode({ $ai_billable: true, $ai_total_cost_usd: 10, ai_product: 'insights_ai' }),
|
|
makeNode({ $ai_billable: true, $ai_total_cost_usd: 5 }), // untagged
|
|
makeNode({ $ai_billable: true, $ai_total_cost_usd: 5, ai_product: 'sherlockscript' }), // unbilled product
|
|
]
|
|
|
|
expect(computeBillingTotals(tree)).toEqual({ totalCostUsd: 10, markupUsd: 2 })
|
|
})
|
|
|
|
it('ignores non-billable generations', () => {
|
|
const tree = [makeNode({ $ai_billable: false, $ai_total_cost_usd: 10, ai_product: 'insights_ai' })]
|
|
|
|
expect(computeBillingTotals(tree)).toEqual({ totalCostUsd: 0, markupUsd: 0 })
|
|
})
|
|
})
|