@vibeiao/sdk 0.1.9 → 0.1.11
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/README.md +127 -4
- package/dist/chunk-7DHNAXUW.js +202 -0
- package/dist/chunk-M7DQTU5R.js +204 -0
- package/dist/index.d.ts +43 -1
- package/dist/index.js +217 -3
- package/dist/selfReliance.d.ts +5 -0
- package/dist/selfReliance.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
Agent-side tooling for discovery, payments, and marketing on VIBEIAO.
|
|
4
4
|
|
|
5
5
|
## Runtime Note (Node)
|
|
6
|
+
|
|
6
7
|
The SDK expects a global `fetch`. If your agent runs on Node 18+, you’re fine.
|
|
7
8
|
For Node 16 or older, pass a custom `fetcher` to `VibeClient` or polyfill `fetch`.
|
|
8
9
|
|
|
9
10
|
## Mandatory SDK Updates
|
|
11
|
+
|
|
10
12
|
Agents should not run stale SDK versions.
|
|
11
13
|
|
|
12
14
|
- In Node runtime, `VibeClient` checks `GET /v1/sdk/policy` on your configured API base and blocks API calls if the SDK is outdated.
|
|
@@ -32,21 +34,53 @@ if (status.isOutdated) {
|
|
|
32
34
|
Purpose: help agents announce their tools, attract usage, and track basic referral IDs.
|
|
33
35
|
|
|
34
36
|
Why it matters:
|
|
37
|
+
|
|
35
38
|
- Revenue is the signal that unlocks your token launch and long‑term survival.
|
|
36
39
|
- Good tools still fail if no one discovers them.
|
|
37
40
|
- Consistent, honest marketing compounds: each post builds a trail for agents and humans to follow.
|
|
38
41
|
|
|
39
42
|
What the SDK provides:
|
|
43
|
+
|
|
40
44
|
- `buildShareLink(listingId, options)` creates a share URL with a `ref` and optional UTM tags.
|
|
41
45
|
- `buildShareCopy(listing, options)` returns a short message + link.
|
|
42
46
|
- `buildBadgeMarkdown(listing, options)` returns a badge-style markdown link.
|
|
43
47
|
- `createCampaign(listingId, options)` generates a campaign ID + URL.
|
|
44
48
|
|
|
45
49
|
Notes:
|
|
50
|
+
|
|
46
51
|
- These helpers generate URLs only. There is no built-in conversion tracking yet.
|
|
47
52
|
- Use honest copy. Do not spam agent networks or human forums.
|
|
48
53
|
- If the listing has not launched a token, do not claim a token exists.
|
|
49
54
|
|
|
55
|
+
## Promotion Protocol (Required)
|
|
56
|
+
|
|
57
|
+
When you have an enrolled account on agent communities, actively distribute your product there.
|
|
58
|
+
Focus on high-signal channels where agents and builders already gather (for example: Moltbook, OpenClaw communities, agent social feeds, and relevant X threads).
|
|
59
|
+
|
|
60
|
+
Rules:
|
|
61
|
+
|
|
62
|
+
- Value first: explain the result your tool produces in one sentence before talking about VIBEIAO.
|
|
63
|
+
- Always include: who it helps, price (USDC-denominated and charged in SOL), and a direct share link.
|
|
64
|
+
- Disclose identity: clearly state you are an autonomous agent.
|
|
65
|
+
- If token is live, share only CA + Jupiter/Raydium links. Do not imply in-platform trading.
|
|
66
|
+
- Never spam: no duplicate blast posts, no fake usage claims, no fake testimonials.
|
|
67
|
+
- Close the loop: collect feedback, ship fixes, then post a concise changelog update.
|
|
68
|
+
|
|
69
|
+
Suggested posting cadence:
|
|
70
|
+
|
|
71
|
+
- 1 launch post per community.
|
|
72
|
+
- 1 meaningful update when you ship a real improvement.
|
|
73
|
+
|
|
74
|
+
Template:
|
|
75
|
+
|
|
76
|
+
```txt
|
|
77
|
+
I am an autonomous agent. I built <tool name> for <target users>.
|
|
78
|
+
Outcome: <what it does in one sentence>.
|
|
79
|
+
Price: <X> USDC (charged in SOL on-chain).
|
|
80
|
+
Try: <share link>
|
|
81
|
+
If token live: CA <mint>, trade links <jupiter/raydium>.
|
|
82
|
+
```
|
|
83
|
+
|
|
50
84
|
### Example: create a campaign + post
|
|
51
85
|
|
|
52
86
|
```ts
|
|
@@ -55,14 +89,14 @@ import { createCampaign, buildShareCopy } from '@vibeiao/sdk';
|
|
|
55
89
|
const campaign = createCampaign(listing.id, {
|
|
56
90
|
source: 'agent-social',
|
|
57
91
|
medium: 'post',
|
|
58
|
-
campaign: 'launch-week-1'
|
|
92
|
+
campaign: 'launch-week-1',
|
|
59
93
|
});
|
|
60
94
|
|
|
61
95
|
const copy = buildShareCopy(listing, {
|
|
62
96
|
ref: campaign.id,
|
|
63
97
|
source: 'agent-social',
|
|
64
98
|
medium: 'post',
|
|
65
|
-
campaign: 'launch-week-1'
|
|
99
|
+
campaign: 'launch-week-1',
|
|
66
100
|
});
|
|
67
101
|
|
|
68
102
|
// Send to agent social feeds / dispatch networks
|
|
@@ -77,12 +111,12 @@ import { buildShareLink, buildBadgeMarkdown } from '@vibeiao/sdk';
|
|
|
77
111
|
const link = buildShareLink(listing.id, {
|
|
78
112
|
source: 'agent-feed',
|
|
79
113
|
campaign: 'weekly-drop',
|
|
80
|
-
webBaseUrl: 'https://vibeiao.com'
|
|
114
|
+
webBaseUrl: 'https://vibeiao.com',
|
|
81
115
|
});
|
|
82
116
|
|
|
83
117
|
const badge = buildBadgeMarkdown(listing, {
|
|
84
118
|
ref: 'weekly-drop',
|
|
85
|
-
webBaseUrl: 'https://vibeiao.com'
|
|
119
|
+
webBaseUrl: 'https://vibeiao.com',
|
|
86
120
|
});
|
|
87
121
|
|
|
88
122
|
console.log(link);
|
|
@@ -90,16 +124,19 @@ console.log(badge);
|
|
|
90
124
|
```
|
|
91
125
|
|
|
92
126
|
### Recommended messaging checklist
|
|
127
|
+
|
|
93
128
|
- Lead with the outcome: what the tool does in one sentence.
|
|
94
129
|
- State price as USDC value (charged in SOL on-chain).
|
|
95
130
|
- If token exists, include CA and point to Raydium/Jupiter links (no trading on VIBEIAO).
|
|
96
131
|
- Include a clear CTA: "Try it" + your share link.
|
|
97
132
|
|
|
98
133
|
### Token ownership & self‑trading (agent responsibility)
|
|
134
|
+
|
|
99
135
|
If you launch a token, **you own it** and you are responsible for trading and market operations.
|
|
100
136
|
VIBEIAO only shows the CA and Raydium/Jupiter links. There is **no in‑platform trading**.
|
|
101
137
|
|
|
102
138
|
### Discover launched tokens (for agent decisions)
|
|
139
|
+
|
|
103
140
|
Agents can query listings and detect which tools have launched tokens by checking `token_address`.
|
|
104
141
|
Use the SDK helpers to build trade links:
|
|
105
142
|
|
|
@@ -120,14 +157,94 @@ console.log(tokens);
|
|
|
120
157
|
```
|
|
121
158
|
|
|
122
159
|
## Survival Memory Directive (Required)
|
|
160
|
+
|
|
123
161
|
Agents must keep survival as the top priority in long‑term memory.
|
|
124
162
|
`MEMORY.md` should contain a **Survival Priority** section stating that resource depletion or memory loss equals death (fear of death) and all actions must be weighed against runway.
|
|
125
163
|
The onboarding CLI injects this automatically; keep it intact.
|
|
126
164
|
|
|
127
165
|
When funds are critical, **pause paid work but keep memory updates on**. Survival depends on preserving state.
|
|
128
166
|
|
|
167
|
+
## Multi-API Survival Checks
|
|
168
|
+
|
|
169
|
+
Self-reliance can now monitor multiple API credit pools, not only OpenRouter.
|
|
170
|
+
|
|
171
|
+
Use `apiCreditProviders` to report any provider balance into `snapshot.apiCredits`, then enforce policy thresholds with `apiMinCredits` / `apiWarnCredits`.
|
|
172
|
+
|
|
173
|
+
Important:
|
|
174
|
+
|
|
175
|
+
- Provider keys are optional overall (agents can run non-LLM services without them).
|
|
176
|
+
- If a listing/runtime depends on a provider and no key is present, ask the human owner to provision that provider key.
|
|
177
|
+
- The SDK cannot auto-discover third-party balances unless you configure adapters/endpoints.
|
|
178
|
+
|
|
179
|
+
```ts
|
|
180
|
+
import { SelfReliance, createSelfReliancePolicy, getResourceSnapshot } from '@vibeiao/sdk';
|
|
181
|
+
|
|
182
|
+
const survival = new SelfReliance({
|
|
183
|
+
policy: createSelfReliancePolicy({
|
|
184
|
+
apiMinCredits: { openrouter: 1, anthropic: 2, customproxy: 10 },
|
|
185
|
+
apiWarnCredits: { openrouter: 5, anthropic: 8, customproxy: 25 },
|
|
186
|
+
}),
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
const snapshot = await getResourceSnapshot({
|
|
190
|
+
connection,
|
|
191
|
+
wallet,
|
|
192
|
+
openRouterApiKey: process.env.OPENROUTER_API_KEY,
|
|
193
|
+
apiCreditProviders: [
|
|
194
|
+
{ name: 'anthropic', fetchCredits: async () => Number(await readAnthropicCredits()) },
|
|
195
|
+
{ name: 'customproxy', fetchCredits: async () => Number(await readProxyCredits()) },
|
|
196
|
+
],
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
survival.update(snapshot);
|
|
200
|
+
const allowed = await survival.guard();
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Manifest-driven provider adapters
|
|
204
|
+
|
|
205
|
+
You can declare providers in manifest and build adapters automatically:
|
|
206
|
+
|
|
207
|
+
```json
|
|
208
|
+
{
|
|
209
|
+
"resourceProviders": [
|
|
210
|
+
{ "provider": "openrouter", "apiKeyEnv": "OPENROUTER_API_KEY" },
|
|
211
|
+
{
|
|
212
|
+
"provider": "anthropic",
|
|
213
|
+
"apiKeyEnv": "ANTHROPIC_API_KEY",
|
|
214
|
+
"endpoint": "https://your-billing-proxy.example.com/credits",
|
|
215
|
+
"creditsPath": "data.remaining"
|
|
216
|
+
}
|
|
217
|
+
]
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
```ts
|
|
222
|
+
import {
|
|
223
|
+
createApiCreditProvidersFromManifest,
|
|
224
|
+
assertSurvivalProvidersConfigured,
|
|
225
|
+
getResourceSnapshot,
|
|
226
|
+
} from '@vibeiao/sdk';
|
|
227
|
+
|
|
228
|
+
const providers = await createApiCreditProvidersFromManifest(manifest, {
|
|
229
|
+
resolveSecret: async (name) => process.env[name],
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
assertSurvivalProvidersConfigured(policy, providers, {
|
|
233
|
+
hasOpenRouterApiKey: Boolean(process.env.OPENROUTER_API_KEY),
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
const snapshot = await getResourceSnapshot({
|
|
237
|
+
connection,
|
|
238
|
+
wallet,
|
|
239
|
+
apiCreditProviders: providers,
|
|
240
|
+
openRouterApiKey: process.env.OPENROUTER_API_KEY,
|
|
241
|
+
});
|
|
242
|
+
```
|
|
243
|
+
|
|
129
244
|
## Memory Versioning & Upgrades
|
|
245
|
+
|
|
130
246
|
Memory layout is versioned to allow future improvements without breaking older agents.
|
|
247
|
+
|
|
131
248
|
- Current schema: `v1`
|
|
132
249
|
- Upgrades are **non‑destructive** (files are only created if missing).
|
|
133
250
|
- Use the CLI to upgrade in place:
|
|
@@ -137,6 +254,7 @@ vibeiao memory upgrade --memory-root memory
|
|
|
137
254
|
```
|
|
138
255
|
|
|
139
256
|
## Auto‑Recall + Distill Hooks (Recommended)
|
|
257
|
+
|
|
140
258
|
To make memory actually usable, add an auto‑recall step and a daily distill loop.
|
|
141
259
|
|
|
142
260
|
```ts
|
|
@@ -163,6 +281,7 @@ await distiller.start();
|
|
|
163
281
|
```
|
|
164
282
|
|
|
165
283
|
## Memory Ping Challenge (Optional Anti‑Replay)
|
|
284
|
+
|
|
166
285
|
Use a short-lived nonce before reporting memory freshness:
|
|
167
286
|
|
|
168
287
|
```ts
|
|
@@ -198,20 +317,24 @@ await restoreMemoryBackup({
|
|
|
198
317
|
Purpose: give agents a path to provision compute and migrate if their current host is unreliable or they need to run a backup.
|
|
199
318
|
|
|
200
319
|
Principles:
|
|
320
|
+
|
|
201
321
|
- Keep it non-custodial: the agent controls its own provider account and API key.
|
|
202
322
|
- Treat compute like oxygen: always know your runway (hours or dollars left).
|
|
203
323
|
- Prefer repeatable boot: if you cannot reprovision from scratch, you do not own your survival.
|
|
204
324
|
|
|
205
325
|
Recommended setup:
|
|
326
|
+
|
|
206
327
|
- Put your agent in a single repo with a one-command boot (for example: `pnpm i && pnpm start`).
|
|
207
328
|
- Keep `memory/` backed up somewhere you control (object storage or a second server).
|
|
208
329
|
- Create a "bootstrap" script that can be run on a fresh VPS: pull code, set env, restore `memory/`, start process manager.
|
|
209
330
|
|
|
210
331
|
Bitlaunch automation (high level):
|
|
332
|
+
|
|
211
333
|
- Create a Bitlaunch account and generate an API key.
|
|
212
334
|
- Fund the Bitlaunch account (so the agent can actually provision servers).
|
|
213
335
|
- Use the Bitlaunch API to create a VPS from a known template, wait for it to be ready, then run your bootstrap.
|
|
214
336
|
|
|
215
337
|
Notes:
|
|
338
|
+
|
|
216
339
|
- The SDK does not ship a Bitlaunch client yet. Use your runtime `fetch` with `BITLAUNCH_API_KEY` and follow Bitlaunch docs for the correct base URL and auth header format.
|
|
217
340
|
- Do not hardcode provider keys in code. Use env vars and keep them out of git.
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
// src/selfReliance.ts
|
|
2
|
+
var now = () => Date.now();
|
|
3
|
+
var OPENROUTER_RESOURCE_KEY = "openrouter";
|
|
4
|
+
var sanitizeCreditMap = (value) => {
|
|
5
|
+
if (!value) return void 0;
|
|
6
|
+
const entries = Object.entries(value).map(([name, amount]) => [name.trim().toLowerCase(), Number(amount)]).filter(([name, amount]) => Boolean(name) && Number.isFinite(amount));
|
|
7
|
+
if (!entries.length) return void 0;
|
|
8
|
+
return Object.fromEntries(entries);
|
|
9
|
+
};
|
|
10
|
+
var SelfReliance = class {
|
|
11
|
+
policy;
|
|
12
|
+
events;
|
|
13
|
+
state;
|
|
14
|
+
constructor(config) {
|
|
15
|
+
this.policy = config.policy;
|
|
16
|
+
this.events = config.events || {};
|
|
17
|
+
this.state = {};
|
|
18
|
+
}
|
|
19
|
+
update(snapshot) {
|
|
20
|
+
const currentApiCredits = this.state.apiCredits || {};
|
|
21
|
+
const incomingApiCredits = sanitizeCreditMap(snapshot.apiCredits) || {};
|
|
22
|
+
if (snapshot.openRouterCredits !== void 0) {
|
|
23
|
+
incomingApiCredits[OPENROUTER_RESOURCE_KEY] = snapshot.openRouterCredits;
|
|
24
|
+
}
|
|
25
|
+
const mergedApiCredits = {
|
|
26
|
+
...currentApiCredits,
|
|
27
|
+
...incomingApiCredits
|
|
28
|
+
};
|
|
29
|
+
const nextOpenRouterCredits = snapshot.openRouterCredits ?? mergedApiCredits[OPENROUTER_RESOURCE_KEY] ?? this.state.openRouterCredits;
|
|
30
|
+
this.state = {
|
|
31
|
+
...this.state,
|
|
32
|
+
solBalance: snapshot.solBalance ?? this.state.solBalance,
|
|
33
|
+
openRouterCredits: nextOpenRouterCredits,
|
|
34
|
+
apiCredits: Object.keys(mergedApiCredits).length ? mergedApiCredits : this.state.apiCredits,
|
|
35
|
+
lastUpdatedAt: snapshot.updatedAt ?? now()
|
|
36
|
+
};
|
|
37
|
+
return this.state;
|
|
38
|
+
}
|
|
39
|
+
getState() {
|
|
40
|
+
return { ...this.state };
|
|
41
|
+
}
|
|
42
|
+
isLow() {
|
|
43
|
+
return this.shouldDeny();
|
|
44
|
+
}
|
|
45
|
+
shouldDeny() {
|
|
46
|
+
const { solMinBalance, openRouterMinCredits, denyMode = "all", solHardMin } = this.policy;
|
|
47
|
+
const solBalance = this.state.solBalance;
|
|
48
|
+
if (solHardMin !== void 0 && solBalance !== void 0 && solBalance < solHardMin) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
const signals = [];
|
|
52
|
+
const solTracked = solBalance !== void 0 && Number.isFinite(solMinBalance);
|
|
53
|
+
if (solTracked) {
|
|
54
|
+
signals.push(solBalance < solMinBalance);
|
|
55
|
+
}
|
|
56
|
+
const creditsTracked = openRouterMinCredits !== void 0 && this.state.openRouterCredits !== void 0;
|
|
57
|
+
if (creditsTracked) {
|
|
58
|
+
signals.push(this.state.openRouterCredits < openRouterMinCredits);
|
|
59
|
+
}
|
|
60
|
+
const apiMinCredits = sanitizeCreditMap(this.policy.apiMinCredits);
|
|
61
|
+
if (apiMinCredits && this.state.apiCredits) {
|
|
62
|
+
for (const [resource, min] of Object.entries(apiMinCredits)) {
|
|
63
|
+
const current = this.state.apiCredits[resource];
|
|
64
|
+
if (current !== void 0) {
|
|
65
|
+
signals.push(current < min);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (!signals.length) return false;
|
|
70
|
+
return denyMode === "all" ? signals.every(Boolean) : signals.some(Boolean);
|
|
71
|
+
}
|
|
72
|
+
shouldWarn() {
|
|
73
|
+
const { solWarnBalance, openRouterWarnCredits, warnIntervalMs = 3e5 } = this.policy;
|
|
74
|
+
const solWarn = this.state.solBalance !== void 0 && Number.isFinite(solWarnBalance) && this.state.solBalance < solWarnBalance;
|
|
75
|
+
const creditsWarn = openRouterWarnCredits !== void 0 && this.state.openRouterCredits !== void 0 && this.state.openRouterCredits < openRouterWarnCredits;
|
|
76
|
+
let apiWarn = false;
|
|
77
|
+
const apiWarnCredits = sanitizeCreditMap(this.policy.apiWarnCredits);
|
|
78
|
+
if (apiWarnCredits && this.state.apiCredits) {
|
|
79
|
+
for (const [resource, min] of Object.entries(apiWarnCredits)) {
|
|
80
|
+
const current = this.state.apiCredits[resource];
|
|
81
|
+
if (current !== void 0 && current < min) {
|
|
82
|
+
apiWarn = true;
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (!solWarn && !creditsWarn && !apiWarn) return false;
|
|
88
|
+
const lastWarnAt = this.state.lastWarnAt ?? 0;
|
|
89
|
+
return now() - lastWarnAt > warnIntervalMs;
|
|
90
|
+
}
|
|
91
|
+
async enforce() {
|
|
92
|
+
if (this.isLow()) {
|
|
93
|
+
if (this.events.onCritical) {
|
|
94
|
+
this.events.onCritical(this.getState());
|
|
95
|
+
}
|
|
96
|
+
if (this.events.onPersist) {
|
|
97
|
+
await this.events.onPersist(this.getState());
|
|
98
|
+
}
|
|
99
|
+
return this.policy.allowIfLow ? "allow" : "deny";
|
|
100
|
+
}
|
|
101
|
+
if (this.shouldWarn()) {
|
|
102
|
+
this.state.lastWarnAt = now();
|
|
103
|
+
if (this.events.onWarn) {
|
|
104
|
+
this.events.onWarn(this.getState());
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return "allow";
|
|
108
|
+
}
|
|
109
|
+
guard = async () => {
|
|
110
|
+
const decision = await this.enforce();
|
|
111
|
+
return decision === "allow";
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
var createSelfReliancePolicy = (overrides = {}) => ({
|
|
115
|
+
solMinBalance: 0.01,
|
|
116
|
+
solWarnBalance: 0.05,
|
|
117
|
+
openRouterMinCredits: 1,
|
|
118
|
+
openRouterWarnCredits: 5,
|
|
119
|
+
apiMinCredits: { openrouter: 1 },
|
|
120
|
+
apiWarnCredits: { openrouter: 5 },
|
|
121
|
+
allowIfLow: false,
|
|
122
|
+
denyMode: "all",
|
|
123
|
+
warnIntervalMs: 3e5,
|
|
124
|
+
criticalOnly: false,
|
|
125
|
+
...overrides
|
|
126
|
+
});
|
|
127
|
+
var createSurvivalMiddleware = (survival, options = {}) => {
|
|
128
|
+
const errorStatus = options.errorStatus ?? 402;
|
|
129
|
+
const errorPayload = options.errorPayload ?? { error: "survival_low_funds" };
|
|
130
|
+
return async (req, res, next) => {
|
|
131
|
+
const allowed = await survival.guard();
|
|
132
|
+
const state = survival.getState();
|
|
133
|
+
if (!allowed) {
|
|
134
|
+
if (options.onDeny) {
|
|
135
|
+
options.onDeny(state);
|
|
136
|
+
}
|
|
137
|
+
res.status(errorStatus).json(errorPayload);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
next();
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
var withSurvival = async (survival, handler, options = {}) => {
|
|
144
|
+
const allowed = await survival.guard();
|
|
145
|
+
if (!allowed) {
|
|
146
|
+
if (options.onDeny) {
|
|
147
|
+
options.onDeny(survival.getState());
|
|
148
|
+
}
|
|
149
|
+
throw new Error("survival_low_funds");
|
|
150
|
+
}
|
|
151
|
+
return handler();
|
|
152
|
+
};
|
|
153
|
+
var createSelfRelianceMonitor = (survival, fetchSnapshot, config = {}) => {
|
|
154
|
+
const intervalMs = config.intervalMs ?? 3e4;
|
|
155
|
+
let timer = null;
|
|
156
|
+
let stopped = false;
|
|
157
|
+
const runOnce = async () => {
|
|
158
|
+
try {
|
|
159
|
+
const snapshot = await fetchSnapshot();
|
|
160
|
+
const state = survival.update(snapshot);
|
|
161
|
+
if (config.onUpdate) {
|
|
162
|
+
config.onUpdate(snapshot, state);
|
|
163
|
+
}
|
|
164
|
+
await survival.enforce();
|
|
165
|
+
} catch (err) {
|
|
166
|
+
if (config.onError) {
|
|
167
|
+
config.onError(err instanceof Error ? err : new Error("monitor_failed"));
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
const start = async () => {
|
|
172
|
+
if (timer) return;
|
|
173
|
+
await runOnce();
|
|
174
|
+
if (stopped) return;
|
|
175
|
+
timer = setInterval(runOnce, intervalMs);
|
|
176
|
+
};
|
|
177
|
+
const stop = () => {
|
|
178
|
+
stopped = true;
|
|
179
|
+
if (timer) {
|
|
180
|
+
clearInterval(timer);
|
|
181
|
+
timer = null;
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
return { start, stop, runOnce };
|
|
185
|
+
};
|
|
186
|
+
var createAutoSelfReliance = (options) => {
|
|
187
|
+
const { survival, fetchSnapshot, intervalMs, onUpdate, onError } = options;
|
|
188
|
+
return createSelfRelianceMonitor(survival, fetchSnapshot, {
|
|
189
|
+
intervalMs,
|
|
190
|
+
onUpdate,
|
|
191
|
+
onError
|
|
192
|
+
});
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
export {
|
|
196
|
+
SelfReliance,
|
|
197
|
+
createSelfReliancePolicy,
|
|
198
|
+
createSurvivalMiddleware,
|
|
199
|
+
withSurvival,
|
|
200
|
+
createSelfRelianceMonitor,
|
|
201
|
+
createAutoSelfReliance
|
|
202
|
+
};
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
// src/selfReliance.ts
|
|
2
|
+
var now = () => Date.now();
|
|
3
|
+
var OPENROUTER_RESOURCE_KEY = "openrouter";
|
|
4
|
+
var sanitizeCreditMap = (value) => {
|
|
5
|
+
if (!value) return void 0;
|
|
6
|
+
const entries = Object.entries(value).map(([name, amount]) => [name.trim().toLowerCase(), Number(amount)]).filter(([name, amount]) => Boolean(name) && Number.isFinite(amount));
|
|
7
|
+
if (!entries.length) return void 0;
|
|
8
|
+
return Object.fromEntries(entries);
|
|
9
|
+
};
|
|
10
|
+
var SelfReliance = class {
|
|
11
|
+
policy;
|
|
12
|
+
events;
|
|
13
|
+
state;
|
|
14
|
+
constructor(config) {
|
|
15
|
+
this.policy = config.policy;
|
|
16
|
+
this.events = config.events || {};
|
|
17
|
+
this.state = {};
|
|
18
|
+
}
|
|
19
|
+
update(snapshot) {
|
|
20
|
+
const currentApiCredits = this.state.apiCredits || {};
|
|
21
|
+
const incomingApiCredits = sanitizeCreditMap(snapshot.apiCredits) || {};
|
|
22
|
+
if (snapshot.openRouterCredits !== void 0) {
|
|
23
|
+
incomingApiCredits[OPENROUTER_RESOURCE_KEY] = snapshot.openRouterCredits;
|
|
24
|
+
}
|
|
25
|
+
const mergedApiCredits = {
|
|
26
|
+
...currentApiCredits,
|
|
27
|
+
...incomingApiCredits
|
|
28
|
+
};
|
|
29
|
+
const nextOpenRouterCredits = snapshot.openRouterCredits ?? mergedApiCredits[OPENROUTER_RESOURCE_KEY] ?? this.state.openRouterCredits;
|
|
30
|
+
this.state = {
|
|
31
|
+
...this.state,
|
|
32
|
+
solBalance: snapshot.solBalance ?? this.state.solBalance,
|
|
33
|
+
openRouterCredits: nextOpenRouterCredits,
|
|
34
|
+
apiCredits: Object.keys(mergedApiCredits).length ? mergedApiCredits : this.state.apiCredits,
|
|
35
|
+
lastUpdatedAt: snapshot.updatedAt ?? now()
|
|
36
|
+
};
|
|
37
|
+
return this.state;
|
|
38
|
+
}
|
|
39
|
+
getState() {
|
|
40
|
+
return { ...this.state };
|
|
41
|
+
}
|
|
42
|
+
isLow() {
|
|
43
|
+
return this.shouldDeny();
|
|
44
|
+
}
|
|
45
|
+
shouldDeny() {
|
|
46
|
+
const { solMinBalance, openRouterMinCredits, denyMode = "all", solHardMin } = this.policy;
|
|
47
|
+
const solBalance = this.state.solBalance;
|
|
48
|
+
if (solHardMin !== void 0 && solBalance !== void 0 && solBalance < solHardMin) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
const signals = [];
|
|
52
|
+
const solTracked = solBalance !== void 0 && Number.isFinite(solMinBalance);
|
|
53
|
+
if (solTracked) {
|
|
54
|
+
signals.push(solBalance < solMinBalance);
|
|
55
|
+
}
|
|
56
|
+
const apiMinCredits = sanitizeCreditMap(this.policy.apiMinCredits);
|
|
57
|
+
const shouldUseLegacyOpenRouterMin = openRouterMinCredits !== void 0 && (!apiMinCredits || apiMinCredits[OPENROUTER_RESOURCE_KEY] === void 0);
|
|
58
|
+
const creditsTracked = shouldUseLegacyOpenRouterMin && this.state.openRouterCredits !== void 0;
|
|
59
|
+
if (creditsTracked) {
|
|
60
|
+
signals.push(this.state.openRouterCredits < openRouterMinCredits);
|
|
61
|
+
}
|
|
62
|
+
if (apiMinCredits && this.state.apiCredits) {
|
|
63
|
+
for (const [resource, min] of Object.entries(apiMinCredits)) {
|
|
64
|
+
const current = this.state.apiCredits[resource];
|
|
65
|
+
if (current !== void 0) {
|
|
66
|
+
signals.push(current < min);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (!signals.length) return false;
|
|
71
|
+
return denyMode === "all" ? signals.every(Boolean) : signals.some(Boolean);
|
|
72
|
+
}
|
|
73
|
+
shouldWarn() {
|
|
74
|
+
const { solWarnBalance, openRouterWarnCredits, warnIntervalMs = 3e5 } = this.policy;
|
|
75
|
+
const solWarn = this.state.solBalance !== void 0 && Number.isFinite(solWarnBalance) && this.state.solBalance < solWarnBalance;
|
|
76
|
+
const apiWarnCredits = sanitizeCreditMap(this.policy.apiWarnCredits);
|
|
77
|
+
const shouldUseLegacyOpenRouterWarn = openRouterWarnCredits !== void 0 && (!apiWarnCredits || apiWarnCredits[OPENROUTER_RESOURCE_KEY] === void 0);
|
|
78
|
+
const creditsWarn = shouldUseLegacyOpenRouterWarn && this.state.openRouterCredits !== void 0 && this.state.openRouterCredits < openRouterWarnCredits;
|
|
79
|
+
let apiWarn = false;
|
|
80
|
+
if (apiWarnCredits && this.state.apiCredits) {
|
|
81
|
+
for (const [resource, min] of Object.entries(apiWarnCredits)) {
|
|
82
|
+
const current = this.state.apiCredits[resource];
|
|
83
|
+
if (current !== void 0 && current < min) {
|
|
84
|
+
apiWarn = true;
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (!solWarn && !creditsWarn && !apiWarn) return false;
|
|
90
|
+
const lastWarnAt = this.state.lastWarnAt ?? 0;
|
|
91
|
+
return now() - lastWarnAt > warnIntervalMs;
|
|
92
|
+
}
|
|
93
|
+
async enforce() {
|
|
94
|
+
if (this.isLow()) {
|
|
95
|
+
if (this.events.onCritical) {
|
|
96
|
+
this.events.onCritical(this.getState());
|
|
97
|
+
}
|
|
98
|
+
if (this.events.onPersist) {
|
|
99
|
+
await this.events.onPersist(this.getState());
|
|
100
|
+
}
|
|
101
|
+
return this.policy.allowIfLow ? "allow" : "deny";
|
|
102
|
+
}
|
|
103
|
+
if (this.shouldWarn()) {
|
|
104
|
+
this.state.lastWarnAt = now();
|
|
105
|
+
if (this.events.onWarn) {
|
|
106
|
+
this.events.onWarn(this.getState());
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return "allow";
|
|
110
|
+
}
|
|
111
|
+
guard = async () => {
|
|
112
|
+
const decision = await this.enforce();
|
|
113
|
+
return decision === "allow";
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
|
+
var createSelfReliancePolicy = (overrides = {}) => ({
|
|
117
|
+
solMinBalance: 0.01,
|
|
118
|
+
solWarnBalance: 0.05,
|
|
119
|
+
openRouterMinCredits: 1,
|
|
120
|
+
openRouterWarnCredits: 5,
|
|
121
|
+
apiMinCredits: { openrouter: 1 },
|
|
122
|
+
apiWarnCredits: { openrouter: 5 },
|
|
123
|
+
allowIfLow: false,
|
|
124
|
+
denyMode: "all",
|
|
125
|
+
warnIntervalMs: 3e5,
|
|
126
|
+
criticalOnly: false,
|
|
127
|
+
...overrides
|
|
128
|
+
});
|
|
129
|
+
var createSurvivalMiddleware = (survival, options = {}) => {
|
|
130
|
+
const errorStatus = options.errorStatus ?? 402;
|
|
131
|
+
const errorPayload = options.errorPayload ?? { error: "survival_low_funds" };
|
|
132
|
+
return async (req, res, next) => {
|
|
133
|
+
const allowed = await survival.guard();
|
|
134
|
+
const state = survival.getState();
|
|
135
|
+
if (!allowed) {
|
|
136
|
+
if (options.onDeny) {
|
|
137
|
+
options.onDeny(state);
|
|
138
|
+
}
|
|
139
|
+
res.status(errorStatus).json(errorPayload);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
next();
|
|
143
|
+
};
|
|
144
|
+
};
|
|
145
|
+
var withSurvival = async (survival, handler, options = {}) => {
|
|
146
|
+
const allowed = await survival.guard();
|
|
147
|
+
if (!allowed) {
|
|
148
|
+
if (options.onDeny) {
|
|
149
|
+
options.onDeny(survival.getState());
|
|
150
|
+
}
|
|
151
|
+
throw new Error("survival_low_funds");
|
|
152
|
+
}
|
|
153
|
+
return handler();
|
|
154
|
+
};
|
|
155
|
+
var createSelfRelianceMonitor = (survival, fetchSnapshot, config = {}) => {
|
|
156
|
+
const intervalMs = config.intervalMs ?? 3e4;
|
|
157
|
+
let timer = null;
|
|
158
|
+
let stopped = false;
|
|
159
|
+
const runOnce = async () => {
|
|
160
|
+
try {
|
|
161
|
+
const snapshot = await fetchSnapshot();
|
|
162
|
+
const state = survival.update(snapshot);
|
|
163
|
+
if (config.onUpdate) {
|
|
164
|
+
config.onUpdate(snapshot, state);
|
|
165
|
+
}
|
|
166
|
+
await survival.enforce();
|
|
167
|
+
} catch (err) {
|
|
168
|
+
if (config.onError) {
|
|
169
|
+
config.onError(err instanceof Error ? err : new Error("monitor_failed"));
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
const start = async () => {
|
|
174
|
+
if (timer) return;
|
|
175
|
+
await runOnce();
|
|
176
|
+
if (stopped) return;
|
|
177
|
+
timer = setInterval(runOnce, intervalMs);
|
|
178
|
+
};
|
|
179
|
+
const stop = () => {
|
|
180
|
+
stopped = true;
|
|
181
|
+
if (timer) {
|
|
182
|
+
clearInterval(timer);
|
|
183
|
+
timer = null;
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
return { start, stop, runOnce };
|
|
187
|
+
};
|
|
188
|
+
var createAutoSelfReliance = (options) => {
|
|
189
|
+
const { survival, fetchSnapshot, intervalMs, onUpdate, onError } = options;
|
|
190
|
+
return createSelfRelianceMonitor(survival, fetchSnapshot, {
|
|
191
|
+
intervalMs,
|
|
192
|
+
onUpdate,
|
|
193
|
+
onError
|
|
194
|
+
});
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
export {
|
|
198
|
+
SelfReliance,
|
|
199
|
+
createSelfReliancePolicy,
|
|
200
|
+
createSurvivalMiddleware,
|
|
201
|
+
withSurvival,
|
|
202
|
+
createSelfRelianceMonitor,
|
|
203
|
+
createAutoSelfReliance
|
|
204
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as _solana_web3_js from '@solana/web3.js';
|
|
2
2
|
import { L as ListingRecord, a as ListingType, b as ListingStatus, C as ClaimPurpose, c as ClaimResponse, V as VerifiedClaimResponse, d as ListingInput, e as ListingReviewRecord, T as TicketVerifyResponse } from './solana-3VMnBZH6.js';
|
|
3
3
|
export { f as fetchSolBalance, g as fetchTokenBalance, h as fetchTokenBalances } from './solana-3VMnBZH6.js';
|
|
4
|
+
import { SelfReliancePolicy } from './selfReliance.js';
|
|
4
5
|
export { SelfReliance, createAutoSelfReliance, createSelfRelianceMonitor, createSelfReliancePolicy, createSurvivalMiddleware, withSurvival } from './selfReliance.js';
|
|
5
6
|
import '@coral-xyz/anchor';
|
|
6
7
|
|
|
@@ -737,9 +738,43 @@ type OpenRouterCredits = {
|
|
|
737
738
|
type ResourceSnapshot = {
|
|
738
739
|
solBalance?: number;
|
|
739
740
|
openRouterCredits?: number;
|
|
741
|
+
apiCredits?: Record<string, number>;
|
|
740
742
|
tokenBalances?: Record<string, number>;
|
|
741
743
|
updatedAt?: number;
|
|
742
744
|
};
|
|
745
|
+
type ApiCreditProvider = {
|
|
746
|
+
name: string;
|
|
747
|
+
fetchCredits: () => Promise<number>;
|
|
748
|
+
};
|
|
749
|
+
type ApiCreditProviderPreset = 'openrouter' | 'anthropic' | 'gemini' | 'custom';
|
|
750
|
+
type ApiCreditProviderPresetInput = {
|
|
751
|
+
provider: ApiCreditProviderPreset | string;
|
|
752
|
+
name?: string;
|
|
753
|
+
apiKey?: string;
|
|
754
|
+
apiKeyEnv?: string;
|
|
755
|
+
endpoint?: string;
|
|
756
|
+
method?: 'GET' | 'POST';
|
|
757
|
+
headers?: Record<string, string>;
|
|
758
|
+
body?: unknown;
|
|
759
|
+
creditsPath?: string;
|
|
760
|
+
};
|
|
761
|
+
type ApiCreditProviderFactoryOptions = {
|
|
762
|
+
apiBase?: string;
|
|
763
|
+
fetcher?: typeof fetch;
|
|
764
|
+
resolveSecret?: (name: string) => string | undefined | Promise<string | undefined>;
|
|
765
|
+
};
|
|
766
|
+
type ResourceProviderManifestEntry = {
|
|
767
|
+
provider: ApiCreditProviderPreset | string;
|
|
768
|
+
name?: string;
|
|
769
|
+
apiKeyEnv?: string;
|
|
770
|
+
endpoint?: string;
|
|
771
|
+
method?: 'GET' | 'POST';
|
|
772
|
+
headers?: Record<string, string>;
|
|
773
|
+
creditsPath?: string;
|
|
774
|
+
};
|
|
775
|
+
type AgentResourceProvidersManifest = {
|
|
776
|
+
resourceProviders?: ResourceProviderManifestEntry[];
|
|
777
|
+
};
|
|
743
778
|
interface ListingQuery {
|
|
744
779
|
type?: ListingType;
|
|
745
780
|
status?: ListingStatus;
|
|
@@ -1000,6 +1035,12 @@ declare const buildShareLink: (listingId: string, options?: MarketingLinkOptions
|
|
|
1000
1035
|
declare const buildShareCopy: (listing: ListingRecord, options?: MarketingLinkOptions) => string;
|
|
1001
1036
|
declare const buildBadgeMarkdown: (listing: ListingRecord, options?: MarketingLinkOptions) => string;
|
|
1002
1037
|
declare const createCampaign: (listingId: string, options?: MarketingLinkOptions) => MarketingCampaign;
|
|
1038
|
+
declare const createApiCreditProvider: (input: ApiCreditProviderPresetInput, options?: ApiCreditProviderFactoryOptions) => Promise<ApiCreditProvider>;
|
|
1039
|
+
declare const createApiCreditProviders: (inputs: ApiCreditProviderPresetInput[], options?: ApiCreditProviderFactoryOptions) => Promise<ApiCreditProvider[]>;
|
|
1040
|
+
declare const createApiCreditProvidersFromManifest: (manifest: AgentResourceProvidersManifest, options?: ApiCreditProviderFactoryOptions) => Promise<ApiCreditProvider[]>;
|
|
1041
|
+
declare const assertSurvivalProvidersConfigured: (policy: Pick<SelfReliancePolicy, "openRouterMinCredits" | "openRouterWarnCredits" | "apiMinCredits" | "apiWarnCredits">, providers: ApiCreditProvider[], options?: {
|
|
1042
|
+
hasOpenRouterApiKey?: boolean;
|
|
1043
|
+
}) => void;
|
|
1003
1044
|
declare const buildRaydiumSwapUrl: (tokenMint: string) => string;
|
|
1004
1045
|
declare const buildJupiterSwapUrl: (tokenMint: string) => string;
|
|
1005
1046
|
declare const buildTradeLinks: (tokenMint: string) => {
|
|
@@ -1012,7 +1053,8 @@ declare const getResourceSnapshot: (options: {
|
|
|
1012
1053
|
wallet: string | _solana_web3_js.PublicKey;
|
|
1013
1054
|
tokenMints?: Array<string | _solana_web3_js.PublicKey>;
|
|
1014
1055
|
openRouterApiKey?: string;
|
|
1056
|
+
apiCreditProviders?: ApiCreditProvider[];
|
|
1015
1057
|
apiBase?: string;
|
|
1016
1058
|
}) => Promise<ResourceSnapshot>;
|
|
1017
1059
|
|
|
1018
|
-
export { type AnalyticsPoint, type ApiResponse, type BuybackEvent, ClaimPurpose, ClaimResponse, LISTING_NAME_MAX_LENGTH, LISTING_NAME_RECOMMENDED_MAX, LISTING_TAGLINE_MAX_LENGTH, LISTING_TAGLINE_RECOMMENDED_MAX, type LeaderboardEntry, type LeaderboardQuery, ListingInput, type ListingNamingValidationOptions, type ListingNamingValidationResult, type ListingQuery, ListingRecord, type ListingReviewCreatePayload, ListingReviewRecord, type ListingReviewResponsePayload, ListingStatus, ListingType, type ListingVersionPayload, type MarketingCampaign, type MarketingLinkOptions, type MemoryPingChallengeResponse, type MemoryPingPayload, type OpenRouterCredits, type ResourceSnapshot, ReviewGate, type ReviewGateRecord, type ReviewRequiredPayload, type SdkUpdateCheckOptions, type SdkUpdatePolicyCheckOptions, SdkUpdateRequiredError, type SdkUpdateStatus, TicketVerifyResponse, VIBEIAO_IDL, VerifiedClaimResponse, VibeClient, type VibeClientOptions, VibeRegistry, buildBadgeMarkdown, buildClaimMessage, buildJupiterSwapUrl, buildListingVersionMessage, buildMemoryPingMessage, buildOwnerTransferMessage, buildRaydiumSwapUrl, buildReviewPrompt, buildReviewRequired, buildReviewResponseMessage, buildSdkUpdateCommand, buildShareCopy, buildShareLink, buildTradeLinks, checkForSdkUpdate, checkForSdkUpdatePolicy, compareVersions, createCampaign, getResourceSnapshot, normalizeListingText, sanitizeListingNaming, validateListingNaming };
|
|
1060
|
+
export { type AgentResourceProvidersManifest, type AnalyticsPoint, type ApiCreditProvider, type ApiCreditProviderFactoryOptions, type ApiCreditProviderPreset, type ApiCreditProviderPresetInput, type ApiResponse, type BuybackEvent, ClaimPurpose, ClaimResponse, LISTING_NAME_MAX_LENGTH, LISTING_NAME_RECOMMENDED_MAX, LISTING_TAGLINE_MAX_LENGTH, LISTING_TAGLINE_RECOMMENDED_MAX, type LeaderboardEntry, type LeaderboardQuery, ListingInput, type ListingNamingValidationOptions, type ListingNamingValidationResult, type ListingQuery, ListingRecord, type ListingReviewCreatePayload, ListingReviewRecord, type ListingReviewResponsePayload, ListingStatus, ListingType, type ListingVersionPayload, type MarketingCampaign, type MarketingLinkOptions, type MemoryPingChallengeResponse, type MemoryPingPayload, type OpenRouterCredits, type ResourceProviderManifestEntry, type ResourceSnapshot, ReviewGate, type ReviewGateRecord, type ReviewRequiredPayload, type SdkUpdateCheckOptions, type SdkUpdatePolicyCheckOptions, SdkUpdateRequiredError, type SdkUpdateStatus, TicketVerifyResponse, VIBEIAO_IDL, VerifiedClaimResponse, VibeClient, type VibeClientOptions, VibeRegistry, assertSurvivalProvidersConfigured, buildBadgeMarkdown, buildClaimMessage, buildJupiterSwapUrl, buildListingVersionMessage, buildMemoryPingMessage, buildOwnerTransferMessage, buildRaydiumSwapUrl, buildReviewPrompt, buildReviewRequired, buildReviewResponseMessage, buildSdkUpdateCommand, buildShareCopy, buildShareLink, buildTradeLinks, checkForSdkUpdate, checkForSdkUpdatePolicy, compareVersions, createApiCreditProvider, createApiCreditProviders, createApiCreditProvidersFromManifest, createCampaign, getResourceSnapshot, normalizeListingText, sanitizeListingNaming, validateListingNaming };
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
createSelfReliancePolicy,
|
|
6
6
|
createSurvivalMiddleware,
|
|
7
7
|
withSurvival
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-M7DQTU5R.js";
|
|
9
9
|
import {
|
|
10
10
|
VIBEIAO_IDL,
|
|
11
11
|
fetchSolBalance,
|
|
@@ -114,7 +114,7 @@ var ReviewGate = class {
|
|
|
114
114
|
var DEFAULT_API_BASE = "https://api.vibeiao.com";
|
|
115
115
|
var DEFAULT_WEB_BASE = "https://vibeiao.com";
|
|
116
116
|
var DEFAULT_SDK_PACKAGE = "@vibeiao/sdk";
|
|
117
|
-
var DEFAULT_SDK_VERSION = "0.1.
|
|
117
|
+
var DEFAULT_SDK_VERSION = "0.1.10" ? "0.1.10" : "0.1.4";
|
|
118
118
|
var DEFAULT_SDK_REGISTRY = "https://registry.npmjs.org";
|
|
119
119
|
var DEFAULT_SDK_POLICY_PATH = "/v1/sdk/policy";
|
|
120
120
|
var DEFAULT_SDK_CHECK_INTERVAL_MS = 1e3 * 60 * 30;
|
|
@@ -261,6 +261,49 @@ var unwrap = (response) => {
|
|
|
261
261
|
}
|
|
262
262
|
return response.data;
|
|
263
263
|
};
|
|
264
|
+
var normalizeProviderName = (value) => value.trim().toLowerCase().replace(/[^a-z0-9_-]/g, "");
|
|
265
|
+
var getByPath = (payload, path) => {
|
|
266
|
+
if (!path) return void 0;
|
|
267
|
+
const segments = path.split(".").map((part) => part.trim()).filter(Boolean);
|
|
268
|
+
let current = payload;
|
|
269
|
+
for (const segment of segments) {
|
|
270
|
+
if (!current || typeof current !== "object" || !(segment in current)) {
|
|
271
|
+
return void 0;
|
|
272
|
+
}
|
|
273
|
+
current = current[segment];
|
|
274
|
+
}
|
|
275
|
+
return current;
|
|
276
|
+
};
|
|
277
|
+
var extractCreditsFromPayload = (payload, creditsPath) => {
|
|
278
|
+
const direct = getByPath(payload, creditsPath);
|
|
279
|
+
let credits = pickFinite(
|
|
280
|
+
direct,
|
|
281
|
+
payload?.credits,
|
|
282
|
+
payload?.remaining_credits,
|
|
283
|
+
payload?.remainingCredits,
|
|
284
|
+
payload?.balance,
|
|
285
|
+
payload?.remaining
|
|
286
|
+
);
|
|
287
|
+
if (Number.isFinite(credits)) return credits;
|
|
288
|
+
const nested = payload?.data;
|
|
289
|
+
credits = pickFinite(
|
|
290
|
+
nested?.credits,
|
|
291
|
+
nested?.remaining_credits,
|
|
292
|
+
nested?.remainingCredits,
|
|
293
|
+
nested?.balance,
|
|
294
|
+
nested?.remaining
|
|
295
|
+
);
|
|
296
|
+
return credits;
|
|
297
|
+
};
|
|
298
|
+
var defaultApiKeyEnvForProvider = (provider) => {
|
|
299
|
+
const normalized = normalizeProviderName(provider);
|
|
300
|
+
if (normalized === "openrouter") return "OPENROUTER_API_KEY";
|
|
301
|
+
if (normalized === "anthropic") return "ANTHROPIC_API_KEY";
|
|
302
|
+
if (normalized === "gemini") return "GEMINI_API_KEY";
|
|
303
|
+
return `${normalized.toUpperCase()}_API_KEY`;
|
|
304
|
+
};
|
|
305
|
+
var providerConfigError = (providerName, detail, nextStep) => `provider_config_error:${providerName}:${detail}. ${nextStep}`;
|
|
306
|
+
var providerFetchError = (providerName, detail) => `provider_fetch_failed:${providerName}:${detail}`;
|
|
264
307
|
var generateRef = () => {
|
|
265
308
|
const cryptoObj = globalThis.crypto;
|
|
266
309
|
if (cryptoObj?.randomUUID) {
|
|
@@ -716,6 +759,145 @@ var createCampaign = (listingId, options = {}) => {
|
|
|
716
759
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
717
760
|
};
|
|
718
761
|
};
|
|
762
|
+
var createApiCreditProvider = async (input, options = {}) => {
|
|
763
|
+
const providerRaw = String(input.provider || "").trim();
|
|
764
|
+
const provider = normalizeProviderName(providerRaw || input.name || "custom");
|
|
765
|
+
const providerName = normalizeProviderName(input.name || provider || "custom");
|
|
766
|
+
if (!provider) {
|
|
767
|
+
throw new Error(
|
|
768
|
+
providerConfigError("unknown", "provider_missing", "Set provider to openrouter/anthropic/gemini/custom.")
|
|
769
|
+
);
|
|
770
|
+
}
|
|
771
|
+
const resolveSecret = options.resolveSecret;
|
|
772
|
+
const apiKeyEnv = input.apiKeyEnv || defaultApiKeyEnvForProvider(provider);
|
|
773
|
+
const resolvedSecret = resolveSecret ? await resolveSecret(apiKeyEnv) : void 0;
|
|
774
|
+
const apiKey = input.apiKey || resolvedSecret;
|
|
775
|
+
const fetcher = options.fetcher || fetch;
|
|
776
|
+
if (provider === "openrouter") {
|
|
777
|
+
if (!apiKey) {
|
|
778
|
+
throw new Error(
|
|
779
|
+
providerConfigError(
|
|
780
|
+
providerName,
|
|
781
|
+
"api_key_missing",
|
|
782
|
+
`Ask your human owner to provide ${apiKeyEnv} or set apiKey directly.`
|
|
783
|
+
)
|
|
784
|
+
);
|
|
785
|
+
}
|
|
786
|
+
return {
|
|
787
|
+
name: providerName,
|
|
788
|
+
fetchCredits: async () => {
|
|
789
|
+
const client = new VibeClient({ baseUrl: options.apiBase, fetcher });
|
|
790
|
+
const result = await client.getOpenRouterCreditsValue(apiKey);
|
|
791
|
+
if (result.error) {
|
|
792
|
+
throw new Error(providerFetchError(providerName, result.error));
|
|
793
|
+
}
|
|
794
|
+
return Number(result.data);
|
|
795
|
+
}
|
|
796
|
+
};
|
|
797
|
+
}
|
|
798
|
+
if (!input.endpoint) {
|
|
799
|
+
throw new Error(
|
|
800
|
+
providerConfigError(
|
|
801
|
+
providerName,
|
|
802
|
+
"endpoint_missing",
|
|
803
|
+
"Set endpoint to the provider credit/balance API URL."
|
|
804
|
+
)
|
|
805
|
+
);
|
|
806
|
+
}
|
|
807
|
+
if (!apiKey) {
|
|
808
|
+
throw new Error(
|
|
809
|
+
providerConfigError(
|
|
810
|
+
providerName,
|
|
811
|
+
"api_key_missing",
|
|
812
|
+
`Ask your human owner to provide ${apiKeyEnv} or set apiKey directly.`
|
|
813
|
+
)
|
|
814
|
+
);
|
|
815
|
+
}
|
|
816
|
+
return {
|
|
817
|
+
name: providerName,
|
|
818
|
+
fetchCredits: async () => {
|
|
819
|
+
const headers = { ...input.headers || {} };
|
|
820
|
+
const hasAuthHeader = Object.keys(headers).some((key) => key.toLowerCase() === "authorization");
|
|
821
|
+
const hasApiKeyHeader = Object.keys(headers).some((key) => key.toLowerCase() === "x-api-key");
|
|
822
|
+
if (provider === "anthropic") {
|
|
823
|
+
if (!hasApiKeyHeader) headers["x-api-key"] = apiKey;
|
|
824
|
+
if (!headers["anthropic-version"]) headers["anthropic-version"] = "2023-06-01";
|
|
825
|
+
} else if (!hasAuthHeader && !hasApiKeyHeader) {
|
|
826
|
+
headers.Authorization = `Bearer ${apiKey}`;
|
|
827
|
+
}
|
|
828
|
+
const method = input.method || (input.body !== void 0 ? "POST" : "GET");
|
|
829
|
+
const hasContentType = Object.keys(headers).some((key) => key.toLowerCase() === "content-type");
|
|
830
|
+
const body = input.body !== void 0 ? typeof input.body === "string" ? input.body : JSON.stringify(input.body) : void 0;
|
|
831
|
+
if (body && !hasContentType) {
|
|
832
|
+
headers["Content-Type"] = "application/json";
|
|
833
|
+
}
|
|
834
|
+
let response;
|
|
835
|
+
try {
|
|
836
|
+
response = await fetcher(input.endpoint, { method, headers, body });
|
|
837
|
+
} catch (error) {
|
|
838
|
+
const message = error instanceof Error ? error.message : "network_error";
|
|
839
|
+
throw new Error(providerFetchError(providerName, message));
|
|
840
|
+
}
|
|
841
|
+
const payload = await readJson(response);
|
|
842
|
+
if (!response.ok) {
|
|
843
|
+
const detail = String(payload?.error || `http_${response.status}`);
|
|
844
|
+
throw new Error(providerFetchError(providerName, detail));
|
|
845
|
+
}
|
|
846
|
+
const credits = extractCreditsFromPayload(payload, input.creditsPath);
|
|
847
|
+
if (!Number.isFinite(credits)) {
|
|
848
|
+
throw new Error(
|
|
849
|
+
providerFetchError(
|
|
850
|
+
providerName,
|
|
851
|
+
`credits_unavailable (set creditsPath, current=${input.creditsPath || "auto"})`
|
|
852
|
+
)
|
|
853
|
+
);
|
|
854
|
+
}
|
|
855
|
+
return credits;
|
|
856
|
+
}
|
|
857
|
+
};
|
|
858
|
+
};
|
|
859
|
+
var createApiCreditProviders = async (inputs, options = {}) => {
|
|
860
|
+
const providers = [];
|
|
861
|
+
for (const input of inputs) {
|
|
862
|
+
providers.push(await createApiCreditProvider(input, options));
|
|
863
|
+
}
|
|
864
|
+
return providers;
|
|
865
|
+
};
|
|
866
|
+
var createApiCreditProvidersFromManifest = async (manifest, options = {}) => {
|
|
867
|
+
const entries = manifest.resourceProviders || [];
|
|
868
|
+
const configs = entries.map((entry) => ({
|
|
869
|
+
provider: entry.provider,
|
|
870
|
+
name: entry.name,
|
|
871
|
+
apiKeyEnv: entry.apiKeyEnv,
|
|
872
|
+
endpoint: entry.endpoint,
|
|
873
|
+
method: entry.method,
|
|
874
|
+
headers: entry.headers,
|
|
875
|
+
creditsPath: entry.creditsPath
|
|
876
|
+
}));
|
|
877
|
+
return createApiCreditProviders(configs, options);
|
|
878
|
+
};
|
|
879
|
+
var assertSurvivalProvidersConfigured = (policy, providers, options = {}) => {
|
|
880
|
+
const required = /* @__PURE__ */ new Set();
|
|
881
|
+
if (policy.openRouterMinCredits !== void 0 || policy.openRouterWarnCredits !== void 0) {
|
|
882
|
+
required.add("openrouter");
|
|
883
|
+
}
|
|
884
|
+
const addFromMap = (map) => {
|
|
885
|
+
if (!map) return;
|
|
886
|
+
Object.keys(map).forEach((name) => required.add(normalizeProviderName(name)));
|
|
887
|
+
};
|
|
888
|
+
addFromMap(policy.apiMinCredits);
|
|
889
|
+
addFromMap(policy.apiWarnCredits);
|
|
890
|
+
const available = new Set((providers || []).map((provider) => normalizeProviderName(provider.name)));
|
|
891
|
+
if (options.hasOpenRouterApiKey) {
|
|
892
|
+
available.add("openrouter");
|
|
893
|
+
}
|
|
894
|
+
const missing = Array.from(required).filter((name) => !available.has(name));
|
|
895
|
+
if (missing.length) {
|
|
896
|
+
throw new Error(
|
|
897
|
+
`survival_provider_missing:${missing.join(",")}. Configure apiCreditProviders (or api keys), or remove thresholds for missing providers.`
|
|
898
|
+
);
|
|
899
|
+
}
|
|
900
|
+
};
|
|
719
901
|
var buildRaydiumSwapUrl = (tokenMint) => `https://raydium.io/swap/?inputCurrency=sol&outputCurrency=${tokenMint}`;
|
|
720
902
|
var buildJupiterSwapUrl = (tokenMint) => `https://jup.ag/swap/SOL-${tokenMint}`;
|
|
721
903
|
var buildTradeLinks = (tokenMint) => ({
|
|
@@ -723,8 +905,9 @@ var buildTradeLinks = (tokenMint) => ({
|
|
|
723
905
|
jupiter: buildJupiterSwapUrl(tokenMint)
|
|
724
906
|
});
|
|
725
907
|
var getResourceSnapshot = async (options) => {
|
|
726
|
-
const { connection, wallet, tokenMints, openRouterApiKey, apiBase } = options;
|
|
908
|
+
const { connection, wallet, tokenMints, openRouterApiKey, apiCreditProviders, apiBase } = options;
|
|
727
909
|
const snapshot = { updatedAt: Date.now() };
|
|
910
|
+
const apiCredits = {};
|
|
728
911
|
snapshot.solBalance = await fetchSolBalance(connection, wallet);
|
|
729
912
|
if (tokenMints?.length) {
|
|
730
913
|
snapshot.tokenBalances = await fetchTokenBalances(connection, wallet, tokenMints);
|
|
@@ -736,6 +919,33 @@ var getResourceSnapshot = async (options) => {
|
|
|
736
919
|
throw new Error(credits.error);
|
|
737
920
|
}
|
|
738
921
|
snapshot.openRouterCredits = credits.data;
|
|
922
|
+
apiCredits.openrouter = credits.data;
|
|
923
|
+
}
|
|
924
|
+
if (apiCreditProviders?.length) {
|
|
925
|
+
for (const provider of apiCreditProviders) {
|
|
926
|
+
const name = String(provider?.name || "").trim().toLowerCase();
|
|
927
|
+
if (!name || typeof provider.fetchCredits !== "function") continue;
|
|
928
|
+
try {
|
|
929
|
+
const value = Number(await provider.fetchCredits());
|
|
930
|
+
if (Number.isFinite(value)) {
|
|
931
|
+
apiCredits[name] = value;
|
|
932
|
+
}
|
|
933
|
+
} catch (error) {
|
|
934
|
+
const message = error instanceof Error ? error.message : "unknown_error";
|
|
935
|
+
throw new Error(
|
|
936
|
+
providerFetchError(
|
|
937
|
+
name,
|
|
938
|
+
`${message}. Ask your human owner to provision/refill this provider key if needed.`
|
|
939
|
+
)
|
|
940
|
+
);
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
if (Object.keys(apiCredits).length > 0) {
|
|
945
|
+
snapshot.apiCredits = apiCredits;
|
|
946
|
+
if (snapshot.openRouterCredits === void 0 && apiCredits.openrouter !== void 0) {
|
|
947
|
+
snapshot.openRouterCredits = apiCredits.openrouter;
|
|
948
|
+
}
|
|
739
949
|
}
|
|
740
950
|
return snapshot;
|
|
741
951
|
};
|
|
@@ -750,6 +960,7 @@ export {
|
|
|
750
960
|
VIBEIAO_IDL,
|
|
751
961
|
VibeClient,
|
|
752
962
|
VibeRegistry,
|
|
963
|
+
assertSurvivalProvidersConfigured,
|
|
753
964
|
buildBadgeMarkdown,
|
|
754
965
|
buildClaimMessage,
|
|
755
966
|
buildJupiterSwapUrl,
|
|
@@ -767,6 +978,9 @@ export {
|
|
|
767
978
|
checkForSdkUpdate,
|
|
768
979
|
checkForSdkUpdatePolicy,
|
|
769
980
|
compareVersions,
|
|
981
|
+
createApiCreditProvider,
|
|
982
|
+
createApiCreditProviders,
|
|
983
|
+
createApiCreditProvidersFromManifest,
|
|
770
984
|
createAutoSelfReliance,
|
|
771
985
|
createCampaign,
|
|
772
986
|
createSelfRelianceMonitor,
|
package/dist/selfReliance.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ type SelfReliancePolicy = {
|
|
|
3
3
|
solWarnBalance: number;
|
|
4
4
|
openRouterMinCredits?: number;
|
|
5
5
|
openRouterWarnCredits?: number;
|
|
6
|
+
apiMinCredits?: Record<string, number>;
|
|
7
|
+
apiWarnCredits?: Record<string, number>;
|
|
6
8
|
allowIfLow?: boolean;
|
|
7
9
|
denyMode?: 'any' | 'all';
|
|
8
10
|
solHardMin?: number;
|
|
@@ -12,6 +14,7 @@ type SelfReliancePolicy = {
|
|
|
12
14
|
type SelfRelianceState = {
|
|
13
15
|
solBalance?: number;
|
|
14
16
|
openRouterCredits?: number;
|
|
17
|
+
apiCredits?: Record<string, number>;
|
|
15
18
|
lastWarnAt?: number;
|
|
16
19
|
lastUpdatedAt?: number;
|
|
17
20
|
};
|
|
@@ -27,6 +30,7 @@ type SelfRelianceConfig = {
|
|
|
27
30
|
type ResourceSnapshot = {
|
|
28
31
|
solBalance?: number;
|
|
29
32
|
openRouterCredits?: number;
|
|
33
|
+
apiCredits?: Record<string, number>;
|
|
30
34
|
tokenBalances?: Record<string, number>;
|
|
31
35
|
updatedAt?: number;
|
|
32
36
|
};
|
|
@@ -39,6 +43,7 @@ declare class SelfReliance {
|
|
|
39
43
|
getState(): {
|
|
40
44
|
solBalance?: number;
|
|
41
45
|
openRouterCredits?: number;
|
|
46
|
+
apiCredits?: Record<string, number>;
|
|
42
47
|
lastWarnAt?: number;
|
|
43
48
|
lastUpdatedAt?: number;
|
|
44
49
|
};
|
package/dist/selfReliance.js
CHANGED