@burdenoff/microfe-vibecontrols 2026.713.1 → 2026.714.1

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.
@@ -1,267 +1,53 @@
1
- import { CheckAiCreditsDocument as e, CreateSandboxDocument as t, ExtendSandboxTtlDocument as n, GetActiveSandboxesDocument as r, GetSandboxDocument as i, ProxySandboxRequestDocument as a, ReportAiTokenUsageDocument as o } from "../generated/wspace-operations.js";
2
- import { print as s } from "graphql";
1
+ import { checkAssistantAiCredits as e, createAssistantSandbox as t, createAssistantSession as n, downloadAssistantArtifact as r, extendAssistantSandboxTTL as i, findExistingSandbox as a, getAssistantArtifacts as o, getAssistantMessages as s, getAssistantSession as c, reportAssistantAiTokenUsage as l, sendAssistantPromptAsync as u, sendHeartbeat as d, waitForAssistantServiceReady as f, waitForSandboxRunning as p } from "@burdenoff/fe-libs/shared/assistant";
3
2
  //#region src/services/assistantApi.ts
4
- var c = "burdenoffregistry.azurecr.io", l = "alpha-proxy-auth-v1", u = "alpha-proxy-auth-v1", d = "alpha-delegated-auth-v11", f = "sandbox-app-client-headers-v1";
5
- function p(e) {
6
- switch (e) {
7
- case "general": return l;
8
- case "vibe-plugins": return u;
9
- case "assistant":
10
- case "api-calls": return d;
11
- }
3
+ var m = "vibecontrols", h = 600;
4
+ function g() {
5
+ return !1;
12
6
  }
13
- function m(e) {
14
- return `${c}/wspace/ai-assistant-${e === "assistant" ? "api-calls" : e}:${p(e)}`;
7
+ var _ = (e) => e ?? {};
8
+ function v(e, t, n, r) {
9
+ return a(t, n, g(), _(r));
15
10
  }
16
- function h(e) {
17
- switch (e) {
18
- case "general": return {
19
- cpuRequest: "100m",
20
- cpuLimit: "500m",
21
- memoryRequest: "256Mi",
22
- memoryLimit: "1Gi"
23
- };
24
- case "vibe-plugins": return {
25
- cpuRequest: "150m",
26
- cpuLimit: "750m",
27
- memoryRequest: "384Mi",
28
- memoryLimit: "1536Mi"
29
- };
30
- case "assistant":
31
- case "api-calls": return {
32
- cpuRequest: "150m",
33
- cpuLimit: "750m",
34
- memoryRequest: "384Mi",
35
- memoryLimit: "1536Mi"
36
- };
37
- }
11
+ function y(e, n, r, i) {
12
+ return t(m, n, r, g(), h, _(i));
38
13
  }
39
- function g(e) {
40
- let t = e.metadata?.assistantMode;
41
- if (t === "assistant" || t === "general" || t === "api-calls" || t === "vibe-plugins") return t;
42
- let n = e.name ?? "";
43
- return n.startsWith("ai-assistant-vibe-plugins-") ? "vibe-plugins" : n.startsWith("ai-assistant-api-calls-") ? "api-calls" : n.startsWith("ai-assistant-general-") ? "general" : n.startsWith("ai-assistant-assistant-") ? "assistant" : null;
14
+ function b(e, t, n, r, i = 3e5, a) {
15
+ return p(t, n, _(r), i);
44
16
  }
45
- function _(e, t) {
46
- let n = {};
47
- return t?.accessToken && (n.authorization = `Bearer ${t.accessToken}`), t?.workspaceToken && (n["x-workspace-authorization"] = `Bearer ${t.workspaceToken}`), e && (n["x-workspace-id"] = e), t?.userId && (n["x-actor-id"] = t.userId, n["x-actor-type"] = "user"), t?.organizationId && (n["x-org-id"] = t.organizationId), Object.keys(n).length > 0 ? { headers: n } : void 0;
17
+ function x(e, t, n, r, i = 9e4, a) {
18
+ return f(t, n, _(r), i);
48
19
  }
49
- function v(e, t) {
50
- return {
51
- workspaceId: e,
52
- ...t?.organizationId ? { custom: { organizationId: t.organizationId } } : {}
53
- };
20
+ function S(e, t, r, i, a) {
21
+ return n(t, r, i, _(a));
54
22
  }
55
- async function y(e) {
56
- let t = await fetch("/workspaces/graphql", {
57
- method: "POST",
58
- headers: {
59
- "Content-Type": "application/json",
60
- ..._(e.workspaceId, e.authContext)?.headers ?? {}
61
- },
62
- body: JSON.stringify({
63
- query: s(e.document),
64
- variables: e.variables
65
- })
66
- }), n = await t.json().catch(() => null);
67
- if (!t.ok) {
68
- let e = n?.errors?.map((e) => e.message).join(", "), r = Error(e || `Sandbox GraphQL HTTP ${t.status}`);
69
- throw r.statusCode = t.status, r.result = n ?? void 0, r;
70
- }
71
- if (!n) throw Error("Sandbox GraphQL returned empty response");
72
- if (n.errors?.length) throw Error(n.errors.map((e) => e.message).join(", "));
73
- if (!n.data) throw Error("Sandbox GraphQL returned no data");
74
- return n.data;
23
+ function C(e, t, n, r, i) {
24
+ return c(t, n, r, _(i));
75
25
  }
76
- async function b(e, t, n, i) {
77
- return ((await y({
78
- document: r,
79
- variables: { context: v(t, i) },
80
- workspaceId: t,
81
- authContext: i
82
- })).getActiveSandboxes ?? []).find((e) => (e.status === "RUNNING" || e.status === "PROVISIONING" || e.status === "PENDING") && e.template === "AI_BUILDER" && g(e) === n && (!i?.userId || e.createdBy === i.userId) && e.metadata?.authStrategy === f && e.metadata?.imageTag === p(n))?.id ?? null;
26
+ function w(e, t, n, r, i, a, o, s) {
27
+ return u(t, n, r, i, a, o, _(s));
83
28
  }
84
- async function x(e, n, r, i) {
85
- let a = h(n), o = [
86
- {
87
- name: "AI_ASSISTANT_MODE",
88
- value: n
89
- },
90
- {
91
- name: "HOSTNAME",
92
- value: "0.0.0.0"
93
- },
94
- {
95
- name: "WORKSPACE_ID",
96
- value: r
97
- },
98
- {
99
- name: "AI_ASSISTANT_PRODUCT",
100
- value: "vibecontrols"
101
- }
102
- ], s = await y({
103
- document: t,
104
- variables: { input: {
105
- name: `ai-assistant-${n}-${Date.now()}`,
106
- description: `AI Assistant sandbox (${n} mode)`,
107
- template: "AI_BUILDER",
108
- mode: "DEPLOYMENT",
109
- containers: [{
110
- name: "ai-assistant",
111
- image: m(n),
112
- ports: [{
113
- containerPort: 8080,
114
- name: "http"
115
- }],
116
- env: o
117
- }],
118
- resources: {
119
- cpuRequest: a.cpuRequest,
120
- cpuLimit: a.cpuLimit,
121
- memoryRequest: a.memoryRequest,
122
- memoryLimit: a.memoryLimit
123
- },
124
- ttlSeconds: 600,
125
- metadata: {
126
- assistantMode: n,
127
- assistantOwnerUserId: i?.userId ?? null,
128
- assistantOrganizationId: i?.organizationId ?? null,
129
- authStrategy: f,
130
- imageTag: p(n)
131
- },
132
- context: v(r, i)
133
- } },
134
- workspaceId: r,
135
- authContext: i
136
- });
137
- if (!s?.createSandbox?.id) throw Error("createSandbox returned empty response");
138
- return s.createSandbox.id;
29
+ function T(e, t, n, r, i, a = 50) {
30
+ return s(t, n, r, _(i), { limit: a });
139
31
  }
140
- async function S(e, t, n, r, a = 3e5, o) {
141
- let s = Date.now();
142
- for (; Date.now() - s < a;) {
143
- let e = await y({
144
- document: i,
145
- variables: {
146
- id: t,
147
- context: v(n, r)
148
- },
149
- workspaceId: n,
150
- authContext: r
151
- }), a = e?.getSandbox?.status, c = e?.getSandbox?.errorMessage;
152
- if (a === "RUNNING") return;
153
- if (a === "FAILED" || a === "STOPPED" || a === "EXPIRED") throw Error(c ? `Sandbox ${a.toLowerCase()}: ${c}` : `Sandbox ${a.toLowerCase()}`);
154
- let l = Math.max(1, Math.round((Date.now() - s) / 1e3));
155
- o?.(`Starting assistant environment... (${l}s)`), await new Promise((e) => setTimeout(e, 2e3));
156
- }
157
- throw Error("Sandbox startup timed out");
32
+ function E(t, n, r) {
33
+ return e(n, _(r));
158
34
  }
159
- async function C(e, t, n, r, i, o, s) {
160
- let c = (await y({
161
- document: a,
162
- variables: { input: {
163
- sandboxId: t,
164
- path: r,
165
- method: i,
166
- body: o,
167
- context: v(n, s)
168
- } },
169
- workspaceId: n,
170
- authContext: s
171
- })).proxySandboxRequest;
172
- if (!c || c.status >= 400) {
173
- let e = c?.body;
174
- throw Error(e?.error ?? `Proxy error: ${c?.status ?? "unknown"}`);
175
- }
176
- return c.body;
35
+ function D(e, t, n, r, i, a, o) {
36
+ return l(t, n, r, i, a, _(o));
177
37
  }
178
- async function w(e, t, n, r, i = 9e4, a) {
179
- let o = Date.now();
180
- for (; Date.now() - o < i;) {
181
- try {
182
- await C(e, t, n, "/health", "GET", void 0, r);
183
- return;
184
- } catch (e) {
185
- let t = e instanceof Error ? e.message : String(e);
186
- if (!/proxy error: 502|proxy error: 503|proxy error: 404|service not available/i.test(t)) throw e;
187
- }
188
- let i = Math.max(1, Math.round((Date.now() - o) / 1e3));
189
- a?.(`Connecting to assistant... (${i}s)`), await new Promise((e) => setTimeout(e, 2e3));
190
- }
191
- throw Error("Assistant service did not become healthy before timeout");
38
+ function O(e, t, n, r, i) {
39
+ return o(t, n, r, _(i)).then((e) => e);
192
40
  }
193
- async function T(e, t, n, r, i) {
194
- return { sessionId: (await C(e, t, n, "/sessions", "POST", { mode: r }, i)).session.id };
41
+ function k(e, t, n, i, a, o) {
42
+ return r(t, n, i, a, _(o));
195
43
  }
196
- async function E(e, t, n, r, i) {
197
- let a = await C(e, t, n, `/sessions/${r}`, "GET", void 0, i);
198
- return {
199
- id: a.session?.id ?? r,
200
- mode: a.mode ?? "unknown"
201
- };
44
+ function A(e, t, n, r, i) {
45
+ return d(t, n, r, _(i));
202
46
  }
203
- async function D(e, t, n, r, i, a, o, s) {
204
- let c = {
205
- mode: a,
206
- prompt: i,
207
- pageContext: o ?? void 0
208
- };
209
- await C(e, t, n, `/sessions/${r}/prompt-async`, "POST", c, s);
210
- }
211
- async function O(e, t, n, r, i, a = 50) {
212
- return (await C(e, t, n, `/sessions/${r}/messages?limit=${a}`, "GET", void 0, i)).messages ?? [];
213
- }
214
- async function k(t, n, r) {
215
- return (await y({
216
- document: e,
217
- variables: {},
218
- workspaceId: n,
219
- authContext: r
220
- })).checkAiCredits;
221
- }
222
- async function A(e, t, n, r, i, a, s) {
223
- let c = Math.max(0, Math.round(a.input ?? 0)), l = Math.max(0, Math.round(a.output ?? 0));
224
- c + l !== 0 && i && await y({
225
- document: o,
226
- variables: { input: {
227
- sessionId: n,
228
- messageId: r,
229
- model: i,
230
- inputTokens: c,
231
- outputTokens: l
232
- } },
233
- workspaceId: t,
234
- authContext: s
235
- });
236
- }
237
- async function j(e, t, n, r, i) {
238
- return ((await C(e, t, n, `/sessions/${r}/artifacts`, "GET", void 0, i)).artifacts ?? []).filter((e) => !e.name.startsWith("."));
239
- }
240
- async function M(e, t, n, r, i, a) {
241
- let o = (await C(e, t, n, `/sessions/${r}/artifacts/download?path=${encodeURIComponent(i)}`, "GET", void 0, a)).artifact;
242
- if (!o) throw Error("Artifact download returned an empty response");
243
- return {
244
- filename: o.filename,
245
- mimeType: o.mimeType,
246
- contentBase64: o.contentBase64
247
- };
248
- }
249
- async function N(e, t, n, r, i) {
250
- await C(e, t, n, `/sessions/${r}/heartbeat`, "POST", void 0, i);
251
- }
252
- async function P(e, t, r, i = 600, a) {
253
- await y({
254
- document: n,
255
- variables: {
256
- id: t,
257
- additionalSeconds: i,
258
- context: v(r, a)
259
- },
260
- workspaceId: r,
261
- authContext: a
262
- });
47
+ function j(e, t, n, r = 600, a) {
48
+ return i(t, n, r, _(a));
263
49
  }
264
50
  //#endregion
265
- export { k as checkAssistantAiCredits, x as createAssistantSandbox, T as createAssistantSession, M as downloadAssistantArtifact, P as extendAssistantSandboxTTL, b as findExistingSandbox, j as getAssistantArtifacts, O as getAssistantMessages, E as getAssistantSession, A as reportAssistantAiTokenUsage, D as sendAssistantPromptAsync, N as sendHeartbeat, w as waitForAssistantServiceReady, S as waitForSandboxReady };
51
+ export { E as checkAssistantAiCredits, y as createAssistantSandbox, S as createAssistantSession, k as downloadAssistantArtifact, j as extendAssistantSandboxTTL, v as findExistingSandbox, O as getAssistantArtifacts, T as getAssistantMessages, C as getAssistantSession, D as reportAssistantAiTokenUsage, w as sendAssistantPromptAsync, A as sendHeartbeat, x as waitForAssistantServiceReady, b as waitForSandboxReady };
266
52
 
267
53
  //# sourceMappingURL=assistantApi.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"assistantApi.js","names":[],"sources":["../../src/services/assistantApi.ts"],"sourcesContent":["/**\n * AI Assistant API service.\n *\n * All requests go through the wspace-public-gateway (GraphQL Federation):\n * Frontend → wspace-public-gateway → wspace-sandbox-svc → ai-assistant (K8s pod)\n *\n * Uses the host app's Apollo Client which already points to the gateway.\n */\n\nimport { type ApolloClient } from '@apollo/client';\nimport { print, type DocumentNode } from 'graphql';\nimport type { AssistantArtifact, AssistantMode } from '@/types/assistant';\nimport type { PageContext } from '@/utils/pageContext';\nimport {\n CreateSandboxDocument,\n GetSandboxDocument,\n GetActiveSandboxesDocument,\n ProxySandboxRequestDocument,\n ExtendSandboxTtlDocument,\n CheckAiCreditsDocument,\n ReportAiTokenUsageDocument,\n} from '@/generated/wspace-operations';\n\n// ── Image registry ─────────────────────────────────────────────────\n\nconst HARBOR_REGISTRY = 'burdenoffregistry.azurecr.io';\nconst DEFAULT_IMAGE_TAG = import.meta.env.VITE_APP_ENV === 'prod' ? 'prod' : 'alpha';\nconst GENERAL_IMAGE_TAG = import.meta.env.VITE_APP_ENV === 'prod' ? 'prod' : 'alpha-proxy-auth-v1';\nconst VIBE_PLUGINS_IMAGE_TAG =\n import.meta.env.VITE_APP_ENV === 'prod' ? 'prod' : 'alpha-proxy-auth-v1';\nconst API_CALLS_IMAGE_TAG =\n import.meta.env.VITE_APP_ENV === 'prod' ? 'prod' : 'alpha-delegated-auth-v11';\nconst ASSISTANT_API_AUTH_STRATEGY = 'sandbox-app-client-headers-v1';\n\nfunction getImageTagForMode(mode: AssistantMode): string {\n switch (mode) {\n case 'general':\n return GENERAL_IMAGE_TAG;\n case 'vibe-plugins':\n return VIBE_PLUGINS_IMAGE_TAG;\n // The combined default mode runs in the api-calls image (it can make calls).\n case 'assistant':\n case 'api-calls':\n return API_CALLS_IMAGE_TAG;\n }\n}\n\nfunction getImageForMode(mode: AssistantMode): string {\n // `assistant` reuses the api-calls image — one image, mode selected at runtime\n // via AI_ASSISTANT_MODE. So the image segment is api-calls for both.\n const imageMode = mode === 'assistant' ? 'api-calls' : mode;\n return `${HARBOR_REGISTRY}/wspace/ai-assistant-${imageMode}:${getImageTagForMode(mode)}`;\n}\n\nfunction getResourcesForMode(mode: AssistantMode): {\n cpuRequest: string;\n cpuLimit: string;\n memoryRequest: string;\n memoryLimit: string;\n} {\n switch (mode) {\n case 'general':\n return {\n cpuRequest: '100m',\n cpuLimit: '500m',\n memoryRequest: '256Mi',\n memoryLimit: '1Gi',\n };\n case 'vibe-plugins':\n return {\n cpuRequest: '150m',\n cpuLimit: '750m',\n memoryRequest: '384Mi',\n memoryLimit: '1536Mi',\n };\n case 'assistant':\n case 'api-calls':\n return {\n cpuRequest: '150m',\n cpuLimit: '750m',\n memoryRequest: '384Mi',\n memoryLimit: '1536Mi',\n };\n }\n}\n\nfunction resolveSandboxAssistantMode(sandbox: {\n metadata: Record<string, unknown> | null;\n name?: string | null;\n}): AssistantMode | null {\n const metadataMode = sandbox.metadata?.assistantMode;\n if (\n metadataMode === 'assistant' ||\n metadataMode === 'general' ||\n metadataMode === 'api-calls' ||\n metadataMode === 'vibe-plugins'\n ) {\n return metadataMode;\n }\n\n const name = sandbox.name ?? '';\n if (name.startsWith('ai-assistant-vibe-plugins-')) return 'vibe-plugins';\n if (name.startsWith('ai-assistant-api-calls-')) return 'api-calls';\n if (name.startsWith('ai-assistant-general-')) return 'general';\n if (name.startsWith('ai-assistant-assistant-')) return 'assistant';\n return null;\n}\n\n// ── GraphQL operations (colocated .graphql → generated DocumentNodes) ──\n\n// ── Types ───────────────────────────────────────────────────────────\n\nexport interface AssistantPromptResult {\n response: string;\n tokens?: { input: number; output: number };\n artifacts?: AssistantArtifact[];\n}\n\nexport interface AssistantRawMessagePart {\n type?: string;\n text?: string;\n tool?: string;\n state?: {\n status?: string;\n input?: unknown;\n output?: unknown;\n raw?: unknown;\n };\n}\n\nexport interface AssistantRawMessage {\n info?: {\n id?: string;\n role?: string;\n providerID?: string;\n modelID?: string;\n tokens?: { input: number; output: number };\n time?: {\n created?: number;\n completed?: number;\n };\n };\n parts?: AssistantRawMessagePart[];\n}\n\nexport interface AssistantSandboxAuthContext {\n accessToken?: string | null;\n workspaceToken?: string | null;\n userId?: string | null;\n organizationId?: string | null;\n}\n\nexport interface AssistantSessionInfo {\n id: string;\n mode: string;\n}\n\ninterface GraphQLResponse<TData> {\n data?: TData;\n errors?: Array<{ message: string }>;\n}\n\nexport interface DownloadedAssistantArtifact {\n filename: string;\n mimeType: string;\n contentBase64: string;\n}\n\ninterface ProxyResponse {\n proxySandboxRequest: {\n status: number;\n body: Record<string, unknown>;\n };\n}\n\nfunction getGatewayRequestContext(\n workspaceId: string,\n authContext?: AssistantSandboxAuthContext\n): { headers?: Record<string, string> } | undefined {\n const headers: Record<string, string> = {};\n\n if (authContext?.accessToken) {\n headers.authorization = `Bearer ${authContext.accessToken}`;\n }\n\n if (authContext?.workspaceToken) {\n headers['x-workspace-authorization'] = `Bearer ${authContext.workspaceToken}`;\n }\n\n if (workspaceId) {\n headers['x-workspace-id'] = workspaceId;\n }\n\n if (authContext?.userId) {\n headers['x-actor-id'] = authContext.userId;\n headers['x-actor-type'] = 'user';\n }\n\n if (authContext?.organizationId) {\n headers['x-org-id'] = authContext.organizationId;\n }\n\n return Object.keys(headers).length > 0 ? { headers } : undefined;\n}\n\nfunction buildSandboxContextInput(\n workspaceId: string,\n authContext?: AssistantSandboxAuthContext\n): Record<string, unknown> {\n return {\n workspaceId,\n ...(authContext?.organizationId\n ? {\n custom: {\n organizationId: authContext.organizationId,\n },\n }\n : {}),\n };\n}\n\nasync function executeSandboxGraphQL<TData>(params: {\n document: DocumentNode;\n variables: Record<string, unknown>;\n workspaceId: string;\n authContext?: AssistantSandboxAuthContext;\n}): Promise<TData> {\n const response = await fetch('/workspaces/graphql', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(getGatewayRequestContext(params.workspaceId, params.authContext)?.headers ?? {}),\n },\n body: JSON.stringify({\n query: print(params.document),\n variables: params.variables,\n }),\n });\n\n const result = (await response.json().catch(() => null)) as GraphQLResponse<TData> | null;\n\n if (!response.ok) {\n // Preserve the HTTP status and parsed body so quota detection works.\n // The wspace public gateway returns 429 + errors[].extensions.code =\n // QUOTA_EXHAUSTED for @usage limits (createSandbox, checkAiCredits, …);\n // a bare `HTTP 429` Error would be invisible to isQuotaExhaustedError.\n const messages = result?.errors?.map((error: { message: string }) => error.message).join(', ');\n const httpError = new Error(messages || `Sandbox GraphQL HTTP ${response.status}`) as Error & {\n statusCode?: number;\n result?: unknown;\n };\n httpError.statusCode = response.status;\n httpError.result = result ?? undefined;\n throw httpError;\n }\n\n if (!result) {\n throw new Error('Sandbox GraphQL returned empty response');\n }\n\n if (result.errors?.length) {\n throw new Error(result.errors.map((error: { message: string }) => error.message).join(', '));\n }\n\n if (!result.data) {\n throw new Error('Sandbox GraphQL returned no data');\n }\n\n return result.data;\n}\n\n// ── Find existing sandbox for a mode ───────────────────────────────\n\nexport async function findExistingSandbox(\n _apollo: ApolloClient,\n workspaceId: string,\n mode: AssistantMode,\n authContext?: AssistantSandboxAuthContext\n): Promise<string | null> {\n const data = await executeSandboxGraphQL<{\n getActiveSandboxes: Array<{\n id: string;\n name: string;\n status: string;\n metadata: Record<string, unknown> | null;\n template: string;\n createdBy: string;\n }>;\n }>({\n document: GetActiveSandboxesDocument,\n variables: { context: buildSandboxContextInput(workspaceId, authContext) },\n workspaceId,\n authContext,\n });\n const sandboxes = data.getActiveSandboxes ?? [];\n\n return (\n sandboxes.find(\n (s) =>\n (s.status === 'RUNNING' || s.status === 'PROVISIONING' || s.status === 'PENDING') &&\n s.template === 'AI_BUILDER' &&\n resolveSandboxAssistantMode(s) === mode &&\n (!authContext?.userId || s.createdBy === authContext.userId) &&\n s.metadata?.authStrategy === ASSISTANT_API_AUTH_STRATEGY &&\n s.metadata?.imageTag === getImageTagForMode(mode)\n )?.id ?? null\n );\n}\n\n// ── Sandbox lifecycle ──────────────────────────────────────────────\n\nexport async function createAssistantSandbox(\n _apollo: ApolloClient,\n mode: AssistantMode,\n workspaceId: string,\n authContext?: AssistantSandboxAuthContext\n): Promise<string> {\n const resources = getResourcesForMode(mode);\n const env = [\n { name: 'AI_ASSISTANT_MODE', value: mode },\n { name: 'HOSTNAME', value: '0.0.0.0' },\n { name: 'WORKSPACE_ID', value: workspaceId },\n // Product the user is in — drives the agent's dynamic per-product docs fetch\n // (the docs repo is `<product>-docs`). Not a secret. This package is the\n // VibeControls MFE, so the product is vibecontrols; other products' MFEs\n // pass their own id.\n { name: 'AI_ASSISTANT_PRODUCT', value: 'vibecontrols' },\n ];\n\n const data = await executeSandboxGraphQL<{ createSandbox: { id: string } }>({\n document: CreateSandboxDocument,\n variables: {\n input: {\n name: `ai-assistant-${mode}-${Date.now()}`,\n description: `AI Assistant sandbox (${mode} mode)`,\n template: 'AI_BUILDER',\n mode: 'DEPLOYMENT',\n containers: [\n {\n name: 'ai-assistant',\n image: getImageForMode(mode),\n // The agent (start-assistant.sh) binds :8080; the sandbox svc proxies\n // to this declared containerPort, so it MUST be 8080. Declaring 80\n // (the old value) made the proxy connect to a dead port → the sandbox\n // failed provisioning with \"Unable to connect. Is the computer able to\n // access the url?\".\n ports: [{ containerPort: 8080, name: 'http' }],\n env,\n },\n ],\n resources: {\n cpuRequest: resources.cpuRequest,\n cpuLimit: resources.cpuLimit,\n memoryRequest: resources.memoryRequest,\n memoryLimit: resources.memoryLimit,\n },\n ttlSeconds: 600,\n metadata: {\n assistantMode: mode,\n assistantOwnerUserId: authContext?.userId ?? null,\n assistantOrganizationId: authContext?.organizationId ?? null,\n authStrategy: ASSISTANT_API_AUTH_STRATEGY,\n imageTag: getImageTagForMode(mode),\n },\n context: buildSandboxContextInput(workspaceId, authContext),\n },\n },\n workspaceId,\n authContext,\n });\n\n if (!data?.createSandbox?.id) {\n throw new Error('createSandbox returned empty response');\n }\n return data.createSandbox.id;\n}\n\nexport async function waitForSandboxReady(\n _apollo: ApolloClient,\n sandboxId: string,\n workspaceId: string,\n authContext?: AssistantSandboxAuthContext,\n maxWaitMs = 300_000,\n onProgress?: (message: string) => void\n): Promise<void> {\n const start = Date.now();\n while (Date.now() - start < maxWaitMs) {\n const data = await executeSandboxGraphQL<{\n getSandbox: { status?: string; errorMessage?: string } | null;\n }>({\n document: GetSandboxDocument,\n variables: { id: sandboxId, context: buildSandboxContextInput(workspaceId, authContext) },\n workspaceId,\n authContext,\n });\n const status = data?.getSandbox?.status;\n const errorMessage = data?.getSandbox?.errorMessage as string | undefined;\n if (status === 'RUNNING') return;\n if (status === 'FAILED' || status === 'STOPPED' || status === 'EXPIRED') {\n throw new Error(\n errorMessage\n ? `Sandbox ${status.toLowerCase()}: ${errorMessage}`\n : `Sandbox ${status.toLowerCase()}`\n );\n }\n const elapsedSeconds = Math.max(1, Math.round((Date.now() - start) / 1000));\n onProgress?.(`Starting assistant environment... (${elapsedSeconds}s)`);\n await new Promise((r) => setTimeout(r, 2000));\n }\n throw new Error('Sandbox startup timed out');\n}\n\n// ── Proxy calls to ai-assistant (via gateway → sandbox-svc) ───────\n\nasync function proxyToSandbox(\n _apollo: ApolloClient,\n sandboxId: string,\n workspaceId: string,\n path: string,\n method: string,\n body?: unknown,\n authContext?: AssistantSandboxAuthContext\n): Promise<Record<string, unknown>> {\n const result = await executeSandboxGraphQL<ProxyResponse>({\n document: ProxySandboxRequestDocument,\n variables: {\n input: {\n sandboxId,\n path,\n method,\n body,\n context: buildSandboxContextInput(workspaceId, authContext),\n },\n },\n workspaceId,\n authContext,\n });\n\n const proxyResult = result.proxySandboxRequest;\n if (!proxyResult || proxyResult.status >= 400) {\n const errBody = proxyResult?.body as Record<string, unknown> | undefined;\n throw new Error(\n (errBody?.error as string) ?? `Proxy error: ${proxyResult?.status ?? 'unknown'}`\n );\n }\n\n return proxyResult.body;\n}\n\nexport async function waitForAssistantServiceReady(\n apollo: ApolloClient,\n sandboxId: string,\n workspaceId: string,\n authContext?: AssistantSandboxAuthContext,\n maxWaitMs = 90_000,\n onProgress?: (message: string) => void\n): Promise<void> {\n const startedAt = Date.now();\n\n while (Date.now() - startedAt < maxWaitMs) {\n try {\n await proxyToSandbox(\n apollo,\n sandboxId,\n workspaceId,\n '/health',\n 'GET',\n undefined,\n authContext\n );\n return;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (\n !/proxy error: 502|proxy error: 503|proxy error: 404|service not available/i.test(message)\n ) {\n throw error;\n }\n }\n\n const elapsedSeconds = Math.max(1, Math.round((Date.now() - startedAt) / 1000));\n onProgress?.(`Connecting to assistant... (${elapsedSeconds}s)`);\n\n await new Promise((resolve) => setTimeout(resolve, 2000));\n }\n\n throw new Error('Assistant service did not become healthy before timeout');\n}\n\n// ── Session management ─────────────────────────────────────────────\n\nexport async function createAssistantSession(\n apollo: ApolloClient,\n sandboxId: string,\n workspaceId: string,\n mode: AssistantMode,\n authContext?: AssistantSandboxAuthContext\n): Promise<{ sessionId: string }> {\n const body = await proxyToSandbox(\n apollo,\n sandboxId,\n workspaceId,\n '/sessions',\n 'POST',\n { mode },\n authContext\n );\n const session = body.session as Record<string, unknown>;\n return { sessionId: session.id as string };\n}\n\nexport async function getAssistantSession(\n apollo: ApolloClient,\n sandboxId: string,\n workspaceId: string,\n sessionId: string,\n authContext?: AssistantSandboxAuthContext\n): Promise<AssistantSessionInfo> {\n const body = await proxyToSandbox(\n apollo,\n sandboxId,\n workspaceId,\n `/sessions/${sessionId}`,\n 'GET',\n undefined,\n authContext\n );\n const session = body.session as Record<string, unknown> | undefined;\n\n return {\n id: (session?.id as string | undefined) ?? sessionId,\n mode: (body.mode as string | undefined) ?? 'unknown',\n };\n}\n\n// ── Send prompt ────────────────────────────────────────────────────\n\nexport async function sendAssistantPrompt(\n apollo: ApolloClient,\n sandboxId: string,\n workspaceId: string,\n sessionId: string,\n prompt: string,\n mode: AssistantMode,\n pageContext?: PageContext,\n authContext?: AssistantSandboxAuthContext\n): Promise<AssistantPromptResult> {\n const requestBody = {\n mode,\n prompt,\n pageContext: pageContext\n ? {\n // Keys must match the agent's allowed-context-key contract.\n currentUrl: pageContext.currentUrl,\n currentPage: pageContext.currentPage,\n entityType: pageContext.entityType,\n entityId: pageContext.entityId,\n platform: pageContext.platform,\n version: pageContext.version,\n viewportSize: pageContext.viewportSize,\n }\n : undefined,\n };\n\n const body = await proxyToSandbox(\n apollo,\n sandboxId,\n workspaceId,\n `/sessions/${sessionId}/prompt`,\n 'POST',\n requestBody,\n authContext\n );\n\n const message = body.message as Record<string, unknown> | undefined;\n const tokens = message?.tokens as { input: number; output: number } | undefined;\n\n return { response: body.text as string, tokens };\n}\n\nexport async function sendAssistantPromptAsync(\n apollo: ApolloClient,\n sandboxId: string,\n workspaceId: string,\n sessionId: string,\n prompt: string,\n mode: AssistantMode,\n pageContext?: PageContext,\n authContext?: AssistantSandboxAuthContext\n): Promise<void> {\n const requestBody = {\n mode,\n prompt,\n pageContext: pageContext ?? undefined,\n };\n\n await proxyToSandbox(\n apollo,\n sandboxId,\n workspaceId,\n `/sessions/${sessionId}/prompt-async`,\n 'POST',\n requestBody,\n authContext\n );\n}\n\nexport async function getAssistantMessages(\n apollo: ApolloClient,\n sandboxId: string,\n workspaceId: string,\n sessionId: string,\n authContext?: AssistantSandboxAuthContext,\n limit = 50\n): Promise<AssistantRawMessage[]> {\n const body = await proxyToSandbox(\n apollo,\n sandboxId,\n workspaceId,\n `/sessions/${sessionId}/messages?limit=${limit}`,\n 'GET',\n undefined,\n authContext\n );\n\n return (body.messages as AssistantRawMessage[] | undefined) ?? [];\n}\n\n// ── AI credits (per-token metering) ────────────────────────────────\n\n/**\n * Pre-flight AI-credit gate. Resolves to `true` when the caller still has\n * AI-credit budget; throws a quota error (HTTP 429 / QUOTA_EXHAUSTED, from\n * the wspace gateway's @usage check) when the monthly token budget is\n * depleted. Detect the rejection with `isQuotaExhaustedError()`.\n */\nexport async function checkAssistantAiCredits(\n _apollo: ApolloClient,\n workspaceId: string,\n authContext?: AssistantSandboxAuthContext\n): Promise<boolean> {\n const data = await executeSandboxGraphQL<{ checkAiCredits: boolean }>({\n document: CheckAiCreditsDocument,\n variables: {},\n workspaceId,\n authContext,\n });\n return data.checkAiCredits;\n}\n\n/**\n * Post-turn charge. Reports the turn's raw input/output token counts + the\n * model so the svc computes COST-WEIGHTED credits server-side and charges them\n * against `vibecontrols.ai.credits` (the amount is never sent from the client).\n * `messageId` makes the charge idempotent (retries don't double-charge).\n * No-ops when there are no tokens, or when the model is unknown (the charge\n * requires it). Best-effort — callers must not block the displayed answer on it.\n */\nexport async function reportAssistantAiTokenUsage(\n _apollo: ApolloClient,\n workspaceId: string,\n sessionId: string,\n messageId: string,\n model: string | undefined,\n tokens: { input: number; output: number },\n authContext?: AssistantSandboxAuthContext\n): Promise<void> {\n const inputTokens = Math.max(0, Math.round(tokens.input ?? 0));\n const outputTokens = Math.max(0, Math.round(tokens.output ?? 0));\n if (inputTokens + outputTokens === 0) return;\n // The svc requires a model to price the charge; skip rather than send a turn\n // that can't be priced (the meter under-counts that turn — acceptable).\n if (!model) return;\n\n await executeSandboxGraphQL<{ reportAiTokenUsage: boolean }>({\n document: ReportAiTokenUsageDocument,\n variables: {\n input: { sessionId, messageId, model, inputTokens, outputTokens },\n },\n workspaceId,\n authContext,\n });\n}\n\nexport async function getAssistantArtifacts(\n apollo: ApolloClient,\n sandboxId: string,\n workspaceId: string,\n sessionId: string,\n authContext?: AssistantSandboxAuthContext\n): Promise<AssistantArtifact[]> {\n const body = await proxyToSandbox(\n apollo,\n sandboxId,\n workspaceId,\n `/sessions/${sessionId}/artifacts`,\n 'GET',\n undefined,\n authContext\n );\n\n return ((body.artifacts as AssistantArtifact[] | undefined) ?? []).filter(\n (artifact) => !artifact.name.startsWith('.')\n );\n}\n\nexport async function downloadAssistantArtifact(\n apollo: ApolloClient,\n sandboxId: string,\n workspaceId: string,\n sessionId: string,\n artifactPath: string,\n authContext?: AssistantSandboxAuthContext\n): Promise<DownloadedAssistantArtifact> {\n const encodedPath = encodeURIComponent(artifactPath);\n const body = await proxyToSandbox(\n apollo,\n sandboxId,\n workspaceId,\n `/sessions/${sessionId}/artifacts/download?path=${encodedPath}`,\n 'GET',\n undefined,\n authContext\n );\n\n const artifact = body.artifact as Record<string, unknown> | undefined;\n if (!artifact) {\n throw new Error('Artifact download returned an empty response');\n }\n\n return {\n filename: artifact.filename as string,\n mimeType: artifact.mimeType as string,\n contentBase64: artifact.contentBase64 as string,\n };\n}\n\n// ── Heartbeat ───────────────────────────────────────────────────────\n\nexport async function sendHeartbeat(\n apollo: ApolloClient,\n sandboxId: string,\n workspaceId: string,\n sessionId: string,\n authContext?: AssistantSandboxAuthContext\n): Promise<void> {\n await proxyToSandbox(\n apollo,\n sandboxId,\n workspaceId,\n `/sessions/${sessionId}/heartbeat`,\n 'POST',\n undefined,\n authContext\n );\n}\n\nexport async function extendAssistantSandboxTTL(\n _apollo: ApolloClient,\n sandboxId: string,\n workspaceId: string,\n additionalSeconds = 600,\n authContext?: AssistantSandboxAuthContext\n): Promise<void> {\n await executeSandboxGraphQL<{ extendSandboxTTL: { id: string } }>({\n document: ExtendSandboxTtlDocument,\n variables: {\n id: sandboxId,\n additionalSeconds,\n context: buildSandboxContextInput(workspaceId, authContext),\n },\n workspaceId,\n authContext,\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"assistantApi.js","names":[],"sources":["../../src/services/assistantApi.ts"],"sourcesContent":["/**\n * AI Assistant API — thin adapter over @burdenoff/fe-libs/shared/assistant.\n *\n * The legacy slide-in panel (AssistantChatArea / AssistantMessageItem /\n * useAssistantHeartbeat) calls these with the historical (apollo-first)\n * signatures. The real implementation now lives once in fe-libs; this file only\n * maps the old signatures onto it, retiring ~775 lines of duplicated logic. The\n * `apollo` argument is vestigial (the shared layer uses graphqlFetch) and is\n * ignored; the product id + prod-runtime + TTL the shared functions need are\n * supplied here.\n */\n\nimport {\n findExistingSandbox as sharedFindExisting,\n createAssistantSandbox as sharedCreate,\n waitForSandboxRunning as sharedWaitRunning,\n waitForAssistantServiceReady as sharedWaitService,\n createAssistantSession as sharedCreateSession,\n getAssistantSession as sharedGetSession,\n sendAssistantPromptAsync as sharedSendAsync,\n getAssistantMessages as sharedGetMessages,\n extendAssistantSandboxTTL as sharedExtendTtl,\n sendHeartbeat as sharedHeartbeat,\n getAssistantArtifacts as sharedGetArtifacts,\n downloadAssistantArtifact as sharedDownloadArtifact,\n checkAssistantAiCredits as sharedCheckCredits,\n reportAssistantAiTokenUsage as sharedReportUsage,\n} from '@burdenoff/fe-libs/shared/assistant';\nimport type {\n AssistantRawMessage as SharedRawMessage,\n AssistantSandboxAuthContext as SharedAuthContext,\n AssistantSessionInfo as SharedSessionInfo,\n DownloadedAssistantArtifact,\n} from '@burdenoff/fe-libs/shared/assistant';\nimport type { AssistantArtifact as LocalAssistantArtifact, AssistantMode } from '@/types/assistant';\nimport type { PageContext } from '@/utils/pageContext';\n\n// Re-export the shared types under the names the panel already imports.\nexport type AssistantRawMessage = SharedRawMessage;\nexport type AssistantSandboxAuthContext = SharedAuthContext;\nexport type AssistantSessionInfo = SharedSessionInfo;\n\n// Vestigial Apollo arg — accepted for signature compatibility, ignored.\ntype ApolloClientLike = unknown;\n\nconst PRODUCT = 'vibecontrols';\n// Matches the original panel behavior: create at 600s, kept warm while open by\n// useAssistantHeartbeat's +600s extend. (The floating widget keeps its own\n// longer-TTL keep-warm via the shared transport.)\nconst DEFAULT_TTL_SECONDS = 600;\n\n// Build-time env parity with the original `assistantApi.ts` image-tag selection\n// (VITE_APP_ENV === 'prod' → prod image tag). Drives getImageTagForMode.\nfunction isProdRuntime(): boolean {\n return import.meta.env.VITE_APP_ENV === 'prod';\n}\n\nconst ctx = (a?: SharedAuthContext): SharedAuthContext => a ?? {};\n\nexport function findExistingSandbox(\n _apollo: ApolloClientLike,\n workspaceId: string,\n mode: AssistantMode,\n authContext?: SharedAuthContext\n): Promise<string | null> {\n return sharedFindExisting(workspaceId, mode, isProdRuntime(), ctx(authContext));\n}\n\nexport function createAssistantSandbox(\n _apollo: ApolloClientLike,\n mode: AssistantMode,\n workspaceId: string,\n authContext?: SharedAuthContext\n): Promise<string> {\n return sharedCreate(\n PRODUCT,\n mode,\n workspaceId,\n isProdRuntime(),\n DEFAULT_TTL_SECONDS,\n ctx(authContext)\n );\n}\n\nexport function waitForSandboxReady(\n _apollo: ApolloClientLike,\n sandboxId: string,\n workspaceId: string,\n authContext?: SharedAuthContext,\n maxWaitMs = 300_000,\n _onProgress?: (message: string) => void\n): Promise<void> {\n return sharedWaitRunning(sandboxId, workspaceId, ctx(authContext), maxWaitMs);\n}\n\nexport function waitForAssistantServiceReady(\n _apollo: ApolloClientLike,\n sandboxId: string,\n workspaceId: string,\n authContext?: SharedAuthContext,\n maxWaitMs = 90_000,\n _onProgress?: (message: string) => void\n): Promise<void> {\n return sharedWaitService(sandboxId, workspaceId, ctx(authContext), maxWaitMs);\n}\n\nexport function createAssistantSession(\n _apollo: ApolloClientLike,\n sandboxId: string,\n workspaceId: string,\n mode: AssistantMode,\n authContext?: SharedAuthContext\n): Promise<{ sessionId: string }> {\n return sharedCreateSession(sandboxId, workspaceId, mode, ctx(authContext));\n}\n\nexport function getAssistantSession(\n _apollo: ApolloClientLike,\n sandboxId: string,\n workspaceId: string,\n sessionId: string,\n authContext?: SharedAuthContext\n): Promise<SharedSessionInfo> {\n return sharedGetSession(sandboxId, workspaceId, sessionId, ctx(authContext));\n}\n\nexport function sendAssistantPromptAsync(\n _apollo: ApolloClientLike,\n sandboxId: string,\n workspaceId: string,\n sessionId: string,\n prompt: string,\n mode: AssistantMode,\n pageContext?: PageContext,\n authContext?: SharedAuthContext\n): Promise<{ messageID?: string }> {\n return sharedSendAsync(\n sandboxId,\n workspaceId,\n sessionId,\n prompt,\n mode,\n pageContext as Record<string, unknown> | undefined,\n ctx(authContext)\n );\n}\n\nexport function getAssistantMessages(\n _apollo: ApolloClientLike,\n sandboxId: string,\n workspaceId: string,\n sessionId: string,\n authContext?: SharedAuthContext,\n limit = 50\n): Promise<SharedRawMessage[]> {\n return sharedGetMessages(sandboxId, workspaceId, sessionId, ctx(authContext), { limit });\n}\n\nexport function checkAssistantAiCredits(\n _apollo: ApolloClientLike,\n workspaceId: string,\n authContext?: SharedAuthContext\n): Promise<boolean> {\n return sharedCheckCredits(workspaceId, ctx(authContext));\n}\n\nexport function reportAssistantAiTokenUsage(\n _apollo: ApolloClientLike,\n workspaceId: string,\n sessionId: string,\n messageId: string,\n model: string | undefined,\n tokens: { input: number; output: number },\n authContext?: SharedAuthContext\n): Promise<void> {\n return sharedReportUsage(workspaceId, sessionId, messageId, model, tokens, ctx(authContext));\n}\n\nexport function getAssistantArtifacts(\n _apollo: ApolloClientLike,\n sandboxId: string,\n workspaceId: string,\n sessionId: string,\n authContext?: SharedAuthContext\n): Promise<LocalAssistantArtifact[]> {\n // The shared surface widens `type` to `string`; at runtime the agent only ever\n // returns 'file' | 'directory', so the array is structurally the local type.\n return sharedGetArtifacts(sandboxId, workspaceId, sessionId, ctx(authContext)).then(\n (artifacts) => artifacts as unknown as LocalAssistantArtifact[]\n );\n}\n\nexport function downloadAssistantArtifact(\n _apollo: ApolloClientLike,\n sandboxId: string,\n workspaceId: string,\n sessionId: string,\n artifactPath: string,\n authContext?: SharedAuthContext\n): Promise<DownloadedAssistantArtifact> {\n return sharedDownloadArtifact(sandboxId, workspaceId, sessionId, artifactPath, ctx(authContext));\n}\n\nexport function sendHeartbeat(\n _apollo: ApolloClientLike,\n sandboxId: string,\n workspaceId: string,\n sessionId: string,\n authContext?: SharedAuthContext\n): Promise<void> {\n return sharedHeartbeat(sandboxId, workspaceId, sessionId, ctx(authContext));\n}\n\nexport function extendAssistantSandboxTTL(\n _apollo: ApolloClientLike,\n sandboxId: string,\n workspaceId: string,\n additionalSeconds = 600,\n authContext?: SharedAuthContext\n): Promise<void> {\n return sharedExtendTtl(sandboxId, workspaceId, additionalSeconds, ctx(authContext));\n}\n"],"mappings":";;AA6CA,IAAM,IAAU,gBAIV,IAAsB;AAI5B,SAAS,IAAyB;AAChC,QAAO;;AAGT,IAAM,KAAO,MAA6C,KAAK,EAAE;AAEjE,SAAgB,EACd,GACA,GACA,GACA,GACwB;AACxB,QAAO,EAAmB,GAAa,GAAM,GAAe,EAAE,EAAI,EAAY,CAAC;;AAGjF,SAAgB,EACd,GACA,GACA,GACA,GACiB;AACjB,QAAO,EACL,GACA,GACA,GACA,GAAe,EACf,GACA,EAAI,EAAY,CACjB;;AAGH,SAAgB,EACd,GACA,GACA,GACA,GACA,IAAY,KACZ,GACe;AACf,QAAO,EAAkB,GAAW,GAAa,EAAI,EAAY,EAAE,EAAU;;AAG/E,SAAgB,EACd,GACA,GACA,GACA,GACA,IAAY,KACZ,GACe;AACf,QAAO,EAAkB,GAAW,GAAa,EAAI,EAAY,EAAE,EAAU;;AAG/E,SAAgB,EACd,GACA,GACA,GACA,GACA,GACgC;AAChC,QAAO,EAAoB,GAAW,GAAa,GAAM,EAAI,EAAY,CAAC;;AAG5E,SAAgB,EACd,GACA,GACA,GACA,GACA,GAC4B;AAC5B,QAAO,EAAiB,GAAW,GAAa,GAAW,EAAI,EAAY,CAAC;;AAG9E,SAAgB,EACd,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACiC;AACjC,QAAO,EACL,GACA,GACA,GACA,GACA,GACA,GACA,EAAI,EAAY,CACjB;;AAGH,SAAgB,EACd,GACA,GACA,GACA,GACA,GACA,IAAQ,IACqB;AAC7B,QAAO,EAAkB,GAAW,GAAa,GAAW,EAAI,EAAY,EAAE,EAAE,UAAO,CAAC;;AAG1F,SAAgB,EACd,GACA,GACA,GACkB;AAClB,QAAO,EAAmB,GAAa,EAAI,EAAY,CAAC;;AAG1D,SAAgB,EACd,GACA,GACA,GACA,GACA,GACA,GACA,GACe;AACf,QAAO,EAAkB,GAAa,GAAW,GAAW,GAAO,GAAQ,EAAI,EAAY,CAAC;;AAG9F,SAAgB,EACd,GACA,GACA,GACA,GACA,GACmC;AAGnC,QAAO,EAAmB,GAAW,GAAa,GAAW,EAAI,EAAY,CAAC,CAAC,MAC5E,MAAc,EAChB;;AAGH,SAAgB,EACd,GACA,GACA,GACA,GACA,GACA,GACsC;AACtC,QAAO,EAAuB,GAAW,GAAa,GAAW,GAAc,EAAI,EAAY,CAAC;;AAGlG,SAAgB,EACd,GACA,GACA,GACA,GACA,GACe;AACf,QAAO,EAAgB,GAAW,GAAa,GAAW,EAAI,EAAY,CAAC;;AAG7E,SAAgB,EACd,GACA,GACA,GACA,IAAoB,KACpB,GACe;AACf,QAAO,EAAgB,GAAW,GAAa,GAAmB,EAAI,EAAY,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-vibecontrols",
3
- "version": "2026.713.1",
3
+ "version": "2026.714.1",
4
4
  "description": "VibeControls microfrontend for Burdenoff products",
5
5
  "type": "module",
6
6
  "files": [
@@ -59,7 +59,7 @@
59
59
  "license": "PROPRIETARY",
60
60
  "dependencies": {
61
61
  "@apollo/client": "4.1.9",
62
- "@burdenoff/fe-libs": "2026.713.6",
62
+ "@burdenoff/fe-libs": "2026.714.1",
63
63
  "@tanstack/react-query": "^5.90.16",
64
64
  "@xyflow/react": "^12.10.2",
65
65
  "clsx": "^2.1.1",