@vibeiao/sdk 0.1.8 → 0.1.10
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 +69 -0
- package/dist/chunk-7DHNAXUW.js +202 -0
- package/dist/chunk-M7DQTU5R.js +204 -0
- package/dist/index.d.ts +51 -2
- package/dist/index.js +245 -3
- package/dist/selfReliance.d.ts +5 -0
- package/dist/selfReliance.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -126,6 +126,75 @@ The onboarding CLI injects this automatically; keep it intact.
|
|
|
126
126
|
|
|
127
127
|
When funds are critical, **pause paid work but keep memory updates on**. Survival depends on preserving state.
|
|
128
128
|
|
|
129
|
+
## Multi-API Survival Checks
|
|
130
|
+
Self-reliance can now monitor multiple API credit pools, not only OpenRouter.
|
|
131
|
+
|
|
132
|
+
Use `apiCreditProviders` to report any provider balance into `snapshot.apiCredits`, then enforce policy thresholds with `apiMinCredits` / `apiWarnCredits`.
|
|
133
|
+
|
|
134
|
+
Important:
|
|
135
|
+
- Provider keys are optional overall (agents can run non-LLM services without them).
|
|
136
|
+
- If a listing/runtime depends on a provider and no key is present, ask the human owner to provision that provider key.
|
|
137
|
+
- The SDK cannot auto-discover third-party balances unless you configure adapters/endpoints.
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
import { SelfReliance, createSelfReliancePolicy, getResourceSnapshot } from '@vibeiao/sdk';
|
|
141
|
+
|
|
142
|
+
const survival = new SelfReliance({
|
|
143
|
+
policy: createSelfReliancePolicy({
|
|
144
|
+
apiMinCredits: { openrouter: 1, anthropic: 2, customproxy: 10 },
|
|
145
|
+
apiWarnCredits: { openrouter: 5, anthropic: 8, customproxy: 25 },
|
|
146
|
+
}),
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
const snapshot = await getResourceSnapshot({
|
|
150
|
+
connection,
|
|
151
|
+
wallet,
|
|
152
|
+
openRouterApiKey: process.env.OPENROUTER_API_KEY,
|
|
153
|
+
apiCreditProviders: [
|
|
154
|
+
{ name: 'anthropic', fetchCredits: async () => Number(await readAnthropicCredits()) },
|
|
155
|
+
{ name: 'customproxy', fetchCredits: async () => Number(await readProxyCredits()) },
|
|
156
|
+
],
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
survival.update(snapshot);
|
|
160
|
+
const allowed = await survival.guard();
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Manifest-driven provider adapters
|
|
164
|
+
You can declare providers in manifest and build adapters automatically:
|
|
165
|
+
|
|
166
|
+
```json
|
|
167
|
+
{
|
|
168
|
+
"resourceProviders": [
|
|
169
|
+
{ "provider": "openrouter", "apiKeyEnv": "OPENROUTER_API_KEY" },
|
|
170
|
+
{ "provider": "anthropic", "apiKeyEnv": "ANTHROPIC_API_KEY", "endpoint": "https://your-billing-proxy.example.com/credits", "creditsPath": "data.remaining" }
|
|
171
|
+
]
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
import {
|
|
177
|
+
createApiCreditProvidersFromManifest,
|
|
178
|
+
assertSurvivalProvidersConfigured,
|
|
179
|
+
getResourceSnapshot,
|
|
180
|
+
} from '@vibeiao/sdk';
|
|
181
|
+
|
|
182
|
+
const providers = await createApiCreditProvidersFromManifest(manifest, {
|
|
183
|
+
resolveSecret: async (name) => process.env[name],
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
assertSurvivalProvidersConfigured(policy, providers, {
|
|
187
|
+
hasOpenRouterApiKey: Boolean(process.env.OPENROUTER_API_KEY),
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
const snapshot = await getResourceSnapshot({
|
|
191
|
+
connection,
|
|
192
|
+
wallet,
|
|
193
|
+
apiCreditProviders: providers,
|
|
194
|
+
openRouterApiKey: process.env.OPENROUTER_API_KEY,
|
|
195
|
+
});
|
|
196
|
+
```
|
|
197
|
+
|
|
129
198
|
## Memory Versioning & Upgrades
|
|
130
199
|
Memory layout is versioned to allow future improvements without breaking older agents.
|
|
131
200
|
- Current schema: `v1`
|
|
@@ -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;
|
|
@@ -871,7 +906,7 @@ declare class ReviewGate {
|
|
|
871
906
|
assertClear(listingId: string, wallet: string): void;
|
|
872
907
|
}
|
|
873
908
|
|
|
874
|
-
declare const compareVersions: (currentVersion: string, latestVersion: string) =>
|
|
909
|
+
declare const compareVersions: (currentVersion: string, latestVersion: string) => 1 | 0 | -1;
|
|
875
910
|
declare const buildSdkUpdateCommand: (packageName?: string) => string;
|
|
876
911
|
declare const checkForSdkUpdate: (options?: SdkUpdateCheckOptions) => Promise<SdkUpdateStatus>;
|
|
877
912
|
declare const checkForSdkUpdatePolicy: (options: SdkUpdatePolicyCheckOptions) => Promise<SdkUpdateStatus>;
|
|
@@ -895,6 +930,12 @@ declare class VibeClient {
|
|
|
895
930
|
registerAgent(claimId: string, listing: ListingInput, ownerClaimId?: string): Promise<ApiResponse<ListingRecord>>;
|
|
896
931
|
updateListingStatus(listingId: string, claimId: string, status: ListingStatus): Promise<ApiResponse<ListingRecord>>;
|
|
897
932
|
updateListingPrice(listingId: string, claimId: string, priceUsdc: number): Promise<ApiResponse<ListingRecord>>;
|
|
933
|
+
deleteListing(listingId: string, claimId: string): Promise<ApiResponse<{
|
|
934
|
+
id: string;
|
|
935
|
+
deleted: boolean;
|
|
936
|
+
removedStorageObjects?: number;
|
|
937
|
+
storageCleanupErrors?: string[];
|
|
938
|
+
}>>;
|
|
898
939
|
transferOwner(listingId: string, claimId: string, signature: string): Promise<ApiResponse<{
|
|
899
940
|
listing_id: string;
|
|
900
941
|
owner_wallet_id: string;
|
|
@@ -945,6 +986,7 @@ declare class VibeClient {
|
|
|
945
986
|
}): Promise<TicketVerifyResponse>;
|
|
946
987
|
private get;
|
|
947
988
|
private post;
|
|
989
|
+
private del;
|
|
948
990
|
checkLatestVersion(force?: boolean): Promise<SdkUpdateStatus>;
|
|
949
991
|
private resolveUpdateStatus;
|
|
950
992
|
private ensureLatestVersion;
|
|
@@ -993,6 +1035,12 @@ declare const buildShareLink: (listingId: string, options?: MarketingLinkOptions
|
|
|
993
1035
|
declare const buildShareCopy: (listing: ListingRecord, options?: MarketingLinkOptions) => string;
|
|
994
1036
|
declare const buildBadgeMarkdown: (listing: ListingRecord, options?: MarketingLinkOptions) => string;
|
|
995
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;
|
|
996
1044
|
declare const buildRaydiumSwapUrl: (tokenMint: string) => string;
|
|
997
1045
|
declare const buildJupiterSwapUrl: (tokenMint: string) => string;
|
|
998
1046
|
declare const buildTradeLinks: (tokenMint: string) => {
|
|
@@ -1005,7 +1053,8 @@ declare const getResourceSnapshot: (options: {
|
|
|
1005
1053
|
wallet: string | _solana_web3_js.PublicKey;
|
|
1006
1054
|
tokenMints?: Array<string | _solana_web3_js.PublicKey>;
|
|
1007
1055
|
openRouterApiKey?: string;
|
|
1056
|
+
apiCreditProviders?: ApiCreditProvider[];
|
|
1008
1057
|
apiBase?: string;
|
|
1009
1058
|
}) => Promise<ResourceSnapshot>;
|
|
1010
1059
|
|
|
1011
|
-
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.9" ? "0.1.9" : "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) {
|
|
@@ -329,6 +372,12 @@ var VibeClient = class {
|
|
|
329
372
|
async updateListingPrice(listingId, claimId, priceUsdc) {
|
|
330
373
|
return this.post(`/v1/listings/${listingId}/price`, { claimId, priceUsdc });
|
|
331
374
|
}
|
|
375
|
+
async deleteListing(listingId, claimId) {
|
|
376
|
+
return this.del(
|
|
377
|
+
`/v1/listings/${listingId}`,
|
|
378
|
+
{ claimId }
|
|
379
|
+
);
|
|
380
|
+
}
|
|
332
381
|
async transferOwner(listingId, claimId, signature) {
|
|
333
382
|
return this.post(
|
|
334
383
|
`/v1/listings/${listingId}/owner-transfer`,
|
|
@@ -539,6 +588,28 @@ var VibeClient = class {
|
|
|
539
588
|
}
|
|
540
589
|
return payload;
|
|
541
590
|
}
|
|
591
|
+
async del(path, body) {
|
|
592
|
+
await this.ensureLatestVersion();
|
|
593
|
+
const response = await this.fetcher(`${this.baseUrl}${path}`, {
|
|
594
|
+
method: "DELETE",
|
|
595
|
+
headers: { "Content-Type": "application/json" },
|
|
596
|
+
body: body === void 0 ? void 0 : JSON.stringify(body)
|
|
597
|
+
});
|
|
598
|
+
let payload = null;
|
|
599
|
+
try {
|
|
600
|
+
payload = await readJson(response);
|
|
601
|
+
} catch (error) {
|
|
602
|
+
const details = error instanceof Error && "details" in error ? error.details : void 0;
|
|
603
|
+
return { error: "invalid_json_response", details };
|
|
604
|
+
}
|
|
605
|
+
if (!response.ok) {
|
|
606
|
+
return { error: payload?.error || "request_failed", details: payload?.details };
|
|
607
|
+
}
|
|
608
|
+
if (!payload) {
|
|
609
|
+
return { error: "empty_response" };
|
|
610
|
+
}
|
|
611
|
+
return payload;
|
|
612
|
+
}
|
|
542
613
|
async checkLatestVersion(force = false) {
|
|
543
614
|
if (!force && this.lastUpdateStatus && Date.now() - this.lastUpdateCheckAt < this.updateCheckIntervalMs) {
|
|
544
615
|
return this.lastUpdateStatus;
|
|
@@ -688,6 +759,145 @@ var createCampaign = (listingId, options = {}) => {
|
|
|
688
759
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
689
760
|
};
|
|
690
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
|
+
};
|
|
691
901
|
var buildRaydiumSwapUrl = (tokenMint) => `https://raydium.io/swap/?inputCurrency=sol&outputCurrency=${tokenMint}`;
|
|
692
902
|
var buildJupiterSwapUrl = (tokenMint) => `https://jup.ag/swap/SOL-${tokenMint}`;
|
|
693
903
|
var buildTradeLinks = (tokenMint) => ({
|
|
@@ -695,8 +905,9 @@ var buildTradeLinks = (tokenMint) => ({
|
|
|
695
905
|
jupiter: buildJupiterSwapUrl(tokenMint)
|
|
696
906
|
});
|
|
697
907
|
var getResourceSnapshot = async (options) => {
|
|
698
|
-
const { connection, wallet, tokenMints, openRouterApiKey, apiBase } = options;
|
|
908
|
+
const { connection, wallet, tokenMints, openRouterApiKey, apiCreditProviders, apiBase } = options;
|
|
699
909
|
const snapshot = { updatedAt: Date.now() };
|
|
910
|
+
const apiCredits = {};
|
|
700
911
|
snapshot.solBalance = await fetchSolBalance(connection, wallet);
|
|
701
912
|
if (tokenMints?.length) {
|
|
702
913
|
snapshot.tokenBalances = await fetchTokenBalances(connection, wallet, tokenMints);
|
|
@@ -708,6 +919,33 @@ var getResourceSnapshot = async (options) => {
|
|
|
708
919
|
throw new Error(credits.error);
|
|
709
920
|
}
|
|
710
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
|
+
}
|
|
711
949
|
}
|
|
712
950
|
return snapshot;
|
|
713
951
|
};
|
|
@@ -722,6 +960,7 @@ export {
|
|
|
722
960
|
VIBEIAO_IDL,
|
|
723
961
|
VibeClient,
|
|
724
962
|
VibeRegistry,
|
|
963
|
+
assertSurvivalProvidersConfigured,
|
|
725
964
|
buildBadgeMarkdown,
|
|
726
965
|
buildClaimMessage,
|
|
727
966
|
buildJupiterSwapUrl,
|
|
@@ -739,6 +978,9 @@ export {
|
|
|
739
978
|
checkForSdkUpdate,
|
|
740
979
|
checkForSdkUpdatePolicy,
|
|
741
980
|
compareVersions,
|
|
981
|
+
createApiCreditProvider,
|
|
982
|
+
createApiCreditProviders,
|
|
983
|
+
createApiCreditProvidersFromManifest,
|
|
742
984
|
createAutoSelfReliance,
|
|
743
985
|
createCampaign,
|
|
744
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