@greenlandai/sdk 0.1.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/LICENSE +208 -0
- package/README.md +54 -0
- package/dist/index.cjs +1011 -0
- package/index.js +40 -0
- package/package.json +33 -0
- package/src/core/crypto.js +301 -0
- package/src/core/errors.js +33 -0
- package/src/core/idempotency.js +83 -0
- package/src/core/transport.js +124 -0
- package/src/enyal.js +165 -0
- package/src/gldai.js +40 -0
- package/src/joulepai.js +116 -0
- package/src/rareeai.js +66 -0
package/src/enyal.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/** client.enyal — full 2.1.0 surface migrated (design §4.1). Citations in JSDoc
|
|
2
|
+
* are package-root-relative to published artifacts. */
|
|
3
|
+
import * as cryptoNs from "./core/crypto.js";
|
|
4
|
+
|
|
5
|
+
export const ENYAL_BASE = "https://api.enyal.ai";
|
|
6
|
+
|
|
7
|
+
export class EnyalSubmodule {
|
|
8
|
+
constructor(transport, baseUrl = ENYAL_BASE) {
|
|
9
|
+
this._t = transport;
|
|
10
|
+
this._base = baseUrl;
|
|
11
|
+
this.crypto = cryptoNs; // pure functions incl. deriveSharesFromMnemonic, shamir, node decrypt
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// ── class A (ENFORCED) ──
|
|
15
|
+
/** 2.1.0: enyal-client.js:444. */
|
|
16
|
+
archive({ agentId, chunkType, chunkKey, data, metadata, proofTier, idempotencyKey, retry = true }) {
|
|
17
|
+
if (typeof data !== "string") data = JSON.stringify(data);
|
|
18
|
+
const body = { agent_id: agentId, chunk_type: chunkType, chunk_key: chunkKey,
|
|
19
|
+
data: Buffer.from(data).toString("base64") };
|
|
20
|
+
if (metadata) body.metadata = metadata;
|
|
21
|
+
if (proofTier) body.proof_tier = proofTier;
|
|
22
|
+
return this._t.request(this._base, "POST", "/api/v1/archive", { body, idempotencyKey, retry });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** 2.1.0: enyal-client.js:499. ENFORCED (G1: trust_routes.py:123-138). */
|
|
26
|
+
timestamp({ payload, description, idempotencyKey, retry = true }) {
|
|
27
|
+
if (typeof payload !== "string") payload = JSON.stringify(payload);
|
|
28
|
+
const body = { payload };
|
|
29
|
+
if (description) body.description = description;
|
|
30
|
+
return this._t.request(this._base, "POST", "/api/v1/timestamp", { body, idempotencyKey, retry });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** ENFORCED (G1: trust_routes.py:223-238). */
|
|
34
|
+
createAgreement({ terms, parties, title, idempotencyKey, retry = true }) {
|
|
35
|
+
const body = { terms, parties };
|
|
36
|
+
if (title) body.title = title;
|
|
37
|
+
return this._t.request(this._base, "POST", "/api/v1/agreement/create", { body, idempotencyKey, retry });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** ENFORCED (G1: trust_routes.py:453-471). */
|
|
41
|
+
complianceAttest({ periodStart, periodEnd, systems, idempotencyKey, retry = true }) {
|
|
42
|
+
return this._t.request(this._base, "POST", "/api/v1/compliance/attest",
|
|
43
|
+
{ body: { period_start: periodStart, period_end: periodEnd, systems }, idempotencyKey, retry });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ── class B (ENFORCED) ──
|
|
47
|
+
/** 2.1.0: enyal-client.js:472. ENFORCED (prove_routes.py:204). */
|
|
48
|
+
prove({ resourceType, geographicRegion, supplyChainStage, chunkIds, quantumResistant = false,
|
|
49
|
+
idempotencyKey, retry = true } = {}) {
|
|
50
|
+
const body = { quantum_resistant: quantumResistant };
|
|
51
|
+
if (resourceType) body.resource_type = resourceType;
|
|
52
|
+
if (geographicRegion) body.geographic_region = geographicRegion;
|
|
53
|
+
if (supplyChainStage) body.supply_chain_stage = supplyChainStage;
|
|
54
|
+
if (chunkIds) body.chunk_ids = chunkIds;
|
|
55
|
+
return this._t.request(this._base, "POST", "/api/v1/prove", { body, idempotencyKey, retry });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
proveBatch({ queries, quantumResistant = true, compress = true, idempotencyKey, retry = true }) {
|
|
59
|
+
return this._t.request(this._base, "POST", "/api/v1/prove-batch",
|
|
60
|
+
{ body: { queries, quantum_resistant: quantumResistant, compress }, idempotencyKey, retry });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** 2.1.0: enyal-client.js:292. ENFORCED (prove_routes.py:666). */
|
|
64
|
+
proveShareCombination({ customerShareHex, poseidonKeyHash, idempotencyKey, retry = true }) {
|
|
65
|
+
const body = { customer_share_hex: customerShareHex };
|
|
66
|
+
if (poseidonKeyHash) body.poseidon_key_hash = poseidonKeyHash;
|
|
67
|
+
return this._t.request(this._base, "POST", "/api/v1/prove/share-combination", { body, idempotencyKey, retry });
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** 2.1.0: enyal-client.js:483. ENFORCED (disclose_routes.py:274). */
|
|
71
|
+
disclose({ chunkIds, recipientPubkeyHex, purpose, idempotencyKey, retry = true }) {
|
|
72
|
+
return this._t.request(this._base, "POST", "/api/v1/disclose",
|
|
73
|
+
{ body: { chunk_ids: chunkIds, recipient_pubkey_hex: recipientPubkeyHex, purpose }, idempotencyKey, retry });
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** 2.1.0: enyal-client.js:201. ENFORCED (disclose_routes.py:654). */
|
|
77
|
+
requestClientDisclosure({ chunkIds, purpose, idempotencyKey, retry = true }) {
|
|
78
|
+
return this._t.request(this._base, "POST", "/api/v1/disclose/client-side",
|
|
79
|
+
{ body: { chunk_ids: chunkIds, purpose }, idempotencyKey, retry });
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** ENFORCED (message_routes.py:312). */
|
|
83
|
+
sendMessage({ senderAgentId, threadId, recipientAgentId, messageType, payload, idempotencyKey, retry = true }) {
|
|
84
|
+
return this._t.request(this._base, "POST", "/api/v1/message/send",
|
|
85
|
+
{ body: { sender_agent_id: senderAgentId, thread_id: threadId,
|
|
86
|
+
recipient_agent_id: recipientAgentId, message_type: messageType, payload },
|
|
87
|
+
idempotencyKey, retry });
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
getInbox({ agentId, direction = "inbox", ...params } = {}) {
|
|
91
|
+
return this._t.request(this._base, "GET", "/api/v1/message/inbox",
|
|
92
|
+
{ params: { agent_id: agentId, direction, ...params } });
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
getThread(threadId) {
|
|
96
|
+
return this._t.request(this._base, "GET", "/api/v1/message/thread/{thread_id}",
|
|
97
|
+
{ pathParams: { thread_id: threadId } });
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
markRead(messageIds, retry = true) {
|
|
101
|
+
return this._t.request(this._base, "POST", "/api/v1/message/read",
|
|
102
|
+
{ body: { message_ids: messageIds }, retry });
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ── reads ──
|
|
106
|
+
search(params = {}) { return this._t.request(this._base, "GET", "/api/v1/search", { params }); }
|
|
107
|
+
verifyAgreement({ agreementChunkId, terms }) {
|
|
108
|
+
return this._t.request(this._base, "POST", "/api/v1/agreement/verify",
|
|
109
|
+
{ body: { agreement_chunk_id: agreementChunkId, terms } });
|
|
110
|
+
}
|
|
111
|
+
getLineage(chunkId) {
|
|
112
|
+
return this._t.request(this._base, "GET", "/api/v1/lineage/{chunk_id}", { pathParams: { chunk_id: chunkId } });
|
|
113
|
+
}
|
|
114
|
+
getKnowledgeNodes(params = {}) { return this._t.request(this._base, "GET", "/api/v1/knowledge/nodes", { params }); }
|
|
115
|
+
getKnowledgeNode(nodeId) {
|
|
116
|
+
return this._t.request(this._base, "GET", "/api/v1/knowledge/node/{node_id}", { pathParams: { node_id: nodeId } });
|
|
117
|
+
}
|
|
118
|
+
getKnowledgeConnections(nodeId, hops = 2) {
|
|
119
|
+
return this._t.request(this._base, "GET", "/api/v1/knowledge/node/{node_id}/connections",
|
|
120
|
+
{ pathParams: { node_id: nodeId }, params: { hops } });
|
|
121
|
+
}
|
|
122
|
+
getContradictions() { return this._t.request(this._base, "GET", "/api/v1/knowledge/contradictions", {}); }
|
|
123
|
+
getKnowledgeStats() { return this._t.request(this._base, "GET", "/api/v1/knowledge/stats", {}); }
|
|
124
|
+
getKnowledgeIndex() { return this._t.request(this._base, "GET", "/api/v1/knowledge/index", {}); }
|
|
125
|
+
getKnowledgeHealth() { return this._t.request(this._base, "GET", "/api/v1/knowledge/health", {}); }
|
|
126
|
+
|
|
127
|
+
/** Absorbed stray (AUDIT.6: index.js:342). */
|
|
128
|
+
getContext({ depth = 1, topic, format = "json" } = {}) {
|
|
129
|
+
const params = { depth, format };
|
|
130
|
+
if (topic) params.topic = topic;
|
|
131
|
+
return this._t.request(this._base, "GET", "/api/v1/knowledge/context", { params });
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** Session-auth only — raise-stub preserved per 2.1.0 + design §6. */
|
|
135
|
+
synthesiseKnowledge() {
|
|
136
|
+
throw new Error("knowledge/synthesise requires session auth (not API key). Use the ENYAL web console at enyal.ai.");
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ── NOT SUPPORTED tier (auto-retry OFF at wrapper) ──
|
|
140
|
+
/** NOT retry-safe (knowledge_routes.py:448 — 500j billed, no server idempotency). */
|
|
141
|
+
knowledgeUpgrade(body = {}) { return this._t.request(this._base, "POST", "/api/v1/knowledge/upgrade", { body }); }
|
|
142
|
+
/** NOT retry-safe (knowledge_routes.py:1337). */
|
|
143
|
+
memoryStructuredQuery(body = {}) { return this._t.request(this._base, "POST", "/api/v1/memory/structured-query", { body }); }
|
|
144
|
+
/** NOT retry-safe (knowledge_routes.py:1374). */
|
|
145
|
+
memoryContentQuery(body = {}) { return this._t.request(this._base, "POST", "/api/v1/memory/content-query", { body }); }
|
|
146
|
+
/** NOT retry-safe (archive_routes.py:440). */
|
|
147
|
+
queueProof(chunkId, quantumResistant = false) {
|
|
148
|
+
return this._t.request(this._base, "POST", "/api/v1/proof/queue",
|
|
149
|
+
{ body: { chunk_id: chunkId, quantum_resistant: quantumResistant } });
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// ── recovery round-trip (design §4.1.3; wrapped-master-key invariant) ──
|
|
153
|
+
async recoverFromRecoveryFile(recoveryFile, mnemonic, passphrase = "") {
|
|
154
|
+
if (typeof recoveryFile === "string") recoveryFile = JSON.parse(recoveryFile);
|
|
155
|
+
const { customerShare } = cryptoNs.deriveSharesFromMnemonic(mnemonic, passphrase);
|
|
156
|
+
const custodial = cryptoNs.hexToBytes(recoveryFile.custodial_share_hex);
|
|
157
|
+
return cryptoNs.combineSharesAndDecrypt(customerShare, custodial, recoveryFile.encrypted_payload);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// ── Arch-3 stubs (design §4.1.4 — activate when render phases B-D ship) ──
|
|
161
|
+
memoryQuery() { throw new Error("NotImplemented: Render phases B-D not yet deployed (Arch-3, REV15-7)"); }
|
|
162
|
+
executePlan() { throw new Error("NotImplemented: Render phases B-D not yet deployed (Arch-3, REV15-7)"); }
|
|
163
|
+
renderNode() { throw new Error("NotImplemented: Render phases B-D not yet deployed (Arch-3, REV15-7)"); }
|
|
164
|
+
renderContext() { throw new Error("NotImplemented: Render phases B-D not yet deployed (Arch-3, REV15-7)"); }
|
|
165
|
+
}
|
package/src/gldai.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/** client.gldai — intelligence query surface (design §4.4; enumerated at BUILD
|
|
2
|
+
* 2026-06-10 from api.py route registrations :692-:1221, read-only). Class C
|
|
3
|
+
* metering middleware-side (rate_limiter.py:256 -> joule_metering). */
|
|
4
|
+
export const GLDAI_BASE = "https://greenlandai.ai";
|
|
5
|
+
|
|
6
|
+
export class GldaiSubmodule {
|
|
7
|
+
constructor(transport, baseUrl = GLDAI_BASE) {
|
|
8
|
+
this._t = transport; this._base = baseUrl;
|
|
9
|
+
}
|
|
10
|
+
companies({ idempotencyKey, ...params } = {}) {
|
|
11
|
+
return this._t.request(this._base, "GET", "/api/v1/companies", { params, idempotencyKey });
|
|
12
|
+
}
|
|
13
|
+
company(companyId) {
|
|
14
|
+
return this._t.request(this._base, "GET", "/api/v1/companies/{cid}", { pathParams: { cid: companyId } });
|
|
15
|
+
}
|
|
16
|
+
deposits({ idempotencyKey, ...params } = {}) {
|
|
17
|
+
return this._t.request(this._base, "GET", "/api/v1/deposits", { params, idempotencyKey });
|
|
18
|
+
}
|
|
19
|
+
deposit(depositId) {
|
|
20
|
+
return this._t.request(this._base, "GET", "/api/v1/deposits/{did}", { pathParams: { did: depositId } });
|
|
21
|
+
}
|
|
22
|
+
infrastructureList({ idempotencyKey, ...params } = {}) {
|
|
23
|
+
return this._t.request(this._base, "GET", "/api/v1/infrastructure", { params, idempotencyKey });
|
|
24
|
+
}
|
|
25
|
+
infrastructure(infraId) {
|
|
26
|
+
return this._t.request(this._base, "GET", "/api/v1/infrastructure/{iid}", { pathParams: { iid: infraId } });
|
|
27
|
+
}
|
|
28
|
+
query(q, { idempotencyKey, ...params } = {}) {
|
|
29
|
+
return this._t.request(this._base, "GET", "/api/v1/query", { params: { q, ...params }, idempotencyKey });
|
|
30
|
+
}
|
|
31
|
+
projects({ idempotencyKey, ...params } = {}) {
|
|
32
|
+
return this._t.request(this._base, "GET", "/api/v1/projects", { params, idempotencyKey });
|
|
33
|
+
}
|
|
34
|
+
project(projectId) {
|
|
35
|
+
return this._t.request(this._base, "GET", "/api/v1/projects/{pid}", { pathParams: { pid: projectId } });
|
|
36
|
+
}
|
|
37
|
+
mapdata({ idempotencyKey, ...params } = {}) {
|
|
38
|
+
return this._t.request(this._base, "GET", "/api/v1/mapdata", { params, idempotencyKey });
|
|
39
|
+
}
|
|
40
|
+
}
|
package/src/joulepai.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/** client.joulepai — 17-method Wallet absorb (design §4.2; AUDIT.6).
|
|
2
|
+
* Source-of-record: local joulepai-sdk-js/index.js (never published).
|
|
3
|
+
* Transfer-class now carries Class-D keys via dispatch (the local SDK sent none). */
|
|
4
|
+
export const JOULEPAI_BASE = "https://joulepai.ai/api/v1";
|
|
5
|
+
|
|
6
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
7
|
+
|
|
8
|
+
export class JoulepaiSubmodule {
|
|
9
|
+
constructor(transport, baseUrl = JOULEPAI_BASE) {
|
|
10
|
+
this._t = transport;
|
|
11
|
+
this._base = baseUrl;
|
|
12
|
+
this._walletId = null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async _ensureId() {
|
|
16
|
+
if (!this._walletId) {
|
|
17
|
+
this._walletId = (await this._t.request(this._base, "GET", "/wallet/me", {})).id;
|
|
18
|
+
}
|
|
19
|
+
return this._walletId;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Absorbs Wallet.create (index.js:50). */
|
|
23
|
+
createWallet({ email, ownerId, ownerType = "human", handle }) {
|
|
24
|
+
const body = { owner_id: ownerId || crypto.randomUUID(), owner_type: ownerType, email };
|
|
25
|
+
if (handle) body.handle = handle;
|
|
26
|
+
return this._t.request(this._base, "POST", "/wallet/create", { body });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Absorbs pay() (index.js:117). ENFORCED class D — dispatch auto-generates the key. */
|
|
30
|
+
async transfer(destination, amount, { platform = "rareeai", note, privacyMode,
|
|
31
|
+
idempotencyKey, retry = true } = {}) {
|
|
32
|
+
const body = { from_wallet_id: await this._ensureId(), amount, platform };
|
|
33
|
+
const dest = destination.replace(/^@/, "");
|
|
34
|
+
body[UUID_RE.test(dest) ? "to_wallet_id" : "to_handle"] = dest;
|
|
35
|
+
if (note != null) body.note = note;
|
|
36
|
+
if (privacyMode != null) body.privacy_mode = privacyMode;
|
|
37
|
+
return this._t.request(this._base, "POST", "/wallet/transfer", { body, idempotencyKey, retry });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
pay(...args) { return this.transfer(...args); }
|
|
41
|
+
|
|
42
|
+
transferStatus(transferId) {
|
|
43
|
+
return this._t.request(this._base, "GET", "/wallet/transfer/{tid}/status", { pathParams: { tid: transferId } });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Absorbs fund() (index.js:152). NOT retry-safe (G1 demotion — duplicate Stripe sessions). */
|
|
47
|
+
async fund(amountFiat, { method = "stripe" } = {}) {
|
|
48
|
+
return this._t.request(this._base, "POST", "/wallet/fund",
|
|
49
|
+
{ body: { wallet_id: await this._ensureId(), amount_fiat: amountFiat, method } });
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async balance() {
|
|
53
|
+
return (await this._t.request(this._base, "GET", "/wallet/balance/{wid}",
|
|
54
|
+
{ pathParams: { wid: await this._ensureId() } })).balance;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async info() {
|
|
58
|
+
return this._t.request(this._base, "GET", "/wallet/balance/{wid}",
|
|
59
|
+
{ pathParams: { wid: await this._ensureId() } });
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async handle() { return (await this.info()).handle ?? null; }
|
|
63
|
+
|
|
64
|
+
async transactions({ limit = 50, offset = 0 } = {}) {
|
|
65
|
+
return this._t.request(this._base, "GET", "/wallet/transactions/{wid}",
|
|
66
|
+
{ pathParams: { wid: await this._ensureId() }, params: { limit, offset } });
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async setHandle(h) {
|
|
70
|
+
return this._t.request(this._base, "PUT", "/wallet/handle",
|
|
71
|
+
{ body: { wallet_id: await this._ensureId(), handle: h.replace(/^@/, "") } });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async exchangeRate(currency = "EUR") {
|
|
75
|
+
return (await this._t.request(this._base, "GET", "/wallet/exchange-rate/{cur}",
|
|
76
|
+
{ pathParams: { cur: currency.toUpperCase() } })).joules_per_unit;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async getLimits() {
|
|
80
|
+
return this._t.request(this._base, "GET", "/wallet/limits/{wid}",
|
|
81
|
+
{ pathParams: { wid: await this._ensureId() } });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async setLimits({ daily, perTransaction, allowedPlatforms } = {}) {
|
|
85
|
+
const body = { agent_wallet_id: await this._ensureId() };
|
|
86
|
+
if (daily != null) body.daily_cap = daily;
|
|
87
|
+
if (perTransaction != null) body.per_transaction_cap = perTransaction;
|
|
88
|
+
if (allowedPlatforms != null) body.allowed_platforms = allowedPlatforms;
|
|
89
|
+
return this._t.request(this._base, "PUT", "/wallet/limits", { body });
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async depositInfo() {
|
|
93
|
+
return this._t.request(this._base, "GET", "/wallet/deposit-info/{wid}",
|
|
94
|
+
{ pathParams: { wid: await this._ensureId() } });
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
depositAddress() { return this._t.request(this._base, "GET", "/wallet/deposit-address", {}); }
|
|
98
|
+
|
|
99
|
+
fundingStatus(fundingEventId) {
|
|
100
|
+
return this._t.request(this._base, "GET", "/wallet/fund/{fid}", { pathParams: { fid: fundingEventId } });
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
resetCredentials(walletId, email) {
|
|
104
|
+
return this._t.request(this._base, "POST", "/wallet/reset-credentials",
|
|
105
|
+
{ body: { wallet_id: walletId, email } });
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
verify(transactionId) {
|
|
109
|
+
return this._t.request(this._base, "GET", "/wallet/transaction/{tid}", { pathParams: { tid: transactionId } });
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async verifyPayment(transactionId, expectedAmount, recipient) {
|
|
113
|
+
return (await this._t.request(this._base, "POST", "/wallet/verify-payment",
|
|
114
|
+
{ params: { transaction_id: transactionId, expected_amount: expectedAmount, recipient } })).verified;
|
|
115
|
+
}
|
|
116
|
+
}
|
package/src/rareeai.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/** client.rareeai — RAREEAI marketplace (single entry point).
|
|
2
|
+
* Collapsed 2026-06-10 (WS-2, audit Decision 1) from the prior dual
|
|
3
|
+
* `.direct`/`.intelligence` sub-namespaces. Empirical reality (P-DAY.26 audit
|
|
4
|
+
* LAYER 1-4): ONE marketplace backend, reachable ONLY via the JoulePAI
|
|
5
|
+
* marketplace_proxy at `/api/v1/marketplace/*`. The prior `.direct`
|
|
6
|
+
* (`/api/v1`) path did NOT reach rareeai. Fee is a single flat 0.5%
|
|
7
|
+
* (config.MATCH_FEE_RATE = 0.005), fixed by ROUTE, never by a parameter.
|
|
8
|
+
*
|
|
9
|
+
* Forward compatibility: a future SECOND entry point (PoolGap tiered-fee
|
|
10
|
+
* design) is added as a NEW sub-namespace in an additive MINOR version,
|
|
11
|
+
* never a breaking rename. See design §4.3 "Forward Compatibility". */
|
|
12
|
+
export const RAREEAI_BASE = "https://joulepai.ai"; // via JoulePAI marketplace_proxy
|
|
13
|
+
const RAREEAI_PREFIX = "/api/v1/marketplace"; // the ONLY route that reaches rareeai
|
|
14
|
+
|
|
15
|
+
export class RareeaiSubmodule {
|
|
16
|
+
constructor(transport, baseUrl = RAREEAI_BASE) {
|
|
17
|
+
this._t = transport; this._base = baseUrl; this._p = RAREEAI_PREFIX;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Pattern B
|
|
21
|
+
createProvider({ resourceType, capacity, idempotencyKey, retry = true, ...fields }) {
|
|
22
|
+
const body = { resource_type: resourceType, ...fields };
|
|
23
|
+
if (capacity) body.capacity = capacity;
|
|
24
|
+
return this._t.request(this._base, "POST", `${this._p}/provide`, { body, idempotencyKey, retry });
|
|
25
|
+
}
|
|
26
|
+
// ENFORCED-WHEN-PRESENT / BEST-EFFORT-keyless (routes.py:1282 guard; SDK dispatch
|
|
27
|
+
// always auto-gens a key → SDK callers effectively enforced; keyless gap raw-HTTP-only).
|
|
28
|
+
createRequest({ resourceType, idempotencyKey, retry = true, ...fields }) {
|
|
29
|
+
return this._t.request(this._base, "POST", `${this._p}/request`,
|
|
30
|
+
{ body: { resource_type: resourceType, ...fields }, idempotencyKey, retry });
|
|
31
|
+
}
|
|
32
|
+
deliver(matchId, { idempotencyKey, retry = true, ...fields } = {}) {
|
|
33
|
+
return this._t.request(this._base, "POST", `${this._p}/deliver/{match_id}`,
|
|
34
|
+
{ pathParams: { match_id: matchId }, body: fields, idempotencyKey, retry });
|
|
35
|
+
}
|
|
36
|
+
resolve(matchId, { idempotencyKey, retry = true, ...fields } = {}) {
|
|
37
|
+
return this._t.request(this._base, "POST", `${this._p}/match/{match_id}/resolve`,
|
|
38
|
+
{ pathParams: { match_id: matchId }, body: fields, idempotencyKey, retry });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// FSM transitions — NOT SUPPORTED (auto-retry OFF)
|
|
42
|
+
approve(matchId, fields = {}) {
|
|
43
|
+
return this._t.request(this._base, "POST", `${this._p}/match/{match_id}/approve`,
|
|
44
|
+
{ pathParams: { match_id: matchId }, body: fields });
|
|
45
|
+
}
|
|
46
|
+
reject(matchId, fields = {}) {
|
|
47
|
+
return this._t.request(this._base, "POST", `${this._p}/match/{match_id}/reject`,
|
|
48
|
+
{ pathParams: { match_id: matchId }, body: fields });
|
|
49
|
+
}
|
|
50
|
+
dispute(matchId, fields = {}) {
|
|
51
|
+
return this._t.request(this._base, "POST", `${this._p}/match/{match_id}/dispute`,
|
|
52
|
+
{ pathParams: { match_id: matchId }, body: fields });
|
|
53
|
+
}
|
|
54
|
+
extendDispute(matchId, fields = {}) {
|
|
55
|
+
return this._t.request(this._base, "POST", `${this._p}/match/{match_id}/extend-dispute`,
|
|
56
|
+
{ pathParams: { match_id: matchId }, body: fields });
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// reads
|
|
60
|
+
providers(params = {}) { return this._t.request(this._base, "GET", `${this._p}/providers`, { params }); }
|
|
61
|
+
myProviders() { return this._t.request(this._base, "GET", `${this._p}/providers/mine`, {}); }
|
|
62
|
+
getRequest(requestId) {
|
|
63
|
+
return this._t.request(this._base, "GET", `${this._p}/request/{request_id}`,
|
|
64
|
+
{ pathParams: { request_id: requestId } });
|
|
65
|
+
}
|
|
66
|
+
}
|