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.
Files changed (24) hide show
  1. package/package.json +1 -1
  2. package/templates/vite/.howone/skills/howone-sdk/01-architect/01-app-generation.md +180 -91
  3. package/templates/vite/.howone/skills/howone-sdk/01-architect/02-manifest-codegen.md +67 -4
  4. package/templates/vite/.howone/skills/howone-sdk/02-database/01-schema-design.md +463 -69
  5. package/templates/vite/.howone/skills/howone-sdk/02-database/02-schema-operations.md +366 -64
  6. package/templates/vite/.howone/skills/howone-sdk/02-database/03-data-access-patterns.md +204 -67
  7. package/templates/vite/.howone/skills/howone-sdk/02-database/04-query-dsl-and-responses.md +237 -0
  8. package/templates/vite/.howone/skills/howone-sdk/02-database/05-ai-persistence-patterns.md +372 -0
  9. package/templates/vite/.howone/skills/howone-sdk/03-sdk/01-client-setup.md +58 -36
  10. package/templates/vite/.howone/skills/howone-sdk/03-sdk/02-entity-operations.md +67 -0
  11. package/templates/vite/.howone/skills/howone-sdk/03-sdk/03-auth.md +267 -469
  12. package/templates/vite/.howone/skills/howone-sdk/03-sdk/04-react-integration.md +113 -320
  13. package/templates/vite/.howone/skills/howone-sdk/03-sdk/07-ai-action-calls.md +66 -16
  14. package/templates/vite/.howone/skills/howone-sdk/03-sdk/08-extension-boundaries.md +226 -0
  15. package/templates/vite/.howone/skills/howone-sdk/04-ai/01-ai-capability-architecture.md +159 -96
  16. package/templates/vite/.howone/skills/howone-sdk/04-ai/02-workflow-contract-rules.md +353 -96
  17. package/templates/vite/.howone/skills/howone-sdk/04-ai/03-ai-sdk-handoff.md +181 -42
  18. package/templates/vite/.howone/skills/howone-sdk/04-ai/04-service-capability-catalog.md +281 -0
  19. package/templates/vite/.howone/skills/howone-sdk/04-ai/05-workflow-operations.md +256 -0
  20. package/templates/vite/.howone/skills/howone-sdk/04-ai/06-ai-feature-playbooks.md +296 -0
  21. package/templates/vite/.howone/skills/howone-sdk/SKILL.md +29 -12
  22. package/templates/vite/.howone/skills/howone-sdk/agents/openai.yaml +2 -2
  23. package/templates/vite/package.json +1 -1
  24. package/templates/vite/.howone/skills/howone-sdk/04-ai/.gitkeep +0 -1
@@ -1,80 +1,219 @@
1
1
  # AI SDK Handoff
2
2
 
3
- Use this reference after AI capability artifacts have been synced and app code needs to call the
4
- workflow.
3
+ Use this reference after AI capability artifacts have been synced and app code must call the
4
+ workflow through `@howone/sdk`.
5
+
6
+ This file answers: **how does `.howone/ai/manifest.json` become `src/lib/sdk.ts`, and how should UI
7
+ call it?**
5
8
 
6
9
  ## Binding Source
7
10
 
8
- Generate `src/lib/sdk.ts` from `.howone/ai/manifest.json`. Do not write AI bindings from memory or
9
- from the original user prompt.
11
+ Generate `src/lib/sdk.ts` from `.howone/ai/manifest.json`. Do not write AI bindings from memory,
12
+ from the original prompt, or from the workflow service response.
10
13
 
11
- For each manifest capability:
14
+ For each manifest capability/action:
12
15
 
13
- 1. Read `name`.
16
+ 1. Read stable action name/ID.
14
17
  2. Read `workflowId`.
15
18
  3. Read `inputSchema`.
16
19
  4. Read `outputSchema`.
17
- 5. Generate zod input and output schemas from the JSON Schema fields.
20
+ 5. Generate Zod input and output schemas.
18
21
  6. Bind with `defineAiAction(name, { workflowId, inputSchema, outputSchema })`.
22
+ 7. Compose with `withAiActions(client, ai)`.
19
23
 
20
24
  `workflowId` is mandatory. Without it, the SDK falls back to the action name as the execution URL
21
- segment, which is not a workflow UUID.
25
+ segment, and the workflow service will reject it because the segment is not a UUID.
26
+
27
+ ## Generated Binding Example
28
+
29
+ ```ts
30
+ import {
31
+ createClient,
32
+ defineAiAction,
33
+ defineAiActions,
34
+ withAiActions,
35
+ } from '@howone/sdk'
36
+ import { z } from 'zod'
37
+
38
+ const client = createClient({
39
+ projectId: import.meta.env.VITE_HOWONE_PROJECT_ID,
40
+ env: import.meta.env.VITE_HOWONE_ENV,
41
+ })
42
+
43
+ export const summarizeDocumentInputSchema = z.object({
44
+ document_url: z.string().url(),
45
+ summary_length: z.string().optional(),
46
+ })
47
+ export type SummarizeDocumentInput = z.infer<typeof summarizeDocumentInputSchema>
48
+
49
+ export const summarizeDocumentOutputSchema = z.object({
50
+ summary: z.string(),
51
+ })
52
+ export type SummarizeDocumentOutput = z.infer<typeof summarizeDocumentOutputSchema>
53
+
54
+ export const ai = defineAiActions({
55
+ summarizeDocument: defineAiAction('summarizeDocument', {
56
+ workflowId: '550e8400-e29b-41d4-a716-446655440000',
57
+ inputSchema: summarizeDocumentInputSchema,
58
+ outputSchema: summarizeDocumentOutputSchema,
59
+ }),
60
+ })
61
+
62
+ const howone = withAiActions(client, ai)
63
+ export default howone
64
+ ```
65
+
66
+ ## JSON Schema To Zod
67
+
68
+ | JSON Schema | Zod |
69
+ |---|---|
70
+ | `string` | `z.string()` |
71
+ | `string` + `format: "uri"` | `z.string().url()` |
72
+ | `number` | `z.number()` |
73
+ | `integer` | `z.number().int()` |
74
+ | `boolean` | `z.boolean()` |
75
+ | `array` of strings | `z.array(z.string())` |
76
+ | `array` of objects | `z.array(z.object({ ... }))` |
77
+ | `object` | `z.object({ ... })` |
78
+ | string enum | `z.enum([...])` |
79
+ | field not in `required` | `.optional()` |
80
+ | nullable | `.nullable()` |
81
+
82
+ Rules:
83
+
84
+ - Required manifest fields must stay required in Zod.
85
+ - Do not add `.passthrough()` to hide execution envelope problems.
86
+ - Do not make outputs optional to silence validation failures.
87
+ - If the workflow returns a different shape, fix the workflow/capability contract.
88
+
89
+ ## Calling Actions
90
+
91
+ For typed one-shot actions:
92
+
93
+ ```ts
94
+ const output = await howone.ai.summarizeDocument.run({
95
+ document_url,
96
+ summary_length: 'short',
97
+ })
98
+
99
+ setSummary(output.summary)
100
+ ```
101
+
102
+ When `outputSchema` exists, `.run()` returns the validated `finalResult` payload directly.
22
103
 
23
- ## Output Handling
104
+ Do not read:
24
105
 
25
- For a typed action with `outputSchema`, `.run()` returns the validated workflow output payload.
26
- The SDK unwraps the EAX execution envelope and validates `finalResult` internally.
106
+ ```ts
107
+ result.finalResult.summary
108
+ result.data.summary
109
+ result.raw.finalResult
110
+ ```
111
+
112
+ Those are execution-envelope paths, not the typed SDK action contract.
113
+
114
+ ## Streaming And Events
27
115
 
28
- Use this pattern:
116
+ Use `.stream()` when UI needs live output or cancellation:
29
117
 
30
118
  ```ts
31
- const output = await howone.ai.generateSummary.run(input)
32
- // output is GenerateSummaryOutput when outputSchema is configured.
119
+ const session = howone.ai.generateStory.stream(input, {
120
+ onStreamChunk: (chunk) => setDraft((prev) => prev + chunk),
121
+ onProgress: (progress) => setProgress(progress),
122
+ onError: (error) => setError(error.message),
123
+ onComplete: (result) => setRawResult(result),
124
+ })
125
+
126
+ cancelButton.onclick = () => session.cancel()
127
+ const final = await session.result
33
128
  ```
34
129
 
35
- Do not read `raw.finalResult`, `raw.result`, or `raw.data.result` from a typed action result. Those
36
- paths are execution/SSE internals. App code should use the value returned by `.run()` directly.
130
+ Use `.events()` when code wants an async iterable:
37
131
 
38
- Do not make every output field `.optional()` or add `.passthrough()` to hide validation errors.
39
- Required fields in the manifest must stay required in Zod. If validation fails, inspect
40
- `AiSchemaValidationError.issues` and fix the capability contract or workflow output mapping.
132
+ ```ts
133
+ for await (const event of howone.ai.generateStory.events(input)) {
134
+ if (event.type === 'stream_content') {
135
+ appendText(String(event.data?.delta ?? ''))
136
+ }
137
+ }
138
+ ```
41
139
 
42
140
  ## UI State
43
141
 
44
- AI calls should run in event handlers, effects, or explicit async actions. Never call
45
- `howone.ai.*.run()` inside JSX render.
142
+ The SDK returns data and exposes callbacks. The app owns all visible UI.
46
143
 
47
- Recommended UI states:
144
+ Recommended states:
48
145
 
49
- - idle
50
- - running
51
- - succeeded
52
- - failed
53
- - cancelled when using streaming
146
+ ```ts
147
+ type AiUiState<T> =
148
+ | { status: 'idle' }
149
+ | { status: 'running'; progress?: number }
150
+ | { status: 'succeeded'; output: T }
151
+ | { status: 'failed'; message: string }
152
+ | { status: 'cancelled' }
153
+ ```
54
154
 
55
- For streaming, keep the `AiSession` in a ref and call `cancel()` from the UI.
155
+ Do not add or import SDK toast APIs. Do not show SDK-owned overlays.
56
156
 
57
157
  ## Persistence Handoff
58
158
 
59
- If the app stores generated output:
159
+ If AI output should survive refresh, use entity persistence after the action returns.
60
160
 
61
- 1. Run the AI workflow.
62
- 2. Use the typed output returned by `.run()`.
63
- 3. Write the resulting data through `howone.entities.*`.
161
+ For history-style products, prefer `runAiActionAndPersist()`:
64
162
 
65
- Do not ask the workflow to write to the database. Do not pass owner fields for authenticated
66
- user-owned entities; HowOne derives ownership from the JWT.
163
+ ```ts
164
+ const result = await runAiActionAndPersist({
165
+ entity: howone.entities.Generation,
166
+ input: { prompt },
167
+ createPending: (input) => ({
168
+ prompt: input.prompt,
169
+ status: 'pending',
170
+ requestedAt: new Date().toISOString(),
171
+ }),
172
+ run: (input) => howone.ai.generateImage.run(input),
173
+ mapCompleted: ({ output }) => ({
174
+ status: 'completed',
175
+ resultUrl: output.generated_image_url,
176
+ completedAt: new Date().toISOString(),
177
+ }),
178
+ mapFailed: ({ error }) => ({
179
+ status: 'failed',
180
+ errorMessage: error instanceof Error ? error.message : 'Generation failed',
181
+ }),
182
+ })
183
+ ```
184
+
185
+ For simple save-after-success:
186
+
187
+ ```ts
188
+ const output = await howone.ai.summarizeDocument.run(input)
189
+ await howone.entities.DocumentSummary.create({
190
+ documentUrl: input.document_url,
191
+ summary: output.summary,
192
+ status: 'completed',
193
+ })
194
+ ```
195
+
196
+ Do not ask the workflow to write records. Do not pass owner fields for authenticated own entities.
67
197
 
68
198
  ## Workflow Edit Handoff
69
199
 
70
- When editing an external workflow implementation later, use `external-ai-capability` with:
200
+ When changing external workflow behavior later:
201
+
202
+ 1. If schema changes, update AI capability contract first and sync manifest.
203
+ 2. Use `workflowConfigID` from a completed status result.
204
+ 3. Submit update with `capabilityName`, `workflowConfigID`, and `updatePrompt`.
205
+ 4. Preserve the new status result and config ID if it changes.
206
+ 5. Regenerate SDK only if manifest contract changed.
71
207
 
72
- - `mode: "update"`
73
- - `capabilityName`
74
- - `workflowConfigID`
75
- - `updatePrompt`
208
+ `workflowConfigID` is not `workflowId`.
76
209
 
77
- `workflowConfigID` is not `workflowId`. It comes from a confirmed workflow status result:
78
- `payload.workflow_details.new_workflow_config_id`.
210
+ ## Handoff Checklist
79
211
 
80
- If the schema changed, update and sync the capability contract before submitting the workflow edit.
212
+ - `.howone/ai/manifest.json` exists and is current.
213
+ - Each action has `workflowId`.
214
+ - Zod input/output schemas match manifest required fields.
215
+ - `defineAiAction` uses action name + exact workflow UUID.
216
+ - UI uses returned typed output, not raw execution envelope.
217
+ - Streaming session is cancellable when UI exposes cancel.
218
+ - Persistence goes through `howone.entities.*`.
219
+ - Visible status/error UI is app-owned.
@@ -0,0 +1,281 @@
1
+ # Service Capability Catalog
2
+
3
+ Use this reference before designing an AI workflow. It tells the agent what the current workflow
4
+ service can actually do and what input/output shapes are expected.
5
+
6
+ Source: `docs/ai-capability.md`.
7
+
8
+ ## Quick Selection Table
9
+
10
+ | User asks for | Use capability family | Typical inputs | Typical outputs |
11
+ |---|---|---|---|
12
+ | Latest info, research, source-backed answer | Web search / crawling | `topic`, `prompt`, `url`, `search_level` | `answer`, `sources`, `page_content` |
13
+ | Generate artwork/photo/logo/mockup | Image generation | `image_description`, `style_preference`, optional references | `generated_image_url` |
14
+ | Edit an image | Image editing | `source_image_url`, `edit_instruction` | `edited_image_url` |
15
+ | OCR or visual analysis | Image analysis / OCR | `image_urls`, `analysis_prompt` | `analysis_result` or `extracted_text` |
16
+ | Generate short video | Video generation | `video_prompt`, aspect/duration/frame URLs | `video_url` |
17
+ | Join clips / extract frames | Video editing | `video_urls` or `video_url` | `video_url` or `image_url` |
18
+ | Text to speech | Audio generation | `text_to_generate`, `language`, `voice_hint` | `audio_url` |
19
+ | Speech to text | Audio recognition | `source_audio_url`, `language` | `transcript_text`, optional `utterances` |
20
+ | Merge audio | Audio merging | `audio_urls` | `merged_audio_url` |
21
+ | Stock/index history | Financial data retrieval | `trading_symbol`, `unit`, `start`, `end` | `price_history` |
22
+ | Literature search/citations | Academic research | `query` | `papers`, `bibtex` |
23
+ | Save generated file | File storage | `file_type`, `content` | `file_url` |
24
+
25
+ If the requested behavior is not in this table or the detailed sections below, do not invent it.
26
+
27
+ ## Web Search And Crawling
28
+
29
+ Use for latest information, news, market context, source-backed answers, web page extraction.
30
+
31
+ Inputs:
32
+
33
+ - `prompt`: query or detailed research instruction;
34
+ - `search_level`: `low`, `medium`, or `high`; default to medium;
35
+ - `offset`: pagination for low-level search;
36
+ - page crawl input should be a URL.
37
+
38
+ Outputs:
39
+
40
+ - synthesized answer or raw search result;
41
+ - `sources` array of URLs;
42
+ - crawled page text/markdown when crawling.
43
+
44
+ Rules:
45
+
46
+ - Use web search when the user asks for current/latest information.
47
+ - Use page crawling when the product needs content from a specific URL.
48
+ - Do not use search as an outbound API caller.
49
+ - Include source links in output when the product promises research.
50
+
51
+ ## Image Generation
52
+
53
+ Use for new images from prompts or prompt + reference URLs.
54
+
55
+ Inputs:
56
+
57
+ - `image_description`: detailed prompt;
58
+ - `style_preference`: optional;
59
+ - `reference_image_urls`: optional URL array;
60
+ - size/format options only when product exposes them.
61
+
62
+ Outputs:
63
+
64
+ - `generated_image_url` or `image_urls`;
65
+ - avoid metadata unless product needs it.
66
+
67
+ Rules:
68
+
69
+ - One image per request is usually more reliable.
70
+ - Do not put resolution text into the prompt when a size parameter exists.
71
+ - Reference images must be URLs and should be described by position/content.
72
+ - Subject to moderation; do not promise forbidden content.
73
+
74
+ ## Image Editing
75
+
76
+ Use for modifying existing images.
77
+
78
+ Inputs:
79
+
80
+ - `source_image_url` or `source_image_urls`;
81
+ - `edit_instruction`;
82
+ - optional output size/format.
83
+
84
+ Outputs:
85
+
86
+ - `edited_image_url`.
87
+
88
+ Supported edits include resize/crop/rotate, background removal/replacement, object removal/addition,
89
+ style transfer, enhancement, merge/composite, lighting/color changes.
90
+
91
+ Rules:
92
+
93
+ - At least one image URL is required.
94
+ - Keep edit instructions focused.
95
+ - For complex multi-step edits, describe the final desired result.
96
+
97
+ ## Image Analysis And OCR
98
+
99
+ Use for visual understanding, image comparison, text extraction, quality review.
100
+
101
+ Inputs:
102
+
103
+ - `image_urls`;
104
+ - `analysis_prompt` or `ocr_instruction`.
105
+
106
+ Outputs:
107
+
108
+ - `analysis_result` for semantic analysis;
109
+ - `extracted_text` for OCR.
110
+
111
+ Rules:
112
+
113
+ - Ask for the exact information needed.
114
+ - Do not include confidence/bounding boxes unless user asks.
115
+ - OCR quality depends on image quality.
116
+
117
+ ## Video Generation
118
+
119
+ Use for short video clips from text or image frames.
120
+
121
+ Inputs:
122
+
123
+ - `video_prompt`;
124
+ - optional `first_frame_url`, `last_frame_url`, `reference_image_urls`;
125
+ - optional `aspect_ratio`, `duration`, `negative_prompt`, `generate_audio`.
126
+
127
+ Outputs:
128
+
129
+ - `video_url`.
130
+
131
+ Rules:
132
+
133
+ - Keep individual clips short, generally 5-10 seconds.
134
+ - For consistency, generate/use a first-frame image.
135
+ - For longer videos, generate clips and concatenate via video editing.
136
+ - Audio in video works best with one speaker per clip.
137
+
138
+ ## Video Editing
139
+
140
+ Use for concatenating clips or extracting first/last frames.
141
+
142
+ Inputs:
143
+
144
+ - concatenate: `video_urls` with at least two URLs;
145
+ - frame extraction: `source_video_url`.
146
+
147
+ Outputs:
148
+
149
+ - `merged_video_url` or `frame_image_url`.
150
+
151
+ Rules:
152
+
153
+ - Inputs must be accessible URLs.
154
+ - Best results when clips share resolution/aspect ratio.
155
+
156
+ ## Audio Generation
157
+
158
+ Use for text-to-speech.
159
+
160
+ Inputs:
161
+
162
+ - `text_to_generate`;
163
+ - `language` or `languages`;
164
+ - `gender`;
165
+ - `audio_hint`;
166
+ - optional output format/name.
167
+
168
+ Outputs:
169
+
170
+ - `audio_url`.
171
+
172
+ Rules:
173
+
174
+ - Single speaker per call.
175
+ - For dialogue, generate each speaker line and merge audio.
176
+ - `audio_hint` should describe voice in English.
177
+
178
+ ## Audio Recognition
179
+
180
+ Use for speech-to-text.
181
+
182
+ Inputs:
183
+
184
+ - `source_audio_url`;
185
+ - optional `language`;
186
+ - optional speaker diarization setting.
187
+
188
+ Outputs:
189
+
190
+ - `transcript_text`;
191
+ - optional `utterances` when speaker info is requested.
192
+
193
+ Rules:
194
+
195
+ - Audio must be URL-accessible.
196
+ - Silent or low-quality audio can produce empty/poor transcript.
197
+
198
+ ## Financial Data Retrieval
199
+
200
+ Use for historical stock/index price data.
201
+
202
+ Inputs:
203
+
204
+ - `trading_symbol`;
205
+ - `unit`: `daily` or `minute`;
206
+ - `start`;
207
+ - `end`.
208
+
209
+ Outputs:
210
+
211
+ - `price_history` array;
212
+ - `trading_symbol`;
213
+ - optional warning.
214
+
215
+ Rules:
216
+
217
+ - Historical data only; no real-time streaming.
218
+ - Indices usually support daily data only.
219
+ - Ask for exact tickers when possible.
220
+ - Does not provide fundamentals, earnings, or live news unless combined with web search.
221
+
222
+ ## Academic Research
223
+
224
+ Use for literature search, paper metadata, BibTeX.
225
+
226
+ Inputs:
227
+
228
+ - `query`.
229
+
230
+ Outputs:
231
+
232
+ - `papers`;
233
+ - `bibtex` when citation output is requested.
234
+
235
+ Rules:
236
+
237
+ - Search quality depends on query specificity.
238
+ - Availability varies by academic source.
239
+ - PDF assets should be handled as URLs.
240
+
241
+ ## File Storage
242
+
243
+ Use when workflow needs to save generated content into a file.
244
+
245
+ Inputs:
246
+
247
+ - `file_type`: `json`, `yaml`, `csv`, `pdf`, `md`, or `txt`;
248
+ - `content`: string content to save.
249
+
250
+ Outputs:
251
+
252
+ - `file_url`.
253
+
254
+ Rules:
255
+
256
+ - Structured content must be serialized to string before saving.
257
+ - Do not use file storage as a database.
258
+ - If app needs records/history, persist file URL through entities.
259
+
260
+ ## Composition Patterns
261
+
262
+ | Pattern | Workflow design |
263
+ |---|---|
264
+ | Image -> Video | generate first-frame image, pass as `first_frame_url` to video generation |
265
+ | Multi-clip video | generate short clips, concatenate via video editing |
266
+ | Dialogue audio | generate each speaker line, merge audio |
267
+ | Search -> Report | web search/crawl, synthesize structured report, optionally save file |
268
+ | Video -> Image edit -> Video | extract frame, edit frame, use as next reference |
269
+ | RAG document chat | indexing workflow + query workflow |
270
+
271
+ ## Capability Rejection Checklist
272
+
273
+ Stop or narrow scope if user requires:
274
+
275
+ - real-time streaming market data;
276
+ - arbitrary external API calls not listed;
277
+ - raw file bytes/base64 in workflow;
278
+ - database CRUD inside workflow;
279
+ - unsupported provider-specific model guarantees;
280
+ - content disallowed by moderation;
281
+ - long video generation in one call beyond service limits.