@fias/arche-sdk 2.22.0 → 2.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/entity-ops.d.ts +3 -0
- package/dist/entity-ops.d.ts.map +1 -1
- package/dist/entity-ops.js +4 -1
- package/dist/entity-ops.js.map +1 -1
- package/dist/generated/permissions.d.ts +1 -1
- package/dist/generated/permissions.d.ts.map +1 -1
- package/dist/generated/permissions.js +2 -0
- package/dist/generated/permissions.js.map +1 -1
- package/dist/hooks.d.ts +31 -3
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +55 -5
- package/dist/hooks.js.map +1 -1
- package/dist/hooks.test.js +38 -2
- package/dist/hooks.test.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +26 -3
- package/dist/protocol.d.ts +8 -0
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +8 -0
- package/dist/protocol.js.map +1 -1
- package/dist/types.d.ts +116 -4
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/templates/default/AGENTS.md +55 -6
- package/templates/default/CLAUDE.md +55 -6
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- fias-sdk-guide-version: 2.
|
|
1
|
+
<!-- fias-sdk-guide-version: 2.24.0 -->
|
|
2
2
|
|
|
3
3
|
# FIAS Plugin Development Guide
|
|
4
4
|
|
|
@@ -551,6 +551,8 @@ function ModelPicker({ value, onChange }: { value: string; onChange: (id: string
|
|
|
551
551
|
|
|
552
552
|
Generate images using platform image models. Images are saved to the user's Fias file system and a display URL is returned.
|
|
553
553
|
|
|
554
|
+
Most images take 10–60 seconds; high quality at large sizes (the GPT Image models especially) can take several minutes, so `generate` waits up to 320 seconds before rejecting. Show progress for the whole wait (`estimatedDurationMs` from `useImageEntities` sizes it), and do not race `generate` against a shorter timeout of your own — the platform is still rendering, and bills, an image your plugin stopped waiting for.
|
|
555
|
+
|
|
554
556
|
#### Choosing an image model
|
|
555
557
|
|
|
556
558
|
The `entityId` parameter accepts three forms. **Prefer the selector forms** (`platformRecommended` / `providerRecommended`) over hardcoded entity IDs: the platform's recommendations evolve, models get retired, and a selector lets your plugin pick up the current best automatically without a code edit. Hardcoded IDs are still supported for back-compat and for cases where you want a specific model — but if the platform retires that exact entity, your plugin breaks unless the platform has registered a successor.
|
|
@@ -583,7 +585,7 @@ generate({
|
|
|
583
585
|
|
|
584
586
|
Mode values: `'text-to-image'` (baseline), `'image-to-image'` (requires `referenceImage`), `'vector'` (SVG output). Style values: `'illustration'` (stylized / digital-art) or `'photoreal'`.
|
|
585
587
|
|
|
586
|
-
**Several reference images, and output resolution.** A model whose `maxReferenceImages` (from `useImageEntities`) is more than one takes them together in `referenceImages` — Nano Banana 2 (`ent_modeldef_nano_banana_2`) takes up to 14. There is no role per image: the model reads them in order, so the prompt says which is which. `resolution` picks one of the model's `supportedResolutions`; higher costs more (`creditsPerImageByResolution`):
|
|
588
|
+
**Several reference images, and output resolution.** A model whose `maxReferenceImages` (from `useImageEntities`) is more than one takes them together in `referenceImages` — Nano Banana 2 (`ent_modeldef_nano_banana_2`) takes up to 14, the GPT Image models up to 16. There is no role per image: the model reads them in order, so the prompt says which is which. `resolution` picks one of the model's `supportedResolutions`; higher costs more (`creditsPerImageByResolution`):
|
|
587
589
|
|
|
588
590
|
```tsx
|
|
589
591
|
generate({
|
|
@@ -670,13 +672,14 @@ const { entities, isLoading } = useImageEntities({
|
|
|
670
672
|
// entities[i]: { entityId, displayName, provider, modes, supportedSizes,
|
|
671
673
|
// supportsReferenceImage, maxReferenceImages,
|
|
672
674
|
// supportedResolutions, defaultResolution, isPlatformRecommended,
|
|
673
|
-
//
|
|
675
|
+
// pricedBy, pixelSizes, defaultQuality,
|
|
676
|
+
// creditsPerImage, creditsPerImageByResolution, creditsPerImageByTier,
|
|
674
677
|
// estimatedDurationMs, company, strengths, providerParams, ... }
|
|
675
678
|
```
|
|
676
679
|
|
|
677
680
|
Each entry is scrubbed — only fields a UI legitimately needs (no provider model strings, no endpoints, no execution config).
|
|
678
681
|
|
|
679
|
-
`creditsPerImage` is what one image costs the user in credits, markup already included — it matches what the ledger deducts, so it is the figure to show. For a model priced by resolution it is the price at `defaultResolution`, and `creditsPerImageByResolution` has each resolution's; Nano Banana 2 also bills reference images and thinking as tokens on top (a fraction of a credit to a few credits). `estimatedDurationMs` sizes a progress indicator; `company` and `strengths` are model-info copy. All optional: absent means the model has nothing to declare, not that the data is missing.
|
|
682
|
+
`creditsPerImage` is what one image costs the user in credits, markup already included — it matches what the ledger deducts, so it is the figure to show. For a model priced by resolution it is the price at `defaultResolution`, and `creditsPerImageByResolution` has each resolution's; Nano Banana 2 also bills reference images and thinking as tokens on top (a fraction of a credit to a few credits). The GPT Image models are `pricedBy: 'quality-and-size'`: `creditsPerImage` is the price at `defaultQuality`, the first `supportedSizes` entry and `defaultResolution`, and `creditsPerImageByTier` has every other, keyed `'<quality>@<WIDTHxHEIGHT>'` — find the pixel size in `pixelSizes` (`'16:9/2K'` → `'2048x1152'`), so a request's price is `creditsPerImageByTier[quality + '@' + pixelSizes[size + '/' + resolution]]`. Their prompt and reference images are billed as tokens on top. `estimatedDurationMs` sizes a progress indicator; `company` and `strengths` are model-info copy. All optional: absent means the model has nothing to declare, not that the data is missing.
|
|
680
683
|
|
|
681
684
|
**Tunable engine parameters.** `providerParams` describes what a model exposes for tuning — enough to render a settings panel without hardcoding a thing:
|
|
682
685
|
|
|
@@ -688,7 +691,7 @@ const seed = entity.providerParams?.find((p) => p.key === 'seed');
|
|
|
688
691
|
await generate({ entityId, prompt, providerParams: { seed: 42 } });
|
|
689
692
|
```
|
|
690
693
|
|
|
691
|
-
Nano Banana 2 exposes `seed`, `temperature` (0–2) and `thinking_level` (`'minimal'` default, or `'high'` — the model plans the picture first: better at layouts and directions like "seen from above", slower, and its thinking tokens are billed).
|
|
694
|
+
Nano Banana 2 exposes `seed`, `temperature` (0–2) and `thinking_level` (`'minimal'` default, or `'high'` — the model plans the picture first: better at layouts and directions like "seen from above", slower, and its thinking tokens are billed). The GPT Image models expose `output_format` (`'png'` default, `'jpeg'`, `'webp'`) and `output_compression` (0–100, JPEG and WebP only); GPT Image 1.5 and the GPT Image 2.5 models also take `background` (`'auto'`, `'opaque'`, `'transparent'` — transparent needs PNG or WebP).
|
|
692
695
|
|
|
693
696
|
**The `category` trap.** A param carrying `category: 'quality'` or `'style'` does NOT belong in `providerParams` — send it on the matching top-level field. Providers read those two from the top level only, and an unrecognized `providerParams` key is dropped without an error, so the image generates at the model's default **and you are billed for it anyway**:
|
|
694
697
|
|
|
@@ -1308,6 +1311,36 @@ Three things to design around:
|
|
|
1308
1311
|
|
|
1309
1312
|
Only images the user made or uploaded in **their own** Fias files can be published (pass the `fileId` from a `useImageGeneration()` result). PNG/JPEG/WebP only; every image is re-encoded to a canonical PNG with metadata stripped. Publishers can `unpublish()` their own assets, and any user can `report()` one for review.
|
|
1310
1313
|
|
|
1314
|
+
### `useCompanyEmail()` — Send email as the Company the app is used in
|
|
1315
|
+
|
|
1316
|
+
**Permission:** `email:company:send`
|
|
1317
|
+
**Returns:** `CompanyEmailApi`
|
|
1318
|
+
|
|
1319
|
+
For apps built for an approved partner Company: send email **from the Company's own verified domain** (e.g. `team@example.com`), not from Fias. Declaring the permission is not enough — a Company admin must also authorize your app to send, and chooses who it may email: members of the workspace it is used in, members of the whole Company, or anyone. Until then every call is refused with `COMPANY_EMAIL_NOT_AUTHORIZED`.
|
|
1320
|
+
|
|
1321
|
+
```tsx
|
|
1322
|
+
import { useCompanyEmail } from '@fias/arche-sdk';
|
|
1323
|
+
|
|
1324
|
+
const email = useCompanyEmail();
|
|
1325
|
+
const { results, sent } = await email.send({
|
|
1326
|
+
requestKey: `digest-${weekId}`, // reuse on retry — never double-sends
|
|
1327
|
+
to: members.map((m) => ({ userId: m.userId })),
|
|
1328
|
+
subject: 'Your weekly digest',
|
|
1329
|
+
text: digestText, // required
|
|
1330
|
+
html: digestHtml, // optional, sanitized
|
|
1331
|
+
});
|
|
1332
|
+
// results[i]: { index, status: 'accepted' | 'unknown' | 'failed' | 'muted' | 'not_sent' }
|
|
1333
|
+
```
|
|
1334
|
+
|
|
1335
|
+
- **You never choose the From address** — it is the address the Company assigned your app. You choose recipients and content.
|
|
1336
|
+
- **Name members by `userId`**; you never see their addresses. Raw `{ email }` recipients work only if the Company let your app email anyone. One recipient outside what the Company allowed refuses the whole call (without saying which).
|
|
1337
|
+
- **The user must be working in one of the Company's workspaces, with edit access.** Each recipient is charged to that user, like any paid call; up to 50 recipients per call, and a daily limit per app per Company.
|
|
1338
|
+
- **Retry with the same `requestKey`.** A recipient already sent under that key is not sent again. `unknown` means it may have gone out — do not resend it under a new key.
|
|
1339
|
+
- **HTML is sanitized** to the email allow-list: tables, inline presentational styles, `https` images and `https`/`mailto` links are kept; `<script>`, `<form>`, `<iframe>` and similar refuse the send (`EMAIL_CONTENT_REJECTED`).
|
|
1340
|
+
- **Attachments:** up to 5 files, 5 MB total, and only `.pdf`, `.png`, `.jpg`/`.jpeg`, `.gif`, `.csv`, `.txt`, `.ics`, `.docx`, `.xlsx`. `contentType` must match the extension (e.g. `application/pdf`), and the bytes must be that format; anything else refuses the send (`EMAIL_CONTENT_REJECTED`).
|
|
1341
|
+
- **Every email carries one-click unsubscribe.** Recipients who used it come back as `muted`; the Company may also show a "Stop emails from this arche" line, which is always shown for `kind: 'marketing'`.
|
|
1342
|
+
- Not available in the builder preview or the local dev harness — it sends real email. Other refusals: `WORKSPACE_REQUIRED`, `RECIPIENT_NOT_ALLOWED`, `COMPANY_EMAIL_UNAVAILABLE` (the Company's domain is not ready or paused), `DAILY_EMAIL_LIMIT_REACHED`, `INSUFFICIENT_CREDITS`.
|
|
1343
|
+
|
|
1311
1344
|
### `useFiasStore()` — In-app purchases (IAP)
|
|
1312
1345
|
|
|
1313
1346
|
**Permission:** `store:purchase`
|
|
@@ -1405,7 +1438,23 @@ the user moves the host themselves with browser back/forward. So a router
|
|
|
1405
1438
|
driven off `currentPath` stays in step with the address bar, and the back
|
|
1406
1439
|
button works the way your users expect — you do not have to mirror the path in
|
|
1407
1440
|
your own state. The dev harness echoes navigations the same way, so what you
|
|
1408
|
-
see locally is what ships.
|
|
1441
|
+
see locally is what ships. To test a deep link locally, open the harness with
|
|
1442
|
+
`?path=/map` (a root-relative path in your route space) and `currentPath`
|
|
1443
|
+
starts there instead of at `/`.
|
|
1444
|
+
|
|
1445
|
+
**Correcting the URL.** Every `navigateTo` pushes a history entry by default,
|
|
1446
|
+
which is right for navigation the user asked for. When you are CORRECTING the
|
|
1447
|
+
address bar instead — normalizing a link you were opened at (`/Map/` →
|
|
1448
|
+
`/map`), or putting it back after refusing a route — pass `{ replace: true }`
|
|
1449
|
+
so Back does not land on the URL you just corrected:
|
|
1450
|
+
|
|
1451
|
+
```tsx
|
|
1452
|
+
navigateTo('/map', { replace: true });
|
|
1453
|
+
```
|
|
1454
|
+
|
|
1455
|
+
A host older than this option ignores it and pushes. If you correct paths
|
|
1456
|
+
automatically as they arrive, never repeat the same correction twice in a
|
|
1457
|
+
row, or a push-only host can trap the Back button between two URLs.
|
|
1409
1458
|
|
|
1410
1459
|
### Opening external links
|
|
1411
1460
|
|