@kaleidorg/mind 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/engine.d.ts +9 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +18 -2
- package/dist/engine.js.map +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/skills/bundle.d.ts +30 -0
- package/dist/skills/bundle.d.ts.map +1 -0
- package/dist/skills/bundle.js +24 -0
- package/dist/skills/bundle.js.map +1 -0
- package/dist/skills/loader.d.ts +33 -0
- package/dist/skills/loader.d.ts.map +1 -0
- package/dist/skills/loader.js +59 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/skills/reference-source.d.ts +18 -0
- package/dist/skills/reference-source.d.ts.map +1 -0
- package/dist/skills/reference-source.js +53 -0
- package/dist/skills/reference-source.js.map +1 -0
- package/dist/skills/registry.d.ts +41 -0
- package/dist/skills/registry.d.ts.map +1 -0
- package/dist/skills/registry.js +167 -0
- package/dist/skills/registry.js.map +1 -0
- package/dist/skills/types.d.ts +53 -0
- package/dist/skills/types.d.ts.map +1 -0
- package/dist/skills/types.js +18 -0
- package/dist/skills/types.js.map +1 -0
- package/dist/tools/l402.d.ts +47 -0
- package/dist/tools/l402.d.ts.map +1 -0
- package/dist/tools/l402.js +84 -0
- package/dist/tools/l402.js.map +1 -0
- package/package.json +9 -2
- package/scripts/bundle-skills.mjs +84 -0
- package/skills/README.md +74 -0
- package/skills/bitrefill/SKILL.md +66 -0
- package/skills/bitrefill/references/api.md +99 -0
- package/skills/bitrefill/references/browse.md +71 -0
- package/skills/bitrefill/references/capability-matrix.md +115 -0
- package/skills/bitrefill/references/cli-headless-auth.md +133 -0
- package/skills/bitrefill/references/cli.md +237 -0
- package/skills/bitrefill/references/host-openclaw.md +167 -0
- package/skills/bitrefill/references/mcp.md +150 -0
- package/skills/bitrefill/references/safeguards.md +138 -0
- package/skills/bitrefill/references/troubleshooting.md +182 -0
- package/skills/kaleido-trading/SKILL.md +31 -0
- package/skills/kaleido-wallet/SKILL.md +28 -0
- package/src/engine.test.ts +204 -0
- package/src/engine.ts +27 -2
- package/src/index.ts +17 -0
- package/src/skills/bundle.ts +42 -0
- package/src/skills/loader.ts +63 -0
- package/src/skills/reference-source.ts +60 -0
- package/src/skills/registry.ts +183 -0
- package/src/skills/skills.test.ts +191 -0
- package/src/skills/types.ts +55 -0
- package/src/tools/l402.test.ts +113 -0
- package/src/tools/l402.ts +122 -0
- package/dist/providers/qvac.d.ts +0 -89
- package/dist/providers/qvac.d.ts.map +0 -1
- package/dist/providers/qvac.js +0 -150
- package/dist/providers/qvac.js.map +0 -1
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skills — Claude-style Agent Skills the brain can "enter".
|
|
3
|
+
*
|
|
4
|
+
* A skill is the top layer of tool use: a folder with a `SKILL.md` (YAML
|
|
5
|
+
* frontmatter + a markdown playbook) and optional `references/*.md` files that
|
|
6
|
+
* are loaded on demand. Entering a skill injects its playbook into the system
|
|
7
|
+
* prompt and (optionally) scopes the agent to a subset of tools. The tools are
|
|
8
|
+
* still invoked via function calling and may be backed by in-process handlers
|
|
9
|
+
* or MCP servers — skills don't replace those, they *direct* them.
|
|
10
|
+
*
|
|
11
|
+
* This is progressive disclosure, the core idea behind Anthropic's Agent Skills:
|
|
12
|
+
* a small local model never sees every tool or instruction at once — only the
|
|
13
|
+
* selected skill's playbook, and it can pull a reference file in when it needs
|
|
14
|
+
* the detail. The format is compatible with skills published for Claude (e.g.
|
|
15
|
+
* `bitrefill/agents`), so the same SKILL.md runs the QVAC brain unchanged.
|
|
16
|
+
*/
|
|
17
|
+
/** A reference file (references/*.md) the agent can read on demand. */
|
|
18
|
+
export interface SkillReference {
|
|
19
|
+
/** Filename, e.g. "mcp.md". */
|
|
20
|
+
name: string;
|
|
21
|
+
/** Markdown contents. */
|
|
22
|
+
content: string;
|
|
23
|
+
}
|
|
24
|
+
export interface Skill {
|
|
25
|
+
/** Stable id, e.g. "bitrefill" / "portfolio-manager". */
|
|
26
|
+
name: string;
|
|
27
|
+
/**
|
|
28
|
+
* "When to use this" — the spec's selection signal. May be long and embed the
|
|
29
|
+
* trigger phrases ("…Triggers when the user mentions gift cards, eSIM…").
|
|
30
|
+
*/
|
|
31
|
+
description: string;
|
|
32
|
+
/** The playbook: markdown instructions injected into the system prompt. */
|
|
33
|
+
instructions: string;
|
|
34
|
+
/**
|
|
35
|
+
* Tool names this skill is allowed to use. When set, the engine exposes only
|
|
36
|
+
* these tools while the skill is active (progressive disclosure). Omit to
|
|
37
|
+
* allow all registered tools (the default for capability-routing skills).
|
|
38
|
+
*/
|
|
39
|
+
tools?: string[];
|
|
40
|
+
/** Optional trigger keywords to boost selection (in addition to description). */
|
|
41
|
+
triggers?: string[];
|
|
42
|
+
/** Remaining frontmatter (compatibility, author, version, homepage, …). */
|
|
43
|
+
metadata?: Record<string, string>;
|
|
44
|
+
/** Reference files (references/*.md) for progressive disclosure. */
|
|
45
|
+
references?: SkillReference[];
|
|
46
|
+
/** Source folder, when loaded from disk (Node). */
|
|
47
|
+
dir?: string;
|
|
48
|
+
}
|
|
49
|
+
/** Picks the most relevant skill for a query (or null for none). */
|
|
50
|
+
export interface SkillSelector {
|
|
51
|
+
select(query: string, skills: Skill[]): Skill | null;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/skills/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,uEAAuE;AACvE,MAAM,WAAW,cAAc;IAC7B,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,yBAAyB;IACzB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,KAAK;IACpB,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,YAAY,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,oEAAoE;IACpE,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAC9B,mDAAmD;IACnD,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,oEAAoE;AACpE,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,GAAG,IAAI,CAAC;CACtD"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skills — Claude-style Agent Skills the brain can "enter".
|
|
3
|
+
*
|
|
4
|
+
* A skill is the top layer of tool use: a folder with a `SKILL.md` (YAML
|
|
5
|
+
* frontmatter + a markdown playbook) and optional `references/*.md` files that
|
|
6
|
+
* are loaded on demand. Entering a skill injects its playbook into the system
|
|
7
|
+
* prompt and (optionally) scopes the agent to a subset of tools. The tools are
|
|
8
|
+
* still invoked via function calling and may be backed by in-process handlers
|
|
9
|
+
* or MCP servers — skills don't replace those, they *direct* them.
|
|
10
|
+
*
|
|
11
|
+
* This is progressive disclosure, the core idea behind Anthropic's Agent Skills:
|
|
12
|
+
* a small local model never sees every tool or instruction at once — only the
|
|
13
|
+
* selected skill's playbook, and it can pull a reference file in when it needs
|
|
14
|
+
* the detail. The format is compatible with skills published for Claude (e.g.
|
|
15
|
+
* `bitrefill/agents`), so the same SKILL.md runs the QVAC brain unchanged.
|
|
16
|
+
*/
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/skills/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* L402 tool source — lets the agent pay for paywalled HTTP resources in sats.
|
|
3
|
+
*
|
|
4
|
+
* Exposes one tool, `fetch_paid_resource(url)`, that runs the L402 flow:
|
|
5
|
+
* GET url → 402 with an L402 challenge (macaroon + Lightning invoice)
|
|
6
|
+
* → pay the invoice (via the injected `payInvoice`, e.g. the on-device wallet)
|
|
7
|
+
* → re-GET with `Authorization: L402 <macaroon>:<preimage>` → return the body.
|
|
8
|
+
*
|
|
9
|
+
* This is the "agent pays for a tool in sats" capability: any KaleidoMind agent
|
|
10
|
+
* (mobile or desktop) can buy premium data / inference autonomously. Payment
|
|
11
|
+
* runs through the host's wallet, so it stays on-device; the engine's
|
|
12
|
+
* confirmation gate can wrap the spend if desired.
|
|
13
|
+
*
|
|
14
|
+
* No dependencies — uses global fetch (Node ≥18, React Native). The fetch impl
|
|
15
|
+
* is injectable for testing.
|
|
16
|
+
*/
|
|
17
|
+
import type { ToolSource } from './source.js';
|
|
18
|
+
export interface L402PayResult {
|
|
19
|
+
/** Payment preimage (hex) — proves the invoice was paid. */
|
|
20
|
+
preimage: string;
|
|
21
|
+
}
|
|
22
|
+
export interface L402Options {
|
|
23
|
+
/** Pay a BOLT11 invoice, resolve with the preimage. Wallet on device; mock in tests. */
|
|
24
|
+
payInvoice: (invoice: string, amountSats: number) => Promise<L402PayResult>;
|
|
25
|
+
/** Override fetch (tests). Defaults to global fetch. */
|
|
26
|
+
fetchImpl?: typeof fetch;
|
|
27
|
+
/** Optional progress logging. */
|
|
28
|
+
log?: (msg: string) => void;
|
|
29
|
+
/**
|
|
30
|
+
* Gate the tool behind the engine's confirmation (default true). The catch:
|
|
31
|
+
* the invoice amount is only known DURING execution (the 402 challenge), so a
|
|
32
|
+
* pre-execution confirmation can't show it. On hosts without a dedicated L402
|
|
33
|
+
* confirmation UX, set this false and bound spending with `maxAutoPaySats`.
|
|
34
|
+
*/
|
|
35
|
+
requiresConfirmation?: boolean;
|
|
36
|
+
/** Auto-pay only invoices up to this many sats; reject larger ones. */
|
|
37
|
+
maxAutoPaySats?: number;
|
|
38
|
+
}
|
|
39
|
+
/** Parse an L402 (or legacy LSAT) WWW-Authenticate challenge. */
|
|
40
|
+
export declare function parseL402Challenge(header: string): {
|
|
41
|
+
macaroon: string;
|
|
42
|
+
invoice: string;
|
|
43
|
+
} | null;
|
|
44
|
+
/** Rough BOLT11 amount → sats (for logging / spend caps). 0 if unparseable. */
|
|
45
|
+
export declare function bolt11AmountSats(invoice: string): number;
|
|
46
|
+
export declare function createL402ToolSource(opts: L402Options): ToolSource;
|
|
47
|
+
//# sourceMappingURL=l402.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"l402.d.ts","sourceRoot":"","sources":["../../src/tools/l402.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,WAAW,aAAa;IAC5B,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,wFAAwF;IACxF,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;IAC5E,wDAAwD;IACxD,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,iCAAiC;IACjC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,uEAAuE;IACvE,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,iEAAiE;AACjE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAI/F;AAED,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAOxD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,WAAW,GAAG,UAAU,CA6DlE"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* L402 tool source — lets the agent pay for paywalled HTTP resources in sats.
|
|
3
|
+
*
|
|
4
|
+
* Exposes one tool, `fetch_paid_resource(url)`, that runs the L402 flow:
|
|
5
|
+
* GET url → 402 with an L402 challenge (macaroon + Lightning invoice)
|
|
6
|
+
* → pay the invoice (via the injected `payInvoice`, e.g. the on-device wallet)
|
|
7
|
+
* → re-GET with `Authorization: L402 <macaroon>:<preimage>` → return the body.
|
|
8
|
+
*
|
|
9
|
+
* This is the "agent pays for a tool in sats" capability: any KaleidoMind agent
|
|
10
|
+
* (mobile or desktop) can buy premium data / inference autonomously. Payment
|
|
11
|
+
* runs through the host's wallet, so it stays on-device; the engine's
|
|
12
|
+
* confirmation gate can wrap the spend if desired.
|
|
13
|
+
*
|
|
14
|
+
* No dependencies — uses global fetch (Node ≥18, React Native). The fetch impl
|
|
15
|
+
* is injectable for testing.
|
|
16
|
+
*/
|
|
17
|
+
/** Parse an L402 (or legacy LSAT) WWW-Authenticate challenge. */
|
|
18
|
+
export function parseL402Challenge(header) {
|
|
19
|
+
const macaroon = header.match(/macaroon="([^"]+)"/i)?.[1];
|
|
20
|
+
const invoice = header.match(/invoice="([^"]+)"/i)?.[1];
|
|
21
|
+
return macaroon && invoice ? { macaroon, invoice } : null;
|
|
22
|
+
}
|
|
23
|
+
/** Rough BOLT11 amount → sats (for logging / spend caps). 0 if unparseable. */
|
|
24
|
+
export function bolt11AmountSats(invoice) {
|
|
25
|
+
const m = invoice.match(/^ln(?:bc|tb|bcrt)(\d+)([munp]?)/i);
|
|
26
|
+
if (!m)
|
|
27
|
+
return 0;
|
|
28
|
+
const n = Number(m[1]);
|
|
29
|
+
const mult = (m[2] || '').toLowerCase();
|
|
30
|
+
const btc = mult === 'm' ? n / 1e3 : mult === 'u' ? n / 1e6 : mult === 'n' ? n / 1e9 : mult === 'p' ? n / 1e12 : n;
|
|
31
|
+
return Math.round(btc * 1e8);
|
|
32
|
+
}
|
|
33
|
+
export function createL402ToolSource(opts) {
|
|
34
|
+
const doFetch = opts.fetchImpl ?? fetch;
|
|
35
|
+
const tool = {
|
|
36
|
+
name: 'fetch_paid_resource',
|
|
37
|
+
description: 'Fetch a paywalled (L402) HTTP resource, automatically paying the required ' +
|
|
38
|
+
'Lightning invoice in sats. Use this for premium or paid APIs (market data, ' +
|
|
39
|
+
'inference, etc.). Pass the resource URL.',
|
|
40
|
+
parameters: {
|
|
41
|
+
type: 'object',
|
|
42
|
+
properties: { url: { type: 'string', description: 'The resource URL to fetch' } },
|
|
43
|
+
required: ['url'],
|
|
44
|
+
},
|
|
45
|
+
requiresConfirmation: opts.requiresConfirmation ?? true,
|
|
46
|
+
};
|
|
47
|
+
async function execute(_name, args) {
|
|
48
|
+
const url = String(args.url ?? '');
|
|
49
|
+
if (!url)
|
|
50
|
+
throw new Error('fetch_paid_resource: url is required');
|
|
51
|
+
let res = await doFetch(url);
|
|
52
|
+
if (res.status === 402) {
|
|
53
|
+
const challenge = parseL402Challenge(res.headers.get('www-authenticate') ?? '');
|
|
54
|
+
if (!challenge)
|
|
55
|
+
throw new Error('402 Payment Required but no L402 challenge present');
|
|
56
|
+
const amountSats = bolt11AmountSats(challenge.invoice) || Number(res.headers.get('x-amount-sats') ?? 0);
|
|
57
|
+
if (opts.maxAutoPaySats != null && amountSats > opts.maxAutoPaySats) {
|
|
58
|
+
throw new Error(`L402 invoice is ${amountSats} sats, above the ${opts.maxAutoPaySats} sat auto-pay cap — declined`);
|
|
59
|
+
}
|
|
60
|
+
opts.log?.(`L402: ${url} requires ${amountSats} sats — paying…`);
|
|
61
|
+
const { preimage } = await opts.payInvoice(challenge.invoice, amountSats);
|
|
62
|
+
res = await doFetch(url, {
|
|
63
|
+
headers: { Authorization: `L402 ${challenge.macaroon}:${preimage}` },
|
|
64
|
+
});
|
|
65
|
+
opts.log?.(`L402: paid ${amountSats} sats → ${res.status}`);
|
|
66
|
+
}
|
|
67
|
+
if (!res.ok)
|
|
68
|
+
throw new Error(`fetch_paid_resource: ${res.status} ${res.statusText}`);
|
|
69
|
+
const body = await res.text();
|
|
70
|
+
try {
|
|
71
|
+
return JSON.parse(body);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return body;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
id: 'l402',
|
|
79
|
+
listTools: () => [tool],
|
|
80
|
+
has: (name) => name === tool.name,
|
|
81
|
+
execute,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=l402.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"l402.js","sourceRoot":"","sources":["../../src/tools/l402.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AA4BH,iEAAiE;AACjE,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC/C,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACxD,OAAO,QAAQ,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5D,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;IAC5D,IAAI,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC;IACjB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvB,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACxC,MAAM,GAAG,GAAG,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACnH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAiB;IACpD,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,IAAI,KAAK,CAAC;IAExC,MAAM,IAAI,GAAY;QACpB,IAAI,EAAE,qBAAqB;QAC3B,WAAW,EACT,4EAA4E;YAC5E,6EAA6E;YAC7E,0CAA0C;QAC5C,UAAU,EAAE;YACV,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,2BAA2B,EAAE,EAAE;YACjF,QAAQ,EAAE,CAAC,KAAK,CAAC;SAClB;QACD,oBAAoB,EAAE,IAAI,CAAC,oBAAoB,IAAI,IAAI;KACxD,CAAC;IAEF,KAAK,UAAU,OAAO,CAAC,KAAa,EAAE,IAA6B;QACjE,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;QACnC,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAElE,IAAI,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;QAE7B,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,MAAM,SAAS,GAAG,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,CAAC;YAChF,IAAI,CAAC,SAAS;gBAAE,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;YAEtF,MAAM,UAAU,GACd,gBAAgB,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;YAEvF,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI,IAAI,UAAU,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpE,MAAM,IAAI,KAAK,CACb,mBAAmB,UAAU,oBAAoB,IAAI,CAAC,cAAc,8BAA8B,CACnG,CAAC;YACJ,CAAC;YAED,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,GAAG,aAAa,UAAU,iBAAiB,CAAC,CAAC;YAEjE,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;YAE1E,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE;gBACvB,OAAO,EAAE,EAAE,aAAa,EAAE,QAAQ,SAAS,CAAC,QAAQ,IAAI,QAAQ,EAAE,EAAE;aACrE,CAAC,CAAC;YACH,IAAI,CAAC,GAAG,EAAE,CAAC,cAAc,UAAU,WAAW,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QAC9D,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;QACrF,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO;QACL,EAAE,EAAE,MAAM;QACV,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC;QACvB,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI;QACjC,OAAO;KACR,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kaleidorg/mind",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Local-first reasoning + function-calling engine for KaleidoSwap. QVAC-powered.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -23,6 +23,10 @@
|
|
|
23
23
|
"import": "./dist/tools/mcp.js",
|
|
24
24
|
"types": "./dist/tools/mcp.d.ts"
|
|
25
25
|
},
|
|
26
|
+
"./skills": {
|
|
27
|
+
"import": "./dist/skills/loader.js",
|
|
28
|
+
"types": "./dist/skills/loader.d.ts"
|
|
29
|
+
},
|
|
26
30
|
"./logger": {
|
|
27
31
|
"import": "./dist/logger.js",
|
|
28
32
|
"types": "./dist/logger.d.ts"
|
|
@@ -31,6 +35,8 @@
|
|
|
31
35
|
"files": [
|
|
32
36
|
"dist",
|
|
33
37
|
"src",
|
|
38
|
+
"skills",
|
|
39
|
+
"scripts",
|
|
34
40
|
"README.md",
|
|
35
41
|
"LICENSE"
|
|
36
42
|
],
|
|
@@ -38,7 +44,8 @@
|
|
|
38
44
|
"build": "tsc",
|
|
39
45
|
"typecheck": "tsc --noEmit",
|
|
40
46
|
"test": "vitest run",
|
|
41
|
-
"lint": "eslint src"
|
|
47
|
+
"lint": "eslint src",
|
|
48
|
+
"bundle-skills": "node scripts/bundle-skills.mjs"
|
|
42
49
|
},
|
|
43
50
|
"devDependencies": {
|
|
44
51
|
"vitest": "^1.6.0"
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* bundle-skills — serialise one or more skill directories into a SkillBundle
|
|
4
|
+
* JSON file, so hosts without a filesystem (React Native) can load the same
|
|
5
|
+
* SKILL.md skills the Node fs loader reads.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* node bundle-skills.mjs --out <file.json> <skills-dir> [<more-dirs>...]
|
|
9
|
+
*
|
|
10
|
+
* Example (mobile: ship the packaged bitrefill skill + the app's own skills):
|
|
11
|
+
* node bundle-skills.mjs --out ./skills.bundle.json \
|
|
12
|
+
* node_modules/@kaleidorg/mind/skills/bitrefill ./skills
|
|
13
|
+
*
|
|
14
|
+
* Each positional arg may be either a single skill folder (contains SKILL.md)
|
|
15
|
+
* or a parent folder of skill folders. References under <skill>/references/*.md
|
|
16
|
+
* are inlined. The output matches the `SkillBundle` type in src/skills/bundle.ts.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { readdirSync, readFileSync, existsSync, writeFileSync, statSync } from 'node:fs';
|
|
20
|
+
import { join, basename } from 'node:path';
|
|
21
|
+
|
|
22
|
+
function parseArgs(argv) {
|
|
23
|
+
const dirs = [];
|
|
24
|
+
let out = null;
|
|
25
|
+
for (let i = 0; i < argv.length; i++) {
|
|
26
|
+
if (argv[i] === '--out') out = argv[++i];
|
|
27
|
+
else dirs.push(argv[i]);
|
|
28
|
+
}
|
|
29
|
+
if (!out || dirs.length === 0) {
|
|
30
|
+
console.error('usage: bundle-skills.mjs --out <file.json> <skills-dir> [<more-dirs>...]');
|
|
31
|
+
process.exit(2);
|
|
32
|
+
}
|
|
33
|
+
return { out, dirs };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function readSkillFolder(dir) {
|
|
37
|
+
const md = join(dir, 'SKILL.md');
|
|
38
|
+
if (!existsSync(md)) return null;
|
|
39
|
+
const refDir = join(dir, 'references');
|
|
40
|
+
const references = existsSync(refDir)
|
|
41
|
+
? readdirSync(refDir)
|
|
42
|
+
.filter((f) => f.endsWith('.md'))
|
|
43
|
+
.sort()
|
|
44
|
+
.map((name) => ({ name, content: readFileSync(join(refDir, name), 'utf8') }))
|
|
45
|
+
: [];
|
|
46
|
+
return {
|
|
47
|
+
dir: basename(dir),
|
|
48
|
+
markdown: readFileSync(md, 'utf8'),
|
|
49
|
+
...(references.length ? { references } : {}),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Expand a path into skill folders: itself if it has a SKILL.md, else its children. */
|
|
54
|
+
function collectSkillDirs(path) {
|
|
55
|
+
if (!existsSync(path)) {
|
|
56
|
+
console.error(`bundle-skills: path not found: ${path}`);
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
if (existsSync(join(path, 'SKILL.md'))) return [path];
|
|
60
|
+
return readdirSync(path)
|
|
61
|
+
.map((e) => join(path, e))
|
|
62
|
+
.filter((p) => statSync(p).isDirectory() && existsSync(join(p, 'SKILL.md')))
|
|
63
|
+
.sort();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const { out, dirs } = parseArgs(process.argv.slice(2));
|
|
67
|
+
const seen = new Set();
|
|
68
|
+
const skills = [];
|
|
69
|
+
for (const arg of dirs) {
|
|
70
|
+
for (const skillDir of collectSkillDirs(arg)) {
|
|
71
|
+
const s = readSkillFolder(skillDir);
|
|
72
|
+
if (!s) continue;
|
|
73
|
+
if (seen.has(s.dir)) {
|
|
74
|
+
console.error(`bundle-skills: duplicate skill folder "${s.dir}" — skipping ${skillDir}`);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
seen.add(s.dir);
|
|
78
|
+
skills.push(s);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const bundle = { version: 1, skills };
|
|
83
|
+
writeFileSync(out, JSON.stringify(bundle, null, 2));
|
|
84
|
+
console.error(`bundle-skills: wrote ${skills.length} skill(s) → ${out} [${skills.map((s) => s.dir).join(', ')}]`);
|
package/skills/README.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Skills
|
|
2
|
+
|
|
3
|
+
Claude-style **Agent Skills** the KaleidoMind brain (QVAC) loads at runtime.
|
|
4
|
+
Skills are the top layer of tool use: entering one injects a focused playbook
|
|
5
|
+
into the system prompt and (optionally) scopes the model to a subset of tools —
|
|
6
|
+
*progressive disclosure*, so a small local model never sees every tool or
|
|
7
|
+
instruction at once.
|
|
8
|
+
|
|
9
|
+
Each subfolder is a skill: a `SKILL.md` (YAML frontmatter + playbook) plus
|
|
10
|
+
optional `references/*.md` files loaded on demand. The format is the Anthropic
|
|
11
|
+
Agent Skills spec, so skills published for Claude (e.g. `bitrefill/agents`) run
|
|
12
|
+
the QVAC brain unchanged.
|
|
13
|
+
|
|
14
|
+
## Frontmatter
|
|
15
|
+
|
|
16
|
+
```yaml
|
|
17
|
+
---
|
|
18
|
+
name: my-skill # required — stable id
|
|
19
|
+
description: When to use this… # required — selection signal (embed triggers here)
|
|
20
|
+
tools: tool_a, tool_b # optional — scope the model to these tools
|
|
21
|
+
triggers: foo, bar # optional — keywords that boost selection
|
|
22
|
+
metadata: # optional — anything else (author, version, …)
|
|
23
|
+
author: kaleidoswap
|
|
24
|
+
---
|
|
25
|
+
# Playbook
|
|
26
|
+
Markdown instructions injected into the system prompt when this skill is active.
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Loading (same skills, every surface)
|
|
30
|
+
|
|
31
|
+
**Node** (desktop sidecar, kaleidoagent) — read folders from disk:
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { loadSkillsDir, packagedSkillsDir } from '@kaleidorg/mind/skills';
|
|
35
|
+
import { SkillRegistry, createSkillReferenceToolSource } from '@kaleidorg/mind';
|
|
36
|
+
|
|
37
|
+
const skills = loadSkillsDir(packagedSkillsDir()); // these shipped skills
|
|
38
|
+
const registry = new SkillRegistry(skills);
|
|
39
|
+
const refSource = createSkillReferenceToolSource(registry); // read_skill_reference
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**React Native** (rate) — no filesystem, so bundle the folders to JSON at build
|
|
43
|
+
time and rehydrate:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
node node_modules/@kaleidorg/mind/scripts/bundle-skills.mjs \
|
|
47
|
+
--out skills.bundle.json ./skills
|
|
48
|
+
```
|
|
49
|
+
```ts
|
|
50
|
+
import { SkillRegistry, skillsFromBundle } from '@kaleidorg/mind';
|
|
51
|
+
import bundle from './skills.bundle.json';
|
|
52
|
+
const registry = new SkillRegistry(skillsFromBundle(bundle));
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Then per query: `const skill = registry.select(query)` →
|
|
56
|
+
`registry.compose(systemPrompt, skill)` → pass `{ system, allowedTools }` to
|
|
57
|
+
`engine.runAgentic(...)`.
|
|
58
|
+
|
|
59
|
+
## Adding a skill
|
|
60
|
+
|
|
61
|
+
1. Create `skills/<name>/SKILL.md` (and `references/*.md` if needed).
|
|
62
|
+
2. Node hosts pick it up automatically. For mobile, re-run the bundler.
|
|
63
|
+
3. That's it — no code changes. The selector routes to it by description/triggers.
|
|
64
|
+
|
|
65
|
+
## Shipped skills
|
|
66
|
+
|
|
67
|
+
- **bitrefill/** — official Bitrefill agent skill (gift cards, mobile top-ups,
|
|
68
|
+
eSIMs; pay in crypto / Lightning / USDC-x402 / balance). Capability-routes to
|
|
69
|
+
the best channel; preferred purchase path is the Bitrefill remote MCP at
|
|
70
|
+
`https://api.bitrefill.com/mcp` (needs `BITREFILL_API_KEY` — anonymous = 401).
|
|
71
|
+
Source: https://github.com/bitrefill/agents (MIT). Update with
|
|
72
|
+
`npx skills add bitrefill/agents` or re-vendor the folder.
|
|
73
|
+
- **kaleido-wallet/** — balances, receive, pay, channels over `kaleido-mcp`.
|
|
74
|
+
- **kaleido-trading/** — prices, quotes, atomic swaps, LSP channels.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bitrefill
|
|
3
|
+
description: "Buy or browse Bitrefill — 1,500+ gift cards, mobile top-ups, and eSIMs across 180+ countries, payable in crypto, Lightning, USDC via x402, or pre-funded account balance. Routes the host agent to its highest-fidelity channel (residential browser, MCP server, npm CLI, or REST API) based on detected runtime capabilities, with a dedicated OpenClaw integration guide for chat-channel scenarios. Triggers when the user mentions Bitrefill, gift cards, mobile top-up, eSIM data plan, refilling a phone, or asks to pay or check out with crypto, Lightning, USDC, or x402."
|
|
4
|
+
compatibility: "Detects host capabilities at runtime. Paths require: browse — residential-IP browser; MCP — MCP-capable client + Bitrefill OAuth/API key; CLI — Node.js >=18 + shell + npm + @bitrefill/cli >=0.3.0 (headless login/verify via magic link); API — outbound HTTP + Bitrefill API key (Personal) or API ID/Secret (Business/Affiliate). OpenClaw host gets a dedicated guide."
|
|
5
|
+
metadata:
|
|
6
|
+
author: bitrefill
|
|
7
|
+
version: "2.1.5"
|
|
8
|
+
homepage: "https://www.bitrefill.com"
|
|
9
|
+
docs: "https://docs.bitrefill.com"
|
|
10
|
+
repository: "https://github.com/bitrefill/cli"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Bitrefill
|
|
14
|
+
|
|
15
|
+
Bitrefill sells digital goods (gift cards, mobile top-ups, eSIMs) across 180+ countries and 1,500+ brands. Pay with crypto, Lightning, USDC via x402, or pre-funded account balance. Codes deliver instantly after payment confirms.
|
|
16
|
+
|
|
17
|
+
This skill **routes by capability, not by use case**. Same intent ("buy a Steam card") plays out differently across hosts. Pick a path below based on what your runtime can do.
|
|
18
|
+
|
|
19
|
+
## Pick a path
|
|
20
|
+
|
|
21
|
+
Walk these checks **in order**. First match wins.
|
|
22
|
+
|
|
23
|
+
1. **Inside OpenClaw?** Check for `~/.openclaw/openclaw.json`, `~/.openclaw/skills/`, or `openclaw` on PATH. If yes → read [host-openclaw.md](references/host-openclaw.md) first. **Default purchase path: guest CLI via `exec`** (no auth). Sign in for `balance`/cashback. OpenClaw also supports MCP, API, Browse, chat-channel scenarios (Telegram, cron, mobile camera).
|
|
24
|
+
|
|
25
|
+
2. **Browse-only intent (no purchase)?** If the user only wants to explore, compare prices, or learn how products work:
|
|
26
|
+
- Have a residential-IP browser (ChatGPT Atlas, Cursor browser tool, Claude/Playwright Chrome extension, OpenClaw on user host)? → [browse.md](references/browse.md).
|
|
27
|
+
- Datacenter egress only (ChatGPT web/Agent, Gemini consumer, Jules)? `www.bitrefill.com` returns **403 Cloudflare** to datacenter IPs. Use [mcp.md](references/mcp.md) `search-products` / `product-details` instead — they return the same catalog without scraping.
|
|
28
|
+
|
|
29
|
+
3. **MCP supported?** Bitrefill ships a remote HTTP/SSE MCP at `https://api.bitrefill.com/mcp`. Works on Claude.ai (Pro+), Cowork, Claude Desktop, Claude Code, ChatGPT (Plus+), Atlas, Codex CLI, Gemini CLI, Cursor, OpenCode, OpenClaw. **Highest-fidelity purchase channel — typed tool calls, OAuth or API key, no shell needed.** → [mcp.md](references/mcp.md).
|
|
30
|
+
|
|
31
|
+
4. **Shell + `npm install` available?** CLI ≥ 0.3.0: **guest checkout first** (no auth — `buy-products --email` + crypto). Sign in for `balance`, cashback, order history. → [cli.md](references/cli.md). Headless sign-in → [cli-headless-auth.md](references/cli-headless-auth.md).
|
|
32
|
+
|
|
33
|
+
5. **Outbound HTTP from agent loop?** Anywhere shell exists, plus Claude Code `WebFetch`. Last resort — verbose, no typed validation. → [api.md](references/api.md).
|
|
34
|
+
|
|
35
|
+
6. **None of the above** (e.g. Gemini consumer free tier): give the user a `bitrefill.com` link and stop.
|
|
36
|
+
|
|
37
|
+
Don't know which host you're in? Read [capability-matrix.md](references/capability-matrix.md) — per-client cheat sheet maps every leading agent product to its viable paths.
|
|
38
|
+
|
|
39
|
+
## Top spending safeguards (read full list before any purchase)
|
|
40
|
+
|
|
41
|
+
This skill enables **real-money transactions**. Codes deliver instantly and digital goods are non-refundable per EU consumer rights.
|
|
42
|
+
|
|
43
|
+
- **Confirm before buying.** Present product, denomination, price, payment method. Wait for explicit user approval. Autonomous purchasing only when user opts in for the current session.
|
|
44
|
+
- **Treat codes as cash.** Never paste in group chats or public channels. Prefer in-memory storage over plain-text logs. Advise user to redeem ASAP.
|
|
45
|
+
- **Use a dedicated, low-balance account.** Never give the agent access to high-balance accounts or crypto wallet seeds. This skill is **not a wallet**.
|
|
46
|
+
- **Log every purchase.** `invoice_id`, product, amount, payment method.
|
|
47
|
+
|
|
48
|
+
Full safeguards + per-host hardening (OpenClaw exec-approvals, Cursor auto-approve, Codex sandbox, Claude Code allowlist) → [safeguards.md](references/safeguards.md).
|
|
49
|
+
|
|
50
|
+
## References
|
|
51
|
+
|
|
52
|
+
| File | Use when |
|
|
53
|
+
|------|----------|
|
|
54
|
+
| [browse.md](references/browse.md) | Agent has residential-IP browser; user wants to explore |
|
|
55
|
+
| [mcp.md](references/mcp.md) | MCP-capable host; preferred purchase path |
|
|
56
|
+
| [cli.md](references/cli.md) | Shell + npm; guest checkout or signed-in CLI ≥ 0.3.0 |
|
|
57
|
+
| [cli-headless-auth.md](references/cli-headless-auth.md) | AgentMail or equivalent inbox + magic-link auth for headless agents |
|
|
58
|
+
| [api.md](references/api.md) | HTTP-only runtime; Personal / Business / Affiliate REST tiers |
|
|
59
|
+
| [host-openclaw.md](references/host-openclaw.md) | OpenClaw Gateway — guest CLI via `exec` preferred |
|
|
60
|
+
| [capability-matrix.md](references/capability-matrix.md) | Per-client viable paths cheat sheet |
|
|
61
|
+
| [safeguards.md](references/safeguards.md) | Spending policy + per-host hardening |
|
|
62
|
+
| [troubleshooting.md](references/troubleshooting.md) | Common errors across all paths |
|
|
63
|
+
|
|
64
|
+
## Source of truth
|
|
65
|
+
|
|
66
|
+
Skill summarizes and routes. For exhaustive enums (countries, payment methods, full endpoint list), follow link-outs to <https://docs.bitrefill.com>.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Path: REST API
|
|
2
|
+
|
|
3
|
+
Use when: outbound HTTP available but no MCP and no shell. Last resort — verbose, no typed validation. Examples below use `curl` but any HTTP client works.
|
|
4
|
+
|
|
5
|
+
Base URL: `https://api.bitrefill.com/v2`
|
|
6
|
+
|
|
7
|
+
## Three tiers
|
|
8
|
+
|
|
9
|
+
| Tier | Auth | Use case |
|
|
10
|
+
|------|------|----------|
|
|
11
|
+
| Personal | Bearer token | Personal projects, agent automation |
|
|
12
|
+
| Business | Basic auth (`API_ID:API_SECRET`) | Platforms, resellers, BRGC batches, deposits, test products |
|
|
13
|
+
| Affiliate | Basic auth | Same as Business + commission tracking, results filtered by `referrer_id` |
|
|
14
|
+
|
|
15
|
+
## Personal API (agent default)
|
|
16
|
+
|
|
17
|
+
Get key: <https://www.bitrefill.com/account/developers>.
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
export BITREFILL_API_KEY=YOUR_API_KEY
|
|
21
|
+
H="Authorization: Bearer $BITREFILL_API_KEY"
|
|
22
|
+
|
|
23
|
+
# 1. Ping
|
|
24
|
+
curl -H "$H" https://api.bitrefill.com/v2/ping
|
|
25
|
+
# → {"data":{"message":"pong"}}
|
|
26
|
+
|
|
27
|
+
# 2. Balance
|
|
28
|
+
curl -H "$H" https://api.bitrefill.com/v2/accounts/balance
|
|
29
|
+
|
|
30
|
+
# 3. Search
|
|
31
|
+
curl -H "$H" "https://api.bitrefill.com/v2/products/search?q=amazon"
|
|
32
|
+
|
|
33
|
+
# 4. Product details
|
|
34
|
+
curl -H "$H" https://api.bitrefill.com/v2/products/amazon-us
|
|
35
|
+
|
|
36
|
+
# 5. Buy (balance, instant)
|
|
37
|
+
curl -X POST -H "$H" -H "Content-Type: application/json" \
|
|
38
|
+
-d '{
|
|
39
|
+
"products": [{"product_id":"amazon-us","package_id":"amazon-us<&>50","quantity":1}],
|
|
40
|
+
"payment_method": "balance",
|
|
41
|
+
"auto_pay": true
|
|
42
|
+
}' \
|
|
43
|
+
https://api.bitrefill.com/v2/invoices
|
|
44
|
+
|
|
45
|
+
# 6. Order / redemption
|
|
46
|
+
curl -H "$H" https://api.bitrefill.com/v2/orders/{order_id}
|
|
47
|
+
# → data.redemption_info.code, .link, .pin, .instructions
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
For crypto: omit `auto_pay`, set `payment_method: "bitcoin"|"lightning"|"usdc_base"|...`, include `refund_address` for crypto methods, then poll `GET /invoices/{id}` until `status: "complete"`.
|
|
51
|
+
|
|
52
|
+
## Business API
|
|
53
|
+
|
|
54
|
+
Apply: <https://www.bitrefill.com/integrate>.
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
TOKEN=$(printf "%s:%s" "$BITREFILL_API_ID" "$BITREFILL_API_SECRET" | base64)
|
|
58
|
+
H="Authorization: Basic $TOKEN"
|
|
59
|
+
|
|
60
|
+
curl -H "$H" https://api.bitrefill.com/v2/ping
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Adds: BRGC (Bitrefill Reusable Gift Card) batches, account deposits via crypto, full product catalog including test products. Same endpoints + `POST /brgc-batches`, `POST /accounts/deposit`.
|
|
64
|
+
|
|
65
|
+
## Affiliate API
|
|
66
|
+
|
|
67
|
+
Apply: <https://www.bitrefill.com/affiliate>. Same auth as Business. Adds `GET /commissions` with `after`/`before` date filters. Order/invoice queries return data filtered by `referrer_id` instead of `user_id`.
|
|
68
|
+
|
|
69
|
+
## Key endpoints
|
|
70
|
+
|
|
71
|
+
- `GET /ping` — health check (1 req / 3 s)
|
|
72
|
+
- `GET /accounts/balance` — current balance
|
|
73
|
+
- `GET /products` — paginated catalog (cache locally, refresh daily; 1000 product req/hr quota shared with search)
|
|
74
|
+
- `GET /products/search?q=...` — keyword search
|
|
75
|
+
- `GET /products/{id}` — product details with `packages` array
|
|
76
|
+
- `POST /invoices` — create invoice (max 20 products)
|
|
77
|
+
- `POST /invoices/{id}/pay` — pay unpaid balance invoice
|
|
78
|
+
- `GET /invoices/{id}` — status
|
|
79
|
+
- `GET /orders/{id}` — redemption info
|
|
80
|
+
- `POST /esims` — create eSIM invoice (or top-up existing via `esim_id`)
|
|
81
|
+
- `GET /esims` / `GET /esims/{id}` — list / get user eSIMs
|
|
82
|
+
|
|
83
|
+
Webhooks: `webhook_url` field on invoice creation → notification when delivered.
|
|
84
|
+
|
|
85
|
+
## Test products
|
|
86
|
+
|
|
87
|
+
Business/Affiliate only. No money charged. Examples: `test-gift-card-code`, etc. Full list: <https://docs.bitrefill.com/docs/test-products>.
|
|
88
|
+
|
|
89
|
+
## Rate limits
|
|
90
|
+
|
|
91
|
+
Most endpoints 60 req / 10 min. `/products` and `/products/search` 60 req/min + 1000 product req/hr quota. `/ping` 1 req / 3 s. Full table: <https://docs.bitrefill.com/docs/rate-limits>.
|
|
92
|
+
|
|
93
|
+
## Source of truth
|
|
94
|
+
|
|
95
|
+
- <https://docs.bitrefill.com/docs/api-overview> — tier comparison + auth
|
|
96
|
+
- <https://docs.bitrefill.com/docs/quickstart-2> — 6-step purchase flow
|
|
97
|
+
- <https://docs.bitrefill.com/reference> — full endpoint catalog
|
|
98
|
+
- <https://docs.bitrefill.com/docs/error-codes> — error codes
|
|
99
|
+
- <https://docs.bitrefill.com/docs/webhooks> — webhook payload spec
|