@harperfast/template-vue-ts-studio 1.6.3 → 1.7.0

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 (26) hide show
  1. package/.agents/skills/harper-best-practices/AGENTS.md +1686 -361
  2. package/.agents/skills/harper-best-practices/SKILL.md +25 -20
  3. package/.agents/skills/harper-best-practices/rules/adding-tables-with-schemas.md +2 -0
  4. package/.agents/skills/harper-best-practices/rules/automatic-apis.md +141 -18
  5. package/.agents/skills/harper-best-practices/rules/caching.md +134 -21
  6. package/.agents/skills/harper-best-practices/rules/checking-authentication.md +139 -148
  7. package/.agents/skills/harper-best-practices/rules/creating-a-fabric-account-and-cluster.md +2 -0
  8. package/.agents/skills/harper-best-practices/rules/creating-harper-apps.md +7 -2
  9. package/.agents/skills/harper-best-practices/rules/custom-resources.md +2 -0
  10. package/.agents/skills/harper-best-practices/rules/defining-relationships.md +2 -0
  11. package/.agents/skills/harper-best-practices/rules/deploying-to-harper-fabric.md +97 -77
  12. package/.agents/skills/harper-best-practices/rules/extending-tables.md +2 -0
  13. package/.agents/skills/harper-best-practices/rules/handling-binary-data.md +2 -0
  14. package/.agents/skills/harper-best-practices/rules/load-env.md +100 -0
  15. package/.agents/skills/harper-best-practices/rules/logging.md +154 -77
  16. package/.agents/skills/harper-best-practices/rules/programmatic-table-requests.md +32 -26
  17. package/.agents/skills/harper-best-practices/rules/querying-rest-apis.md +190 -15
  18. package/.agents/skills/harper-best-practices/rules/real-time-apps.md +80 -21
  19. package/.agents/skills/harper-best-practices/rules/schema-design-tooling.md +133 -40
  20. package/.agents/skills/harper-best-practices/rules/serving-web-content.md +2 -0
  21. package/.agents/skills/harper-best-practices/rules/typescript-type-stripping.md +48 -16
  22. package/.agents/skills/harper-best-practices/rules/using-blob-datatype.md +2 -0
  23. package/.agents/skills/harper-best-practices/rules/vector-indexing.md +85 -120
  24. package/.agents/skills/harper-best-practices/rules.manifest.yaml +302 -0
  25. package/package.json +1 -1
  26. package/skills-lock.json +1 -1
@@ -1,40 +1,56 @@
1
1
  ---
2
2
  name: vector-indexing
3
3
  description: How to enable and query vector indexes for similarity search in Harper.
4
+ metadata:
5
+ mode: generate
6
+ sources:
7
+ - reference/v5/database/schema.md#Vector Indexing
8
+ sourceCommit: b7fbddadd42eb4487190b650a9abc4bcfeef5819
9
+ inputHash: 3732961c671aac00
4
10
  ---
5
11
 
6
12
  # Vector Indexing
7
13
 
8
- Instructions for the agent to follow when implementing vector search in Harper.
14
+ Instructions for the agent to follow when enabling and querying vector indexes for similarity search in Harper using the HNSW algorithm.
9
15
 
10
16
  ## When to Use
11
17
 
12
- Use this skill when you need to perform similarity searches on high-dimensional data, such as AI embeddings for semantic search, recommendations, or image retrieval.
18
+ Apply this rule when adding a vector index to a Harper table schema or writing similarity search queries against high-dimensional vector fields. Use it whenever you need approximate nearest-neighbor search, distance-threshold filtering, or distance-scored results.
13
19
 
14
20
  ## How It Works
15
21
 
16
- 1. **Enable Vector Indexing**: In your GraphQL schema, add `@indexed(type: "HNSW")` to a numeric array field:
22
+ 1. **Declare the vector index on a `[Float]` field**: Add `@indexed(type: "HNSW")` to any `[Float]` attribute in a `@table` type. See [adding-tables-with-schemas.md](adding-tables-with-schemas.md) for general schema setup.
23
+
17
24
  ```graphql
18
- type Product @table {
19
- id: ID @primaryKey
25
+ type Document @table {
26
+ id: Long @primaryKey
20
27
  textEmbeddings: [Float] @indexed(type: "HNSW")
21
28
  }
22
29
  ```
23
- 2. **Configure Index Options (Optional)**: Fine-tune the index with parameters like `distance` (`cosine` or `euclidean`), `M`, and `efConstruction`.
24
- 3. **Query with Vector Search**: Use `tables.Table.search()` with a `sort` object containing the `target` vector:
30
+
31
+ 2. **Query by nearest neighbors using `sort`**: Call `Document.search()` with a `sort` object containing `attribute` (the indexed field name) and `target` (the query vector). Include `limit` to cap results.
32
+
25
33
  ```javascript
26
- const results = await tables.Product.search({
27
- select: ['name', '$distance'],
28
- sort: {
29
- attribute: 'textEmbeddings',
30
- target: [0.1, 0.2, ...], // query vector
31
- },
32
- limit: 5,
34
+ let results = Document.search({
35
+ sort: { attribute: 'textEmbeddings', target: searchVector },
36
+ limit: 5,
33
37
  });
34
38
  ```
35
- 4. **Filter by Distance**: Use `conditions` with a `target` vector and a `comparator` (e.g., `lt`) to return results within a similarity threshold:
39
+
40
+ 3. **Combine with filter conditions**: Add a `conditions` array alongside `sort` to pre-filter records before ranking by similarity.
41
+
36
42
  ```javascript
37
- const results = await tables.Product.search({
43
+ let results = Document.search({
44
+ conditions: [{ attribute: 'price', comparator: 'lt', value: 50 }],
45
+ sort: { attribute: 'textEmbeddings', target: searchVector },
46
+ limit: 5,
47
+ });
48
+ ```
49
+
50
+ 4. **Filter by distance threshold**: To return only records within a similarity cutoff (without ranking), place `target` directly on the condition alongside `comparator` and `value`. Omit `sort`.
51
+
52
+ ```javascript
53
+ let results = Document.search({
38
54
  conditions: {
39
55
  attribute: 'textEmbeddings',
40
56
  comparator: 'lt',
@@ -43,117 +59,66 @@ Use this skill when you need to perform similarity searches on high-dimensional
43
59
  },
44
60
  });
45
61
  ```
46
- 5. **Generate Embeddings**: Use external services (OpenAI, Ollama) to generate the numeric vectors before storing or searching them in Harper.
47
-
48
- ```typescript
49
- import OpenAI from 'openai';
50
- import ollama from 'ollama';
51
-
52
- const { Product } = tables;
53
- const openai = new OpenAI();
54
- // the name of the OpenAI embedding model
55
- const OPENAI_EMBEDDING_MODEL = 'text-embedding-3-small';
56
-
57
- // the name of the Ollama embedding model
58
- const OLLAMA_EMBEDDING_MODEL = 'llama3';
59
-
60
- const SIMILARITY_THRESHOLD = 0.5;
61
-
62
- export class ProductSearch extends Resource {
63
- // based on env variable we choose the appropriate embedding generator
64
- generateEmbedding =
65
- process.env.EMBEDDING_GENERATOR === 'ollama'
66
- ? this._generateOllamaEmbedding
67
- : this._generateOpenAIEmbedding;
68
-
69
- /**
70
- * Executes a search query using a generated text embedding and returns the matching products.
71
- *
72
- * @param {Object} data - The input data for the request.
73
- * @param {string} data.prompt - The prompt to generate the text embedding from.
74
- * @return {Promise<Array>} Returns a promise that resolves to an array of products matching the conditions,
75
- * including fields: name, description, price, and $distance.
76
- */
77
- async post(data) {
78
- const embedding = await this.generateEmbedding(data.prompt);
79
-
80
- return await Product.search({
81
- select: ['name', 'description', 'price', '$distance'],
82
- conditions: {
83
- attribute: 'textEmbeddings',
84
- comparator: 'lt',
85
- value: SIMILARITY_THRESHOLD,
86
- target: embedding[0],
87
- },
88
- limit: 5,
89
- });
90
- }
91
-
92
- /**
93
- * Generates an embedding using the Ollama API.
94
- *
95
- * @param {string} promptData - The input data for which the embedding is to be generated.
96
- * @return {Promise<number[][]>} A promise that resolves to the generated embedding as an array of numbers.
97
- */
98
- async _generateOllamaEmbedding(promptData) {
99
- const embedding = await ollama.embed({
100
- model: OLLAMA_EMBEDDING_MODEL,
101
- input: promptData,
102
- });
103
- return embedding?.embeddings;
104
- }
105
-
106
- /**
107
- * Generates OpenAI embeddings based on the given prompt data.
108
- *
109
- * @param {string} promptData - The input data used for generating the embedding.
110
- * @return {Promise<number[][]>} A promise that resolves to an array of embeddings, where each embedding is an array of floats.
111
- */
112
- async _generateOpenAIEmbedding(promptData) {
113
- const embedding = await openai.embeddings.create({
114
- model: OPENAI_EMBEDDING_MODEL,
115
- input: promptData,
116
- encoding_format: 'float',
117
- });
118
-
119
- let embeddings = [];
120
- embedding.data.forEach((embeddingData) => {
121
- embeddings.push(embeddingData.embedding);
122
- });
123
-
124
- return embeddings;
125
- }
126
- }
127
- ```
128
62
 
129
- ## Examples
63
+ 5. **Include computed distance in results**: Use the special `$distance` field in `select` to return the distance from the target vector. Works with both `sort`-based and `conditions`-based queries.
130
64
 
131
- Sample request to the `ProductSearch` resource which prompts to find "shorts for the gym":
65
+ ```javascript
66
+ let results = Document.search({
67
+ select: ['name', '$distance'],
68
+ sort: { attribute: 'textEmbeddings', target: searchVector },
69
+ limit: 5,
70
+ });
71
+ ```
132
72
 
133
- ```bash
134
- curl -X POST "http://localhost:9926/ProductSearch/" \
135
- -H "Accept: application/json" \
136
- -H "Content-Type: application/json" \
137
- -H "Authorization: Basic <YOUR_AUTH>" \
138
- -d '{"prompt": "shorts for the gym"}'
139
- ```
73
+ 6. **Tune HNSW parameters**: Pass additional parameters to `@indexed(type: "HNSW", ...)` to control index quality and performance.
140
74
 
141
- ---
75
+ | Parameter | Default | Description |
76
+ | ---------------------- | ----------------- | --------------------------------------------------------------------------------------------------- |
77
+ | `distance` | `"cosine"` | Distance function: `"euclidean"` or `"cosine"` (negative cosine similarity) |
78
+ | `efConstruction` | `100` | Max nodes explored during index construction. Higher = better recall, lower = better performance |
79
+ | `M` | `16` | Preferred connections per graph layer. Higher = more space, better recall for high-dimensional data |
80
+ | `optimizeRouting` | `0.5` | Heuristic aggressiveness for omitting redundant connections (0 = off, 1 = most aggressive) |
81
+ | `mL` | computed from `M` | Normalization factor for level generation |
82
+ | `efSearchConstruction` | `50` | Max nodes explored during search |
142
83
 
143
- ## When to Use Vector Indexing
84
+ ## Examples
144
85
 
145
- Vector indexing is ideal when:
86
+ **Schema with custom HNSW parameters:**
146
87
 
147
- - Storing embedding vectors from ML models
148
- - Performing semantic or similarity-based search
149
- - Working with high-dimensional numeric data
150
- - Exact-match indexes are insufficient
88
+ ```graphql
89
+ type Document @table {
90
+ id: Long @primaryKey
91
+ textEmbeddings: [Float]
92
+ @indexed(type: "HNSW", distance: "euclidean", optimizeRouting: 0, efSearchConstruction: 100)
93
+ }
94
+ ```
151
95
 
152
- ---
96
+ **Nearest-neighbor search with distance score:**
97
+
98
+ ```javascript
99
+ let results = Document.search({
100
+ select: ['name', '$distance'],
101
+ sort: { attribute: 'textEmbeddings', target: searchVector },
102
+ limit: 5,
103
+ });
104
+ ```
105
+
106
+ **Distance-threshold filter (no ranking):**
107
+
108
+ ```javascript
109
+ let results = Document.search({
110
+ conditions: {
111
+ attribute: 'textEmbeddings',
112
+ comparator: 'lt',
113
+ value: 0.1,
114
+ target: searchVector,
115
+ },
116
+ });
117
+ ```
153
118
 
154
- ## Summary
119
+ ## Notes
155
120
 
156
- - Vector indexing enables fast similarity search on numeric arrays
157
- - Defined using `@indexed(type: "HNSW")`
158
- - Queried using a target vector in search sorting
159
- - Tunable for performance and accuracy
121
+ - The default `distance` function is `cosine`. Pass `distance: "euclidean"` to switch.
122
+ - `efConstruction` controls index build quality; raising it improves recall at the cost of build time.
123
+ - `$distance` is available in both `sort`-based ranking and `conditions`-based threshold queries.
124
+ - Use the threshold (`conditions` + `target`) form when you want to bound result quality by a similarity cutoff rather than ranking by similarity.
@@ -0,0 +1,302 @@
1
+ # Rules manifest for the harper-best-practices skill.
2
+ #
3
+ # Declarative source of truth for rule taxonomy, sources, and generation mode.
4
+ # Owned by humans; the generator reads this file and writes derived artifacts
5
+ # (rule bodies, AGENTS.md). See docs/plans/docs-driven-skills.md for the
6
+ # full schema definition and Manifest ↔ frontmatter reconciliation semantics.
7
+ #
8
+ # Phase 2 flipped vector-indexing to mode: generate.
9
+ # Phase 3 flips 7 obvious 1:1 rules to mode: generate (automatic-apis,
10
+ # querying-rest-apis, real-time-apps, checking-authentication, logging,
11
+ # deploying-to-harper-fabric, caching). All others remain synthesized.
12
+ # Phase 4 migrates schema-design-tooling and typescript-type-stripping to
13
+ # mode: generate. creating-harper-apps stays synthesized pending dedicated
14
+ # create-harper CLI documentation.
15
+
16
+ rules:
17
+ # ===========================================================================
18
+ # Schema & Data Design (priority 1 — HIGH)
19
+ # ===========================================================================
20
+
21
+ - rule: adding-tables-with-schemas
22
+ description: Guidelines for adding tables to a Harper database using GraphQL schemas.
23
+ category: schema
24
+ priority: 1
25
+ order: 1
26
+ mode: synthesized
27
+
28
+ - rule: schema-design-tooling
29
+ description: Best practices for Harper schema design, including core directives and GraphQL tooling configuration.
30
+ category: schema
31
+ priority: 1
32
+ order: 2
33
+ mode: generate
34
+ sources:
35
+ - path: reference/v5/database/schema.md
36
+ section: 'Overview'
37
+ role: primary
38
+ - path: reference/v5/database/schema.md
39
+ section: 'Type Directives'
40
+ role: primary
41
+ - path: reference/v5/database/schema.md
42
+ section: 'Field Directives'
43
+ role: primary
44
+ must_cover:
45
+ - '@table'
46
+ - '@export'
47
+ - '@primaryKey'
48
+ - '@indexed'
49
+ - 'graphqlSchema'
50
+
51
+ - rule: defining-relationships
52
+ description: How to define and use relationships between tables in Harper using GraphQL.
53
+ category: schema
54
+ priority: 1
55
+ order: 3
56
+ mode: synthesized
57
+
58
+ - rule: vector-indexing
59
+ description: How to enable and query vector indexes for similarity search in Harper.
60
+ category: schema
61
+ priority: 1
62
+ order: 4
63
+ mode: generate
64
+ sources:
65
+ - path: reference/v5/database/schema.md
66
+ section: 'Vector Indexing'
67
+ role: primary
68
+ must_cover:
69
+ - '@indexed(type: "HNSW")'
70
+ - 'sort'
71
+ - 'target'
72
+ - 'cosine'
73
+ - 'efConstruction'
74
+ cross_links:
75
+ - adding-tables-with-schemas
76
+
77
+ - rule: using-blob-datatype
78
+ description: How to use the Blob data type for efficient binary storage in Harper.
79
+ category: schema
80
+ priority: 1
81
+ order: 5
82
+ mode: synthesized
83
+
84
+ - rule: handling-binary-data
85
+ description: How to store and serve binary data like images or audio in Harper.
86
+ category: schema
87
+ priority: 1
88
+ order: 6
89
+ mode: synthesized
90
+
91
+ # ===========================================================================
92
+ # API & Communication (priority 2 — HIGH)
93
+ # ===========================================================================
94
+
95
+ - rule: automatic-apis
96
+ description: How to use Harper's automatically generated REST and WebSocket APIs.
97
+ category: api
98
+ priority: 2
99
+ order: 1
100
+ mode: generate
101
+ sources:
102
+ - path: reference/v5/rest/overview.md
103
+ role: primary
104
+ - path: reference/v5/rest/websockets.md
105
+ role: supplemental
106
+ must_cover:
107
+ - 'rest: true'
108
+ - '@export'
109
+ - 'WebSocket'
110
+ cross_links:
111
+ - querying-rest-apis
112
+ - real-time-apps
113
+
114
+ - rule: querying-rest-apis
115
+ description: How to use query parameters to filter, sort, and paginate Harper REST APIs.
116
+ category: api
117
+ priority: 2
118
+ order: 2
119
+ mode: generate
120
+ sources:
121
+ - path: reference/v5/rest/querying.md
122
+ role: primary
123
+ must_cover:
124
+ - '=gt='
125
+ - '=lt='
126
+ - 'select('
127
+ - 'sort('
128
+ - 'limit('
129
+ cross_links:
130
+ - automatic-apis
131
+
132
+ - rule: real-time-apps
133
+ description: How to build real-time features in Harper using WebSockets and Pub/Sub.
134
+ category: api
135
+ priority: 2
136
+ order: 3
137
+ mode: generate
138
+ sources:
139
+ - path: reference/v5/rest/websockets.md
140
+ role: primary
141
+ must_cover:
142
+ - 'WebSocket'
143
+ - 'connect('
144
+ cross_links:
145
+ - automatic-apis
146
+
147
+ - rule: checking-authentication
148
+ description: How to handle user authentication and sessions in Harper Resources.
149
+ category: api
150
+ priority: 2
151
+ order: 4
152
+ mode: generate
153
+ sources:
154
+ - path: reference/v5/resources/resource-api.md
155
+ section: '`getCurrentUser(): User | undefined`'
156
+ role: primary
157
+ - path: reference/v5/resources/resource-api.md
158
+ section: 'Session and Login from a Resource'
159
+ role: primary
160
+ - path: reference/v5/security/jwt-authentication.md
161
+ role: supplemental
162
+ must_cover:
163
+ - 'getCurrentUser()'
164
+ - 'getContext()'
165
+ - 'context.login'
166
+ - 'enableSessions'
167
+ cross_links:
168
+ - custom-resources
169
+
170
+ # ===========================================================================
171
+ # Logic & Extension (priority 3 — MEDIUM)
172
+ # ===========================================================================
173
+
174
+ - rule: custom-resources
175
+ description: How to define custom REST endpoints with JavaScript or TypeScript in Harper.
176
+ category: logic
177
+ priority: 3
178
+ order: 1
179
+ mode: synthesized
180
+
181
+ - rule: extending-tables
182
+ description: How to add custom logic to automatically generated table resources in Harper.
183
+ category: logic
184
+ priority: 3
185
+ order: 2
186
+ mode: synthesized
187
+
188
+ - rule: programmatic-table-requests
189
+ description: How to interact with Harper tables programmatically using the `tables` object.
190
+ category: logic
191
+ priority: 3
192
+ order: 3
193
+ mode: synthesized
194
+
195
+ - rule: typescript-type-stripping
196
+ description: How to run TypeScript files directly in Harper without a build step.
197
+ category: logic
198
+ priority: 3
199
+ order: 4
200
+ mode: generate
201
+ sources:
202
+ - path: reference/v5/components/javascript-environment.md
203
+ section: 'TypeScript Support'
204
+ role: primary
205
+ must_cover:
206
+ - '.ts'
207
+ - 'jsResource'
208
+ - 'Node.js 22.6'
209
+ - 'type stripping'
210
+
211
+ - rule: caching
212
+ description: How to implement integrated data caching in Harper from external sources.
213
+ category: logic
214
+ priority: 3
215
+ order: 5
216
+ mode: generate
217
+ sources:
218
+ - path: learn/developers/caching-with-harper.md
219
+ role: primary
220
+ must_cover:
221
+ - 'expiration'
222
+ - 'sourcedFrom'
223
+ - '@table'
224
+ cross_links:
225
+ - custom-resources
226
+ - automatic-apis
227
+
228
+ # ===========================================================================
229
+ # Infrastructure & Ops (priority 4 — MEDIUM)
230
+ # ===========================================================================
231
+
232
+ - rule: deploying-to-harper-fabric
233
+ description: How to deploy a Harper application to the Harper Fabric cloud.
234
+ category: ops
235
+ priority: 4
236
+ order: 1
237
+ mode: generate
238
+ sources:
239
+ - path: reference/v5/components/applications.md
240
+ section: 'Remote Management'
241
+ role: primary
242
+ - path: fabric/cluster-creation-management.md
243
+ section: 'Connecting the Harper CLI to a Cluster'
244
+ role: supplemental
245
+ must_cover:
246
+ - 'harper deploy'
247
+ - 'harper login'
248
+ cross_links:
249
+ - creating-a-fabric-account-and-cluster
250
+
251
+ - rule: creating-a-fabric-account-and-cluster
252
+ description: How to create a Harper Fabric account, organization, and cluster.
253
+ category: ops
254
+ priority: 4
255
+ order: 2
256
+ mode: synthesized
257
+
258
+ - rule: creating-harper-apps
259
+ description: How to initialize a new Harper application using the CLI.
260
+ category: ops
261
+ priority: 4
262
+ order: 3
263
+ mode: synthesized
264
+
265
+ - rule: serving-web-content
266
+ description: How to serve static files and integrated Vite/React applications in Harper.
267
+ category: ops
268
+ priority: 4
269
+ order: 4
270
+ mode: synthesized
271
+
272
+ - rule: logging
273
+ description: Best practices for logging in Harper, including console capture, the granular logger interface, and programmatic log retrieval.
274
+ category: ops
275
+ priority: 4
276
+ order: 5
277
+ mode: generate
278
+ sources:
279
+ - path: reference/v5/logging/overview.md
280
+ role: primary
281
+ - path: reference/v5/logging/api.md
282
+ role: primary
283
+ must_cover:
284
+ - 'console.log'
285
+ - 'logger'
286
+ - 'withTag('
287
+
288
+ - rule: load-env
289
+ description: How to load environment variables from .env files into a Harper application using the loadEnv plugin.
290
+ category: ops
291
+ priority: 4
292
+ order: 6
293
+ mode: generate
294
+ sources:
295
+ - path: reference/v5/environment-variables/overview.md
296
+ role: primary
297
+ must_cover:
298
+ - 'loadEnv'
299
+ - 'files'
300
+ - 'process.env'
301
+ - 'override'
302
+ - 'config.yaml'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@harperfast/template-vue-ts-studio",
3
- "version": "1.6.3",
3
+ "version": "1.7.0",
4
4
  "type": "module",
5
5
  "repository": "github:HarperFast/create-harper",
6
6
  "scripts": {},
package/skills-lock.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "source": "harperfast/skills",
6
6
  "sourceType": "github",
7
7
  "skillPath": "harper-best-practices/SKILL.md",
8
- "computedHash": "838b776573e9ebd05ac70c9ad38233a5bf40d1882be0cc54744168092e96e251"
8
+ "computedHash": "95a41a7ba907538a69fc52b31399db843b403b617cc6705d9e54ee2c0b7af502"
9
9
  }
10
10
  }
11
11
  }