@axiom-lattice/gateway 2.1.24 → 2.1.26

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": "@axiom-lattice/gateway",
3
- "version": "2.1.24",
3
+ "version": "2.1.26",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",
@@ -36,9 +36,9 @@
36
36
  "pino-roll": "^3.1.0",
37
37
  "redis": "^5.0.1",
38
38
  "uuid": "^9.0.1",
39
- "@axiom-lattice/core": "2.1.19",
40
- "@axiom-lattice/protocols": "2.1.11",
41
- "@axiom-lattice/queue-redis": "1.0.10"
39
+ "@axiom-lattice/core": "2.1.21",
40
+ "@axiom-lattice/queue-redis": "1.0.11",
41
+ "@axiom-lattice/protocols": "2.1.12"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/jest": "^29.5.14",
@@ -6,7 +6,7 @@ import type {
6
6
  CreateAssistantRequest,
7
7
  } from "@axiom-lattice/protocols";
8
8
  import { randomUUID } from "crypto";
9
- import { AgentConfig, getAllAgentConfigs } from "@axiom-lattice/core";
9
+ import { AgentConfig, getAllAgentConfigs, eventBus } from "@axiom-lattice/core";
10
10
 
11
11
  /**
12
12
  * Assistant Controller
@@ -142,48 +142,78 @@ export async function getAssistant(
142
142
  };
143
143
  }
144
144
 
145
+ /**
146
+ * Upsert assistant - create if not exists in store, update if exists
147
+ */
148
+ async function upsertAssistant(
149
+ id: string,
150
+ data: CreateAssistantRequest | AssistantUpdateBody,
151
+ reply: FastifyReply,
152
+ requireFields: boolean = false
153
+ ): Promise<AssistantResponse> {
154
+ const storeLattice = getStoreLattice("default", "assistant");
155
+ const assistantStore = storeLattice.store;
156
+
157
+ const exists = await assistantStore.hasAssistant(id);
158
+
159
+ let assistant: Assistant | null;
160
+ if (exists) {
161
+ assistant = await assistantStore.updateAssistant(id, data);
162
+ if (!assistant) {
163
+ return reply.status(500).send({
164
+ success: false,
165
+ message: "Failed to update assistant",
166
+ });
167
+ }
168
+ eventBus.publish("assistant:updated", { id: assistant.id, name: assistant.name });
169
+ return {
170
+ success: true,
171
+ message: "Updated assistant",
172
+ data: assistant,
173
+ };
174
+ }
175
+
176
+ if (requireFields) {
177
+ const createData = data as CreateAssistantRequest;
178
+ if (!createData.name || !createData.graphDefinition) {
179
+ return reply.status(400).send({
180
+ success: false,
181
+ message: "name and graphDefinition are required",
182
+ });
183
+ }
184
+ }
185
+
186
+ assistant = await assistantStore.createAssistant(id, data as CreateAssistantRequest);
187
+ eventBus.publish("assistant:created", { id: assistant.id, name: assistant.name });
188
+ return reply.status(201).send({
189
+ success: true,
190
+ message: "Created assistant",
191
+ data: assistant,
192
+ });
193
+ }
194
+
145
195
  /**
146
196
  * Create a new assistant
147
197
  */
148
198
  export async function createAssistant(
149
- request: FastifyRequest<{ Body: CreateAssistantRequest }>,
199
+ request: FastifyRequest<{ Body: CreateAssistantRequest & { id?: string } }>,
150
200
  reply: FastifyReply
151
201
  ): Promise<AssistantResponse> {
152
202
  const data = request.body;
153
203
 
154
- // Validate required fields
155
- if (!data.name) {
204
+ if (!data.name || !data.graphDefinition) {
156
205
  return reply.status(400).send({
157
206
  success: false,
158
- message: "name is required",
207
+ message: "name and graphDefinition are required",
159
208
  });
160
209
  }
161
210
 
162
- if (!data.graphDefinition) {
163
- return reply.status(400).send({
164
- success: false,
165
- message: "graphDefinition is required",
166
- });
167
- }
168
-
169
- // Generate ID if not provided
170
- const id = randomUUID();
171
-
172
- // Create assistant
173
- const storeLattice = getStoreLattice("default", "assistant");
174
- const assistantStore = storeLattice.store;
175
- const newAssistant = await assistantStore.createAssistant(id, data);
176
-
177
- return reply.status(201).send({
178
- success: true,
179
- message: "Successfully created assistant",
180
- data: newAssistant,
181
- });
211
+ const id = data.id ?? randomUUID();
212
+ return upsertAssistant(id, data, reply, true);
182
213
  }
183
214
 
184
215
  /**
185
216
  * Update an existing assistant by ID
186
- * Only works on stored assistants, not code-configured ones
187
217
  */
188
218
  export async function updateAssistant(
189
219
  request: FastifyRequest<{
@@ -195,50 +225,13 @@ export async function updateAssistant(
195
225
  const { id } = request.params;
196
226
  const updates = request.body;
197
227
 
198
- // Check if it's a code-configured agent
199
- const agentConfigs = await getAllAgentConfigs();
200
- const isCodeConfigured = agentConfigs.some((config) => config.key === id);
201
-
202
- if (isCodeConfigured) {
203
- return reply.status(403).send({
204
- success: false,
205
- message:
206
- "Cannot update code-configured assistant. Only stored assistants can be updated.",
207
- });
208
- }
209
-
210
- const storeLattice = getStoreLattice("default", "assistant");
211
- const assistantStore = storeLattice.store;
212
-
213
- // Check if assistant exists in store
214
- const exists = await assistantStore.hasAssistant(id);
215
- if (!exists) {
216
- return reply.status(404).send({
217
- success: false,
218
- message: "Assistant not found",
219
- });
220
- }
221
-
222
- // Update assistant
223
- const updatedAssistant = await assistantStore.updateAssistant(id, updates);
224
-
225
- if (!updatedAssistant) {
226
- return reply.status(500).send({
227
- success: false,
228
- message: "Failed to update assistant",
229
- });
230
- }
231
-
232
- return {
233
- success: true,
234
- message: "Successfully updated assistant",
235
- data: updatedAssistant,
236
- };
228
+ return upsertAssistant(id, updates, reply, false);
237
229
  }
238
230
 
239
231
  /**
240
232
  * Delete an assistant by ID
241
- * Only works on stored assistants, not code-configured ones
233
+ * For stored assistants: deletes from store
234
+ * For code-configured assistants: only deletes from store if exists (code registration remains)
242
235
  */
243
236
  export async function deleteAssistant(
244
237
  request: FastifyRequest<{ Params: { id: string } }>,
@@ -246,22 +239,28 @@ export async function deleteAssistant(
246
239
  ): Promise<{ success: boolean; message: string }> {
247
240
  const { id } = request.params;
248
241
 
249
- // Check if it's a code-configured agent
242
+ const storeLattice = getStoreLattice("default", "assistant");
243
+ const assistantStore = storeLattice.store;
244
+
250
245
  const agentConfigs = await getAllAgentConfigs();
251
246
  const isCodeConfigured = agentConfigs.some((config) => config.key === id);
252
247
 
253
248
  if (isCodeConfigured) {
254
- return reply.status(403).send({
255
- success: false,
256
- message:
257
- "Cannot delete code-configured assistant. Only stored assistants can be deleted.",
258
- });
249
+ const exists = await assistantStore.hasAssistant(id);
250
+ if (!exists) {
251
+ return reply.status(404).send({
252
+ success: false,
253
+ message: "Assistant not found (code-configured assistants cannot be deleted from code, only from store)",
254
+ });
255
+ }
256
+ await assistantStore.deleteAssistant(id);
257
+ eventBus.publish("assistant:deleted", { id });
258
+ return {
259
+ success: true,
260
+ message: "Deleted assistant from store (code-configured registration remains)",
261
+ };
259
262
  }
260
263
 
261
- const storeLattice = getStoreLattice("default", "assistant");
262
- const assistantStore = storeLattice.store;
263
-
264
- // Check if assistant exists in store
265
264
  const exists = await assistantStore.hasAssistant(id);
266
265
  if (!exists) {
267
266
  return reply.status(404).send({
@@ -270,7 +269,6 @@ export async function deleteAssistant(
270
269
  });
271
270
  }
272
271
 
273
- // Delete the assistant
274
272
  const deleted = await assistantStore.deleteAssistant(id);
275
273
 
276
274
  if (!deleted) {
@@ -280,6 +278,8 @@ export async function deleteAssistant(
280
278
  });
281
279
  }
282
280
 
281
+ eventBus.publish("assistant:deleted", { id });
282
+
283
283
  return {
284
284
  success: true,
285
285
  message: "Successfully deleted assistant",
@@ -54,12 +54,11 @@ export function registerSandboxProxyRoutes(app: FastifyInstance): void {
54
54
  console.log("[Sandbox Upload] Route matched:", request.url);
55
55
  const { assistantId, threadId } = request.params;
56
56
 
57
- const sandboxConfig = sandboxService.getSandboxConfig(assistantId);
58
- if (!sandboxConfig) {
57
+ const isolatedLevel = sandboxService.getFilesystemIsolatedLevel(assistantId);
58
+ if (!isolatedLevel) {
59
59
  return reply.status(500).send({ error: "Assistant sandbox config not found" });
60
60
  }
61
61
 
62
- const { isolatedLevel } = sandboxConfig;
63
62
  const sandboxName = sandboxService.computeSandboxName(
64
63
  assistantId,
65
64
  threadId,
@@ -122,12 +121,11 @@ export function registerSandboxProxyRoutes(app: FastifyInstance): void {
122
121
  return reply.status(400).send({ error: "Query parameter 'path' is required" });
123
122
  }
124
123
 
125
- const sandboxConfig = sandboxService.getSandboxConfig(assistantId);
126
- if (!sandboxConfig) {
127
- return reply.status(404).send({ error: "Assistant sandbox config not found" });
124
+ const isolatedLevel = sandboxService.getFilesystemIsolatedLevel(assistantId);
125
+ if (!isolatedLevel) {
126
+ return reply.status(500).send({ error: "Assistant filesystem isolated level not found" });
128
127
  }
129
128
 
130
- const { isolatedLevel } = sandboxConfig;
131
129
  const sandboxName = sandboxService.computeSandboxName(
132
130
  assistantId,
133
131
  threadId,
@@ -1,5 +1,5 @@
1
1
  import { getAgentConfig, getAgentLattice, getSandBoxManager, normalizeSandboxName, sandboxLatticeManager } from "@axiom-lattice/core";
2
- import { ConnectedSandboxConfig } from "@axiom-lattice/protocols";
2
+ import { ConnectedSandboxConfig, SandboxMiddlewareConfig } from "@axiom-lattice/protocols";
3
3
 
4
4
 
5
5
  const ERROR_HTML = `<!DOCTYPE html>
@@ -114,14 +114,19 @@ const ERROR_HTML = `<!DOCTYPE html>
114
114
 
115
115
  export class SandboxService {
116
116
 
117
- getSandboxConfig(assistantId: string): ConnectedSandboxConfig | null {
117
+ getFilesystemIsolatedLevel(assistantId: string): "agent" | "thread" | "global" | null {
118
118
  const agentConfig = getAgentConfig(assistantId);
119
119
  if (!agentConfig) {
120
120
  return null;
121
121
  }
122
122
 
123
123
  const agentLattice = getAgentLattice(assistantId);
124
- return agentLattice?.config?.connectedSandbox || null;
124
+ const filesystemConfig = agentLattice?.config?.middleware?.find(m => m.type === "filesystem");
125
+ if (!filesystemConfig) {
126
+ return null;
127
+ }
128
+
129
+ return filesystemConfig.config?.isolatedLevel || null;
125
130
  }
126
131
 
127
132
  computeSandboxName(