@cat-factory/spend 0.7.4 → 0.8.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/SpendService.d.ts +11 -2
- package/dist/SpendService.d.ts.map +1 -1
- package/dist/SpendService.js +10 -3
- package/dist/SpendService.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/pricing.d.ts +15 -0
- package/dist/pricing.d.ts.map +1 -1
- package/dist/pricing.js +27 -1
- package/dist/pricing.js.map +1 -1
- package/package.json +4 -4
package/dist/SpendService.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SpendStatus } from '@cat-factory/contracts';
|
|
1
|
+
import type { OpenRouterModelMeta, SpendStatus } from '@cat-factory/contracts';
|
|
2
2
|
import type { AgentTokenUsage } from '@cat-factory/kernel';
|
|
3
3
|
import type { Clock, IdGenerator } from '@cat-factory/kernel';
|
|
4
4
|
import type { TokenUsageRepository } from '@cat-factory/kernel';
|
|
@@ -8,6 +8,14 @@ export interface SpendServiceDependencies {
|
|
|
8
8
|
idGenerator: IdGenerator;
|
|
9
9
|
clock: Clock;
|
|
10
10
|
pricing: SpendPricing;
|
|
11
|
+
/**
|
|
12
|
+
* Optional resolver for a workspace's dynamic gateway model prices (the enabled
|
|
13
|
+
* OpenRouter catalog). When wired, a metered `openrouter:<slug>` call is priced at the
|
|
14
|
+
* model's real per-1M rate (overlaid onto the base table) instead of the bare-`openrouter`
|
|
15
|
+
* fallback — so budgets meter dynamic models as accurately as the curated ones. Absent →
|
|
16
|
+
* the static table is used (the fallback price applies to uncatalogued slugs).
|
|
17
|
+
*/
|
|
18
|
+
dynamicPricesFor?: (workspaceId: string) => Promise<OpenRouterModelMeta[]>;
|
|
11
19
|
}
|
|
12
20
|
/** Details of a single metered LLM call, handed in by the execution engine. */
|
|
13
21
|
export interface RecordUsageInput {
|
|
@@ -30,7 +38,8 @@ export declare class SpendService {
|
|
|
30
38
|
private readonly idGenerator;
|
|
31
39
|
private readonly clock;
|
|
32
40
|
private readonly pricing;
|
|
33
|
-
|
|
41
|
+
private readonly dynamicPricesFor?;
|
|
42
|
+
constructor({ tokenUsageRepository, idGenerator, clock, pricing, dynamicPricesFor, }: SpendServiceDependencies);
|
|
34
43
|
/** Parse a `provider:model` identifier into a {@link ModelRef}. */
|
|
35
44
|
private parseModel;
|
|
36
45
|
/** Meter and persist one LLM call; returns its estimated cost. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpendService.d.ts","sourceRoot":"","sources":["../src/SpendService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"SpendService.d.ts","sourceRoot":"","sources":["../src/SpendService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAC9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAE1D,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC/D,OAAO,EAAE,KAAK,YAAY,EAAoD,MAAM,cAAc,CAAA;AAElG,MAAM,WAAW,wBAAwB;IACvC,oBAAoB,EAAE,oBAAoB,CAAA;IAC1C,WAAW,EAAE,WAAW,CAAA;IACxB,KAAK,EAAE,KAAK,CAAA;IACZ,OAAO,EAAE,YAAY,CAAA;IACrB;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAA;CAC3E;AAED,+EAA+E;AAC/E,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,EAAE,MAAM,CAAA;IACjB,kFAAkF;IAClF,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,eAAe,CAAA;CACvB;AAED;;;;;;GAMG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAsB;IAC3D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAa;IACzC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAO;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAyD;IAE3F,YAAY,EACV,oBAAoB,EACpB,WAAW,EACX,KAAK,EACL,OAAO,EACP,gBAAgB,GACjB,EAAE,wBAAwB,EAM1B;IAED,mEAAmE;IACnE,OAAO,CAAC,UAAU;IAMlB,kEAAkE;IAC5D,MAAM,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBrD;IAED,wEAAwE;IAClE,MAAM,IAAI,OAAO,CAAC,WAAW,CAAC,CAYnC;IAED,8EAA8E;IACxE,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC,CAIrC;CACF"}
|
package/dist/SpendService.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { estimateCost, startOfMonthUtc } from './pricing.js';
|
|
1
|
+
import { estimateCost, startOfMonthUtc, withDynamicPrices } from './pricing.js';
|
|
2
2
|
/**
|
|
3
3
|
* The spend safeguard. It meters token usage into a persistent ledger, prices
|
|
4
4
|
* each call into a single currency, and reports the current billing period's
|
|
@@ -11,11 +11,13 @@ export class SpendService {
|
|
|
11
11
|
idGenerator;
|
|
12
12
|
clock;
|
|
13
13
|
pricing;
|
|
14
|
-
|
|
14
|
+
dynamicPricesFor;
|
|
15
|
+
constructor({ tokenUsageRepository, idGenerator, clock, pricing, dynamicPricesFor, }) {
|
|
15
16
|
this.tokenUsageRepository = tokenUsageRepository;
|
|
16
17
|
this.idGenerator = idGenerator;
|
|
17
18
|
this.clock = clock;
|
|
18
19
|
this.pricing = pricing;
|
|
20
|
+
this.dynamicPricesFor = dynamicPricesFor;
|
|
19
21
|
}
|
|
20
22
|
/** Parse a `provider:model` identifier into a {@link ModelRef}. */
|
|
21
23
|
parseModel(model) {
|
|
@@ -27,7 +29,12 @@ export class SpendService {
|
|
|
27
29
|
/** Meter and persist one LLM call; returns its estimated cost. */
|
|
28
30
|
async record(input) {
|
|
29
31
|
const ref = this.parseModel(input.model);
|
|
30
|
-
|
|
32
|
+
// Price a dynamic OpenRouter gateway model at its real per-model rate (overlaid onto
|
|
33
|
+
// the base table) rather than the bare-`openrouter` fallback, when the resolver is wired.
|
|
34
|
+
const pricing = ref.provider === 'openrouter' && this.dynamicPricesFor
|
|
35
|
+
? withDynamicPrices(this.pricing, await this.dynamicPricesFor(input.workspaceId))
|
|
36
|
+
: this.pricing;
|
|
37
|
+
const costEstimate = estimateCost(pricing, ref, input.usage);
|
|
31
38
|
await this.tokenUsageRepository.record({
|
|
32
39
|
id: this.idGenerator.next('tok'),
|
|
33
40
|
workspaceId: input.workspaceId,
|
package/dist/SpendService.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpendService.js","sourceRoot":"","sources":["../src/SpendService.ts"],"names":[],"mappings":"AAKA,OAAO,EAAqB,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"SpendService.js","sourceRoot":"","sources":["../src/SpendService.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { SpendService, type SpendServiceDependencies, type RecordUsageInput, } from './SpendService.js';
|
|
2
|
-
export { type ModelPrice, type SpendPricing, DEFAULT_MODEL_PRICES, DEFAULT_MONTHLY_LIMIT_EUR, DEFAULT_SPEND_PRICING, priceFor, modelCostResolver, estimateCost, startOfMonthUtc, } from './pricing.js';
|
|
2
|
+
export { type ModelPrice, type SpendPricing, DEFAULT_MODEL_PRICES, DEFAULT_MONTHLY_LIMIT_EUR, DEFAULT_SPEND_PRICING, priceFor, modelCostResolver, estimateCost, withDynamicPrices, startOfMonthUtc, } from './pricing.js';
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,YAAY,EACZ,KAAK,wBAAwB,EAC7B,KAAK,gBAAgB,GACtB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,oBAAoB,EACpB,yBAAyB,EACzB,qBAAqB,EACrB,QAAQ,EACR,iBAAiB,EACjB,YAAY,EACZ,eAAe,GAChB,MAAM,cAAc,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,YAAY,EACZ,KAAK,wBAAwB,EAC7B,KAAK,gBAAgB,GACtB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,oBAAoB,EACpB,yBAAyB,EACzB,qBAAqB,EACrB,QAAQ,EACR,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,eAAe,GAChB,MAAM,cAAc,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// Pricing tables and spend metering/gating for @cat-factory.
|
|
2
2
|
export { SpendService, } from './SpendService.js';
|
|
3
|
-
export { DEFAULT_MODEL_PRICES, DEFAULT_MONTHLY_LIMIT_EUR, DEFAULT_SPEND_PRICING, priceFor, modelCostResolver, estimateCost, startOfMonthUtc, } from './pricing.js';
|
|
3
|
+
export { DEFAULT_MODEL_PRICES, DEFAULT_MONTHLY_LIMIT_EUR, DEFAULT_SPEND_PRICING, priceFor, modelCostResolver, estimateCost, withDynamicPrices, startOfMonthUtc, } from './pricing.js';
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAE7D,OAAO,EACL,YAAY,GAGb,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAGL,oBAAoB,EACpB,yBAAyB,EACzB,qBAAqB,EACrB,QAAQ,EACR,iBAAiB,EACjB,YAAY,EACZ,eAAe,GAChB,MAAM,cAAc,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAE7D,OAAO,EACL,YAAY,GAGb,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAGL,oBAAoB,EACpB,yBAAyB,EACzB,qBAAqB,EACrB,QAAQ,EACR,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,eAAe,GAChB,MAAM,cAAc,CAAA"}
|
package/dist/pricing.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ModelRef } from '@cat-factory/kernel';
|
|
2
2
|
import type { AgentTokenUsage } from '@cat-factory/kernel';
|
|
3
|
+
import type { OpenRouterModelMeta } from '@cat-factory/contracts';
|
|
3
4
|
/** Price per 1M input/output tokens for one model. */
|
|
4
5
|
export interface ModelPrice {
|
|
5
6
|
inputPerMillion: number;
|
|
@@ -23,6 +24,20 @@ export declare const DEFAULT_MODEL_PRICES: Record<string, ModelPrice>;
|
|
|
23
24
|
/** Default budget: roughly 100 EUR of tokens per calendar month. */
|
|
24
25
|
export declare const DEFAULT_MONTHLY_LIMIT_EUR = 100;
|
|
25
26
|
export declare const DEFAULT_SPEND_PRICING: SpendPricing;
|
|
27
|
+
/**
|
|
28
|
+
* Overlay a workspace's dynamic OpenRouter catalog prices onto a base pricing table,
|
|
29
|
+
* keyed by the `openrouter:<slug>` ref so {@link priceFor} resolves each enabled model
|
|
30
|
+
* at its real upstream rate (the prices are already in the spend currency — see
|
|
31
|
+
* `OpenRouterCatalogService`). Used by the per-workspace `/models` cost resolver and the
|
|
32
|
+
* spend gate so budgets meter dynamic models accurately instead of the bare-`openrouter`
|
|
33
|
+
* fallback guess. Returns a new {@link SpendPricing}; the input is not mutated.
|
|
34
|
+
*
|
|
35
|
+
* A model whose cached price is entirely non-positive (OpenRouter reported no pricing, so
|
|
36
|
+
* `parseModels` zeroed it) is SKIPPED rather than overlaid as free: a budget safeguard must
|
|
37
|
+
* never undercount, so such a model keeps the more conservative bare-`openrouter` (or curated)
|
|
38
|
+
* fallback instead of being metered at zero.
|
|
39
|
+
*/
|
|
40
|
+
export declare function withDynamicPrices(pricing: SpendPricing, models: OpenRouterModelMeta[]): SpendPricing;
|
|
26
41
|
/** Resolve the price for a model, most-specific entry first. */
|
|
27
42
|
export declare function priceFor(pricing: SpendPricing, ref: ModelRef): ModelPrice;
|
|
28
43
|
/**
|
package/dist/pricing.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pricing.d.ts","sourceRoot":"","sources":["../src/pricing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"pricing.d.ts","sourceRoot":"","sources":["../src/pricing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAC1D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAYjE,sDAAsD;AACtD,MAAM,WAAW,UAAU;IACzB,eAAe,EAAE,MAAM,CAAA;IACvB,gBAAgB,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAA;IAChB,wDAAwD;IACxD,YAAY,EAAE,MAAM,CAAA;IACpB,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;IAClC,+EAA+E;IAC/E,YAAY,EAAE,UAAU,CAAA;CACzB;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAoD3D,CAAA;AAED,oEAAoE;AACpE,eAAO,MAAM,yBAAyB,MAAM,CAAA;AAE5C,eAAO,MAAM,qBAAqB,EAAE,YAKnC,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,mBAAmB,EAAE,GAC5B,YAAY,CAWd;AAED,gEAAgE;AAChE,wBAAgB,QAAQ,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,QAAQ,GAAG,UAAU,CAMzE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,YAAY,GACpB,CAAC,GAAG,EAAE,QAAQ,KAAK;IAAE,eAAe,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAS5F;AAED,oEAAoE;AACpE,wBAAgB,YAAY,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,eAAe,GAAG,MAAM,CAMjG;AAED,2EAA2E;AAC3E,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGvD"}
|
package/dist/pricing.js
CHANGED
|
@@ -49,7 +49,6 @@ export const DEFAULT_MODEL_PRICES = {
|
|
|
49
49
|
'openrouter:google/gemini-3-pro': { inputPerMillion: 1.84, outputPerMillion: 11.04 },
|
|
50
50
|
'openrouter:openai/gpt-5.5': { inputPerMillion: 3.68, outputPerMillion: 22.08 },
|
|
51
51
|
'openrouter:deepseek/deepseek-chat': { inputPerMillion: 0.26, outputPerMillion: 1.01 },
|
|
52
|
-
'openrouter:meta-llama/llama-3.3-70b-instruct': { inputPerMillion: 0.12, outputPerMillion: 0.37 },
|
|
53
52
|
openrouter: { inputPerMillion: 1.84, outputPerMillion: 11.04 },
|
|
54
53
|
// LiteLLM — an operator-hosted gateway whose true cost depends entirely on the backend
|
|
55
54
|
// model it routes to, which we can't know here. Default to the generic fallback rate;
|
|
@@ -64,6 +63,33 @@ export const DEFAULT_SPEND_PRICING = {
|
|
|
64
63
|
prices: DEFAULT_MODEL_PRICES,
|
|
65
64
|
defaultPrice: { inputPerMillion: 0.14, outputPerMillion: 0.55 },
|
|
66
65
|
};
|
|
66
|
+
/**
|
|
67
|
+
* Overlay a workspace's dynamic OpenRouter catalog prices onto a base pricing table,
|
|
68
|
+
* keyed by the `openrouter:<slug>` ref so {@link priceFor} resolves each enabled model
|
|
69
|
+
* at its real upstream rate (the prices are already in the spend currency — see
|
|
70
|
+
* `OpenRouterCatalogService`). Used by the per-workspace `/models` cost resolver and the
|
|
71
|
+
* spend gate so budgets meter dynamic models accurately instead of the bare-`openrouter`
|
|
72
|
+
* fallback guess. Returns a new {@link SpendPricing}; the input is not mutated.
|
|
73
|
+
*
|
|
74
|
+
* A model whose cached price is entirely non-positive (OpenRouter reported no pricing, so
|
|
75
|
+
* `parseModels` zeroed it) is SKIPPED rather than overlaid as free: a budget safeguard must
|
|
76
|
+
* never undercount, so such a model keeps the more conservative bare-`openrouter` (or curated)
|
|
77
|
+
* fallback instead of being metered at zero.
|
|
78
|
+
*/
|
|
79
|
+
export function withDynamicPrices(pricing, models) {
|
|
80
|
+
if (models.length === 0)
|
|
81
|
+
return pricing;
|
|
82
|
+
const prices = { ...pricing.prices };
|
|
83
|
+
for (const m of models) {
|
|
84
|
+
if (m.inputPerMillion <= 0 && m.outputPerMillion <= 0)
|
|
85
|
+
continue;
|
|
86
|
+
prices[`openrouter:${m.id}`] = {
|
|
87
|
+
inputPerMillion: m.inputPerMillion,
|
|
88
|
+
outputPerMillion: m.outputPerMillion,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
return { ...pricing, prices };
|
|
92
|
+
}
|
|
67
93
|
/** Resolve the price for a model, most-specific entry first. */
|
|
68
94
|
export function priceFor(pricing, ref) {
|
|
69
95
|
return (pricing.prices[`${ref.provider}:${ref.model}`] ??
|
package/dist/pricing.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pricing.js","sourceRoot":"","sources":["../src/pricing.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pricing.js","sourceRoot":"","sources":["../src/pricing.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/spend",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
|
+
"description": "Pricing tables and spend metering for the Agent Architecture Board.",
|
|
4
5
|
"repository": {
|
|
5
6
|
"type": "git",
|
|
6
7
|
"url": "git+https://github.com/kibertoad/cat-factory.git",
|
|
7
8
|
"directory": "backend/packages/spend"
|
|
8
9
|
},
|
|
9
|
-
"description": "Pricing tables and spend metering for the Agent Architecture Board.",
|
|
10
10
|
"files": [
|
|
11
11
|
"dist"
|
|
12
12
|
],
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
"access": "public"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@cat-factory/contracts": "0.
|
|
28
|
-
"@cat-factory/kernel": "0.
|
|
27
|
+
"@cat-factory/contracts": "0.10.0",
|
|
28
|
+
"@cat-factory/kernel": "0.10.1"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"typescript": "7.0.1-rc"
|