howone 0.1.23 → 0.1.25
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/package.json +1 -1
- package/templates/vite/.howone/skills/howone-sdk/01-architect/01-app-generation.md +180 -91
- package/templates/vite/.howone/skills/howone-sdk/01-architect/02-manifest-codegen.md +67 -4
- package/templates/vite/.howone/skills/howone-sdk/02-database/01-schema-design.md +463 -69
- package/templates/vite/.howone/skills/howone-sdk/02-database/02-schema-operations.md +366 -64
- package/templates/vite/.howone/skills/howone-sdk/02-database/03-data-access-patterns.md +204 -67
- package/templates/vite/.howone/skills/howone-sdk/02-database/04-query-dsl-and-responses.md +237 -0
- package/templates/vite/.howone/skills/howone-sdk/02-database/05-ai-persistence-patterns.md +372 -0
- package/templates/vite/.howone/skills/howone-sdk/03-sdk/01-client-setup.md +58 -36
- package/templates/vite/.howone/skills/howone-sdk/03-sdk/02-entity-operations.md +67 -0
- package/templates/vite/.howone/skills/howone-sdk/03-sdk/03-auth.md +267 -469
- package/templates/vite/.howone/skills/howone-sdk/03-sdk/04-react-integration.md +113 -320
- package/templates/vite/.howone/skills/howone-sdk/03-sdk/07-ai-action-calls.md +66 -16
- package/templates/vite/.howone/skills/howone-sdk/03-sdk/08-extension-boundaries.md +226 -0
- package/templates/vite/.howone/skills/howone-sdk/04-ai/01-ai-capability-architecture.md +159 -96
- package/templates/vite/.howone/skills/howone-sdk/04-ai/02-workflow-contract-rules.md +353 -96
- package/templates/vite/.howone/skills/howone-sdk/04-ai/03-ai-sdk-handoff.md +181 -42
- package/templates/vite/.howone/skills/howone-sdk/04-ai/04-service-capability-catalog.md +281 -0
- package/templates/vite/.howone/skills/howone-sdk/04-ai/05-workflow-operations.md +256 -0
- package/templates/vite/.howone/skills/howone-sdk/04-ai/06-ai-feature-playbooks.md +296 -0
- package/templates/vite/.howone/skills/howone-sdk/SKILL.md +29 -12
- package/templates/vite/.howone/skills/howone-sdk/agents/openai.yaml +2 -2
- package/templates/vite/package.json +1 -1
- package/templates/vite/.howone/skills/howone-sdk/04-ai/.gitkeep +0 -1
package/package.json
CHANGED
|
@@ -1,126 +1,215 @@
|
|
|
1
1
|
# App Generation Architect
|
|
2
2
|
|
|
3
|
-
Use this file
|
|
4
|
-
|
|
3
|
+
Use this file before building or changing a HowOne generated app. It decides which platform tracks
|
|
4
|
+
must be used and what order to execute them in.
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
This is the planning layer. It should prevent the agent from jumping straight into UI code while
|
|
7
|
+
missing schema, auth, AI, manifest, or SDK binding contracts.
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
## Platform Shape
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
manifests.
|
|
12
|
-
2. **AI contract + workflow implementation**: AI capability contracts are versioned by HowOne;
|
|
13
|
-
external workflow create/update is submitted from synced AI manifests.
|
|
14
|
-
3. **SDK binding**: `src/lib/sdk.ts` converts manifests into typed entity and AI clients.
|
|
15
|
-
4. **Frontend experience**: React/UI code calls the SDK and owns app-specific interaction design.
|
|
11
|
+
HowOne generated apps have four product layers:
|
|
16
12
|
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
| Layer | Source of truth | App code should do |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| Backend database | synced `.howone/database/manifest.json` | generate entity types/bindings and call SDK |
|
|
16
|
+
| AI capabilities | synced `.howone/ai/manifest.json` + workflow status | generate AI action bindings and call SDK |
|
|
17
|
+
| SDK runtime | `@howone/sdk` + `src/lib/sdk.ts` | centralize env/auth/entities/AI/upload |
|
|
18
|
+
| Frontend app | user experience | own UI, state, feedback, forms, navigation |
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
The agent may propose schema/capability changes, but the validated/synced manifests drive code.
|
|
21
21
|
|
|
22
22
|
```text
|
|
23
|
-
|
|
24
|
-
validated backend manifest = source of truth
|
|
25
|
-
generated files = compiler/binding output
|
|
23
|
+
user request -> architecture decision -> backend/AI contracts -> sync manifests -> sdk binding -> UI
|
|
26
24
|
```
|
|
27
25
|
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
Do not skip the binding layer. UI code should import `howone` from `src/lib/sdk.ts`, not construct
|
|
27
|
+
raw URLs or guessed entity/action names.
|
|
28
|
+
|
|
29
|
+
## First Decision: What Surfaces Are Touched?
|
|
30
|
+
|
|
31
|
+
Classify the request before editing.
|
|
32
|
+
|
|
33
|
+
| User request says | Touched surfaces | Required references |
|
|
34
|
+
|---|---|---|
|
|
35
|
+
| "store/save/history/list/my data" | database + SDK + UI | `02-database/`, `03-sdk/02-entity-operations.md` |
|
|
36
|
+
| "login/account/my/private" | auth + database access | `03-sdk/03-auth.md`, `03-sdk/04-react-integration.md` |
|
|
37
|
+
| "public page/share/link/landing/catalog" | public access + SDK public namespace | `02-database/03-data-access-patterns.md` |
|
|
38
|
+
| "AI/generate/analyze/summarize/research/edit image/video/audio" | AI contract + workflow + SDK | `04-ai/` |
|
|
39
|
+
| "upload file/image/audio/pdf" | upload + maybe AI URL input | `03-sdk/05-file-upload.md`, `04-ai/02-workflow-contract-rules.md` |
|
|
40
|
+
| "change schema/add field/new table" | schema operations + manifest codegen | `02-database/02-schema-operations.md`, `01-architect/02-manifest-codegen.md` |
|
|
41
|
+
| "frontend only" | SDK usage + UI | `03-sdk/01-client-setup.md` and relevant SDK docs |
|
|
42
|
+
|
|
43
|
+
If multiple surfaces are touched, read one reference from each surface before editing.
|
|
30
44
|
|
|
31
|
-
##
|
|
45
|
+
## Data Posture Decision
|
|
32
46
|
|
|
33
|
-
|
|
47
|
+
Choose data posture before schema and UI.
|
|
34
48
|
|
|
35
|
-
|
|
|
49
|
+
| Product need | Access contract | SDK read |
|
|
36
50
|
|---|---|---|
|
|
37
|
-
|
|
|
38
|
-
|
|
|
39
|
-
|
|
|
40
|
-
|
|
|
51
|
+
| per-user private data | authenticated own, public none | `howone.entities.X.query.mine()` |
|
|
52
|
+
| logged-in shared admin/team data | authenticated all, public none | `howone.entities.X.query()` |
|
|
53
|
+
| anonymous public catalog/feed | authenticated all, public list | `howone.public.entities.X.query()` |
|
|
54
|
+
| one public share/detail page | authenticated own/all, public scoped | `howone.public.entities.X.queryScoped()` |
|
|
55
|
+
| anonymous form submission | authenticated all, public create scoped/any | `howone.public.entities.X.create()` |
|
|
56
|
+
| AI generation history | authenticated own, public none | `runAiActionAndPersist()` + `query.mine()` |
|
|
57
|
+
| AI public share | private history + public scoped share entity | two entities |
|
|
58
|
+
|
|
59
|
+
Defaults:
|
|
41
60
|
|
|
42
|
-
|
|
43
|
-
|
|
61
|
+
- "my" / "per user" / "private" -> authenticated own.
|
|
62
|
+
- "landing page" / "blog" / "gallery" -> public list only if fields are safe.
|
|
63
|
+
- "share link" / "QR" / "public result" -> public scoped, small `maxLimit`.
|
|
64
|
+
- "AI history" -> private history entity; do not make it public just for sharing.
|
|
65
|
+
|
|
66
|
+
## Auth Decision
|
|
67
|
+
|
|
68
|
+
| Need | SDK config | Provider behavior |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| default HowOne login | `createClient({ projectId, env })` | hosted login |
|
|
71
|
+
| custom designed login page using HowOne auth APIs | `auth: 'custom'`, `HowOneProvider auth="none"` | app owns login UI |
|
|
72
|
+
| external identity provider/JWT | `auth: { mode: 'headless', adapter }` | adapter owns token/user |
|
|
73
|
+
| public-only app | `auth: 'none'` | no auth guard |
|
|
74
|
+
|
|
75
|
+
Rules:
|
|
76
|
+
|
|
77
|
+
- Keep the bottom-right HowOne `FloatingButton` by default unless explicitly hidden.
|
|
78
|
+
- SDK must not add toast/overlay/login-page UI.
|
|
79
|
+
- Use `client.me()` or `client.requireMe()` for first-load user resolution.
|
|
80
|
+
- Do not use `auth.isAuthenticated()` as the only initial truth when user data must be loaded.
|
|
44
81
|
|
|
45
82
|
## Backend Feature Workflow
|
|
46
83
|
|
|
47
|
-
|
|
84
|
+
Use when persistence or schema changes are needed:
|
|
48
85
|
|
|
49
|
-
1. Read `02-database/01-schema-design.md
|
|
50
|
-
2.
|
|
51
|
-
3.
|
|
52
|
-
4.
|
|
53
|
-
5.
|
|
54
|
-
6.
|
|
55
|
-
7.
|
|
56
|
-
8. Read
|
|
57
|
-
9. Update `src/lib/sdk.ts`.
|
|
58
|
-
10.
|
|
59
|
-
11.
|
|
60
|
-
12. Validate.
|
|
86
|
+
1. Read `02-database/01-schema-design.md`.
|
|
87
|
+
2. Read `02-database/02-schema-operations.md`.
|
|
88
|
+
3. Inspect current schema state/manifest.
|
|
89
|
+
4. Design complete entity contract: fields, required, access, indexes, presentation.
|
|
90
|
+
5. Preview one complete schema patch.
|
|
91
|
+
6. Apply the exact previewed patch if risk is acceptable.
|
|
92
|
+
7. Sync schema artifacts from returned version.
|
|
93
|
+
8. Read `.howone/database/manifest.json`.
|
|
94
|
+
9. Update `src/lib/sdk.ts` from manifest using `01-architect/02-manifest-codegen.md`.
|
|
95
|
+
10. Implement UI with `howone.entities.*` or `howone.public.entities.*`.
|
|
96
|
+
11. Validate build/tests.
|
|
61
97
|
|
|
62
|
-
|
|
63
|
-
|
|
98
|
+
Risk stops:
|
|
99
|
+
|
|
100
|
+
- deleting entity/field;
|
|
101
|
+
- making required field without default;
|
|
102
|
+
- broadening public access;
|
|
103
|
+
- enabling public write;
|
|
104
|
+
- changing owner/public scope semantics.
|
|
64
105
|
|
|
65
106
|
## AI Feature Workflow
|
|
66
107
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
1. Read `04-ai/01-ai-capability-architecture.md` and
|
|
70
|
-
`04-ai/02-workflow-contract-rules.md`.
|
|
71
|
-
2. Inspect current AI capability state.
|
|
72
|
-
3. Design one complete AI capability patch for the feature.
|
|
73
|
-
4. Preview the AI patch.
|
|
74
|
-
5. Apply the exact previewed operations.
|
|
75
|
-
6. Sync AI artifacts.
|
|
76
|
-
7. Read `.howone/ai/manifest.json`.
|
|
77
|
-
8. Submit external workflow create/update with `external-ai-capability`.
|
|
78
|
-
9. Preserve returned request IDs for the status/background-task layer.
|
|
79
|
-
10. Read `04-ai/03-ai-sdk-handoff.md`, `01-architect/02-manifest-codegen.md`, and
|
|
80
|
-
`03-sdk/07-ai-action-calls.md`.
|
|
81
|
-
11. Update `src/lib/sdk.ts` from the synced manifest.
|
|
82
|
-
12. Update the UI.
|
|
83
|
-
13. Validate.
|
|
84
|
-
|
|
85
|
-
If generated output must be saved, design the AI capability first. Then derive persistence entities
|
|
86
|
-
from the synced AI `outputSchema`, plus only necessary request metadata.
|
|
108
|
+
Use when AI capability/workflow is needed:
|
|
87
109
|
|
|
88
|
-
|
|
110
|
+
1. Read `04-ai/01-ai-capability-architecture.md`.
|
|
111
|
+
2. Read `04-ai/04-service-capability-catalog.md` to verify support.
|
|
112
|
+
3. Pick a playbook from `04-ai/06-ai-feature-playbooks.md` when applicable.
|
|
113
|
+
4. Design schemas with `04-ai/02-workflow-contract-rules.md`.
|
|
114
|
+
5. Preview/apply AI capability patch.
|
|
115
|
+
6. Sync `.howone/ai/manifest.json`.
|
|
116
|
+
7. Submit external workflow create/update using `04-ai/05-workflow-operations.md`.
|
|
117
|
+
8. Preserve returned `request_id`.
|
|
118
|
+
9. Poll status until terminal; preserve `workflowConfigID` on success.
|
|
119
|
+
10. Update `src/lib/sdk.ts` with `04-ai/03-ai-sdk-handoff.md`.
|
|
120
|
+
11. Implement UI through `howone.ai.*`.
|
|
121
|
+
12. If output persists, use `02-database/05-ai-persistence-patterns.md`.
|
|
89
122
|
|
|
90
|
-
|
|
123
|
+
Do not build fake AI. If the required capability is unsupported, report the exact gap.
|
|
91
124
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
125
|
+
## Manifest Codegen Workflow
|
|
126
|
+
|
|
127
|
+
Run after database or AI sync:
|
|
128
|
+
|
|
129
|
+
1. Read current `src/lib/sdk.ts`.
|
|
130
|
+
2. Read synced manifests.
|
|
131
|
+
3. Preserve existing exports and naming style.
|
|
132
|
+
4. Generate/update:
|
|
133
|
+
- entity `Record/Create/Update` types;
|
|
134
|
+
- optional exported `*EntityDefinition` for guards;
|
|
135
|
+
- `client.entity<...>()` bindings;
|
|
136
|
+
- AI Zod schemas and `defineAiAction(...)`;
|
|
137
|
+
- composed `howone` export.
|
|
138
|
+
5. Never write generated source under `.howone/`.
|
|
139
|
+
|
|
140
|
+
## Common User Situations
|
|
97
141
|
|
|
98
|
-
|
|
142
|
+
### User asks for "just a frontend"
|
|
99
143
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
144
|
+
Still check whether UI needs stored data, auth, upload, or AI. If it only renders static/local state,
|
|
145
|
+
do not invent schema or workflow. If it saves anything, use database flow.
|
|
146
|
+
|
|
147
|
+
### User asks for "AI app" but no persistence
|
|
148
|
+
|
|
149
|
+
Design AI capability and SDK binding only. Keep results in app state. Do not create entities unless
|
|
150
|
+
history, refresh resilience, user library, or share page is needed.
|
|
151
|
+
|
|
152
|
+
### User asks for "AI app with history"
|
|
153
|
+
|
|
154
|
+
Design AI first, then database:
|
|
155
|
+
|
|
156
|
+
```text
|
|
157
|
+
AI output contract -> Generation entity -> runAiActionAndPersist -> history query.mine()
|
|
104
158
|
```
|
|
105
159
|
|
|
106
|
-
|
|
107
|
-
|
|
160
|
+
Do not put history fields into workflow output unless the AI itself must generate them.
|
|
161
|
+
|
|
162
|
+
### User asks for "public AI result"
|
|
163
|
+
|
|
164
|
+
Use two entities:
|
|
165
|
+
|
|
166
|
+
- private `Generation` for owner history and retry;
|
|
167
|
+
- public scoped `SharedGeneration` for anonymous viewing.
|
|
168
|
+
|
|
169
|
+
Do not expose private prompt/history broadly.
|
|
170
|
+
|
|
171
|
+
### User asks for "latest/current/research"
|
|
172
|
+
|
|
173
|
+
Use AI workflow with web search/crawling capability. If app also lists saved briefings, add entity
|
|
174
|
+
persistence after output contract.
|
|
175
|
+
|
|
176
|
+
### User asks to modify existing AI behavior
|
|
177
|
+
|
|
178
|
+
If only behavior changes, use external workflow update with `workflowConfigID`.
|
|
179
|
+
If input/output changes, update AI capability contract first, sync manifest, then update workflow
|
|
180
|
+
and SDK bindings.
|
|
181
|
+
|
|
182
|
+
### User asks to change schema used by UI
|
|
183
|
+
|
|
184
|
+
Change backend schema first, sync, regenerate SDK, then update UI. Do not patch UI types from memory.
|
|
185
|
+
|
|
186
|
+
### User asks for custom auth
|
|
187
|
+
|
|
188
|
+
Use `auth: 'custom'` or headless `AuthAdapter`. App owns visible login UI. Keep SDK callbacks/data
|
|
189
|
+
only.
|
|
190
|
+
|
|
191
|
+
## Implementation Guardrails
|
|
108
192
|
|
|
109
|
-
|
|
193
|
+
- Use `@howone/sdk` typed clients before `raw`.
|
|
194
|
+
- Use `howone.raw` only when typed surface is missing.
|
|
195
|
+
- Do not hardcode HowOne API URLs.
|
|
196
|
+
- Do not pass owner fields for authenticated own records.
|
|
197
|
+
- Do not import or create SDK toast APIs.
|
|
198
|
+
- Do not remove HowOne floating logo unless explicitly requested.
|
|
199
|
+
- Do not call AI workflows from render.
|
|
200
|
+
- Do not persist workflow envelopes or UI-only fields.
|
|
201
|
+
- Do not assume unavailable AI capabilities.
|
|
110
202
|
|
|
111
|
-
|
|
112
|
-
- Preserve existing bindings unless the manifest changed.
|
|
113
|
-
- Export explicit `Record`, `Create`, and `Update` types.
|
|
114
|
-
- Do not include system fields in create/update payloads.
|
|
115
|
-
- Do not infer public access from `visibility` alone; inspect `access.public`.
|
|
203
|
+
## Final Architecture Checklist
|
|
116
204
|
|
|
117
|
-
|
|
205
|
+
Before writing final code:
|
|
118
206
|
|
|
119
|
-
-
|
|
120
|
-
|
|
121
|
-
-
|
|
122
|
-
|
|
123
|
-
-
|
|
124
|
-
|
|
125
|
-
-
|
|
126
|
-
|
|
207
|
+
- Data posture is explicit.
|
|
208
|
+
- Auth mode is explicit.
|
|
209
|
+
- Public access has filters/sorts/scopes/limits.
|
|
210
|
+
- AI capability is supported by service catalog.
|
|
211
|
+
- Workflow count follows one-feature rule or RAG exception.
|
|
212
|
+
- Persistence is separate from AI workflow.
|
|
213
|
+
- Manifests are synced before SDK codegen.
|
|
214
|
+
- `src/lib/sdk.ts` is the only app SDK entrypoint.
|
|
215
|
+
- UI owns visible states and feedback.
|
|
@@ -260,6 +260,8 @@ import {
|
|
|
260
260
|
defineAiAction,
|
|
261
261
|
defineAiActions,
|
|
262
262
|
defineEntities,
|
|
263
|
+
runAiActionAndPersist,
|
|
264
|
+
type EntityDefinition,
|
|
263
265
|
type EntityRecord,
|
|
264
266
|
withAiActions,
|
|
265
267
|
withEntities,
|
|
@@ -304,6 +306,41 @@ export type CommentCreate = {
|
|
|
304
306
|
}
|
|
305
307
|
export type CommentUpdate = Partial<CommentCreate>
|
|
306
308
|
|
|
309
|
+
export const storyEntityDefinition = {
|
|
310
|
+
name: 'Story',
|
|
311
|
+
type: 'object',
|
|
312
|
+
properties: {
|
|
313
|
+
title: { type: 'string' },
|
|
314
|
+
content: { type: 'string' },
|
|
315
|
+
authorId: { type: 'string' },
|
|
316
|
+
status: { type: 'string', enum: ['draft', 'published', 'archived'] },
|
|
317
|
+
wordCount: { type: 'integer' },
|
|
318
|
+
tags: { type: 'array', items: { type: 'string' } },
|
|
319
|
+
coverUrl: { type: 'string' },
|
|
320
|
+
},
|
|
321
|
+
required: ['title', 'content', 'authorId', 'status', 'wordCount'],
|
|
322
|
+
access: {
|
|
323
|
+
authenticated: { read: 'own', create: 'own', update: 'own', delete: 'own' },
|
|
324
|
+
public: { read: 'none', create: 'none', update: 'none', delete: 'none' },
|
|
325
|
+
},
|
|
326
|
+
} satisfies EntityDefinition
|
|
327
|
+
|
|
328
|
+
export const commentEntityDefinition = {
|
|
329
|
+
name: 'Comment',
|
|
330
|
+
type: 'object',
|
|
331
|
+
properties: {
|
|
332
|
+
storyId: { type: 'string' },
|
|
333
|
+
authorId: { type: 'string' },
|
|
334
|
+
body: { type: 'string' },
|
|
335
|
+
likes: { type: 'integer' },
|
|
336
|
+
},
|
|
337
|
+
required: ['storyId', 'authorId', 'body'],
|
|
338
|
+
access: {
|
|
339
|
+
authenticated: { read: 'own', create: 'own', update: 'own', delete: 'own' },
|
|
340
|
+
public: { read: 'none', create: 'none', update: 'none', delete: 'none' },
|
|
341
|
+
},
|
|
342
|
+
} satisfies EntityDefinition
|
|
343
|
+
|
|
307
344
|
// ═══════════════════════════════════════════════════════════════
|
|
308
345
|
// AI SCHEMAS & TYPES
|
|
309
346
|
// ═══════════════════════════════════════════════════════════════
|
|
@@ -377,6 +414,7 @@ export default howone
|
|
|
377
414
|
Before finalising generated code, verify:
|
|
378
415
|
|
|
379
416
|
- [ ] Every entity from `.howone/database/manifest.json` has a `Record`, `Create`, and `Update` type
|
|
417
|
+
- [ ] Entity definitions are exported as `*EntityDefinition` when app code needs payload/query guards
|
|
380
418
|
- [ ] `Create` types are defined **explicitly** (not via `Omit`)
|
|
381
419
|
- [ ] Create optionality accounts for `required`, `default`, `defaultValue`, `autoGenerate`, and nullable types
|
|
382
420
|
- [ ] System fields are not present in create/update input types
|
|
@@ -423,10 +461,14 @@ export const entities = defineEntities({
|
|
|
423
461
|
|
|
424
462
|
When the app generates data with AI and saves it to an entity:
|
|
425
463
|
|
|
426
|
-
1. Read `.howone/ai/manifest.json`
|
|
427
|
-
2.
|
|
428
|
-
3. Add
|
|
429
|
-
|
|
464
|
+
1. Read `.howone/ai/manifest.json` to know the typed AI output.
|
|
465
|
+
2. Decide which output fields are durable product fields.
|
|
466
|
+
3. Add app-specific persistence fields such as `status`, `errorMessage`, `requestedAt`,
|
|
467
|
+
`completedAt`, source URLs, prompt/options, or share state.
|
|
468
|
+
4. Define/update the entity schema from product persistence needs, not by blindly copying
|
|
469
|
+
`outputSchema`.
|
|
470
|
+
5. Generate entity types and AI action bindings from synced manifests.
|
|
471
|
+
6. Use `runAiActionAndPersist()` for history-style products.
|
|
430
472
|
|
|
431
473
|
```ts
|
|
432
474
|
// AI generates: { title: string, content: string, summary: string }
|
|
@@ -444,3 +486,24 @@ async function generateAndSave(input: GenerateStoryInput, authorId: string) {
|
|
|
444
486
|
})
|
|
445
487
|
}
|
|
446
488
|
```
|
|
489
|
+
|
|
490
|
+
History-style generation should create a pending record before running AI:
|
|
491
|
+
|
|
492
|
+
```ts
|
|
493
|
+
await runAiActionAndPersist({
|
|
494
|
+
entity: howone.entities.Generation,
|
|
495
|
+
input,
|
|
496
|
+
createPending: (input) => ({
|
|
497
|
+
prompt: input.topic,
|
|
498
|
+
status: 'pending',
|
|
499
|
+
requestedAt: new Date().toISOString(),
|
|
500
|
+
}),
|
|
501
|
+
run: (input) => howone.ai.generateStory.run(input),
|
|
502
|
+
mapCompleted: ({ output }) => ({
|
|
503
|
+
status: 'completed',
|
|
504
|
+
title: output.title,
|
|
505
|
+
content: output.content,
|
|
506
|
+
completedAt: new Date().toISOString(),
|
|
507
|
+
}),
|
|
508
|
+
})
|
|
509
|
+
```
|