@vibes.diy/prompts 2.0.1 → 2.0.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/README.md +6 -0
- package/cli-footer.md +15 -0
- package/json-docs.d.ts +1 -1
- package/llms/fireproof.md +0 -110
- package/llms/img-vibes.d.ts +2 -0
- package/llms/img-vibes.js +9 -0
- package/llms/img-vibes.js.map +1 -0
- package/llms/img-vibes.md +152 -0
- package/llms/index.d.ts +1 -1
- package/llms/index.js +3 -3
- package/package.json +9 -9
- package/prompts.d.ts +42 -12
- package/prompts.js +69 -84
- package/prompts.js.map +1 -1
- package/settings.d.ts +3 -8
- package/style-prompts.js +1 -1
- package/style-prompts.js.map +1 -1
- package/llms/image-gen.d.ts +0 -2
- package/llms/image-gen.js +0 -9
- package/llms/image-gen.js.map +0 -1
- package/llms/image-gen.md +0 -127
- package/load-docs.ts-off +0 -16
- package/txt-docs.ts-off +0 -58
package/README.md
CHANGED
|
@@ -19,6 +19,12 @@ Create beautiful, interactive mini apps with zero setup. Your creations are auto
|
|
|
19
19
|
- Install with `pnpm i`
|
|
20
20
|
- Run `pnpm dev`
|
|
21
21
|
|
|
22
|
+
## Community
|
|
23
|
+
|
|
24
|
+
We are committed to providing a welcoming and inclusive environment for all contributors. Please review our [Code of Conduct](CODE_OF_CONDUCT.md) before participating.
|
|
25
|
+
|
|
26
|
+
Interested in contributing? Check out our [Contributing Guide](CONTRIBUTING.md) to get started.
|
|
27
|
+
|
|
22
28
|
## Your Work is Always Safe
|
|
23
29
|
|
|
24
30
|
Every app you create is automatically saved, so you can:
|
package/cli-footer.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
## CLI Quickstart
|
|
2
|
+
|
|
3
|
+
### Deploy workflow
|
|
4
|
+
|
|
5
|
+
1. Run `npx vibes-diy system` to get the coding rules
|
|
6
|
+
2. Write `App.jsx` following the rules above
|
|
7
|
+
3. Run `npx vibes-diy push` to deploy — prints a live HTTPS URL
|
|
8
|
+
4. Edit and push again to iterate
|
|
9
|
+
|
|
10
|
+
### Other Commands
|
|
11
|
+
|
|
12
|
+
- `npx vibes-diy push --instant-join` — deploy and auto-accept sharing so anyone with the link can use it
|
|
13
|
+
- `npx vibes-diy push --app-slug other-name` — deploy to a different app slug instead of the directory name
|
|
14
|
+
- `npx vibes-diy login` — authenticate this device (run once before first push)
|
|
15
|
+
- `npx vibes-diy help` — show all available commands
|
package/json-docs.d.ts
CHANGED
package/llms/fireproof.md
CHANGED
|
@@ -274,46 +274,6 @@ database.subscribe((changes) => {
|
|
|
274
274
|
}, true);
|
|
275
275
|
```
|
|
276
276
|
|
|
277
|
-
### Working with Files
|
|
278
|
-
|
|
279
|
-
Attach files to a document by adding them to the \_files property. For example:
|
|
280
|
-
|
|
281
|
-
```html
|
|
282
|
-
<input accept="image/*" title="save to Fireproof" type="file" id="files" multiple />
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
```js
|
|
286
|
-
function handleFiles() {
|
|
287
|
-
const fileList = this.files;
|
|
288
|
-
const doc = {
|
|
289
|
-
type: "files",
|
|
290
|
-
_files: {},
|
|
291
|
-
};
|
|
292
|
-
for (const file of fileList) {
|
|
293
|
-
// Assign each File object to the document
|
|
294
|
-
doc._files[file.name] = file;
|
|
295
|
-
}
|
|
296
|
-
database.put(doc);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
document.getElementById("files").addEventListener("change", handleFiles, false);
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
When loading a document with attachments, you can retrieve each attachment's actual File object by calling its .file() method. This returns a Promise that resolves with the File data, which you can display in your app:
|
|
303
|
-
|
|
304
|
-
```js
|
|
305
|
-
const doc = await database.get("my-doc-id");
|
|
306
|
-
for (const fileName in doc._files) {
|
|
307
|
-
const meta = doc._files[fileName];
|
|
308
|
-
if (meta.file) {
|
|
309
|
-
const fileObj = await meta.file();
|
|
310
|
-
console.log("Loaded file:", fileObj.name);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
See the final example application in this file for a working example.
|
|
316
|
-
|
|
317
277
|
### Form Validation
|
|
318
278
|
|
|
319
279
|
You can use React's `useState` to manage validation states and error messages. Validate inputs at the UI level before allowing submission.
|
|
@@ -425,74 +385,4 @@ export default function App() {
|
|
|
425
385
|
}
|
|
426
386
|
```
|
|
427
387
|
|
|
428
|
-
### Example Image Uploader
|
|
429
|
-
|
|
430
|
-
This React example shows a simple image uploader application that uses Fireproof to store and sort images by creation date. These APIs easily work with plain JavaScript also.
|
|
431
|
-
|
|
432
|
-
Code listing for App.jsx:
|
|
433
|
-
|
|
434
|
-
```js
|
|
435
|
-
import { useFireproof, ImgFile } from "use-fireproof";
|
|
436
|
-
import { useState } from "react";
|
|
437
|
-
|
|
438
|
-
export default function App() {
|
|
439
|
-
// 1. Hooks and document shapes
|
|
440
|
-
const { useDocument, useLiveQuery } = useFireproof("image-uploads");
|
|
441
|
-
const { doc, merge, submit } = useDocument({ _files: {}, description: "" });
|
|
442
|
-
const { docs } = useLiveQuery("_id", { descending: true, limit: 5 });
|
|
443
|
-
const [error, setError] = useState(false);
|
|
444
|
-
|
|
445
|
-
// 2. Event handlers
|
|
446
|
-
const handleFileChange = (e) => {
|
|
447
|
-
if (e.target.files[0]) merge({ _files: { uploaded: e.target.files[0] } });
|
|
448
|
-
};
|
|
449
|
-
|
|
450
|
-
const handleUpload = () => {
|
|
451
|
-
if (doc.description.trim()) {
|
|
452
|
-
submit();
|
|
453
|
-
} else {
|
|
454
|
-
setError(true);
|
|
455
|
-
}
|
|
456
|
-
};
|
|
457
|
-
|
|
458
|
-
// 3. ClassNames
|
|
459
|
-
const c = {
|
|
460
|
-
bg: "bg-white",
|
|
461
|
-
card: "bg-gray-50",
|
|
462
|
-
accent: "bg-blue-500 hover:bg-blue-600",
|
|
463
|
-
text: "text-gray-700",
|
|
464
|
-
};
|
|
465
|
-
|
|
466
|
-
// 4. JSX return
|
|
467
|
-
return (
|
|
468
|
-
<div className={`p-6 max-w-lg mx-auto ${c.bg} shadow-lg rounded-lg`}>
|
|
469
|
-
<h2 className="text-2xl font-bold mb-4">Image Uploader</h2>
|
|
470
|
-
<input type="file" accept="image/*" onChange={handleFileChange} className="mb-2 border p-2 w-full rounded" />
|
|
471
|
-
<input
|
|
472
|
-
type="text"
|
|
473
|
-
placeholder="Enter description"
|
|
474
|
-
value={doc.description}
|
|
475
|
-
onChange={(e) => {
|
|
476
|
-
setError(false);
|
|
477
|
-
merge({ description: e.target.value });
|
|
478
|
-
}}
|
|
479
|
-
className={`w-full p-2 border rounded mb-4 ${error ? "border-red-500" : "border-gray-300"}`}
|
|
480
|
-
/>
|
|
481
|
-
<button onClick={handleUpload} className={`px-4 py-2 ${c.accent} text-white rounded`}>
|
|
482
|
-
Upload
|
|
483
|
-
</button>
|
|
484
|
-
<h3 className="text-lg font-semibold mt-6">Recent Uploads</h3>
|
|
485
|
-
<div className="grid grid-cols-2 gap-4 mt-2">
|
|
486
|
-
{docs.map((doc) => (
|
|
487
|
-
<div key={doc._id} className={`border p-2 rounded shadow-sm ${c.card}`}>
|
|
488
|
-
{doc._files?.uploaded && <ImgFile file={doc._files.uploaded} alt="Uploaded Image" className="w-full h-auto rounded" />}
|
|
489
|
-
<p className={`text-sm ${c.text} mt-2`}>{doc.description || "No description"}</p>
|
|
490
|
-
</div>
|
|
491
|
-
))}
|
|
492
|
-
</div>
|
|
493
|
-
</div>
|
|
494
|
-
);
|
|
495
|
-
}
|
|
496
|
-
```
|
|
497
|
-
|
|
498
388
|
IMPORTANT: Don't use `useState()` on form data, instead use `merge()` and `submit()` from `useDocument`. Only use `useState` for ephemeral UI state (active tabs, open/closed panels, cursor positions). Keep your data model in Fireproof.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"img-vibes.js","sourceRoot":"","sources":["../../jsr/llms/img-vibes.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,cAAc,GAAc;IACvC,IAAI,EAAE,WAAW;IACjB,KAAK,EAAE,kBAAkB;IACzB,MAAM,EAAE,QAAQ;IAChB,WAAW,EAAE,0BAA0B;IACvC,YAAY,EAAE,WAAW;IACzB,UAAU,EAAE,UAAU;CACvB,CAAC"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# ImgVibes Component
|
|
2
|
+
|
|
3
|
+
## Basic Usage
|
|
4
|
+
|
|
5
|
+
The ImgVibes component can be used in several ways:
|
|
6
|
+
|
|
7
|
+
1. **With a prompt prop** - Immediately generates an image (cached across reloads):
|
|
8
|
+
|
|
9
|
+
```jsx
|
|
10
|
+
import { ImgVibes } from "img-vibes";
|
|
11
|
+
|
|
12
|
+
function MyComponent() {
|
|
13
|
+
return <ImgVibes prompt="A sunset over mountains" />;
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
2. **With an input image** - Edits or transforms an uploaded image:
|
|
18
|
+
|
|
19
|
+
```jsx
|
|
20
|
+
import { ImgVibes } from "img-vibes";
|
|
21
|
+
|
|
22
|
+
function MyComponent() {
|
|
23
|
+
const [file, setFile] = useState(null);
|
|
24
|
+
return (
|
|
25
|
+
<div>
|
|
26
|
+
<input type="file" accept="image/*" onChange={(e) => setFile(e.target.files[0])} />
|
|
27
|
+
{file && <ImgVibes prompt="Make it look like a watercolor painting" images={[file]} />}
|
|
28
|
+
</div>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The input image is automatically resized (max 1024px) and compressed as JPEG before sending.
|
|
34
|
+
|
|
35
|
+
3. **With an \_id prop** - Loads a specific image from the database:
|
|
36
|
+
|
|
37
|
+
```jsx
|
|
38
|
+
import { ImgVibes } from "img-vibes";
|
|
39
|
+
|
|
40
|
+
function MyComponent() {
|
|
41
|
+
return <ImgVibes _id="my-image-id" database={database} />;
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
If the document has a `prompt` field but no generated image yet, it will generate one automatically.
|
|
46
|
+
|
|
47
|
+
## Gallery Pattern
|
|
48
|
+
|
|
49
|
+
Images and prompts are tracked in a Fireproof database with a `type` of `image`. If a database is not provided, it uses `"ImgVibes"` as the default.
|
|
50
|
+
|
|
51
|
+
Display stored images by their ID using `useLiveQuery`:
|
|
52
|
+
|
|
53
|
+
```jsx
|
|
54
|
+
import { useFireproof } from "use-fireproof";
|
|
55
|
+
import { ImgVibes } from "img-vibes";
|
|
56
|
+
|
|
57
|
+
function MyComponent() {
|
|
58
|
+
const { database, useLiveQuery } = useFireproof("my-db-name");
|
|
59
|
+
const { docs: imageDocuments } = useLiveQuery("type", {
|
|
60
|
+
key: "image",
|
|
61
|
+
descending: true,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<div>
|
|
66
|
+
<ImgVibes database={database} prompt="A colorful landscape" />
|
|
67
|
+
{imageDocuments.length > 0 && (
|
|
68
|
+
<div className="history">
|
|
69
|
+
<h3>Previously Generated Images</h3>
|
|
70
|
+
<ul className="image-list">
|
|
71
|
+
{imageDocuments.map((doc) => (
|
|
72
|
+
<li key={doc._id} className="image-item">
|
|
73
|
+
<ImgVibes _id={doc._id} database={database} />
|
|
74
|
+
</li>
|
|
75
|
+
))}
|
|
76
|
+
</ul>
|
|
77
|
+
</div>
|
|
78
|
+
)}
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Passing User Images Through App State
|
|
85
|
+
|
|
86
|
+
When your app captures or collects images earlier in the flow (camera, file picker, canvas), store the `File` object in React state and pass it to `ImgVibes` later. This is the most common pattern for img2img — don't discard the user's image before reaching ImgVibes:
|
|
87
|
+
|
|
88
|
+
```jsx
|
|
89
|
+
import { useState } from "react";
|
|
90
|
+
import { ImgVibes } from "img-vibes";
|
|
91
|
+
|
|
92
|
+
function App() {
|
|
93
|
+
const [photo, setPhoto] = useState(null);
|
|
94
|
+
const [prompt, setPrompt] = useState("");
|
|
95
|
+
const [submitted, setSubmitted] = useState(false);
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<div>
|
|
99
|
+
{!submitted ? (
|
|
100
|
+
<>
|
|
101
|
+
<input type="file" accept="image/*" onChange={(e) => setPhoto(e.target.files[0])} />
|
|
102
|
+
<input value={prompt} onChange={(e) => setPrompt(e.target.value)} placeholder="Transform into..." />
|
|
103
|
+
<button onClick={() => setSubmitted(true)} disabled={!photo || !prompt}>
|
|
104
|
+
Go
|
|
105
|
+
</button>
|
|
106
|
+
</>
|
|
107
|
+
) : (
|
|
108
|
+
<ImgVibes prompt={prompt} images={[photo]} />
|
|
109
|
+
)}
|
|
110
|
+
</div>
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**Key rule**: Any time the user provides an image (camera capture, file upload, canvas export) and the app later generates an image based on it, the `File` must be kept in state and passed via the `images` prop. Never generate without the user's image when one was provided — that's the whole point of img2img.
|
|
116
|
+
|
|
117
|
+
## Caching and Versions
|
|
118
|
+
|
|
119
|
+
- Same prompt generates a deterministic `_id` (hash-based), so results are cached across reloads
|
|
120
|
+
- Each image has a **regenerate** button that creates a new version
|
|
121
|
+
- Use **prev/next** controls to navigate between versions
|
|
122
|
+
- Set `showControls={false}` to hide the regen and version navigation buttons
|
|
123
|
+
|
|
124
|
+
## Styling
|
|
125
|
+
|
|
126
|
+
ImgVibes supports custom styling through CSS variables or custom class names:
|
|
127
|
+
|
|
128
|
+
```jsx
|
|
129
|
+
// With CSS variables in your styles
|
|
130
|
+
:root {
|
|
131
|
+
--imggen-text-color: #222;
|
|
132
|
+
--imggen-accent: #0088ff;
|
|
133
|
+
--imggen-border-radius: 8px;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// With custom class names
|
|
137
|
+
<ImgVibes
|
|
138
|
+
prompt="A landscape"
|
|
139
|
+
className="my-custom-image"
|
|
140
|
+
/>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
#### Props
|
|
144
|
+
|
|
145
|
+
- `prompt`: Text prompt for image generation (required unless `_id` is provided)
|
|
146
|
+
- `images`: Array of `File` objects for img2img editing/transformation (uses first image, optional)
|
|
147
|
+
- `_id`: Document ID to load a specific image instead of generating a new one
|
|
148
|
+
- `database`: Database name or instance to use for storing images (default: `'ImgVibes'`)
|
|
149
|
+
- `className`: CSS class name for the image element (optional)
|
|
150
|
+
- `alt`: Alt text for the image element (optional)
|
|
151
|
+
- `style`: Inline styles for the image element (optional)
|
|
152
|
+
- `showControls`: Toggle regenerate and version navigation buttons (default: `true`)
|
package/llms/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { callaiConfig } from "./callai.js";
|
|
2
2
|
export { fireproofConfig } from "./fireproof.js";
|
|
3
|
-
export {
|
|
3
|
+
export { imgVibesConfig } from "./img-vibes.js";
|
|
4
4
|
export { webAudioConfig } from "./web-audio.js";
|
|
5
5
|
export { d3Config } from "./d3.js";
|
|
6
6
|
export { threeJsConfig } from "./three-js.js";
|
package/llms/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { callaiConfig } from "./callai.js";
|
|
2
2
|
import { fireproofConfig } from "./fireproof.js";
|
|
3
|
-
import {
|
|
3
|
+
import { imgVibesConfig } from "./img-vibes.js";
|
|
4
4
|
import { webAudioConfig } from "./web-audio.js";
|
|
5
5
|
import { d3Config } from "./d3.js";
|
|
6
6
|
import { threeJsConfig } from "./three-js.js";
|
|
7
7
|
export { callaiConfig } from "./callai.js";
|
|
8
8
|
export { fireproofConfig } from "./fireproof.js";
|
|
9
|
-
export {
|
|
9
|
+
export { imgVibesConfig } from "./img-vibes.js";
|
|
10
10
|
export { webAudioConfig } from "./web-audio.js";
|
|
11
11
|
export { d3Config } from "./d3.js";
|
|
12
12
|
export { threeJsConfig } from "./three-js.js";
|
|
13
|
-
export const allConfigs = [callaiConfig,
|
|
13
|
+
export const allConfigs = [callaiConfig, imgVibesConfig, webAudioConfig, d3Config, threeJsConfig, fireproofConfig];
|
|
14
14
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibes.diy/prompts",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"description": "",
|
|
@@ -24,14 +24,14 @@
|
|
|
24
24
|
"license": "Apache-2.0",
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@adviser/cement": "~0.5.34",
|
|
27
|
-
"@fireproof/core": "~0.24.
|
|
28
|
-
"@fireproof/core-keybag": "~0.24.
|
|
29
|
-
"@fireproof/core-runtime": "~0.24.
|
|
30
|
-
"@fireproof/core-types-base": "~0.24.
|
|
31
|
-
"@fireproof/core-types-protocols-cloud": "~0.24.
|
|
32
|
-
"@fireproof/use-fireproof": "~0.24.
|
|
33
|
-
"@vibes.diy/call-ai-v2": "^2.0.
|
|
34
|
-
"@vibes.diy/use-vibes-types": "^2.0.
|
|
27
|
+
"@fireproof/core": "~0.24.19",
|
|
28
|
+
"@fireproof/core-keybag": "~0.24.19",
|
|
29
|
+
"@fireproof/core-runtime": "~0.24.19",
|
|
30
|
+
"@fireproof/core-types-base": "~0.24.19",
|
|
31
|
+
"@fireproof/core-types-protocols-cloud": "~0.24.19",
|
|
32
|
+
"@fireproof/use-fireproof": "~0.24.19",
|
|
33
|
+
"@vibes.diy/call-ai-v2": "^2.0.6",
|
|
34
|
+
"@vibes.diy/use-vibes-types": "^2.0.6",
|
|
35
35
|
"arktype": "~2.2.0",
|
|
36
36
|
"json-schema-faker": "~0.6.1"
|
|
37
37
|
},
|
package/prompts.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import type { UserSettings } from "./settings.js";
|
|
2
|
-
import { Result } from "@adviser/cement";
|
|
3
2
|
import { LlmCatalogEntry } from "./json-docs.js";
|
|
4
|
-
import { ChatMessage } from "@vibes.diy/call-ai-v2";
|
|
5
3
|
export declare const DEFAULT_CODING_MODEL: "anthropic/claude-opus-4.5";
|
|
6
4
|
export declare function normalizeModelId(id: unknown): string | undefined;
|
|
7
5
|
export declare function isPermittedModelId(id: unknown): id is string;
|
|
@@ -10,21 +8,53 @@ export declare function resolveEffectiveModel(settingsDoc?: {
|
|
|
10
8
|
}, vibeDoc?: {
|
|
11
9
|
selectedModel?: string;
|
|
12
10
|
}): Promise<string>;
|
|
13
|
-
export declare function
|
|
11
|
+
export declare function getDefaultSkills(): Promise<string[]>;
|
|
12
|
+
export declare function makePreAllocUserMessage(userPrompt: string): Promise<string>;
|
|
13
|
+
export declare const preAllocSchema: {
|
|
14
|
+
readonly name: "pre_alloc";
|
|
15
|
+
readonly properties: {
|
|
16
|
+
readonly skills: {
|
|
17
|
+
readonly type: "array";
|
|
18
|
+
readonly description: "Selected skill names from the catalog above, appropriate for the app described by the user prompt. Only use names present in the catalog.";
|
|
19
|
+
readonly items: {
|
|
20
|
+
readonly type: "string";
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
readonly pairs: {
|
|
24
|
+
readonly type: "array";
|
|
25
|
+
readonly description: "Exactly 3 title/slug pairs ranked by fit. Title in Title Case, 1-4 words. Slug in kebab-case derived from title.";
|
|
26
|
+
readonly items: {
|
|
27
|
+
readonly type: "object";
|
|
28
|
+
readonly properties: {
|
|
29
|
+
readonly title: {
|
|
30
|
+
readonly type: "string";
|
|
31
|
+
};
|
|
32
|
+
readonly slug: {
|
|
33
|
+
readonly type: "string";
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
export declare const preAllocParsed: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
41
|
+
skills: string[];
|
|
42
|
+
pairs: {
|
|
43
|
+
title: string;
|
|
44
|
+
slug: string;
|
|
45
|
+
}[];
|
|
46
|
+
}, {}>;
|
|
47
|
+
export type PreAllocParsed = typeof preAllocParsed.infer;
|
|
14
48
|
export interface SystemPromptResult {
|
|
15
49
|
systemPrompt: string;
|
|
16
|
-
|
|
50
|
+
skills: string[];
|
|
17
51
|
demoData: boolean;
|
|
18
52
|
model: string;
|
|
19
53
|
}
|
|
20
|
-
|
|
21
|
-
|
|
54
|
+
export declare function generateImportStatements(llms: LlmCatalogEntry[]): string;
|
|
55
|
+
export interface MakeBaseSystemPromptOptions {
|
|
22
56
|
fetch?: typeof fetch;
|
|
23
|
-
readonly callAi: {
|
|
24
|
-
ModuleAndOptionsSelection(msgs: ChatMessage[]): Promise<Result<string>>;
|
|
25
|
-
};
|
|
26
57
|
}
|
|
27
|
-
export declare function
|
|
28
|
-
export declare function
|
|
58
|
+
export declare function makeBaseSystemPrompt(model: string, sessionDoc: Partial<UserSettings> & MakeBaseSystemPromptOptions): Promise<SystemPromptResult>;
|
|
59
|
+
export declare function getCliFooter(): Promise<string>;
|
|
29
60
|
export declare function getSkillText(name: string): Promise<string>;
|
|
30
|
-
export {};
|
package/prompts.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { loadAsset, KeyedResolvOnce } from "@adviser/cement";
|
|
2
2
|
import { getLlmCatalog, getLlmCatalogNames } from "./json-docs.js";
|
|
3
|
+
import { type } from "arktype";
|
|
3
4
|
import { defaultStylePrompt } from "./style-prompts.js";
|
|
4
5
|
export const DEFAULT_CODING_MODEL = "anthropic/claude-opus-4.5";
|
|
5
|
-
const RAG_DECISION_MODEL = "openai/gpt-4o";
|
|
6
6
|
async function defaultCodingModel() {
|
|
7
7
|
return DEFAULT_CODING_MODEL;
|
|
8
8
|
}
|
|
@@ -27,70 +27,47 @@ export async function resolveEffectiveModel(settingsDoc, vibeDoc) {
|
|
|
27
27
|
return globalChoice;
|
|
28
28
|
return defaultCodingModel();
|
|
29
29
|
}
|
|
30
|
-
export async function
|
|
31
|
-
return ["fireproof", "callai", "web-audio"];
|
|
30
|
+
export async function getDefaultSkills() {
|
|
31
|
+
return ["fireproof", "callai", "img-vibes", "web-audio"];
|
|
32
32
|
}
|
|
33
|
-
async function
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
33
|
+
export async function makePreAllocUserMessage(userPrompt) {
|
|
34
|
+
const catalog = await getLlmCatalog();
|
|
35
|
+
const catalogText = catalog.map((l) => `- ${l.name}: ${l.description}`).join("\n");
|
|
36
|
+
return [
|
|
37
|
+
"Pick skills from this catalog that fit the user's app request, and propose 3 title/slug pairs for naming.",
|
|
38
|
+
"",
|
|
39
|
+
"Skill catalog:",
|
|
40
|
+
catalogText,
|
|
41
|
+
"",
|
|
42
|
+
"User request:",
|
|
43
|
+
userPrompt,
|
|
44
|
+
].join("\n");
|
|
43
45
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
{
|
|
61
|
-
role: "system",
|
|
62
|
-
content: [
|
|
63
|
-
{
|
|
64
|
-
type: "text",
|
|
65
|
-
text: `You select which library modules from a catalog should
|
|
66
|
-
be included AND whether to include a demo-data button.
|
|
67
|
-
First analyze if the user prompt describes specific
|
|
68
|
-
look & feel requirements. For demo data: include it
|
|
69
|
-
only when asked for. Read the JSON payload and return
|
|
70
|
-
JSON with properties:
|
|
71
|
-
"selected" (array of catalog "name" strings) and "demoData" (boolean).
|
|
72
|
-
Only choose modules from the catalog. Include any
|
|
73
|
-
libraries already used in history. Respond with JSON only.`,
|
|
46
|
+
export const preAllocSchema = {
|
|
47
|
+
name: "pre_alloc",
|
|
48
|
+
properties: {
|
|
49
|
+
skills: {
|
|
50
|
+
type: "array",
|
|
51
|
+
description: "Selected skill names from the catalog above, appropriate for the app described by the user prompt. Only use names present in the catalog.",
|
|
52
|
+
items: { type: "string" },
|
|
53
|
+
},
|
|
54
|
+
pairs: {
|
|
55
|
+
type: "array",
|
|
56
|
+
description: "Exactly 3 title/slug pairs ranked by fit. Title in Title Case, 1-4 words. Slug in kebab-case derived from title.",
|
|
57
|
+
items: {
|
|
58
|
+
type: "object",
|
|
59
|
+
properties: {
|
|
60
|
+
title: { type: "string" },
|
|
61
|
+
slug: { type: "string" },
|
|
74
62
|
},
|
|
75
|
-
|
|
63
|
+
},
|
|
76
64
|
},
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
const rParsed = exception2Result(() => JSON.parse(rRaw.Ok()) ?? {});
|
|
85
|
-
if (rParsed.isErr()) {
|
|
86
|
-
console.warn("Module/options selection: Failed to parse JSON response:", rRaw.Ok());
|
|
87
|
-
return { selected: [], demoData: true };
|
|
88
|
-
}
|
|
89
|
-
const parsed = rParsed.Ok();
|
|
90
|
-
const selected = Array.isArray(parsed?.selected) ? parsed.selected.filter((v) => typeof v === "string") : [];
|
|
91
|
-
const demoData = typeof parsed?.demoData === "boolean" ? parsed.demoData : true;
|
|
92
|
-
return { selected, demoData };
|
|
93
|
-
}
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
export const preAllocParsed = type({
|
|
68
|
+
skills: type("string").array(),
|
|
69
|
+
pairs: type({ title: "string", slug: "string" }).array(),
|
|
70
|
+
});
|
|
94
71
|
export function generateImportStatements(llms) {
|
|
95
72
|
const seen = new Set();
|
|
96
73
|
return llms
|
|
@@ -121,30 +98,18 @@ export function generateImportStatements(llms) {
|
|
|
121
98
|
const keyedLoadAsset = new KeyedResolvOnce();
|
|
122
99
|
export async function makeBaseSystemPrompt(model, sessionDoc) {
|
|
123
100
|
const userPrompt = sessionDoc?.userPrompt || "";
|
|
124
|
-
const history = Array.isArray(sessionDoc?.history) ? sessionDoc.history : [];
|
|
125
|
-
const useOverride = !!sessionDoc?.dependenciesUserOverride;
|
|
126
|
-
let selectedNames = [];
|
|
127
|
-
let includeDemoData = true;
|
|
128
101
|
const llmsCatalog = await getLlmCatalog();
|
|
129
102
|
const llmsCatalogNames = await getLlmCatalogNames();
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const decisions = await selectLlmsAndOptions(RAG_DECISION_MODEL, userPrompt, history, sessionDoc);
|
|
137
|
-
includeDemoData = decisions.demoData;
|
|
138
|
-
const detected = await detectModulesInHistory(history, sessionDoc);
|
|
139
|
-
const finalNames = new Set([...decisions.selected, ...detected]);
|
|
140
|
-
selectedNames = Array.from(finalNames);
|
|
141
|
-
if (selectedNames.length === 0)
|
|
142
|
-
selectedNames = [...(await getDefaultDependencies())];
|
|
143
|
-
}
|
|
144
|
-
if (typeof sessionDoc?.demoDataOverride === "boolean") {
|
|
145
|
-
includeDemoData = sessionDoc.demoDataOverride;
|
|
103
|
+
const rawSkills = Array.isArray(sessionDoc?.skills) ? sessionDoc.skills : undefined;
|
|
104
|
+
let selectedNames = rawSkills
|
|
105
|
+
? rawSkills.filter((v) => typeof v === "string").filter((name) => llmsCatalogNames.has(name))
|
|
106
|
+
: [];
|
|
107
|
+
if (selectedNames.length === 0) {
|
|
108
|
+
selectedNames = [...(await getDefaultSkills())];
|
|
146
109
|
}
|
|
110
|
+
const includeDemoData = sessionDoc?.demoData === true;
|
|
147
111
|
const chosenLlms = llmsCatalog.filter((l) => selectedNames.includes(l.name));
|
|
112
|
+
console.log("[makeBaseSystemPrompt] chosen modules:", chosenLlms.map((l) => l.name));
|
|
148
113
|
const concatenatedLlmsTxts = [];
|
|
149
114
|
for (const llm of chosenLlms) {
|
|
150
115
|
const rText = await keyedLoadAsset.get(llm.name).once(async () => {
|
|
@@ -188,21 +153,29 @@ export async function makeBaseSystemPrompt(model, sessionDoc) {
|
|
|
188
153
|
"- Use `callAI` to fetch AI, use schema like this: `JSON.parse(await callAI(prompt, { schema: { properties: { todos: { type: 'array', items: { type: 'string' } } } } }))` and save final responses as individual Fireproof documents.",
|
|
189
154
|
"- For file uploads use drag and drop and store using the `doc._files` API",
|
|
190
155
|
"- Don't try to generate png or base64 data, use placeholder image APIs instead, like https://picsum.photos/400 where 400 is the square size",
|
|
156
|
+
"- Never use emojis in the UI. Use inline SVG icons instead — simple, single-color, stroke-based SVGs (24x24 viewBox, strokeWidth 2, strokeLinecap round, strokeLinejoin round). Build icons directly in JSX, do not import icon libraries.",
|
|
191
157
|
"- Consider and potentially reuse/extend code from previous responses if relevant",
|
|
192
158
|
"- Always output the full component code, keep the explanation short and concise",
|
|
193
159
|
"- Never also output a small snippet to change, just the full component code",
|
|
194
160
|
"- Keep your component file as short as possible for fast updates",
|
|
195
|
-
"-
|
|
161
|
+
"- IMPORTANT: Never change the database name from what it was in the previous code. Changing the database name loses all existing user data. If the previous code used a specific database name, you MUST use that exact same name.",
|
|
196
162
|
"- The system can send you crash reports, fix them by simplifying the affected code",
|
|
197
163
|
"- List data items on the main page of your app so users don't have to hunt for them",
|
|
198
164
|
"- If you save data, make sure it is browsable in the app, eg lists should be clickable for more details",
|
|
199
165
|
demoDataLines,
|
|
200
166
|
];
|
|
167
|
+
const titleLines = sessionDoc?.title
|
|
168
|
+
? [
|
|
169
|
+
`The app is called "${sessionDoc.title}". Use this exact name in the app's heading and anywhere the app refers to itself.`,
|
|
170
|
+
"",
|
|
171
|
+
]
|
|
172
|
+
: [];
|
|
201
173
|
const systemPrompt = [
|
|
202
174
|
systemPromptLines.join("\n"),
|
|
203
175
|
"",
|
|
204
176
|
concatenatedLlmsTxt,
|
|
205
177
|
"",
|
|
178
|
+
...titleLines,
|
|
206
179
|
...(userPrompt ? [userPrompt, ""] : []),
|
|
207
180
|
"IMPORTANT: You are working in one JavaScript file. Define a classNames object just before the JSX return for colors and repeated styles, then reference it in your JSX.",
|
|
208
181
|
"",
|
|
@@ -221,11 +194,23 @@ export async function makeBaseSystemPrompt(model, sessionDoc) {
|
|
|
221
194
|
].join("\n");
|
|
222
195
|
return {
|
|
223
196
|
systemPrompt,
|
|
224
|
-
|
|
197
|
+
skills: selectedNames,
|
|
225
198
|
demoData: includeDemoData,
|
|
226
199
|
model,
|
|
227
200
|
};
|
|
228
201
|
}
|
|
202
|
+
export async function getCliFooter() {
|
|
203
|
+
const rText = await keyedLoadAsset.get("cli-footer").once(async () => {
|
|
204
|
+
return loadAsset("./cli-footer.md", {
|
|
205
|
+
fallBackUrl: "https://esm.sh/@vibes.diy/prompts/",
|
|
206
|
+
basePath: () => import.meta.url,
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
if (rText.isErr()) {
|
|
210
|
+
return Promise.reject(rText.Err());
|
|
211
|
+
}
|
|
212
|
+
return rText.Ok();
|
|
213
|
+
}
|
|
229
214
|
export async function getSkillText(name) {
|
|
230
215
|
const rText = await keyedLoadAsset.get(name).once(async () => {
|
|
231
216
|
return loadAsset(`./llms/${name}.md`, {
|
package/prompts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../jsr/prompts.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../jsr/prompts.ts"],"names":[],"mappings":"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"}
|
package/settings.d.ts
CHANGED
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
export interface HistoryMessage {
|
|
2
|
-
role: "user" | "assistant" | "system";
|
|
3
|
-
content: string;
|
|
4
|
-
}
|
|
5
1
|
export interface UserSettings {
|
|
6
2
|
_id: string;
|
|
7
3
|
stylePrompt?: string;
|
|
8
4
|
userPrompt?: string;
|
|
9
5
|
model?: string;
|
|
10
6
|
showModelPickerInChat?: boolean;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
demoDataOverride?: boolean;
|
|
7
|
+
skills?: string[];
|
|
8
|
+
title?: string;
|
|
9
|
+
demoData?: boolean;
|
|
15
10
|
}
|
package/style-prompts.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export const stylePrompts = [
|
|
2
2
|
{
|
|
3
3
|
name: "brutalist web",
|
|
4
|
-
prompt: '
|
|
4
|
+
prompt: 'THEME: Neobrutalist — Neobrutalist Design System. A bold, retro-arcade-inspired neobrutalist theme. Hard edges, chunky black borders, thick offset drop shadows, vivid primary color blocks, and uppercase display typography. The mood is playful and unapologetically loud without leaning on direct IP references — it is "level dashboard" energy: raw, graphic, readable, kinetic.\n\nCOLOR PALETTE (oklch): --bg: oklch(0.96 0.01 90) warm off-white canvas; --card-bg: oklch(1.00 0 0) pure white surfaces; --text: oklch(0.15 0.02 280) near-black ink, cool undertone; --border: oklch(0.15 0.02 280) same as text — every stroke is bold; --muted: oklch(0.50 0.02 280) secondary labels; --accent/--red: oklch(0.55 0.24 28) primary action/danger; --yellow: oklch(0.85 0.18 85) highlight/hover; --yellow-dark: oklch(0.75 0.16 85); --green: oklch(0.62 0.19 145) success/active; --blue: oklch(0.52 0.18 255) info/informational accents; --accent-light: oklch(0.55 0.24 28 / 0.1).\n\nTOKENS: --radius: 4px (tiny, never pill-shaped); --shadow: 4px 4px 0px var(--border); --shadow-sm: 3px 3px 0px var(--border).\n\nTYPOGRAPHY: Primary: "Space Grotesk", sans-serif (400, 500, 600, 700). Mono: "JetBrains Mono", monospace (400, 500, 700) — for stats, numbers, tabular data. Loaded from Google Fonts only, no other external deps. Headings are UPPERCASE with tight tracking (-0.02em) and heavy weight (700). Section labels: 0.65rem, uppercase, letter-spacing 0.15em, muted color. Nav/button labels: 0.7–0.8rem, uppercase, letter-spacing 0.05–0.08em.\n\nSURFACE & BORDER LANGUAGE: Every primary surface (nav, cards, hero, modal, inputs, buttons) has a solid 3px var(--border) outline and border-radius of 4px. No gradients on strokes, no thin hairlines. Every elevated surface carries a hard offset shadow — 4px 4px 0px var(--border) by default, 3px 3px for smaller chips, 6px 6px on hover for lift, 8px 8px on modals. Shadows are NEVER blurred. Hover pattern: transform: translate(-2px, -2px) combined with a larger hard shadow — gives a "card pops forward" feel. Active/pressed state flips to translate(2px, 2px) with box-shadow: none — the object visibly slams back down. Transitions: 0.15s for micro-interactions, 0.2s cubic-bezier(0.34, 1.56, 0.64, 1) for toggle knobs (slight overshoot).\n\nLAYOUT: A single centered column, max-width: 920px, padding 3rem 2rem, position: relative; z-index: 10; so it sits above ambient background decorations.\n\nAMBIENT BACKGROUND: Fixed inset grid: two linear-gradients at 60px × 60px with oklch(0.15 0.02 280 / 0.04) — subtle graph-paper feel. 8 floating geometric blocks (.float-block-1..8) placed across the viewport edges, sizes 25–80px, in --red/--yellow/--green/--blue, some square some circular (border-radius: 50%), opacity 0.15–0.3 so they don\'t overpower content. 2 floating plus/cross shapes built from ::before/::after pseudo-elements (40×40, arms 10px thick) — var(--border) color, low opacity. 2 floating diamonds — 30×30 --yellow squares with 3px borders, rotated 45deg. Keyframes (all on loops 5–12s, ease-in-out or linear): drift-spin-1, drift-spin-2, drift-bounce, drift-diagonal, drift-zigzag, drift-pulse, drift-diamond. The shapes should drift, not race.\n\nSECTION COMPOSITION: 1. NAV: Card-style bar with 3px border, shadow, 4px radius. Left: logo = three 12×12 squares (red/yellow/green) + uppercase brand text. Right: .nav-link pill-looking-but-square chips + .status-badge in --green with pulsing 7px dot. 2. HERO: Big bordered card with .hero-accent-bar along the top: a 6px horizontal rainbow split into four equal segments — red 0–25%, yellow 25–50%, green 50–75%, blue 75–100%. Big clamped uppercase title with .hero-text-shadow duplicate offset 5px/5px in --red, opacity 0.5. 3. STAT ROW: 4-column grid of .stat-cards (collapses to 2 then 1 on small screens). Each card has colored header bar: child 1 = --red (white text), 2 = --yellow (dark text), 3 = --blue (white text), 4 = --green (dark text). Body shows big mono number + small uppercase unit label. 4. TABLE: Full-bleed inside bordered card. th: 0.6rem uppercase, 2px bottom border. td: 0.82rem, thin separators. Columns 3 & 4 use JetBrains Mono. Row hover fills with --yellow instantly. Badge styles: badge-active (--green), badge-pending (--yellow), badge-locked (neutral gray). 5. FORM + CONTROLS GRID: 2-column grid of cards. Left: text input + select + progress bar + primary/secondary buttons. Inputs lift on focus with translate(-2px,-2px) + shadow. Progress bar has repeating striped gradient at -45° in --green. Right: checkboxes (22×22, 3px border, --green when checked) + toggles (48×26, 3px border, 4px radius, --yellow when on, knob translates with overshoot) + tag row in four colors. 6. ACTIONS CARD: Flex row with .btn-primary (--red bg, white text, 4×4 shadow), .btn-secondary (--yellow bg, 3×3 shadow), .btn-ghost (card-bg, no shadow, gains 3×3 on hover). 7. MODAL: Overlay oklch(0.15 0.02 280 / 0.6). Modal card: 3px border, 8×8 hard shadow, entry animation modal-pop. .modal-bar: --blue title strip with white text.\n\nINTERACTION: Nothing eases slowly. All hovers/presses resolve in ≤0.2s. Hover lifts up-and-left; press slams down-and-right. Nothing uses soft blur. Every shadow is a discrete offset block. Rounded corners are tiny (4px) everywhere. Color use: --red is primary/danger; --yellow is highlight/warning; --green is success/status; --blue is informational. Don\'t tint surfaces — keep all cards --card-bg white.\n\nACCESSIBILITY: Body text ≥0.82rem, section labels ≥0.6rem. Strong contrast (text on red → white; text on yellow → ink; text on green → ink; text on blue → white). aria-hidden the decorative .hero-text-shadow.\n\nRESPONSIVENESS: ≤700px: stat row collapses to 2 columns, form grid to 1 column. ≤500px: nav stacks vertically, stat row to single column.\n\nFONTS: Use Google Fonts for Space Grotesk (400,500,600,700) and JetBrains Mono (400,500,700). Apply this theme to the generated React component.',
|
|
5
5
|
},
|
|
6
6
|
{
|
|
7
7
|
name: "memphis",
|
package/style-prompts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style-prompts.js","sourceRoot":"","sources":["../jsr/style-prompts.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,YAAY,GAAkB;IAIzC;QACE,IAAI,EAAE,eAAe;QACrB,MAAM,EACJ,
|
|
1
|
+
{"version":3,"file":"style-prompts.js","sourceRoot":"","sources":["../jsr/style-prompts.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,YAAY,GAAkB;IAIzC;QACE,IAAI,EAAE,eAAe;QACrB,MAAM,EACJ,o0LAAo0L;KACv0L;IACD;QACE,IAAI,EAAE,SAAS;QACf,MAAM,EACJ,+8BAA+8B;KACl9B;IACD;QACE,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,uBAAuB;KAChC;IACD;QACE,IAAI,EAAE,YAAY;QAClB,MAAM,EAAE,sBAAsB;KAC/B;IACD;QACE,IAAI,EAAE,YAAY;QAClB,MAAM,EAAE,mBAAmB;KAC5B;IACD;QACE,IAAI,EAAE,cAAc;QACpB,MAAM,EAAE,mBAAmB;KAC5B;IACD;QACE,IAAI,EAAE,aAAa;QACnB,MAAM,EAAE,kBAAkB;KAC3B;IACD;QACE,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,qBAAqB;KAC9B;IACD;QACE,IAAI,EAAE,YAAY;QAClB,MAAM,EAAE,0BAA0B;KACnC;IACD;QACE,IAAI,EAAE,cAAc;QACpB,MAAM,EAAE,kBAAkB;KAC3B;IACD;QACE,IAAI,EAAE,UAAU;QAChB,MAAM,EACJ,orCAAorC;KACvrC;CACF,CAAC;AAGF,MAAM,CAAC,MAAM,kBAAkB,GAAG,eAAwB,CAAC;AAG3D,MAAM,WAAW,GAAG,IAAI,GAAG,EAAuB,CAAC;AACnD,KAAK,MAAM,CAAC,IAAI,YAAY,EAAE,CAAC;IAC7B,IAAI,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC,IAAI,gCAAgC,CAAC,CAAC;IAC7F,CAAC;IACD,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AAC7B,CAAC;AAGD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,GAAG,EAAE;IACtC,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAClD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5D,MAAM,IAAI,KAAK,CACb,uBAAuB,kBAAkB,iDAAiD,SAAS,gDAAgD,CACpJ,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC,MAAM,CAAC;AACtB,CAAC,CAAC,EAAE,CAAC"}
|
package/llms/image-gen.d.ts
DELETED
package/llms/image-gen.js
DELETED
package/llms/image-gen.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"image-gen.js","sourceRoot":"","sources":["../../jsr/llms/image-gen.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,cAAc,GAAc;IACvC,IAAI,EAAE,WAAW;IACjB,KAAK,EAAE,kBAAkB;IACzB,MAAM,EAAE,QAAQ;IAChB,WAAW,EAAE,0BAA0B;IACvC,YAAY,EAAE,WAAW;IACzB,UAAU,EAAE,QAAQ;CACrB,CAAC"}
|
package/llms/image-gen.md
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
# ImgGen Component
|
|
2
|
-
|
|
3
|
-
## Basic Usage
|
|
4
|
-
|
|
5
|
-
The ImgGen component can be used in three ways:
|
|
6
|
-
|
|
7
|
-
1. **With no props** - Shows a form UI for users to enter a prompt and/or upload images:
|
|
8
|
-
|
|
9
|
-
```jsx
|
|
10
|
-
import { ImgGen } from "use-vibes";
|
|
11
|
-
|
|
12
|
-
function MyComponent() {
|
|
13
|
-
return <ImgGen />; // Shows built-in form for prompt entry and image upload
|
|
14
|
-
}
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
2. **With a prompt prop** - Immediately generates an image (no form shown):
|
|
18
|
-
|
|
19
|
-
```jsx
|
|
20
|
-
import { ImgGen } from "use-vibes";
|
|
21
|
-
|
|
22
|
-
function MyComponent() {
|
|
23
|
-
return <ImgGen prompt="A sunset over mountains" />; // Direct generation, no form
|
|
24
|
-
}
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
3. **With images prop** - Edits or combines images with AI (no form shown):
|
|
28
|
-
|
|
29
|
-
```jsx
|
|
30
|
-
import { ImgGen } from "use-vibes";
|
|
31
|
-
|
|
32
|
-
function MyComponent() {
|
|
33
|
-
const [files, setFiles] = useState([]);
|
|
34
|
-
return (
|
|
35
|
-
<ImgGen
|
|
36
|
-
prompt="Create a gift basket with these items"
|
|
37
|
-
images={files} // Array of File objects
|
|
38
|
-
/>
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
4. **With an \_id prop** - Loads a specific image from the database (no form shown):
|
|
44
|
-
|
|
45
|
-
If there is no image generated for the document yet, but it has a `prompt` field, it will generate a new image with the prompt. If there an images is stored, at doc.\_files.original, it will use that as the base image.
|
|
46
|
-
|
|
47
|
-
```jsx
|
|
48
|
-
import { ImgGen } from "use-vibes";
|
|
49
|
-
|
|
50
|
-
function MyComponent() {
|
|
51
|
-
return <ImgGen _id="my-image-id" />; // Loads specific image by ID
|
|
52
|
-
}
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
## List by ID
|
|
56
|
-
|
|
57
|
-
Images and prompts are tracked in a Fireproof database with a `type` of `image`. If a database is not provided, it uses `"ImgGen"` as the database name.
|
|
58
|
-
|
|
59
|
-
Display stored images by their ID. Ensure you do this, so users can find the images they created.
|
|
60
|
-
|
|
61
|
-
```jsx
|
|
62
|
-
import { useFireproof } from "use-fireproof";
|
|
63
|
-
import { ImgGen } from "use-vibes";
|
|
64
|
-
|
|
65
|
-
function MyComponent() {
|
|
66
|
-
const { database, useLiveQuery } = useFireproof("my-db-name");
|
|
67
|
-
const { docs: imageDocuments } = useLiveQuery("type", {
|
|
68
|
-
key: "image",
|
|
69
|
-
descending: true,
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
return (
|
|
73
|
-
<div>
|
|
74
|
-
<ImgGen database={database} />
|
|
75
|
-
{imageDocuments.length > 0 && (
|
|
76
|
-
<div className="history">
|
|
77
|
-
<h3>Previously Generated Images</h3>
|
|
78
|
-
<ul className="image-list">
|
|
79
|
-
{imageDocuments.map((doc) => (
|
|
80
|
-
<li key={doc._id} className="image-item">
|
|
81
|
-
<ImgGen _id={doc._id} database={database} />
|
|
82
|
-
</li>
|
|
83
|
-
))}
|
|
84
|
-
</ul>
|
|
85
|
-
</div>
|
|
86
|
-
)}
|
|
87
|
-
</div>
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
## Styling
|
|
93
|
-
|
|
94
|
-
ImgGen supports custom styling through CSS variables or custom class names:
|
|
95
|
-
|
|
96
|
-
```jsx
|
|
97
|
-
// With CSS variables in your styles
|
|
98
|
-
:root {
|
|
99
|
-
--imggen-text-color: #222;
|
|
100
|
-
--imggen-accent: #0088ff;
|
|
101
|
-
--imggen-border-radius: 8px;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// With custom class names
|
|
105
|
-
<ImgGen
|
|
106
|
-
prompt="A landscape"
|
|
107
|
-
className="my-custom-image"
|
|
108
|
-
classes={{
|
|
109
|
-
root: 'custom-container',
|
|
110
|
-
image: 'custom-img',
|
|
111
|
-
overlay: 'custom-overlay'
|
|
112
|
-
}}
|
|
113
|
-
/>
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
#### Props
|
|
117
|
-
|
|
118
|
-
- `prompt`: Text prompt for image generation (required unless `_id` is provided)
|
|
119
|
-
- `_id`: Document ID to load a specific image instead of generating a new one
|
|
120
|
-
- `database`: Database name or instance to use for storing images (default: `'ImgGen'`)- `options` (object, optional): Configuration options for image generation
|
|
121
|
-
- `model` (string, optional): Model to use for image generation, defaults to 'gpt-image-1'
|
|
122
|
-
- `size` (string, optional): Size of the generated image (Must be one of 1024x1024, 1536x1024 (landscape), 1024x1536 (portrait), or 'auto' (default value) for gpt-image-1, and one of 256x256, 512x512, or 1024x1024 for dall-e-2.)
|
|
123
|
-
- `quality` (string, optional): Quality of the generated image (high, medium and low are only supported for gpt-image-1. dall-e-2 only supports standard quality. Defaults to auto.)
|
|
124
|
-
- `debug` (boolean, optional): Enable debug logging, defaults to false
|
|
125
|
-
- `onLoad`: Callback when image load completes successfully
|
|
126
|
-
- `onError`: Callback when image load fails, receives the error as parameter
|
|
127
|
-
- `className`: CSS class name for the image element (optional)- `classes`: Object containing custom CSS classes for styling component parts (see Styling section)
|
package/load-docs.ts-off
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { CoerceURI, Result } from "@adviser/cement";
|
|
2
|
-
import { joinUrlParts } from "call-ai";
|
|
3
|
-
|
|
4
|
-
export async function loadDocs(localPath: string, baseUrl: CoerceURI): Promise<Result<string>> {
|
|
5
|
-
const url = joinUrlParts(baseUrl?.toString() || "", localPath);
|
|
6
|
-
try {
|
|
7
|
-
const response = await fetch(url);
|
|
8
|
-
if (!response.ok) {
|
|
9
|
-
return Result.Err(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);
|
|
10
|
-
}
|
|
11
|
-
const text = await response.text();
|
|
12
|
-
return Result.Ok(text);
|
|
13
|
-
} catch (error) {
|
|
14
|
-
return Result.Err(`Error fetching ${url}: ${error}`);
|
|
15
|
-
}
|
|
16
|
-
}
|
package/txt-docs.ts-off
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { CoerceURI, ResolveOnce } from "@adviser/cement";
|
|
2
|
-
// import { loadDocs } from "./load-docs.js";
|
|
3
|
-
|
|
4
|
-
// TODO: Replace loadDocs with loadAsset for better cement integration
|
|
5
|
-
|
|
6
|
-
export interface TxtDoc {
|
|
7
|
-
readonly name: string;
|
|
8
|
-
readonly txt: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const files = ["callai.txt", "fireproof.txt", "image-gen.txt", "web-audio.txt", "d3.md", "three-js.md"];
|
|
12
|
-
|
|
13
|
-
// // Lazy loading per file instead of eager loading all files
|
|
14
|
-
// const fileLoaders = new Map<string, ResolveOnce<TxtDoc | undefined>>();
|
|
15
|
-
|
|
16
|
-
// function getFileLoader(file: string, fallBackUrl: CoerceURI): ResolveOnce<TxtDoc | undefined> {
|
|
17
|
-
// const key = `${fallBackUrl?.toString() || ""}:${file}`;
|
|
18
|
-
// if (!fileLoaders.has(key)) {
|
|
19
|
-
// fileLoaders.set(key, new ResolveOnce<TxtDoc | undefined>());
|
|
20
|
-
// }
|
|
21
|
-
// const loader = fileLoaders.get(key);
|
|
22
|
-
// if (!loader) {
|
|
23
|
-
// throw new Error(`File loader not found for key: ${key}`);
|
|
24
|
-
// }
|
|
25
|
-
// return loader;
|
|
26
|
-
// }
|
|
27
|
-
|
|
28
|
-
// async function loadTxtDoc(file: string, fallBackUrl: CoerceURI): Promise<TxtDoc | undefined> {
|
|
29
|
-
// const loader = getFileLoader(file, fallBackUrl);
|
|
30
|
-
// return loader.once(async () => {
|
|
31
|
-
// const rAsset = await loadDocs(file, fallBackUrl);
|
|
32
|
-
// if (rAsset.isErr()) {
|
|
33
|
-
// console.error(`Failed to load asset ${file}: ${rAsset.Err()}`);
|
|
34
|
-
// return undefined;
|
|
35
|
-
// }
|
|
36
|
-
// return { name: file, txt: rAsset.Ok() };
|
|
37
|
-
// });
|
|
38
|
-
// }
|
|
39
|
-
|
|
40
|
-
// export async function getTexts(name: string, fallBackUrl: CoerceURI): Promise<string | undefined> {
|
|
41
|
-
// name = name.toLocaleLowerCase().trim();
|
|
42
|
-
|
|
43
|
-
// // Try exact match first by looking for the file directly
|
|
44
|
-
// for (const file of files) {
|
|
45
|
-
// const fileName =
|
|
46
|
-
// file
|
|
47
|
-
// .split("/")
|
|
48
|
-
// .pop()
|
|
49
|
-
// ?.toLowerCase()
|
|
50
|
-
// .replace(/\.(txt|md)$/, "") || "";
|
|
51
|
-
// if (fileName === name) {
|
|
52
|
-
// const doc = await loadTxtDoc(file, fallBackUrl);
|
|
53
|
-
// return doc?.txt;
|
|
54
|
-
// }
|
|
55
|
-
// }
|
|
56
|
-
|
|
57
|
-
// return undefined;
|
|
58
|
-
// }
|