@fias/arche-sdk 1.1.4 → 1.1.6
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/bridge.d.ts +11 -1
- package/dist/bridge.d.ts.map +1 -1
- package/dist/bridge.js +61 -2
- package/dist/bridge.js.map +1 -1
- package/dist/bridge.test.js +24 -7
- package/dist/bridge.test.js.map +1 -1
- package/dist/cli/create-plugin.js +4 -1
- package/dist/cli/create-plugin.js.map +1 -1
- package/dist/hooks.d.ts +18 -1
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +69 -2
- package/dist/hooks.js.map +1 -1
- package/dist/hooks.test.js +30 -6
- package/dist/hooks.test.js.map +1 -1
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1966 -5
- package/dist/theme.d.ts +18 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +85 -0
- package/dist/theme.js.map +1 -0
- package/dist/themes/catalog-data.d.ts +3 -0
- package/dist/themes/catalog-data.d.ts.map +1 -0
- package/dist/themes/catalog-data.js +1559 -0
- package/dist/themes/catalog-data.js.map +1 -0
- package/dist/themes/fonts.d.ts +17 -0
- package/dist/themes/fonts.d.ts.map +1 -0
- package/dist/themes/fonts.js +175 -0
- package/dist/themes/fonts.js.map +1 -0
- package/dist/themes/index.d.ts +20 -0
- package/dist/themes/index.d.ts.map +1 -0
- package/dist/themes/index.js +76 -0
- package/dist/themes/index.js.map +1 -0
- package/dist/types.d.ts +28 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -4
- package/templates/default/.cursorrules +1 -0
- package/templates/default/.github/copilot-instructions.md +1 -0
- package/templates/default/AGENTS.md +359 -0
- package/templates/default/CLAUDE.md +359 -0
- package/templates/default/fias-plugin.json +2 -1
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
# FIAS Plugin Development Guide
|
|
2
|
+
|
|
3
|
+
This project is a FIAS platform plugin — a React application that runs in a sandboxed iframe within the FIAS marketplace. This file provides the context AI coding assistants need to build, test, and submit plugins effectively.
|
|
4
|
+
|
|
5
|
+
For other AI tool instruction files, see `CLAUDE.md` (identical content).
|
|
6
|
+
|
|
7
|
+
## Project Structure
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
fias-plugin.json # Plugin manifest (required) — name, permissions, pricing, AI configs
|
|
11
|
+
package.json # Dependencies and scripts
|
|
12
|
+
src/
|
|
13
|
+
index.tsx # Entry point — must render into #root with <FiasProvider> wrapper
|
|
14
|
+
App.tsx # Main component
|
|
15
|
+
vite.config.ts # Vite dev server config (port 3100)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## SDK API Reference
|
|
19
|
+
|
|
20
|
+
All hooks require the app to be wrapped in `<FiasProvider>`:
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
import { FiasProvider } from '@fias/arche-sdk';
|
|
24
|
+
|
|
25
|
+
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
26
|
+
<FiasProvider>
|
|
27
|
+
<App />
|
|
28
|
+
</FiasProvider>
|
|
29
|
+
);
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### `useFiasTheme()` — Platform theme tokens
|
|
33
|
+
|
|
34
|
+
**Permission:** `theme:read`
|
|
35
|
+
**Returns:** `FiasTheme | null` (null while loading)
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
import { useFiasTheme } from '@fias/arche-sdk';
|
|
39
|
+
|
|
40
|
+
function MyComponent() {
|
|
41
|
+
const theme = useFiasTheme();
|
|
42
|
+
if (!theme) return null;
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<div style={{
|
|
46
|
+
color: theme.colors.text,
|
|
47
|
+
backgroundColor: theme.colors.background,
|
|
48
|
+
fontFamily: theme.fonts.body,
|
|
49
|
+
padding: theme.spacing.md,
|
|
50
|
+
borderRadius: theme.components.cardRadius,
|
|
51
|
+
}}>
|
|
52
|
+
{theme.mode === 'dark' ? 'Dark mode' : 'Light mode'}
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**FiasTheme shape:**
|
|
59
|
+
- `mode`: `'light' | 'dark'`
|
|
60
|
+
- `colors`: `{ primary, primaryText, secondary, accent, background, surface, card, cardText, text, textSecondary, muted, mutedText, border, error, warning, success, info }`
|
|
61
|
+
- `spacing`: `{ xs, sm, md, lg, xl }` (CSS values like `'8px'`)
|
|
62
|
+
- `fonts`: `{ body, heading, mono }` (font-family strings)
|
|
63
|
+
- `components`: `{ borderRadius, buttonRadius, cardRadius, inputRadius, shadowSm, shadowMd, shadowLg, borderWidth }`
|
|
64
|
+
|
|
65
|
+
### `useFiasUser()` — Current user profile
|
|
66
|
+
|
|
67
|
+
**Permission:** `user:profile:read`
|
|
68
|
+
**Returns:** `FiasUser | null`
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
import { useFiasUser } from '@fias/arche-sdk';
|
|
72
|
+
|
|
73
|
+
const user = useFiasUser();
|
|
74
|
+
// { userId: string, displayName: string, avatar: string | null }
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### `useFiasStorage()` — Sandboxed file storage
|
|
78
|
+
|
|
79
|
+
**Permission:** `storage:sandbox`
|
|
80
|
+
**Returns:** `FiasStorageApi`
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
import { useFiasStorage } from '@fias/arche-sdk';
|
|
84
|
+
|
|
85
|
+
const { readFile, writeFile, listFiles, deleteFile } = useFiasStorage();
|
|
86
|
+
|
|
87
|
+
await writeFile('data/settings.json', JSON.stringify(settings));
|
|
88
|
+
const content = await readFile('data/settings.json'); // string | null
|
|
89
|
+
const files = await listFiles('data/'); // string[]
|
|
90
|
+
await deleteFile('data/old.json');
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### `useEntityInvocation()` — Invoke AI entities
|
|
94
|
+
|
|
95
|
+
**Permission:** `entities:invoke`
|
|
96
|
+
**Returns:** `EntityInvocationApi`
|
|
97
|
+
|
|
98
|
+
```tsx
|
|
99
|
+
import { useEntityInvocation } from '@fias/arche-sdk';
|
|
100
|
+
|
|
101
|
+
function AISummarizer() {
|
|
102
|
+
const { invoke, isLoading, result, error, streamingText } = useEntityInvocation();
|
|
103
|
+
|
|
104
|
+
async function summarize(text: string) {
|
|
105
|
+
await invoke({ entityId: 'ent_abc123', input: text });
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<div>
|
|
110
|
+
<button onClick={() => summarize('...')} disabled={isLoading}>
|
|
111
|
+
Summarize
|
|
112
|
+
</button>
|
|
113
|
+
{isLoading && <p>{streamingText}</p>}
|
|
114
|
+
{result && <p>{result.output}</p>}
|
|
115
|
+
{error && <p>Error: {error.message}</p>}
|
|
116
|
+
</div>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The `entityId` references a published entity on the platform. Browse available entities with `npx fias-dev entities`.
|
|
122
|
+
|
|
123
|
+
### `useFiasNavigation()` — In-plugin routing
|
|
124
|
+
|
|
125
|
+
**Permission:** None required
|
|
126
|
+
**Returns:** `FiasNavigationApi`
|
|
127
|
+
|
|
128
|
+
```tsx
|
|
129
|
+
import { useFiasNavigation } from '@fias/arche-sdk';
|
|
130
|
+
|
|
131
|
+
const { navigateTo, currentPath } = useFiasNavigation();
|
|
132
|
+
navigateTo('/settings');
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### `useStepNavigation()` — Multi-step workflows
|
|
136
|
+
|
|
137
|
+
**Returns:** `StepNavigationApi`
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
import { useStepNavigation } from '@fias/arche-sdk';
|
|
141
|
+
|
|
142
|
+
const { currentStep, setCurrentStep } = useStepNavigation('step-1');
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### `usePersistentState()` — Auto-saving state
|
|
146
|
+
|
|
147
|
+
**Permission:** `storage:sandbox`
|
|
148
|
+
|
|
149
|
+
```tsx
|
|
150
|
+
import { usePersistentState } from '@fias/arche-sdk';
|
|
151
|
+
|
|
152
|
+
const [count, setCount] = usePersistentState<number>('counter', 0);
|
|
153
|
+
// Automatically persists to storage on change
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### `fias` — Imperative utilities
|
|
157
|
+
|
|
158
|
+
```tsx
|
|
159
|
+
import { fias } from '@fias/arche-sdk';
|
|
160
|
+
|
|
161
|
+
fias.resize(800); // Resize iframe height
|
|
162
|
+
fias.showToast('Saved!', 'success'); // Toast: 'info' | 'success' | 'warning' | 'error'
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Manifest Reference (`fias-plugin.json`)
|
|
166
|
+
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"name": "my-plugin",
|
|
170
|
+
"version": "1.0.0",
|
|
171
|
+
"description": "What this plugin does",
|
|
172
|
+
"main": "src/index.tsx",
|
|
173
|
+
"archeType": "tool",
|
|
174
|
+
"tags": ["utility"],
|
|
175
|
+
"pricing": { "model": "free", "currency": "usd" },
|
|
176
|
+
"permissions": ["theme:read", "entities:invoke"],
|
|
177
|
+
"sdk": "^1.0.0",
|
|
178
|
+
"dependencies": { "recharts": "2.15.0" },
|
|
179
|
+
"aiConfigs": [
|
|
180
|
+
{
|
|
181
|
+
"configId": "summarizer",
|
|
182
|
+
"label": "Text Summarizer",
|
|
183
|
+
"entityId": "ent_abc123",
|
|
184
|
+
"systemPrompt": "Summarize the input concisely.",
|
|
185
|
+
"parameters": { "temperature": 0.3, "maxTokens": 500 }
|
|
186
|
+
}
|
|
187
|
+
]
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
**Fields:**
|
|
192
|
+
|
|
193
|
+
| Field | Required | Description |
|
|
194
|
+
|----------------|----------|-------------|
|
|
195
|
+
| `name` | Yes | Plugin identifier (lowercase, hyphens) |
|
|
196
|
+
| `version` | Yes | Semver (e.g., `"1.0.0"`) |
|
|
197
|
+
| `description` | Yes | Short marketplace description |
|
|
198
|
+
| `main` | Yes | Entry point source file |
|
|
199
|
+
| `archeType` | Yes | `"tool"` or `"site"` |
|
|
200
|
+
| `tags` | No | Discovery tags |
|
|
201
|
+
| `pricing` | Yes | `{ model: "free" | "fixed" | "per_use" | "tiered" }` |
|
|
202
|
+
| `permissions` | Yes | Array of permission scopes |
|
|
203
|
+
| `sdk` | Yes | SDK version range |
|
|
204
|
+
| `dependencies` | No | npm packages with **exact** versions (max 20) |
|
|
205
|
+
| `aiConfigs` | No | AI entity configurations (see below) |
|
|
206
|
+
|
|
207
|
+
**Permissions:** `theme:read`, `user:profile:read`, `storage:sandbox`, `entities:invoke`
|
|
208
|
+
|
|
209
|
+
**AI Configs:** Declare entity invocations the plugin will use. Each config's `entityId` must reference a published prompt entity. Browse entities with `npx fias-dev entities`. Requires `entities:invoke` permission.
|
|
210
|
+
|
|
211
|
+
## Plugin Constraints
|
|
212
|
+
|
|
213
|
+
These are hard limits enforced by the platform. Code that violates these will fail review or be blocked at runtime.
|
|
214
|
+
|
|
215
|
+
### Sandboxing
|
|
216
|
+
- Plugins run in an iframe with `sandbox="allow-scripts allow-forms allow-same-origin"`
|
|
217
|
+
- **No `fetch()` or `XMLHttpRequest`** — all network access is blocked
|
|
218
|
+
- **No access** to parent DOM, cookies, or localStorage
|
|
219
|
+
- **No external scripts or stylesheets** — everything must be bundled
|
|
220
|
+
- All platform communication goes through the bridge (SDK hooks)
|
|
221
|
+
|
|
222
|
+
### Size and File Limits
|
|
223
|
+
- **Bundle size:** Max 5 MB compressed
|
|
224
|
+
- **Dependencies:** Max 20, exact semver versions only (e.g., `"4.4.7"`, not `"^4.4.7"`)
|
|
225
|
+
- Platform packages (`react`, `react-dom`, `@fias/arche-sdk`) are provided — do not include in `dependencies`
|
|
226
|
+
|
|
227
|
+
### Rate Limits
|
|
228
|
+
- `entity_invoke`: 60/minute
|
|
229
|
+
- `storage_write`: 120/minute
|
|
230
|
+
- `storage_read`: 300/minute
|
|
231
|
+
- `storage_list`, `storage_delete`: 60/minute
|
|
232
|
+
|
|
233
|
+
### Security Rules (enforced during review)
|
|
234
|
+
- No `eval()`, `Function()`, `innerHTML`, or dynamic code execution
|
|
235
|
+
- No attempts to escape the iframe sandbox
|
|
236
|
+
- No credential collection or dark patterns
|
|
237
|
+
- No obfuscated code
|
|
238
|
+
- No accessing `window.parent`, `window.top`, or `document.cookie`
|
|
239
|
+
|
|
240
|
+
## Styling Guidelines
|
|
241
|
+
|
|
242
|
+
- Always use `useFiasTheme()` for colors, fonts, and spacing — never hardcode
|
|
243
|
+
- Support both light and dark modes (check `theme.mode`)
|
|
244
|
+
- Use `theme.components.cardRadius`, `theme.components.shadowMd`, etc. for consistent component styling
|
|
245
|
+
- The plugin renders at full width inside the platform layout
|
|
246
|
+
|
|
247
|
+
## Development Workflow
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
# Terminal 1: Start plugin dev server (Vite, port 3100)
|
|
251
|
+
npm run dev
|
|
252
|
+
|
|
253
|
+
# Terminal 2: Start dev harness (mock mode, port 3200)
|
|
254
|
+
npm run dev:mock
|
|
255
|
+
|
|
256
|
+
# Open http://localhost:3200 in browser
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Authenticating with the FIAS Platform
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
npx fias-dev login # Opens browser to authenticate (recommended)
|
|
263
|
+
npx fias-dev login --key fias_sk_... # Or paste an API key directly
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Running `npx fias-dev login` opens your browser to the FIAS platform. After signing in, an API key is created automatically and saved to `~/.fias/credentials`. No manual key copying needed.
|
|
267
|
+
|
|
268
|
+
### Testing with Real AI Entities (costs credits)
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
npm run dev:harness # Start harness in live mode (requires login first)
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Browsing Available Entities
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
npx fias-dev entities # List all
|
|
278
|
+
npx fias-dev entities --search "text" # Search by keyword
|
|
279
|
+
npx fias-dev entities --type "prompt" # Filter by type
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Validating the Manifest
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
npx fias-dev validate
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Submitting to the Arche Store
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
npm run submit
|
|
292
|
+
# Builds, validates, packages, uploads, submits for AI review
|
|
293
|
+
# First listing: 5000 credits ($50). Re-submissions: 100 credits ($1).
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
## Common Patterns
|
|
297
|
+
|
|
298
|
+
### Theme-Aware Card Component
|
|
299
|
+
|
|
300
|
+
```tsx
|
|
301
|
+
function Card({ children }: { children: React.ReactNode }) {
|
|
302
|
+
const theme = useFiasTheme();
|
|
303
|
+
if (!theme) return null;
|
|
304
|
+
|
|
305
|
+
return (
|
|
306
|
+
<div style={{
|
|
307
|
+
backgroundColor: theme.colors.card,
|
|
308
|
+
color: theme.colors.cardText,
|
|
309
|
+
borderRadius: theme.components.cardRadius,
|
|
310
|
+
boxShadow: theme.components.shadowMd,
|
|
311
|
+
border: `${theme.components.borderWidth} solid ${theme.colors.border}`,
|
|
312
|
+
padding: theme.spacing.lg,
|
|
313
|
+
}}>
|
|
314
|
+
{children}
|
|
315
|
+
</div>
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Streaming AI Response
|
|
321
|
+
|
|
322
|
+
```tsx
|
|
323
|
+
function AIChat() {
|
|
324
|
+
const { invoke, isLoading, streamingText, result } = useEntityInvocation();
|
|
325
|
+
const [input, setInput] = useState('');
|
|
326
|
+
|
|
327
|
+
return (
|
|
328
|
+
<div>
|
|
329
|
+
<textarea value={input} onChange={e => setInput(e.target.value)} />
|
|
330
|
+
<button onClick={() => invoke({ entityId: 'ent_abc', input })} disabled={isLoading}>
|
|
331
|
+
Send
|
|
332
|
+
</button>
|
|
333
|
+
<div>{isLoading ? streamingText : result?.output}</div>
|
|
334
|
+
</div>
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Persistent Settings
|
|
340
|
+
|
|
341
|
+
```tsx
|
|
342
|
+
function Settings() {
|
|
343
|
+
const [settings, setSettings] = usePersistentState('settings', {
|
|
344
|
+
notifications: true,
|
|
345
|
+
fontSize: 14,
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
return (
|
|
349
|
+
<label>
|
|
350
|
+
<input
|
|
351
|
+
type="checkbox"
|
|
352
|
+
checked={settings.notifications}
|
|
353
|
+
onChange={e => setSettings({ ...settings, notifications: e.target.checked })}
|
|
354
|
+
/>
|
|
355
|
+
Notifications
|
|
356
|
+
</label>
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
```
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
# FIAS Plugin Development Guide
|
|
2
|
+
|
|
3
|
+
This project is a FIAS platform plugin — a React application that runs in a sandboxed iframe within the FIAS marketplace. This file provides the context AI coding assistants need to build, test, and submit plugins effectively.
|
|
4
|
+
|
|
5
|
+
For other AI tool instruction files, see `AGENTS.md` (identical content).
|
|
6
|
+
|
|
7
|
+
## Project Structure
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
fias-plugin.json # Plugin manifest (required) — name, permissions, pricing, AI configs
|
|
11
|
+
package.json # Dependencies and scripts
|
|
12
|
+
src/
|
|
13
|
+
index.tsx # Entry point — must render into #root with <FiasProvider> wrapper
|
|
14
|
+
App.tsx # Main component
|
|
15
|
+
vite.config.ts # Vite dev server config (port 3100)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## SDK API Reference
|
|
19
|
+
|
|
20
|
+
All hooks require the app to be wrapped in `<FiasProvider>`:
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
import { FiasProvider } from '@fias/arche-sdk';
|
|
24
|
+
|
|
25
|
+
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
26
|
+
<FiasProvider>
|
|
27
|
+
<App />
|
|
28
|
+
</FiasProvider>
|
|
29
|
+
);
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### `useFiasTheme()` — Platform theme tokens
|
|
33
|
+
|
|
34
|
+
**Permission:** `theme:read`
|
|
35
|
+
**Returns:** `FiasTheme | null` (null while loading)
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
import { useFiasTheme } from '@fias/arche-sdk';
|
|
39
|
+
|
|
40
|
+
function MyComponent() {
|
|
41
|
+
const theme = useFiasTheme();
|
|
42
|
+
if (!theme) return null;
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<div style={{
|
|
46
|
+
color: theme.colors.text,
|
|
47
|
+
backgroundColor: theme.colors.background,
|
|
48
|
+
fontFamily: theme.fonts.body,
|
|
49
|
+
padding: theme.spacing.md,
|
|
50
|
+
borderRadius: theme.components.cardRadius,
|
|
51
|
+
}}>
|
|
52
|
+
{theme.mode === 'dark' ? 'Dark mode' : 'Light mode'}
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**FiasTheme shape:**
|
|
59
|
+
- `mode`: `'light' | 'dark'`
|
|
60
|
+
- `colors`: `{ primary, primaryText, secondary, accent, background, surface, card, cardText, text, textSecondary, muted, mutedText, border, error, warning, success, info }`
|
|
61
|
+
- `spacing`: `{ xs, sm, md, lg, xl }` (CSS values like `'8px'`)
|
|
62
|
+
- `fonts`: `{ body, heading, mono }` (font-family strings)
|
|
63
|
+
- `components`: `{ borderRadius, buttonRadius, cardRadius, inputRadius, shadowSm, shadowMd, shadowLg, borderWidth }`
|
|
64
|
+
|
|
65
|
+
### `useFiasUser()` — Current user profile
|
|
66
|
+
|
|
67
|
+
**Permission:** `user:profile:read`
|
|
68
|
+
**Returns:** `FiasUser | null`
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
import { useFiasUser } from '@fias/arche-sdk';
|
|
72
|
+
|
|
73
|
+
const user = useFiasUser();
|
|
74
|
+
// { userId: string, displayName: string, avatar: string | null }
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### `useFiasStorage()` — Sandboxed file storage
|
|
78
|
+
|
|
79
|
+
**Permission:** `storage:sandbox`
|
|
80
|
+
**Returns:** `FiasStorageApi`
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
import { useFiasStorage } from '@fias/arche-sdk';
|
|
84
|
+
|
|
85
|
+
const { readFile, writeFile, listFiles, deleteFile } = useFiasStorage();
|
|
86
|
+
|
|
87
|
+
await writeFile('data/settings.json', JSON.stringify(settings));
|
|
88
|
+
const content = await readFile('data/settings.json'); // string | null
|
|
89
|
+
const files = await listFiles('data/'); // string[]
|
|
90
|
+
await deleteFile('data/old.json');
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### `useEntityInvocation()` — Invoke AI entities
|
|
94
|
+
|
|
95
|
+
**Permission:** `entities:invoke`
|
|
96
|
+
**Returns:** `EntityInvocationApi`
|
|
97
|
+
|
|
98
|
+
```tsx
|
|
99
|
+
import { useEntityInvocation } from '@fias/arche-sdk';
|
|
100
|
+
|
|
101
|
+
function AISummarizer() {
|
|
102
|
+
const { invoke, isLoading, result, error, streamingText } = useEntityInvocation();
|
|
103
|
+
|
|
104
|
+
async function summarize(text: string) {
|
|
105
|
+
await invoke({ entityId: 'ent_abc123', input: text });
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<div>
|
|
110
|
+
<button onClick={() => summarize('...')} disabled={isLoading}>
|
|
111
|
+
Summarize
|
|
112
|
+
</button>
|
|
113
|
+
{isLoading && <p>{streamingText}</p>}
|
|
114
|
+
{result && <p>{result.output}</p>}
|
|
115
|
+
{error && <p>Error: {error.message}</p>}
|
|
116
|
+
</div>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The `entityId` references a published entity on the platform. Browse available entities with `npx fias-dev entities`.
|
|
122
|
+
|
|
123
|
+
### `useFiasNavigation()` — In-plugin routing
|
|
124
|
+
|
|
125
|
+
**Permission:** None required
|
|
126
|
+
**Returns:** `FiasNavigationApi`
|
|
127
|
+
|
|
128
|
+
```tsx
|
|
129
|
+
import { useFiasNavigation } from '@fias/arche-sdk';
|
|
130
|
+
|
|
131
|
+
const { navigateTo, currentPath } = useFiasNavigation();
|
|
132
|
+
navigateTo('/settings');
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### `useStepNavigation()` — Multi-step workflows
|
|
136
|
+
|
|
137
|
+
**Returns:** `StepNavigationApi`
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
import { useStepNavigation } from '@fias/arche-sdk';
|
|
141
|
+
|
|
142
|
+
const { currentStep, setCurrentStep } = useStepNavigation('step-1');
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### `usePersistentState()` — Auto-saving state
|
|
146
|
+
|
|
147
|
+
**Permission:** `storage:sandbox`
|
|
148
|
+
|
|
149
|
+
```tsx
|
|
150
|
+
import { usePersistentState } from '@fias/arche-sdk';
|
|
151
|
+
|
|
152
|
+
const [count, setCount] = usePersistentState<number>('counter', 0);
|
|
153
|
+
// Automatically persists to storage on change
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### `fias` — Imperative utilities
|
|
157
|
+
|
|
158
|
+
```tsx
|
|
159
|
+
import { fias } from '@fias/arche-sdk';
|
|
160
|
+
|
|
161
|
+
fias.resize(800); // Resize iframe height
|
|
162
|
+
fias.showToast('Saved!', 'success'); // Toast: 'info' | 'success' | 'warning' | 'error'
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Manifest Reference (`fias-plugin.json`)
|
|
166
|
+
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"name": "my-plugin",
|
|
170
|
+
"version": "1.0.0",
|
|
171
|
+
"description": "What this plugin does",
|
|
172
|
+
"main": "src/index.tsx",
|
|
173
|
+
"archeType": "tool",
|
|
174
|
+
"tags": ["utility"],
|
|
175
|
+
"pricing": { "model": "free", "currency": "usd" },
|
|
176
|
+
"permissions": ["theme:read", "entities:invoke"],
|
|
177
|
+
"sdk": "^1.0.0",
|
|
178
|
+
"dependencies": { "recharts": "2.15.0" },
|
|
179
|
+
"aiConfigs": [
|
|
180
|
+
{
|
|
181
|
+
"configId": "summarizer",
|
|
182
|
+
"label": "Text Summarizer",
|
|
183
|
+
"entityId": "ent_abc123",
|
|
184
|
+
"systemPrompt": "Summarize the input concisely.",
|
|
185
|
+
"parameters": { "temperature": 0.3, "maxTokens": 500 }
|
|
186
|
+
}
|
|
187
|
+
]
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
**Fields:**
|
|
192
|
+
|
|
193
|
+
| Field | Required | Description |
|
|
194
|
+
|----------------|----------|-------------|
|
|
195
|
+
| `name` | Yes | Plugin identifier (lowercase, hyphens) |
|
|
196
|
+
| `version` | Yes | Semver (e.g., `"1.0.0"`) |
|
|
197
|
+
| `description` | Yes | Short marketplace description |
|
|
198
|
+
| `main` | Yes | Entry point source file |
|
|
199
|
+
| `archeType` | Yes | `"tool"` or `"site"` |
|
|
200
|
+
| `tags` | No | Discovery tags |
|
|
201
|
+
| `pricing` | Yes | `{ model: "free" | "fixed" | "per_use" | "tiered" }` |
|
|
202
|
+
| `permissions` | Yes | Array of permission scopes |
|
|
203
|
+
| `sdk` | Yes | SDK version range |
|
|
204
|
+
| `dependencies` | No | npm packages with **exact** versions (max 20) |
|
|
205
|
+
| `aiConfigs` | No | AI entity configurations (see below) |
|
|
206
|
+
|
|
207
|
+
**Permissions:** `theme:read`, `user:profile:read`, `storage:sandbox`, `entities:invoke`
|
|
208
|
+
|
|
209
|
+
**AI Configs:** Declare entity invocations the plugin will use. Each config's `entityId` must reference a published prompt entity. Browse entities with `npx fias-dev entities`. Requires `entities:invoke` permission.
|
|
210
|
+
|
|
211
|
+
## Plugin Constraints
|
|
212
|
+
|
|
213
|
+
These are hard limits enforced by the platform. Code that violates these will fail review or be blocked at runtime.
|
|
214
|
+
|
|
215
|
+
### Sandboxing
|
|
216
|
+
- Plugins run in an iframe with `sandbox="allow-scripts allow-forms allow-same-origin"`
|
|
217
|
+
- **No `fetch()` or `XMLHttpRequest`** — all network access is blocked
|
|
218
|
+
- **No access** to parent DOM, cookies, or localStorage
|
|
219
|
+
- **No external scripts or stylesheets** — everything must be bundled
|
|
220
|
+
- All platform communication goes through the bridge (SDK hooks)
|
|
221
|
+
|
|
222
|
+
### Size and File Limits
|
|
223
|
+
- **Bundle size:** Max 5 MB compressed
|
|
224
|
+
- **Dependencies:** Max 20, exact semver versions only (e.g., `"4.4.7"`, not `"^4.4.7"`)
|
|
225
|
+
- Platform packages (`react`, `react-dom`, `@fias/arche-sdk`) are provided — do not include in `dependencies`
|
|
226
|
+
|
|
227
|
+
### Rate Limits
|
|
228
|
+
- `entity_invoke`: 60/minute
|
|
229
|
+
- `storage_write`: 120/minute
|
|
230
|
+
- `storage_read`: 300/minute
|
|
231
|
+
- `storage_list`, `storage_delete`: 60/minute
|
|
232
|
+
|
|
233
|
+
### Security Rules (enforced during review)
|
|
234
|
+
- No `eval()`, `Function()`, `innerHTML`, or dynamic code execution
|
|
235
|
+
- No attempts to escape the iframe sandbox
|
|
236
|
+
- No credential collection or dark patterns
|
|
237
|
+
- No obfuscated code
|
|
238
|
+
- No accessing `window.parent`, `window.top`, or `document.cookie`
|
|
239
|
+
|
|
240
|
+
## Styling Guidelines
|
|
241
|
+
|
|
242
|
+
- Always use `useFiasTheme()` for colors, fonts, and spacing — never hardcode
|
|
243
|
+
- Support both light and dark modes (check `theme.mode`)
|
|
244
|
+
- Use `theme.components.cardRadius`, `theme.components.shadowMd`, etc. for consistent component styling
|
|
245
|
+
- The plugin renders at full width inside the platform layout
|
|
246
|
+
|
|
247
|
+
## Development Workflow
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
# Terminal 1: Start plugin dev server (Vite, port 3100)
|
|
251
|
+
npm run dev
|
|
252
|
+
|
|
253
|
+
# Terminal 2: Start dev harness (mock mode, port 3200)
|
|
254
|
+
npm run dev:mock
|
|
255
|
+
|
|
256
|
+
# Open http://localhost:3200 in browser
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Authenticating with the FIAS Platform
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
npx fias-dev login # Opens browser to authenticate (recommended)
|
|
263
|
+
npx fias-dev login --key fias_sk_... # Or paste an API key directly
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Running `npx fias-dev login` opens your browser to the FIAS platform. After signing in, an API key is created automatically and saved to `~/.fias/credentials`. No manual key copying needed.
|
|
267
|
+
|
|
268
|
+
### Testing with Real AI Entities (costs credits)
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
npm run dev:harness # Start harness in live mode (requires login first)
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Browsing Available Entities
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
npx fias-dev entities # List all
|
|
278
|
+
npx fias-dev entities --search "text" # Search by keyword
|
|
279
|
+
npx fias-dev entities --type "prompt" # Filter by type
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Validating the Manifest
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
npx fias-dev validate
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Submitting to the Arche Store
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
npm run submit
|
|
292
|
+
# Builds, validates, packages, uploads, submits for AI review
|
|
293
|
+
# First listing: 5000 credits ($50). Re-submissions: 100 credits ($1).
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
## Common Patterns
|
|
297
|
+
|
|
298
|
+
### Theme-Aware Card Component
|
|
299
|
+
|
|
300
|
+
```tsx
|
|
301
|
+
function Card({ children }: { children: React.ReactNode }) {
|
|
302
|
+
const theme = useFiasTheme();
|
|
303
|
+
if (!theme) return null;
|
|
304
|
+
|
|
305
|
+
return (
|
|
306
|
+
<div style={{
|
|
307
|
+
backgroundColor: theme.colors.card,
|
|
308
|
+
color: theme.colors.cardText,
|
|
309
|
+
borderRadius: theme.components.cardRadius,
|
|
310
|
+
boxShadow: theme.components.shadowMd,
|
|
311
|
+
border: `${theme.components.borderWidth} solid ${theme.colors.border}`,
|
|
312
|
+
padding: theme.spacing.lg,
|
|
313
|
+
}}>
|
|
314
|
+
{children}
|
|
315
|
+
</div>
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Streaming AI Response
|
|
321
|
+
|
|
322
|
+
```tsx
|
|
323
|
+
function AIChat() {
|
|
324
|
+
const { invoke, isLoading, streamingText, result } = useEntityInvocation();
|
|
325
|
+
const [input, setInput] = useState('');
|
|
326
|
+
|
|
327
|
+
return (
|
|
328
|
+
<div>
|
|
329
|
+
<textarea value={input} onChange={e => setInput(e.target.value)} />
|
|
330
|
+
<button onClick={() => invoke({ entityId: 'ent_abc', input })} disabled={isLoading}>
|
|
331
|
+
Send
|
|
332
|
+
</button>
|
|
333
|
+
<div>{isLoading ? streamingText : result?.output}</div>
|
|
334
|
+
</div>
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Persistent Settings
|
|
340
|
+
|
|
341
|
+
```tsx
|
|
342
|
+
function Settings() {
|
|
343
|
+
const [settings, setSettings] = usePersistentState('settings', {
|
|
344
|
+
notifications: true,
|
|
345
|
+
fontSize: 14,
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
return (
|
|
349
|
+
<label>
|
|
350
|
+
<input
|
|
351
|
+
type="checkbox"
|
|
352
|
+
checked={settings.notifications}
|
|
353
|
+
onChange={e => setSettings({ ...settings, notifications: e.target.checked })}
|
|
354
|
+
/>
|
|
355
|
+
Notifications
|
|
356
|
+
</label>
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
```
|