bopodev-db 0.1.25 → 0.1.27
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/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-typecheck.log +1 -1
- package/README.md +29 -0
- package/dist/index.d.ts +1 -0
- package/dist/repositories.d.ts +21 -36
- package/dist/schema.d.ts +68 -320
- package/package.json +1 -1
- package/src/bootstrap.ts +11 -12
- package/src/index.ts +1 -0
- package/src/repositories.ts +13 -65
- package/src/schema.ts +2 -19
package/.turbo/turbo-build.log
CHANGED
package/README.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# `packages/db`
|
|
2
|
+
|
|
3
|
+
Database schema and repository layer for Bopo, backed by Drizzle + PGlite.
|
|
4
|
+
|
|
5
|
+
## Responsibilities
|
|
6
|
+
|
|
7
|
+
- Define schema models and migrations/bootstrap behavior.
|
|
8
|
+
- Expose repository functions used by API services/routes.
|
|
9
|
+
- Provide typed DB access primitives for shared business logic.
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
Primary consumer is `apps/api`.
|
|
14
|
+
|
|
15
|
+
## Commands
|
|
16
|
+
|
|
17
|
+
- `pnpm --filter bopodev-db build`
|
|
18
|
+
- `pnpm --filter bopodev-db typecheck`
|
|
19
|
+
|
|
20
|
+
## Notes
|
|
21
|
+
|
|
22
|
+
- Default DB path is managed by app/runtime config; see configuration docs before overriding.
|
|
23
|
+
- API startup bootstraps DB and registers built-in plugins/templates.
|
|
24
|
+
|
|
25
|
+
## Related Docs
|
|
26
|
+
|
|
27
|
+
- `docs/developer/architecture.md`
|
|
28
|
+
- `docs/developer/configuration-reference.md`
|
|
29
|
+
- `docs/operations/deployment.md`
|
package/dist/index.d.ts
CHANGED
package/dist/repositories.d.ts
CHANGED
|
@@ -326,6 +326,23 @@ export declare function listIssues(db: BopoDb, companyId: string, projectId?: st
|
|
|
326
326
|
createdAt: Date;
|
|
327
327
|
updatedAt: Date;
|
|
328
328
|
}[]>;
|
|
329
|
+
export declare function getIssue(db: BopoDb, companyId: string, issueId: string): Promise<{
|
|
330
|
+
id: string;
|
|
331
|
+
companyId: string;
|
|
332
|
+
projectId: string;
|
|
333
|
+
parentIssueId: string | null;
|
|
334
|
+
title: string;
|
|
335
|
+
body: string | null;
|
|
336
|
+
status: string;
|
|
337
|
+
priority: string;
|
|
338
|
+
assigneeAgentId: string | null;
|
|
339
|
+
labelsJson: string;
|
|
340
|
+
tagsJson: string;
|
|
341
|
+
isClaimed: boolean;
|
|
342
|
+
claimedByHeartbeatRunId: string | null;
|
|
343
|
+
createdAt: Date;
|
|
344
|
+
updatedAt: Date;
|
|
345
|
+
} | null>;
|
|
329
346
|
export declare function createIssue(db: BopoDb, input: {
|
|
330
347
|
companyId: string;
|
|
331
348
|
projectId: string;
|
|
@@ -872,11 +889,13 @@ export declare function markAttentionInboxResolved(db: BopoDb, input: {
|
|
|
872
889
|
}): Promise<void>;
|
|
873
890
|
export declare function appendCost(db: BopoDb, input: {
|
|
874
891
|
companyId: string;
|
|
892
|
+
runId?: string | null;
|
|
875
893
|
providerType: string;
|
|
876
894
|
runtimeModelId?: string | null;
|
|
877
895
|
pricingProviderType?: string | null;
|
|
878
896
|
pricingModelId?: string | null;
|
|
879
897
|
pricingSource?: "exact" | "missing" | null;
|
|
898
|
+
usdCostStatus?: "exact" | "estimated" | "unknown" | null;
|
|
880
899
|
tokenInput: number;
|
|
881
900
|
tokenOutput: number;
|
|
882
901
|
usdCost: string;
|
|
@@ -887,6 +906,7 @@ export declare function appendCost(db: BopoDb, input: {
|
|
|
887
906
|
export declare function listCostEntries(db: BopoDb, companyId: string, limit?: number): Promise<{
|
|
888
907
|
id: string;
|
|
889
908
|
companyId: string;
|
|
909
|
+
runId: string | null;
|
|
890
910
|
projectId: string | null;
|
|
891
911
|
issueId: string | null;
|
|
892
912
|
agentId: string | null;
|
|
@@ -898,6 +918,7 @@ export declare function listCostEntries(db: BopoDb, companyId: string, limit?: n
|
|
|
898
918
|
tokenInput: number;
|
|
899
919
|
tokenOutput: number;
|
|
900
920
|
usdCost: string;
|
|
921
|
+
usdCostStatus: string | null;
|
|
901
922
|
createdAt: Date;
|
|
902
923
|
}[]>;
|
|
903
924
|
export declare function listHeartbeatRuns(db: BopoDb, companyId: string, limit?: number): Promise<{
|
|
@@ -1429,39 +1450,3 @@ export declare function createTemplateInstall(db: BopoDb, input: {
|
|
|
1429
1450
|
templateVersionId: string | null;
|
|
1430
1451
|
summaryJson: string;
|
|
1431
1452
|
} | null>;
|
|
1432
|
-
export declare function listModelPricing(db: BopoDb, companyId: string): Promise<{
|
|
1433
|
-
companyId: string;
|
|
1434
|
-
providerType: string;
|
|
1435
|
-
modelId: string;
|
|
1436
|
-
displayName: string | null;
|
|
1437
|
-
inputUsdPer1M: string;
|
|
1438
|
-
outputUsdPer1M: string;
|
|
1439
|
-
currency: string;
|
|
1440
|
-
updatedAt: Date;
|
|
1441
|
-
updatedBy: string | null;
|
|
1442
|
-
}[]>;
|
|
1443
|
-
export declare function getModelPricing(db: BopoDb, input: {
|
|
1444
|
-
companyId: string;
|
|
1445
|
-
providerType: string;
|
|
1446
|
-
modelId: string;
|
|
1447
|
-
}): Promise<{
|
|
1448
|
-
companyId: string;
|
|
1449
|
-
providerType: string;
|
|
1450
|
-
modelId: string;
|
|
1451
|
-
displayName: string | null;
|
|
1452
|
-
inputUsdPer1M: string;
|
|
1453
|
-
outputUsdPer1M: string;
|
|
1454
|
-
currency: string;
|
|
1455
|
-
updatedAt: Date;
|
|
1456
|
-
updatedBy: string | null;
|
|
1457
|
-
} | null>;
|
|
1458
|
-
export declare function upsertModelPricing(db: BopoDb, input: {
|
|
1459
|
-
companyId: string;
|
|
1460
|
-
providerType: string;
|
|
1461
|
-
modelId: string;
|
|
1462
|
-
displayName?: string | null;
|
|
1463
|
-
inputUsdPer1M?: string | null;
|
|
1464
|
-
outputUsdPer1M?: string | null;
|
|
1465
|
-
currency?: string | null;
|
|
1466
|
-
updatedBy?: string | null;
|
|
1467
|
-
}): Promise<void>;
|
package/dist/schema.d.ts
CHANGED
|
@@ -2980,6 +2980,23 @@ export declare const costLedger: import("drizzle-orm/pg-core").PgTableWithColumn
|
|
|
2980
2980
|
identity: undefined;
|
|
2981
2981
|
generated: undefined;
|
|
2982
2982
|
}, {}, {}>;
|
|
2983
|
+
runId: import("drizzle-orm/pg-core").PgColumn<{
|
|
2984
|
+
name: "run_id";
|
|
2985
|
+
tableName: "cost_ledger";
|
|
2986
|
+
dataType: "string";
|
|
2987
|
+
columnType: "PgText";
|
|
2988
|
+
data: string;
|
|
2989
|
+
driverParam: string;
|
|
2990
|
+
notNull: false;
|
|
2991
|
+
hasDefault: false;
|
|
2992
|
+
isPrimaryKey: false;
|
|
2993
|
+
isAutoincrement: false;
|
|
2994
|
+
hasRuntimeDefault: false;
|
|
2995
|
+
enumValues: [string, ...string[]];
|
|
2996
|
+
baseColumn: never;
|
|
2997
|
+
identity: undefined;
|
|
2998
|
+
generated: undefined;
|
|
2999
|
+
}, {}, {}>;
|
|
2983
3000
|
projectId: import("drizzle-orm/pg-core").PgColumn<{
|
|
2984
3001
|
name: "project_id";
|
|
2985
3002
|
tableName: "cost_ledger";
|
|
@@ -3167,6 +3184,23 @@ export declare const costLedger: import("drizzle-orm/pg-core").PgTableWithColumn
|
|
|
3167
3184
|
identity: undefined;
|
|
3168
3185
|
generated: undefined;
|
|
3169
3186
|
}, {}, {}>;
|
|
3187
|
+
usdCostStatus: import("drizzle-orm/pg-core").PgColumn<{
|
|
3188
|
+
name: "usd_cost_status";
|
|
3189
|
+
tableName: "cost_ledger";
|
|
3190
|
+
dataType: "string";
|
|
3191
|
+
columnType: "PgText";
|
|
3192
|
+
data: string;
|
|
3193
|
+
driverParam: string;
|
|
3194
|
+
notNull: false;
|
|
3195
|
+
hasDefault: false;
|
|
3196
|
+
isPrimaryKey: false;
|
|
3197
|
+
isAutoincrement: false;
|
|
3198
|
+
hasRuntimeDefault: false;
|
|
3199
|
+
enumValues: [string, ...string[]];
|
|
3200
|
+
baseColumn: never;
|
|
3201
|
+
identity: undefined;
|
|
3202
|
+
generated: undefined;
|
|
3203
|
+
}, {}, {}>;
|
|
3170
3204
|
createdAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
3171
3205
|
name: "created_at";
|
|
3172
3206
|
tableName: "cost_ledger";
|
|
@@ -4004,166 +4038,6 @@ export declare const templateInstalls: import("drizzle-orm/pg-core").PgTableWith
|
|
|
4004
4038
|
};
|
|
4005
4039
|
dialect: "pg";
|
|
4006
4040
|
}>;
|
|
4007
|
-
export declare const modelPricing: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
4008
|
-
name: "model_pricing";
|
|
4009
|
-
schema: undefined;
|
|
4010
|
-
columns: {
|
|
4011
|
-
companyId: import("drizzle-orm/pg-core").PgColumn<{
|
|
4012
|
-
name: "company_id";
|
|
4013
|
-
tableName: "model_pricing";
|
|
4014
|
-
dataType: "string";
|
|
4015
|
-
columnType: "PgText";
|
|
4016
|
-
data: string;
|
|
4017
|
-
driverParam: string;
|
|
4018
|
-
notNull: true;
|
|
4019
|
-
hasDefault: false;
|
|
4020
|
-
isPrimaryKey: false;
|
|
4021
|
-
isAutoincrement: false;
|
|
4022
|
-
hasRuntimeDefault: false;
|
|
4023
|
-
enumValues: [string, ...string[]];
|
|
4024
|
-
baseColumn: never;
|
|
4025
|
-
identity: undefined;
|
|
4026
|
-
generated: undefined;
|
|
4027
|
-
}, {}, {}>;
|
|
4028
|
-
providerType: import("drizzle-orm/pg-core").PgColumn<{
|
|
4029
|
-
name: "provider_type";
|
|
4030
|
-
tableName: "model_pricing";
|
|
4031
|
-
dataType: "string";
|
|
4032
|
-
columnType: "PgText";
|
|
4033
|
-
data: string;
|
|
4034
|
-
driverParam: string;
|
|
4035
|
-
notNull: true;
|
|
4036
|
-
hasDefault: false;
|
|
4037
|
-
isPrimaryKey: false;
|
|
4038
|
-
isAutoincrement: false;
|
|
4039
|
-
hasRuntimeDefault: false;
|
|
4040
|
-
enumValues: [string, ...string[]];
|
|
4041
|
-
baseColumn: never;
|
|
4042
|
-
identity: undefined;
|
|
4043
|
-
generated: undefined;
|
|
4044
|
-
}, {}, {}>;
|
|
4045
|
-
modelId: import("drizzle-orm/pg-core").PgColumn<{
|
|
4046
|
-
name: "model_id";
|
|
4047
|
-
tableName: "model_pricing";
|
|
4048
|
-
dataType: "string";
|
|
4049
|
-
columnType: "PgText";
|
|
4050
|
-
data: string;
|
|
4051
|
-
driverParam: string;
|
|
4052
|
-
notNull: true;
|
|
4053
|
-
hasDefault: false;
|
|
4054
|
-
isPrimaryKey: false;
|
|
4055
|
-
isAutoincrement: false;
|
|
4056
|
-
hasRuntimeDefault: false;
|
|
4057
|
-
enumValues: [string, ...string[]];
|
|
4058
|
-
baseColumn: never;
|
|
4059
|
-
identity: undefined;
|
|
4060
|
-
generated: undefined;
|
|
4061
|
-
}, {}, {}>;
|
|
4062
|
-
displayName: import("drizzle-orm/pg-core").PgColumn<{
|
|
4063
|
-
name: "display_name";
|
|
4064
|
-
tableName: "model_pricing";
|
|
4065
|
-
dataType: "string";
|
|
4066
|
-
columnType: "PgText";
|
|
4067
|
-
data: string;
|
|
4068
|
-
driverParam: string;
|
|
4069
|
-
notNull: false;
|
|
4070
|
-
hasDefault: false;
|
|
4071
|
-
isPrimaryKey: false;
|
|
4072
|
-
isAutoincrement: false;
|
|
4073
|
-
hasRuntimeDefault: false;
|
|
4074
|
-
enumValues: [string, ...string[]];
|
|
4075
|
-
baseColumn: never;
|
|
4076
|
-
identity: undefined;
|
|
4077
|
-
generated: undefined;
|
|
4078
|
-
}, {}, {}>;
|
|
4079
|
-
inputUsdPer1M: import("drizzle-orm/pg-core").PgColumn<{
|
|
4080
|
-
name: "input_usd_per_1m";
|
|
4081
|
-
tableName: "model_pricing";
|
|
4082
|
-
dataType: "string";
|
|
4083
|
-
columnType: "PgNumeric";
|
|
4084
|
-
data: string;
|
|
4085
|
-
driverParam: string;
|
|
4086
|
-
notNull: true;
|
|
4087
|
-
hasDefault: true;
|
|
4088
|
-
isPrimaryKey: false;
|
|
4089
|
-
isAutoincrement: false;
|
|
4090
|
-
hasRuntimeDefault: false;
|
|
4091
|
-
enumValues: undefined;
|
|
4092
|
-
baseColumn: never;
|
|
4093
|
-
identity: undefined;
|
|
4094
|
-
generated: undefined;
|
|
4095
|
-
}, {}, {}>;
|
|
4096
|
-
outputUsdPer1M: import("drizzle-orm/pg-core").PgColumn<{
|
|
4097
|
-
name: "output_usd_per_1m";
|
|
4098
|
-
tableName: "model_pricing";
|
|
4099
|
-
dataType: "string";
|
|
4100
|
-
columnType: "PgNumeric";
|
|
4101
|
-
data: string;
|
|
4102
|
-
driverParam: string;
|
|
4103
|
-
notNull: true;
|
|
4104
|
-
hasDefault: true;
|
|
4105
|
-
isPrimaryKey: false;
|
|
4106
|
-
isAutoincrement: false;
|
|
4107
|
-
hasRuntimeDefault: false;
|
|
4108
|
-
enumValues: undefined;
|
|
4109
|
-
baseColumn: never;
|
|
4110
|
-
identity: undefined;
|
|
4111
|
-
generated: undefined;
|
|
4112
|
-
}, {}, {}>;
|
|
4113
|
-
currency: import("drizzle-orm/pg-core").PgColumn<{
|
|
4114
|
-
name: "currency";
|
|
4115
|
-
tableName: "model_pricing";
|
|
4116
|
-
dataType: "string";
|
|
4117
|
-
columnType: "PgText";
|
|
4118
|
-
data: string;
|
|
4119
|
-
driverParam: string;
|
|
4120
|
-
notNull: true;
|
|
4121
|
-
hasDefault: true;
|
|
4122
|
-
isPrimaryKey: false;
|
|
4123
|
-
isAutoincrement: false;
|
|
4124
|
-
hasRuntimeDefault: false;
|
|
4125
|
-
enumValues: [string, ...string[]];
|
|
4126
|
-
baseColumn: never;
|
|
4127
|
-
identity: undefined;
|
|
4128
|
-
generated: undefined;
|
|
4129
|
-
}, {}, {}>;
|
|
4130
|
-
updatedAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
4131
|
-
name: "updated_at";
|
|
4132
|
-
tableName: "model_pricing";
|
|
4133
|
-
dataType: "date";
|
|
4134
|
-
columnType: "PgTimestamp";
|
|
4135
|
-
data: Date;
|
|
4136
|
-
driverParam: string;
|
|
4137
|
-
notNull: true;
|
|
4138
|
-
hasDefault: true;
|
|
4139
|
-
isPrimaryKey: false;
|
|
4140
|
-
isAutoincrement: false;
|
|
4141
|
-
hasRuntimeDefault: false;
|
|
4142
|
-
enumValues: undefined;
|
|
4143
|
-
baseColumn: never;
|
|
4144
|
-
identity: undefined;
|
|
4145
|
-
generated: undefined;
|
|
4146
|
-
}, {}, {}>;
|
|
4147
|
-
updatedBy: import("drizzle-orm/pg-core").PgColumn<{
|
|
4148
|
-
name: "updated_by";
|
|
4149
|
-
tableName: "model_pricing";
|
|
4150
|
-
dataType: "string";
|
|
4151
|
-
columnType: "PgText";
|
|
4152
|
-
data: string;
|
|
4153
|
-
driverParam: string;
|
|
4154
|
-
notNull: false;
|
|
4155
|
-
hasDefault: false;
|
|
4156
|
-
isPrimaryKey: false;
|
|
4157
|
-
isAutoincrement: false;
|
|
4158
|
-
hasRuntimeDefault: false;
|
|
4159
|
-
enumValues: [string, ...string[]];
|
|
4160
|
-
baseColumn: never;
|
|
4161
|
-
identity: undefined;
|
|
4162
|
-
generated: undefined;
|
|
4163
|
-
}, {}, {}>;
|
|
4164
|
-
};
|
|
4165
|
-
dialect: "pg";
|
|
4166
|
-
}>;
|
|
4167
4041
|
export declare const pluginConfigs: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
4168
4042
|
name: "plugin_configs";
|
|
4169
4043
|
schema: undefined;
|
|
@@ -7348,6 +7222,23 @@ export declare const schema: {
|
|
|
7348
7222
|
identity: undefined;
|
|
7349
7223
|
generated: undefined;
|
|
7350
7224
|
}, {}, {}>;
|
|
7225
|
+
runId: import("drizzle-orm/pg-core").PgColumn<{
|
|
7226
|
+
name: "run_id";
|
|
7227
|
+
tableName: "cost_ledger";
|
|
7228
|
+
dataType: "string";
|
|
7229
|
+
columnType: "PgText";
|
|
7230
|
+
data: string;
|
|
7231
|
+
driverParam: string;
|
|
7232
|
+
notNull: false;
|
|
7233
|
+
hasDefault: false;
|
|
7234
|
+
isPrimaryKey: false;
|
|
7235
|
+
isAutoincrement: false;
|
|
7236
|
+
hasRuntimeDefault: false;
|
|
7237
|
+
enumValues: [string, ...string[]];
|
|
7238
|
+
baseColumn: never;
|
|
7239
|
+
identity: undefined;
|
|
7240
|
+
generated: undefined;
|
|
7241
|
+
}, {}, {}>;
|
|
7351
7242
|
projectId: import("drizzle-orm/pg-core").PgColumn<{
|
|
7352
7243
|
name: "project_id";
|
|
7353
7244
|
tableName: "cost_ledger";
|
|
@@ -7535,6 +7426,23 @@ export declare const schema: {
|
|
|
7535
7426
|
identity: undefined;
|
|
7536
7427
|
generated: undefined;
|
|
7537
7428
|
}, {}, {}>;
|
|
7429
|
+
usdCostStatus: import("drizzle-orm/pg-core").PgColumn<{
|
|
7430
|
+
name: "usd_cost_status";
|
|
7431
|
+
tableName: "cost_ledger";
|
|
7432
|
+
dataType: "string";
|
|
7433
|
+
columnType: "PgText";
|
|
7434
|
+
data: string;
|
|
7435
|
+
driverParam: string;
|
|
7436
|
+
notNull: false;
|
|
7437
|
+
hasDefault: false;
|
|
7438
|
+
isPrimaryKey: false;
|
|
7439
|
+
isAutoincrement: false;
|
|
7440
|
+
hasRuntimeDefault: false;
|
|
7441
|
+
enumValues: [string, ...string[]];
|
|
7442
|
+
baseColumn: never;
|
|
7443
|
+
identity: undefined;
|
|
7444
|
+
generated: undefined;
|
|
7445
|
+
}, {}, {}>;
|
|
7538
7446
|
createdAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
7539
7447
|
name: "created_at";
|
|
7540
7448
|
tableName: "cost_ledger";
|
|
@@ -8692,166 +8600,6 @@ export declare const schema: {
|
|
|
8692
8600
|
};
|
|
8693
8601
|
dialect: "pg";
|
|
8694
8602
|
}>;
|
|
8695
|
-
modelPricing: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
8696
|
-
name: "model_pricing";
|
|
8697
|
-
schema: undefined;
|
|
8698
|
-
columns: {
|
|
8699
|
-
companyId: import("drizzle-orm/pg-core").PgColumn<{
|
|
8700
|
-
name: "company_id";
|
|
8701
|
-
tableName: "model_pricing";
|
|
8702
|
-
dataType: "string";
|
|
8703
|
-
columnType: "PgText";
|
|
8704
|
-
data: string;
|
|
8705
|
-
driverParam: string;
|
|
8706
|
-
notNull: true;
|
|
8707
|
-
hasDefault: false;
|
|
8708
|
-
isPrimaryKey: false;
|
|
8709
|
-
isAutoincrement: false;
|
|
8710
|
-
hasRuntimeDefault: false;
|
|
8711
|
-
enumValues: [string, ...string[]];
|
|
8712
|
-
baseColumn: never;
|
|
8713
|
-
identity: undefined;
|
|
8714
|
-
generated: undefined;
|
|
8715
|
-
}, {}, {}>;
|
|
8716
|
-
providerType: import("drizzle-orm/pg-core").PgColumn<{
|
|
8717
|
-
name: "provider_type";
|
|
8718
|
-
tableName: "model_pricing";
|
|
8719
|
-
dataType: "string";
|
|
8720
|
-
columnType: "PgText";
|
|
8721
|
-
data: string;
|
|
8722
|
-
driverParam: string;
|
|
8723
|
-
notNull: true;
|
|
8724
|
-
hasDefault: false;
|
|
8725
|
-
isPrimaryKey: false;
|
|
8726
|
-
isAutoincrement: false;
|
|
8727
|
-
hasRuntimeDefault: false;
|
|
8728
|
-
enumValues: [string, ...string[]];
|
|
8729
|
-
baseColumn: never;
|
|
8730
|
-
identity: undefined;
|
|
8731
|
-
generated: undefined;
|
|
8732
|
-
}, {}, {}>;
|
|
8733
|
-
modelId: import("drizzle-orm/pg-core").PgColumn<{
|
|
8734
|
-
name: "model_id";
|
|
8735
|
-
tableName: "model_pricing";
|
|
8736
|
-
dataType: "string";
|
|
8737
|
-
columnType: "PgText";
|
|
8738
|
-
data: string;
|
|
8739
|
-
driverParam: string;
|
|
8740
|
-
notNull: true;
|
|
8741
|
-
hasDefault: false;
|
|
8742
|
-
isPrimaryKey: false;
|
|
8743
|
-
isAutoincrement: false;
|
|
8744
|
-
hasRuntimeDefault: false;
|
|
8745
|
-
enumValues: [string, ...string[]];
|
|
8746
|
-
baseColumn: never;
|
|
8747
|
-
identity: undefined;
|
|
8748
|
-
generated: undefined;
|
|
8749
|
-
}, {}, {}>;
|
|
8750
|
-
displayName: import("drizzle-orm/pg-core").PgColumn<{
|
|
8751
|
-
name: "display_name";
|
|
8752
|
-
tableName: "model_pricing";
|
|
8753
|
-
dataType: "string";
|
|
8754
|
-
columnType: "PgText";
|
|
8755
|
-
data: string;
|
|
8756
|
-
driverParam: string;
|
|
8757
|
-
notNull: false;
|
|
8758
|
-
hasDefault: false;
|
|
8759
|
-
isPrimaryKey: false;
|
|
8760
|
-
isAutoincrement: false;
|
|
8761
|
-
hasRuntimeDefault: false;
|
|
8762
|
-
enumValues: [string, ...string[]];
|
|
8763
|
-
baseColumn: never;
|
|
8764
|
-
identity: undefined;
|
|
8765
|
-
generated: undefined;
|
|
8766
|
-
}, {}, {}>;
|
|
8767
|
-
inputUsdPer1M: import("drizzle-orm/pg-core").PgColumn<{
|
|
8768
|
-
name: "input_usd_per_1m";
|
|
8769
|
-
tableName: "model_pricing";
|
|
8770
|
-
dataType: "string";
|
|
8771
|
-
columnType: "PgNumeric";
|
|
8772
|
-
data: string;
|
|
8773
|
-
driverParam: string;
|
|
8774
|
-
notNull: true;
|
|
8775
|
-
hasDefault: true;
|
|
8776
|
-
isPrimaryKey: false;
|
|
8777
|
-
isAutoincrement: false;
|
|
8778
|
-
hasRuntimeDefault: false;
|
|
8779
|
-
enumValues: undefined;
|
|
8780
|
-
baseColumn: never;
|
|
8781
|
-
identity: undefined;
|
|
8782
|
-
generated: undefined;
|
|
8783
|
-
}, {}, {}>;
|
|
8784
|
-
outputUsdPer1M: import("drizzle-orm/pg-core").PgColumn<{
|
|
8785
|
-
name: "output_usd_per_1m";
|
|
8786
|
-
tableName: "model_pricing";
|
|
8787
|
-
dataType: "string";
|
|
8788
|
-
columnType: "PgNumeric";
|
|
8789
|
-
data: string;
|
|
8790
|
-
driverParam: string;
|
|
8791
|
-
notNull: true;
|
|
8792
|
-
hasDefault: true;
|
|
8793
|
-
isPrimaryKey: false;
|
|
8794
|
-
isAutoincrement: false;
|
|
8795
|
-
hasRuntimeDefault: false;
|
|
8796
|
-
enumValues: undefined;
|
|
8797
|
-
baseColumn: never;
|
|
8798
|
-
identity: undefined;
|
|
8799
|
-
generated: undefined;
|
|
8800
|
-
}, {}, {}>;
|
|
8801
|
-
currency: import("drizzle-orm/pg-core").PgColumn<{
|
|
8802
|
-
name: "currency";
|
|
8803
|
-
tableName: "model_pricing";
|
|
8804
|
-
dataType: "string";
|
|
8805
|
-
columnType: "PgText";
|
|
8806
|
-
data: string;
|
|
8807
|
-
driverParam: string;
|
|
8808
|
-
notNull: true;
|
|
8809
|
-
hasDefault: true;
|
|
8810
|
-
isPrimaryKey: false;
|
|
8811
|
-
isAutoincrement: false;
|
|
8812
|
-
hasRuntimeDefault: false;
|
|
8813
|
-
enumValues: [string, ...string[]];
|
|
8814
|
-
baseColumn: never;
|
|
8815
|
-
identity: undefined;
|
|
8816
|
-
generated: undefined;
|
|
8817
|
-
}, {}, {}>;
|
|
8818
|
-
updatedAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
8819
|
-
name: "updated_at";
|
|
8820
|
-
tableName: "model_pricing";
|
|
8821
|
-
dataType: "date";
|
|
8822
|
-
columnType: "PgTimestamp";
|
|
8823
|
-
data: Date;
|
|
8824
|
-
driverParam: string;
|
|
8825
|
-
notNull: true;
|
|
8826
|
-
hasDefault: true;
|
|
8827
|
-
isPrimaryKey: false;
|
|
8828
|
-
isAutoincrement: false;
|
|
8829
|
-
hasRuntimeDefault: false;
|
|
8830
|
-
enumValues: undefined;
|
|
8831
|
-
baseColumn: never;
|
|
8832
|
-
identity: undefined;
|
|
8833
|
-
generated: undefined;
|
|
8834
|
-
}, {}, {}>;
|
|
8835
|
-
updatedBy: import("drizzle-orm/pg-core").PgColumn<{
|
|
8836
|
-
name: "updated_by";
|
|
8837
|
-
tableName: "model_pricing";
|
|
8838
|
-
dataType: "string";
|
|
8839
|
-
columnType: "PgText";
|
|
8840
|
-
data: string;
|
|
8841
|
-
driverParam: string;
|
|
8842
|
-
notNull: false;
|
|
8843
|
-
hasDefault: false;
|
|
8844
|
-
isPrimaryKey: false;
|
|
8845
|
-
isAutoincrement: false;
|
|
8846
|
-
hasRuntimeDefault: false;
|
|
8847
|
-
enumValues: [string, ...string[]];
|
|
8848
|
-
baseColumn: never;
|
|
8849
|
-
identity: undefined;
|
|
8850
|
-
generated: undefined;
|
|
8851
|
-
}, {}, {}>;
|
|
8852
|
-
};
|
|
8853
|
-
dialect: "pg";
|
|
8854
|
-
}>;
|
|
8855
8603
|
agentIssueLabels: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
8856
8604
|
name: "agent_issue_labels";
|
|
8857
8605
|
schema: undefined;
|
package/package.json
CHANGED
package/src/bootstrap.ts
CHANGED
|
@@ -371,6 +371,7 @@ export async function bootstrapDatabase(dbPath?: string) {
|
|
|
371
371
|
CREATE TABLE IF NOT EXISTS cost_ledger (
|
|
372
372
|
id TEXT PRIMARY KEY,
|
|
373
373
|
company_id TEXT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
|
374
|
+
run_id TEXT REFERENCES heartbeat_runs(id) ON DELETE SET NULL,
|
|
374
375
|
project_id TEXT REFERENCES projects(id) ON DELETE SET NULL,
|
|
375
376
|
issue_id TEXT REFERENCES issues(id) ON DELETE SET NULL,
|
|
376
377
|
agent_id TEXT REFERENCES agents(id) ON DELETE SET NULL,
|
|
@@ -382,9 +383,14 @@ export async function bootstrapDatabase(dbPath?: string) {
|
|
|
382
383
|
token_input INTEGER NOT NULL DEFAULT 0,
|
|
383
384
|
token_output INTEGER NOT NULL DEFAULT 0,
|
|
384
385
|
usd_cost NUMERIC(12, 6) NOT NULL DEFAULT 0,
|
|
386
|
+
usd_cost_status TEXT,
|
|
385
387
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
386
388
|
);
|
|
387
389
|
`);
|
|
390
|
+
await db.execute(sql`
|
|
391
|
+
ALTER TABLE cost_ledger
|
|
392
|
+
ADD COLUMN IF NOT EXISTS run_id TEXT REFERENCES heartbeat_runs(id) ON DELETE SET NULL;
|
|
393
|
+
`);
|
|
388
394
|
await db.execute(sql`
|
|
389
395
|
ALTER TABLE cost_ledger
|
|
390
396
|
ADD COLUMN IF NOT EXISTS runtime_model_id TEXT;
|
|
@@ -402,18 +408,11 @@ export async function bootstrapDatabase(dbPath?: string) {
|
|
|
402
408
|
ADD COLUMN IF NOT EXISTS pricing_source TEXT;
|
|
403
409
|
`);
|
|
404
410
|
await db.execute(sql`
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
input_usd_per_1m NUMERIC(12, 6) NOT NULL DEFAULT 0,
|
|
411
|
-
output_usd_per_1m NUMERIC(12, 6) NOT NULL DEFAULT 0,
|
|
412
|
-
currency TEXT NOT NULL DEFAULT 'USD',
|
|
413
|
-
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
414
|
-
updated_by TEXT,
|
|
415
|
-
PRIMARY KEY (company_id, provider_type, model_id)
|
|
416
|
-
);
|
|
411
|
+
ALTER TABLE cost_ledger
|
|
412
|
+
ADD COLUMN IF NOT EXISTS usd_cost_status TEXT;
|
|
413
|
+
`);
|
|
414
|
+
await db.execute(sql`
|
|
415
|
+
DROP TABLE IF EXISTS model_pricing;
|
|
417
416
|
`);
|
|
418
417
|
await db.execute(sql`
|
|
419
418
|
CREATE TABLE IF NOT EXISTS audit_events (
|
package/src/index.ts
CHANGED
package/src/repositories.ts
CHANGED
|
@@ -17,7 +17,6 @@ import {
|
|
|
17
17
|
issueAttachments,
|
|
18
18
|
issueComments,
|
|
19
19
|
issues,
|
|
20
|
-
modelPricing,
|
|
21
20
|
pluginConfigs,
|
|
22
21
|
pluginRuns,
|
|
23
22
|
plugins,
|
|
@@ -541,6 +540,15 @@ export async function listIssues(db: BopoDb, companyId: string, projectId?: stri
|
|
|
541
540
|
return db.select().from(issues).where(where).orderBy(desc(issues.updatedAt));
|
|
542
541
|
}
|
|
543
542
|
|
|
543
|
+
export async function getIssue(db: BopoDb, companyId: string, issueId: string) {
|
|
544
|
+
const [row] = await db
|
|
545
|
+
.select()
|
|
546
|
+
.from(issues)
|
|
547
|
+
.where(and(eq(issues.companyId, companyId), eq(issues.id, issueId)))
|
|
548
|
+
.limit(1);
|
|
549
|
+
return row ?? null;
|
|
550
|
+
}
|
|
551
|
+
|
|
544
552
|
export async function createIssue(
|
|
545
553
|
db: BopoDb,
|
|
546
554
|
input: {
|
|
@@ -1458,11 +1466,13 @@ export async function appendCost(
|
|
|
1458
1466
|
db: BopoDb,
|
|
1459
1467
|
input: {
|
|
1460
1468
|
companyId: string;
|
|
1469
|
+
runId?: string | null;
|
|
1461
1470
|
providerType: string;
|
|
1462
1471
|
runtimeModelId?: string | null;
|
|
1463
1472
|
pricingProviderType?: string | null;
|
|
1464
1473
|
pricingModelId?: string | null;
|
|
1465
1474
|
pricingSource?: "exact" | "missing" | null;
|
|
1475
|
+
usdCostStatus?: "exact" | "estimated" | "unknown" | null;
|
|
1466
1476
|
tokenInput: number;
|
|
1467
1477
|
tokenOutput: number;
|
|
1468
1478
|
usdCost: string;
|
|
@@ -1475,11 +1485,13 @@ export async function appendCost(
|
|
|
1475
1485
|
await db.insert(costLedger).values({
|
|
1476
1486
|
id,
|
|
1477
1487
|
companyId: input.companyId,
|
|
1488
|
+
runId: input.runId ?? null,
|
|
1478
1489
|
providerType: input.providerType,
|
|
1479
1490
|
runtimeModelId: input.runtimeModelId ?? null,
|
|
1480
1491
|
pricingProviderType: input.pricingProviderType ?? null,
|
|
1481
1492
|
pricingModelId: input.pricingModelId ?? null,
|
|
1482
1493
|
pricingSource: input.pricingSource ?? null,
|
|
1494
|
+
usdCostStatus: input.usdCostStatus ?? null,
|
|
1483
1495
|
tokenInput: input.tokenInput,
|
|
1484
1496
|
tokenOutput: input.tokenOutput,
|
|
1485
1497
|
usdCost: input.usdCost,
|
|
@@ -2367,70 +2379,6 @@ export async function createTemplateInstall(
|
|
|
2367
2379
|
return row ?? null;
|
|
2368
2380
|
}
|
|
2369
2381
|
|
|
2370
|
-
export async function listModelPricing(db: BopoDb, companyId: string) {
|
|
2371
|
-
return db
|
|
2372
|
-
.select()
|
|
2373
|
-
.from(modelPricing)
|
|
2374
|
-
.where(eq(modelPricing.companyId, companyId))
|
|
2375
|
-
.orderBy(asc(modelPricing.providerType), asc(modelPricing.modelId));
|
|
2376
|
-
}
|
|
2377
|
-
|
|
2378
|
-
export async function getModelPricing(
|
|
2379
|
-
db: BopoDb,
|
|
2380
|
-
input: { companyId: string; providerType: string; modelId: string }
|
|
2381
|
-
) {
|
|
2382
|
-
const rows = await db
|
|
2383
|
-
.select()
|
|
2384
|
-
.from(modelPricing)
|
|
2385
|
-
.where(
|
|
2386
|
-
and(
|
|
2387
|
-
eq(modelPricing.companyId, input.companyId),
|
|
2388
|
-
eq(modelPricing.providerType, input.providerType),
|
|
2389
|
-
eq(modelPricing.modelId, input.modelId)
|
|
2390
|
-
)
|
|
2391
|
-
)
|
|
2392
|
-
.limit(1);
|
|
2393
|
-
return rows[0] ?? null;
|
|
2394
|
-
}
|
|
2395
|
-
|
|
2396
|
-
export async function upsertModelPricing(
|
|
2397
|
-
db: BopoDb,
|
|
2398
|
-
input: {
|
|
2399
|
-
companyId: string;
|
|
2400
|
-
providerType: string;
|
|
2401
|
-
modelId: string;
|
|
2402
|
-
displayName?: string | null;
|
|
2403
|
-
inputUsdPer1M?: string | null;
|
|
2404
|
-
outputUsdPer1M?: string | null;
|
|
2405
|
-
currency?: string | null;
|
|
2406
|
-
updatedBy?: string | null;
|
|
2407
|
-
}
|
|
2408
|
-
) {
|
|
2409
|
-
await db
|
|
2410
|
-
.insert(modelPricing)
|
|
2411
|
-
.values({
|
|
2412
|
-
companyId: input.companyId,
|
|
2413
|
-
providerType: input.providerType,
|
|
2414
|
-
modelId: input.modelId,
|
|
2415
|
-
displayName: input.displayName ?? null,
|
|
2416
|
-
inputUsdPer1M: input.inputUsdPer1M ?? "0.000000",
|
|
2417
|
-
outputUsdPer1M: input.outputUsdPer1M ?? "0.000000",
|
|
2418
|
-
currency: input.currency ?? "USD",
|
|
2419
|
-
updatedBy: input.updatedBy ?? null
|
|
2420
|
-
})
|
|
2421
|
-
.onConflictDoUpdate({
|
|
2422
|
-
target: [modelPricing.companyId, modelPricing.providerType, modelPricing.modelId],
|
|
2423
|
-
set: compactUpdate({
|
|
2424
|
-
displayName: input.displayName ?? null,
|
|
2425
|
-
inputUsdPer1M: input.inputUsdPer1M ?? "0.000000",
|
|
2426
|
-
outputUsdPer1M: input.outputUsdPer1M ?? "0.000000",
|
|
2427
|
-
currency: input.currency ?? "USD",
|
|
2428
|
-
updatedBy: input.updatedBy ?? null,
|
|
2429
|
-
updatedAt: touchUpdatedAtSql
|
|
2430
|
-
})
|
|
2431
|
-
});
|
|
2432
|
-
}
|
|
2433
|
-
|
|
2434
2382
|
function compactUpdate<T extends Record<string, unknown>>(input: T) {
|
|
2435
2383
|
return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== undefined));
|
|
2436
2384
|
}
|
package/src/schema.ts
CHANGED
|
@@ -280,6 +280,7 @@ export const costLedger = pgTable("cost_ledger", {
|
|
|
280
280
|
companyId: text("company_id")
|
|
281
281
|
.notNull()
|
|
282
282
|
.references(() => companies.id, { onDelete: "cascade" }),
|
|
283
|
+
runId: text("run_id").references(() => heartbeatRuns.id, { onDelete: "set null" }),
|
|
283
284
|
projectId: text("project_id").references(() => projects.id, { onDelete: "set null" }),
|
|
284
285
|
issueId: text("issue_id").references(() => issues.id, { onDelete: "set null" }),
|
|
285
286
|
agentId: text("agent_id").references(() => agents.id, { onDelete: "set null" }),
|
|
@@ -291,6 +292,7 @@ export const costLedger = pgTable("cost_ledger", {
|
|
|
291
292
|
tokenInput: integer("token_input").notNull().default(0),
|
|
292
293
|
tokenOutput: integer("token_output").notNull().default(0),
|
|
293
294
|
usdCost: numeric("usd_cost", { precision: 12, scale: 6 }).notNull().default("0"),
|
|
295
|
+
usdCostStatus: text("usd_cost_status"),
|
|
294
296
|
createdAt: timestamp("created_at", { mode: "date" }).defaultNow().notNull()
|
|
295
297
|
});
|
|
296
298
|
|
|
@@ -365,24 +367,6 @@ export const templateInstalls = pgTable("template_installs", {
|
|
|
365
367
|
createdAt: timestamp("created_at", { mode: "date" }).defaultNow().notNull()
|
|
366
368
|
});
|
|
367
369
|
|
|
368
|
-
export const modelPricing = pgTable(
|
|
369
|
-
"model_pricing",
|
|
370
|
-
{
|
|
371
|
-
companyId: text("company_id")
|
|
372
|
-
.notNull()
|
|
373
|
-
.references(() => companies.id, { onDelete: "cascade" }),
|
|
374
|
-
providerType: text("provider_type").notNull(),
|
|
375
|
-
modelId: text("model_id").notNull(),
|
|
376
|
-
displayName: text("display_name"),
|
|
377
|
-
inputUsdPer1M: numeric("input_usd_per_1m", { precision: 12, scale: 6 }).notNull().default("0"),
|
|
378
|
-
outputUsdPer1M: numeric("output_usd_per_1m", { precision: 12, scale: 6 }).notNull().default("0"),
|
|
379
|
-
currency: text("currency").notNull().default("USD"),
|
|
380
|
-
updatedAt: timestamp("updated_at", { mode: "date" }).defaultNow().notNull(),
|
|
381
|
-
updatedBy: text("updated_by")
|
|
382
|
-
},
|
|
383
|
-
(table) => [primaryKey({ columns: [table.companyId, table.providerType, table.modelId] })]
|
|
384
|
-
);
|
|
385
|
-
|
|
386
370
|
export const pluginConfigs = pgTable(
|
|
387
371
|
"plugin_configs",
|
|
388
372
|
{
|
|
@@ -456,7 +440,6 @@ export const schema = {
|
|
|
456
440
|
templates,
|
|
457
441
|
templateVersions,
|
|
458
442
|
templateInstalls,
|
|
459
|
-
modelPricing,
|
|
460
443
|
agentIssueLabels,
|
|
461
444
|
projectWorkspaces
|
|
462
445
|
};
|