howone 0.1.6 → 0.1.8
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
CHANGED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: howone-sdk
|
|
3
|
+
description: Build application code with @howone/sdk correctly. Use when implementing or reviewing HowOne app SDK wiring, src/lib/sdk.ts, dynamic entity bindings, AI action bindings, zod runtime schemas, Vite environment variables, calls like howone.entities.* and howone.ai.*.run, or code generated from .howone/database and .howone/ai manifests.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# HowOne SDK
|
|
7
|
+
|
|
8
|
+
Use this skill when writing app code that consumes `@howone/sdk`. The goal is stable generated code: read backend-synced manifests, define zod schemas, bind entities and AI actions in the app SDK entry, then call those bindings from UI code.
|
|
9
|
+
|
|
10
|
+
## Workflow
|
|
11
|
+
|
|
12
|
+
1. Locate the app root first. If an app was created by `howone init app <name>`, all `.howone/*` metadata and `src/lib/sdk.ts` work should happen inside that created app directory.
|
|
13
|
+
2. Read the existing app SDK entry, usually `src/lib/sdk.ts`, before editing. Preserve its imports and local style.
|
|
14
|
+
3. For Entity bindings, read `.howone/database/manifest.json`.
|
|
15
|
+
4. For AI action bindings, read `.howone/ai/manifest.json`.
|
|
16
|
+
5. Generate source code from the manifests, not from memory or tool-call summaries.
|
|
17
|
+
6. Keep sync tools and app-code edits separate. `sync_schema_artifacts` and `sync_ai_artifacts` write metadata only; the coding agent edits `src/lib/sdk.ts`.
|
|
18
|
+
|
|
19
|
+
## Rules
|
|
20
|
+
|
|
21
|
+
- Use `createClient({ projectId: import.meta.env.VITE_HOWONE_PROJECT_ID, env: import.meta.env.VITE_HOWONE_ENV })` in Vite apps. Do not add `?? 'prod'` or hardcoded project IDs in generated app code.
|
|
22
|
+
- Use zod for AI input/output runtime schemas.
|
|
23
|
+
- Use `defineAiAction` inside `defineAiActions`.
|
|
24
|
+
- Current action binding shape is `howone.ai.<actionName>.run(input)`, `stream(input)`, and `events(input)`. Do not generate `howone.ai.run.<actionName>(input)` unless the SDK implementation has been changed to support that API.
|
|
25
|
+
- Do not name AI actions `run`, `stream`, or `events`; those are reserved.
|
|
26
|
+
- Define entity create/update types explicitly. Avoid deriving create types from `Omit<EntityRecord & ...>` when it widens the payload.
|
|
27
|
+
- Never make generated SDK/type files under `.howone`. `.howone` stores manifests only.
|
|
28
|
+
- If an AI-first feature persists generated results, create/update AI capability schema first, sync `.howone/ai`, then derive Entity fields from the AI `outputSchema`.
|
|
29
|
+
|
|
30
|
+
## References
|
|
31
|
+
|
|
32
|
+
Read `references/usage-patterns.md` when implementing or reviewing actual code.
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# HowOne SDK Usage Patterns
|
|
2
|
+
|
|
3
|
+
## App SDK Entry
|
|
4
|
+
|
|
5
|
+
Preferred Vite app entry shape:
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import {
|
|
9
|
+
createClient,
|
|
10
|
+
defineAiAction,
|
|
11
|
+
defineAiActions,
|
|
12
|
+
defineEntities,
|
|
13
|
+
type EntityRecord,
|
|
14
|
+
withAiActions,
|
|
15
|
+
withEntities,
|
|
16
|
+
} from '@howone/sdk'
|
|
17
|
+
import { z } from 'zod'
|
|
18
|
+
|
|
19
|
+
const client = createClient({
|
|
20
|
+
projectId: import.meta.env.VITE_HOWONE_PROJECT_ID,
|
|
21
|
+
env: import.meta.env.VITE_HOWONE_ENV,
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
export const entities = defineEntities({
|
|
25
|
+
// Todo: client.entity<Todo, TodoCreate, TodoUpdate>('Todo'),
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
export const ai = defineAiActions({
|
|
29
|
+
// generateImage: defineAiAction('generateImage', {
|
|
30
|
+
// inputSchema: generateImageInputSchema,
|
|
31
|
+
// outputSchema: generateImageOutputSchema,
|
|
32
|
+
// }),
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const howone = withAiActions(withEntities(client, entities), ai)
|
|
36
|
+
|
|
37
|
+
export default howone
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Entity Types
|
|
41
|
+
|
|
42
|
+
Prefer explicit payload types:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
export type StoryRecord = EntityRecord & {
|
|
46
|
+
title: string
|
|
47
|
+
content: string
|
|
48
|
+
prompt: string
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type StoryCreate = {
|
|
52
|
+
title: string
|
|
53
|
+
content: string
|
|
54
|
+
prompt: string
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export type StoryUpdate = Partial<StoryCreate>
|
|
58
|
+
|
|
59
|
+
export const entities = defineEntities({
|
|
60
|
+
Story: client.entity<StoryRecord, StoryCreate, StoryUpdate>('Story'),
|
|
61
|
+
})
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Avoid this for generated create payloads:
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
type StoryCreate = Omit<StoryRecord, 'id' | 'createdDate' | 'updatedDate'>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
`EntityRecord` has an index signature, so `Omit` can make generated create types looser than intended.
|
|
71
|
+
|
|
72
|
+
## AI Action Types
|
|
73
|
+
|
|
74
|
+
Generate zod schemas from `.howone/ai/manifest.json`:
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
export const generateStoryInputSchema = z.object({
|
|
78
|
+
topic: z.string().min(1),
|
|
79
|
+
ageRange: z.enum(['3-5', '6-8', '9-12']),
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
export const generateStoryOutputSchema = z.object({
|
|
83
|
+
title: z.string(),
|
|
84
|
+
content: z.string(),
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
export type GenerateStoryInput = z.infer<typeof generateStoryInputSchema>
|
|
88
|
+
export type GenerateStoryOutput = z.infer<typeof generateStoryOutputSchema>
|
|
89
|
+
|
|
90
|
+
export const ai = defineAiActions({
|
|
91
|
+
generateStory: defineAiAction('generateStory', {
|
|
92
|
+
inputSchema: generateStoryInputSchema,
|
|
93
|
+
outputSchema: generateStoryOutputSchema,
|
|
94
|
+
mode: 'run',
|
|
95
|
+
}),
|
|
96
|
+
})
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Call from app code:
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
const result = await howone.ai.generateStory.run({
|
|
103
|
+
topic,
|
|
104
|
+
ageRange,
|
|
105
|
+
})
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
For streaming:
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
const session = howone.ai.generateStory.stream(input)
|
|
112
|
+
session.cancel()
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
For event iteration:
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
for await (const event of howone.ai.generateStory.events(input)) {
|
|
119
|
+
console.log(event)
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## AI Output Validation Caveat
|
|
124
|
+
|
|
125
|
+
Check `packages/sdk/src/services/ai.ts` before relying on output validation. The desired behavior is for `defineAiAction(...).run()` to validate and return the workflow final result, not the whole SSE execution envelope.
|
|
126
|
+
|
|
127
|
+
Desired implementation shape:
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
const result = await base.run(definition.id, validInputs, options)
|
|
131
|
+
const output = result?.finalResult ?? result
|
|
132
|
+
return parseAiValue(definition.id, 'output', output, definition.outputSchema)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
If the SDK still validates the whole `ExecutionResult`, either fix the SDK first or avoid generating final-result `outputSchema` in app code that will immediately run.
|
|
136
|
+
|
|
137
|
+
## AI Result Persistence
|
|
138
|
+
|
|
139
|
+
For AI-generated data that should be saved:
|
|
140
|
+
|
|
141
|
+
1. Define AI input/output schemas from `.howone/ai/manifest.json`.
|
|
142
|
+
2. Define entity fields from the AI output schema.
|
|
143
|
+
3. Add only needed request metadata fields, such as prompt, selected options, language, status, or timestamps.
|
|
144
|
+
4. Save with `howone.entities.<Entity>.create(...)`.
|
|
145
|
+
|
|
146
|
+
Example:
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
const story = await howone.ai.generateStory.run(input)
|
|
150
|
+
|
|
151
|
+
await howone.entities.Story.create({
|
|
152
|
+
title: story.title,
|
|
153
|
+
content: story.content,
|
|
154
|
+
prompt: input.topic,
|
|
155
|
+
})
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Generated Code Checklist
|
|
159
|
+
|
|
160
|
+
- `src/lib/sdk.ts` imports only APIs it uses.
|
|
161
|
+
- `createClient` uses `import.meta.env.VITE_HOWONE_PROJECT_ID` and `import.meta.env.VITE_HOWONE_ENV`.
|
|
162
|
+
- Entity names match `.howone/database/manifest.json`.
|
|
163
|
+
- AI action names and schemas match `.howone/ai/manifest.json`.
|
|
164
|
+
- zod schemas are strict enough for generated UI inputs and backend contracts.
|
|
165
|
+
- UI code calls `howone.ai.<action>.run(input)` and `howone.entities.<Entity>.*`.
|
|
166
|
+
- No generated source file is written under `.howone`.
|
package/templates/vite/AGENTS.md
CHANGED
|
@@ -1,11 +1,46 @@
|
|
|
1
|
-
|
|
1
|
+
# AGENTS.md
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This file defines project-specific instructions for coding agents.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
Read this file once when entering the project.
|
|
6
|
+
Follow it during implementation.
|
|
7
|
+
Do not repeatedly reread it unless it changes or the current task requires checking project rules again.
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
```
|
|
9
|
+
## Library Trust Policy
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
For common public libraries already known to modern coding models, prefer model knowledge and package metadata over reading local source files.
|
|
12
|
+
|
|
13
|
+
This project may include generated or vendored library-style files, such as shadcn/ui components under `src/components/ui/*`.
|
|
14
|
+
|
|
15
|
+
Do not inspect these files during ordinary feature work just to confirm standard APIs.
|
|
16
|
+
|
|
17
|
+
Examples of trusted public libraries:
|
|
18
|
+
|
|
19
|
+
- React
|
|
20
|
+
- Vite
|
|
21
|
+
- TypeScript
|
|
22
|
+
- Tailwind CSS
|
|
23
|
+
- shadcn/ui
|
|
24
|
+
- lucide-react
|
|
25
|
+
- Radix UI
|
|
26
|
+
- clsx
|
|
27
|
+
- class-variance-authority
|
|
28
|
+
|
|
29
|
+
When implementing ordinary usage of these libraries:
|
|
30
|
+
|
|
31
|
+
1. Use standard public APIs first.
|
|
32
|
+
2. Read `package.json`, `components.json`, `tsconfig.json`, or alias config only when needed.
|
|
33
|
+
3. Implement the feature.
|
|
34
|
+
4. Run build/typecheck.
|
|
35
|
+
5. Inspect the smallest relevant local file only if validation fails or the API is genuinely unclear.
|
|
36
|
+
|
|
37
|
+
Only read local component or library-style source files when:
|
|
38
|
+
|
|
39
|
+
- build/typecheck fails
|
|
40
|
+
- imports cannot be resolved from `package.json`, `tsconfig.json`, or `components.json`
|
|
41
|
+
- the component API is unclear
|
|
42
|
+
- the task requires modifying the component implementation
|
|
43
|
+
- the project has custom wrappers, custom variants, or unusual exports
|
|
44
|
+
- the user explicitly asks to follow local component conventions
|
|
45
|
+
|
|
46
|
+
Prefer failure-driven inspection over speculative context loading.
|