@gemmein/sdk 0.5.0 → 0.7.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/CHANGELOG.md +224 -0
- package/REFERENCE.md +397 -20
- package/dist/index.cjs +259 -5
- package/dist/index.d.cts +179 -4
- package/dist/index.d.ts +179 -4
- package/dist/index.js +256 -4
- package/llms.txt +260 -25
- package/migrations/README.md +35 -0
- package/migrations/list-limit-refusal.md +42 -0
- package/package.json +7 -3
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# Changelog — @gemmein/sdk
|
|
2
|
+
|
|
3
|
+
All notable changes to the SDK are recorded here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow
|
|
5
|
+
semver. A change that asks something of your app has a note in
|
|
6
|
+
[`migrations/`](./migrations/README.md) naming the version it arrived in
|
|
7
|
+
and the version by which the action is required.
|
|
8
|
+
|
|
9
|
+
The SDK and the local engine (`@gemmein/cli`) share a minor version from
|
|
10
|
+
0.6.0 / 0.7.0 onward: a feature that lands in one lands in the other in
|
|
11
|
+
the same release.
|
|
12
|
+
|
|
13
|
+
## [Unreleased]
|
|
14
|
+
|
|
15
|
+
## [0.7.0] — 2026-09-04
|
|
16
|
+
|
|
17
|
+
### Credits and the AI route
|
|
18
|
+
|
|
19
|
+
Credits are a general consumable: a balance your customers hold and your
|
|
20
|
+
product spends. A product carries `grantsCredits` (1..1,000,000) and each
|
|
21
|
+
confirmed purchase adds that many to the buyer's balance, idempotent on the
|
|
22
|
+
payment; a full refund claws back what is still unspent, floor zero. The
|
|
23
|
+
browser reads the balance with `g.credits.balance()`; a server spends with
|
|
24
|
+
`gemmeinServer(sk).spendCredits(personId, { amount?, reason, key? })` behind
|
|
25
|
+
the fourth key capability, "Spend a person's credits" — one atomic
|
|
26
|
+
decrement, refused whole below zero with `402 credits_exhausted` and the
|
|
27
|
+
balance in the message, at-most-once on `key`. `Holdings.credits` is
|
|
28
|
+
`{ balance }` from engine 0.8.0 (the type is unchanged; an older local engine
|
|
29
|
+
still answers `null`). A relay adds with `grant_credits`; the owner comps
|
|
30
|
+
from the person's page. Credits never expire and are never priced by token.
|
|
31
|
+
|
|
32
|
+
The AI route lets a browser session call OpenAI, Anthropic or Google through
|
|
33
|
+
Gemmein on the owner's own provider key, pasted once in the Keys room and
|
|
34
|
+
write-only from then on. `g.ai.chat(body, { provider?, signal? })` spends one
|
|
35
|
+
credit, forwards the provider's own request body as sent (minus `provider`,
|
|
36
|
+
and for Google `model` and `stream`, which ride the URL) with the auth
|
|
37
|
+
headers, `content-type` and `accept` added, and returns the fetch `Response`
|
|
38
|
+
untouched — the provider's answer, 2xx or not, is yours to read; a stream
|
|
39
|
+
stays a stream. `g.ai.text(body)` collects a non-stream answer to one string
|
|
40
|
+
per provider and throws `provider_error` on a provider's own non-2xx. A
|
|
41
|
+
credit is refunded only when the provider fails before its first byte
|
|
42
|
+
(`x-gemmein-credit: refunded`); a stream that dies mid-way does not refund,
|
|
43
|
+
and hanging up before the headers does not refund. A secret key is refused
|
|
44
|
+
(`403 scope_denied`): a server calls the provider directly. The codes that
|
|
45
|
+
join `GemmeinError`: `credits_exhausted`, `credits_ceiling`,
|
|
46
|
+
`dedupe_conflict`, `invalid_amount`, `invalid_reason`, `invalid_key`,
|
|
47
|
+
`person_not_found`, `capability_required`, `invalid_body`,
|
|
48
|
+
`ai_not_configured`, `provider_required`, `model_not_allowed`, `ai_capped`,
|
|
49
|
+
`payload_too_large`, `session_required`, `scope_denied`,
|
|
50
|
+
`provider_unreachable`, and `provider_error` from `g.ai.text`. `REFERENCE.md`
|
|
51
|
+
carries the Credits and AI chapters; `llms.txt` carries both capability
|
|
52
|
+
cards. `gemmein dev` answers a fake provider without a key and its pay
|
|
53
|
+
simulator honours the `grantsCredits` a product declares in
|
|
54
|
+
`gemmein/payments.json` (`gemmein payments setup` asks for it).
|
|
55
|
+
|
|
56
|
+
The ledger's laws, stated: a full refund claws back what that purchase's own
|
|
57
|
+
ledger row granted, whatever the product says today; a balance carries at
|
|
58
|
+
most 1,000,000,000 (`credits_ceiling`, nothing added past it); a server
|
|
59
|
+
spend's `key` is scoped to the person, so one order id reused for two people
|
|
60
|
+
charges both and a key that names a different movement is `dedupe_conflict`;
|
|
61
|
+
the person's page shows the credits that person spent in the last 30 days; a
|
|
62
|
+
provider that echoes the key in a refusal reaches the app as `***<hint>`.
|
|
63
|
+
|
|
64
|
+
### Added
|
|
65
|
+
- `g.credits.balance()` → `GET /auth/credits` → `{ balance }` (session required).
|
|
66
|
+
- `g.ai.chat(body, { provider?, signal? })` → `POST /ai/chat`; answers the
|
|
67
|
+
fetch `Response` untouched (streaming intact) whenever the answer passed
|
|
68
|
+
the spend — the provider's own status and body, 2xx or not; Gemmein's
|
|
69
|
+
refusals throw `GemmeinError` with the engine's code — `credits_exhausted`
|
|
70
|
+
(402), `ai_not_configured` (409), `provider_required` (400),
|
|
71
|
+
`model_not_allowed` (403), `ai_capped` (429), `payload_too_large` (413),
|
|
72
|
+
`invalid_body` (400), `session_required` (401), `scope_denied` (403),
|
|
73
|
+
`provider_unreachable` (502).
|
|
74
|
+
- `g.ai.text(body, options?)` — the non-streaming answer as a string
|
|
75
|
+
(OpenAI `choices[0].message.content`; Anthropic `content[].text`;
|
|
76
|
+
Google `candidates[0].content.parts[].text`); `invalid_response` when
|
|
77
|
+
no text came back; `provider_error` (the provider's status and message)
|
|
78
|
+
on a provider's own non-2xx.
|
|
79
|
+
- `gemmeinServer(sk).spendCredits(personId, { amount?, reason, key? })` →
|
|
80
|
+
`POST /server/people/:id/credits/spend` → `{ ok, spent, deduped,
|
|
81
|
+
balance: { before, after }, event: { id, reason, actor } }` (a deduped
|
|
82
|
+
repeat answers `spent: 0` and the same event); needs the key's "Spend a
|
|
83
|
+
person's credits" capability; `402 credits_exhausted`.
|
|
84
|
+
- `Holdings.credits` is filled (`{ balance }`) from engine 0.8.0 — the
|
|
85
|
+
type is unchanged.
|
|
86
|
+
- Relays: `grant_credits { amount 1..10,000, reason? }` action, mirrored
|
|
87
|
+
in `@gemmein/mcp`'s offline validator.
|
|
88
|
+
- Console: the Keys room's AI provider card (set · test · replace ·
|
|
89
|
+
remove), "Grants credits" on a product, CREDITS + Grant credits + the
|
|
90
|
+
ledger on a person, the Usage room's "AI calls" row.
|
|
91
|
+
|
|
92
|
+
## [0.6.0] — 2026-09-04
|
|
93
|
+
|
|
94
|
+
### Changed
|
|
95
|
+
- `list({ limit })` is honoured or refused, never clamped: a `limit`
|
|
96
|
+
outside 1..100 answers 400 `invalid_limit` ("limit must be between 1 and
|
|
97
|
+
100"). The default stays 25 and the maximum 100. Apps that asked for more
|
|
98
|
+
than 100 and read the first page as the whole set now get the refusal —
|
|
99
|
+
page with `cursor`. See `migrations/list-limit-refusal.md`.
|
|
100
|
+
- `verifyEmailCode` throws `GemmeinError` with code `invalid_response`
|
|
101
|
+
(status 0) when a 200 answer carries no session token, where it threw a
|
|
102
|
+
bare `Error` before. Every error the SDK raises is now a `GemmeinError`.
|
|
103
|
+
- `engines.node` is `>=20`. Node 18 reached end of life in April 2025; the
|
|
104
|
+
SDK is built and tested on 20 and 22.
|
|
105
|
+
|
|
106
|
+
### Added
|
|
107
|
+
- Relays. One JSON file, `gemmein/relays/<name>.json`: a trigger (a
|
|
108
|
+
provider's signed webhook at `POST /hooks/<appId>/<name>`, a schedule, or a
|
|
109
|
+
record change) and one to ten of Gemmein's own verbs (write a record, grant
|
|
110
|
+
or revoke access, email the person, call your URL), run in order with
|
|
111
|
+
retries and a replay button in the dashboard. No SDK method: the surface is
|
|
112
|
+
the file and the dashboard. `REFERENCE.md` carries the definition, the
|
|
113
|
+
triggers, the actions, the `call_url` contract and its signature header,
|
|
114
|
+
the templates, the lifecycle and the codes; `llms.txt` carries the
|
|
115
|
+
GoCardless worked example. A `call_url` that writes back through the SDK
|
|
116
|
+
fires `data_change` like any write. Stripe stays built in; any provider that
|
|
117
|
+
signs its webhooks drives access the same way.
|
|
118
|
+
- `GrantSource` gains `relay`: a grant a relay's `grant_access`
|
|
119
|
+
wrote. `holdings` and `verifySession` list it by kind like the other six;
|
|
120
|
+
`ManualGrantSource` is unchanged — no key can mint it.
|
|
121
|
+
- `gemmeinServer(...).invitePerson(email)` creates a person by email before
|
|
122
|
+
they sign in, or returns the one that exists (`{ person, created }`, type
|
|
123
|
+
`InvitedPerson`). Behind the third key capability, "Create a person by
|
|
124
|
+
email before they sign in". Refusals: `invalid_email`, `invite_capped`
|
|
125
|
+
(500 accepted calls per app per day, raised on request). An invited person
|
|
126
|
+
shows as invited on the person page until their first sign-in and is not
|
|
127
|
+
counted in the people band (the billable unit) until then.
|
|
128
|
+
- Every request carries `x-client-info: gemmein-sdk/<version>`. The Keys
|
|
129
|
+
page shows the SDK build behind a key's most recent call ("Last seen
|
|
130
|
+
from gemmein-sdk/0.6.0, as reported"). `SDK_VERSION` and `CLIENT_INFO`
|
|
131
|
+
are exported.
|
|
132
|
+
- `CHANGELOG.md` and `migrations/` ship in the package.
|
|
133
|
+
|
|
134
|
+
## [0.5.0] — 2026-09-03
|
|
135
|
+
|
|
136
|
+
### Added
|
|
137
|
+
- The server gate on `gemmeinServer(sk)`: `verifySession(token)`,
|
|
138
|
+
`holdings(personId)`, `grantAccess(personId, { entitlement, reason? })`,
|
|
139
|
+
`revokeAccess(personId, grantId, { reason? })`. Grant and revoke require
|
|
140
|
+
the key's `grantAccess` capability (minted on the Keys page).
|
|
141
|
+
- Exported types `Holdings`, `Grant`, `GatePerson`, `GrantSource`,
|
|
142
|
+
`ManualGrantSource`.
|
|
143
|
+
|
|
144
|
+
## [0.4.7] — 2026-09-02
|
|
145
|
+
|
|
146
|
+
### Changed
|
|
147
|
+
- Documentation-only release. The packaged `llms.txt` and `REFERENCE.md`
|
|
148
|
+
carry the W5 teaching: a promote run carries new fields as well as new
|
|
149
|
+
collections.
|
|
150
|
+
|
|
151
|
+
## [0.4.6] — 2026-08-26
|
|
152
|
+
|
|
153
|
+
### Changed
|
|
154
|
+
- `reaffirm.mjs` runs the 16-probe harness; its teachings are rewritten.
|
|
155
|
+
|
|
156
|
+
## [0.4.5] — 2026-08-26
|
|
157
|
+
|
|
158
|
+
### Changed
|
|
159
|
+
- Documentation-only release. `REFERENCE.md` catches up with documents,
|
|
160
|
+
`since`, `watch()`, `notify()`, the file laws and `purchases.mine()`.
|
|
161
|
+
|
|
162
|
+
## [0.4.4] — 2026-08-26
|
|
163
|
+
|
|
164
|
+
### Added
|
|
165
|
+
- `upload(file, { for })` addresses a file to one person; the file-kind
|
|
166
|
+
(image or document) and file-class teaching.
|
|
167
|
+
|
|
168
|
+
## [0.4.3] — 2026-08-25
|
|
169
|
+
|
|
170
|
+
### Added
|
|
171
|
+
- `gemmeinServer(sk).notify(personId, { subject, text, kind?, key? })`.
|
|
172
|
+
|
|
173
|
+
### Changed
|
|
174
|
+
- `watch()` stops on an auth-terminal answer instead of retrying it.
|
|
175
|
+
|
|
176
|
+
## [0.4.2] — 2026-08-25
|
|
177
|
+
|
|
178
|
+
### Added
|
|
179
|
+
- `list({ since })` with `ListResult.deleted` and `ListResult.watermark`;
|
|
180
|
+
`watch()` on a collection.
|
|
181
|
+
|
|
182
|
+
## [0.4.1] — 2026-08-22
|
|
183
|
+
|
|
184
|
+
### Added
|
|
185
|
+
- `GemmeinError.requires` (and `requiresAny`) on 403 `entitlement_required`,
|
|
186
|
+
on both the collection path and the runtime clients.
|
|
187
|
+
|
|
188
|
+
## [0.4.0] — 2026-07-30
|
|
189
|
+
|
|
190
|
+
### Changed
|
|
191
|
+
- A product's file lives on the product card and the purchase is the
|
|
192
|
+
authorisation to read it.
|
|
193
|
+
|
|
194
|
+
## [0.3.2] — 2026-07-29
|
|
195
|
+
|
|
196
|
+
### Fixed
|
|
197
|
+
- The wave-audit fixes for the 0.3 line.
|
|
198
|
+
|
|
199
|
+
## [0.3.1] — 2026-07-29
|
|
200
|
+
|
|
201
|
+
### Changed
|
|
202
|
+
- Documentation: the guide teaches paid access.
|
|
203
|
+
|
|
204
|
+
## [0.3.0] — 2026-07-29
|
|
205
|
+
|
|
206
|
+
### Added
|
|
207
|
+
- The file reference contract: records store references, files resolve
|
|
208
|
+
through the SDK.
|
|
209
|
+
|
|
210
|
+
## [0.2.1] — 2026-07-22
|
|
211
|
+
|
|
212
|
+
### Changed
|
|
213
|
+
- Documentation-only refresh.
|
|
214
|
+
|
|
215
|
+
## [0.2.0] — 2026-07-22
|
|
216
|
+
|
|
217
|
+
### Changed
|
|
218
|
+
- Two-layer shape: `g.collection(name)` plus the self-service primitives.
|
|
219
|
+
|
|
220
|
+
## [0.1.0] — 2026-07-11
|
|
221
|
+
|
|
222
|
+
### Added
|
|
223
|
+
- First published release: built `dist`, persistent sessions, journey
|
|
224
|
+
signposts.
|