stellarium-ts 0.19.0 → 0.20.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/client/operatorClient.d.ts +34 -3
- package/dist/client/operatorClient.d.ts.map +1 -1
- package/dist/client/operatorClient.js +15 -0
- package/dist/contract/repository.d.ts +49 -0
- package/dist/contract/repository.d.ts.map +1 -0
- package/dist/contract/repository.js +80 -0
- package/dist/contract/service.d.ts +103 -0
- package/dist/contract/service.d.ts.map +1 -0
- package/dist/contract/service.js +297 -0
- package/dist/contract/state.d.ts +43 -0
- package/dist/contract/state.d.ts.map +1 -0
- package/dist/contract/state.js +79 -0
- package/dist/db/database.d.ts +25 -0
- package/dist/db/database.d.ts.map +1 -0
- package/dist/db/database.js +1 -0
- package/dist/db/db.d.ts +12 -4
- package/dist/db/db.d.ts.map +1 -1
- package/dist/db/db.js +97 -24
- package/dist/db/postgres.d.ts +39 -0
- package/dist/db/postgres.d.ts.map +1 -0
- package/dist/db/postgres.js +132 -0
- package/dist/db/sqlite.d.ts +16 -0
- package/dist/db/sqlite.d.ts.map +1 -0
- package/dist/db/sqlite.js +53 -0
- package/dist/grant/repository.d.ts +2 -2
- package/dist/grant/repository.d.ts.map +1 -1
- package/dist/grant/repository.js +2 -2
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/peer/repository.d.ts +2 -2
- package/dist/peer/repository.d.ts.map +1 -1
- package/dist/peer/repository.js +1 -1
- package/dist/resource/invoker.d.ts +85 -0
- package/dist/resource/invoker.d.ts.map +1 -1
- package/dist/resource/invoker.js +69 -6
- package/dist/resource/repository.d.ts +51 -10
- package/dist/resource/repository.d.ts.map +1 -1
- package/dist/resource/repository.js +116 -61
- package/dist/resource/settlement.d.ts +5 -0
- package/dist/resource/settlement.d.ts.map +1 -1
- package/dist/resource/settlement.js +19 -0
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +161 -25
- package/dist/server.d.ts +30 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +80 -5
- package/dist/service.d.ts +27 -2
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +16 -1
- package/dist/startup.d.ts +2 -2
- package/dist/startup.d.ts.map +1 -1
- package/dist/startup.js +43 -34
- package/dist/tests/contract/repository.test.d.ts +2 -0
- package/dist/tests/contract/repository.test.d.ts.map +1 -0
- package/dist/tests/contract/repository.test.js +68 -0
- package/dist/tests/contract/routes.test.d.ts +2 -0
- package/dist/tests/contract/routes.test.d.ts.map +1 -0
- package/dist/tests/contract/routes.test.js +252 -0
- package/dist/tests/contract/state-routes.test.d.ts +2 -0
- package/dist/tests/contract/state-routes.test.d.ts.map +1 -0
- package/dist/tests/contract/state-routes.test.js +158 -0
- package/dist/tests/contract/state.test.d.ts +2 -0
- package/dist/tests/contract/state.test.d.ts.map +1 -0
- package/dist/tests/contract/state.test.js +57 -0
- package/dist/tests/db/db.test.js +1 -1
- package/dist/tests/db/postgres.test.d.ts +2 -0
- package/dist/tests/db/postgres.test.d.ts.map +1 -0
- package/dist/tests/db/postgres.test.js +43 -0
- package/dist/tests/grant/service.test.js +3 -4
- package/dist/tests/helpers.d.ts +8 -0
- package/dist/tests/helpers.d.ts.map +1 -1
- package/dist/tests/helpers.js +37 -0
- package/dist/tests/integration/network.test.js +74 -4
- package/dist/tests/peer/repository.test.js +3 -4
- package/dist/tests/resource/repository.test.js +3 -4
- package/dist/tests/routes.test.js +10 -11
- package/dist/tests/server.test.js +30 -0
- package/dist/tests/startup.test.js +4 -5
- package/package.json +5 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/grant/repository.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/grant/repository.ts"],"names":[],"mappings":"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"}
|
package/dist/grant/repository.js
CHANGED
|
@@ -75,7 +75,7 @@ export class GrantRepository {
|
|
|
75
75
|
/** False when `key` was already claimed. */
|
|
76
76
|
async claimNonce(key, expiresAt) {
|
|
77
77
|
const result = await this.db.run('INSERT INTO seen_nonce (key, expires_at) VALUES (?, ?) ON CONFLICT (key) DO NOTHING', [key, expiresAt]);
|
|
78
|
-
return
|
|
78
|
+
return result.changes > 0;
|
|
79
79
|
}
|
|
80
80
|
async deleteExpiredNonces(now) {
|
|
81
81
|
await this.db.run('DELETE FROM seen_nonce WHERE expires_at <= ?', [now]);
|
|
@@ -87,7 +87,7 @@ export class GrantRepository {
|
|
|
87
87
|
/** False when the key wasn't blocked. */
|
|
88
88
|
async unblock(publicKey) {
|
|
89
89
|
const result = await this.db.run('DELETE FROM blocked_caller WHERE public_key = ?', [publicKey]);
|
|
90
|
-
return
|
|
90
|
+
return result.changes > 0;
|
|
91
91
|
}
|
|
92
92
|
async anyBlocked(publicKeys) {
|
|
93
93
|
if (publicKeys.length === 0) {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export { StellariumNode, resolveConfig, type StellariumNodeOptions } from './server.js';
|
|
2
2
|
export type { NodeConfig } from './service.js';
|
|
3
|
+
export { DEFAULT_DATABASE_PATH, openDatabase, type OpenDatabaseOptions } from './db/db.js';
|
|
4
|
+
export type { DatabaseDialect, NodeDatabase, RunResult } from './db/database.js';
|
|
3
5
|
export type { StellariumFixedPaymentManifest, StellariumInferencePaymentManifest, StellariumResource, StellariumResourceFunction, StellariumResourceFunctionKind, StellariumResourceFunctionParameter, StellariumResourceFunctionPaymentManifest, } from './resource/repository.js';
|
|
4
|
-
export { CombinationResourceInvoker, inferenceVoucherPayload, invocationHash, paymentVoucherPayload, type RunContext, type InferenceEstimate, type InferencePaymentVoucher, type PaymentVoucher, } from './resource/invoker.js';
|
|
6
|
+
export { CombinationResourceInvoker, contractVoucherPayload, inferenceVoucherPayload, invocationHash, paymentVoucherPayload, type RunContext, type ContractPaymentVoucher, type InferenceEstimate, type InferencePaymentVoucher, type PaymentVoucher, } from './resource/invoker.js';
|
|
5
7
|
export { inferenceCharge, MAX_TOKENS_PARAMETER, type InferenceResult, type InferenceUsage } from './resource/inference.js';
|
|
6
8
|
export type { FixedPaymentVoucher, InferencePaymentSubmission, InferenceVoucher, PaymentSubmission, RunAuthorizationRequest } from './client/operatorClient.js';
|
|
7
9
|
export { RUN_TOKEN_ISSUER, RunTokenVerifier, type RunTokenClaims } from './client/runTokens.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,KAAK,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACxF,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,YAAY,EACR,8BAA8B,EAC9B,kCAAkC,EAClC,kBAAkB,EAClB,0BAA0B,EAC1B,8BAA8B,EAC9B,mCAAmC,EACnC,yCAAyC,GAC5C,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACH,0BAA0B,EAC1B,uBAAuB,EACvB,cAAc,EACd,qBAAqB,EACrB,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,EAC5B,KAAK,cAAc,GACtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC3H,YAAY,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAEhK,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEhG,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAE/G,OAAO,EACH,SAAS,EACT,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,UAAU,EACV,uBAAuB,EACvB,8BAA8B,EAC9B,6BAA6B,EAC7B,sBAAsB,EACtB,qBAAqB,EACrB,KAAK,UAAU,EACf,KAAK,KAAK,EACV,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,uBAAuB,GAC/B,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACpF,YAAY,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,KAAK,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACxF,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAC3F,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACjF,YAAY,EACR,8BAA8B,EAC9B,kCAAkC,EAClC,kBAAkB,EAClB,0BAA0B,EAC1B,8BAA8B,EAC9B,mCAAmC,EACnC,yCAAyC,GAC5C,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACH,0BAA0B,EAC1B,sBAAsB,EACtB,uBAAuB,EACvB,cAAc,EACd,qBAAqB,EACrB,KAAK,UAAU,EACf,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,EAC5B,KAAK,cAAc,GACtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC3H,YAAY,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAEhK,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEhG,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAE/G,OAAO,EACH,SAAS,EACT,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,UAAU,EACV,uBAAuB,EACvB,8BAA8B,EAC9B,6BAA6B,EAC7B,sBAAsB,EACtB,qBAAqB,EACrB,KAAK,UAAU,EACf,KAAK,KAAK,EACV,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,uBAAuB,GAC/B,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACpF,YAAY,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { StellariumNode, resolveConfig } from './server.js';
|
|
2
|
+
export { DEFAULT_DATABASE_PATH, openDatabase } from './db/db.js';
|
|
2
3
|
// The voucher wire format, so the operator and other settlers can test against the real signer.
|
|
3
|
-
export { CombinationResourceInvoker, inferenceVoucherPayload, invocationHash, paymentVoucherPayload, } from './resource/invoker.js';
|
|
4
|
+
export { CombinationResourceInvoker, contractVoucherPayload, inferenceVoucherPayload, invocationHash, paymentVoucherPayload, } from './resource/invoker.js';
|
|
4
5
|
export { inferenceCharge, MAX_TOKENS_PARAMETER } from './resource/inference.js';
|
|
5
6
|
// Run token verification, so the operator can test its tokens against the real verifier.
|
|
6
7
|
export { RUN_TOKEN_ISSUER, RunTokenVerifier } from './client/runTokens.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { NodeDatabase } from "../db/database.js";
|
|
2
2
|
export interface Peer {
|
|
3
3
|
baseUrl: string;
|
|
4
4
|
name: string;
|
|
@@ -21,7 +21,7 @@ export declare function peerAnnouncementPayload(peer: Peer, expiry: string): {
|
|
|
21
21
|
};
|
|
22
22
|
export declare class PeerRepository {
|
|
23
23
|
private readonly db;
|
|
24
|
-
constructor(db:
|
|
24
|
+
constructor(db: NodeDatabase);
|
|
25
25
|
/**
|
|
26
26
|
* Saves a peer learned from a trusted source (the starting peer) without a signature.
|
|
27
27
|
* Does nothing if a peer with the same public key, base URL or name already exists.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/peer/repository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/peer/repository.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,WAAW,IAAI;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAW,SAAQ,IAAI;IACpC,EAAE,EAAE,MAAM,CAAC;CACd;AAED,sCAAsC;AACtC,MAAM,MAAM,qBAAqB,GAAG,mBAAmB,GAAG,UAAU,CAAC;AAErE;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM;;;;;EAGjE;AAaD,qBAAa,cAAc;IACX,OAAO,CAAC,QAAQ,CAAC,EAAE;IAA/B,YAA6B,EAAE,EAAE,YAAY,EAAI;IAEjD;;;OAGG;IACG,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAMtC;IAED;;;;OAIG;IACG,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,IAAI,CAAA;KAAE,GAAG;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,qBAAqB,CAAA;KAAE,CAAC,CAoBjI;IAEK,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAE/B;IAEK,WAAW,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,CAQnC;IAED,uFAAuF;IACjF,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAQ7D;IAEK,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAG3E;CACJ"}
|
package/dist/peer/repository.js
CHANGED
|
@@ -21,7 +21,7 @@ export class PeerRepository {
|
|
|
21
21
|
*/
|
|
22
22
|
async create(peer) {
|
|
23
23
|
const createdAt = new Date().toISOString();
|
|
24
|
-
await this.db.run('INSERT
|
|
24
|
+
await this.db.run('INSERT INTO peer (base_url, name, public_key, created_at, updated_at) VALUES (?, ?, ?, ?, ?) ON CONFLICT DO NOTHING', [peer.baseUrl, peer.name, peer.publicKey, createdAt, createdAt]);
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
27
|
* Saves a peer that announced itself. The announcement must be signed by `peer.publicKey`.
|
|
@@ -3,6 +3,7 @@ import type { OperatorClient } from "../client/operatorClient.js";
|
|
|
3
3
|
import type { GrantService } from "../grant/service.js";
|
|
4
4
|
import { type InferenceUsage } from "./inference.js";
|
|
5
5
|
import { ResourceRepository, type StellariumInferencePaymentManifest } from "./repository.js";
|
|
6
|
+
import { type InvokeResult } from "./settlement.js";
|
|
6
7
|
export interface PaymentVoucher {
|
|
7
8
|
requestId: string;
|
|
8
9
|
invocationId: string;
|
|
@@ -36,6 +37,25 @@ export interface InferencePaymentVoucher {
|
|
|
36
37
|
/** Set for a call made by a script run billed to an API client: the run's hold pays instead of this node's organization. */
|
|
37
38
|
runId?: string;
|
|
38
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* A voucher for a call to a contract on another node. It signs the provider's price per million tokens and
|
|
42
|
+
* the most the caller will pay, `maxAmount`: the provider authorizes a run with it, which holds up to
|
|
43
|
+
* `maxAmount` for the contract's tokens and for the paid calls the contract makes.
|
|
44
|
+
*/
|
|
45
|
+
export interface ContractPaymentVoucher {
|
|
46
|
+
kind: 'contract';
|
|
47
|
+
requestId: string;
|
|
48
|
+
invocationId: string;
|
|
49
|
+
maxAmount: number;
|
|
50
|
+
priceMicroUsdPerMillionTokens: number;
|
|
51
|
+
recipientOrganizationId: string;
|
|
52
|
+
signature: string;
|
|
53
|
+
expiresAt: string;
|
|
54
|
+
invocationHash: string;
|
|
55
|
+
publicKey: string;
|
|
56
|
+
/** Set for a call made by a billed run: that run's hold pays, and the contract's run is held from it. */
|
|
57
|
+
runId?: string;
|
|
58
|
+
}
|
|
39
59
|
/** What a provider's `POST /v1/run/resource/estimate` answers. */
|
|
40
60
|
export interface InferenceEstimate {
|
|
41
61
|
inputTokens: number;
|
|
@@ -79,10 +99,29 @@ export declare function inferenceVoucherPayload(voucher: Omit<InferencePaymentVo
|
|
|
79
99
|
invocationHash: string;
|
|
80
100
|
publicKey: string;
|
|
81
101
|
};
|
|
102
|
+
/**
|
|
103
|
+
* The object `createContractVoucher` signs: every contract voucher field except `signature`.
|
|
104
|
+
* Key order is part of the signed bytes.
|
|
105
|
+
*/
|
|
106
|
+
export declare function contractVoucherPayload(voucher: Omit<ContractPaymentVoucher, "signature">): {
|
|
107
|
+
runId?: string;
|
|
108
|
+
kind: "contract";
|
|
109
|
+
requestId: string;
|
|
110
|
+
invocationId: string;
|
|
111
|
+
maxAmount: number;
|
|
112
|
+
priceMicroUsdPerMillionTokens: number;
|
|
113
|
+
recipientOrganizationId: string;
|
|
114
|
+
expiresAt: string;
|
|
115
|
+
invocationHash: string;
|
|
116
|
+
publicKey: string;
|
|
117
|
+
};
|
|
118
|
+
export declare function isContractVoucher(voucher: unknown): voucher is ContractPaymentVoucher;
|
|
82
119
|
export declare function isInferenceVoucher(voucher: PaymentVoucher | InferencePaymentVoucher): voucher is InferencePaymentVoucher;
|
|
83
120
|
export declare const PAYMENT_VOUCHER_LIFETIME_MS: number;
|
|
84
121
|
/** Inference can run for minutes, and the operator refuses a voucher that expired before the provider settled it. */
|
|
85
122
|
export declare const INFERENCE_VOUCHER_LIFETIME_MS: number;
|
|
123
|
+
/** A contract may make inference calls of its own. */
|
|
124
|
+
export declare const CONTRACT_VOUCHER_LIFETIME_MS: number;
|
|
86
125
|
export declare const EXTERNAL_INVOKE_MAX_RETRIES = 3;
|
|
87
126
|
export declare const EXTERNAL_INVOKE_BASE_DELAY_MS = 500;
|
|
88
127
|
/** Per attempt. A timed-out attempt is retried like a network error. */
|
|
@@ -93,6 +132,43 @@ export declare const INFERENCE_INVOKE_TIMEOUT_MS = 120000;
|
|
|
93
132
|
export interface RunContext {
|
|
94
133
|
runId: string;
|
|
95
134
|
}
|
|
135
|
+
/** Who a contract is running for, which it reads as the built-in `caller`. */
|
|
136
|
+
export interface CallerIdentity {
|
|
137
|
+
/** The organization paying for the call, or null when that isn't known (a node not enrolled in one). */
|
|
138
|
+
org: string | null;
|
|
139
|
+
/** The public key of the node that made the call. */
|
|
140
|
+
node: string;
|
|
141
|
+
}
|
|
142
|
+
/** The script, request or contract, that calls are made from. */
|
|
143
|
+
export interface ScriptContext {
|
|
144
|
+
/** A billed run's id: the run's hold pays the script's paid calls. */
|
|
145
|
+
runId?: string;
|
|
146
|
+
/** What the script reads as `jwt`, which contracts it calls on this node read too. Null when absent. */
|
|
147
|
+
jwt?: unknown;
|
|
148
|
+
/** How many contracts deep the script is: 0 for a request script. */
|
|
149
|
+
depth?: number;
|
|
150
|
+
/** Who the script runs for. Contracts it calls on this node see it as `caller`. */
|
|
151
|
+
caller?: CallerIdentity;
|
|
152
|
+
/** The contracts (`path.Name`) this script runs inside on this node, outermost first. */
|
|
153
|
+
contracts?: string[];
|
|
154
|
+
}
|
|
155
|
+
/** Contracts may call each other, so each call goes one deeper, and a call past this depth fails. */
|
|
156
|
+
export declare const MAX_CONTRACT_DEPTH = 8;
|
|
157
|
+
/** Runs the contracts deployed to this node, for scripts on this node. */
|
|
158
|
+
export interface ContractHost {
|
|
159
|
+
/**
|
|
160
|
+
* Runs the contract served as `resource`, one level deeper than `context`. A billed script's call is held
|
|
161
|
+
* from its run's hold, as a call from another node is held from the caller's balance.
|
|
162
|
+
*/
|
|
163
|
+
invokeLocal(resource: Resource, parameters: ResourceFunctionCallParameter[], context: ScriptContext): Promise<InvokeResult>;
|
|
164
|
+
}
|
|
165
|
+
/** How this node calls contracts. */
|
|
166
|
+
export interface ContractInvocation {
|
|
167
|
+
/** The most a call to a contract on another node may hold: its voucher's `maxAmount`. */
|
|
168
|
+
costLimitMicroUsd: number;
|
|
169
|
+
/** Runs contracts on this node. Without one, calls to them fail. */
|
|
170
|
+
host?: ContractHost;
|
|
171
|
+
}
|
|
96
172
|
/** How a node settles its own paid functions when a billed run calls them. */
|
|
97
173
|
export interface LocalSettlement {
|
|
98
174
|
operatorClient: OperatorClient;
|
|
@@ -113,12 +189,19 @@ export declare class CombinationResourceInvoker implements ResourceInvoker {
|
|
|
113
189
|
* Without `localSettlement`, a billed run can't call this node's own paid functions.
|
|
114
190
|
*/
|
|
115
191
|
constructor(resourceRepository: ResourceRepository, costLimitMicroUsd: number, publicKey: string, privateKey: string, grantService?: GrantService | undefined, inferenceCostLimitMicroUsd?: number, localSettlement?: LocalSettlement | undefined);
|
|
192
|
+
/** Set once the node's contract host exists, since the host calls back into this invoker. */
|
|
193
|
+
contracts?: ContractInvocation;
|
|
116
194
|
/**
|
|
117
195
|
* An invoker for one billed run. Its paid calls, remote or to this node's own paid functions, carry
|
|
118
196
|
* the run's id, so the run's hold pays for them. The run's hold limits what they cost, in place of the
|
|
119
197
|
* cost limits.
|
|
120
198
|
*/
|
|
121
199
|
forRun(run: RunContext): ResourceInvoker;
|
|
200
|
+
/**
|
|
201
|
+
* An invoker for one script. With a `runId`, its paid calls are billed to the run as `forRun`'s are.
|
|
202
|
+
* Contracts it calls on this node see its `jwt`.
|
|
203
|
+
*/
|
|
204
|
+
forScript(context: ScriptContext): ResourceInvoker;
|
|
122
205
|
/**
|
|
123
206
|
* Invoke a function on a resource.
|
|
124
207
|
* If the resource has a baseUrl, it will be invoked as a remote function.
|
|
@@ -152,5 +235,7 @@ export declare class CombinationResourceInvoker implements ResourceInvoker {
|
|
|
152
235
|
createPaymentVoucher(recipientOrganizationId: string, amount: number, resourcePath: string, resourceName: string, functionName: string, parameters: ResourceFunctionCallParameter[], runId?: string): PaymentVoucher;
|
|
153
236
|
/** With `runId`, the voucher is paid from that run's hold. */
|
|
154
237
|
createInferenceVoucher(manifest: StellariumInferencePaymentManifest, maxAmount: number, maxTokens: number, resourcePath: string, resourceName: string, functionName: string, parameters: ResourceFunctionCallParameter[], runId?: string): InferencePaymentVoucher;
|
|
238
|
+
/** With `runId`, the run's hold pays, and the contract's run is held from it. */
|
|
239
|
+
createContractVoucher(recipientOrganizationId: string, priceMicroUsdPerMillionTokens: number, maxAmount: number, resourcePath: string, resourceName: string, functionName: string, parameters: ResourceFunctionCallParameter[], runId?: string): ContractPaymentVoucher;
|
|
155
240
|
}
|
|
156
241
|
//# sourceMappingURL=invoker.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"invoker.d.ts","sourceRoot":"","sources":["../../src/resource/invoker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,6BAA6B,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACzF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAwC,KAAK,cAAc,EAAkF,MAAM,gBAAgB,CAAC;AAC3K,OAAO,
|
|
1
|
+
{"version":3,"file":"invoker.d.ts","sourceRoot":"","sources":["../../src/resource/invoker.ts"],"names":[],"mappings":"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"}
|
package/dist/resource/invoker.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { hashData, signData } from "../crypto/utils.js";
|
|
2
2
|
import { estimateInputTokens, inferenceCharge, isInferenceFunction, isInferenceManifest, parseInferenceResult, parseMaxTokens } from "./inference.js";
|
|
3
|
+
import { isContractFunction, isContractManifest } from "./repository.js";
|
|
3
4
|
import { settlePaidCall } from "./settlement.js";
|
|
4
5
|
/**
|
|
5
6
|
* Hash binding a voucher to one function call. Providers recompute it from the
|
|
@@ -29,12 +30,25 @@ export function inferenceVoucherPayload(voucher) {
|
|
|
29
30
|
const { kind, requestId, invocationId, maxAmount, inputCostMicroUsdPerMillionTokens, outputCostMicroUsdPerMillionTokens, maxTokens, recipientOrganizationId, expiresAt, invocationHash, publicKey } = voucher;
|
|
30
31
|
return { kind, requestId, invocationId, maxAmount, inputCostMicroUsdPerMillionTokens, outputCostMicroUsdPerMillionTokens, maxTokens, recipientOrganizationId, expiresAt, invocationHash, publicKey, ...runPayload(voucher.runId) };
|
|
31
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* The object `createContractVoucher` signs: every contract voucher field except `signature`.
|
|
35
|
+
* Key order is part of the signed bytes.
|
|
36
|
+
*/
|
|
37
|
+
export function contractVoucherPayload(voucher) {
|
|
38
|
+
const { kind, requestId, invocationId, maxAmount, priceMicroUsdPerMillionTokens, recipientOrganizationId, expiresAt, invocationHash, publicKey } = voucher;
|
|
39
|
+
return { kind, requestId, invocationId, maxAmount, priceMicroUsdPerMillionTokens, recipientOrganizationId, expiresAt, invocationHash, publicKey, ...runPayload(voucher.runId) };
|
|
40
|
+
}
|
|
41
|
+
export function isContractVoucher(voucher) {
|
|
42
|
+
return voucher?.kind === 'contract';
|
|
43
|
+
}
|
|
32
44
|
export function isInferenceVoucher(voucher) {
|
|
33
45
|
return voucher.kind === 'inference';
|
|
34
46
|
}
|
|
35
47
|
export const PAYMENT_VOUCHER_LIFETIME_MS = 1000 * 60 * 2;
|
|
36
48
|
/** Inference can run for minutes, and the operator refuses a voucher that expired before the provider settled it. */
|
|
37
49
|
export const INFERENCE_VOUCHER_LIFETIME_MS = 1000 * 60 * 10;
|
|
50
|
+
/** A contract may make inference calls of its own. */
|
|
51
|
+
export const CONTRACT_VOUCHER_LIFETIME_MS = INFERENCE_VOUCHER_LIFETIME_MS;
|
|
38
52
|
export const EXTERNAL_INVOKE_MAX_RETRIES = 3;
|
|
39
53
|
export const EXTERNAL_INVOKE_BASE_DELAY_MS = 500;
|
|
40
54
|
/** Per attempt. A timed-out attempt is retried like a network error. */
|
|
@@ -66,6 +80,8 @@ async function fetchWithRetry(url, init, timeoutMs = EXTERNAL_INVOKE_TIMEOUT_MS)
|
|
|
66
80
|
await new Promise(resolve => setTimeout(resolve, EXTERNAL_INVOKE_BASE_DELAY_MS * 2 ** attempt));
|
|
67
81
|
}
|
|
68
82
|
}
|
|
83
|
+
/** Contracts may call each other, so each call goes one deeper, and a call past this depth fails. */
|
|
84
|
+
export const MAX_CONTRACT_DEPTH = 8;
|
|
69
85
|
export class CombinationResourceInvoker {
|
|
70
86
|
resourceRepository;
|
|
71
87
|
costLimitMicroUsd;
|
|
@@ -88,13 +104,22 @@ export class CombinationResourceInvoker {
|
|
|
88
104
|
this.inferenceCostLimitMicroUsd = inferenceCostLimitMicroUsd;
|
|
89
105
|
this.localSettlement = localSettlement;
|
|
90
106
|
}
|
|
107
|
+
/** Set once the node's contract host exists, since the host calls back into this invoker. */
|
|
108
|
+
contracts;
|
|
91
109
|
/**
|
|
92
110
|
* An invoker for one billed run. Its paid calls, remote or to this node's own paid functions, carry
|
|
93
111
|
* the run's id, so the run's hold pays for them. The run's hold limits what they cost, in place of the
|
|
94
112
|
* cost limits.
|
|
95
113
|
*/
|
|
96
114
|
forRun(run) {
|
|
97
|
-
return
|
|
115
|
+
return this.forScript(run);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* An invoker for one script. With a `runId`, its paid calls are billed to the run as `forRun`'s are.
|
|
119
|
+
* Contracts it calls on this node see its `jwt`.
|
|
120
|
+
*/
|
|
121
|
+
forScript(context) {
|
|
122
|
+
return { invoke: (resource, functionName, parameters) => this.invokeIn(resource, functionName, parameters, context) };
|
|
98
123
|
}
|
|
99
124
|
/**
|
|
100
125
|
* Invoke a function on a resource.
|
|
@@ -112,7 +137,9 @@ export class CombinationResourceInvoker {
|
|
|
112
137
|
async invoke(resource, functionName, parameters) {
|
|
113
138
|
return this.invokeIn(resource, functionName, parameters, undefined);
|
|
114
139
|
}
|
|
115
|
-
async invokeIn(resource, functionName, parameters,
|
|
140
|
+
async invokeIn(resource, functionName, parameters, context) {
|
|
141
|
+
// Only a billed run has a run id. Its hold limits what its calls cost, in place of the cost limits.
|
|
142
|
+
const run = context?.runId === undefined ? undefined : { runId: context.runId };
|
|
116
143
|
if (resource.metadata.baseUrl) {
|
|
117
144
|
let requestBody = {
|
|
118
145
|
resourcePath: resource.path,
|
|
@@ -136,10 +163,24 @@ export class CombinationResourceInvoker {
|
|
|
136
163
|
}
|
|
137
164
|
const manifest = resourceFunction.paymentManifest;
|
|
138
165
|
const inference = isInferenceFunction(resourceFunction);
|
|
166
|
+
const contract = isContractFunction(resourceFunction);
|
|
139
167
|
if (manifest && !manifest.recipientOrganizationId) {
|
|
140
168
|
return { value: null, error: { message: `Failed to invoke ${resource.name}.${functionName}: its payment manifest names no recipient organization` } };
|
|
141
169
|
}
|
|
142
|
-
if (
|
|
170
|
+
if (contract) {
|
|
171
|
+
// A contract may make paid calls of its own, so a call always carries a voucher, even at a price of 0.
|
|
172
|
+
if (!manifest || !isContractManifest(manifest) || !Number.isSafeInteger(manifest.priceMicroUsdPerMillionTokens) || manifest.priceMicroUsdPerMillionTokens < 0) {
|
|
173
|
+
return { value: null, error: { message: `Failed to invoke ${resource.name}.${functionName}: it is a contract without a valid price` } };
|
|
174
|
+
}
|
|
175
|
+
const depth = (context?.depth ?? 0) + 1;
|
|
176
|
+
if (depth > MAX_CONTRACT_DEPTH) {
|
|
177
|
+
return { value: null, error: { message: `Failed to invoke ${resource.name}.${functionName}: contracts may call each other at most ${MAX_CONTRACT_DEPTH} deep` } };
|
|
178
|
+
}
|
|
179
|
+
const costLimit = this.contracts?.costLimitMicroUsd ?? this.costLimitMicroUsd;
|
|
180
|
+
requestBody.paymentVoucher = this.createContractVoucher(manifest.recipientOrganizationId, manifest.priceMicroUsdPerMillionTokens, costLimit, resource.path, resource.name, functionName, parameters, run?.runId);
|
|
181
|
+
requestBody.contractDepth = depth;
|
|
182
|
+
}
|
|
183
|
+
else if (manifest && inference) {
|
|
143
184
|
console.log(`Resource function ${resource.name}.${functionName} is a paid inference function, creating payment voucher...`);
|
|
144
185
|
// Peers' manifests aren't validated on receipt.
|
|
145
186
|
if (!isInferenceManifest(manifest) || !Number.isSafeInteger(manifest.inputCostMicroUsdPerMillionTokens) || manifest.inputCostMicroUsdPerMillionTokens < 0
|
|
@@ -165,7 +206,7 @@ export class CombinationResourceInvoker {
|
|
|
165
206
|
}
|
|
166
207
|
else if (manifest) {
|
|
167
208
|
console.log(`Resource function ${resource.name}.${functionName} has a payment manifest, creating payment voucher...`);
|
|
168
|
-
if (isInferenceManifest(manifest)) {
|
|
209
|
+
if (isInferenceManifest(manifest) || isContractManifest(manifest)) {
|
|
169
210
|
return { value: null, error: { message: `Failed to invoke ${resource.name}.${functionName}: it has per-token pricing but isn't an inference function` } };
|
|
170
211
|
}
|
|
171
212
|
if (!run && manifest.costMicroUsd > this.costLimitMicroUsd) {
|
|
@@ -182,7 +223,7 @@ export class CombinationResourceInvoker {
|
|
|
182
223
|
headers: {
|
|
183
224
|
'Content-Type': 'application/json',
|
|
184
225
|
},
|
|
185
|
-
}), inference ? INFERENCE_INVOKE_TIMEOUT_MS : EXTERNAL_INVOKE_TIMEOUT_MS);
|
|
226
|
+
}), inference || contract ? INFERENCE_INVOKE_TIMEOUT_MS : EXTERNAL_INVOKE_TIMEOUT_MS);
|
|
186
227
|
if (!result.ok) {
|
|
187
228
|
// The provider's JSON error is more useful than the status text, which can be empty.
|
|
188
229
|
const detail = await result.json().then((body) => body?.error, () => undefined);
|
|
@@ -197,6 +238,12 @@ export class CombinationResourceInvoker {
|
|
|
197
238
|
if (!fn) {
|
|
198
239
|
return { value: null, error: { message: `Function ${functionName} not found in resource ${resource.name}` } };
|
|
199
240
|
}
|
|
241
|
+
if (isContractFunction(fn)) {
|
|
242
|
+
if (!this.contracts?.host) {
|
|
243
|
+
return { value: null, error: { message: `Failed to invoke ${resource.name}.${fn.name}: this node doesn't run contracts` } };
|
|
244
|
+
}
|
|
245
|
+
return this.contracts.host.invokeLocal(resource, parameters, context ?? {});
|
|
246
|
+
}
|
|
200
247
|
// A billed run pays for this node's own paid functions as a remote caller would.
|
|
201
248
|
if (run && fn.paymentManifest) {
|
|
202
249
|
return this.invokeLocalPaid(resource, fn, parameters, run);
|
|
@@ -239,7 +286,7 @@ export class CombinationResourceInvoker {
|
|
|
239
286
|
const maxAmount = inferenceCharge(manifest, inputTokens, maxTokens);
|
|
240
287
|
voucher = this.createInferenceVoucher({ ...manifest, recipientOrganizationId: organizationId }, maxAmount, maxTokens, resource.path, resource.name, fn.name, parameters, run.runId);
|
|
241
288
|
}
|
|
242
|
-
else if (!isInferenceManifest(manifest)) {
|
|
289
|
+
else if (!isInferenceManifest(manifest) && !isContractManifest(manifest)) {
|
|
243
290
|
voucher = this.createPaymentVoucher(organizationId, manifest.costMicroUsd, resource.path, resource.name, fn.name, parameters, run.runId);
|
|
244
291
|
}
|
|
245
292
|
else {
|
|
@@ -304,4 +351,20 @@ export class CombinationResourceInvoker {
|
|
|
304
351
|
};
|
|
305
352
|
return { ...unsigned, signature: signData(inferenceVoucherPayload(unsigned), this.privateKey) };
|
|
306
353
|
}
|
|
354
|
+
/** With `runId`, the run's hold pays, and the contract's run is held from it. */
|
|
355
|
+
createContractVoucher(recipientOrganizationId, priceMicroUsdPerMillionTokens, maxAmount, resourcePath, resourceName, functionName, parameters, runId) {
|
|
356
|
+
const unsigned = {
|
|
357
|
+
kind: 'contract',
|
|
358
|
+
requestId: crypto.randomUUID(),
|
|
359
|
+
invocationId: crypto.randomUUID(),
|
|
360
|
+
maxAmount,
|
|
361
|
+
priceMicroUsdPerMillionTokens,
|
|
362
|
+
recipientOrganizationId,
|
|
363
|
+
expiresAt: new Date(Date.now() + CONTRACT_VOUCHER_LIFETIME_MS).toISOString(),
|
|
364
|
+
invocationHash: invocationHash(resourcePath, resourceName, functionName, parameters),
|
|
365
|
+
publicKey: this.publicKey,
|
|
366
|
+
...runPayload(runId),
|
|
367
|
+
};
|
|
368
|
+
return { ...unsigned, signature: signData(contractVoucherPayload(unsigned), this.privateKey) };
|
|
369
|
+
}
|
|
307
370
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Resource, ResourceFunction, ResourceFunctionCallParameter, ResourceFunctionParameter } from "requestscript";
|
|
2
|
-
import {
|
|
2
|
+
import type { NodeDatabase } from "../db/database.js";
|
|
3
|
+
import type { ContractRepository, StoredContract } from "../contract/repository.js";
|
|
3
4
|
import type { StoredPeer } from "../peer/repository.js";
|
|
4
5
|
/**
|
|
5
6
|
* A flat price per call. `recipientOrganizationId` is filled in by the hosting node when it advertises
|
|
@@ -17,9 +18,35 @@ export interface StellariumInferencePaymentManifest {
|
|
|
17
18
|
outputCostMicroUsdPerMillionTokens: number;
|
|
18
19
|
recipientOrganizationId?: string;
|
|
19
20
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
/**
|
|
22
|
+
* A contract's price: the hosting node's listed price per million tokens the contract executes. A call is
|
|
23
|
+
* paid with a contract voucher, which also pays for the paid calls the contract makes.
|
|
24
|
+
*/
|
|
25
|
+
export interface StellariumContractPaymentManifest {
|
|
26
|
+
id?: number;
|
|
27
|
+
priceMicroUsdPerMillionTokens: number;
|
|
28
|
+
recipientOrganizationId?: string;
|
|
29
|
+
}
|
|
30
|
+
export type StellariumResourceFunctionPaymentManifest = StellariumFixedPaymentManifest | StellariumInferencePaymentManifest | StellariumContractPaymentManifest;
|
|
31
|
+
/**
|
|
32
|
+
* Fixed functions return one value. Inference functions run AI inference and are priced per token.
|
|
33
|
+
* Contract functions run a contract deployed to the node, and are priced per token it executes.
|
|
34
|
+
*/
|
|
35
|
+
export type StellariumResourceFunctionKind = 'fixed' | 'inference' | 'contract';
|
|
36
|
+
/** The one function a contract's resource has. It runs the contract's latest version. */
|
|
37
|
+
export declare const CONTRACT_FUNCTION = "run";
|
|
38
|
+
export declare function isContractManifest(manifest: StellariumResourceFunctionPaymentManifest | undefined): manifest is StellariumContractPaymentManifest;
|
|
39
|
+
export declare function isContractFunction(fn: Pick<StellariumResourceFunction, 'kind'>): boolean;
|
|
40
|
+
/** The resource a contract is served as. Its function always has a manifest, so every call needs a voucher. */
|
|
41
|
+
export declare function contractResource(contract: StoredContract, baseUrl: string, priceMicroUsdPerMillionTokens: number, recipientOrganizationId?: string): StellariumResource;
|
|
42
|
+
/** Where a `ResourceRepository` finds this node's contracts, and what it charges for them. */
|
|
43
|
+
export interface ContractSource {
|
|
44
|
+
repository: ContractRepository;
|
|
45
|
+
/** This node's listed price per million tokens. */
|
|
46
|
+
price: () => number;
|
|
47
|
+
/** This node's organization, which is paid for contract calls. It may be learned after the node starts. */
|
|
48
|
+
organizationId: () => string | undefined;
|
|
49
|
+
}
|
|
23
50
|
export interface StellariumResourceFunctionParameter extends ResourceFunctionParameter {
|
|
24
51
|
description?: string;
|
|
25
52
|
}
|
|
@@ -65,12 +92,23 @@ export declare class ResourceRepository {
|
|
|
65
92
|
private resources;
|
|
66
93
|
private readonly baseUrl;
|
|
67
94
|
private readonly organizationId?;
|
|
68
|
-
private
|
|
69
|
-
/**
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
95
|
+
private readonly contracts?;
|
|
96
|
+
/**
|
|
97
|
+
* `organizationId` is the operator organization this node is enrolled in, which is paid for its functions.
|
|
98
|
+
* The contracts deployed to the node are its resources too, after the registered ones.
|
|
99
|
+
*/
|
|
100
|
+
constructor(db: NodeDatabase, resources?: StellariumResource[], baseUrl?: string, organizationId?: string | undefined, contracts?: ContractSource | undefined);
|
|
101
|
+
/** A resource registered on this node. */
|
|
102
|
+
isRegistered(resource: {
|
|
103
|
+
path: string;
|
|
104
|
+
name: string;
|
|
105
|
+
}): boolean;
|
|
106
|
+
/** A resource this node hosts: registered, or a contract deployed to it. */
|
|
73
107
|
private isInternal;
|
|
108
|
+
/** A resource learned from a peer. */
|
|
109
|
+
isLearned(path: string, name: string): Promise<boolean>;
|
|
110
|
+
private contractResources;
|
|
111
|
+
private contractResource;
|
|
74
112
|
/**
|
|
75
113
|
* Saves a resource learned from the starting peer, if it isn't known yet. Resources hosted
|
|
76
114
|
* by this node and resources already known are left alone, so startup can run on every boot.
|
|
@@ -89,7 +127,10 @@ export declare class ResourceRepository {
|
|
|
89
127
|
private deleteFunctions;
|
|
90
128
|
getInternalResource(path: string, name: string): Promise<StellariumResource | undefined>;
|
|
91
129
|
getResource(key: string): Promise<Resource | undefined>;
|
|
92
|
-
/**
|
|
130
|
+
/**
|
|
131
|
+
* This node's resources, with its base URL and its organization as the recipient of every paid function:
|
|
132
|
+
* the registered ones, then its contracts by path and name.
|
|
133
|
+
*/
|
|
93
134
|
getInternalResources(): Promise<StellariumResource[]>;
|
|
94
135
|
/** Learned resources in insertion order. A negative `limit` means no limit. */
|
|
95
136
|
getExternalResources(offset?: number, limit?: number): Promise<StellariumResource[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/resource/repository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,6BAA6B,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AACrH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/resource/repository.ts"],"names":[],"mappings":"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"}
|