howone 0.1.15 → 0.1.16

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "howone",
3
- "version": "0.1.15",
3
+ "version": "0.1.16",
4
4
  "private": false,
5
5
  "description": "HowOne command line tools for creating app templates.",
6
6
  "type": "module",
@@ -1,5 +1,32 @@
1
1
  # AI Actions
2
2
 
3
+ ## Manifest Contract — Read This First
4
+
5
+ **`src/lib/sdk.ts` must be generated from `.howone/ai/manifest.json`. Do not write it from memory or from generic examples.**
6
+
7
+ For every capability in `manifest.json`:
8
+ 1. Read `name`, `workflowId`, `inputSchema`, `outputSchema`
9
+ 2. Generate a zod schema from `inputSchema.properties`
10
+ 3. Call `defineAiAction(name, { workflowId, inputSchema })` — **`workflowId` is mandatory**
11
+
12
+ Without `workflowId`, the SDK falls back to using the action name as the URL segment. Action names are not UUIDs — the EAX server will reject the call with "invalid input syntax for type uuid".
13
+
14
+ ## When to Write SDK Bindings
15
+
16
+ **Do NOT write `defineAiAction` until `.howone/ai/manifest.json` contains a confirmed `workflowId`.**
17
+
18
+ Correct sequence:
19
+ 1. `ai_capability_design` — design the capability schema
20
+ 2. `sync_ai_artifacts` — sync manifest to disk
21
+ 3. `external_ai_capability` — submit workflow to EAX; returns confirmed `workflowId`
22
+ 4. Confirmed `workflowId` is written back to the backend capability record
23
+ 5. `sync_ai_artifacts` again — manifest now contains `workflowId`
24
+ 6. Read `.howone/ai/manifest.json` → write `src/lib/sdk.ts` with `workflowId`
25
+
26
+ Building without errors does **not** mean the AI workflow binding is correct. A missing `workflowId` causes a runtime UUID error at the EAX execution call.
27
+
28
+ ---
29
+
3
30
  ## Core Concepts
4
31
 
5
32
  - `defineAiAction(id, config)` declares a typed AI action from a workflow ID.
@@ -16,6 +43,7 @@
16
43
 
17
44
  ```ts
18
45
  type AiActionConfig<TInput, TOutput> = {
46
+ workflowId: string // REQUIRED — UUID from manifest.json. Without this, SDK uses action name as URL segment (not a UUID → EAX rejects).
19
47
  inputSchema?: z.ZodType<TInput> // validates input before calling the workflow
20
48
  outputSchema?: z.ZodType<TOutput> // validates the full ExecutionResult envelope (see caution below)
21
49
  mode?: 'run' | 'stream' | 'events' // default: supports all three modes
@@ -69,12 +97,13 @@ type AiEvent = {
69
97
 
70
98
  ## Defining AI Actions
71
99
 
72
- ### Basic action — input only, output unwrapped manually
100
+ ### Basic action — always include workflowId from manifest.json
73
101
 
74
102
  ```ts
75
103
  import { defineAiAction, defineAiActions } from '@howone/sdk'
76
104
  import { z } from 'zod'
77
105
 
106
+ // Source: .howone/ai/manifest.json → capabilities[0].inputSchema.properties
78
107
  export const generateStoryInputSchema = z.object({
79
108
  topic: z.string().min(1),
80
109
  ageRange: z.enum(['3-5', '6-8', '9-12']),
@@ -82,8 +111,10 @@ export const generateStoryInputSchema = z.object({
82
111
  })
83
112
  export type GenerateStoryInput = z.infer<typeof generateStoryInputSchema>
84
113
 
114
+ // workflowId from .howone/ai/manifest.json → capabilities[0].workflowId
85
115
  export const ai = defineAiActions({
86
116
  generateStory: defineAiAction('generateStory', {
117
+ workflowId: 'd69ab648-2c00-4d94-928e-01bd7b2a5bb2', // ← from manifest.json
87
118
  inputSchema: generateStoryInputSchema,
88
119
  }),
89
120
  })
@@ -103,31 +134,39 @@ export type GenerateStoryOutput = z.infer<typeof generateStoryOutputSchema>
103
134
  // AiResult envelope. Instead, cast finalResult after run():
104
135
  export const ai = defineAiActions({
105
136
  generateStory: defineAiAction('generateStory', {
137
+ workflowId: 'd69ab648-2c00-4d94-928e-01bd7b2a5bb2', // ← from manifest.json
106
138
  inputSchema: generateStoryInputSchema,
107
139
  // outputSchema: omit — cast manually
108
140
  }),
109
141
  })
110
142
  ```
111
143
 
112
- ### Multiple actions
144
+ ### Multiple actions — each must have its own workflowId from manifest.json
113
145
 
114
146
  ```ts
147
+ // Each workflowId is the UUID from .howone/ai/manifest.json for that capability
115
148
  export const ai = defineAiActions({
116
149
  generateStory: defineAiAction('generateStory', {
150
+ workflowId: 'd69ab648-2c00-4d94-928e-01bd7b2a5bb2',
117
151
  inputSchema: z.object({ topic: z.string(), language: z.string() }),
118
152
  }),
119
153
  translateText: defineAiAction('translateText', {
154
+ workflowId: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
120
155
  inputSchema: z.object({ text: z.string(), targetLang: z.string() }),
121
156
  }),
122
157
  summarizeArticle: defineAiAction('summarizeArticle', {
158
+ workflowId: 'f9e8d7c6-b5a4-3210-fedc-ba9876543210',
123
159
  inputSchema: z.object({ url: z.string().url(), maxWords: z.number().int().optional() }),
124
160
  }),
125
161
  analyzeImage: defineAiAction('analyzeImage', {
162
+ workflowId: '11223344-5566-7788-99aa-bbccddeeff00',
126
163
  inputSchema: z.object({ imageUrl: z.string().url(), prompt: z.string().optional() }),
127
164
  }),
128
165
  })
129
166
  ```
130
167
 
168
+ > **Note**: The UUIDs above are placeholders. Always copy the exact value from `.howone/ai/manifest.json`.
169
+
131
170
  ---
132
171
 
133
172
  ## Calling AI Actions
@@ -482,6 +521,9 @@ function StreamingStoryGenerator({ input }: { input: GenerateStoryInput }) {
482
521
 
483
522
  | Mistake | Correct Pattern |
484
523
  |---|---|
524
+ | `defineAiAction('generateStory', { inputSchema })` — no `workflowId` | Always include `workflowId` from `manifest.json`; SDK falls back to action name, which is not a UUID → EAX rejects |
525
+ | Writing `src/lib/sdk.ts` before `sync_ai_artifacts` has a confirmed `workflowId` | Run `external_ai_capability` → `sync_ai_artifacts` first; only write bindings after manifest has `workflowId` |
526
+ | Hardcoding `workflowId` from memory or guessing | Always read from `.howone/ai/manifest.json` — copy the exact UUID |
485
527
  | `howone.ai.run.generateStory(input)` | `howone.ai.generateStory.run(input)` |
486
528
  | Action named `run`, `stream`, or `events` | Rename to e.g. `executeWorkflow`, `streamContent` |
487
529
  | `outputSchema: z.object({ title: z.string() })` expecting `finalResult` shape | Omit `outputSchema`; cast `result.finalResult` manually |
@@ -19,6 +19,7 @@ export const entities = defineEntities({
19
19
  export const ai = defineAiActions({
20
20
  // Add generated AI action bindings here, for example:
21
21
  // generateImage: defineAiAction("generateImage", {
22
+ // workflowId: "<workflow-uuid>", // workflow ID for this capability
22
23
  // inputSchema: generateImageInputSchema,
23
24
  // outputSchema: generateImageOutputSchema,
24
25
  // }),