@zweer/mage-space-client 1.3.1 → 1.4.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/README.md +35 -0
- package/dist/index.cjs +108 -7
- package/dist/index.d.cts +54 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +54 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +106 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -168,6 +168,41 @@ Unlike traditional REST APIs, mage.space uses Next.js Server Actions:
|
|
|
168
168
|
- Responses use the React Server Component (RSC) "Flight" wire format
|
|
169
169
|
- Action hashes change on every Vercel deploy — discovered from the page bundles (across routes) and cached, with a bundled seed for a warm start
|
|
170
170
|
|
|
171
|
+
### Batched discovery (subrequest-capped hosts)
|
|
172
|
+
|
|
173
|
+
`discoverActions` fetches every discovery page and every referenced chunk in one
|
|
174
|
+
go. On hosts with a hard per-invocation subrequest cap — e.g. the Cloudflare
|
|
175
|
+
Workers free plan — that can exceed the limit. Three platform-agnostic
|
|
176
|
+
primitives let such a host discover hashes in bounded batches:
|
|
177
|
+
|
|
178
|
+
- `listDiscoveryChunks({ fetch, baseUrl, pages? })` — GETs only the pages
|
|
179
|
+
(one subrequest each, `<= pages.length`) and returns the de-duplicated,
|
|
180
|
+
insertion-ordered `chunkPaths` plus the `deploymentId`.
|
|
181
|
+
- `scrapeChunks({ fetch, baseUrl, chunkPaths })` — fetches ONLY the chunk paths
|
|
182
|
+
it is given (one subrequest each) and returns a partial `hashes` map that can
|
|
183
|
+
be merged across batches. It never throws on an empty batch.
|
|
184
|
+
- `requiredActionsForClient()` — the action names the portal actually invokes,
|
|
185
|
+
so a batched caller can early-exit once it has found all of them.
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
import {
|
|
189
|
+
listDiscoveryChunks,
|
|
190
|
+
scrapeChunks,
|
|
191
|
+
requiredActionsForClient,
|
|
192
|
+
} from '@zweer/mage-space-client';
|
|
193
|
+
|
|
194
|
+
const { chunkPaths } = await listDiscoveryChunks({ fetch, baseUrl });
|
|
195
|
+
const required = requiredActionsForClient();
|
|
196
|
+
const hashes: Record<string, string> = {};
|
|
197
|
+
|
|
198
|
+
// Process chunks in batches sized to the host's subrequest budget.
|
|
199
|
+
for (const batch of chunksInGroupsOf(chunkPaths, 40)) {
|
|
200
|
+
const partial = await scrapeChunks({ fetch, baseUrl, chunkPaths: batch });
|
|
201
|
+
Object.assign(hashes, partial.hashes);
|
|
202
|
+
if (required.every((name) => name in hashes)) break; // early-exit
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
171
206
|
## Project Structure
|
|
172
207
|
|
|
173
208
|
```
|
package/dist/index.cjs
CHANGED
|
@@ -125,14 +125,66 @@ var InMemoryActionCache = class {
|
|
|
125
125
|
}
|
|
126
126
|
};
|
|
127
127
|
/**
|
|
128
|
-
*
|
|
129
|
-
* chunk URLs and extracting `createServerReference(...)` calls from each chunk.
|
|
128
|
+
* The action names the portal actually invokes.
|
|
130
129
|
*
|
|
131
|
-
* @
|
|
130
|
+
* @remarks
|
|
131
|
+
* Verified against `lib/auth.ts`, `lib/generation.ts`/`lib/history.ts` (via
|
|
132
|
+
* `resolveActionName` on `PRODUCTION_TARGET`), `lib/characters.ts`, and
|
|
133
|
+
* `lib/references.ts`. A batched, subrequest-capped caller (e.g. a Cloudflare
|
|
134
|
+
* Worker) uses this list to know when it has discovered everything it needs and
|
|
135
|
+
* can early-exit without scraping the remaining chunks. Every name is a key in
|
|
136
|
+
* {@link SEED_SNAPSHOT}.hashes.
|
|
132
137
|
*/
|
|
133
|
-
|
|
138
|
+
const REQUIRED_ACTIONS = [
|
|
139
|
+
"createUserSession",
|
|
140
|
+
"getHistoryPaginated",
|
|
141
|
+
"getHistoryById",
|
|
142
|
+
"runArchitecture",
|
|
143
|
+
"cancelArchitectureJob",
|
|
144
|
+
"getCreationsPaginatedParallel",
|
|
145
|
+
"getMentionSuggestionsParallel",
|
|
146
|
+
"createCharacter",
|
|
147
|
+
"updateCharacter",
|
|
148
|
+
"deleteCharacter",
|
|
149
|
+
"getCharacter",
|
|
150
|
+
"getCharacters",
|
|
151
|
+
"publishCharacter",
|
|
152
|
+
"unpublishCharacter",
|
|
153
|
+
"uploadCharacterImage",
|
|
154
|
+
"getCharactersPaginated",
|
|
155
|
+
"generateCharacterVoice",
|
|
156
|
+
"followCharacter",
|
|
157
|
+
"unfollowCharacter",
|
|
158
|
+
"uploadReferenceImage",
|
|
159
|
+
"createReference",
|
|
160
|
+
"updateReference",
|
|
161
|
+
"deleteReference",
|
|
162
|
+
"getReferences",
|
|
163
|
+
"getReferencesPaginated"
|
|
164
|
+
];
|
|
165
|
+
/**
|
|
166
|
+
* The action names a batched discovery caller must find before it can stop.
|
|
167
|
+
*
|
|
168
|
+
* @remarks
|
|
169
|
+
* These are the actions the portal invokes; once a batched caller has hashes for
|
|
170
|
+
* all of them it can early-exit instead of scraping every remaining chunk.
|
|
171
|
+
*/
|
|
172
|
+
function requiredActionsForClient() {
|
|
173
|
+
return [...REQUIRED_ACTIONS];
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* List the JS chunk paths referenced by the discovery pages.
|
|
177
|
+
*
|
|
178
|
+
* @remarks
|
|
179
|
+
* Issues at most one GET per page (`<= pages.length` subrequests), so a caller on
|
|
180
|
+
* a subrequest-capped host (e.g. Cloudflare Workers free plan) can list chunks
|
|
181
|
+
* cheaply and then scrape them in bounded batches via {@link scrapeChunks}.
|
|
182
|
+
*
|
|
183
|
+
* @throws {DiscoveryError} when no JS chunk references are found.
|
|
184
|
+
*/
|
|
185
|
+
async function listDiscoveryChunks(opts) {
|
|
134
186
|
const { fetch, baseUrl } = opts;
|
|
135
|
-
const pages = opts.
|
|
187
|
+
const pages = opts.pages ?? DISCOVERY_PAGES;
|
|
136
188
|
let deploymentId = "";
|
|
137
189
|
const chunkPaths = /* @__PURE__ */ new Set();
|
|
138
190
|
for (const page of pages) {
|
|
@@ -151,8 +203,26 @@ async function discoverActions(opts) {
|
|
|
151
203
|
}
|
|
152
204
|
}
|
|
153
205
|
if (chunkPaths.size === 0) throw new DiscoveryError("No JS chunk references found in discovery pages");
|
|
206
|
+
return {
|
|
207
|
+
deploymentId,
|
|
208
|
+
chunkPaths: [...chunkPaths]
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Scrape a specific set of JS chunks for `createServerReference(...)` hashes.
|
|
213
|
+
*
|
|
214
|
+
* @remarks
|
|
215
|
+
* Fetches ONLY the passed `chunkPaths` (one subrequest each), so a caller can
|
|
216
|
+
* process chunks in batches sized to its subrequest budget and merge the partial
|
|
217
|
+
* hash maps across batches. First hash wins per function name, mirroring
|
|
218
|
+
* {@link discoverActions}. Never throws on an empty result — a single batch may
|
|
219
|
+
* legitimately find nothing.
|
|
220
|
+
*/
|
|
221
|
+
async function scrapeChunks(opts) {
|
|
222
|
+
const { fetch, baseUrl, chunkPaths } = opts;
|
|
223
|
+
let deploymentId = "";
|
|
154
224
|
const hashes = {};
|
|
155
|
-
await Promise.all(
|
|
225
|
+
await Promise.all(chunkPaths.map(async (path) => {
|
|
156
226
|
try {
|
|
157
227
|
const chunkRes = await fetch(`${baseUrl}${path}`, { headers: { accept: "application/javascript" } });
|
|
158
228
|
if (!chunkRes.ok) return;
|
|
@@ -165,9 +235,37 @@ async function discoverActions(opts) {
|
|
|
165
235
|
}
|
|
166
236
|
} catch {}
|
|
167
237
|
}));
|
|
168
|
-
if (Object.keys(hashes).length === 0) throw new DiscoveryError("No server action hashes discovered in JS chunks");
|
|
169
238
|
return {
|
|
170
239
|
deploymentId,
|
|
240
|
+
hashes
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Discover the current Server Action hashes by scraping the page HTML for JS
|
|
245
|
+
* chunk URLs and extracting `createServerReference(...)` calls from each chunk.
|
|
246
|
+
*
|
|
247
|
+
* @remarks
|
|
248
|
+
* Composes {@link listDiscoveryChunks} (page GETs) and {@link scrapeChunks} (over
|
|
249
|
+
* all discovered chunks) into the full snapshot. Unsuitable for subrequest-capped
|
|
250
|
+
* hosts, which should batch {@link scrapeChunks} instead.
|
|
251
|
+
*
|
|
252
|
+
* @throws {DiscoveryError} on network failure or when nothing is discovered.
|
|
253
|
+
*/
|
|
254
|
+
async function discoverActions(opts) {
|
|
255
|
+
const { fetch, baseUrl } = opts;
|
|
256
|
+
const { deploymentId: pageDeploymentId, chunkPaths } = await listDiscoveryChunks({
|
|
257
|
+
fetch,
|
|
258
|
+
baseUrl,
|
|
259
|
+
pages: opts.discoveryPath !== void 0 ? [opts.discoveryPath] : opts.discoveryPaths ?? DISCOVERY_PAGES
|
|
260
|
+
});
|
|
261
|
+
const { deploymentId: chunkDeploymentId, hashes } = await scrapeChunks({
|
|
262
|
+
fetch,
|
|
263
|
+
baseUrl,
|
|
264
|
+
chunkPaths
|
|
265
|
+
});
|
|
266
|
+
if (Object.keys(hashes).length === 0) throw new DiscoveryError("No server action hashes discovered in JS chunks");
|
|
267
|
+
return {
|
|
268
|
+
deploymentId: pageDeploymentId !== "" ? pageDeploymentId : chunkDeploymentId,
|
|
171
269
|
hashes,
|
|
172
270
|
discoveredAt: Date.now()
|
|
173
271
|
};
|
|
@@ -1670,8 +1768,11 @@ exports.StaleActionError = StaleActionError;
|
|
|
1670
1768
|
exports.TimeoutError = TimeoutError;
|
|
1671
1769
|
exports.VERSION = VERSION;
|
|
1672
1770
|
exports.discoverActions = discoverActions;
|
|
1771
|
+
exports.listDiscoveryChunks = listDiscoveryChunks;
|
|
1673
1772
|
exports.parseFlightRows = parseFlightRows;
|
|
1674
1773
|
exports.parseServerActionResponse = parseServerActionResponse;
|
|
1774
|
+
exports.requiredActionsForClient = requiredActionsForClient;
|
|
1675
1775
|
exports.resolveActionName = resolveActionName;
|
|
1676
1776
|
exports.resolveFlightValue = resolveFlightValue;
|
|
1777
|
+
exports.scrapeChunks = scrapeChunks;
|
|
1677
1778
|
exports.unwrapResult = unwrapResult;
|
package/dist/index.d.cts
CHANGED
|
@@ -539,10 +539,63 @@ interface DiscoveryOptions {
|
|
|
539
539
|
/** Pages to scrape and union (default: the main app routes). */
|
|
540
540
|
discoveryPaths?: string[];
|
|
541
541
|
}
|
|
542
|
+
/** Result of {@link listDiscoveryChunks}: the JS chunk paths to scrape. */
|
|
543
|
+
interface ChunkListResult {
|
|
544
|
+
/** Vercel deployment id from the first page's `x-deployment-id` (`''` if none). */
|
|
545
|
+
deploymentId: string;
|
|
546
|
+
/** De-duplicated, insertion-ordered `/_next/static/chunks/*.js` paths. */
|
|
547
|
+
chunkPaths: string[];
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* The action names a batched discovery caller must find before it can stop.
|
|
551
|
+
*
|
|
552
|
+
* @remarks
|
|
553
|
+
* These are the actions the portal invokes; once a batched caller has hashes for
|
|
554
|
+
* all of them it can early-exit instead of scraping every remaining chunk.
|
|
555
|
+
*/
|
|
556
|
+
export declare function requiredActionsForClient(): ActionName[];
|
|
557
|
+
/**
|
|
558
|
+
* List the JS chunk paths referenced by the discovery pages.
|
|
559
|
+
*
|
|
560
|
+
* @remarks
|
|
561
|
+
* Issues at most one GET per page (`<= pages.length` subrequests), so a caller on
|
|
562
|
+
* a subrequest-capped host (e.g. Cloudflare Workers free plan) can list chunks
|
|
563
|
+
* cheaply and then scrape them in bounded batches via {@link scrapeChunks}.
|
|
564
|
+
*
|
|
565
|
+
* @throws {DiscoveryError} when no JS chunk references are found.
|
|
566
|
+
*/
|
|
567
|
+
export declare function listDiscoveryChunks(opts: {
|
|
568
|
+
fetch: FetchLike;
|
|
569
|
+
baseUrl: string;
|
|
570
|
+
pages?: string[];
|
|
571
|
+
}): Promise<ChunkListResult>;
|
|
572
|
+
/**
|
|
573
|
+
* Scrape a specific set of JS chunks for `createServerReference(...)` hashes.
|
|
574
|
+
*
|
|
575
|
+
* @remarks
|
|
576
|
+
* Fetches ONLY the passed `chunkPaths` (one subrequest each), so a caller can
|
|
577
|
+
* process chunks in batches sized to its subrequest budget and merge the partial
|
|
578
|
+
* hash maps across batches. First hash wins per function name, mirroring
|
|
579
|
+
* {@link discoverActions}. Never throws on an empty result — a single batch may
|
|
580
|
+
* legitimately find nothing.
|
|
581
|
+
*/
|
|
582
|
+
export declare function scrapeChunks(opts: {
|
|
583
|
+
fetch: FetchLike;
|
|
584
|
+
baseUrl: string;
|
|
585
|
+
chunkPaths: string[];
|
|
586
|
+
}): Promise<{
|
|
587
|
+
deploymentId: string;
|
|
588
|
+
hashes: ActionHashes;
|
|
589
|
+
}>;
|
|
542
590
|
/**
|
|
543
591
|
* Discover the current Server Action hashes by scraping the page HTML for JS
|
|
544
592
|
* chunk URLs and extracting `createServerReference(...)` calls from each chunk.
|
|
545
593
|
*
|
|
594
|
+
* @remarks
|
|
595
|
+
* Composes {@link listDiscoveryChunks} (page GETs) and {@link scrapeChunks} (over
|
|
596
|
+
* all discovered chunks) into the full snapshot. Unsuitable for subrequest-capped
|
|
597
|
+
* hosts, which should batch {@link scrapeChunks} instead.
|
|
598
|
+
*
|
|
546
599
|
* @throws {DiscoveryError} on network failure or when nothing is discovered.
|
|
547
600
|
*/
|
|
548
601
|
export declare function discoverActions(opts: DiscoveryOptions): Promise<ActionSnapshot>;
|
|
@@ -935,5 +988,5 @@ export declare const SEED_SNAPSHOT: ActionSnapshot;
|
|
|
935
988
|
/** Public entry point for `@zweer/mage-space-client`. */
|
|
936
989
|
export declare const VERSION = "0.0.0";
|
|
937
990
|
//#endregion
|
|
938
|
-
export type { ActionCache, ActionHashes, ActionName, ActionSnapshot, ArchitectureConfig, AspectRatio, AuthTokens, Character, CharacterPage, CharacterRef, CharacterSearchResult, ConfirmOptions, CreateCharacterInput, CreateReferenceInput, Creation, CreationPage, FallbackOptions, FetchLike, GenerateOptions, GenerateVideoOptions, GenerateVoiceOptions, GenerationMode, GenerationResult, HistoryItem, HistoryPage, JobStatus, ListCharactersOptions, ListCreationsOptions, ListHistoryOptions, ListReferencesOptions, LogicalAction, MageSpaceClientOptions, Modality, PollStrategy, Reference, ReferenceOrder, ReferencePage, ReferenceVariant, Resolution, SearchCharactersOptions, SessionState, Target, TargetKey, UpdateCharacterInput, UpdateReferenceInput, VideoArchitectureConfig, VideoAspectRatio, VideoResolution, Visibility, VoiceResult, WaitOptions };
|
|
991
|
+
export type { ActionCache, ActionHashes, ActionName, ActionSnapshot, ArchitectureConfig, AspectRatio, AuthTokens, Character, CharacterPage, CharacterRef, CharacterSearchResult, ChunkListResult, ConfirmOptions, CreateCharacterInput, CreateReferenceInput, Creation, CreationPage, FallbackOptions, FetchLike, GenerateOptions, GenerateVideoOptions, GenerateVoiceOptions, GenerationMode, GenerationResult, HistoryItem, HistoryPage, JobStatus, ListCharactersOptions, ListCreationsOptions, ListHistoryOptions, ListReferencesOptions, LogicalAction, MageSpaceClientOptions, Modality, PollStrategy, Reference, ReferenceOrder, ReferencePage, ReferenceVariant, Resolution, SearchCharactersOptions, SessionState, Target, TargetKey, UpdateCharacterInput, UpdateReferenceInput, VideoArchitectureConfig, VideoAspectRatio, VideoResolution, Visibility, VoiceResult, WaitOptions };
|
|
939
992
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../lib/targets.ts","../lib/types.ts","../lib/actions.ts","../lib/http.ts","../lib/auth.ts","../lib/characters.ts","../lib/references.ts","../lib/client.ts","../lib/errors.ts","../lib/rsc.ts","../lib/seed.ts","../lib/index.ts"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../lib/targets.ts","../lib/types.ts","../lib/actions.ts","../lib/http.ts","../lib/auth.ts","../lib/characters.ts","../lib/references.ts","../lib/client.ts","../lib/errors.ts","../lib/rsc.ts","../lib/seed.ts","../lib/index.ts"],"mappings":";;;;;;;;;;;;KAYY;;KAGA;;;;;;KAOA;;UAQK;WACN,KAAK;WACL;;WAEA,aAAa,SAAS,QAAQ,OAAO;WACrC,cAAc;;;wBAIT,kBAAkB,QAAQ,QAAQ,SAAS;;;;;;;;;;;;;qBAgB9C,mBAAmB;;;;;qBAiBnB,aAAa;;qBAkBb,+BAA+B;;;;KC/EhC,aAAa,eAAe,OAAO,gBAAgB,QAAQ;;UAOtD;;EAEf;;EAEA;;EAEA;;EAEA;;;UAIe;;EAEf;;EAEA;;;KAQU;;KAoCA,eAAe;;UAGV;;EAEf;;EAEA,QAAQ;;EAER;;;;;;;;;;UAWe;EACf,QAAQ,QAAQ;EAChB,KAAK,UAAU,iBAAiB;;KAOtB;KACA;;KAEA;;KAEA;;UAGK;EACf;EACA;EACA;EACA;;EAEA;;;UAIe;EACf;EACA;EACA;EACA;EACA;EACA;EACA,eAAe;;EAEf;EACA;EACA,YAAY;EACZ;EACA;;EAEA;;;UAIe;EACf;IACE;IACA;IACA;IACA;IACA;IACA;MAAe;MAAkB;;;EAEnC;EACA;;;UAIe;EACf;EACA;EACA,QAAQ;EACR;EACA;EACA;EACA,QAAQ;EACR;EACA,sBAAsB;EACtB;EACA;EACA;GACC;;;UAIc;EACf,WAAW;EACX;;UAOe;;EAEf;;EAEA,QAAQ;;EAER,QAAQ;;EAER;;EAEA,OAAO;;EAEP;;EAEA;;;;;;EAMA,WAAW;;;UAII;;EAEf,QAAQ;;EAER;;EAEA,iBAAiB;;UAGF;;EAEf;;EAEA;;EAEA;;EAEA;EACA,cAAc;EACd,aAAa;;EAEb;;EAEA;;EAEA,aAAa;;;;;;EAMb,aAAa;;EAEb;;EAEA;;EAEA,iBAAiB;;;KAQP;;KAEA;;;;;;;;UASK;EACf;EACA;EACA;EACA;;EAEA;EACA;EACA,qBAAqB;;EAErB;;EAEA;EACA;EACA,YAAY;EACZ;EACA;;UAGe;;EAEf;;EAEA;;EAEA;;EAEA;;EAEA,cAAc;;EAEd,aAAa;;EAEb;;EAEA;;EAEA;;EAEA,aAAa;;EAEb,aAAa;;EAEb;;EAEA;;EAEA,iBAAiB;;;;;;;;;UAUF;EACf;;UAGe;;EAEf;;EAEA;;EAEA,SAAS;;UAGM;;EAEf;;EAEA;;EAEA,SAAS;;;KAQC;;KAEA;;;;;;;;UASK;EACf;EACA;EACA;EACA;EACA;EACA;EACA,WAAW;EACX;EACA;EACA,aAAa;EACb;EACA;EACA;EACA;EACA;EACA;EACA;EACA;GACC;;;KAIS,YAAY;;UAGP;EACf,YAAY;EACZ,YAAY;EACZ;;UAGe;;EAEf;;EAEA;;EAEA;;EAEA,sBAAsB;;UAGP;;EAEf;;;;;;;;;EASA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA,aAAa;;EAEb;;UAGe;EACf;EACA;EACA;EACA,aAAa;EACb;;UAGe;;EAEf;;;;;EAKA;;EAEA;;EAEA;;EAEA,WAAW;;EAEX;EACA;EACA;EACA,aAAa;EACb;;;KAIU;UAEK;EACf;EACA;EACA;EACA,aAAa;;;KAIH;UAEK;;EAEf;;EAEA;;EAEA;;EAEA,aAAa;;EAEb,UAAU;;EAEV;;EAEA,WAAW;;;UAII;EACf,YAAY;EACZ;;UAGe;;EAEf;;EAEA;;EAEA;;EAEA,aAAa;;EAEb,WAAW;;EAEX;;;UAIe;EACf,YAAY;EACZ;;;UAIe;EACf;EACA;;EAEA;EACA;EACA;EACA,aAAa;EACb;EACA,sBAAsB;EACtB;IACE;IACA;IACA;IACA;IACA;MAAe;MAAkB;;;EAEnC;EACA;EACA;GACC;;;UAIc;EACf,WAAW;EACX;;UAGe;;EAEf;;EAEA;;UAGe;;EAEf;;EAEA;;;UAIe;EACf;EACA;;IAEE;;IAEA;;EAEF;IACE;IACA;IACA;;;;;;qBCpiBS,+BAA+B;UAClC;EAEF,QAAQ,QAAQ;EAIhB,KAAK,UAAU,iBAAiB;;UAKvB;EACf,OAAO;EACP;;EAEA;;EAEA;;;UAIe;;EAEf;;EAEA;;;;;;;;;wBAiDc,4BAA4B;;;;;;;;;;;wBActB,oBAAoB;EACxC,OAAO;EACP;EACA;IACE,QAAQ;;;;;;;;;;;wBA4CU,aAAa;EACjC,OAAO;EACP;EACA;IACE;EAAU;EAAsB,QAAQ;;;;;;;;;;;;;wBA+CtB,gBAAgB,MAAM,mBAAmB,QAAQ;UA6BtD;EACf,OAAO;EACP;EACA,QAAQ;EACR,OAAO;EACP;EACA;;EAEA;;;;;;qBAOW;mBACM;mBACA;mBACA;mBACA;mBACA;mBACA;mBACA;UACT;UACA;EAER,YAAY,MAAM;UAUV;;EAKF,eAAe,QAAQ;;EAkBvB,WAAW,QAAQ;;EAuBnB,QAAQ,QAAQ,sBAAsB;IAAU;IAAc;;;EAc9D,cAAc,QAAQ;;;;UC5Sb;;EAEf;;EAEA;;EAEA;;EAEA;;UAGe,iBAAiB;EAChC,MAAM;EACN,SAAS;EACT;;cAGW;mBAEQ;mBACA;mBACA;mBACA;mBACA;EALnB,YACmB,UAAU,gBACV,WAAW,WACX,iBACA,mBACA;;UAIX;EAMF,WAAW,aACf,QAAQ,kBACR,oBACC,QAAQ,iBAAiB;;;;UC9Cb;EACf;;;;;;EAMA,eAAe;EACf,OAAO;EACP;;EAEA;;cAGW;UACH;mBACS;mBACA;mBACA;mBACA;UACT;UACA;EAER,YAAY,MAAM;;;;;;EAalB;;EAKM,cAAc;;EAQd,aAAa;;EAQb,cAAc;UAmBN;;;;qBC7BH;mBAEQ;mBACA;EAFnB,YACmB,MAAM,YACN,MAAM;;EAInB,OAAO,MAAM,0BAA0B,QAAQ;;EAmB/C,OAAO,OAAO,uBAAuB,QAAQ;;EAwB7C,OAAO,YAAY,OAAO,uBAAuB,QAAQ;;EAYzD,OAAO,aAAa;;EAWpB,IAAI,aAAa,QAAQ;;EAYzB,QAAQ,gBAAgB,QAAQ;;EAYhC,QAAQ,aAAa;;EAWrB,UAAU,aAAa;;;;;;EAevB,YAAY,kBAAkB;;;;;;;;EAkB9B,cAAc,OAAM,wBAA6B,QAAQ;;;;;;;EAgCzD,cAAc,MAAM,uBAAuB,QAAQ;;;;;;EAmBnD,OAAO,aAAa;;;;;;EAepB,SAAS,aAAa;;;;qBC/NjB;mBAEQ;mBACA;EAFnB,YACmB,MAAM,YACN,MAAM;;;;;;EAQnB,YAAY,kBAAkB;;EAY9B,OAAO,OAAO,uBAAuB,QAAQ;;EA0B7C,OAAO,YAAY,OAAO,uBAAuB,QAAQ;;;;;EAezD,OAAO,YAAY,OAAO,iBAAiB;;EAY3C,KAAK,WAAU,WAAqB,QAAQ;;;;;;;;EAkB5C,cAAc,OAAM,wBAA6B,QAAQ;;;;qBC9GpD;mBACM;mBACA;mBACA;mBACA;mBAMA;UACT;UACA;UACA;;;;;;;;;WAUC,YAAY;;;;;;;;;WAUZ,YAAY;EAErB,YAAY,SAAS;;UAqEb;;UAYA;;UAWA;;UAWA;;UAQM;;EAiBd,SAAS,SAAS,kBAAkB;IAAU;;;EAK9C,cAAc,SAAS,uBAAuB;IAAU;;;EAKxD,UAAU,oBAAoB,QAAQ;;EAKtC,cAAc,mBAAmB,UAAU,cAAc,QAAQ;;EAKjE,UAAU,oBAAoB;;EAK9B,YAAY,UAAU,qBAAqB,QAAQ;;EAKnD,cAAc,UAAU,uBAAuB,QAAQ;;EAKvD,aAAa,QAAQ,mBAAmB;;EAKxC,cAAc,mBAAmB,UAAU,iBAAiB;;EAK5D,oBAAoB,sBAAsB,UAAU,iBAAiB;;EAKrE,eAAe,oBAAoB,UAAU,iBAAiB;;EAK9D,oBAAoB,uBAAuB,UAAU,iBAAiB;;EAKtE,kBAAkB,QAAQ;;EAK1B,UAAU;;EAKV,mBAAmB;;;;;;qBC/QR,uBAAuB;EAClC,YAAY,iBAAiB;IAAY;;;;qBAO9B,kBAAkB;EAC7B,YAAY,iBAAiB;IAAY;;;;qBAO9B,uBAAuB;;;;;WAKlB;EAEhB,YAAY,iBAAiB;IAAY;IAAiB;;;;;;;qBAW/C,+BAA+B;WAExB;WACA;EAFlB,YACkB,gBACA,mBAChB;IAAY;;;;;;;;;;qBAcH,yBAAyB;WAElB;EADlB,YACkB,gBAChB;IAAY;;;;qBAQH,wBAAwB;WAGjB;EAFlB,YACE,iBACgB,2BAChB;IAAY;;;;qBAQH,sBAAsB;EACjC,YAAY,iBAAiB;IAAY;;;;qBAO9B,qBAAqB;EAChC,YAAY,iBAAiB;IAAY;;;;;;;;;;;;;;;;;wBCjC3B,gBAAgB,eAAe;;wBAmE/B,mBACd,gBACA,MAAM,sBACN,OAAM;;;;;;wBAqDQ,0BAA0B,aAAa,eAAe;;;;;;;;;;;;wBA8BtD,aAAa,GAAG,iBAAiB;;;;;;;;;;;;qBCpMpC,eAAe;;;;qBCVf"}
|
package/dist/index.d.mts
CHANGED
|
@@ -539,10 +539,63 @@ interface DiscoveryOptions {
|
|
|
539
539
|
/** Pages to scrape and union (default: the main app routes). */
|
|
540
540
|
discoveryPaths?: string[];
|
|
541
541
|
}
|
|
542
|
+
/** Result of {@link listDiscoveryChunks}: the JS chunk paths to scrape. */
|
|
543
|
+
interface ChunkListResult {
|
|
544
|
+
/** Vercel deployment id from the first page's `x-deployment-id` (`''` if none). */
|
|
545
|
+
deploymentId: string;
|
|
546
|
+
/** De-duplicated, insertion-ordered `/_next/static/chunks/*.js` paths. */
|
|
547
|
+
chunkPaths: string[];
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* The action names a batched discovery caller must find before it can stop.
|
|
551
|
+
*
|
|
552
|
+
* @remarks
|
|
553
|
+
* These are the actions the portal invokes; once a batched caller has hashes for
|
|
554
|
+
* all of them it can early-exit instead of scraping every remaining chunk.
|
|
555
|
+
*/
|
|
556
|
+
export declare function requiredActionsForClient(): ActionName[];
|
|
557
|
+
/**
|
|
558
|
+
* List the JS chunk paths referenced by the discovery pages.
|
|
559
|
+
*
|
|
560
|
+
* @remarks
|
|
561
|
+
* Issues at most one GET per page (`<= pages.length` subrequests), so a caller on
|
|
562
|
+
* a subrequest-capped host (e.g. Cloudflare Workers free plan) can list chunks
|
|
563
|
+
* cheaply and then scrape them in bounded batches via {@link scrapeChunks}.
|
|
564
|
+
*
|
|
565
|
+
* @throws {DiscoveryError} when no JS chunk references are found.
|
|
566
|
+
*/
|
|
567
|
+
export declare function listDiscoveryChunks(opts: {
|
|
568
|
+
fetch: FetchLike;
|
|
569
|
+
baseUrl: string;
|
|
570
|
+
pages?: string[];
|
|
571
|
+
}): Promise<ChunkListResult>;
|
|
572
|
+
/**
|
|
573
|
+
* Scrape a specific set of JS chunks for `createServerReference(...)` hashes.
|
|
574
|
+
*
|
|
575
|
+
* @remarks
|
|
576
|
+
* Fetches ONLY the passed `chunkPaths` (one subrequest each), so a caller can
|
|
577
|
+
* process chunks in batches sized to its subrequest budget and merge the partial
|
|
578
|
+
* hash maps across batches. First hash wins per function name, mirroring
|
|
579
|
+
* {@link discoverActions}. Never throws on an empty result — a single batch may
|
|
580
|
+
* legitimately find nothing.
|
|
581
|
+
*/
|
|
582
|
+
export declare function scrapeChunks(opts: {
|
|
583
|
+
fetch: FetchLike;
|
|
584
|
+
baseUrl: string;
|
|
585
|
+
chunkPaths: string[];
|
|
586
|
+
}): Promise<{
|
|
587
|
+
deploymentId: string;
|
|
588
|
+
hashes: ActionHashes;
|
|
589
|
+
}>;
|
|
542
590
|
/**
|
|
543
591
|
* Discover the current Server Action hashes by scraping the page HTML for JS
|
|
544
592
|
* chunk URLs and extracting `createServerReference(...)` calls from each chunk.
|
|
545
593
|
*
|
|
594
|
+
* @remarks
|
|
595
|
+
* Composes {@link listDiscoveryChunks} (page GETs) and {@link scrapeChunks} (over
|
|
596
|
+
* all discovered chunks) into the full snapshot. Unsuitable for subrequest-capped
|
|
597
|
+
* hosts, which should batch {@link scrapeChunks} instead.
|
|
598
|
+
*
|
|
546
599
|
* @throws {DiscoveryError} on network failure or when nothing is discovered.
|
|
547
600
|
*/
|
|
548
601
|
export declare function discoverActions(opts: DiscoveryOptions): Promise<ActionSnapshot>;
|
|
@@ -935,5 +988,5 @@ export declare const SEED_SNAPSHOT: ActionSnapshot;
|
|
|
935
988
|
/** Public entry point for `@zweer/mage-space-client`. */
|
|
936
989
|
export declare const VERSION = "0.0.0";
|
|
937
990
|
//#endregion
|
|
938
|
-
export type { ActionCache, ActionHashes, ActionName, ActionSnapshot, ArchitectureConfig, AspectRatio, AuthTokens, Character, CharacterPage, CharacterRef, CharacterSearchResult, ConfirmOptions, CreateCharacterInput, CreateReferenceInput, Creation, CreationPage, FallbackOptions, FetchLike, GenerateOptions, GenerateVideoOptions, GenerateVoiceOptions, GenerationMode, GenerationResult, HistoryItem, HistoryPage, JobStatus, ListCharactersOptions, ListCreationsOptions, ListHistoryOptions, ListReferencesOptions, LogicalAction, MageSpaceClientOptions, Modality, PollStrategy, Reference, ReferenceOrder, ReferencePage, ReferenceVariant, Resolution, SearchCharactersOptions, SessionState, Target, TargetKey, UpdateCharacterInput, UpdateReferenceInput, VideoArchitectureConfig, VideoAspectRatio, VideoResolution, Visibility, VoiceResult, WaitOptions };
|
|
991
|
+
export type { ActionCache, ActionHashes, ActionName, ActionSnapshot, ArchitectureConfig, AspectRatio, AuthTokens, Character, CharacterPage, CharacterRef, CharacterSearchResult, ChunkListResult, ConfirmOptions, CreateCharacterInput, CreateReferenceInput, Creation, CreationPage, FallbackOptions, FetchLike, GenerateOptions, GenerateVideoOptions, GenerateVoiceOptions, GenerationMode, GenerationResult, HistoryItem, HistoryPage, JobStatus, ListCharactersOptions, ListCreationsOptions, ListHistoryOptions, ListReferencesOptions, LogicalAction, MageSpaceClientOptions, Modality, PollStrategy, Reference, ReferenceOrder, ReferencePage, ReferenceVariant, Resolution, SearchCharactersOptions, SessionState, Target, TargetKey, UpdateCharacterInput, UpdateReferenceInput, VideoArchitectureConfig, VideoAspectRatio, VideoResolution, Visibility, VoiceResult, WaitOptions };
|
|
939
992
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../lib/targets.ts","../lib/types.ts","../lib/actions.ts","../lib/http.ts","../lib/auth.ts","../lib/characters.ts","../lib/references.ts","../lib/client.ts","../lib/errors.ts","../lib/rsc.ts","../lib/seed.ts","../lib/index.ts"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../lib/targets.ts","../lib/types.ts","../lib/actions.ts","../lib/http.ts","../lib/auth.ts","../lib/characters.ts","../lib/references.ts","../lib/client.ts","../lib/errors.ts","../lib/rsc.ts","../lib/seed.ts","../lib/index.ts"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -124,14 +124,66 @@ var InMemoryActionCache = class {
|
|
|
124
124
|
}
|
|
125
125
|
};
|
|
126
126
|
/**
|
|
127
|
-
*
|
|
128
|
-
* chunk URLs and extracting `createServerReference(...)` calls from each chunk.
|
|
127
|
+
* The action names the portal actually invokes.
|
|
129
128
|
*
|
|
130
|
-
* @
|
|
129
|
+
* @remarks
|
|
130
|
+
* Verified against `lib/auth.ts`, `lib/generation.ts`/`lib/history.ts` (via
|
|
131
|
+
* `resolveActionName` on `PRODUCTION_TARGET`), `lib/characters.ts`, and
|
|
132
|
+
* `lib/references.ts`. A batched, subrequest-capped caller (e.g. a Cloudflare
|
|
133
|
+
* Worker) uses this list to know when it has discovered everything it needs and
|
|
134
|
+
* can early-exit without scraping the remaining chunks. Every name is a key in
|
|
135
|
+
* {@link SEED_SNAPSHOT}.hashes.
|
|
131
136
|
*/
|
|
132
|
-
|
|
137
|
+
const REQUIRED_ACTIONS = [
|
|
138
|
+
"createUserSession",
|
|
139
|
+
"getHistoryPaginated",
|
|
140
|
+
"getHistoryById",
|
|
141
|
+
"runArchitecture",
|
|
142
|
+
"cancelArchitectureJob",
|
|
143
|
+
"getCreationsPaginatedParallel",
|
|
144
|
+
"getMentionSuggestionsParallel",
|
|
145
|
+
"createCharacter",
|
|
146
|
+
"updateCharacter",
|
|
147
|
+
"deleteCharacter",
|
|
148
|
+
"getCharacter",
|
|
149
|
+
"getCharacters",
|
|
150
|
+
"publishCharacter",
|
|
151
|
+
"unpublishCharacter",
|
|
152
|
+
"uploadCharacterImage",
|
|
153
|
+
"getCharactersPaginated",
|
|
154
|
+
"generateCharacterVoice",
|
|
155
|
+
"followCharacter",
|
|
156
|
+
"unfollowCharacter",
|
|
157
|
+
"uploadReferenceImage",
|
|
158
|
+
"createReference",
|
|
159
|
+
"updateReference",
|
|
160
|
+
"deleteReference",
|
|
161
|
+
"getReferences",
|
|
162
|
+
"getReferencesPaginated"
|
|
163
|
+
];
|
|
164
|
+
/**
|
|
165
|
+
* The action names a batched discovery caller must find before it can stop.
|
|
166
|
+
*
|
|
167
|
+
* @remarks
|
|
168
|
+
* These are the actions the portal invokes; once a batched caller has hashes for
|
|
169
|
+
* all of them it can early-exit instead of scraping every remaining chunk.
|
|
170
|
+
*/
|
|
171
|
+
function requiredActionsForClient() {
|
|
172
|
+
return [...REQUIRED_ACTIONS];
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* List the JS chunk paths referenced by the discovery pages.
|
|
176
|
+
*
|
|
177
|
+
* @remarks
|
|
178
|
+
* Issues at most one GET per page (`<= pages.length` subrequests), so a caller on
|
|
179
|
+
* a subrequest-capped host (e.g. Cloudflare Workers free plan) can list chunks
|
|
180
|
+
* cheaply and then scrape them in bounded batches via {@link scrapeChunks}.
|
|
181
|
+
*
|
|
182
|
+
* @throws {DiscoveryError} when no JS chunk references are found.
|
|
183
|
+
*/
|
|
184
|
+
async function listDiscoveryChunks(opts) {
|
|
133
185
|
const { fetch, baseUrl } = opts;
|
|
134
|
-
const pages = opts.
|
|
186
|
+
const pages = opts.pages ?? DISCOVERY_PAGES;
|
|
135
187
|
let deploymentId = "";
|
|
136
188
|
const chunkPaths = /* @__PURE__ */ new Set();
|
|
137
189
|
for (const page of pages) {
|
|
@@ -150,8 +202,26 @@ async function discoverActions(opts) {
|
|
|
150
202
|
}
|
|
151
203
|
}
|
|
152
204
|
if (chunkPaths.size === 0) throw new DiscoveryError("No JS chunk references found in discovery pages");
|
|
205
|
+
return {
|
|
206
|
+
deploymentId,
|
|
207
|
+
chunkPaths: [...chunkPaths]
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Scrape a specific set of JS chunks for `createServerReference(...)` hashes.
|
|
212
|
+
*
|
|
213
|
+
* @remarks
|
|
214
|
+
* Fetches ONLY the passed `chunkPaths` (one subrequest each), so a caller can
|
|
215
|
+
* process chunks in batches sized to its subrequest budget and merge the partial
|
|
216
|
+
* hash maps across batches. First hash wins per function name, mirroring
|
|
217
|
+
* {@link discoverActions}. Never throws on an empty result — a single batch may
|
|
218
|
+
* legitimately find nothing.
|
|
219
|
+
*/
|
|
220
|
+
async function scrapeChunks(opts) {
|
|
221
|
+
const { fetch, baseUrl, chunkPaths } = opts;
|
|
222
|
+
let deploymentId = "";
|
|
153
223
|
const hashes = {};
|
|
154
|
-
await Promise.all(
|
|
224
|
+
await Promise.all(chunkPaths.map(async (path) => {
|
|
155
225
|
try {
|
|
156
226
|
const chunkRes = await fetch(`${baseUrl}${path}`, { headers: { accept: "application/javascript" } });
|
|
157
227
|
if (!chunkRes.ok) return;
|
|
@@ -164,9 +234,37 @@ async function discoverActions(opts) {
|
|
|
164
234
|
}
|
|
165
235
|
} catch {}
|
|
166
236
|
}));
|
|
167
|
-
if (Object.keys(hashes).length === 0) throw new DiscoveryError("No server action hashes discovered in JS chunks");
|
|
168
237
|
return {
|
|
169
238
|
deploymentId,
|
|
239
|
+
hashes
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Discover the current Server Action hashes by scraping the page HTML for JS
|
|
244
|
+
* chunk URLs and extracting `createServerReference(...)` calls from each chunk.
|
|
245
|
+
*
|
|
246
|
+
* @remarks
|
|
247
|
+
* Composes {@link listDiscoveryChunks} (page GETs) and {@link scrapeChunks} (over
|
|
248
|
+
* all discovered chunks) into the full snapshot. Unsuitable for subrequest-capped
|
|
249
|
+
* hosts, which should batch {@link scrapeChunks} instead.
|
|
250
|
+
*
|
|
251
|
+
* @throws {DiscoveryError} on network failure or when nothing is discovered.
|
|
252
|
+
*/
|
|
253
|
+
async function discoverActions(opts) {
|
|
254
|
+
const { fetch, baseUrl } = opts;
|
|
255
|
+
const { deploymentId: pageDeploymentId, chunkPaths } = await listDiscoveryChunks({
|
|
256
|
+
fetch,
|
|
257
|
+
baseUrl,
|
|
258
|
+
pages: opts.discoveryPath !== void 0 ? [opts.discoveryPath] : opts.discoveryPaths ?? DISCOVERY_PAGES
|
|
259
|
+
});
|
|
260
|
+
const { deploymentId: chunkDeploymentId, hashes } = await scrapeChunks({
|
|
261
|
+
fetch,
|
|
262
|
+
baseUrl,
|
|
263
|
+
chunkPaths
|
|
264
|
+
});
|
|
265
|
+
if (Object.keys(hashes).length === 0) throw new DiscoveryError("No server action hashes discovered in JS chunks");
|
|
266
|
+
return {
|
|
267
|
+
deploymentId: pageDeploymentId !== "" ? pageDeploymentId : chunkDeploymentId,
|
|
170
268
|
hashes,
|
|
171
269
|
discoveredAt: Date.now()
|
|
172
270
|
};
|
|
@@ -1650,6 +1748,6 @@ var MageSpaceClient = class {
|
|
|
1650
1748
|
/** Public entry point for `@zweer/mage-space-client`. */
|
|
1651
1749
|
const VERSION = "0.0.0";
|
|
1652
1750
|
//#endregion
|
|
1653
|
-
export { ActionRegistry, ActionUnavailableError, AuthError, BETA_TARGET, CharactersService, DEFAULT_TARGET_CHAIN, DiscoveryError, GenerationError, InMemoryActionCache, MageSpaceClient, MageSpaceError, PRODUCTION_TARGET, ReferencesService, RscParseError, SEED_SNAPSHOT, StaleActionError, TimeoutError, VERSION, discoverActions, parseFlightRows, parseServerActionResponse, resolveActionName, resolveFlightValue, unwrapResult };
|
|
1751
|
+
export { ActionRegistry, ActionUnavailableError, AuthError, BETA_TARGET, CharactersService, DEFAULT_TARGET_CHAIN, DiscoveryError, GenerationError, InMemoryActionCache, MageSpaceClient, MageSpaceError, PRODUCTION_TARGET, ReferencesService, RscParseError, SEED_SNAPSHOT, StaleActionError, TimeoutError, VERSION, discoverActions, listDiscoveryChunks, parseFlightRows, parseServerActionResponse, requiredActionsForClient, resolveActionName, resolveFlightValue, scrapeChunks, unwrapResult };
|
|
1654
1752
|
|
|
1655
1753
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["USERNAME_MAX","USERNAME_RE","generateUsername","validateUsername","HISTORY_PATH","UNDEFINED"],"sources":["../lib/errors.ts","../lib/actions.ts","../lib/rsc.ts","../lib/characters.ts","../lib/auth.ts","../lib/targets.ts","../lib/generation.ts","../lib/history.ts","../lib/references.ts","../lib/seed.ts","../lib/http.ts","../lib/target-context.ts","../lib/client.ts","../lib/index.ts"],"sourcesContent":["/** Typed error hierarchy for the mage.space client. */\n\n/** Base class for every error thrown by this library. */\nexport class MageSpaceError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'MageSpaceError';\n }\n}\n\n/** Authentication failures (token refresh, session creation). */\nexport class AuthError extends MageSpaceError {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'AuthError';\n }\n}\n\n/** Action-hash discovery failures (page/chunk fetch, empty registry). */\nexport class DiscoveryError extends MageSpaceError {\n /**\n * `true` when the action name was absent even after a forced re-discovery\n * (a fallback trigger); `false` for scrape failures (no chunks/no hashes).\n */\n public readonly notFound: boolean;\n\n constructor(message: string, options?: { cause?: unknown; notFound?: boolean }) {\n super(message, options);\n this.name = 'DiscoveryError';\n this.notFound = options?.notFound ?? false;\n }\n}\n\n/**\n * A required action is unavailable on the active host (a persistent 404 / HTML\n * fallback that survived one in-place re-discovery). A fallback trigger.\n */\nexport class ActionUnavailableError extends MageSpaceError {\n constructor(\n public readonly action: string,\n public readonly targetKey: string,\n options?: { cause?: unknown },\n ) {\n super(`Action \"${action}\" is unavailable on target \"${targetKey}\"`, options);\n this.name = 'ActionUnavailableError';\n }\n}\n\n/**\n * A Server Action returned 404, indicating a stale (post-deploy) hash.\n *\n * @deprecated Legacy export kept for backward compatibility; no longer thrown.\n * The current signal for a definitively unavailable action is\n * {@link ActionUnavailableError}.\n */\nexport class StaleActionError extends MageSpaceError {\n constructor(\n public readonly action: string,\n options?: { cause?: unknown },\n ) {\n super(`Action \"${action}\" returned 404 (stale hash)`, options);\n this.name = 'StaleActionError';\n }\n}\n\n/** Failures while submitting or polling a generation job. */\nexport class GenerationError extends MageSpaceError {\n constructor(\n message: string,\n public readonly code?: number,\n options?: { cause?: unknown },\n ) {\n super(message, options);\n this.name = 'GenerationError';\n }\n}\n\n/** Failure to parse a React Server Component (RSC) wire response. */\nexport class RscParseError extends MageSpaceError {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'RscParseError';\n }\n}\n\n/** A wait/poll operation exceeded its deadline or was aborted. */\nexport class TimeoutError extends MageSpaceError {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'TimeoutError';\n }\n}\n\n/**\n * Guard for irreversible operations: throws unless `{ confirm: true }` is passed.\n *\n * @throws {MageSpaceError} when confirmation is missing.\n */\nexport function requireConfirm(action: string, opts?: { confirm?: boolean }): void {\n if (opts?.confirm !== true) {\n throw new MageSpaceError(\n `${action} is irreversible and requires explicit confirmation: pass { confirm: true }`,\n );\n }\n}\n","/**\n * Action-hash discovery and caching.\n *\n * mage.space's Server Action hashes change on every Vercel deploy, so the client\n * discovers them from the page's JS bundles and caches the result. The registry\n * serves hashes from a warm seed / cache and only re-discovers when a hash goes\n * stale (a request 404s) or when explicitly refreshed.\n */\nimport { DiscoveryError } from './errors.js';\nimport type { ActionCache, ActionName, ActionSnapshot, FetchLike } from './types.js';\n\n/** `createServerReference)(\"<hash>\", callServer, void 0, findSourceMapURL, \"<fn>\")` */\nconst CREATE_SERVER_REF_RE = /createServerReference\\)\\(\"([0-9a-f]+)\"[^)]*?\"([^\"]+)\"\\)/g;\n/** `/_next/static/chunks/....js` references in the page HTML. */\nconst CHUNK_RE = /\\/_next\\/static\\/chunks\\/[^\"'`()\\s]+?\\.js/g;\n/**\n * Default pages scraped during discovery. Server Actions are split per route, so\n * a single page misses route-specific actions (e.g. `deleteReference` lives only\n * in the `/references` bundle) — scrape the main routes and union their chunks.\n */\nconst DISCOVERY_PAGES = ['/explore', '/creations', '/characters', '/references'];\n\n/** Default in-process snapshot cache. */\nexport class InMemoryActionCache implements ActionCache {\n private snapshot: ActionSnapshot | null = null;\n\n async load(): Promise<ActionSnapshot | null> {\n return this.snapshot;\n }\n\n async save(snapshot: ActionSnapshot): Promise<void> {\n this.snapshot = snapshot;\n }\n}\n\nexport interface DiscoveryOptions {\n fetch: FetchLike;\n baseUrl: string;\n /** Single page to scrape for chunk references (overrides {@link discoveryPaths}). */\n discoveryPath?: string;\n /** Pages to scrape and union (default: the main app routes). */\n discoveryPaths?: string[];\n}\n\n/**\n * Discover the current Server Action hashes by scraping the page HTML for JS\n * chunk URLs and extracting `createServerReference(...)` calls from each chunk.\n *\n * @throws {DiscoveryError} on network failure or when nothing is discovered.\n */\nexport async function discoverActions(opts: DiscoveryOptions): Promise<ActionSnapshot> {\n const { fetch, baseUrl } = opts;\n const pages =\n opts.discoveryPath !== undefined\n ? [opts.discoveryPath]\n : (opts.discoveryPaths ?? DISCOVERY_PAGES);\n\n let deploymentId = '';\n const chunkPaths = new Set<string>();\n for (const page of pages) {\n let res: Response;\n try {\n res = await fetch(`${baseUrl}${page}`, { headers: { accept: 'text/html' } });\n } catch {\n // A single unreachable page must not abort discovery.\n continue;\n }\n if (!res.ok) {\n continue;\n }\n if (deploymentId === '') {\n deploymentId = res.headers.get('x-deployment-id') ?? '';\n }\n const html = await res.text();\n for (const match of html.matchAll(CHUNK_RE)) {\n const chunkPath = match[0];\n if (chunkPath !== undefined) {\n chunkPaths.add(chunkPath);\n }\n }\n }\n if (chunkPaths.size === 0) {\n throw new DiscoveryError('No JS chunk references found in discovery pages');\n }\n\n const hashes: ActionSnapshot['hashes'] = {};\n await Promise.all(\n [...chunkPaths].map(async (path) => {\n try {\n const chunkRes = await fetch(`${baseUrl}${path}`, {\n headers: { accept: 'application/javascript' },\n });\n if (!chunkRes.ok) {\n return;\n }\n // Fallback: CDN-cached page HTML may omit x-deployment-id; chunk responses\n // are served by the deployment and usually carry it.\n if (deploymentId === '') {\n deploymentId = chunkRes.headers.get('x-deployment-id') ?? '';\n }\n const js = await chunkRes.text();\n for (const match of js.matchAll(CREATE_SERVER_REF_RE)) {\n const hash = match[1];\n const fn = match[2];\n if (hash !== undefined && fn !== undefined && !(fn in hashes)) {\n hashes[fn] = hash;\n }\n }\n } catch {\n // A single failed chunk must not abort discovery.\n }\n }),\n );\n\n if (Object.keys(hashes).length === 0) {\n throw new DiscoveryError('No server action hashes discovered in JS chunks');\n }\n return { deploymentId, hashes, discoveredAt: Date.now() };\n}\n\nexport interface ActionRegistryOptions {\n fetch: FetchLike;\n baseUrl: string;\n cache?: ActionCache;\n seed?: ActionSnapshot;\n discoveryPath?: string;\n discoveryPaths?: string[];\n /** Re-discover when the snapshot is older than this (ms). 0 = never by age. */\n maxAgeMs?: number;\n}\n\n/**\n * Serves action hashes from a warm seed / pluggable cache, discovering lazily and\n * refreshing on staleness. Concurrent refreshes are de-duplicated (single-flight).\n */\nexport class ActionRegistry {\n private readonly fetch: FetchLike;\n private readonly baseUrl: string;\n private readonly cache: ActionCache;\n private readonly seed: ActionSnapshot | undefined;\n private readonly discoveryPath: string | undefined;\n private readonly discoveryPaths: string[] | undefined;\n private readonly maxAgeMs: number;\n private snapshot: ActionSnapshot | null = null;\n private inflight: Promise<ActionSnapshot> | null = null;\n\n constructor(opts: ActionRegistryOptions) {\n this.fetch = opts.fetch;\n this.baseUrl = opts.baseUrl;\n this.cache = opts.cache ?? new InMemoryActionCache();\n this.seed = opts.seed;\n this.discoveryPath = opts.discoveryPath;\n this.discoveryPaths = opts.discoveryPaths;\n this.maxAgeMs = opts.maxAgeMs ?? 0;\n }\n\n private isStale(snapshot: ActionSnapshot): boolean {\n return this.maxAgeMs > 0 && Date.now() - snapshot.discoveredAt > this.maxAgeMs;\n }\n\n /** Return the current snapshot, loading from cache/seed or discovering as needed. */\n async getSnapshot(): Promise<ActionSnapshot> {\n if (this.snapshot !== null && !this.isStale(this.snapshot)) {\n return this.snapshot;\n }\n const cached = await this.cache.load();\n if (cached !== null && !this.isStale(cached)) {\n this.snapshot = cached;\n return cached;\n }\n if (this.seed !== undefined) {\n this.snapshot = this.seed;\n await this.cache.save(this.seed);\n return this.seed;\n }\n return this.refresh();\n }\n\n /** Force re-discovery. Concurrent callers share one in-flight discovery. */\n async refresh(): Promise<ActionSnapshot> {\n if (this.inflight !== null) {\n return this.inflight;\n }\n this.inflight = (async () => {\n try {\n const fresh = await discoverActions({\n fetch: this.fetch,\n baseUrl: this.baseUrl,\n discoveryPath: this.discoveryPath,\n discoveryPaths: this.discoveryPaths,\n });\n this.snapshot = fresh;\n await this.cache.save(fresh);\n return fresh;\n } finally {\n this.inflight = null;\n }\n })();\n return this.inflight;\n }\n\n /** Resolve a function name to its current hash + deployment id. */\n async getHash(action: ActionName | string): Promise<{ hash: string; deploymentId: string }> {\n let snapshot = await this.getSnapshot();\n let hash = snapshot.hashes[action];\n if (hash === undefined) {\n snapshot = await this.refresh();\n hash = snapshot.hashes[action];\n }\n if (hash === undefined) {\n throw new DiscoveryError(`Action \"${action}\" not found after discovery`, { notFound: true });\n }\n return { hash, deploymentId: snapshot.deploymentId };\n }\n\n /** Drop the cached snapshot and re-discover (called on a stale 404). */\n async invalidate(): Promise<ActionSnapshot> {\n this.snapshot = null;\n return this.refresh();\n }\n}\n","/**\n * Minimal parser for the React Server Component (RSC) \"Flight\" wire format used\n * by Next.js Server Action responses.\n *\n * The wire format is a sequence of newline-delimited rows:\n *\n * ```text\n * 0:{\"a\":\"$@1\",\"f\":\"\",\"b\":\"buildId\"}\n * 1:{\"history_id\":\"e3357fb8-...\",\"architecture_config\":\"$T0:0:architectureConfig\"}\n * ```\n *\n * Each row is `<hexId>:<jsonPayload>`. Values may contain sentinels:\n * - `$undefined` → `undefined`\n * - `$@<id>` → reference to another row (a resolved promise)\n * - `$$...` → an escaped literal string starting with `$`\n * - `$<other>` → a typed marker (kept verbatim, best-effort)\n *\n * @remarks\n * The exact envelope for some read actions (e.g. `getHistoryById`) should be\n * confirmed against live traffic via the rev-eng Playwright flow; this parser is\n * intentionally tolerant and falls back to the last JSON row when the row-0\n * `{ a: ... }` envelope is absent.\n */\nimport { RscParseError } from './errors.js';\n\nconst REF_RE = /^\\$@([0-9a-f]+)$/i;\n/** A plain row reference like `$5` (not a promise `$@5`, nor a `$D`/`$S`/... marker). */\nconst HEX_REF_RE = /^\\$([0-9a-f]+)$/i;\nconst ROW_ID_RE = /^[0-9a-f]+$/i;\n\n/** Return the char index after consuming exactly `byteLen` UTF-8 bytes from `start`. */\nfunction endOfUtf8Slice(text: string, start: number, byteLen: number): number {\n let bytes = 0;\n let i = start;\n while (i < text.length && bytes < byteLen) {\n const cp = text.codePointAt(i) as number;\n bytes += cp <= 0x7f ? 1 : cp <= 0x7ff ? 2 : cp <= 0xffff ? 3 : 4;\n i += cp > 0xffff ? 2 : 1;\n }\n return i;\n}\n\n/**\n * Parse the raw Flight text into a map of `rowId → value`.\n *\n * @remarks\n * Most rows are `id:<json>\\n`, but text rows are length-delimited:\n * `id:T<hexlen>,<hexlen UTF-8 bytes>` and are NOT newline-terminated — the next\n * row begins immediately after the counted bytes. A naive line split therefore\n * glues the following data row onto a multi-line prompt (which is exactly why\n * large `getHistoryPaginated` responses failed to parse). This parser is\n * position/length aware so length-delimited rows are consumed exactly and every\n * subsequent row stays isolated.\n */\nexport function parseFlightRows(text: string): Map<string, unknown> {\n const rows = new Map<string, unknown>();\n const n = text.length;\n let pos = 0;\n while (pos < n) {\n if (text[pos] === '\\n') {\n pos += 1;\n continue;\n }\n const colon = text.indexOf(':', pos);\n if (colon === -1) {\n break;\n }\n const id = text.slice(pos, colon);\n if (!ROW_ID_RE.test(id)) {\n // Not a row boundary; skip to the next line and resync.\n const nl = text.indexOf('\\n', pos);\n if (nl === -1) {\n break;\n }\n pos = nl + 1;\n continue;\n }\n if (text[colon + 1] === 'T') {\n // Length-delimited text row: T<hexlen>,<bytes> (no trailing newline).\n const comma = text.indexOf(',', colon + 2);\n if (comma === -1) {\n break;\n }\n const byteLen = Number.parseInt(text.slice(colon + 2, comma), 16);\n const start = comma + 1;\n const end = endOfUtf8Slice(text, start, byteLen);\n rows.set(id, text.slice(start, end));\n pos = end;\n continue;\n }\n // Any other row is a single line terminated by \\n.\n const nl = text.indexOf('\\n', colon + 1);\n const payload = nl === -1 ? text.slice(colon + 1) : text.slice(colon + 1, nl);\n pos = nl === -1 ? n : nl + 1;\n const first = payload[0];\n if (first === undefined) {\n continue;\n }\n const looksJson =\n first === '{' ||\n first === '[' ||\n first === '\"' ||\n first === '-' ||\n (first >= '0' && first <= '9') ||\n payload === 'true' ||\n payload === 'false' ||\n payload === 'null';\n if (!looksJson) {\n // Module/element/hint rows (e.g. `1:I[...]`, `2:\"$Sreact...\"`) are not data.\n continue;\n }\n try {\n rows.set(id, JSON.parse(payload));\n } catch {\n // Ignore rows that are not valid JSON.\n }\n }\n return rows;\n}\n\n/** Recursively resolve Flight sentinels/references within a parsed value. */\nexport function resolveFlightValue(\n value: unknown,\n rows: Map<string, unknown>,\n seen: Set<string> = new Set(),\n): unknown {\n if (typeof value === 'string') {\n if (value === '$undefined') {\n return undefined;\n }\n const ref = REF_RE.exec(value) ?? HEX_REF_RE.exec(value);\n if (ref) {\n const refId = ref[1];\n if (refId === undefined || seen.has(refId)) {\n return undefined;\n }\n const target = rows.get(refId);\n if (target === undefined) {\n return undefined;\n }\n // Scope the cycle guard to the current depth-first path: descend with a\n // fresh copy that records this ref. Siblings keep the unmutated `seen`, so\n // a DAG (many siblings pointing at one shared row) resolves on every sibling,\n // while a true cycle (a refId already on this ancestor path) still returns\n // undefined.\n const nextSeen = new Set(seen);\n nextSeen.add(refId);\n return resolveFlightValue(target, rows, nextSeen);\n }\n if (value.startsWith('$$')) {\n return value.slice(1);\n }\n // $D<iso> → Date object (React Flight Date sentinel).\n if (value.startsWith('$D')) {\n return new Date(value.slice(2));\n }\n // Other `$`-prefixed markers are kept verbatim.\n return value;\n }\n if (Array.isArray(value)) {\n return value.map((entry) => resolveFlightValue(entry, rows, seen));\n }\n if (value !== null && typeof value === 'object') {\n const out: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(value)) {\n out[key] = resolveFlightValue(entry, rows, seen);\n }\n return out;\n }\n return value;\n}\n\n/**\n * Parse a Server Action response and return the action's resolved return value.\n *\n * @throws {RscParseError} when the response contains no parseable rows.\n */\nexport function parseServerActionResponse<T = unknown>(text: string): T {\n const rows = parseFlightRows(text);\n if (rows.size === 0) {\n throw new RscParseError('Empty or unparseable RSC response');\n }\n const root = rows.get('0');\n if (root !== null && typeof root === 'object' && !Array.isArray(root) && 'a' in root) {\n return resolveFlightValue((root as Record<string, unknown>).a, rows) as T;\n }\n // Fallback: the highest-id row usually carries the payload.\n let lastId: string | null = null;\n for (const id of rows.keys()) {\n if (lastId === null || Number.parseInt(id, 16) > Number.parseInt(lastId, 16)) {\n lastId = id;\n }\n }\n return resolveFlightValue(lastId === null ? undefined : rows.get(lastId), rows) as T;\n}\n\n/**\n * Unwrap a single-object result that some Server Actions (notably the\n * `*Parallel` family) wrap in a one-element array.\n *\n * @remarks\n * `getCreationsPaginatedParallel` and `getMentionSuggestionsParallel` return their\n * payload as `[value]` on the RSC wire (`1:[\"$@2\"]`), whereas most actions return\n * the value directly. This normalizes object-returning actions to the value; it is\n * a no-op when the response is already the object. Do NOT use it for actions whose\n * genuine return type is an array (e.g. `getReferences`).\n */\nexport function unwrapResult<T>(value: unknown): T {\n return (Array.isArray(value) && value.length === 1 ? value[0] : value) as T;\n}\n","/**\n * Character & reference management.\n *\n * Covers the verified Server Actions from `docs/api/characters.md`: search\n * (`getMentionSuggestionsParallel`), full CRUD, pagination, publish/unpublish,\n * and base64 image uploads.\n *\n * @remarks\n * Read operations pass the caller's `uid` in the body; write operations rely on\n * the `__session` cookie (the server derives the uid from it). All actions are\n * posted to the `/explore` page where their bundles are loaded.\n */\nimport type { AuthManager } from './auth.js';\nimport { MageSpaceError } from './errors.js';\nimport type { HttpClient } from './http.js';\nimport { unwrapResult } from './rsc.js';\nimport type {\n Character,\n CharacterPage,\n CharacterSearchResult,\n CreateCharacterInput,\n GenerateVoiceOptions,\n ListCharactersOptions,\n SearchCharactersOptions,\n UpdateCharacterInput,\n VoiceResult,\n} from './types.js';\n\n/** Character actions are served from the `/explore` page. */\nconst CHARACTERS_PATH = '/explore';\nconst DEFAULT_SEARCH_LIMIT = 10;\n\n/** Server-enforced username constraints (from module 64428). */\nconst USERNAME_MIN = 1;\nconst USERNAME_MAX = 15;\nconst USERNAME_RE = /^[a-z][a-z0-9_-]*$/;\n\n/**\n * Generate a username from a display name, matching the web UI logic:\n * lowercase, strip special chars, append a 4-char random suffix, truncate to 15.\n */\nfunction generateUsername(name: string): string {\n const suffix = Math.random().toString(36).substring(2, 6);\n const base = name\n .toLowerCase()\n .trim()\n .replace(/[^a-z0-9\\s]/g, '')\n .replace(/\\s+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '');\n // Ensure the random suffix always fits: base is truncated to leave room for `-xxxx`.\n const maxBase = USERNAME_MAX - suffix.length - 1; // 1 for the dash separator\n const trimmedBase = base.slice(0, maxBase).replace(/[-_]+$/, '');\n return `${trimmedBase}-${suffix}`;\n}\n\n/** Validate a username and throw early with a clear message instead of a server 500. */\nfunction validateUsername(username: string): void {\n if (username.length < USERNAME_MIN) {\n throw new MageSpaceError('Username is required (min 1 character)');\n }\n if (username.length > USERNAME_MAX) {\n throw new MageSpaceError(\n `Username \"${username}\" is too long (${username.length} chars, max ${USERNAME_MAX})`,\n );\n }\n if (!USERNAME_RE.test(username)) {\n throw new MageSpaceError(\n `Username \"${username}\" is invalid: must start with a lowercase letter and contain only a-z, 0-9, _ or -`,\n );\n }\n}\n\nexport class CharactersService {\n constructor(\n private readonly http: HttpClient,\n private readonly auth: AuthManager,\n ) {}\n\n /** Search the caller's characters (and optionally public references) by name. */\n async search(opts: SearchCharactersOptions): Promise<CharacterSearchResult> {\n const [uid, session] = await Promise.all([this.auth.getUserId(), this.auth.getSession()]);\n const body = {\n query: opts.query,\n uid,\n limit: opts.limit ?? DEFAULT_SEARCH_LIMIT,\n includePublicReferences: opts.includePublicReferences ?? false,\n referenceModalities: opts.referenceModalities ?? ['image', 'audio'],\n };\n const { data } = await this.http.callAction<CharacterSearchResult>({\n action: 'getMentionSuggestionsParallel',\n path: CHARACTERS_PATH,\n args: [body],\n session,\n });\n return unwrapResult<CharacterSearchResult>(data);\n }\n\n /** Create a new character from an already-uploaded image URL. */\n async create(input: CreateCharacterInput): Promise<Character> {\n const username = input.username ?? generateUsername(input.name);\n validateUsername(username);\n const session = await this.auth.getSession();\n const body = {\n name: input.name,\n username,\n image_url: input.image_url,\n audio_url: input.audio_url ?? null,\n description: input.description ?? null,\n tags: input.tags ?? [],\n visibility: input.visibility ?? 'private',\n moderation: input.moderation ?? [],\n };\n const { data } = await this.http.callAction<Character>({\n action: 'createCharacter',\n path: CHARACTERS_PATH,\n args: [body],\n session,\n });\n return data;\n }\n\n /** Update a character's mutable fields (name, description, tags, visibility, voice). */\n async update(id: string, patch: UpdateCharacterInput): Promise<Character> {\n const session = await this.auth.getSession();\n const { data } = await this.http.callAction<Character>({\n action: 'updateCharacter',\n path: CHARACTERS_PATH,\n args: [id, patch],\n session,\n });\n return data;\n }\n\n /** Soft-delete a character. */\n async delete(id: string): Promise<void> {\n const session = await this.auth.getSession();\n await this.http.callAction({\n action: 'deleteCharacter',\n path: CHARACTERS_PATH,\n args: [id],\n session,\n });\n }\n\n /** Fetch a single character by id; resolves to `null` when it does not exist. */\n async get(id: string): Promise<Character | null> {\n const session = await this.auth.getSession();\n const { data } = await this.http.callAction<Character | null>({\n action: 'getCharacter',\n path: CHARACTERS_PATH,\n args: [id],\n session,\n });\n return data ?? null;\n }\n\n /** Fetch multiple characters by id in a single call. */\n async getMany(ids: string[]): Promise<Character[]> {\n const session = await this.auth.getSession();\n const { data } = await this.http.callAction<Character[]>({\n action: 'getCharacters',\n path: CHARACTERS_PATH,\n args: [ids],\n session,\n });\n return data ?? [];\n }\n\n /** Make a character public. */\n async publish(id: string): Promise<void> {\n const session = await this.auth.getSession();\n await this.http.callAction({\n action: 'publishCharacter',\n path: CHARACTERS_PATH,\n args: [id],\n session,\n });\n }\n\n /** Make a character private. */\n async unpublish(id: string): Promise<void> {\n const session = await this.auth.getSession();\n await this.http.callAction({\n action: 'unpublishCharacter',\n path: CHARACTERS_PATH,\n args: [id],\n session,\n });\n }\n\n /**\n * Upload a character reference image (base64 data URL) and return its CDN URL.\n *\n * @param dataUrl - `data:image/jpeg;base64,...` (JPEG preferred; PNG/WebP ok).\n */\n async uploadImage(dataUrl: string): Promise<string> {\n const [uid, session] = await Promise.all([this.auth.getUserId(), this.auth.getSession()]);\n const { data } = await this.http.callAction<string>({\n action: 'uploadCharacterImage',\n path: CHARACTERS_PATH,\n args: [dataUrl, uid],\n session,\n });\n return data;\n }\n\n /**\n * Browse characters with pagination.\n *\n * @remarks\n * Omit `uid` to browse the public/featured feed; pass it to page through a\n * single user's characters.\n */\n async listPaginated(opts: ListCharactersOptions = {}): Promise<CharacterPage> {\n const session = await this.auth.getSession();\n const limit = opts.limit ?? 100;\n const offset = opts.offset ?? 0;\n const filters: Record<string, unknown> = {};\n if (opts.uid !== undefined) {\n filters.uid = opts.uid;\n }\n if (opts.visibility !== undefined) {\n filters.visibility = opts.visibility;\n }\n if (opts.modality !== undefined) {\n filters.modality = opts.modality;\n }\n if (opts.featured !== undefined) {\n filters.featured = opts.featured;\n }\n const { data } = await this.http.callAction<CharacterPage>({\n action: 'getCharactersPaginated',\n path: CHARACTERS_PATH,\n args: [limit, offset, filters],\n session,\n });\n return data;\n }\n\n /**\n * Generate a voice for a character from its reference image.\n *\n * @remarks Costs gems (not covered by the unlimited tier).\n * @experimental Request body inferred from JS bundle; not yet verified live.\n */\n async generateVoice(opts: GenerateVoiceOptions): Promise<VoiceResult> {\n const [authToken, session] = await Promise.all([\n this.auth.getIdToken(),\n this.auth.getSession(),\n ]);\n const { data } = await this.http.callAction<VoiceResult>({\n action: 'generateCharacterVoice',\n path: CHARACTERS_PATH,\n args: [{ imageUrl: opts.imageUrl, guidancePrompt: opts.guidancePrompt ?? '' }, authToken],\n session,\n });\n return data;\n }\n\n /**\n * Follow a (public) character.\n *\n * @experimental Request body inferred from JS bundle; not yet verified live.\n */\n async follow(id: string): Promise<void> {\n const session = await this.auth.getSession();\n await this.http.callAction({\n action: 'followCharacter',\n path: CHARACTERS_PATH,\n args: [id],\n session,\n });\n }\n\n /**\n * Unfollow a character.\n *\n * @experimental Request body inferred from JS bundle; not yet verified live.\n */\n async unfollow(id: string): Promise<void> {\n const session = await this.auth.getSession();\n await this.http.callAction({\n action: 'unfollowCharacter',\n path: CHARACTERS_PATH,\n args: [id],\n session,\n });\n }\n}\n","/**\n * Firebase authentication: refresh token → ID token → session cookie.\n *\n * The refresh token is the only long-lived credential the caller supplies.\n * From it we mint a Firebase ID token (~1h) via the Secure Token REST API, and\n * exchange that for a `__session` cookie (~24h) via the `createUserSession`\n * Server Action. Both are cached and refreshed 5 minutes before expiry.\n */\nimport { decodeJwt } from 'jose';\nimport { AuthError } from './errors.js';\nimport type { HttpClient } from './http.js';\nimport type { AuthTokens, FetchLike, SessionState } from './types.js';\n\nconst DEFAULT_FIREBASE_API_KEY = 'AIzaSyAzUV2NNUOlLTL04jwmUw9oLhjteuv6Qr4';\nconst SECURE_TOKEN_URL = 'https://securetoken.googleapis.com/v1/token';\nconst EXPIRY_BUFFER_MS = 5 * 60 * 1000;\nconst SESSION_DEFAULT_TTL_MS = 24 * 60 * 60 * 1000;\nconst ID_TOKEN_DEFAULT_TTL_S = 3600;\n\ninterface SecureTokenResponse {\n id_token?: string;\n refresh_token?: string;\n user_id?: string;\n expires_in?: string;\n}\n\nexport interface AuthManagerOptions {\n refreshToken: string;\n /**\n * Accessor for the active host's {@link HttpClient}. A closure (not the client\n * itself) so `createUserSession` always hits whichever host is currently\n * active after an automatic fallback.\n */\n getHttp: () => HttpClient;\n fetch: FetchLike;\n firebaseApiKey?: string;\n /** Page path for the `createUserSession` action (default `/creations`). */\n sessionPath?: string;\n}\n\nexport class AuthManager {\n private refreshToken: string;\n private readonly getHttp: () => HttpClient;\n private readonly fetchImpl: FetchLike;\n private readonly apiKey: string;\n private readonly sessionPath: string;\n private tokens: AuthTokens | null = null;\n private session: SessionState | null = null;\n\n constructor(opts: AuthManagerOptions) {\n this.refreshToken = opts.refreshToken;\n this.getHttp = opts.getHttp;\n this.fetchImpl = opts.fetch;\n this.apiKey = opts.firebaseApiKey ?? DEFAULT_FIREBASE_API_KEY;\n this.sessionPath = opts.sessionPath ?? '/creations';\n }\n\n /**\n * Drop the cached `__session` cookie so the next {@link getSession} mints a\n * fresh one against the (newly) active host. The Firebase token chain is kept\n * because it is host-independent.\n */\n resetSession(): void {\n this.session = null;\n }\n\n /** Return a valid Firebase ID token, refreshing via the refresh token if needed. */\n async getIdToken(): Promise<string> {\n if (this.tokens !== null && Date.now() < this.tokens.expiresAt - EXPIRY_BUFFER_MS) {\n return this.tokens.idToken;\n }\n return (await this.refreshTokens()).idToken;\n }\n\n /** Return the Firebase uid (fetching an ID token first if necessary). */\n async getUserId(): Promise<string> {\n if (this.tokens !== null) {\n return this.tokens.userId;\n }\n return (await this.refreshTokens()).userId;\n }\n\n /** Return a valid `__session` cookie, creating one via `createUserSession` if needed. */\n async getSession(): Promise<string> {\n if (this.session !== null && Date.now() < this.session.expiresAt - EXPIRY_BUFFER_MS) {\n return this.session.cookie;\n }\n const idToken = await this.getIdToken();\n const result = await this.getHttp().callAction<unknown>({\n action: 'createUserSession',\n path: this.sessionPath,\n args: [idToken],\n });\n const cookie = extractSessionCookie(result.headers);\n if (cookie === null) {\n throw new AuthError('createUserSession did not return a __session cookie');\n }\n const expiresAt = jwtExpiryMs(cookie) ?? Date.now() + SESSION_DEFAULT_TTL_MS;\n this.session = { cookie, expiresAt };\n return cookie;\n }\n\n private async refreshTokens(): Promise<AuthTokens> {\n const body = new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: this.refreshToken,\n });\n const res = await this.fetchImpl(`${SECURE_TOKEN_URL}?key=${this.apiKey}`, {\n method: 'POST',\n headers: { 'content-type': 'application/x-www-form-urlencoded' },\n body: body.toString(),\n });\n if (!res.ok) {\n throw new AuthError(\n `Token refresh failed: HTTP ${res.status} (refresh token may be invalid or revoked)`,\n );\n }\n const json = (await res.json()) as SecureTokenResponse;\n if (json.id_token === undefined || json.user_id === undefined) {\n throw new AuthError('Token refresh response missing id_token/user_id');\n }\n if (json.refresh_token !== undefined) {\n this.refreshToken = json.refresh_token;\n }\n const ttlS = json.expires_in === undefined ? ID_TOKEN_DEFAULT_TTL_S : Number(json.expires_in);\n const expiresAt = jwtExpiryMs(json.id_token) ?? Date.now() + ttlS * 1000;\n this.tokens = {\n idToken: json.id_token,\n refreshToken: this.refreshToken,\n userId: json.user_id,\n expiresAt,\n };\n return this.tokens;\n }\n}\n\n/** Read the `exp` claim (ms) from a JWT, or `null` if it cannot be decoded. */\nfunction jwtExpiryMs(jwt: string): number | null {\n try {\n const { exp } = decodeJwt(jwt);\n return typeof exp === 'number' ? exp * 1000 : null;\n } catch {\n return null;\n }\n}\n\n/** Extract the `__session` value from a `Set-Cookie` response header. */\nfunction extractSessionCookie(headers: Headers): string | null {\n const withGetSetCookie = headers as Headers & { getSetCookie?: () => string[] };\n const list =\n typeof withGetSetCookie.getSetCookie === 'function'\n ? withGetSetCookie.getSetCookie()\n : headers.get('set-cookie') !== null\n ? [headers.get('set-cookie') as string]\n : [];\n for (const cookie of list) {\n const match = /(?:^|;\\s*)__session=([^;]+)/.exec(cookie);\n if (match !== null && match[1] !== undefined) {\n return match[1];\n }\n }\n return null;\n}\n","/**\n * Per-host {@link Target} descriptors.\n *\n * mage.space is migrating from production (`https://www.mage.space`) to a new\n * portal (`https://beta.mage.space`). Rather than hard-coding one base URL and\n * one action-name set, each host is modelled as a `Target` so host differences\n * (renamed actions, poll strategy) live in a single table. The client holds an\n * ordered chain `[production, beta]` and advances to the next target only when\n * the active host can no longer serve a required action.\n */\n\n/** Hosts the client can talk to. */\nexport type TargetKey = 'production' | 'beta';\n\n/** How a single history-status read is performed on a given host. */\nexport type PollStrategy = 'byId' | 'paginated';\n\n/**\n * Logical operations the generation/history services invoke, decoupled from the\n * host-specific wire names. `createUserSession` is intentionally NOT a member:\n * it is resolved by its literal name on both hosts (see `lib/auth.ts`).\n */\nexport type LogicalAction =\n | 'submitGeneration'\n | 'getHistoryById'\n | 'cancelJob'\n | 'listHistory'\n | 'listCreations';\n\n/** A single host the client can target. */\nexport interface Target {\n readonly key: TargetKey;\n readonly baseUrl: string;\n /** logical name → host-specific wire name; unlisted names resolve to themselves. */\n readonly actionNames: Readonly<Partial<Record<LogicalAction, string>>>;\n readonly pollStrategy: PollStrategy;\n}\n\n/** Resolve a logical action to its host-specific wire name (identity if unlisted). */\nexport function resolveActionName(target: Target, logical: LogicalAction): string {\n return target.actionNames[logical] ?? logical;\n}\n\n/**\n * Production target.\n *\n * @remarks\n * Maps each logical action to the wire name the current production deploy\n * actually serves (all VERIFIED against `lib/seed.ts` / the existing MSW tests):\n * `submitGeneration → runArchitecture`, `cancelJob → cancelArchitectureJob`,\n * `listHistory → getHistoryPaginated`, `listCreations → getCreationsPaginatedParallel`,\n * and `getHistoryById → getHistoryById` (identity). The table is explicit rather\n * than empty so production behaviour is reproduced exactly regardless of the\n * logical-name vocabulary.\n */\nexport const PRODUCTION_TARGET: Target = {\n key: 'production',\n baseUrl: 'https://www.mage.space',\n actionNames: {\n submitGeneration: 'runArchitecture',\n getHistoryById: 'getHistoryById',\n cancelJob: 'cancelArchitectureJob',\n listHistory: 'getHistoryPaginated',\n listCreations: 'getCreationsPaginatedParallel',\n },\n pollStrategy: 'byId',\n};\n\n/**\n * Beta target. Beta facts are assumptions pending a reverse-engineering capture\n * under `docs/api/beta` — treat them as unverified until that doc lands.\n */\nexport const BETA_TARGET: Target = {\n key: 'beta',\n baseUrl: 'https://beta.mage.space',\n actionNames: {\n // ASSUMED (pending docs/api/beta) — source: brief, re-verify via rev-eng\n submitGeneration: 'runArchitecture',\n // ASSUMED (pending docs/api/beta) — source: brief, re-verify via rev-eng\n cancelJob: 'cancelArchitectureJob',\n // ASSUMED (pending docs/api/beta) — source: brief, re-verify via rev-eng\n listHistory: 'getHistoryPaginated',\n // ASSUMED (pending docs/api/beta) — getHistoryById is absent on beta; poll via pagination\n listCreations: 'getCreationsPaginated',\n },\n // ASSUMED (pending docs/api/beta) — source: brief, re-verify via rev-eng\n pollStrategy: 'paginated',\n};\n\n/** Default ordered fallback chain: production first, then beta. */\nexport const DEFAULT_TARGET_CHAIN: readonly Target[] = [PRODUCTION_TARGET, BETA_TARGET];\n\n/** Page size used by the beta paginated poll strategy. */\nexport const PAGINATED_POLL_PAGE_SIZE = 20;\n\n/** Maximum number of pages the beta paginated poll strategy scans per read. */\nexport const PAGINATED_POLL_MAX_PAGES = 10;\n","/**\n * Image generation: submit a job via `runArchitecture`, then poll\n * `getHistoryById` until the job succeeds, fails, or times out.\n */\nimport type { AuthManager } from './auth.js';\nimport { GenerationError, TimeoutError } from './errors.js';\nimport type { HttpClient } from './http.js';\nimport { unwrapResult } from './rsc.js';\nimport {\n PAGINATED_POLL_MAX_PAGES,\n PAGINATED_POLL_PAGE_SIZE,\n resolveActionName,\n type Target,\n} from './targets.js';\nimport type {\n ArchitectureConfig,\n CharacterRef,\n GenerateOptions,\n GenerateVideoOptions,\n GenerationMode,\n HistoryItem,\n HistoryPage,\n VideoArchitectureConfig,\n WaitOptions,\n} from './types.js';\n\n/** Generation actions are served from the `/explore` page. */\nconst GENERATION_PATH = '/explore';\n/** Mirrors HistoryService.HISTORY_PATH ('/creations'); kept local to avoid coupling the two services. */\nconst HISTORY_PATH = '/creations';\n/** RSC sentinel for an absent value. */\nconst UNDEFINED = '$undefined';\n/** Default concept id for mango-v3-pro (from docs — verify per model via rev-eng). */\nconst DEFAULT_CONCEPT_ID = '0cd8c7ed2e554d0f98f20c8cf8c0f7c';\n/** Default concept id for berry-2 video (from docs — verify per model via rev-eng). */\nconst DEFAULT_BERRY_CONCEPT_ID = '0b1fa74f7347406392422d24f2885684';\n\nconst DEFAULT_POLL_INTERVAL_MS = 4000;\nconst DEFAULT_TIMEOUT_MS = 5 * 60 * 1000;\n\nexport class GenerationService {\n /** Single-status-read primitive; overridable so the client can make it fallback-aware. */\n private readonly pollOnce: (historyId: string) => Promise<HistoryItem>;\n\n constructor(\n private readonly http: HttpClient,\n private readonly auth: AuthManager,\n private readonly target: Target,\n pollOnce?: (historyId: string) => Promise<HistoryItem>,\n ) {\n // Arrow captures `this` lazily so the default works regardless of field-init order.\n this.pollOnce = pollOnce ?? ((id) => this.getHistory(id));\n }\n\n /** Submit an image generation job and return its `historyId`. */\n async submit(opts: GenerateOptions): Promise<{ historyId: string }> {\n const config: ArchitectureConfig = {\n seed: opts.seed ?? null,\n prompt: opts.prompt,\n model_id: opts.model ?? 'mango-v3-pro',\n fast_mode: opts.fastMode ?? false,\n resolution: opts.resolution ?? '1K',\n architecture: opts.architecture ?? 'mango',\n aspect_ratio: opts.aspectRatio ?? 'portrait',\n image: opts.image ?? UNDEFINED,\n additional_images: opts.additionalImages ?? [],\n characters: mapCharacters(opts.characters),\n references: mapCharacters(opts.references),\n audio_references: [],\n moodboard: UNDEFINED,\n };\n return this.runArchitecture(config, opts.conceptId ?? DEFAULT_CONCEPT_ID, opts.generationMode);\n }\n\n /** Submit a video generation job (Berry-2 family) and return its `historyId`. */\n async submitVideo(opts: GenerateVideoOptions): Promise<{ historyId: string }> {\n const config: VideoArchitectureConfig = {\n seed: opts.seed ?? null,\n prompt: opts.prompt,\n model_id: opts.model ?? 'berry-2',\n fast_mode: opts.fastMode ?? false,\n resolution: opts.resolution ?? '480p',\n architecture: opts.architecture ?? 'berry',\n berry_aspect_ratio: opts.aspectRatio ?? '9:16',\n duration: opts.duration ?? '3',\n image: opts.image ?? UNDEFINED,\n additional_images: opts.additionalImages ?? [],\n characters: mapCharacters(opts.characters),\n references: mapCharacters(opts.references),\n audio_references: [],\n };\n return this.runArchitecture(\n config,\n opts.conceptId ?? DEFAULT_BERRY_CONCEPT_ID,\n opts.generationMode,\n );\n }\n\n /** Shared `runArchitecture` call for image and video configs. */\n private async runArchitecture(\n config: ArchitectureConfig | VideoArchitectureConfig,\n conceptId: string,\n generationMode: GenerationMode = 'unlimited',\n ): Promise<{ historyId: string }> {\n const [authToken, session] = await Promise.all([\n this.auth.getIdToken(),\n this.auth.getSession(),\n ]);\n\n const args = [\n {\n architectureConfig: config,\n architectureConfigToSave: '$0:0:architectureConfig',\n authToken,\n conceptId,\n activePowerPack: null,\n generationMode,\n },\n ];\n\n const { data } = await this.http.callAction<Record<string, unknown>>({\n action: resolveActionName(this.target, 'submitGeneration'),\n path: GENERATION_PATH,\n args,\n session,\n });\n\n if (data !== null && typeof data === 'object' && 'error_code' in data) {\n const code = Number(data.error_code);\n throw new GenerationError(errorMessageForCode(code), code);\n }\n const historyId = data !== null && typeof data === 'object' ? data.history_id : undefined;\n if (typeof historyId !== 'string') {\n throw new GenerationError('runArchitecture did not return a history_id');\n }\n return { historyId };\n }\n\n /** Fetch a single history record by id, dispatching on the target's poll strategy. */\n async getHistory(historyId: string): Promise<HistoryItem> {\n if (this.target.pollStrategy === 'paginated') {\n return this.getHistoryPaginated(historyId);\n }\n const session = await this.auth.getSession();\n const { data } = await this.http.callAction<HistoryItem>({\n action: resolveActionName(this.target, 'getHistoryById'),\n path: GENERATION_PATH,\n args: [historyId],\n session,\n });\n return data;\n }\n\n /**\n * Beta status read: `getHistoryById` is absent, so page `getHistoryPaginated`\n * and find the item whose `id === historyId`.\n *\n * @remarks\n * ASSUMED (pending docs/api/beta): each page window is swept in two phases —\n * `running` first, then the raw `$undefined` sentinel (terminal items) — since\n * which filter surfaces a running job on beta is not yet documented. Bounded by\n * {@link PAGINATED_POLL_MAX_PAGES} pages of {@link PAGINATED_POLL_PAGE_SIZE}.\n */\n private async getHistoryPaginated(historyId: string): Promise<HistoryItem> {\n const uid = await this.auth.getUserId();\n const limit = PAGINATED_POLL_PAGE_SIZE;\n let offset = 0;\n for (let pageIndex = 0; pageIndex < PAGINATED_POLL_MAX_PAGES; pageIndex += 1) {\n // Phase 1: running jobs; Phase 2: terminal (no status filter).\n for (const status of ['running', UNDEFINED]) {\n const page = await this.fetchHistoryPage(uid, status, limit, offset);\n const found = page.histories.find((h) => h.id === historyId);\n if (found !== undefined) {\n return found;\n }\n if (status === UNDEFINED && !page.hasMore) {\n throw new GenerationError(`history ${historyId} not found on beta`);\n }\n }\n offset += limit;\n }\n throw new GenerationError(`history ${historyId} not found on beta`);\n }\n\n /** Fetch one page of history via `listHistory` (resolved per target) on `/creations`. */\n private async fetchHistoryPage(\n uid: string,\n status: string,\n limit: number,\n offset: number,\n ): Promise<HistoryPage> {\n const session = await this.auth.getSession();\n const filters = { status, type: UNDEFINED };\n const { data } = await this.http.callAction<HistoryPage>({\n action: resolveActionName(this.target, 'listHistory'),\n path: HISTORY_PATH,\n args: [uid, limit, offset, filters],\n session,\n });\n return unwrapResult<HistoryPage>(data);\n }\n\n /** Cancel a running generation job. */\n async cancelJob(historyId: string): Promise<void> {\n const session = await this.auth.getSession();\n await this.http.callAction({\n action: resolveActionName(this.target, 'cancelJob'),\n path: GENERATION_PATH,\n args: [historyId],\n session,\n });\n }\n\n /** Poll until the job leaves the `running` state, returning the final record. */\n async waitForResult(historyId: string, opts: WaitOptions = {}): Promise<HistoryItem> {\n const intervalMs = opts.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;\n const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const deadline = Date.now() + timeoutMs;\n\n for (;;) {\n if (opts.signal?.aborted === true) {\n throw new TimeoutError('waitForResult was aborted');\n }\n const item = await this.pollOnce(historyId);\n if (item.status === 'success') {\n return item;\n }\n if (item.status === 'error') {\n throw new GenerationError(`Generation failed: ${JSON.stringify(item.error ?? null)}`);\n }\n if (Date.now() > deadline) {\n throw new TimeoutError(\n `Generation timed out after ${timeoutMs}ms (last status: ${item.status})`,\n );\n }\n await delay(intervalMs, opts.signal);\n }\n }\n}\n\nfunction delay(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const timer = setTimeout(resolve, ms);\n signal?.addEventListener(\n 'abort',\n () => {\n clearTimeout(timer);\n reject(new TimeoutError('waitForResult was aborted'));\n },\n { once: true },\n );\n });\n}\n\n/** Normalize characters for an `architectureConfig`, defaulting absent audio to the RSC sentinel. */\nfunction mapCharacters(characters: CharacterRef[] = []): CharacterRef[] {\n return characters.map((c) => ({\n id: c.id,\n name: c.name,\n username: c.username,\n image_url: c.image_url,\n audio_url: c.audio_url ?? UNDEFINED,\n }));\n}\n\nfunction errorMessageForCode(code: number): string {\n switch (code) {\n case 400:\n return 'Bad request (wrong generationMode for your subscription tier?)';\n case 401:\n return 'Authentication failed (token expired or invalid)';\n case 403:\n return 'User is banned';\n case 4031:\n return 'Prompt blocked by content moderation';\n default:\n return `Generation error (code ${code})`;\n }\n}\n","/** Generation history listing via `getHistoryPaginated`. */\nimport type { AuthManager } from './auth.js';\nimport { requireConfirm } from './errors.js';\nimport type { HttpClient } from './http.js';\nimport { unwrapResult } from './rsc.js';\nimport { resolveActionName, type Target } from './targets.js';\nimport type {\n ConfirmOptions,\n CreationPage,\n GenerationResult,\n HistoryPage,\n ListCreationsOptions,\n ListHistoryOptions,\n} from './types.js';\n\n/** History actions are served from the `/creations` page. */\nconst HISTORY_PATH = '/creations';\nconst DEFAULT_LIMIT = 10;\n/** RSC sentinel for an absent value. */\nconst UNDEFINED = '$undefined';\n\nexport class HistoryService {\n constructor(\n private readonly http: HttpClient,\n private readonly auth: AuthManager,\n private readonly target: Target,\n ) {}\n\n /** List generation history for the authenticated user. */\n async list(opts: ListHistoryOptions = {}): Promise<HistoryPage> {\n const [uid, session] = await Promise.all([this.auth.getUserId(), this.auth.getSession()]);\n const limit = opts.limit ?? DEFAULT_LIMIT;\n const offset = opts.offset ?? 0;\n const status = opts.status === 'all' ? UNDEFINED : (opts.status ?? 'success');\n const filters = { status, type: UNDEFINED };\n\n const { data } = await this.http.callAction<HistoryPage>({\n action: resolveActionName(this.target, 'listHistory'),\n path: HISTORY_PATH,\n args: [uid, limit, offset, filters],\n session,\n });\n return unwrapResult<HistoryPage>(data);\n }\n\n /** List the user's permanently saved creations. */\n async listCreations(opts: ListCreationsOptions = {}): Promise<CreationPage> {\n const [uid, session] = await Promise.all([this.auth.getUserId(), this.auth.getSession()]);\n const limit = opts.limit ?? DEFAULT_LIMIT;\n const offset = opts.offset ?? 0;\n const { data } = await this.http.callAction<CreationPage>({\n action: resolveActionName(this.target, 'listCreations'),\n path: HISTORY_PATH,\n args: [uid, limit, offset],\n session,\n });\n return unwrapResult<CreationPage>(data);\n }\n\n /**\n * Save a completed generation result as a permanent creation.\n *\n * @param result - the `result` object of a completed history item.\n * @remarks The API returns no body; call {@link listCreations} to retrieve the\n * saved creation.\n */\n async saveCreation(result: GenerationResult): Promise<void> {\n const session = await this.auth.getSession();\n await this.http.callAction({\n action: 'saveCreation',\n path: HISTORY_PATH,\n args: [result],\n session,\n });\n }\n\n /**\n * Permanently delete a history item. Irreversible — requires `{ confirm: true }`.\n */\n async deleteHistory(historyId: string, opts?: ConfirmOptions): Promise<void> {\n requireConfirm('deleteHistory', opts);\n const session = await this.auth.getSession();\n await this.http.callAction({\n action: 'deleteHistory',\n path: HISTORY_PATH,\n args: [historyId],\n session,\n });\n }\n\n /**\n * Permanently delete many history items. Irreversible — requires `{ confirm: true }`.\n *\n * @experimental Request body inferred from JS bundle; not yet verified live.\n */\n async deleteManyHistories(historyIds: string[], opts?: ConfirmOptions): Promise<void> {\n requireConfirm('deleteManyHistories', opts);\n const session = await this.auth.getSession();\n await this.http.callAction({\n action: 'deleteManyHistories',\n path: HISTORY_PATH,\n args: [historyIds],\n session,\n });\n }\n\n /**\n * Permanently delete a saved creation. Irreversible — requires `{ confirm: true }`.\n */\n async deleteCreation(creationId: string, opts?: ConfirmOptions): Promise<void> {\n requireConfirm('deleteCreation', opts);\n const session = await this.auth.getSession();\n await this.http.callAction({\n action: 'deleteCreation',\n path: HISTORY_PATH,\n args: [creationId],\n session,\n });\n }\n\n /**\n * Permanently delete many creations. Irreversible — requires `{ confirm: true }`.\n *\n * @experimental Request body inferred from JS bundle; not yet verified live.\n */\n async deleteManyCreations(creationIds: string[], opts?: ConfirmOptions): Promise<void> {\n requireConfirm('deleteManyCreations', opts);\n const session = await this.auth.getSession();\n await this.http.callAction({\n action: 'deleteManyCreations',\n path: HISTORY_PATH,\n args: [creationIds],\n session,\n });\n }\n}\n","/**\n * Reference asset management.\n *\n * References are reusable image/audio assets (generic references, objects,\n * outfits, poses) applied across generations — distinct from characters, which\n * are trained identities. Covers upload, create, update, and listing (own +\n * public feed) per `docs/api/references.md`.\n */\nimport type { AuthManager } from './auth.js';\nimport { MageSpaceError, requireConfirm } from './errors.js';\nimport type { HttpClient } from './http.js';\nimport type {\n ConfirmOptions,\n CreateReferenceInput,\n ListReferencesOptions,\n Modality,\n Reference,\n ReferencePage,\n UpdateReferenceInput,\n} from './types.js';\n\n/** Server-enforced username constraints (shared with characters, module 64428). */\nconst USERNAME_MAX = 15;\nconst USERNAME_RE = /^[a-z][a-z0-9_-]*$/;\n\n/** Generate a username from a display name (same logic as characters). */\nfunction generateUsername(name: string): string {\n const suffix = Math.random().toString(36).substring(2, 6);\n const base = name\n .toLowerCase()\n .trim()\n .replace(/[^a-z0-9\\s]/g, '')\n .replace(/\\s+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '');\n const maxBase = USERNAME_MAX - suffix.length - 1;\n const trimmedBase = base.slice(0, maxBase).replace(/[-_]+$/, '');\n return `${trimmedBase}-${suffix}`;\n}\n\nfunction validateUsername(username: string): void {\n if (username.length > USERNAME_MAX) {\n throw new MageSpaceError(\n `Username \"${username}\" is too long (${username.length} chars, max ${USERNAME_MAX})`,\n );\n }\n if (!USERNAME_RE.test(username)) {\n throw new MageSpaceError(\n `Username \"${username}\" is invalid: must start with a lowercase letter and contain only a-z, 0-9, _ or -`,\n );\n }\n}\n\n/** Reference actions are served from the `/explore` page. */\nconst REFERENCES_PATH = '/explore';\nconst DEFAULT_PAGE_LIMIT = 20;\n\nexport class ReferencesService {\n constructor(\n private readonly http: HttpClient,\n private readonly auth: AuthManager,\n ) {}\n\n /**\n * Upload a reference image (base64 data URL) and return its CDN URL.\n *\n * @param dataUrl - `data:image/jpeg;base64,...` (JPEG preferred; PNG/WebP ok).\n */\n async uploadImage(dataUrl: string): Promise<string> {\n const [uid, session] = await Promise.all([this.auth.getUserId(), this.auth.getSession()]);\n const { data } = await this.http.callAction<string>({\n action: 'uploadReferenceImage',\n path: REFERENCES_PATH,\n args: [dataUrl, uid],\n session,\n });\n return data;\n }\n\n /** Create a reusable reference from an uploaded image/audio URL. */\n async create(input: CreateReferenceInput): Promise<Reference> {\n const username = input.username ?? generateUsername(input.name);\n validateUsername(username);\n const session = await this.auth.getSession();\n const body = {\n name: input.name,\n username,\n image_url: input.image_url,\n audio_url: input.audio_url ?? null,\n modality: input.modality ?? 'image',\n variant: input.variant ?? 'reference',\n description: input.description ?? null,\n tags: input.tags ?? [],\n visibility: input.visibility ?? 'private',\n moderation: input.moderation ?? [],\n };\n const { data } = await this.http.callAction<Reference>({\n action: 'createReference',\n path: REFERENCES_PATH,\n args: [body],\n session,\n });\n return data;\n }\n\n /** Update a reference's mutable fields (name, description, tags, visibility). */\n async update(id: string, patch: UpdateReferenceInput): Promise<Reference> {\n const session = await this.auth.getSession();\n const { data } = await this.http.callAction<Reference>({\n action: 'updateReference',\n path: REFERENCES_PATH,\n args: [id, patch],\n session,\n });\n return data;\n }\n\n /**\n * Permanently delete a reference (soft-delete). Irreversible — requires\n * `{ confirm: true }`.\n */\n async delete(id: string, opts?: ConfirmOptions): Promise<void> {\n requireConfirm('deleteReference', opts);\n const session = await this.auth.getSession();\n await this.http.callAction({\n action: 'deleteReference',\n path: REFERENCES_PATH,\n args: [id],\n session,\n });\n }\n\n /** List the caller's own references for a given modality (default `image`). */\n async list(modality: Modality = 'image'): Promise<Reference[]> {\n const [uid, session] = await Promise.all([this.auth.getUserId(), this.auth.getSession()]);\n const { data } = await this.http.callAction<Reference[]>({\n action: 'getReferences',\n path: REFERENCES_PATH,\n args: [uid, modality],\n session,\n });\n return data ?? [];\n }\n\n /**\n * Browse references with pagination.\n *\n * @remarks\n * Omit `uid` to browse the public/featured feed; pass it to page through a\n * single user's references.\n */\n async listPaginated(opts: ListReferencesOptions = {}): Promise<ReferencePage> {\n const session = await this.auth.getSession();\n const limit = opts.limit ?? DEFAULT_PAGE_LIMIT;\n const offset = opts.offset ?? 0;\n const filters: Record<string, unknown> = {\n visibility: opts.visibility ?? 'public',\n orderBy: opts.orderBy ?? 'top',\n featuredOnly: opts.featuredOnly ?? false,\n modality: opts.modality ?? 'image',\n };\n if (opts.uid !== undefined) {\n filters.uid = opts.uid;\n }\n const { data } = await this.http.callAction<ReferencePage>({\n action: 'getReferencesPaginated',\n path: REFERENCES_PATH,\n args: [limit, offset, filters],\n session,\n });\n return data;\n }\n}\n","import type { ActionSnapshot } from './types.js';\n\n/**\n * Bundled action-hash snapshot from the mage.space Vercel deploy discovered on\n * 2026-08-24 (`docs/api/actions.md`).\n *\n * @remarks\n * Used as a warm seed so the very first call does not pay the discovery cost.\n * Hashes change on every deploy; when one goes stale the client re-discovers\n * automatically (404 → invalidate → refresh).\n */\nexport const SEED_SNAPSHOT: ActionSnapshot = {\n deploymentId: 'dpl_2w2igPYTRJKeDaX6iAUMbGwDEWZC',\n discoveredAt: Date.parse('2026-08-24T13:15:00.000Z'),\n hashes: {\n createUserSession: '60b45776be93d57b1f43deaf8d6f9a837c6b9c169b',\n deleteUserSession: '0044441bb36afa0ba15ca13c4cf3a831ac81108c7a',\n getUserHydrationData: '40b253dcab658b78ba3673c5244f96578f22d65606',\n runArchitecture: '40c4d7d5e695e1a2e2992174b75562ef5df377b206',\n getHistoryById: '4042bfb22d370cd4e3f0f41812e826a63c179cb8a8',\n cancelArchitectureJob: '401dc98670483cb67cc9b1b6a623c4fa7cb71348a2',\n cancelAllRunningArchitectureJobs: '0004b976add66997b6518bd2d25f04444b8df4e3b2',\n getMentionSuggestionsParallel: '7fe1156be29ed3824514220877818246e7649234fa',\n createCharacter: '401ceece486398904b9ba48daa7fc0ac951fb72168',\n updateCharacter: '6057ae8c4ae8868e3a4b045845814b0689ac61a1e0',\n deleteCharacter: '4071b6010bffdf242150e0322cd0966463268414d8',\n getCharacter: '40ce38eb438c78fa51ee09be911ba0c3b02d7cbcad',\n getCharacters: '40c74f795b040ec3d0841360b532eb938932fc4bc3',\n getCharactersPaginated: '709855baaecec89ad7b73ca44621fe93dfd93fcdee',\n publishCharacter: '40b489876c75c1cd836a108742da4753fb2f671565',\n unpublishCharacter: '40c785b54f5c25bd50cfaebc6817f9d0b9f5e6e145',\n uploadCharacterImage: '60ef3377c68f0cf34c60646d9356e622a9230a68e5',\n uploadReferenceImage: '60c497b22c1b65f8a4e78055c5d9e0c2bc49e2c7bd',\n createReference: '403a057e1bd8967b3bb728df1722019d14ca7c4e14',\n updateReference: '60819ffb5ec61122bc4dd52b2232fd486a155d23c6',\n deleteReference: '409098eedd49e49ac5f0275d8af9c70a0988e9859c',\n getReferences: '605e5d2876598666c4681f8f08f4ecbe7488d1762d',\n getReferencesPaginated: '702382e902dbe43b4343265b6a251c30b878eae08a',\n getCreationsPaginatedParallel: '7f5eb618ca5c4c243c51a04c5dea108aefe8aa37d2',\n getHistoryPaginated: '7817d35897de571dfa2c6c525ee7bff73ba6d590d6',\n clearUserHistory: '4038b8e21b2e6eac7c78c076ef04f1db91718cfd69',\n deleteHistory: '40f4de31887560f79274b13f8abd3a282f6c3321f7',\n deleteManyHistories: '4006a9773613e8ea05421e6f2c91fe6417fe33d892',\n deleteCreation: '40ceaf58a77a287e3146d5792b147dba9df5ec0257',\n deleteManyCreations: '4092a1e1531442421916268184300f37a4478900ed',\n saveCreation: '60860eb37a9862d41d7b92af9bbe572652e076bc43',\n saveManyCreations: '400f59bf4b0ce788050b25259aecc9bf7839f8ba11',\n generateCharacterVoice: '60b54e75a5c3de2b0e4df7ebec5cf6ef1aaeb2ed35',\n followCharacter: '403b46c309f4239df7579c00654881afd855fc1757',\n unfollowCharacter: '400dd84b2d0f2f582df6c72092ea5249678b68d4d5',\n getFilteredCharacterIds: '403b8603d61033bbe1c30c9d1c12133b9ed4e16348',\n getFilteredReferenceIds: '40a87aa0793c102e72b7858e1024c0c2f01c96a720',\n getConceptsParallel: '7f5cf8a4696938e3a148c3c293922fbcd0f8cdbd08',\n getConcept: '408caa15371b2240267a5521c4130fefcff4ba515d',\n getModel: '40f88ee2580ed9a6ae6ff3bf6ec5840b22946dbba3',\n getModels: '70fbe28eadea3cb6d563b1f5bf50c2ad179535e6e8',\n getArticlesParallel: '7f743849b6ddf8eeb21eefceb2b93c93b6d19f203f',\n searchUsersParallel: '7ff9c981309e38b9efb215d0943b34380401a93362',\n getEmbeddingParallel: '7fa14c0b84ee996caad1a598bc2b021bd9545a3383',\n getLatestPublishedArticleCached: '7f0e2eb3e1407b27b2cc338235134b3fbf25c88ddc',\n hasPurchasedGemsParallel: '7f223962cad80e4dbdd3df7dc2039f65a42c461d87',\n syncStripeSubscriptionParallel: '7f19bb611b725a3cb8d99dc5d72ab11e0595087f6e',\n getSubscriptionPlayUsage: '40c9d7d3d029eee45885df18797dbca20315ff4fca',\n saveContentSettings: '4095ebf4d1b43894777ef2e3e06b9a556275fafcf0',\n deleteUser: '40692c054de95018353e0c8512082f6f9103cac6d7',\n getMyUserMembership: '007ce34998f2bf4f19be3cf46e3cfcb387110ae5d5',\n getActiveUserBan: '60e4352df1676fbe169421c5709479f1534cccb371',\n getCreditBalance: '009364b01be29ea5b25711fff2c6284af88caa4e4c',\n getCreditBalanceBreakdown: '00ddc14328cf19e8fbec823474a7169214cfd30603',\n getActivePowerPack: '00a6404083c8958fcd47607a088c1d1a7a5dfd4514',\n getUnusedPowerPacks: '00b5d80d96598fc2db4641fff117cfa47b37f2482f',\n getPowerPackStatsById: '4027b533e8532d2f35cbbb7518160d7569b738cb20',\n getLastGemPurchaseType: '008f0fb3448464f9f0e5ac2b6b15fc5fb59d8ccce4',\n getCheckoutUrlWithStripeDirect: '7c0f0773c703de16b1abe5f869c2164108473c5820',\n getPortalUrlWithStripeDirect: '60655cb929f6eb281aef8c25311806cfaed5aeb8af',\n removeInactiveSubscriptions: '00b5b012ef33665bb3cdf3f8e931483a0d8dc96461',\n hasCreatedImageReference: '002876b36888ccf790e8e5b9413ae951d07594a4c3',\n createLink: '40ffeee6dd712d83ce286aa22d07446822adb5ec02',\n tempToPermanentFile: '40f30eb9909274b48fa7654e7648cdf188bf3e015d',\n uploadTempCreationImage: '60f0c8b2c98566eb131e69ec1e8ee95c78ad4c332f',\n uploadUserImage: '604d67807ffec2bcdaf936e03c27c7fcc8e49880f8',\n getUserAudioUploadUrl: '7019e155efbd5aa4eb2200a48d6f7265cf6aa686e9',\n getUserVideoUploadUrl: '70cab2e17fe2c04a964489850642235ada2cb0adf3',\n processVideoFromUrl: '70901405c8bff0dcb9ea40053f1176caeb1b99ae4c',\n processAudio: '60bd5fa2fd7c30e53ef2a22342408ed1aab0a766a7',\n segmentImage: '40d827c38726f2d2bbc559f94eafe0f1fc84b50e70',\n moderateMedia: '403006c99a6b3cd6e684c163e0df35f44e403f7ca7',\n checkSharedUsernameAvailable: '6000cca07091fb38d8a77fad195b95b2ea73634895',\n getCreationTagCountsParallel: '7f0f20d7a26711c076aefeb73e65273ac1572381d8',\n updateCreations: '4055ce23f7e1fac54bfceb33b816f9574b82d2127d',\n getCreationsPaginated: '780d8f5e01f24e1342e5e4a475321123eb156dcf2a',\n resolveMoodboardRuntimeSelection: '40080c3021ac4c02f675c25a7443b03ee96e57837a',\n saveProfileCollections: '4071958ca110ab37fe59be3b019bfc39b1fa0c9143',\n banUser: '70c46c18b6223613cee3a4f17ce076672f29a6bba5',\n undoTemporaryBanUser: '40199a810acd4149e53fc182ba1ff9e8a7dde19283',\n temporaryBanUser: '788b8a43fb42b87cd942e3d0229307bea6497ef8e9',\n getCharacterFollowStatus: '40d220eb13610f029b46bbcfc7c9117478b3b738f2',\n reportCharacter: '400525e8101daa2496bad7a7c7e91c5cca00d574c2',\n toggleFeatureCharacter: '40a640496a2e6bf7cb124405c74f8a928aeccbf964',\n getSiteAlertParallel: '7f382e755e1d8d7670272b36656280dd661aa9abce',\n getChatsParallel: '7f741bb8b517b0ba95f6b941ab1ce0efcb870341f6',\n getChatMessages: '40f8886c57d93aae7265d1805af5765589e2be7d15',\n markChatRead: '408c569fdaa0d2ab12e0b8019cf661a99c9d182f68',\n getPostMediaFeedParallel: '7f9ce48dd331eb4103e9d2d18b23b6008e3bf5c502',\n createAutoCreationCampaign: '404c84350ce7aba35a332ab3129334ed19cfb107fd',\n },\n};\n","/**\n * Internal HTTP client for Next.js Server Action calls.\n *\n * Every call is a `POST` to a page path with a `next-action` header carrying the\n * action hash, a JSON-array body, and an RSC response that is parsed into the\n * action's return value. A 404 is treated as a stale hash: the registry is\n * invalidated and the call is retried once against freshly discovered hashes.\n */\nimport type { ActionRegistry } from './actions.js';\nimport { ActionUnavailableError, MageSpaceError } from './errors.js';\nimport { parseServerActionResponse } from './rsc.js';\nimport type { FetchLike } from './types.js';\n\nconst DEFAULT_USER_AGENT =\n 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ' +\n '(KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36';\n\n/**\n * HTTP statuses that mean \"this action is unavailable on this host\". A stale\n * (post-deploy) action hash surfaces as a 404 on the production host and as a\n * 409 (\"Server Action unavailable\") on the beta host — both mean the same\n * thing: invalidate the registry, re-discover, and (if still unavailable) fall\n * back to the next host.\n */\nconst UNAVAILABLE_STATUSES = new Set([404, 409]);\n\n/**\n * Known RSC error digests mapped to human-readable messages.\n * Discovered via reverse engineering; the server does not expose error details.\n */\nconst KNOWN_DIGESTS: Record<string, string> = {\n '709776019': 'Username already taken (duplicate character/reference username)',\n '1853426377':\n 'Invalid username (must be 1–15 lowercase chars, start with a letter, only a-z 0-9 _ -)',\n};\n\nexport interface CallActionParams {\n /** Server Action function name (resolved to a hash via the registry). */\n action: string;\n /** Page path to POST to (e.g. `/explore`, `/creations`). */\n path: string;\n /** Request body — always a JSON array of arguments. */\n args: unknown[];\n /** `__session` cookie value for authenticated actions. */\n session?: string;\n}\n\nexport interface CallActionResult<T> {\n data: T;\n headers: Headers;\n deploymentId: string;\n}\n\nexport class HttpClient {\n constructor(\n private readonly registry: ActionRegistry,\n private readonly fetchImpl: FetchLike,\n private readonly baseUrl: string,\n private readonly targetKey: string,\n private readonly userAgent: string = DEFAULT_USER_AGENT,\n ) {}\n\n /** A response that means the action is unavailable (stale hash or gone). */\n private isUnavailable(res: Response): boolean {\n const contentType = res.headers.get('content-type') ?? '';\n const isHtmlFallback = res.ok && contentType.includes('text/html');\n return UNAVAILABLE_STATUSES.has(res.status) || isHtmlFallback;\n }\n\n async callAction<T = unknown>(\n params: CallActionParams,\n retried = false,\n ): Promise<CallActionResult<T>> {\n const { hash, deploymentId } = await this.registry.getHash(params.action);\n\n const headers: Record<string, string> = {\n accept: 'text/x-component',\n 'content-type': 'text/plain;charset=UTF-8',\n 'next-action': hash,\n 'x-deployment-id': deploymentId,\n origin: this.baseUrl,\n referer: `${this.baseUrl}${params.path}`,\n 'user-agent': this.userAgent,\n };\n if (params.session !== undefined) {\n headers.cookie = `__session=${params.session}`;\n }\n\n const res = await this.fetchImpl(`${this.baseUrl}${params.path}`, {\n method: 'POST',\n headers,\n body: JSON.stringify(params.args),\n });\n\n // A stale (post-deploy) hash surfaces as a 404 OR as a 200 with HTML\n // (Next.js returns the page shell instead of the RSC action response).\n if (this.isUnavailable(res) && !retried) {\n // Consume the body to prevent socket leaks.\n await safeText(res);\n await this.registry.invalidate();\n return this.callAction<T>(params, true);\n }\n // A retried response that is still unavailable means the action is gone from\n // this host — a definitive, host-level signal the client treats as a\n // fallback trigger (distinct from a transient stale hash).\n if (this.isUnavailable(res)) {\n await safeText(res);\n throw new ActionUnavailableError(params.action, this.targetKey);\n }\n if (!res.ok) {\n const body = await safeText(res);\n // RSC error rows look like: `1:E{\"digest\":\"...\"}` — extract the digest when possible.\n const rscErrorMatch = body.match(/E\\{\"digest\":\"([^\"]+)\"\\}/);\n const digest = rscErrorMatch?.[1];\n const knownDigest = digest !== undefined ? KNOWN_DIGESTS[digest] : undefined;\n const hint = knownDigest ? ` — ${knownDigest}` : digest ? ` (server digest: ${digest})` : '';\n const raw = body.length > 0 ? ` — ${body.slice(0, 200)}` : '';\n throw new MageSpaceError(`Action \"${params.action}\" failed: HTTP ${res.status}${hint}${raw}`);\n }\n\n const text = await res.text();\n const data = parseServerActionResponse<T>(text);\n return {\n data,\n headers: res.headers,\n deploymentId: res.headers.get('x-deployment-id') ?? deploymentId,\n };\n }\n}\n\nasync function safeText(res: Response): Promise<string> {\n try {\n return await res.text();\n } catch {\n return '';\n }\n}\n","/**\n * A {@link TargetContext} bundles one host's {@link ActionRegistry} and\n * {@link HttpClient} so the client can hold one pair per target and switch by\n * selecting the other pair (rather than mutating a shared `baseUrl`).\n */\nimport { ActionRegistry, InMemoryActionCache } from './actions.js';\nimport { HttpClient } from './http.js';\nimport type { Target } from './targets.js';\nimport type { ActionCache, ActionSnapshot, FetchLike } from './types.js';\n\n/** The per-host registry + HTTP client bound to a single {@link Target}. */\nexport interface TargetContext {\n readonly target: Target;\n readonly registry: ActionRegistry;\n readonly http: HttpClient;\n}\n\n/** Dependencies shared across every target context the client builds. */\nexport interface TargetContextDeps {\n fetch: FetchLike;\n userAgent?: string;\n /** Caller-supplied cache — used for the production target only. */\n cache?: ActionCache;\n /** Production seed snapshot — passed to the production target only. */\n seed?: ActionSnapshot;\n}\n\n/**\n * Build the registry + HTTP client for a single target.\n *\n * @remarks\n * The caller's `cache` and the production `seed` are production-only concerns:\n * the bundled seed holds production hashes and the single-slot cache cannot be\n * namespaced per host. Non-production targets always discover fresh with their\n * own {@link InMemoryActionCache} and no seed.\n */\nexport function createTargetContext(target: Target, deps: TargetContextDeps): TargetContext {\n const isProduction = target.key === 'production';\n const registry = new ActionRegistry({\n fetch: deps.fetch,\n baseUrl: target.baseUrl,\n cache: isProduction ? deps.cache : new InMemoryActionCache(),\n seed: isProduction ? deps.seed : undefined,\n });\n const http = new HttpClient(registry, deps.fetch, target.baseUrl, target.key, deps.userAgent);\n return { target, registry, http };\n}\n","/**\n * {@link MageSpaceClient} — the public facade that wires together action\n * discovery, authentication, generation, and history.\n *\n * The client models each mage.space host as a {@link Target} and holds an\n * ordered chain (production first, then beta). When the active host can no\n * longer serve a required action, the client advances to the next target and\n * retries once. The switch is sticky for the lifetime of the instance.\n */\nimport { AuthManager } from './auth.js';\nimport { CharactersService } from './characters.js';\nimport { ActionUnavailableError, DiscoveryError } from './errors.js';\nimport { GenerationService } from './generation.js';\nimport { HistoryService } from './history.js';\nimport { ReferencesService } from './references.js';\nimport { SEED_SNAPSHOT } from './seed.js';\nimport { createTargetContext, type TargetContext } from './target-context.js';\nimport { DEFAULT_TARGET_CHAIN, type Target, type TargetKey } from './targets.js';\nimport type {\n ActionSnapshot,\n ConfirmOptions,\n CreationPage,\n FetchLike,\n GenerateOptions,\n GenerateVideoOptions,\n GenerationResult,\n HistoryItem,\n HistoryPage,\n ListCreationsOptions,\n ListHistoryOptions,\n MageSpaceClientOptions,\n WaitOptions,\n} from './types.js';\n\n/** Generation + history services bound to one active {@link Target}. */\ninterface ServiceBundle {\n target: Target;\n generationService: GenerationService;\n historyService: HistoryService;\n}\n\nexport class MageSpaceClient {\n private readonly auth: AuthManager;\n private readonly chain: readonly Target[];\n private readonly auto: boolean;\n private readonly contextDeps: {\n fetch: FetchLike;\n userAgent?: string;\n cache?: MageSpaceClientOptions['cache'];\n seed?: ActionSnapshot;\n };\n private readonly contexts: Map<TargetKey, TargetContext> = new Map();\n private activeIndex: number;\n private activeContext: TargetContext;\n private activeBundle: ServiceBundle;\n\n /**\n * Character management (search, CRUD, pagination, uploads).\n *\n * @remarks\n * Bound to the initial host (production by default) and does not follow an\n * automatic beta fallback. Construct a client with `fallback: { start: 'beta' }`\n * to use these against beta.\n */\n readonly characters: CharactersService;\n\n /**\n * Reference asset management (upload, create, update, list, feed).\n *\n * @remarks\n * Bound to the initial host (production by default) and does not follow an\n * automatic beta fallback. Construct a client with `fallback: { start: 'beta' }`\n * to use these against beta.\n */\n readonly references: ReferencesService;\n\n constructor(options: MageSpaceClientOptions) {\n if (!options.refreshToken) {\n throw new Error('MageSpaceClient requires a refreshToken');\n }\n\n const fetchImpl: FetchLike = options.fetch ?? ((input, init) => fetch(input, init));\n const fallback = options.fallback;\n const baseUrlPinned = typeof options.baseUrl === 'string' && options.baseUrl.length > 0;\n\n // `baseUrl` pins a single host and is incompatible with fallback tuning.\n if (\n baseUrlPinned &&\n fallback !== undefined &&\n (fallback.chain !== undefined || fallback.start !== undefined || fallback.auto !== undefined)\n ) {\n throw new Error('baseUrl pins a single host and cannot be combined with fallback options');\n }\n\n if (baseUrlPinned) {\n // Collapse to a single synthetic target reproducing today's single-host behaviour.\n this.chain = [\n {\n key: 'production',\n baseUrl: options.baseUrl as string,\n actionNames: {},\n pollStrategy: 'byId',\n },\n ];\n this.auto = false;\n } else {\n const chain = fallback?.chain ?? DEFAULT_TARGET_CHAIN;\n if (chain.length === 0) {\n throw new Error('fallback.chain must be a non-empty array');\n }\n this.chain = chain;\n this.auto = fallback?.auto ?? true;\n }\n\n const startKey = baseUrlPinned ? 'production' : (fallback?.start ?? 'production');\n const startIndex = this.chain.findIndex((t) => t.key === startKey);\n if (startIndex === -1) {\n throw new Error(`fallback.start '${startKey}' is not in the target chain`);\n }\n\n this.contextDeps = {\n fetch: fetchImpl,\n userAgent: options.userAgent,\n cache: options.cache,\n seed: options.seed ?? SEED_SNAPSHOT,\n };\n\n this.activeIndex = startIndex;\n this.activeContext = this.getContext(startIndex);\n\n this.auth = new AuthManager({\n refreshToken: options.refreshToken,\n getHttp: () => this.activeContext.http,\n fetch: fetchImpl,\n firebaseApiKey: options.firebaseApiKey,\n });\n\n this.activeBundle = this.buildBundle(this.activeContext);\n\n // Sub-services bind to the INITIAL active context and are never rebuilt.\n this.characters = new CharactersService(this.activeContext.http, this.auth);\n this.references = new ReferencesService(this.activeContext.http, this.auth);\n }\n\n /** Lazily build (and memoise) the {@link TargetContext} for a chain index. */\n private getContext(index: number): TargetContext {\n const target = this.chain[index] as Target;\n const existing = this.contexts.get(target.key);\n if (existing !== undefined) {\n return existing;\n }\n const context = createTargetContext(target, this.contextDeps);\n this.contexts.set(target.key, context);\n return context;\n }\n\n /** Build the generation/history service bundle for a context. */\n private buildBundle(context: TargetContext): ServiceBundle {\n const pollOnce = (id: string): Promise<HistoryItem> =>\n this.withFallback((bundle) => bundle.generationService.getHistory(id));\n return {\n target: context.target,\n generationService: new GenerationService(context.http, this.auth, context.target, pollOnce),\n historyService: new HistoryService(context.http, this.auth, context.target),\n };\n }\n\n /** Advance to the next target (sticky). Returns `null` if none or `auto` is off. */\n private advanceTarget(): ServiceBundle | null {\n if (this.auto === false || this.activeIndex >= this.chain.length - 1) {\n return null;\n }\n this.activeIndex += 1;\n this.activeContext = this.getContext(this.activeIndex);\n this.activeBundle = this.buildBundle(this.activeContext);\n return this.activeBundle;\n }\n\n /** Whether an error is a definitive action-unavailable signal (a fallback trigger). */\n private shouldFallback(err: unknown): boolean {\n return (\n err instanceof ActionUnavailableError ||\n (err instanceof DiscoveryError && err.notFound === true)\n );\n }\n\n /** Run `op` against the active bundle, switching to the next target once on a trigger. */\n private async withFallback<T>(op: (bundle: ServiceBundle) => Promise<T>): Promise<T> {\n try {\n return await op(this.activeBundle);\n } catch (err) {\n if (!this.shouldFallback(err)) {\n throw err;\n }\n const next = this.advanceTarget();\n if (next === null) {\n throw err;\n }\n this.auth.resetSession();\n return op(this.activeBundle);\n }\n }\n\n /** Submit a generation job; returns its `historyId`. */\n generate(options: GenerateOptions): Promise<{ historyId: string }> {\n return this.withFallback((b) => b.generationService.submit(options));\n }\n\n /** Submit a video generation job (Berry-2 family); returns its `historyId`. */\n generateVideo(options: GenerateVideoOptions): Promise<{ historyId: string }> {\n return this.withFallback((b) => b.generationService.submitVideo(options));\n }\n\n /** Fetch the current state of a generation by id. */\n getResult(historyId: string): Promise<HistoryItem> {\n return this.withFallback((b) => b.generationService.getHistory(historyId));\n }\n\n /** Poll until a generation finishes (or fails / times out). */\n waitForResult(historyId: string, options?: WaitOptions): Promise<HistoryItem> {\n return this.withFallback((b) => b.generationService.waitForResult(historyId, options));\n }\n\n /** Cancel a running generation job. */\n cancelJob(historyId: string): Promise<void> {\n return this.withFallback((b) => b.generationService.cancelJob(historyId));\n }\n\n /** List past generations for the authenticated user. */\n listHistory(options?: ListHistoryOptions): Promise<HistoryPage> {\n return this.withFallback((b) => b.historyService.list(options));\n }\n\n /** List the user's permanently saved creations. */\n listCreations(options?: ListCreationsOptions): Promise<CreationPage> {\n return this.withFallback((b) => b.historyService.listCreations(options));\n }\n\n /** Save a completed generation result as a permanent creation. */\n saveCreation(result: GenerationResult): Promise<void> {\n return this.withFallback((b) => b.historyService.saveCreation(result));\n }\n\n /** Permanently delete a history item. Irreversible — requires `{ confirm: true }`. */\n deleteHistory(historyId: string, options?: ConfirmOptions): Promise<void> {\n return this.withFallback((b) => b.historyService.deleteHistory(historyId, options));\n }\n\n /** Permanently delete many history items. Irreversible — requires `{ confirm: true }`. */\n deleteManyHistories(historyIds: string[], options?: ConfirmOptions): Promise<void> {\n return this.withFallback((b) => b.historyService.deleteManyHistories(historyIds, options));\n }\n\n /** Permanently delete a saved creation. Irreversible — requires `{ confirm: true }`. */\n deleteCreation(creationId: string, options?: ConfirmOptions): Promise<void> {\n return this.withFallback((b) => b.historyService.deleteCreation(creationId, options));\n }\n\n /** Permanently delete many creations. Irreversible — requires `{ confirm: true }`. */\n deleteManyCreations(creationIds: string[], options?: ConfirmOptions): Promise<void> {\n return this.withFallback((b) => b.historyService.deleteManyCreations(creationIds, options));\n }\n\n /** Force re-discovery of the Server Action hashes on the active host. */\n refreshActions(): Promise<ActionSnapshot> {\n return this.activeContext.registry.refresh();\n }\n\n /** Return the authenticated user's Firebase uid. */\n getUid(): Promise<string> {\n return this.auth.getUserId();\n }\n\n /** Return the key of the currently active target (`'production'` or `'beta'`). */\n getActiveTarget(): TargetKey {\n return (this.chain[this.activeIndex] as Target).key;\n }\n}\n","/** Public entry point for `@zweer/mage-space-client`. */\nexport const VERSION = '0.0.0';\n\nexport { ActionRegistry, discoverActions, InMemoryActionCache } from './actions.js';\nexport { CharactersService } from './characters.js';\nexport { MageSpaceClient } from './client.js';\nexport {\n ActionUnavailableError,\n AuthError,\n DiscoveryError,\n GenerationError,\n MageSpaceError,\n RscParseError,\n StaleActionError,\n TimeoutError,\n} from './errors.js';\nexport { ReferencesService } from './references.js';\nexport {\n parseFlightRows,\n parseServerActionResponse,\n resolveFlightValue,\n unwrapResult,\n} from './rsc.js';\nexport { SEED_SNAPSHOT } from './seed.js';\nexport type { LogicalAction, PollStrategy, Target, TargetKey } from './targets.js';\nexport {\n BETA_TARGET,\n DEFAULT_TARGET_CHAIN,\n PRODUCTION_TARGET,\n resolveActionName,\n} from './targets.js';\nexport type * from './types.js';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["USERNAME_MAX","USERNAME_RE","generateUsername","validateUsername","HISTORY_PATH","UNDEFINED"],"sources":["../lib/errors.ts","../lib/actions.ts","../lib/rsc.ts","../lib/characters.ts","../lib/auth.ts","../lib/targets.ts","../lib/generation.ts","../lib/history.ts","../lib/references.ts","../lib/seed.ts","../lib/http.ts","../lib/target-context.ts","../lib/client.ts","../lib/index.ts"],"sourcesContent":["/** Typed error hierarchy for the mage.space client. */\n\n/** Base class for every error thrown by this library. */\nexport class MageSpaceError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'MageSpaceError';\n }\n}\n\n/** Authentication failures (token refresh, session creation). */\nexport class AuthError extends MageSpaceError {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'AuthError';\n }\n}\n\n/** Action-hash discovery failures (page/chunk fetch, empty registry). */\nexport class DiscoveryError extends MageSpaceError {\n /**\n * `true` when the action name was absent even after a forced re-discovery\n * (a fallback trigger); `false` for scrape failures (no chunks/no hashes).\n */\n public readonly notFound: boolean;\n\n constructor(message: string, options?: { cause?: unknown; notFound?: boolean }) {\n super(message, options);\n this.name = 'DiscoveryError';\n this.notFound = options?.notFound ?? false;\n }\n}\n\n/**\n * A required action is unavailable on the active host (a persistent 404 / HTML\n * fallback that survived one in-place re-discovery). A fallback trigger.\n */\nexport class ActionUnavailableError extends MageSpaceError {\n constructor(\n public readonly action: string,\n public readonly targetKey: string,\n options?: { cause?: unknown },\n ) {\n super(`Action \"${action}\" is unavailable on target \"${targetKey}\"`, options);\n this.name = 'ActionUnavailableError';\n }\n}\n\n/**\n * A Server Action returned 404, indicating a stale (post-deploy) hash.\n *\n * @deprecated Legacy export kept for backward compatibility; no longer thrown.\n * The current signal for a definitively unavailable action is\n * {@link ActionUnavailableError}.\n */\nexport class StaleActionError extends MageSpaceError {\n constructor(\n public readonly action: string,\n options?: { cause?: unknown },\n ) {\n super(`Action \"${action}\" returned 404 (stale hash)`, options);\n this.name = 'StaleActionError';\n }\n}\n\n/** Failures while submitting or polling a generation job. */\nexport class GenerationError extends MageSpaceError {\n constructor(\n message: string,\n public readonly code?: number,\n options?: { cause?: unknown },\n ) {\n super(message, options);\n this.name = 'GenerationError';\n }\n}\n\n/** Failure to parse a React Server Component (RSC) wire response. */\nexport class RscParseError extends MageSpaceError {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'RscParseError';\n }\n}\n\n/** A wait/poll operation exceeded its deadline or was aborted. */\nexport class TimeoutError extends MageSpaceError {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'TimeoutError';\n }\n}\n\n/**\n * Guard for irreversible operations: throws unless `{ confirm: true }` is passed.\n *\n * @throws {MageSpaceError} when confirmation is missing.\n */\nexport function requireConfirm(action: string, opts?: { confirm?: boolean }): void {\n if (opts?.confirm !== true) {\n throw new MageSpaceError(\n `${action} is irreversible and requires explicit confirmation: pass { confirm: true }`,\n );\n }\n}\n","/**\n * Action-hash discovery and caching.\n *\n * mage.space's Server Action hashes change on every Vercel deploy, so the client\n * discovers them from the page's JS bundles and caches the result. The registry\n * serves hashes from a warm seed / cache and only re-discovers when a hash goes\n * stale (a request 404s) or when explicitly refreshed.\n */\nimport { DiscoveryError } from './errors.js';\nimport type { ActionCache, ActionHashes, ActionName, ActionSnapshot, FetchLike } from './types.js';\n\n/** `createServerReference)(\"<hash>\", callServer, void 0, findSourceMapURL, \"<fn>\")` */\nconst CREATE_SERVER_REF_RE = /createServerReference\\)\\(\"([0-9a-f]+)\"[^)]*?\"([^\"]+)\"\\)/g;\n/** `/_next/static/chunks/....js` references in the page HTML. */\nconst CHUNK_RE = /\\/_next\\/static\\/chunks\\/[^\"'`()\\s]+?\\.js/g;\n/**\n * Default pages scraped during discovery. Server Actions are split per route, so\n * a single page misses route-specific actions (e.g. `deleteReference` lives only\n * in the `/references` bundle) — scrape the main routes and union their chunks.\n */\nconst DISCOVERY_PAGES = ['/explore', '/creations', '/characters', '/references'];\n\n/** Default in-process snapshot cache. */\nexport class InMemoryActionCache implements ActionCache {\n private snapshot: ActionSnapshot | null = null;\n\n async load(): Promise<ActionSnapshot | null> {\n return this.snapshot;\n }\n\n async save(snapshot: ActionSnapshot): Promise<void> {\n this.snapshot = snapshot;\n }\n}\n\nexport interface DiscoveryOptions {\n fetch: FetchLike;\n baseUrl: string;\n /** Single page to scrape for chunk references (overrides {@link discoveryPaths}). */\n discoveryPath?: string;\n /** Pages to scrape and union (default: the main app routes). */\n discoveryPaths?: string[];\n}\n\n/** Result of {@link listDiscoveryChunks}: the JS chunk paths to scrape. */\nexport interface ChunkListResult {\n /** Vercel deployment id from the first page's `x-deployment-id` (`''` if none). */\n deploymentId: string;\n /** De-duplicated, insertion-ordered `/_next/static/chunks/*.js` paths. */\n chunkPaths: string[];\n}\n\n/**\n * The action names the portal actually invokes.\n *\n * @remarks\n * Verified against `lib/auth.ts`, `lib/generation.ts`/`lib/history.ts` (via\n * `resolveActionName` on `PRODUCTION_TARGET`), `lib/characters.ts`, and\n * `lib/references.ts`. A batched, subrequest-capped caller (e.g. a Cloudflare\n * Worker) uses this list to know when it has discovered everything it needs and\n * can early-exit without scraping the remaining chunks. Every name is a key in\n * {@link SEED_SNAPSHOT}.hashes.\n */\nconst REQUIRED_ACTIONS = [\n 'createUserSession',\n 'getHistoryPaginated',\n 'getHistoryById',\n 'runArchitecture',\n 'cancelArchitectureJob',\n 'getCreationsPaginatedParallel',\n 'getMentionSuggestionsParallel',\n 'createCharacter',\n 'updateCharacter',\n 'deleteCharacter',\n 'getCharacter',\n 'getCharacters',\n 'publishCharacter',\n 'unpublishCharacter',\n 'uploadCharacterImage',\n 'getCharactersPaginated',\n 'generateCharacterVoice',\n 'followCharacter',\n 'unfollowCharacter',\n 'uploadReferenceImage',\n 'createReference',\n 'updateReference',\n 'deleteReference',\n 'getReferences',\n 'getReferencesPaginated',\n] as const satisfies readonly ActionName[];\n\n/**\n * The action names a batched discovery caller must find before it can stop.\n *\n * @remarks\n * These are the actions the portal invokes; once a batched caller has hashes for\n * all of them it can early-exit instead of scraping every remaining chunk.\n */\nexport function requiredActionsForClient(): ActionName[] {\n return [...REQUIRED_ACTIONS];\n}\n\n/**\n * List the JS chunk paths referenced by the discovery pages.\n *\n * @remarks\n * Issues at most one GET per page (`<= pages.length` subrequests), so a caller on\n * a subrequest-capped host (e.g. Cloudflare Workers free plan) can list chunks\n * cheaply and then scrape them in bounded batches via {@link scrapeChunks}.\n *\n * @throws {DiscoveryError} when no JS chunk references are found.\n */\nexport async function listDiscoveryChunks(opts: {\n fetch: FetchLike;\n baseUrl: string;\n pages?: string[];\n}): Promise<ChunkListResult> {\n const { fetch, baseUrl } = opts;\n const pages = opts.pages ?? DISCOVERY_PAGES;\n\n let deploymentId = '';\n const chunkPaths = new Set<string>();\n for (const page of pages) {\n let res: Response;\n try {\n res = await fetch(`${baseUrl}${page}`, { headers: { accept: 'text/html' } });\n } catch {\n // A single unreachable page must not abort discovery.\n continue;\n }\n if (!res.ok) {\n continue;\n }\n if (deploymentId === '') {\n deploymentId = res.headers.get('x-deployment-id') ?? '';\n }\n const html = await res.text();\n for (const match of html.matchAll(CHUNK_RE)) {\n const chunkPath = match[0];\n if (chunkPath !== undefined) {\n chunkPaths.add(chunkPath);\n }\n }\n }\n if (chunkPaths.size === 0) {\n throw new DiscoveryError('No JS chunk references found in discovery pages');\n }\n return { deploymentId, chunkPaths: [...chunkPaths] };\n}\n\n/**\n * Scrape a specific set of JS chunks for `createServerReference(...)` hashes.\n *\n * @remarks\n * Fetches ONLY the passed `chunkPaths` (one subrequest each), so a caller can\n * process chunks in batches sized to its subrequest budget and merge the partial\n * hash maps across batches. First hash wins per function name, mirroring\n * {@link discoverActions}. Never throws on an empty result — a single batch may\n * legitimately find nothing.\n */\nexport async function scrapeChunks(opts: {\n fetch: FetchLike;\n baseUrl: string;\n chunkPaths: string[];\n}): Promise<{ deploymentId: string; hashes: ActionHashes }> {\n const { fetch, baseUrl, chunkPaths } = opts;\n\n let deploymentId = '';\n const hashes: ActionHashes = {};\n await Promise.all(\n chunkPaths.map(async (path) => {\n try {\n const chunkRes = await fetch(`${baseUrl}${path}`, {\n headers: { accept: 'application/javascript' },\n });\n if (!chunkRes.ok) {\n return;\n }\n // Chunk responses are served by the deployment and usually carry the id,\n // even when CDN-cached page HTML omits it.\n if (deploymentId === '') {\n deploymentId = chunkRes.headers.get('x-deployment-id') ?? '';\n }\n const js = await chunkRes.text();\n for (const match of js.matchAll(CREATE_SERVER_REF_RE)) {\n const hash = match[1];\n const fn = match[2];\n if (hash !== undefined && fn !== undefined && !(fn in hashes)) {\n hashes[fn] = hash;\n }\n }\n } catch {\n // A single failed chunk must not abort the rest.\n }\n }),\n );\n\n return { deploymentId, hashes };\n}\n\n/**\n * Discover the current Server Action hashes by scraping the page HTML for JS\n * chunk URLs and extracting `createServerReference(...)` calls from each chunk.\n *\n * @remarks\n * Composes {@link listDiscoveryChunks} (page GETs) and {@link scrapeChunks} (over\n * all discovered chunks) into the full snapshot. Unsuitable for subrequest-capped\n * hosts, which should batch {@link scrapeChunks} instead.\n *\n * @throws {DiscoveryError} on network failure or when nothing is discovered.\n */\nexport async function discoverActions(opts: DiscoveryOptions): Promise<ActionSnapshot> {\n const { fetch, baseUrl } = opts;\n const pages =\n opts.discoveryPath !== undefined\n ? [opts.discoveryPath]\n : (opts.discoveryPaths ?? DISCOVERY_PAGES);\n\n const { deploymentId: pageDeploymentId, chunkPaths } = await listDiscoveryChunks({\n fetch,\n baseUrl,\n pages,\n });\n\n const { deploymentId: chunkDeploymentId, hashes } = await scrapeChunks({\n fetch,\n baseUrl,\n chunkPaths,\n });\n\n if (Object.keys(hashes).length === 0) {\n throw new DiscoveryError('No server action hashes discovered in JS chunks');\n }\n\n // Fallback: CDN-cached page HTML may omit x-deployment-id; chunk responses\n // are served by the deployment and usually carry it.\n const deploymentId = pageDeploymentId !== '' ? pageDeploymentId : chunkDeploymentId;\n return { deploymentId, hashes, discoveredAt: Date.now() };\n}\n\nexport interface ActionRegistryOptions {\n fetch: FetchLike;\n baseUrl: string;\n cache?: ActionCache;\n seed?: ActionSnapshot;\n discoveryPath?: string;\n discoveryPaths?: string[];\n /** Re-discover when the snapshot is older than this (ms). 0 = never by age. */\n maxAgeMs?: number;\n}\n\n/**\n * Serves action hashes from a warm seed / pluggable cache, discovering lazily and\n * refreshing on staleness. Concurrent refreshes are de-duplicated (single-flight).\n */\nexport class ActionRegistry {\n private readonly fetch: FetchLike;\n private readonly baseUrl: string;\n private readonly cache: ActionCache;\n private readonly seed: ActionSnapshot | undefined;\n private readonly discoveryPath: string | undefined;\n private readonly discoveryPaths: string[] | undefined;\n private readonly maxAgeMs: number;\n private snapshot: ActionSnapshot | null = null;\n private inflight: Promise<ActionSnapshot> | null = null;\n\n constructor(opts: ActionRegistryOptions) {\n this.fetch = opts.fetch;\n this.baseUrl = opts.baseUrl;\n this.cache = opts.cache ?? new InMemoryActionCache();\n this.seed = opts.seed;\n this.discoveryPath = opts.discoveryPath;\n this.discoveryPaths = opts.discoveryPaths;\n this.maxAgeMs = opts.maxAgeMs ?? 0;\n }\n\n private isStale(snapshot: ActionSnapshot): boolean {\n return this.maxAgeMs > 0 && Date.now() - snapshot.discoveredAt > this.maxAgeMs;\n }\n\n /** Return the current snapshot, loading from cache/seed or discovering as needed. */\n async getSnapshot(): Promise<ActionSnapshot> {\n if (this.snapshot !== null && !this.isStale(this.snapshot)) {\n return this.snapshot;\n }\n const cached = await this.cache.load();\n if (cached !== null && !this.isStale(cached)) {\n this.snapshot = cached;\n return cached;\n }\n if (this.seed !== undefined) {\n this.snapshot = this.seed;\n await this.cache.save(this.seed);\n return this.seed;\n }\n return this.refresh();\n }\n\n /** Force re-discovery. Concurrent callers share one in-flight discovery. */\n async refresh(): Promise<ActionSnapshot> {\n if (this.inflight !== null) {\n return this.inflight;\n }\n this.inflight = (async () => {\n try {\n const fresh = await discoverActions({\n fetch: this.fetch,\n baseUrl: this.baseUrl,\n discoveryPath: this.discoveryPath,\n discoveryPaths: this.discoveryPaths,\n });\n this.snapshot = fresh;\n await this.cache.save(fresh);\n return fresh;\n } finally {\n this.inflight = null;\n }\n })();\n return this.inflight;\n }\n\n /** Resolve a function name to its current hash + deployment id. */\n async getHash(action: ActionName | string): Promise<{ hash: string; deploymentId: string }> {\n let snapshot = await this.getSnapshot();\n let hash = snapshot.hashes[action];\n if (hash === undefined) {\n snapshot = await this.refresh();\n hash = snapshot.hashes[action];\n }\n if (hash === undefined) {\n throw new DiscoveryError(`Action \"${action}\" not found after discovery`, { notFound: true });\n }\n return { hash, deploymentId: snapshot.deploymentId };\n }\n\n /** Drop the cached snapshot and re-discover (called on a stale 404). */\n async invalidate(): Promise<ActionSnapshot> {\n this.snapshot = null;\n return this.refresh();\n }\n}\n","/**\n * Minimal parser for the React Server Component (RSC) \"Flight\" wire format used\n * by Next.js Server Action responses.\n *\n * The wire format is a sequence of newline-delimited rows:\n *\n * ```text\n * 0:{\"a\":\"$@1\",\"f\":\"\",\"b\":\"buildId\"}\n * 1:{\"history_id\":\"e3357fb8-...\",\"architecture_config\":\"$T0:0:architectureConfig\"}\n * ```\n *\n * Each row is `<hexId>:<jsonPayload>`. Values may contain sentinels:\n * - `$undefined` → `undefined`\n * - `$@<id>` → reference to another row (a resolved promise)\n * - `$$...` → an escaped literal string starting with `$`\n * - `$<other>` → a typed marker (kept verbatim, best-effort)\n *\n * @remarks\n * The exact envelope for some read actions (e.g. `getHistoryById`) should be\n * confirmed against live traffic via the rev-eng Playwright flow; this parser is\n * intentionally tolerant and falls back to the last JSON row when the row-0\n * `{ a: ... }` envelope is absent.\n */\nimport { RscParseError } from './errors.js';\n\nconst REF_RE = /^\\$@([0-9a-f]+)$/i;\n/** A plain row reference like `$5` (not a promise `$@5`, nor a `$D`/`$S`/... marker). */\nconst HEX_REF_RE = /^\\$([0-9a-f]+)$/i;\nconst ROW_ID_RE = /^[0-9a-f]+$/i;\n\n/** Return the char index after consuming exactly `byteLen` UTF-8 bytes from `start`. */\nfunction endOfUtf8Slice(text: string, start: number, byteLen: number): number {\n let bytes = 0;\n let i = start;\n while (i < text.length && bytes < byteLen) {\n const cp = text.codePointAt(i) as number;\n bytes += cp <= 0x7f ? 1 : cp <= 0x7ff ? 2 : cp <= 0xffff ? 3 : 4;\n i += cp > 0xffff ? 2 : 1;\n }\n return i;\n}\n\n/**\n * Parse the raw Flight text into a map of `rowId → value`.\n *\n * @remarks\n * Most rows are `id:<json>\\n`, but text rows are length-delimited:\n * `id:T<hexlen>,<hexlen UTF-8 bytes>` and are NOT newline-terminated — the next\n * row begins immediately after the counted bytes. A naive line split therefore\n * glues the following data row onto a multi-line prompt (which is exactly why\n * large `getHistoryPaginated` responses failed to parse). This parser is\n * position/length aware so length-delimited rows are consumed exactly and every\n * subsequent row stays isolated.\n */\nexport function parseFlightRows(text: string): Map<string, unknown> {\n const rows = new Map<string, unknown>();\n const n = text.length;\n let pos = 0;\n while (pos < n) {\n if (text[pos] === '\\n') {\n pos += 1;\n continue;\n }\n const colon = text.indexOf(':', pos);\n if (colon === -1) {\n break;\n }\n const id = text.slice(pos, colon);\n if (!ROW_ID_RE.test(id)) {\n // Not a row boundary; skip to the next line and resync.\n const nl = text.indexOf('\\n', pos);\n if (nl === -1) {\n break;\n }\n pos = nl + 1;\n continue;\n }\n if (text[colon + 1] === 'T') {\n // Length-delimited text row: T<hexlen>,<bytes> (no trailing newline).\n const comma = text.indexOf(',', colon + 2);\n if (comma === -1) {\n break;\n }\n const byteLen = Number.parseInt(text.slice(colon + 2, comma), 16);\n const start = comma + 1;\n const end = endOfUtf8Slice(text, start, byteLen);\n rows.set(id, text.slice(start, end));\n pos = end;\n continue;\n }\n // Any other row is a single line terminated by \\n.\n const nl = text.indexOf('\\n', colon + 1);\n const payload = nl === -1 ? text.slice(colon + 1) : text.slice(colon + 1, nl);\n pos = nl === -1 ? n : nl + 1;\n const first = payload[0];\n if (first === undefined) {\n continue;\n }\n const looksJson =\n first === '{' ||\n first === '[' ||\n first === '\"' ||\n first === '-' ||\n (first >= '0' && first <= '9') ||\n payload === 'true' ||\n payload === 'false' ||\n payload === 'null';\n if (!looksJson) {\n // Module/element/hint rows (e.g. `1:I[...]`, `2:\"$Sreact...\"`) are not data.\n continue;\n }\n try {\n rows.set(id, JSON.parse(payload));\n } catch {\n // Ignore rows that are not valid JSON.\n }\n }\n return rows;\n}\n\n/** Recursively resolve Flight sentinels/references within a parsed value. */\nexport function resolveFlightValue(\n value: unknown,\n rows: Map<string, unknown>,\n seen: Set<string> = new Set(),\n): unknown {\n if (typeof value === 'string') {\n if (value === '$undefined') {\n return undefined;\n }\n const ref = REF_RE.exec(value) ?? HEX_REF_RE.exec(value);\n if (ref) {\n const refId = ref[1];\n if (refId === undefined || seen.has(refId)) {\n return undefined;\n }\n const target = rows.get(refId);\n if (target === undefined) {\n return undefined;\n }\n // Scope the cycle guard to the current depth-first path: descend with a\n // fresh copy that records this ref. Siblings keep the unmutated `seen`, so\n // a DAG (many siblings pointing at one shared row) resolves on every sibling,\n // while a true cycle (a refId already on this ancestor path) still returns\n // undefined.\n const nextSeen = new Set(seen);\n nextSeen.add(refId);\n return resolveFlightValue(target, rows, nextSeen);\n }\n if (value.startsWith('$$')) {\n return value.slice(1);\n }\n // $D<iso> → Date object (React Flight Date sentinel).\n if (value.startsWith('$D')) {\n return new Date(value.slice(2));\n }\n // Other `$`-prefixed markers are kept verbatim.\n return value;\n }\n if (Array.isArray(value)) {\n return value.map((entry) => resolveFlightValue(entry, rows, seen));\n }\n if (value !== null && typeof value === 'object') {\n const out: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(value)) {\n out[key] = resolveFlightValue(entry, rows, seen);\n }\n return out;\n }\n return value;\n}\n\n/**\n * Parse a Server Action response and return the action's resolved return value.\n *\n * @throws {RscParseError} when the response contains no parseable rows.\n */\nexport function parseServerActionResponse<T = unknown>(text: string): T {\n const rows = parseFlightRows(text);\n if (rows.size === 0) {\n throw new RscParseError('Empty or unparseable RSC response');\n }\n const root = rows.get('0');\n if (root !== null && typeof root === 'object' && !Array.isArray(root) && 'a' in root) {\n return resolveFlightValue((root as Record<string, unknown>).a, rows) as T;\n }\n // Fallback: the highest-id row usually carries the payload.\n let lastId: string | null = null;\n for (const id of rows.keys()) {\n if (lastId === null || Number.parseInt(id, 16) > Number.parseInt(lastId, 16)) {\n lastId = id;\n }\n }\n return resolveFlightValue(lastId === null ? undefined : rows.get(lastId), rows) as T;\n}\n\n/**\n * Unwrap a single-object result that some Server Actions (notably the\n * `*Parallel` family) wrap in a one-element array.\n *\n * @remarks\n * `getCreationsPaginatedParallel` and `getMentionSuggestionsParallel` return their\n * payload as `[value]` on the RSC wire (`1:[\"$@2\"]`), whereas most actions return\n * the value directly. This normalizes object-returning actions to the value; it is\n * a no-op when the response is already the object. Do NOT use it for actions whose\n * genuine return type is an array (e.g. `getReferences`).\n */\nexport function unwrapResult<T>(value: unknown): T {\n return (Array.isArray(value) && value.length === 1 ? value[0] : value) as T;\n}\n","/**\n * Character & reference management.\n *\n * Covers the verified Server Actions from `docs/api/characters.md`: search\n * (`getMentionSuggestionsParallel`), full CRUD, pagination, publish/unpublish,\n * and base64 image uploads.\n *\n * @remarks\n * Read operations pass the caller's `uid` in the body; write operations rely on\n * the `__session` cookie (the server derives the uid from it). All actions are\n * posted to the `/explore` page where their bundles are loaded.\n */\nimport type { AuthManager } from './auth.js';\nimport { MageSpaceError } from './errors.js';\nimport type { HttpClient } from './http.js';\nimport { unwrapResult } from './rsc.js';\nimport type {\n Character,\n CharacterPage,\n CharacterSearchResult,\n CreateCharacterInput,\n GenerateVoiceOptions,\n ListCharactersOptions,\n SearchCharactersOptions,\n UpdateCharacterInput,\n VoiceResult,\n} from './types.js';\n\n/** Character actions are served from the `/explore` page. */\nconst CHARACTERS_PATH = '/explore';\nconst DEFAULT_SEARCH_LIMIT = 10;\n\n/** Server-enforced username constraints (from module 64428). */\nconst USERNAME_MIN = 1;\nconst USERNAME_MAX = 15;\nconst USERNAME_RE = /^[a-z][a-z0-9_-]*$/;\n\n/**\n * Generate a username from a display name, matching the web UI logic:\n * lowercase, strip special chars, append a 4-char random suffix, truncate to 15.\n */\nfunction generateUsername(name: string): string {\n const suffix = Math.random().toString(36).substring(2, 6);\n const base = name\n .toLowerCase()\n .trim()\n .replace(/[^a-z0-9\\s]/g, '')\n .replace(/\\s+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '');\n // Ensure the random suffix always fits: base is truncated to leave room for `-xxxx`.\n const maxBase = USERNAME_MAX - suffix.length - 1; // 1 for the dash separator\n const trimmedBase = base.slice(0, maxBase).replace(/[-_]+$/, '');\n return `${trimmedBase}-${suffix}`;\n}\n\n/** Validate a username and throw early with a clear message instead of a server 500. */\nfunction validateUsername(username: string): void {\n if (username.length < USERNAME_MIN) {\n throw new MageSpaceError('Username is required (min 1 character)');\n }\n if (username.length > USERNAME_MAX) {\n throw new MageSpaceError(\n `Username \"${username}\" is too long (${username.length} chars, max ${USERNAME_MAX})`,\n );\n }\n if (!USERNAME_RE.test(username)) {\n throw new MageSpaceError(\n `Username \"${username}\" is invalid: must start with a lowercase letter and contain only a-z, 0-9, _ or -`,\n );\n }\n}\n\nexport class CharactersService {\n constructor(\n private readonly http: HttpClient,\n private readonly auth: AuthManager,\n ) {}\n\n /** Search the caller's characters (and optionally public references) by name. */\n async search(opts: SearchCharactersOptions): Promise<CharacterSearchResult> {\n const [uid, session] = await Promise.all([this.auth.getUserId(), this.auth.getSession()]);\n const body = {\n query: opts.query,\n uid,\n limit: opts.limit ?? DEFAULT_SEARCH_LIMIT,\n includePublicReferences: opts.includePublicReferences ?? false,\n referenceModalities: opts.referenceModalities ?? ['image', 'audio'],\n };\n const { data } = await this.http.callAction<CharacterSearchResult>({\n action: 'getMentionSuggestionsParallel',\n path: CHARACTERS_PATH,\n args: [body],\n session,\n });\n return unwrapResult<CharacterSearchResult>(data);\n }\n\n /** Create a new character from an already-uploaded image URL. */\n async create(input: CreateCharacterInput): Promise<Character> {\n const username = input.username ?? generateUsername(input.name);\n validateUsername(username);\n const session = await this.auth.getSession();\n const body = {\n name: input.name,\n username,\n image_url: input.image_url,\n audio_url: input.audio_url ?? null,\n description: input.description ?? null,\n tags: input.tags ?? [],\n visibility: input.visibility ?? 'private',\n moderation: input.moderation ?? [],\n };\n const { data } = await this.http.callAction<Character>({\n action: 'createCharacter',\n path: CHARACTERS_PATH,\n args: [body],\n session,\n });\n return data;\n }\n\n /** Update a character's mutable fields (name, description, tags, visibility, voice). */\n async update(id: string, patch: UpdateCharacterInput): Promise<Character> {\n const session = await this.auth.getSession();\n const { data } = await this.http.callAction<Character>({\n action: 'updateCharacter',\n path: CHARACTERS_PATH,\n args: [id, patch],\n session,\n });\n return data;\n }\n\n /** Soft-delete a character. */\n async delete(id: string): Promise<void> {\n const session = await this.auth.getSession();\n await this.http.callAction({\n action: 'deleteCharacter',\n path: CHARACTERS_PATH,\n args: [id],\n session,\n });\n }\n\n /** Fetch a single character by id; resolves to `null` when it does not exist. */\n async get(id: string): Promise<Character | null> {\n const session = await this.auth.getSession();\n const { data } = await this.http.callAction<Character | null>({\n action: 'getCharacter',\n path: CHARACTERS_PATH,\n args: [id],\n session,\n });\n return data ?? null;\n }\n\n /** Fetch multiple characters by id in a single call. */\n async getMany(ids: string[]): Promise<Character[]> {\n const session = await this.auth.getSession();\n const { data } = await this.http.callAction<Character[]>({\n action: 'getCharacters',\n path: CHARACTERS_PATH,\n args: [ids],\n session,\n });\n return data ?? [];\n }\n\n /** Make a character public. */\n async publish(id: string): Promise<void> {\n const session = await this.auth.getSession();\n await this.http.callAction({\n action: 'publishCharacter',\n path: CHARACTERS_PATH,\n args: [id],\n session,\n });\n }\n\n /** Make a character private. */\n async unpublish(id: string): Promise<void> {\n const session = await this.auth.getSession();\n await this.http.callAction({\n action: 'unpublishCharacter',\n path: CHARACTERS_PATH,\n args: [id],\n session,\n });\n }\n\n /**\n * Upload a character reference image (base64 data URL) and return its CDN URL.\n *\n * @param dataUrl - `data:image/jpeg;base64,...` (JPEG preferred; PNG/WebP ok).\n */\n async uploadImage(dataUrl: string): Promise<string> {\n const [uid, session] = await Promise.all([this.auth.getUserId(), this.auth.getSession()]);\n const { data } = await this.http.callAction<string>({\n action: 'uploadCharacterImage',\n path: CHARACTERS_PATH,\n args: [dataUrl, uid],\n session,\n });\n return data;\n }\n\n /**\n * Browse characters with pagination.\n *\n * @remarks\n * Omit `uid` to browse the public/featured feed; pass it to page through a\n * single user's characters.\n */\n async listPaginated(opts: ListCharactersOptions = {}): Promise<CharacterPage> {\n const session = await this.auth.getSession();\n const limit = opts.limit ?? 100;\n const offset = opts.offset ?? 0;\n const filters: Record<string, unknown> = {};\n if (opts.uid !== undefined) {\n filters.uid = opts.uid;\n }\n if (opts.visibility !== undefined) {\n filters.visibility = opts.visibility;\n }\n if (opts.modality !== undefined) {\n filters.modality = opts.modality;\n }\n if (opts.featured !== undefined) {\n filters.featured = opts.featured;\n }\n const { data } = await this.http.callAction<CharacterPage>({\n action: 'getCharactersPaginated',\n path: CHARACTERS_PATH,\n args: [limit, offset, filters],\n session,\n });\n return data;\n }\n\n /**\n * Generate a voice for a character from its reference image.\n *\n * @remarks Costs gems (not covered by the unlimited tier).\n * @experimental Request body inferred from JS bundle; not yet verified live.\n */\n async generateVoice(opts: GenerateVoiceOptions): Promise<VoiceResult> {\n const [authToken, session] = await Promise.all([\n this.auth.getIdToken(),\n this.auth.getSession(),\n ]);\n const { data } = await this.http.callAction<VoiceResult>({\n action: 'generateCharacterVoice',\n path: CHARACTERS_PATH,\n args: [{ imageUrl: opts.imageUrl, guidancePrompt: opts.guidancePrompt ?? '' }, authToken],\n session,\n });\n return data;\n }\n\n /**\n * Follow a (public) character.\n *\n * @experimental Request body inferred from JS bundle; not yet verified live.\n */\n async follow(id: string): Promise<void> {\n const session = await this.auth.getSession();\n await this.http.callAction({\n action: 'followCharacter',\n path: CHARACTERS_PATH,\n args: [id],\n session,\n });\n }\n\n /**\n * Unfollow a character.\n *\n * @experimental Request body inferred from JS bundle; not yet verified live.\n */\n async unfollow(id: string): Promise<void> {\n const session = await this.auth.getSession();\n await this.http.callAction({\n action: 'unfollowCharacter',\n path: CHARACTERS_PATH,\n args: [id],\n session,\n });\n }\n}\n","/**\n * Firebase authentication: refresh token → ID token → session cookie.\n *\n * The refresh token is the only long-lived credential the caller supplies.\n * From it we mint a Firebase ID token (~1h) via the Secure Token REST API, and\n * exchange that for a `__session` cookie (~24h) via the `createUserSession`\n * Server Action. Both are cached and refreshed 5 minutes before expiry.\n */\nimport { decodeJwt } from 'jose';\nimport { AuthError } from './errors.js';\nimport type { HttpClient } from './http.js';\nimport type { AuthTokens, FetchLike, SessionState } from './types.js';\n\nconst DEFAULT_FIREBASE_API_KEY = 'AIzaSyAzUV2NNUOlLTL04jwmUw9oLhjteuv6Qr4';\nconst SECURE_TOKEN_URL = 'https://securetoken.googleapis.com/v1/token';\nconst EXPIRY_BUFFER_MS = 5 * 60 * 1000;\nconst SESSION_DEFAULT_TTL_MS = 24 * 60 * 60 * 1000;\nconst ID_TOKEN_DEFAULT_TTL_S = 3600;\n\ninterface SecureTokenResponse {\n id_token?: string;\n refresh_token?: string;\n user_id?: string;\n expires_in?: string;\n}\n\nexport interface AuthManagerOptions {\n refreshToken: string;\n /**\n * Accessor for the active host's {@link HttpClient}. A closure (not the client\n * itself) so `createUserSession` always hits whichever host is currently\n * active after an automatic fallback.\n */\n getHttp: () => HttpClient;\n fetch: FetchLike;\n firebaseApiKey?: string;\n /** Page path for the `createUserSession` action (default `/creations`). */\n sessionPath?: string;\n}\n\nexport class AuthManager {\n private refreshToken: string;\n private readonly getHttp: () => HttpClient;\n private readonly fetchImpl: FetchLike;\n private readonly apiKey: string;\n private readonly sessionPath: string;\n private tokens: AuthTokens | null = null;\n private session: SessionState | null = null;\n\n constructor(opts: AuthManagerOptions) {\n this.refreshToken = opts.refreshToken;\n this.getHttp = opts.getHttp;\n this.fetchImpl = opts.fetch;\n this.apiKey = opts.firebaseApiKey ?? DEFAULT_FIREBASE_API_KEY;\n this.sessionPath = opts.sessionPath ?? '/creations';\n }\n\n /**\n * Drop the cached `__session` cookie so the next {@link getSession} mints a\n * fresh one against the (newly) active host. The Firebase token chain is kept\n * because it is host-independent.\n */\n resetSession(): void {\n this.session = null;\n }\n\n /** Return a valid Firebase ID token, refreshing via the refresh token if needed. */\n async getIdToken(): Promise<string> {\n if (this.tokens !== null && Date.now() < this.tokens.expiresAt - EXPIRY_BUFFER_MS) {\n return this.tokens.idToken;\n }\n return (await this.refreshTokens()).idToken;\n }\n\n /** Return the Firebase uid (fetching an ID token first if necessary). */\n async getUserId(): Promise<string> {\n if (this.tokens !== null) {\n return this.tokens.userId;\n }\n return (await this.refreshTokens()).userId;\n }\n\n /** Return a valid `__session` cookie, creating one via `createUserSession` if needed. */\n async getSession(): Promise<string> {\n if (this.session !== null && Date.now() < this.session.expiresAt - EXPIRY_BUFFER_MS) {\n return this.session.cookie;\n }\n const idToken = await this.getIdToken();\n const result = await this.getHttp().callAction<unknown>({\n action: 'createUserSession',\n path: this.sessionPath,\n args: [idToken],\n });\n const cookie = extractSessionCookie(result.headers);\n if (cookie === null) {\n throw new AuthError('createUserSession did not return a __session cookie');\n }\n const expiresAt = jwtExpiryMs(cookie) ?? Date.now() + SESSION_DEFAULT_TTL_MS;\n this.session = { cookie, expiresAt };\n return cookie;\n }\n\n private async refreshTokens(): Promise<AuthTokens> {\n const body = new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: this.refreshToken,\n });\n const res = await this.fetchImpl(`${SECURE_TOKEN_URL}?key=${this.apiKey}`, {\n method: 'POST',\n headers: { 'content-type': 'application/x-www-form-urlencoded' },\n body: body.toString(),\n });\n if (!res.ok) {\n throw new AuthError(\n `Token refresh failed: HTTP ${res.status} (refresh token may be invalid or revoked)`,\n );\n }\n const json = (await res.json()) as SecureTokenResponse;\n if (json.id_token === undefined || json.user_id === undefined) {\n throw new AuthError('Token refresh response missing id_token/user_id');\n }\n if (json.refresh_token !== undefined) {\n this.refreshToken = json.refresh_token;\n }\n const ttlS = json.expires_in === undefined ? ID_TOKEN_DEFAULT_TTL_S : Number(json.expires_in);\n const expiresAt = jwtExpiryMs(json.id_token) ?? Date.now() + ttlS * 1000;\n this.tokens = {\n idToken: json.id_token,\n refreshToken: this.refreshToken,\n userId: json.user_id,\n expiresAt,\n };\n return this.tokens;\n }\n}\n\n/** Read the `exp` claim (ms) from a JWT, or `null` if it cannot be decoded. */\nfunction jwtExpiryMs(jwt: string): number | null {\n try {\n const { exp } = decodeJwt(jwt);\n return typeof exp === 'number' ? exp * 1000 : null;\n } catch {\n return null;\n }\n}\n\n/** Extract the `__session` value from a `Set-Cookie` response header. */\nfunction extractSessionCookie(headers: Headers): string | null {\n const withGetSetCookie = headers as Headers & { getSetCookie?: () => string[] };\n const list =\n typeof withGetSetCookie.getSetCookie === 'function'\n ? withGetSetCookie.getSetCookie()\n : headers.get('set-cookie') !== null\n ? [headers.get('set-cookie') as string]\n : [];\n for (const cookie of list) {\n const match = /(?:^|;\\s*)__session=([^;]+)/.exec(cookie);\n if (match !== null && match[1] !== undefined) {\n return match[1];\n }\n }\n return null;\n}\n","/**\n * Per-host {@link Target} descriptors.\n *\n * mage.space is migrating from production (`https://www.mage.space`) to a new\n * portal (`https://beta.mage.space`). Rather than hard-coding one base URL and\n * one action-name set, each host is modelled as a `Target` so host differences\n * (renamed actions, poll strategy) live in a single table. The client holds an\n * ordered chain `[production, beta]` and advances to the next target only when\n * the active host can no longer serve a required action.\n */\n\n/** Hosts the client can talk to. */\nexport type TargetKey = 'production' | 'beta';\n\n/** How a single history-status read is performed on a given host. */\nexport type PollStrategy = 'byId' | 'paginated';\n\n/**\n * Logical operations the generation/history services invoke, decoupled from the\n * host-specific wire names. `createUserSession` is intentionally NOT a member:\n * it is resolved by its literal name on both hosts (see `lib/auth.ts`).\n */\nexport type LogicalAction =\n | 'submitGeneration'\n | 'getHistoryById'\n | 'cancelJob'\n | 'listHistory'\n | 'listCreations';\n\n/** A single host the client can target. */\nexport interface Target {\n readonly key: TargetKey;\n readonly baseUrl: string;\n /** logical name → host-specific wire name; unlisted names resolve to themselves. */\n readonly actionNames: Readonly<Partial<Record<LogicalAction, string>>>;\n readonly pollStrategy: PollStrategy;\n}\n\n/** Resolve a logical action to its host-specific wire name (identity if unlisted). */\nexport function resolveActionName(target: Target, logical: LogicalAction): string {\n return target.actionNames[logical] ?? logical;\n}\n\n/**\n * Production target.\n *\n * @remarks\n * Maps each logical action to the wire name the current production deploy\n * actually serves (all VERIFIED against `lib/seed.ts` / the existing MSW tests):\n * `submitGeneration → runArchitecture`, `cancelJob → cancelArchitectureJob`,\n * `listHistory → getHistoryPaginated`, `listCreations → getCreationsPaginatedParallel`,\n * and `getHistoryById → getHistoryById` (identity). The table is explicit rather\n * than empty so production behaviour is reproduced exactly regardless of the\n * logical-name vocabulary.\n */\nexport const PRODUCTION_TARGET: Target = {\n key: 'production',\n baseUrl: 'https://www.mage.space',\n actionNames: {\n submitGeneration: 'runArchitecture',\n getHistoryById: 'getHistoryById',\n cancelJob: 'cancelArchitectureJob',\n listHistory: 'getHistoryPaginated',\n listCreations: 'getCreationsPaginatedParallel',\n },\n pollStrategy: 'byId',\n};\n\n/**\n * Beta target. Beta facts are assumptions pending a reverse-engineering capture\n * under `docs/api/beta` — treat them as unverified until that doc lands.\n */\nexport const BETA_TARGET: Target = {\n key: 'beta',\n baseUrl: 'https://beta.mage.space',\n actionNames: {\n // ASSUMED (pending docs/api/beta) — source: brief, re-verify via rev-eng\n submitGeneration: 'runArchitecture',\n // ASSUMED (pending docs/api/beta) — source: brief, re-verify via rev-eng\n cancelJob: 'cancelArchitectureJob',\n // ASSUMED (pending docs/api/beta) — source: brief, re-verify via rev-eng\n listHistory: 'getHistoryPaginated',\n // ASSUMED (pending docs/api/beta) — getHistoryById is absent on beta; poll via pagination\n listCreations: 'getCreationsPaginated',\n },\n // ASSUMED (pending docs/api/beta) — source: brief, re-verify via rev-eng\n pollStrategy: 'paginated',\n};\n\n/** Default ordered fallback chain: production first, then beta. */\nexport const DEFAULT_TARGET_CHAIN: readonly Target[] = [PRODUCTION_TARGET, BETA_TARGET];\n\n/** Page size used by the beta paginated poll strategy. */\nexport const PAGINATED_POLL_PAGE_SIZE = 20;\n\n/** Maximum number of pages the beta paginated poll strategy scans per read. */\nexport const PAGINATED_POLL_MAX_PAGES = 10;\n","/**\n * Image generation: submit a job via `runArchitecture`, then poll\n * `getHistoryById` until the job succeeds, fails, or times out.\n */\nimport type { AuthManager } from './auth.js';\nimport { GenerationError, TimeoutError } from './errors.js';\nimport type { HttpClient } from './http.js';\nimport { unwrapResult } from './rsc.js';\nimport {\n PAGINATED_POLL_MAX_PAGES,\n PAGINATED_POLL_PAGE_SIZE,\n resolveActionName,\n type Target,\n} from './targets.js';\nimport type {\n ArchitectureConfig,\n CharacterRef,\n GenerateOptions,\n GenerateVideoOptions,\n GenerationMode,\n HistoryItem,\n HistoryPage,\n VideoArchitectureConfig,\n WaitOptions,\n} from './types.js';\n\n/** Generation actions are served from the `/explore` page. */\nconst GENERATION_PATH = '/explore';\n/** Mirrors HistoryService.HISTORY_PATH ('/creations'); kept local to avoid coupling the two services. */\nconst HISTORY_PATH = '/creations';\n/** RSC sentinel for an absent value. */\nconst UNDEFINED = '$undefined';\n/** Default concept id for mango-v3-pro (from docs — verify per model via rev-eng). */\nconst DEFAULT_CONCEPT_ID = '0cd8c7ed2e554d0f98f20c8cf8c0f7c';\n/** Default concept id for berry-2 video (from docs — verify per model via rev-eng). */\nconst DEFAULT_BERRY_CONCEPT_ID = '0b1fa74f7347406392422d24f2885684';\n\nconst DEFAULT_POLL_INTERVAL_MS = 4000;\nconst DEFAULT_TIMEOUT_MS = 5 * 60 * 1000;\n\nexport class GenerationService {\n /** Single-status-read primitive; overridable so the client can make it fallback-aware. */\n private readonly pollOnce: (historyId: string) => Promise<HistoryItem>;\n\n constructor(\n private readonly http: HttpClient,\n private readonly auth: AuthManager,\n private readonly target: Target,\n pollOnce?: (historyId: string) => Promise<HistoryItem>,\n ) {\n // Arrow captures `this` lazily so the default works regardless of field-init order.\n this.pollOnce = pollOnce ?? ((id) => this.getHistory(id));\n }\n\n /** Submit an image generation job and return its `historyId`. */\n async submit(opts: GenerateOptions): Promise<{ historyId: string }> {\n const config: ArchitectureConfig = {\n seed: opts.seed ?? null,\n prompt: opts.prompt,\n model_id: opts.model ?? 'mango-v3-pro',\n fast_mode: opts.fastMode ?? false,\n resolution: opts.resolution ?? '1K',\n architecture: opts.architecture ?? 'mango',\n aspect_ratio: opts.aspectRatio ?? 'portrait',\n image: opts.image ?? UNDEFINED,\n additional_images: opts.additionalImages ?? [],\n characters: mapCharacters(opts.characters),\n references: mapCharacters(opts.references),\n audio_references: [],\n moodboard: UNDEFINED,\n };\n return this.runArchitecture(config, opts.conceptId ?? DEFAULT_CONCEPT_ID, opts.generationMode);\n }\n\n /** Submit a video generation job (Berry-2 family) and return its `historyId`. */\n async submitVideo(opts: GenerateVideoOptions): Promise<{ historyId: string }> {\n const config: VideoArchitectureConfig = {\n seed: opts.seed ?? null,\n prompt: opts.prompt,\n model_id: opts.model ?? 'berry-2',\n fast_mode: opts.fastMode ?? false,\n resolution: opts.resolution ?? '480p',\n architecture: opts.architecture ?? 'berry',\n berry_aspect_ratio: opts.aspectRatio ?? '9:16',\n duration: opts.duration ?? '3',\n image: opts.image ?? UNDEFINED,\n additional_images: opts.additionalImages ?? [],\n characters: mapCharacters(opts.characters),\n references: mapCharacters(opts.references),\n audio_references: [],\n };\n return this.runArchitecture(\n config,\n opts.conceptId ?? DEFAULT_BERRY_CONCEPT_ID,\n opts.generationMode,\n );\n }\n\n /** Shared `runArchitecture` call for image and video configs. */\n private async runArchitecture(\n config: ArchitectureConfig | VideoArchitectureConfig,\n conceptId: string,\n generationMode: GenerationMode = 'unlimited',\n ): Promise<{ historyId: string }> {\n const [authToken, session] = await Promise.all([\n this.auth.getIdToken(),\n this.auth.getSession(),\n ]);\n\n const args = [\n {\n architectureConfig: config,\n architectureConfigToSave: '$0:0:architectureConfig',\n authToken,\n conceptId,\n activePowerPack: null,\n generationMode,\n },\n ];\n\n const { data } = await this.http.callAction<Record<string, unknown>>({\n action: resolveActionName(this.target, 'submitGeneration'),\n path: GENERATION_PATH,\n args,\n session,\n });\n\n if (data !== null && typeof data === 'object' && 'error_code' in data) {\n const code = Number(data.error_code);\n throw new GenerationError(errorMessageForCode(code), code);\n }\n const historyId = data !== null && typeof data === 'object' ? data.history_id : undefined;\n if (typeof historyId !== 'string') {\n throw new GenerationError('runArchitecture did not return a history_id');\n }\n return { historyId };\n }\n\n /** Fetch a single history record by id, dispatching on the target's poll strategy. */\n async getHistory(historyId: string): Promise<HistoryItem> {\n if (this.target.pollStrategy === 'paginated') {\n return this.getHistoryPaginated(historyId);\n }\n const session = await this.auth.getSession();\n const { data } = await this.http.callAction<HistoryItem>({\n action: resolveActionName(this.target, 'getHistoryById'),\n path: GENERATION_PATH,\n args: [historyId],\n session,\n });\n return data;\n }\n\n /**\n * Beta status read: `getHistoryById` is absent, so page `getHistoryPaginated`\n * and find the item whose `id === historyId`.\n *\n * @remarks\n * ASSUMED (pending docs/api/beta): each page window is swept in two phases —\n * `running` first, then the raw `$undefined` sentinel (terminal items) — since\n * which filter surfaces a running job on beta is not yet documented. Bounded by\n * {@link PAGINATED_POLL_MAX_PAGES} pages of {@link PAGINATED_POLL_PAGE_SIZE}.\n */\n private async getHistoryPaginated(historyId: string): Promise<HistoryItem> {\n const uid = await this.auth.getUserId();\n const limit = PAGINATED_POLL_PAGE_SIZE;\n let offset = 0;\n for (let pageIndex = 0; pageIndex < PAGINATED_POLL_MAX_PAGES; pageIndex += 1) {\n // Phase 1: running jobs; Phase 2: terminal (no status filter).\n for (const status of ['running', UNDEFINED]) {\n const page = await this.fetchHistoryPage(uid, status, limit, offset);\n const found = page.histories.find((h) => h.id === historyId);\n if (found !== undefined) {\n return found;\n }\n if (status === UNDEFINED && !page.hasMore) {\n throw new GenerationError(`history ${historyId} not found on beta`);\n }\n }\n offset += limit;\n }\n throw new GenerationError(`history ${historyId} not found on beta`);\n }\n\n /** Fetch one page of history via `listHistory` (resolved per target) on `/creations`. */\n private async fetchHistoryPage(\n uid: string,\n status: string,\n limit: number,\n offset: number,\n ): Promise<HistoryPage> {\n const session = await this.auth.getSession();\n const filters = { status, type: UNDEFINED };\n const { data } = await this.http.callAction<HistoryPage>({\n action: resolveActionName(this.target, 'listHistory'),\n path: HISTORY_PATH,\n args: [uid, limit, offset, filters],\n session,\n });\n return unwrapResult<HistoryPage>(data);\n }\n\n /** Cancel a running generation job. */\n async cancelJob(historyId: string): Promise<void> {\n const session = await this.auth.getSession();\n await this.http.callAction({\n action: resolveActionName(this.target, 'cancelJob'),\n path: GENERATION_PATH,\n args: [historyId],\n session,\n });\n }\n\n /** Poll until the job leaves the `running` state, returning the final record. */\n async waitForResult(historyId: string, opts: WaitOptions = {}): Promise<HistoryItem> {\n const intervalMs = opts.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;\n const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const deadline = Date.now() + timeoutMs;\n\n for (;;) {\n if (opts.signal?.aborted === true) {\n throw new TimeoutError('waitForResult was aborted');\n }\n const item = await this.pollOnce(historyId);\n if (item.status === 'success') {\n return item;\n }\n if (item.status === 'error') {\n throw new GenerationError(`Generation failed: ${JSON.stringify(item.error ?? null)}`);\n }\n if (Date.now() > deadline) {\n throw new TimeoutError(\n `Generation timed out after ${timeoutMs}ms (last status: ${item.status})`,\n );\n }\n await delay(intervalMs, opts.signal);\n }\n }\n}\n\nfunction delay(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const timer = setTimeout(resolve, ms);\n signal?.addEventListener(\n 'abort',\n () => {\n clearTimeout(timer);\n reject(new TimeoutError('waitForResult was aborted'));\n },\n { once: true },\n );\n });\n}\n\n/** Normalize characters for an `architectureConfig`, defaulting absent audio to the RSC sentinel. */\nfunction mapCharacters(characters: CharacterRef[] = []): CharacterRef[] {\n return characters.map((c) => ({\n id: c.id,\n name: c.name,\n username: c.username,\n image_url: c.image_url,\n audio_url: c.audio_url ?? UNDEFINED,\n }));\n}\n\nfunction errorMessageForCode(code: number): string {\n switch (code) {\n case 400:\n return 'Bad request (wrong generationMode for your subscription tier?)';\n case 401:\n return 'Authentication failed (token expired or invalid)';\n case 403:\n return 'User is banned';\n case 4031:\n return 'Prompt blocked by content moderation';\n default:\n return `Generation error (code ${code})`;\n }\n}\n","/** Generation history listing via `getHistoryPaginated`. */\nimport type { AuthManager } from './auth.js';\nimport { requireConfirm } from './errors.js';\nimport type { HttpClient } from './http.js';\nimport { unwrapResult } from './rsc.js';\nimport { resolveActionName, type Target } from './targets.js';\nimport type {\n ConfirmOptions,\n CreationPage,\n GenerationResult,\n HistoryPage,\n ListCreationsOptions,\n ListHistoryOptions,\n} from './types.js';\n\n/** History actions are served from the `/creations` page. */\nconst HISTORY_PATH = '/creations';\nconst DEFAULT_LIMIT = 10;\n/** RSC sentinel for an absent value. */\nconst UNDEFINED = '$undefined';\n\nexport class HistoryService {\n constructor(\n private readonly http: HttpClient,\n private readonly auth: AuthManager,\n private readonly target: Target,\n ) {}\n\n /** List generation history for the authenticated user. */\n async list(opts: ListHistoryOptions = {}): Promise<HistoryPage> {\n const [uid, session] = await Promise.all([this.auth.getUserId(), this.auth.getSession()]);\n const limit = opts.limit ?? DEFAULT_LIMIT;\n const offset = opts.offset ?? 0;\n const status = opts.status === 'all' ? UNDEFINED : (opts.status ?? 'success');\n const filters = { status, type: UNDEFINED };\n\n const { data } = await this.http.callAction<HistoryPage>({\n action: resolveActionName(this.target, 'listHistory'),\n path: HISTORY_PATH,\n args: [uid, limit, offset, filters],\n session,\n });\n return unwrapResult<HistoryPage>(data);\n }\n\n /** List the user's permanently saved creations. */\n async listCreations(opts: ListCreationsOptions = {}): Promise<CreationPage> {\n const [uid, session] = await Promise.all([this.auth.getUserId(), this.auth.getSession()]);\n const limit = opts.limit ?? DEFAULT_LIMIT;\n const offset = opts.offset ?? 0;\n const { data } = await this.http.callAction<CreationPage>({\n action: resolveActionName(this.target, 'listCreations'),\n path: HISTORY_PATH,\n args: [uid, limit, offset],\n session,\n });\n return unwrapResult<CreationPage>(data);\n }\n\n /**\n * Save a completed generation result as a permanent creation.\n *\n * @param result - the `result` object of a completed history item.\n * @remarks The API returns no body; call {@link listCreations} to retrieve the\n * saved creation.\n */\n async saveCreation(result: GenerationResult): Promise<void> {\n const session = await this.auth.getSession();\n await this.http.callAction({\n action: 'saveCreation',\n path: HISTORY_PATH,\n args: [result],\n session,\n });\n }\n\n /**\n * Permanently delete a history item. Irreversible — requires `{ confirm: true }`.\n */\n async deleteHistory(historyId: string, opts?: ConfirmOptions): Promise<void> {\n requireConfirm('deleteHistory', opts);\n const session = await this.auth.getSession();\n await this.http.callAction({\n action: 'deleteHistory',\n path: HISTORY_PATH,\n args: [historyId],\n session,\n });\n }\n\n /**\n * Permanently delete many history items. Irreversible — requires `{ confirm: true }`.\n *\n * @experimental Request body inferred from JS bundle; not yet verified live.\n */\n async deleteManyHistories(historyIds: string[], opts?: ConfirmOptions): Promise<void> {\n requireConfirm('deleteManyHistories', opts);\n const session = await this.auth.getSession();\n await this.http.callAction({\n action: 'deleteManyHistories',\n path: HISTORY_PATH,\n args: [historyIds],\n session,\n });\n }\n\n /**\n * Permanently delete a saved creation. Irreversible — requires `{ confirm: true }`.\n */\n async deleteCreation(creationId: string, opts?: ConfirmOptions): Promise<void> {\n requireConfirm('deleteCreation', opts);\n const session = await this.auth.getSession();\n await this.http.callAction({\n action: 'deleteCreation',\n path: HISTORY_PATH,\n args: [creationId],\n session,\n });\n }\n\n /**\n * Permanently delete many creations. Irreversible — requires `{ confirm: true }`.\n *\n * @experimental Request body inferred from JS bundle; not yet verified live.\n */\n async deleteManyCreations(creationIds: string[], opts?: ConfirmOptions): Promise<void> {\n requireConfirm('deleteManyCreations', opts);\n const session = await this.auth.getSession();\n await this.http.callAction({\n action: 'deleteManyCreations',\n path: HISTORY_PATH,\n args: [creationIds],\n session,\n });\n }\n}\n","/**\n * Reference asset management.\n *\n * References are reusable image/audio assets (generic references, objects,\n * outfits, poses) applied across generations — distinct from characters, which\n * are trained identities. Covers upload, create, update, and listing (own +\n * public feed) per `docs/api/references.md`.\n */\nimport type { AuthManager } from './auth.js';\nimport { MageSpaceError, requireConfirm } from './errors.js';\nimport type { HttpClient } from './http.js';\nimport type {\n ConfirmOptions,\n CreateReferenceInput,\n ListReferencesOptions,\n Modality,\n Reference,\n ReferencePage,\n UpdateReferenceInput,\n} from './types.js';\n\n/** Server-enforced username constraints (shared with characters, module 64428). */\nconst USERNAME_MAX = 15;\nconst USERNAME_RE = /^[a-z][a-z0-9_-]*$/;\n\n/** Generate a username from a display name (same logic as characters). */\nfunction generateUsername(name: string): string {\n const suffix = Math.random().toString(36).substring(2, 6);\n const base = name\n .toLowerCase()\n .trim()\n .replace(/[^a-z0-9\\s]/g, '')\n .replace(/\\s+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '');\n const maxBase = USERNAME_MAX - suffix.length - 1;\n const trimmedBase = base.slice(0, maxBase).replace(/[-_]+$/, '');\n return `${trimmedBase}-${suffix}`;\n}\n\nfunction validateUsername(username: string): void {\n if (username.length > USERNAME_MAX) {\n throw new MageSpaceError(\n `Username \"${username}\" is too long (${username.length} chars, max ${USERNAME_MAX})`,\n );\n }\n if (!USERNAME_RE.test(username)) {\n throw new MageSpaceError(\n `Username \"${username}\" is invalid: must start with a lowercase letter and contain only a-z, 0-9, _ or -`,\n );\n }\n}\n\n/** Reference actions are served from the `/explore` page. */\nconst REFERENCES_PATH = '/explore';\nconst DEFAULT_PAGE_LIMIT = 20;\n\nexport class ReferencesService {\n constructor(\n private readonly http: HttpClient,\n private readonly auth: AuthManager,\n ) {}\n\n /**\n * Upload a reference image (base64 data URL) and return its CDN URL.\n *\n * @param dataUrl - `data:image/jpeg;base64,...` (JPEG preferred; PNG/WebP ok).\n */\n async uploadImage(dataUrl: string): Promise<string> {\n const [uid, session] = await Promise.all([this.auth.getUserId(), this.auth.getSession()]);\n const { data } = await this.http.callAction<string>({\n action: 'uploadReferenceImage',\n path: REFERENCES_PATH,\n args: [dataUrl, uid],\n session,\n });\n return data;\n }\n\n /** Create a reusable reference from an uploaded image/audio URL. */\n async create(input: CreateReferenceInput): Promise<Reference> {\n const username = input.username ?? generateUsername(input.name);\n validateUsername(username);\n const session = await this.auth.getSession();\n const body = {\n name: input.name,\n username,\n image_url: input.image_url,\n audio_url: input.audio_url ?? null,\n modality: input.modality ?? 'image',\n variant: input.variant ?? 'reference',\n description: input.description ?? null,\n tags: input.tags ?? [],\n visibility: input.visibility ?? 'private',\n moderation: input.moderation ?? [],\n };\n const { data } = await this.http.callAction<Reference>({\n action: 'createReference',\n path: REFERENCES_PATH,\n args: [body],\n session,\n });\n return data;\n }\n\n /** Update a reference's mutable fields (name, description, tags, visibility). */\n async update(id: string, patch: UpdateReferenceInput): Promise<Reference> {\n const session = await this.auth.getSession();\n const { data } = await this.http.callAction<Reference>({\n action: 'updateReference',\n path: REFERENCES_PATH,\n args: [id, patch],\n session,\n });\n return data;\n }\n\n /**\n * Permanently delete a reference (soft-delete). Irreversible — requires\n * `{ confirm: true }`.\n */\n async delete(id: string, opts?: ConfirmOptions): Promise<void> {\n requireConfirm('deleteReference', opts);\n const session = await this.auth.getSession();\n await this.http.callAction({\n action: 'deleteReference',\n path: REFERENCES_PATH,\n args: [id],\n session,\n });\n }\n\n /** List the caller's own references for a given modality (default `image`). */\n async list(modality: Modality = 'image'): Promise<Reference[]> {\n const [uid, session] = await Promise.all([this.auth.getUserId(), this.auth.getSession()]);\n const { data } = await this.http.callAction<Reference[]>({\n action: 'getReferences',\n path: REFERENCES_PATH,\n args: [uid, modality],\n session,\n });\n return data ?? [];\n }\n\n /**\n * Browse references with pagination.\n *\n * @remarks\n * Omit `uid` to browse the public/featured feed; pass it to page through a\n * single user's references.\n */\n async listPaginated(opts: ListReferencesOptions = {}): Promise<ReferencePage> {\n const session = await this.auth.getSession();\n const limit = opts.limit ?? DEFAULT_PAGE_LIMIT;\n const offset = opts.offset ?? 0;\n const filters: Record<string, unknown> = {\n visibility: opts.visibility ?? 'public',\n orderBy: opts.orderBy ?? 'top',\n featuredOnly: opts.featuredOnly ?? false,\n modality: opts.modality ?? 'image',\n };\n if (opts.uid !== undefined) {\n filters.uid = opts.uid;\n }\n const { data } = await this.http.callAction<ReferencePage>({\n action: 'getReferencesPaginated',\n path: REFERENCES_PATH,\n args: [limit, offset, filters],\n session,\n });\n return data;\n }\n}\n","import type { ActionSnapshot } from './types.js';\n\n/**\n * Bundled action-hash snapshot from the mage.space Vercel deploy discovered on\n * 2026-08-24 (`docs/api/actions.md`).\n *\n * @remarks\n * Used as a warm seed so the very first call does not pay the discovery cost.\n * Hashes change on every deploy; when one goes stale the client re-discovers\n * automatically (404 → invalidate → refresh).\n */\nexport const SEED_SNAPSHOT: ActionSnapshot = {\n deploymentId: 'dpl_2w2igPYTRJKeDaX6iAUMbGwDEWZC',\n discoveredAt: Date.parse('2026-08-24T13:15:00.000Z'),\n hashes: {\n createUserSession: '60b45776be93d57b1f43deaf8d6f9a837c6b9c169b',\n deleteUserSession: '0044441bb36afa0ba15ca13c4cf3a831ac81108c7a',\n getUserHydrationData: '40b253dcab658b78ba3673c5244f96578f22d65606',\n runArchitecture: '40c4d7d5e695e1a2e2992174b75562ef5df377b206',\n getHistoryById: '4042bfb22d370cd4e3f0f41812e826a63c179cb8a8',\n cancelArchitectureJob: '401dc98670483cb67cc9b1b6a623c4fa7cb71348a2',\n cancelAllRunningArchitectureJobs: '0004b976add66997b6518bd2d25f04444b8df4e3b2',\n getMentionSuggestionsParallel: '7fe1156be29ed3824514220877818246e7649234fa',\n createCharacter: '401ceece486398904b9ba48daa7fc0ac951fb72168',\n updateCharacter: '6057ae8c4ae8868e3a4b045845814b0689ac61a1e0',\n deleteCharacter: '4071b6010bffdf242150e0322cd0966463268414d8',\n getCharacter: '40ce38eb438c78fa51ee09be911ba0c3b02d7cbcad',\n getCharacters: '40c74f795b040ec3d0841360b532eb938932fc4bc3',\n getCharactersPaginated: '709855baaecec89ad7b73ca44621fe93dfd93fcdee',\n publishCharacter: '40b489876c75c1cd836a108742da4753fb2f671565',\n unpublishCharacter: '40c785b54f5c25bd50cfaebc6817f9d0b9f5e6e145',\n uploadCharacterImage: '60ef3377c68f0cf34c60646d9356e622a9230a68e5',\n uploadReferenceImage: '60c497b22c1b65f8a4e78055c5d9e0c2bc49e2c7bd',\n createReference: '403a057e1bd8967b3bb728df1722019d14ca7c4e14',\n updateReference: '60819ffb5ec61122bc4dd52b2232fd486a155d23c6',\n deleteReference: '409098eedd49e49ac5f0275d8af9c70a0988e9859c',\n getReferences: '605e5d2876598666c4681f8f08f4ecbe7488d1762d',\n getReferencesPaginated: '702382e902dbe43b4343265b6a251c30b878eae08a',\n getCreationsPaginatedParallel: '7f5eb618ca5c4c243c51a04c5dea108aefe8aa37d2',\n getHistoryPaginated: '7817d35897de571dfa2c6c525ee7bff73ba6d590d6',\n clearUserHistory: '4038b8e21b2e6eac7c78c076ef04f1db91718cfd69',\n deleteHistory: '40f4de31887560f79274b13f8abd3a282f6c3321f7',\n deleteManyHistories: '4006a9773613e8ea05421e6f2c91fe6417fe33d892',\n deleteCreation: '40ceaf58a77a287e3146d5792b147dba9df5ec0257',\n deleteManyCreations: '4092a1e1531442421916268184300f37a4478900ed',\n saveCreation: '60860eb37a9862d41d7b92af9bbe572652e076bc43',\n saveManyCreations: '400f59bf4b0ce788050b25259aecc9bf7839f8ba11',\n generateCharacterVoice: '60b54e75a5c3de2b0e4df7ebec5cf6ef1aaeb2ed35',\n followCharacter: '403b46c309f4239df7579c00654881afd855fc1757',\n unfollowCharacter: '400dd84b2d0f2f582df6c72092ea5249678b68d4d5',\n getFilteredCharacterIds: '403b8603d61033bbe1c30c9d1c12133b9ed4e16348',\n getFilteredReferenceIds: '40a87aa0793c102e72b7858e1024c0c2f01c96a720',\n getConceptsParallel: '7f5cf8a4696938e3a148c3c293922fbcd0f8cdbd08',\n getConcept: '408caa15371b2240267a5521c4130fefcff4ba515d',\n getModel: '40f88ee2580ed9a6ae6ff3bf6ec5840b22946dbba3',\n getModels: '70fbe28eadea3cb6d563b1f5bf50c2ad179535e6e8',\n getArticlesParallel: '7f743849b6ddf8eeb21eefceb2b93c93b6d19f203f',\n searchUsersParallel: '7ff9c981309e38b9efb215d0943b34380401a93362',\n getEmbeddingParallel: '7fa14c0b84ee996caad1a598bc2b021bd9545a3383',\n getLatestPublishedArticleCached: '7f0e2eb3e1407b27b2cc338235134b3fbf25c88ddc',\n hasPurchasedGemsParallel: '7f223962cad80e4dbdd3df7dc2039f65a42c461d87',\n syncStripeSubscriptionParallel: '7f19bb611b725a3cb8d99dc5d72ab11e0595087f6e',\n getSubscriptionPlayUsage: '40c9d7d3d029eee45885df18797dbca20315ff4fca',\n saveContentSettings: '4095ebf4d1b43894777ef2e3e06b9a556275fafcf0',\n deleteUser: '40692c054de95018353e0c8512082f6f9103cac6d7',\n getMyUserMembership: '007ce34998f2bf4f19be3cf46e3cfcb387110ae5d5',\n getActiveUserBan: '60e4352df1676fbe169421c5709479f1534cccb371',\n getCreditBalance: '009364b01be29ea5b25711fff2c6284af88caa4e4c',\n getCreditBalanceBreakdown: '00ddc14328cf19e8fbec823474a7169214cfd30603',\n getActivePowerPack: '00a6404083c8958fcd47607a088c1d1a7a5dfd4514',\n getUnusedPowerPacks: '00b5d80d96598fc2db4641fff117cfa47b37f2482f',\n getPowerPackStatsById: '4027b533e8532d2f35cbbb7518160d7569b738cb20',\n getLastGemPurchaseType: '008f0fb3448464f9f0e5ac2b6b15fc5fb59d8ccce4',\n getCheckoutUrlWithStripeDirect: '7c0f0773c703de16b1abe5f869c2164108473c5820',\n getPortalUrlWithStripeDirect: '60655cb929f6eb281aef8c25311806cfaed5aeb8af',\n removeInactiveSubscriptions: '00b5b012ef33665bb3cdf3f8e931483a0d8dc96461',\n hasCreatedImageReference: '002876b36888ccf790e8e5b9413ae951d07594a4c3',\n createLink: '40ffeee6dd712d83ce286aa22d07446822adb5ec02',\n tempToPermanentFile: '40f30eb9909274b48fa7654e7648cdf188bf3e015d',\n uploadTempCreationImage: '60f0c8b2c98566eb131e69ec1e8ee95c78ad4c332f',\n uploadUserImage: '604d67807ffec2bcdaf936e03c27c7fcc8e49880f8',\n getUserAudioUploadUrl: '7019e155efbd5aa4eb2200a48d6f7265cf6aa686e9',\n getUserVideoUploadUrl: '70cab2e17fe2c04a964489850642235ada2cb0adf3',\n processVideoFromUrl: '70901405c8bff0dcb9ea40053f1176caeb1b99ae4c',\n processAudio: '60bd5fa2fd7c30e53ef2a22342408ed1aab0a766a7',\n segmentImage: '40d827c38726f2d2bbc559f94eafe0f1fc84b50e70',\n moderateMedia: '403006c99a6b3cd6e684c163e0df35f44e403f7ca7',\n checkSharedUsernameAvailable: '6000cca07091fb38d8a77fad195b95b2ea73634895',\n getCreationTagCountsParallel: '7f0f20d7a26711c076aefeb73e65273ac1572381d8',\n updateCreations: '4055ce23f7e1fac54bfceb33b816f9574b82d2127d',\n getCreationsPaginated: '780d8f5e01f24e1342e5e4a475321123eb156dcf2a',\n resolveMoodboardRuntimeSelection: '40080c3021ac4c02f675c25a7443b03ee96e57837a',\n saveProfileCollections: '4071958ca110ab37fe59be3b019bfc39b1fa0c9143',\n banUser: '70c46c18b6223613cee3a4f17ce076672f29a6bba5',\n undoTemporaryBanUser: '40199a810acd4149e53fc182ba1ff9e8a7dde19283',\n temporaryBanUser: '788b8a43fb42b87cd942e3d0229307bea6497ef8e9',\n getCharacterFollowStatus: '40d220eb13610f029b46bbcfc7c9117478b3b738f2',\n reportCharacter: '400525e8101daa2496bad7a7c7e91c5cca00d574c2',\n toggleFeatureCharacter: '40a640496a2e6bf7cb124405c74f8a928aeccbf964',\n getSiteAlertParallel: '7f382e755e1d8d7670272b36656280dd661aa9abce',\n getChatsParallel: '7f741bb8b517b0ba95f6b941ab1ce0efcb870341f6',\n getChatMessages: '40f8886c57d93aae7265d1805af5765589e2be7d15',\n markChatRead: '408c569fdaa0d2ab12e0b8019cf661a99c9d182f68',\n getPostMediaFeedParallel: '7f9ce48dd331eb4103e9d2d18b23b6008e3bf5c502',\n createAutoCreationCampaign: '404c84350ce7aba35a332ab3129334ed19cfb107fd',\n },\n};\n","/**\n * Internal HTTP client for Next.js Server Action calls.\n *\n * Every call is a `POST` to a page path with a `next-action` header carrying the\n * action hash, a JSON-array body, and an RSC response that is parsed into the\n * action's return value. A 404 is treated as a stale hash: the registry is\n * invalidated and the call is retried once against freshly discovered hashes.\n */\nimport type { ActionRegistry } from './actions.js';\nimport { ActionUnavailableError, MageSpaceError } from './errors.js';\nimport { parseServerActionResponse } from './rsc.js';\nimport type { FetchLike } from './types.js';\n\nconst DEFAULT_USER_AGENT =\n 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ' +\n '(KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36';\n\n/**\n * HTTP statuses that mean \"this action is unavailable on this host\". A stale\n * (post-deploy) action hash surfaces as a 404 on the production host and as a\n * 409 (\"Server Action unavailable\") on the beta host — both mean the same\n * thing: invalidate the registry, re-discover, and (if still unavailable) fall\n * back to the next host.\n */\nconst UNAVAILABLE_STATUSES = new Set([404, 409]);\n\n/**\n * Known RSC error digests mapped to human-readable messages.\n * Discovered via reverse engineering; the server does not expose error details.\n */\nconst KNOWN_DIGESTS: Record<string, string> = {\n '709776019': 'Username already taken (duplicate character/reference username)',\n '1853426377':\n 'Invalid username (must be 1–15 lowercase chars, start with a letter, only a-z 0-9 _ -)',\n};\n\nexport interface CallActionParams {\n /** Server Action function name (resolved to a hash via the registry). */\n action: string;\n /** Page path to POST to (e.g. `/explore`, `/creations`). */\n path: string;\n /** Request body — always a JSON array of arguments. */\n args: unknown[];\n /** `__session` cookie value for authenticated actions. */\n session?: string;\n}\n\nexport interface CallActionResult<T> {\n data: T;\n headers: Headers;\n deploymentId: string;\n}\n\nexport class HttpClient {\n constructor(\n private readonly registry: ActionRegistry,\n private readonly fetchImpl: FetchLike,\n private readonly baseUrl: string,\n private readonly targetKey: string,\n private readonly userAgent: string = DEFAULT_USER_AGENT,\n ) {}\n\n /** A response that means the action is unavailable (stale hash or gone). */\n private isUnavailable(res: Response): boolean {\n const contentType = res.headers.get('content-type') ?? '';\n const isHtmlFallback = res.ok && contentType.includes('text/html');\n return UNAVAILABLE_STATUSES.has(res.status) || isHtmlFallback;\n }\n\n async callAction<T = unknown>(\n params: CallActionParams,\n retried = false,\n ): Promise<CallActionResult<T>> {\n const { hash, deploymentId } = await this.registry.getHash(params.action);\n\n const headers: Record<string, string> = {\n accept: 'text/x-component',\n 'content-type': 'text/plain;charset=UTF-8',\n 'next-action': hash,\n 'x-deployment-id': deploymentId,\n origin: this.baseUrl,\n referer: `${this.baseUrl}${params.path}`,\n 'user-agent': this.userAgent,\n };\n if (params.session !== undefined) {\n headers.cookie = `__session=${params.session}`;\n }\n\n const res = await this.fetchImpl(`${this.baseUrl}${params.path}`, {\n method: 'POST',\n headers,\n body: JSON.stringify(params.args),\n });\n\n // A stale (post-deploy) hash surfaces as a 404 OR as a 200 with HTML\n // (Next.js returns the page shell instead of the RSC action response).\n if (this.isUnavailable(res) && !retried) {\n // Consume the body to prevent socket leaks.\n await safeText(res);\n await this.registry.invalidate();\n return this.callAction<T>(params, true);\n }\n // A retried response that is still unavailable means the action is gone from\n // this host — a definitive, host-level signal the client treats as a\n // fallback trigger (distinct from a transient stale hash).\n if (this.isUnavailable(res)) {\n await safeText(res);\n throw new ActionUnavailableError(params.action, this.targetKey);\n }\n if (!res.ok) {\n const body = await safeText(res);\n // RSC error rows look like: `1:E{\"digest\":\"...\"}` — extract the digest when possible.\n const rscErrorMatch = body.match(/E\\{\"digest\":\"([^\"]+)\"\\}/);\n const digest = rscErrorMatch?.[1];\n const knownDigest = digest !== undefined ? KNOWN_DIGESTS[digest] : undefined;\n const hint = knownDigest ? ` — ${knownDigest}` : digest ? ` (server digest: ${digest})` : '';\n const raw = body.length > 0 ? ` — ${body.slice(0, 200)}` : '';\n throw new MageSpaceError(`Action \"${params.action}\" failed: HTTP ${res.status}${hint}${raw}`);\n }\n\n const text = await res.text();\n const data = parseServerActionResponse<T>(text);\n return {\n data,\n headers: res.headers,\n deploymentId: res.headers.get('x-deployment-id') ?? deploymentId,\n };\n }\n}\n\nasync function safeText(res: Response): Promise<string> {\n try {\n return await res.text();\n } catch {\n return '';\n }\n}\n","/**\n * A {@link TargetContext} bundles one host's {@link ActionRegistry} and\n * {@link HttpClient} so the client can hold one pair per target and switch by\n * selecting the other pair (rather than mutating a shared `baseUrl`).\n */\nimport { ActionRegistry, InMemoryActionCache } from './actions.js';\nimport { HttpClient } from './http.js';\nimport type { Target } from './targets.js';\nimport type { ActionCache, ActionSnapshot, FetchLike } from './types.js';\n\n/** The per-host registry + HTTP client bound to a single {@link Target}. */\nexport interface TargetContext {\n readonly target: Target;\n readonly registry: ActionRegistry;\n readonly http: HttpClient;\n}\n\n/** Dependencies shared across every target context the client builds. */\nexport interface TargetContextDeps {\n fetch: FetchLike;\n userAgent?: string;\n /** Caller-supplied cache — used for the production target only. */\n cache?: ActionCache;\n /** Production seed snapshot — passed to the production target only. */\n seed?: ActionSnapshot;\n}\n\n/**\n * Build the registry + HTTP client for a single target.\n *\n * @remarks\n * The caller's `cache` and the production `seed` are production-only concerns:\n * the bundled seed holds production hashes and the single-slot cache cannot be\n * namespaced per host. Non-production targets always discover fresh with their\n * own {@link InMemoryActionCache} and no seed.\n */\nexport function createTargetContext(target: Target, deps: TargetContextDeps): TargetContext {\n const isProduction = target.key === 'production';\n const registry = new ActionRegistry({\n fetch: deps.fetch,\n baseUrl: target.baseUrl,\n cache: isProduction ? deps.cache : new InMemoryActionCache(),\n seed: isProduction ? deps.seed : undefined,\n });\n const http = new HttpClient(registry, deps.fetch, target.baseUrl, target.key, deps.userAgent);\n return { target, registry, http };\n}\n","/**\n * {@link MageSpaceClient} — the public facade that wires together action\n * discovery, authentication, generation, and history.\n *\n * The client models each mage.space host as a {@link Target} and holds an\n * ordered chain (production first, then beta). When the active host can no\n * longer serve a required action, the client advances to the next target and\n * retries once. The switch is sticky for the lifetime of the instance.\n */\nimport { AuthManager } from './auth.js';\nimport { CharactersService } from './characters.js';\nimport { ActionUnavailableError, DiscoveryError } from './errors.js';\nimport { GenerationService } from './generation.js';\nimport { HistoryService } from './history.js';\nimport { ReferencesService } from './references.js';\nimport { SEED_SNAPSHOT } from './seed.js';\nimport { createTargetContext, type TargetContext } from './target-context.js';\nimport { DEFAULT_TARGET_CHAIN, type Target, type TargetKey } from './targets.js';\nimport type {\n ActionSnapshot,\n ConfirmOptions,\n CreationPage,\n FetchLike,\n GenerateOptions,\n GenerateVideoOptions,\n GenerationResult,\n HistoryItem,\n HistoryPage,\n ListCreationsOptions,\n ListHistoryOptions,\n MageSpaceClientOptions,\n WaitOptions,\n} from './types.js';\n\n/** Generation + history services bound to one active {@link Target}. */\ninterface ServiceBundle {\n target: Target;\n generationService: GenerationService;\n historyService: HistoryService;\n}\n\nexport class MageSpaceClient {\n private readonly auth: AuthManager;\n private readonly chain: readonly Target[];\n private readonly auto: boolean;\n private readonly contextDeps: {\n fetch: FetchLike;\n userAgent?: string;\n cache?: MageSpaceClientOptions['cache'];\n seed?: ActionSnapshot;\n };\n private readonly contexts: Map<TargetKey, TargetContext> = new Map();\n private activeIndex: number;\n private activeContext: TargetContext;\n private activeBundle: ServiceBundle;\n\n /**\n * Character management (search, CRUD, pagination, uploads).\n *\n * @remarks\n * Bound to the initial host (production by default) and does not follow an\n * automatic beta fallback. Construct a client with `fallback: { start: 'beta' }`\n * to use these against beta.\n */\n readonly characters: CharactersService;\n\n /**\n * Reference asset management (upload, create, update, list, feed).\n *\n * @remarks\n * Bound to the initial host (production by default) and does not follow an\n * automatic beta fallback. Construct a client with `fallback: { start: 'beta' }`\n * to use these against beta.\n */\n readonly references: ReferencesService;\n\n constructor(options: MageSpaceClientOptions) {\n if (!options.refreshToken) {\n throw new Error('MageSpaceClient requires a refreshToken');\n }\n\n const fetchImpl: FetchLike = options.fetch ?? ((input, init) => fetch(input, init));\n const fallback = options.fallback;\n const baseUrlPinned = typeof options.baseUrl === 'string' && options.baseUrl.length > 0;\n\n // `baseUrl` pins a single host and is incompatible with fallback tuning.\n if (\n baseUrlPinned &&\n fallback !== undefined &&\n (fallback.chain !== undefined || fallback.start !== undefined || fallback.auto !== undefined)\n ) {\n throw new Error('baseUrl pins a single host and cannot be combined with fallback options');\n }\n\n if (baseUrlPinned) {\n // Collapse to a single synthetic target reproducing today's single-host behaviour.\n this.chain = [\n {\n key: 'production',\n baseUrl: options.baseUrl as string,\n actionNames: {},\n pollStrategy: 'byId',\n },\n ];\n this.auto = false;\n } else {\n const chain = fallback?.chain ?? DEFAULT_TARGET_CHAIN;\n if (chain.length === 0) {\n throw new Error('fallback.chain must be a non-empty array');\n }\n this.chain = chain;\n this.auto = fallback?.auto ?? true;\n }\n\n const startKey = baseUrlPinned ? 'production' : (fallback?.start ?? 'production');\n const startIndex = this.chain.findIndex((t) => t.key === startKey);\n if (startIndex === -1) {\n throw new Error(`fallback.start '${startKey}' is not in the target chain`);\n }\n\n this.contextDeps = {\n fetch: fetchImpl,\n userAgent: options.userAgent,\n cache: options.cache,\n seed: options.seed ?? SEED_SNAPSHOT,\n };\n\n this.activeIndex = startIndex;\n this.activeContext = this.getContext(startIndex);\n\n this.auth = new AuthManager({\n refreshToken: options.refreshToken,\n getHttp: () => this.activeContext.http,\n fetch: fetchImpl,\n firebaseApiKey: options.firebaseApiKey,\n });\n\n this.activeBundle = this.buildBundle(this.activeContext);\n\n // Sub-services bind to the INITIAL active context and are never rebuilt.\n this.characters = new CharactersService(this.activeContext.http, this.auth);\n this.references = new ReferencesService(this.activeContext.http, this.auth);\n }\n\n /** Lazily build (and memoise) the {@link TargetContext} for a chain index. */\n private getContext(index: number): TargetContext {\n const target = this.chain[index] as Target;\n const existing = this.contexts.get(target.key);\n if (existing !== undefined) {\n return existing;\n }\n const context = createTargetContext(target, this.contextDeps);\n this.contexts.set(target.key, context);\n return context;\n }\n\n /** Build the generation/history service bundle for a context. */\n private buildBundle(context: TargetContext): ServiceBundle {\n const pollOnce = (id: string): Promise<HistoryItem> =>\n this.withFallback((bundle) => bundle.generationService.getHistory(id));\n return {\n target: context.target,\n generationService: new GenerationService(context.http, this.auth, context.target, pollOnce),\n historyService: new HistoryService(context.http, this.auth, context.target),\n };\n }\n\n /** Advance to the next target (sticky). Returns `null` if none or `auto` is off. */\n private advanceTarget(): ServiceBundle | null {\n if (this.auto === false || this.activeIndex >= this.chain.length - 1) {\n return null;\n }\n this.activeIndex += 1;\n this.activeContext = this.getContext(this.activeIndex);\n this.activeBundle = this.buildBundle(this.activeContext);\n return this.activeBundle;\n }\n\n /** Whether an error is a definitive action-unavailable signal (a fallback trigger). */\n private shouldFallback(err: unknown): boolean {\n return (\n err instanceof ActionUnavailableError ||\n (err instanceof DiscoveryError && err.notFound === true)\n );\n }\n\n /** Run `op` against the active bundle, switching to the next target once on a trigger. */\n private async withFallback<T>(op: (bundle: ServiceBundle) => Promise<T>): Promise<T> {\n try {\n return await op(this.activeBundle);\n } catch (err) {\n if (!this.shouldFallback(err)) {\n throw err;\n }\n const next = this.advanceTarget();\n if (next === null) {\n throw err;\n }\n this.auth.resetSession();\n return op(this.activeBundle);\n }\n }\n\n /** Submit a generation job; returns its `historyId`. */\n generate(options: GenerateOptions): Promise<{ historyId: string }> {\n return this.withFallback((b) => b.generationService.submit(options));\n }\n\n /** Submit a video generation job (Berry-2 family); returns its `historyId`. */\n generateVideo(options: GenerateVideoOptions): Promise<{ historyId: string }> {\n return this.withFallback((b) => b.generationService.submitVideo(options));\n }\n\n /** Fetch the current state of a generation by id. */\n getResult(historyId: string): Promise<HistoryItem> {\n return this.withFallback((b) => b.generationService.getHistory(historyId));\n }\n\n /** Poll until a generation finishes (or fails / times out). */\n waitForResult(historyId: string, options?: WaitOptions): Promise<HistoryItem> {\n return this.withFallback((b) => b.generationService.waitForResult(historyId, options));\n }\n\n /** Cancel a running generation job. */\n cancelJob(historyId: string): Promise<void> {\n return this.withFallback((b) => b.generationService.cancelJob(historyId));\n }\n\n /** List past generations for the authenticated user. */\n listHistory(options?: ListHistoryOptions): Promise<HistoryPage> {\n return this.withFallback((b) => b.historyService.list(options));\n }\n\n /** List the user's permanently saved creations. */\n listCreations(options?: ListCreationsOptions): Promise<CreationPage> {\n return this.withFallback((b) => b.historyService.listCreations(options));\n }\n\n /** Save a completed generation result as a permanent creation. */\n saveCreation(result: GenerationResult): Promise<void> {\n return this.withFallback((b) => b.historyService.saveCreation(result));\n }\n\n /** Permanently delete a history item. Irreversible — requires `{ confirm: true }`. */\n deleteHistory(historyId: string, options?: ConfirmOptions): Promise<void> {\n return this.withFallback((b) => b.historyService.deleteHistory(historyId, options));\n }\n\n /** Permanently delete many history items. Irreversible — requires `{ confirm: true }`. */\n deleteManyHistories(historyIds: string[], options?: ConfirmOptions): Promise<void> {\n return this.withFallback((b) => b.historyService.deleteManyHistories(historyIds, options));\n }\n\n /** Permanently delete a saved creation. Irreversible — requires `{ confirm: true }`. */\n deleteCreation(creationId: string, options?: ConfirmOptions): Promise<void> {\n return this.withFallback((b) => b.historyService.deleteCreation(creationId, options));\n }\n\n /** Permanently delete many creations. Irreversible — requires `{ confirm: true }`. */\n deleteManyCreations(creationIds: string[], options?: ConfirmOptions): Promise<void> {\n return this.withFallback((b) => b.historyService.deleteManyCreations(creationIds, options));\n }\n\n /** Force re-discovery of the Server Action hashes on the active host. */\n refreshActions(): Promise<ActionSnapshot> {\n return this.activeContext.registry.refresh();\n }\n\n /** Return the authenticated user's Firebase uid. */\n getUid(): Promise<string> {\n return this.auth.getUserId();\n }\n\n /** Return the key of the currently active target (`'production'` or `'beta'`). */\n getActiveTarget(): TargetKey {\n return (this.chain[this.activeIndex] as Target).key;\n }\n}\n","/** Public entry point for `@zweer/mage-space-client`. */\nexport const VERSION = '0.0.0';\n\nexport type { ChunkListResult } from './actions.js';\nexport {\n ActionRegistry,\n discoverActions,\n InMemoryActionCache,\n listDiscoveryChunks,\n requiredActionsForClient,\n scrapeChunks,\n} from './actions.js';\nexport { CharactersService } from './characters.js';\nexport { MageSpaceClient } from './client.js';\nexport {\n ActionUnavailableError,\n AuthError,\n DiscoveryError,\n GenerationError,\n MageSpaceError,\n RscParseError,\n StaleActionError,\n TimeoutError,\n} from './errors.js';\nexport { ReferencesService } from './references.js';\nexport {\n parseFlightRows,\n parseServerActionResponse,\n resolveFlightValue,\n unwrapResult,\n} from './rsc.js';\nexport { SEED_SNAPSHOT } from './seed.js';\nexport type { LogicalAction, PollStrategy, Target, TargetKey } from './targets.js';\nexport {\n BETA_TARGET,\n DEFAULT_TARGET_CHAIN,\n PRODUCTION_TARGET,\n resolveActionName,\n} from './targets.js';\nexport type * from './types.js';\n"],"mappings":"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"}
|