@vertesia/client 1.0.0-dev.20260128.144200 → 1.0.0-dev.20260225.024852Z

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 (106) hide show
  1. package/lib/cjs/AuditTrailApi.js +35 -0
  2. package/lib/cjs/AuditTrailApi.js.map +1 -0
  3. package/lib/cjs/ProjectsApi.js +16 -0
  4. package/lib/cjs/ProjectsApi.js.map +1 -1
  5. package/lib/cjs/RunsApi.js +0 -5
  6. package/lib/cjs/RunsApi.js.map +1 -1
  7. package/lib/cjs/UsersApi.js +7 -1
  8. package/lib/cjs/UsersApi.js.map +1 -1
  9. package/lib/cjs/client.js +2 -0
  10. package/lib/cjs/client.js.map +1 -1
  11. package/lib/cjs/store/HiveMemoryApi.js +174 -0
  12. package/lib/cjs/store/HiveMemoryApi.js.map +1 -0
  13. package/lib/cjs/store/IndexingApi.js +207 -0
  14. package/lib/cjs/store/IndexingApi.js.map +1 -0
  15. package/lib/cjs/store/ObjectsApi.js +6 -4
  16. package/lib/cjs/store/ObjectsApi.js.map +1 -1
  17. package/lib/cjs/store/QueryApi.js +67 -0
  18. package/lib/cjs/store/QueryApi.js.map +1 -0
  19. package/lib/cjs/store/RenderingApi.js +84 -0
  20. package/lib/cjs/store/RenderingApi.js.map +1 -0
  21. package/lib/cjs/store/TypeCatalogApi.js +50 -0
  22. package/lib/cjs/store/TypeCatalogApi.js.map +1 -0
  23. package/lib/cjs/store/TypesApi.js +3 -0
  24. package/lib/cjs/store/TypesApi.js.map +1 -1
  25. package/lib/cjs/store/client.js +8 -0
  26. package/lib/cjs/store/client.js.map +1 -1
  27. package/lib/cjs/store/index.js +6 -0
  28. package/lib/cjs/store/index.js.map +1 -1
  29. package/lib/cjs/store/version.js +1 -1
  30. package/lib/esm/AuditTrailApi.js +32 -0
  31. package/lib/esm/AuditTrailApi.js.map +1 -0
  32. package/lib/esm/ProjectsApi.js +16 -0
  33. package/lib/esm/ProjectsApi.js.map +1 -1
  34. package/lib/esm/RunsApi.js +0 -5
  35. package/lib/esm/RunsApi.js.map +1 -1
  36. package/lib/esm/UsersApi.js +8 -2
  37. package/lib/esm/UsersApi.js.map +1 -1
  38. package/lib/esm/client.js +2 -0
  39. package/lib/esm/client.js.map +1 -1
  40. package/lib/esm/store/HiveMemoryApi.js +170 -0
  41. package/lib/esm/store/HiveMemoryApi.js.map +1 -0
  42. package/lib/esm/store/IndexingApi.js +203 -0
  43. package/lib/esm/store/IndexingApi.js.map +1 -0
  44. package/lib/esm/store/ObjectsApi.js +7 -5
  45. package/lib/esm/store/ObjectsApi.js.map +1 -1
  46. package/lib/esm/store/QueryApi.js +63 -0
  47. package/lib/esm/store/QueryApi.js.map +1 -0
  48. package/lib/esm/store/RenderingApi.js +80 -0
  49. package/lib/esm/store/RenderingApi.js.map +1 -0
  50. package/lib/esm/store/TypeCatalogApi.js +46 -0
  51. package/lib/esm/store/TypeCatalogApi.js.map +1 -0
  52. package/lib/esm/store/TypesApi.js +3 -0
  53. package/lib/esm/store/TypesApi.js.map +1 -1
  54. package/lib/esm/store/client.js +8 -0
  55. package/lib/esm/store/client.js.map +1 -1
  56. package/lib/esm/store/index.js +6 -0
  57. package/lib/esm/store/index.js.map +1 -1
  58. package/lib/esm/store/version.js +1 -1
  59. package/lib/tsconfig.tsbuildinfo +1 -1
  60. package/lib/types/AuditTrailApi.d.ts +6 -0
  61. package/lib/types/AuditTrailApi.d.ts.map +1 -0
  62. package/lib/types/ProjectsApi.d.ts +5 -1
  63. package/lib/types/ProjectsApi.d.ts.map +1 -1
  64. package/lib/types/RunsApi.d.ts +1 -2
  65. package/lib/types/RunsApi.d.ts.map +1 -1
  66. package/lib/types/UsersApi.d.ts +6 -2
  67. package/lib/types/UsersApi.d.ts.map +1 -1
  68. package/lib/types/client.d.ts +2 -0
  69. package/lib/types/client.d.ts.map +1 -1
  70. package/lib/types/store/HiveMemoryApi.d.ts +160 -0
  71. package/lib/types/store/HiveMemoryApi.d.ts.map +1 -0
  72. package/lib/types/store/IndexingApi.d.ts +140 -0
  73. package/lib/types/store/IndexingApi.d.ts.map +1 -0
  74. package/lib/types/store/ObjectsApi.d.ts +3 -1
  75. package/lib/types/store/ObjectsApi.d.ts.map +1 -1
  76. package/lib/types/store/QueryApi.d.ts +99 -0
  77. package/lib/types/store/QueryApi.d.ts.map +1 -0
  78. package/lib/types/store/RenderingApi.d.ts +34 -0
  79. package/lib/types/store/RenderingApi.d.ts.map +1 -0
  80. package/lib/types/store/TypeCatalogApi.d.ts +39 -0
  81. package/lib/types/store/TypeCatalogApi.d.ts.map +1 -0
  82. package/lib/types/store/TypesApi.d.ts +2 -0
  83. package/lib/types/store/TypesApi.d.ts.map +1 -1
  84. package/lib/types/store/client.d.ts +8 -0
  85. package/lib/types/store/client.d.ts.map +1 -1
  86. package/lib/types/store/index.d.ts +6 -0
  87. package/lib/types/store/index.d.ts.map +1 -1
  88. package/lib/types/store/version.d.ts +1 -1
  89. package/lib/vertesia-client.js +1 -1
  90. package/lib/vertesia-client.js.map +1 -1
  91. package/package.json +4 -4
  92. package/src/AuditTrailApi.ts +25 -0
  93. package/src/ProjectsApi.ts +21 -1
  94. package/src/RunsApi.ts +0 -7
  95. package/src/UsersApi.ts +9 -5
  96. package/src/client.ts +2 -0
  97. package/src/store/HiveMemoryApi.ts +231 -0
  98. package/src/store/IndexingApi.ts +250 -0
  99. package/src/store/ObjectsApi.ts +12 -8
  100. package/src/store/QueryApi.ts +110 -0
  101. package/src/store/RenderingApi.ts +105 -0
  102. package/src/store/TypeCatalogApi.ts +53 -0
  103. package/src/store/TypesApi.ts +3 -0
  104. package/src/store/client.ts +8 -0
  105. package/src/store/index.ts +6 -0
  106. package/src/store/version.ts +1 -1
package/src/client.ts CHANGED
@@ -3,6 +3,7 @@ import { AuthTokenPayload, AuthTokenResponse } from "@vertesia/common";
3
3
  import AccountApi from "./AccountApi.js";
4
4
  import AccountsApi from "./AccountsApi.js";
5
5
  import AnalyticsApi from "./AnalyticsApi.js";
6
+ import AuditTrailApi from "./AuditTrailApi.js";
6
7
  import { ApiKeysApi } from "./ApiKeysApi.js";
7
8
  import AppsApi from "./AppsApi.js";
8
9
  import CommandsApi from "./CommandsApi.js";
@@ -333,6 +334,7 @@ export class VertesiaClient extends AbstractFetchClient<VertesiaClient> {
333
334
  accounts = new AccountsApi(this);
334
335
  apikeys = new ApiKeysApi(this);
335
336
  analytics = new AnalyticsApi(this);
337
+ auditTrail = new AuditTrailApi(this);
336
338
  training = new TrainingApi(this);
337
339
  users = new UsersApi(this);
338
340
  iam = new IamApi(this);
@@ -0,0 +1,231 @@
1
+ import { ApiTopic, ClientBase } from "@vertesia/api-fetch-client";
2
+ import {
3
+ CreateHiveMemoryPayload,
4
+ FormattedMemoryForAgent,
5
+ HiveMemory,
6
+ HiveMemorySearchParams,
7
+ HiveMemorySearchResult,
8
+ UpdateHiveMemoryPayload,
9
+ } from "@vertesia/common";
10
+
11
+ /**
12
+ * Statistics about hive memories in the project
13
+ */
14
+ export interface HiveMemoryStats {
15
+ total_memories: number;
16
+ by_category: Array<{
17
+ category: string;
18
+ count: number;
19
+ avg_confidence: number;
20
+ total_usage: number;
21
+ }>;
22
+ overall: {
23
+ avgConfidence: number;
24
+ avgUsage: number;
25
+ totalContributions: number;
26
+ };
27
+ }
28
+
29
+ /**
30
+ * Result from recall endpoint
31
+ */
32
+ export interface RecallResult {
33
+ memories: FormattedMemoryForAgent[];
34
+ count: number;
35
+ }
36
+
37
+ /**
38
+ * Client API for managing hive memories.
39
+ *
40
+ * Hive memory is a system for storing and retrieving agent learnings,
41
+ * enabling agents to learn from past runs and share knowledge.
42
+ */
43
+ export class HiveMemoryApi extends ApiTopic {
44
+ constructor(parent: ClientBase) {
45
+ super(parent, "/api/v1/hive-memory");
46
+ }
47
+
48
+ /**
49
+ * List memories in the project.
50
+ *
51
+ * @param options - Optional filters and pagination
52
+ */
53
+ list(options?: {
54
+ category?: string;
55
+ scope?: string;
56
+ limit?: number;
57
+ offset?: number;
58
+ }): Promise<HiveMemory[]> {
59
+ const params = new URLSearchParams();
60
+ if (options?.category) params.set('category', options.category);
61
+ if (options?.scope) params.set('scope', options.scope);
62
+ if (options?.limit) params.set('limit', String(options.limit));
63
+ if (options?.offset) params.set('offset', String(options.offset));
64
+
65
+ const queryString = params.toString();
66
+ return this.get(queryString ? `/?${queryString}` : '/');
67
+ }
68
+
69
+ /**
70
+ * Retrieve a memory by ID.
71
+ */
72
+ retrieve(id: string): Promise<HiveMemory> {
73
+ return this.get(`/${id}`);
74
+ }
75
+
76
+ /**
77
+ * Create a new hive memory.
78
+ *
79
+ * @param payload - Memory content including category, summary, and learnings
80
+ */
81
+ create(payload: CreateHiveMemoryPayload): Promise<HiveMemory> {
82
+ return this.post("/", { payload });
83
+ }
84
+
85
+ /**
86
+ * Update an existing memory with new learnings.
87
+ *
88
+ * This merges new learnings with existing ones rather than replacing them.
89
+ *
90
+ * @param id - Memory ID
91
+ * @param payload - Fields to update/merge
92
+ */
93
+ update(id: string, payload: UpdateHiveMemoryPayload): Promise<HiveMemory> {
94
+ return this.put(`/${id}`, { payload });
95
+ }
96
+
97
+ /**
98
+ * Delete a memory.
99
+ *
100
+ * @param id - Memory ID
101
+ */
102
+ delete(id: string): Promise<{ id: string; deleted: boolean }> {
103
+ return this.del(`/${id}`);
104
+ }
105
+
106
+ /**
107
+ * Search memories using semantic and keyword search.
108
+ *
109
+ * @param params - Search parameters including query, filters, and pagination
110
+ */
111
+ search(params: HiveMemorySearchParams): Promise<HiveMemorySearchResult> {
112
+ return this.post("/search", { payload: params });
113
+ }
114
+
115
+ /**
116
+ * Recall memories for an agent.
117
+ *
118
+ * This is the primary method for agents to retrieve relevant learnings.
119
+ * It searches for memories matching the task description and returns
120
+ * them formatted for agent consumption.
121
+ *
122
+ * @param taskDescription - Description of the current task
123
+ * @param options - Optional filters
124
+ *
125
+ * @example
126
+ * ```typescript
127
+ * const result = await client.hiveMemory.recall(
128
+ * "Extract financial data from PDF documents",
129
+ * {
130
+ * tools: ["extract_text", "analyze_document"],
131
+ * maxResults: 5
132
+ * }
133
+ * );
134
+ * ```
135
+ */
136
+ recall(
137
+ taskDescription: string,
138
+ options?: {
139
+ tools?: string[];
140
+ category?: string;
141
+ maxResults?: number;
142
+ }
143
+ ): Promise<RecallResult> {
144
+ return this.post("/recall", {
145
+ payload: {
146
+ task_description: taskDescription,
147
+ tools: options?.tools,
148
+ category: options?.category,
149
+ max_results: options?.maxResults,
150
+ }
151
+ });
152
+ }
153
+
154
+ /**
155
+ * Get a memory formatted for agent consumption.
156
+ *
157
+ * @param id - Memory ID
158
+ */
159
+ getFormatted(id: string): Promise<FormattedMemoryForAgent> {
160
+ return this.get(`/${id}/formatted`);
161
+ }
162
+
163
+ /**
164
+ * Record that a memory was used.
165
+ *
166
+ * This increments the usage count and helps track memory effectiveness.
167
+ *
168
+ * @param id - Memory ID
169
+ */
170
+ recordUsage(id: string): Promise<{ success: boolean }> {
171
+ return this.post(`/${id}/usage`, {});
172
+ }
173
+
174
+ /**
175
+ * Get memories by category.
176
+ *
177
+ * @param category - Task category (e.g., "document-analysis", "data-extraction")
178
+ * @param options - Pagination options
179
+ */
180
+ getByCategory(
181
+ category: string,
182
+ options?: { limit?: number; offset?: number }
183
+ ): Promise<HiveMemory[]> {
184
+ const params = new URLSearchParams();
185
+ if (options?.limit) params.set('limit', String(options.limit));
186
+ if (options?.offset) params.set('offset', String(options.offset));
187
+
188
+ const queryString = params.toString();
189
+ return this.get(`/category/${category}${queryString ? `?${queryString}` : ''}`);
190
+ }
191
+
192
+ /**
193
+ * Get memory statistics for the project.
194
+ */
195
+ getStats(): Promise<HiveMemoryStats> {
196
+ return this.get("/stats");
197
+ }
198
+
199
+ /**
200
+ * Apply confidence decay to unused memories.
201
+ *
202
+ * Admin operation that reduces confidence scores for memories
203
+ * that haven't been used recently.
204
+ *
205
+ * @param options - Decay parameters
206
+ */
207
+ applyDecay(options?: {
208
+ daysThreshold?: number;
209
+ decayRate?: number;
210
+ }): Promise<{ modified_count: number }> {
211
+ return this.post("/admin/decay", {
212
+ payload: {
213
+ days_threshold: options?.daysThreshold,
214
+ decay_rate: options?.decayRate,
215
+ }
216
+ });
217
+ }
218
+
219
+ /**
220
+ * Archive memories with low confidence scores.
221
+ *
222
+ * Admin operation that removes memories below a confidence threshold.
223
+ *
224
+ * @param threshold - Confidence threshold (0-1), default 0.2
225
+ */
226
+ archiveLowConfidence(threshold?: number): Promise<{ archived_count: number }> {
227
+ return this.post("/admin/archive", {
228
+ payload: { threshold }
229
+ });
230
+ }
231
+ }
@@ -0,0 +1,250 @@
1
+ import { ApiTopic, ClientBase } from "@vertesia/api-fetch-client";
2
+ import {
3
+ IndexingStatusResponse,
4
+ GenericCommandResponse,
5
+ ElasticsearchDocumentData,
6
+ BulkIndexResult,
7
+ CreateReindexTargetResult,
8
+ ReindexRangeResult,
9
+ FetchBatchResult,
10
+ IndexBatchResult,
11
+ TriggerReindexResult,
12
+ ElasticsearchIndexStats,
13
+ IndexConfiguration,
14
+ FetchDocumentsByIdsResult,
15
+ BulkDeleteResult,
16
+ EnsureIndexResult,
17
+ SwapAliasResult,
18
+ } from "@vertesia/common";
19
+
20
+ /**
21
+ * API for indexing operations on content objects.
22
+ * Provides status, reindex, and configuration management.
23
+ *
24
+ * Internal endpoints (prefixed with /internal/) are used by Temporal workflow activities
25
+ * and require content_admin permission.
26
+ */
27
+ export class IndexingApi extends ApiTopic {
28
+
29
+ constructor(parent: ClientBase, basePath: string = "/api/v1/indexing") {
30
+ super(parent, basePath);
31
+ }
32
+
33
+ // ========================================================================
34
+ // User-facing endpoints
35
+ // ========================================================================
36
+
37
+ /**
38
+ * Get Elasticsearch status for the current project
39
+ */
40
+ async status(): Promise<IndexingStatusResponse> {
41
+ return this.get("/status");
42
+ }
43
+
44
+ /**
45
+ * Trigger a full reindex of all documents
46
+ * @param recreateIndex If true, drops and recreates the index before reindexing
47
+ */
48
+ async reindex(recreateIndex?: boolean): Promise<GenericCommandResponse> {
49
+ return this.post("/reindex", { payload: { recreateIndex } });
50
+ }
51
+
52
+ /**
53
+ * Enable indexing for this project
54
+ */
55
+ async enableIndexing(): Promise<GenericCommandResponse> {
56
+ return this.post("/enable-indexing");
57
+ }
58
+
59
+ /**
60
+ * Disable indexing for this project
61
+ */
62
+ async disableIndexing(): Promise<GenericCommandResponse> {
63
+ return this.post("/disable-indexing");
64
+ }
65
+
66
+ /**
67
+ * Enable index-based queries for this project
68
+ * @deprecated Queries are now automatically enabled when indexing is enabled
69
+ */
70
+ async enableQueries(): Promise<GenericCommandResponse> {
71
+ return this.post("/enable-queries");
72
+ }
73
+
74
+ /**
75
+ * Disable index-based queries for this project
76
+ * @deprecated Queries are now automatically enabled when indexing is enabled
77
+ */
78
+ async disableQueries(): Promise<GenericCommandResponse> {
79
+ return this.post("/disable-queries");
80
+ }
81
+
82
+ // ========================================================================
83
+ // Internal endpoints - called by Temporal workflow activities
84
+ // ========================================================================
85
+
86
+ /**
87
+ * Index a single document to Elasticsearch
88
+ */
89
+ index(objectId: string, document: ElasticsearchDocumentData): Promise<{ status: string; objectId: string }> {
90
+ return this.post("/internal/index", {
91
+ payload: { objectId, document },
92
+ });
93
+ }
94
+
95
+ /**
96
+ * Delete a document from Elasticsearch
97
+ */
98
+ delete(objectId: string): Promise<{ status: string; objectId: string }> {
99
+ return this.post("/internal/delete", {
100
+ payload: { objectId },
101
+ });
102
+ }
103
+
104
+ /**
105
+ * Bulk index multiple documents to Elasticsearch
106
+ *
107
+ * @param documents Array of documents to index
108
+ * @param targetIndex Optional explicit index name for zero-downtime reindexing
109
+ */
110
+ bulkIndex(
111
+ documents: Array<{ id: string; document: ElasticsearchDocumentData }>,
112
+ targetIndex?: string
113
+ ): Promise<BulkIndexResult> {
114
+ return this.post("/internal/bulk-index", {
115
+ payload: { documents, targetIndex },
116
+ });
117
+ }
118
+
119
+ /**
120
+ * Ensure Elasticsearch index exists for the project
121
+ *
122
+ * @param recreate If true, drops and recreates the index
123
+ */
124
+ ensureIndex(recreate?: boolean): Promise<EnsureIndexResult> {
125
+ return this.post("/internal/ensure-index", {
126
+ payload: { recreate },
127
+ });
128
+ }
129
+
130
+ /**
131
+ * Create a new versioned index for reindexing (without alias)
132
+ * The alias will be swapped after reindexing completes via swapAlias
133
+ */
134
+ createReindexTarget(): Promise<CreateReindexTargetResult> {
135
+ return this.post("/internal/create-reindex-target", {
136
+ payload: {},
137
+ });
138
+ }
139
+
140
+ /**
141
+ * Atomically swap the alias from old index to new index
142
+ *
143
+ * @param newIndexName The new index to point the alias to
144
+ * @param deleteOld If true, deletes the old index after swapping
145
+ */
146
+ swapAlias(newIndexName: string, deleteOld?: boolean): Promise<SwapAliasResult> {
147
+ return this.post("/internal/swap-alias", {
148
+ payload: { newIndexName, deleteOld },
149
+ });
150
+ }
151
+
152
+ /**
153
+ * Get Elasticsearch index statistics for the project
154
+ */
155
+ getStats(): Promise<ElasticsearchIndexStats> {
156
+ return this.post("/internal/stats", {
157
+ payload: {},
158
+ });
159
+ }
160
+
161
+ /**
162
+ * Get the _id range for reindexing (first, last, count)
163
+ * Used by workflow to set up cursor-based pagination
164
+ */
165
+ getReindexRange(): Promise<ReindexRangeResult> {
166
+ return this.post("/internal/reindex-range", {
167
+ payload: {},
168
+ });
169
+ }
170
+
171
+ /**
172
+ * Fetch a batch of documents from MongoDB (without indexing)
173
+ * Used by pipeline approach: fetch next batch while indexing current
174
+ *
175
+ * @param cursor Cursor from previous batch (null for first batch)
176
+ * @param limit Maximum documents to fetch (default: 500)
177
+ */
178
+ fetchBatch(cursor?: string | null, limit?: number): Promise<FetchBatchResult> {
179
+ return this.post("/internal/fetch-batch", {
180
+ payload: { cursor, limit },
181
+ });
182
+ }
183
+
184
+ /**
185
+ * Fetch and index a batch of documents (server-side)
186
+ * Uses cursor-based pagination for reliability
187
+ *
188
+ * @param cursor Cursor from previous batch (null for first batch)
189
+ * @param limit Maximum documents to process (default: 500)
190
+ * @param targetIndex Optional explicit index name for zero-downtime reindexing
191
+ * @param since Only index docs with updated_at >= this ISO timestamp (for catch-up after reindex)
192
+ */
193
+ indexBatch(cursor?: string | null, limit?: number, targetIndex?: string, since?: string): Promise<IndexBatchResult> {
194
+ return this.post("/internal/index-batch", {
195
+ payload: { cursor, limit, targetIndex, since },
196
+ });
197
+ }
198
+
199
+ /**
200
+ * Trigger a reindex operation via Temporal workflow (internal version with more options)
201
+ *
202
+ * @param fullReindex If true, reindexes all documents in the project
203
+ * @param objectIds Specific object IDs to reindex (if not fullReindex)
204
+ * @param recreateIndex If true, recreates the index before reindexing
205
+ */
206
+ triggerReindex(options?: {
207
+ fullReindex?: boolean;
208
+ objectIds?: string[];
209
+ recreateIndex?: boolean;
210
+ }): Promise<TriggerReindexResult> {
211
+ return this.post("/internal/trigger-reindex", {
212
+ payload: options ?? {},
213
+ });
214
+ }
215
+
216
+ /**
217
+ * Fetch documents by their IDs from MongoDB (for retry workflow)
218
+ * Returns documents ready for bulk indexing
219
+ *
220
+ * @param objectIds Array of object IDs to fetch
221
+ */
222
+ fetchDocumentsByIds(objectIds: string[]): Promise<FetchDocumentsByIdsResult> {
223
+ return this.post("/internal/fetch-by-ids", {
224
+ payload: { objectIds },
225
+ });
226
+ }
227
+
228
+ /**
229
+ * Bulk delete documents from Elasticsearch
230
+ *
231
+ * @param objectIds Array of object IDs to delete
232
+ */
233
+ bulkDelete(objectIds: string[]): Promise<BulkDeleteResult> {
234
+ return this.post("/internal/bulk-delete", {
235
+ payload: { objectIds },
236
+ });
237
+ }
238
+
239
+ /**
240
+ * Get detailed index configuration for the project
241
+ *
242
+ * Returns comprehensive information about the Elasticsearch index including
243
+ * status, embedding dimensions, field mappings, and project configuration.
244
+ */
245
+ getConfiguration(): Promise<IndexConfiguration> {
246
+ return this.post("/internal/configuration", {
247
+ payload: {},
248
+ });
249
+ }
250
+ }
@@ -1,10 +1,10 @@
1
1
  import { ApiTopic, ClientBase } from "@vertesia/api-fetch-client";
2
2
  import {
3
3
  canGenerateRendition,
4
- ContentObjectApiHeaders,
5
4
  ComplexSearchPayload,
6
5
  ComputeObjectFacetPayload,
7
6
  ContentObject,
7
+ ContentObjectApiHeaders,
8
8
  ContentObjectItem,
9
9
  ContentObjectProcessingPriority,
10
10
  ContentSource,
@@ -23,7 +23,7 @@ import {
23
23
  ObjectSearchPayload,
24
24
  ObjectSearchQuery,
25
25
  SupportedEmbeddingTypes,
26
- supportsVisualRendition,
26
+ supportsVisualRendition
27
27
  } from "@vertesia/common";
28
28
 
29
29
  // Re-export rendition utilities for consumers
@@ -151,6 +151,7 @@ export class ObjectsApi extends ApiTopic {
151
151
  name: source.name,
152
152
  mime_type: source.type,
153
153
  });
154
+ const sourceMimeType = source.type || mime_type;
154
155
 
155
156
  // upload the file content to the signed URL
156
157
  /*const res = await this.fetch(url, {
@@ -175,9 +176,7 @@ export class ObjectsApi extends ApiTopic {
175
176
  body: isStream ? source.stream : source,
176
177
  //@ts-ignore: duplex is not in the types. See https://github.com/node-fetch/node-fetch/issues/1769
177
178
  duplex: isStream ? "half" : undefined,
178
- headers: {
179
- "Content-Type": mime_type || "application/octet-stream",
180
- },
179
+ headers: sourceMimeType ? { "Content-Type": sourceMimeType } : undefined,
181
180
  })
182
181
  .then((res: Response) => {
183
182
  if (res.ok) {
@@ -201,7 +200,7 @@ export class ObjectsApi extends ApiTopic {
201
200
  return {
202
201
  source: id,
203
202
  name: source.name,
204
- type: mime_type,
203
+ type: sourceMimeType,
205
204
  etag,
206
205
  };
207
206
  }
@@ -226,7 +225,7 @@ export class ObjectsApi extends ApiTopic {
226
225
  const headers: Record<string, string> = {};
227
226
  if (options?.processing_priority) {
228
227
  headers[ContentObjectApiHeaders.PROCESSING_PRIORITY] = options.processing_priority;
229
- }
228
+ }
230
229
  if (options?.collection_id) {
231
230
  headers[ContentObjectApiHeaders.COLLECTION_ID] = options.collection_id;
232
231
  }
@@ -270,7 +269,7 @@ export class ObjectsApi extends ApiTopic {
270
269
  const headers: Record<string, string> = {};
271
270
  if (options?.processing_priority) {
272
271
  headers[ContentObjectApiHeaders.PROCESSING_PRIORITY] = options.processing_priority;
273
- }
272
+ }
274
273
  if (options?.collection_id) {
275
274
  headers[ContentObjectApiHeaders.COLLECTION_ID] = options.collection_id;
276
275
  }
@@ -301,6 +300,8 @@ export class ObjectsApi extends ApiTopic {
301
300
  revisionLabel?: string;
302
301
  processing_priority?: ContentObjectProcessingPriority;
303
302
  suppressWorkflows?: boolean;
303
+ /** If provided, the server will reject the update with 412 if the document's content etag no longer matches. */
304
+ ifMatch?: string;
304
305
  },
305
306
  ): Promise<ContentObject> {
306
307
  const updatePayload: Partial<CreateContentObjectPayload> = {
@@ -316,6 +317,9 @@ export class ObjectsApi extends ApiTopic {
316
317
  }
317
318
 
318
319
  const headers: Record<string, string> = {};
320
+ if (options?.ifMatch) {
321
+ headers['if-match'] = options.ifMatch;
322
+ }
319
323
  if (options?.processing_priority) {
320
324
  headers[ContentObjectApiHeaders.PROCESSING_PRIORITY] = options.processing_priority;
321
325
  }
@@ -0,0 +1,110 @@
1
+ import { ApiTopic, ClientBase } from "@vertesia/api-fetch-client";
2
+
3
+ /**
4
+ * Query payload for agent data access
5
+ */
6
+ export interface QueryPayload {
7
+ /** SQL query (uses ES SQL API) */
8
+ sql?: string;
9
+ /** ES|QL query (Elastic's piped query language) */
10
+ esql?: string;
11
+ /** Raw DSL query for full control */
12
+ dsl?: {
13
+ query?: Record<string, unknown>;
14
+ aggs?: Record<string, unknown>;
15
+ size?: number;
16
+ from?: number;
17
+ sort?: Array<Record<string, unknown>>;
18
+ };
19
+ /** Output format */
20
+ format?: 'json' | 'csv' | 'table';
21
+ }
22
+
23
+ /**
24
+ * Query result
25
+ */
26
+ export interface QueryResult {
27
+ /** Result type */
28
+ type: 'sql' | 'esql' | 'dsl';
29
+ /** Column definitions */
30
+ columns?: Array<{ name: string; type: string }>;
31
+ /** Rows for SQL/ES|QL */
32
+ rows?: unknown[][];
33
+ /** Hits for DSL */
34
+ hits?: Array<{ id: string; score: number; source: unknown }>;
35
+ /** Total count */
36
+ total?: number;
37
+ /** Aggregations for DSL */
38
+ aggregations?: Record<string, unknown>;
39
+ /** Cursor for pagination (SQL) */
40
+ cursor?: string;
41
+ /** Query execution time in ms */
42
+ took?: number;
43
+ }
44
+
45
+ /**
46
+ * API for querying documents using SQL, ES|QL, or raw Elasticsearch DSL.
47
+ * All queries are automatically filtered based on the authenticated user's permissions.
48
+ */
49
+ export class QueryApi extends ApiTopic {
50
+
51
+ constructor(parent: ClientBase, basePath: string = "/api/v1/query") {
52
+ super(parent, basePath);
53
+ }
54
+
55
+ /**
56
+ * Execute a query against the project's document index
57
+ *
58
+ * @param payload - Query payload with sql, esql, or dsl
59
+ * @returns Query result with columns/rows or hits/aggregations
60
+ *
61
+ * @example SQL query
62
+ * ```typescript
63
+ * const result = await client.query.execute({
64
+ * sql: "SELECT name, status FROM content WHERE status = 'published' LIMIT 10"
65
+ * });
66
+ * ```
67
+ *
68
+ * @example ES|QL query
69
+ * ```typescript
70
+ * const result = await client.query.execute({
71
+ * esql: "FROM content | WHERE status == 'published' | STATS count = COUNT(*) BY type.name"
72
+ * });
73
+ * ```
74
+ *
75
+ * @example DSL query with aggregations
76
+ * ```typescript
77
+ * const result = await client.query.execute({
78
+ * dsl: {
79
+ * query: { match: { text: "machine learning" } },
80
+ * aggs: { by_type: { terms: { field: "type.name" } } },
81
+ * size: 10
82
+ * }
83
+ * });
84
+ * ```
85
+ */
86
+ async execute(payload: QueryPayload): Promise<QueryResult> {
87
+ return this.post("/", { payload });
88
+ }
89
+
90
+ /**
91
+ * Execute a SQL query
92
+ */
93
+ async sql(query: string): Promise<QueryResult> {
94
+ return this.execute({ sql: query });
95
+ }
96
+
97
+ /**
98
+ * Execute an ES|QL query
99
+ */
100
+ async esql(query: string): Promise<QueryResult> {
101
+ return this.execute({ esql: query });
102
+ }
103
+
104
+ /**
105
+ * Execute a DSL query
106
+ */
107
+ async dsl(query: QueryPayload['dsl']): Promise<QueryResult> {
108
+ return this.execute({ dsl: query });
109
+ }
110
+ }