@flexkit/studio 0.0.36 → 0.1.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 (164) hide show
  1. package/README.md +81 -0
  2. package/dist/astro.d.ts +3 -5
  3. package/dist/astro.js +3 -8
  4. package/dist/chat-page-NWMI4XOE.js +2 -0
  5. package/dist/chat-page-NWMI4XOE.js.map +1 -0
  6. package/dist/chunk-2DXR5NJV.js +2 -0
  7. package/dist/chunk-2DXR5NJV.js.map +1 -0
  8. package/dist/chunk-3CPWATOI.js +2 -0
  9. package/dist/chunk-3CPWATOI.js.map +1 -0
  10. package/dist/chunk-5DHOBLAE.js +2 -0
  11. package/dist/chunk-5DHOBLAE.js.map +1 -0
  12. package/dist/chunk-6LYEDKFY.js +7 -0
  13. package/dist/chunk-6LYEDKFY.js.map +1 -0
  14. package/dist/chunk-7PDYCDX6.js +2 -0
  15. package/dist/chunk-7PDYCDX6.js.map +1 -0
  16. package/dist/chunk-7SK5YPHT.js +2 -0
  17. package/dist/chunk-7SK5YPHT.js.map +1 -0
  18. package/dist/chunk-AKQ6ELDX.js +2 -0
  19. package/dist/chunk-AKQ6ELDX.js.map +1 -0
  20. package/dist/{chunk-POQX5GIA.js → chunk-C2BPRGGQ.js} +47 -172
  21. package/dist/chunk-CSUHZFEP.js +2 -0
  22. package/dist/chunk-CSUHZFEP.js.map +1 -0
  23. package/dist/chunk-G4PYYHI3.js +2 -0
  24. package/dist/chunk-G4PYYHI3.js.map +1 -0
  25. package/dist/chunk-GZIMMYLK.js +2 -0
  26. package/dist/chunk-GZIMMYLK.js.map +1 -0
  27. package/dist/chunk-HROHAMPM.js +3 -0
  28. package/dist/chunk-HROHAMPM.js.map +1 -0
  29. package/dist/chunk-NNA4MLFC.js +3 -0
  30. package/dist/chunk-NNA4MLFC.js.map +1 -0
  31. package/dist/chunk-NSYO57O3.js +5 -0
  32. package/dist/chunk-NSYO57O3.js.map +1 -0
  33. package/dist/chunk-ODORXGGY.js +2 -0
  34. package/dist/chunk-ODORXGGY.js.map +1 -0
  35. package/dist/chunk-OUSEULBR.js +384 -0
  36. package/dist/chunk-OUSEULBR.js.map +1 -0
  37. package/dist/chunk-P6BZ4QP7.js +2 -0
  38. package/dist/chunk-P6BZ4QP7.js.map +1 -0
  39. package/dist/chunk-QQUNCDUB.js +2 -0
  40. package/dist/chunk-QQUNCDUB.js.map +1 -0
  41. package/dist/chunk-SZEGGBOC.js +2 -0
  42. package/dist/chunk-SZEGGBOC.js.map +1 -0
  43. package/dist/chunk-W2EBZZAY.js +3 -0
  44. package/dist/chunk-W2EBZZAY.js.map +1 -0
  45. package/dist/chunk-YINI2YKQ.js +4 -0
  46. package/dist/chunk-YINI2YKQ.js.map +1 -0
  47. package/dist/{core-handler-C3xC98bN.d.ts → core-handler-XAVVKLhV.d.ts} +0 -3
  48. package/dist/edit-entity-PVT34FD7.js +2 -0
  49. package/dist/edit-entity-PVT34FD7.js.map +1 -0
  50. package/dist/index.css +1402 -0
  51. package/dist/index.d.ts +433 -33
  52. package/dist/index.js +12 -395
  53. package/dist/index.js.map +1 -1
  54. package/dist/list-SQCN7HA3.js +2 -0
  55. package/dist/list-SQCN7HA3.js.map +1 -0
  56. package/dist/nextjs.d.ts +61 -56
  57. package/dist/nextjs.js +3 -8
  58. package/dist/pages-OIAPASPF.js +3 -0
  59. package/dist/pages-OIAPASPF.js.map +1 -0
  60. package/dist/plugin-pages-AHOA6YJE.js +2 -0
  61. package/dist/plugin-pages-AHOA6YJE.js.map +1 -0
  62. package/dist/project-selector-72VM6SUI.js +2 -0
  63. package/dist/project-selector-72VM6SUI.js.map +1 -0
  64. package/dist/root-4FGNRGCD.js +23 -0
  65. package/dist/root-4FGNRGCD.js.map +1 -0
  66. package/dist/root-5ZW536V7.js +2 -0
  67. package/dist/root-5ZW536V7.js.map +1 -0
  68. package/dist/root-IIILTOJI.js +31 -0
  69. package/dist/root-IIILTOJI.js.map +1 -0
  70. package/dist/root-QPQQ3DFJ.js +2 -0
  71. package/dist/root-QPQQ3DFJ.js.map +1 -0
  72. package/dist/search-2K2BU4UU.js +2 -0
  73. package/dist/{search-XKG5A7XM.js.map → search-2K2BU4UU.js.map} +1 -1
  74. package/dist/skills-pages-PSBRTFGK.js +2 -0
  75. package/dist/skills-pages-PSBRTFGK.js.map +1 -0
  76. package/dist/tanstack-start.d.ts +4 -6
  77. package/dist/tanstack-start.js +5 -12
  78. package/dist/ui.d.ts +5 -7
  79. package/dist/ui.js +1 -6
  80. package/dist/ui.js.map +1 -1
  81. package/dist/user-nav-QZFCICK3.js +2 -0
  82. package/dist/{user-nav-LSEOOH4E.js.map → user-nav-QZFCICK3.js.map} +1 -1
  83. package/package.json +30 -12
  84. package/dist/asset-3XMRPTA5.js +0 -2
  85. package/dist/asset-3XMRPTA5.js.map +0 -1
  86. package/dist/boolean-MTD44LXP.js +0 -2
  87. package/dist/boolean-MTD44LXP.js.map +0 -1
  88. package/dist/chunk-3VOTTOJT.js +0 -2
  89. package/dist/chunk-3VOTTOJT.js.map +0 -1
  90. package/dist/chunk-5I7Q5ODB.js +0 -2
  91. package/dist/chunk-5I7Q5ODB.js.map +0 -1
  92. package/dist/chunk-6NRQMG26.js +0 -2
  93. package/dist/chunk-6NRQMG26.js.map +0 -1
  94. package/dist/chunk-6V73336R.js +0 -623
  95. package/dist/chunk-7BOX7HHO.js +0 -2
  96. package/dist/chunk-7BOX7HHO.js.map +0 -1
  97. package/dist/chunk-7JFLGBWE.js +0 -2
  98. package/dist/chunk-7JFLGBWE.js.map +0 -1
  99. package/dist/chunk-7ZJN4MWQ.js +0 -2
  100. package/dist/chunk-7ZJN4MWQ.js.map +0 -1
  101. package/dist/chunk-AICNS7KW.js +0 -2
  102. package/dist/chunk-AICNS7KW.js.map +0 -1
  103. package/dist/chunk-D4XLXU2H.js +0 -2
  104. package/dist/chunk-D4XLXU2H.js.map +0 -1
  105. package/dist/chunk-FLT6RWXH.js +0 -2
  106. package/dist/chunk-FLT6RWXH.js.map +0 -1
  107. package/dist/chunk-GBM7VKFS.js +0 -2
  108. package/dist/chunk-GBM7VKFS.js.map +0 -1
  109. package/dist/chunk-HMMBYXYA.js +0 -2
  110. package/dist/chunk-HMMBYXYA.js.map +0 -1
  111. package/dist/chunk-IRY4KWB5.js +0 -2
  112. package/dist/chunk-IRY4KWB5.js.map +0 -1
  113. package/dist/chunk-JH4MVD36.js +0 -2
  114. package/dist/chunk-JH4MVD36.js.map +0 -1
  115. package/dist/chunk-JKHUO27E.js +0 -2
  116. package/dist/chunk-JKHUO27E.js.map +0 -1
  117. package/dist/chunk-LIV5RBWJ.js +0 -2
  118. package/dist/chunk-LIV5RBWJ.js.map +0 -1
  119. package/dist/chunk-PENRGDNC.js +0 -2
  120. package/dist/chunk-PENRGDNC.js.map +0 -1
  121. package/dist/chunk-QOX3QNMM.js +0 -2
  122. package/dist/chunk-QOX3QNMM.js.map +0 -1
  123. package/dist/chunk-QVBNGGOE.js +0 -2
  124. package/dist/chunk-QVBNGGOE.js.map +0 -1
  125. package/dist/chunk-S6MOM5G3.js +0 -2
  126. package/dist/chunk-S6MOM5G3.js.map +0 -1
  127. package/dist/chunk-UGRS4FEI.js +0 -2
  128. package/dist/chunk-UGRS4FEI.js.map +0 -1
  129. package/dist/chunk-USNXQOMJ.js +0 -2
  130. package/dist/chunk-USNXQOMJ.js.map +0 -1
  131. package/dist/chunk-UWMJBBTY.js +0 -2
  132. package/dist/chunk-UWMJBBTY.js.map +0 -1
  133. package/dist/chunk-W3Z33ETA.js +0 -2
  134. package/dist/chunk-W3Z33ETA.js.map +0 -1
  135. package/dist/chunk-WDRCARCP.js +0 -3
  136. package/dist/chunk-WDRCARCP.js.map +0 -1
  137. package/dist/chunk-WIUPQHZ5.js +0 -2
  138. package/dist/chunk-WIUPQHZ5.js.map +0 -1
  139. package/dist/chunk-WJ4ORIXF.js +0 -2
  140. package/dist/chunk-WJ4ORIXF.js.map +0 -1
  141. package/dist/chunk-YSLN4XT6.js +0 -2
  142. package/dist/chunk-YSLN4XT6.js.map +0 -1
  143. package/dist/datetime-C55QQQJK.js +0 -2
  144. package/dist/datetime-C55QQQJK.js.map +0 -1
  145. package/dist/editor-NZLXIOE7.js +0 -2
  146. package/dist/editor-NZLXIOE7.js.map +0 -1
  147. package/dist/project-selector-GQ24PVO6.js +0 -2
  148. package/dist/project-selector-GQ24PVO6.js.map +0 -1
  149. package/dist/search-XKG5A7XM.js +0 -2
  150. package/dist/select-SO3DICYX.js +0 -2
  151. package/dist/select-SO3DICYX.js.map +0 -1
  152. package/dist/switch-SU3OIXL6.js +0 -2
  153. package/dist/switch-SU3OIXL6.js.map +0 -1
  154. package/dist/text-FZSI6W5I.js +0 -2
  155. package/dist/text-FZSI6W5I.js.map +0 -1
  156. package/dist/text-QXGOD2KW.js +0 -2
  157. package/dist/text-QXGOD2KW.js.map +0 -1
  158. package/dist/textarea-INLURFNU.js +0 -2
  159. package/dist/textarea-INLURFNU.js.map +0 -1
  160. package/dist/tools.d.ts +0 -78
  161. package/dist/tools.js +0 -60
  162. package/dist/types-U28Ppixq.d.ts +0 -56
  163. package/dist/types.d-CPIuPrvL.d.ts +0 -458
  164. package/dist/user-nav-LSEOOH4E.js +0 -2
@@ -1,623 +0,0 @@
1
- // src/tools/actor.ts
2
- function isStringArray(value) {
3
- return Array.isArray(value) && value.every((item) => typeof item === "string");
4
- }
5
- function parseCustomerToolActor(value) {
6
- if (!value || typeof value !== "object") {
7
- return null;
8
- }
9
- const record = value;
10
- if (record.kind === "chat") {
11
- if (typeof record.userId !== "string" || !record.userId) {
12
- return null;
13
- }
14
- if (typeof record.role !== "string" || !record.role) {
15
- return null;
16
- }
17
- if (!isStringArray(record.spaceCodes)) {
18
- return null;
19
- }
20
- return {
21
- kind: "chat",
22
- role: record.role,
23
- spaceCodes: record.spaceCodes,
24
- userId: record.userId
25
- };
26
- }
27
- if (record.kind === "automation") {
28
- if (typeof record.automationId !== "string" || !record.automationId) {
29
- return null;
30
- }
31
- const spaceId = record.spaceId ?? null;
32
- if (spaceId !== null && typeof spaceId !== "string") {
33
- return null;
34
- }
35
- if (!isStringArray(record.spaceCodes)) {
36
- return null;
37
- }
38
- return {
39
- automationId: record.automationId,
40
- kind: "automation",
41
- spaceCodes: record.spaceCodes,
42
- spaceId
43
- };
44
- }
45
- return null;
46
- }
47
-
48
- // src/tools/tool-names.ts
49
- var CUSTOM_TOOL_NAME_PREFIX = "custom_";
50
- var TOOL_NAME_PATTERN = /^[a-z][a-zA-Z0-9_]*$/;
51
- function isValidToolName(name) {
52
- return TOOL_NAME_PATTERN.test(name) && !name.startsWith(CUSTOM_TOOL_NAME_PREFIX);
53
- }
54
- function toAgentToolName(name) {
55
- return `${CUSTOM_TOOL_NAME_PREFIX}${name}`;
56
- }
57
-
58
- // src/tools/define-tool.ts
59
- import { z } from "zod";
60
-
61
- // src/tools/json-schema.ts
62
- function stripJsonSchemaMeta(value) {
63
- if (Array.isArray(value)) {
64
- return value.map((entry) => stripJsonSchemaMeta(entry));
65
- }
66
- if (!value || typeof value !== "object") {
67
- return value;
68
- }
69
- const result = {};
70
- for (const [key, nested] of Object.entries(value)) {
71
- if (key === "$schema") {
72
- continue;
73
- }
74
- result[key] = stripJsonSchemaMeta(nested);
75
- }
76
- return result;
77
- }
78
-
79
- // src/tools/define-tool.ts
80
- function defineTool(options) {
81
- if (!isValidToolName(options.name)) {
82
- throw new Error(
83
- `Invalid custom tool name "${options.name}". Use a camelCase identifier that does not start with \`custom_\`.`
84
- );
85
- }
86
- if (!options.description.trim()) {
87
- throw new Error(`Custom tool "${options.name}" must have a description.`);
88
- }
89
- return {
90
- description: options.description.trim(),
91
- execute: (input, actor) => options.execute(input, actor),
92
- input: options.input,
93
- name: options.name
94
- };
95
- }
96
- function toolToManifest(tool) {
97
- const inputSchema = stripJsonSchemaMeta(
98
- z.toJSONSchema(tool.input, { target: "draft-07" })
99
- );
100
- return {
101
- description: tool.description,
102
- inputSchema,
103
- name: tool.name
104
- };
105
- }
106
-
107
- // src/tools/hmac.ts
108
- var FLEXKIT_TIMESTAMP_HEADER = "flexkit-timestamp";
109
- var FLEXKIT_SIGNATURE_HEADER = "flexkit-signature";
110
- var FLEXKIT_SIGNATURE_PREVIOUS_HEADER = "flexkit-signature-previous";
111
- var CUSTOMER_TOOLS_SERVE_PATH = "/api/flexkit/tools";
112
- var CUSTOMER_TOOLS_HELLO_PATH = "/tools/dev-connect/hello";
113
- var CUSTOMER_TOOLS_POLL_PATH = "/tools/dev-connect/poll";
114
- var CUSTOMER_TOOLS_RESPOND_PATH = "/tools/dev-connect/respond";
115
- var DEFAULT_MAX_SKEW_SECONDS = 300;
116
- function getSubtleCrypto() {
117
- const subtle = globalThis.crypto?.subtle;
118
- if (!subtle) {
119
- throw new Error("Web Crypto is not available.");
120
- }
121
- return subtle;
122
- }
123
- function encodeUtf8(value) {
124
- return new TextEncoder().encode(value);
125
- }
126
- function toBase64Url(bytes) {
127
- const binary = String.fromCharCode(...new Uint8Array(bytes));
128
- return btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", "");
129
- }
130
- function timingSafeEqualBytes(left, right) {
131
- if (left.length !== right.length) {
132
- return false;
133
- }
134
- let diff = 0;
135
- for (let index = 0; index < left.length; index += 1) {
136
- diff |= (left[index] ?? 0) ^ (right[index] ?? 0);
137
- }
138
- return diff === 0;
139
- }
140
- function getUnixTimestampSeconds() {
141
- return Math.floor(Date.now() / 1e3);
142
- }
143
- function buildSignaturePayload({
144
- body,
145
- method,
146
- path,
147
- timestamp
148
- }) {
149
- return `${timestamp.toString()}.${method.toUpperCase()}.${path}.${body}`;
150
- }
151
- async function signPayload(secret, payload) {
152
- const key = await getSubtleCrypto().importKey(
153
- "raw",
154
- encodeUtf8(secret),
155
- { hash: "SHA-256", name: "HMAC" },
156
- false,
157
- ["sign"]
158
- );
159
- const signature = await getSubtleCrypto().sign("HMAC", key, encodeUtf8(payload));
160
- return `v1=${toBase64Url(signature)}`;
161
- }
162
- async function createSignedHeaders({
163
- body,
164
- method,
165
- path,
166
- previousSecret,
167
- secret,
168
- timestamp = getUnixTimestampSeconds()
169
- }) {
170
- const payload = buildSignaturePayload({ body, method, path, timestamp });
171
- const headers = {
172
- "Flexkit-Timestamp": timestamp.toString(),
173
- "Flexkit-Signature": await signPayload(secret, payload)
174
- };
175
- if (previousSecret) {
176
- headers["Flexkit-Signature-Previous"] = await signPayload(previousSecret, payload);
177
- }
178
- return headers;
179
- }
180
- function uniqueSecrets(secret) {
181
- const values = Array.isArray(secret) ? secret : [secret];
182
- const unique = [];
183
- for (const value of values) {
184
- const trimmed = value.trim();
185
- if (trimmed && !unique.includes(trimmed)) {
186
- unique.push(trimmed);
187
- }
188
- }
189
- return unique;
190
- }
191
- function parseSignatureHeader(value) {
192
- const trimmed = value.trim();
193
- if (trimmed.startsWith("v1=")) {
194
- return trimmed.slice(3);
195
- }
196
- return null;
197
- }
198
- async function verifySignedHeaders({
199
- body,
200
- maxSkewSeconds = DEFAULT_MAX_SKEW_SECONDS,
201
- method,
202
- path,
203
- previousSignatureHeader,
204
- secret,
205
- signatureHeader,
206
- timestampHeader
207
- }) {
208
- const secrets = uniqueSecrets(secret);
209
- const signatureHeaders = [signatureHeader, previousSignatureHeader ?? null].filter(
210
- (value) => Boolean(value)
211
- );
212
- if (secrets.length === 0 || signatureHeaders.length === 0 || !timestampHeader) {
213
- return false;
214
- }
215
- const timestamp = Number(timestampHeader);
216
- if (!Number.isInteger(timestamp)) {
217
- return false;
218
- }
219
- const now = getUnixTimestampSeconds();
220
- if (Math.abs(now - timestamp) > maxSkewSeconds) {
221
- return false;
222
- }
223
- const payload = buildSignaturePayload({ body, method, path, timestamp });
224
- for (const candidateSecret of secrets) {
225
- const expected = await signPayload(candidateSecret, payload);
226
- const expectedDigest = parseSignatureHeader(expected);
227
- if (!expectedDigest) {
228
- continue;
229
- }
230
- const expectedBytes = encodeUtf8(expectedDigest);
231
- for (const header of signatureHeaders) {
232
- const providedDigest = parseSignatureHeader(header);
233
- if (!providedDigest) {
234
- continue;
235
- }
236
- const providedBytes = encodeUtf8(providedDigest);
237
- if (providedBytes.length !== expectedBytes.length) {
238
- continue;
239
- }
240
- if (timingSafeEqualBytes(providedBytes, expectedBytes)) {
241
- return true;
242
- }
243
- }
244
- }
245
- return false;
246
- }
247
- function getHeader(headers, name) {
248
- return headers.get(name) ?? headers.get(name.toLowerCase());
249
- }
250
-
251
- // src/core/domains.ts
252
- var defaultFlexkitDomain = "flexkit.io";
253
- var allowedFlexkitDomains = {
254
- "flexkit.io": true,
255
- "flexkit.test": true
256
- };
257
- function getConfiguredFlexkitDomain() {
258
- const configuredDomain = globalThis.process?.env?.FLEXKIT_DOMAIN?.trim();
259
- if (!configuredDomain) {
260
- return defaultFlexkitDomain;
261
- }
262
- if (allowedFlexkitDomains[configuredDomain]) {
263
- return configuredDomain;
264
- }
265
- return defaultFlexkitDomain;
266
- }
267
- var flexkitDomain = getConfiguredFlexkitDomain();
268
- var flexkitApiDomain = `api.${flexkitDomain}`;
269
-
270
- // src/tools/dev-connect.ts
271
- var CUSTOMER_TOOLS_ME_PATH = "/users/me";
272
- var FLEXKIT_STUDIO_RUNTIME_HEADER = "Flexkit-Studio-Runtime";
273
- var FLEXKIT_STUDIO_RUNTIME_LOCAL = "local";
274
- var DEV_CONNECT_ROLES = {
275
- developer: true,
276
- owner: true
277
- };
278
- function jsonResult(status, body) {
279
- return {
280
- body,
281
- headers: { "Content-Type": "application/json" },
282
- status,
283
- type: "json"
284
- };
285
- }
286
- function noContentResult() {
287
- return {
288
- body: null,
289
- status: 204,
290
- type: "response"
291
- };
292
- }
293
- function shouldHandleDevConnectTick() {
294
- const env = globalThis.process?.env ?? {};
295
- if (env.FLEXKIT_TOOLS_DEV_CONNECT === "1") {
296
- return true;
297
- }
298
- return env.NODE_ENV !== "production";
299
- }
300
- function isDevConnectRole(role) {
301
- return Boolean(role && DEV_CONNECT_ROLES[role]);
302
- }
303
- function getProjectApiOrigin(projectId) {
304
- return `https://${projectId}.${flexkitApiDomain}`;
305
- }
306
- function guessClientLabel(fallbackProjectId) {
307
- const env = globalThis.process?.env ?? {};
308
- const port = env.PORT ?? "3000";
309
- return `${env.npm_package_name ?? fallbackProjectId}@localhost:${port}`;
310
- }
311
- function isCustomerToolsTickPath(pathname) {
312
- return /^\/api\/flexkit\/[^/]+\/tools\/dev-connect\/tick$/.test(pathname);
313
- }
314
- function getCustomerToolsTickPath(projectId) {
315
- return `/api/flexkit/${projectId}/tools/dev-connect/tick`;
316
- }
317
- async function sessionFetch({
318
- body,
319
- method,
320
- path,
321
- projectId,
322
- sessionToken
323
- }) {
324
- const headers = {
325
- Cookie: `sessionToken=${sessionToken}`
326
- };
327
- if (body) {
328
- headers["Content-Type"] = "application/json";
329
- }
330
- return fetch(`${getProjectApiOrigin(projectId)}${path}`, {
331
- body,
332
- headers,
333
- method
334
- });
335
- }
336
- var tickInFlight = false;
337
- var HELLO_INTERVAL_MS = 3e4;
338
- var connectDecisions = {};
339
- var helloStates = {};
340
- function connectDecisionKey(projectId, sessionToken) {
341
- return `${sessionToken}\0${projectId}`;
342
- }
343
- function forgetConnectDecision({ projectId, sessionToken }) {
344
- const key = connectDecisionKey(projectId, sessionToken);
345
- delete connectDecisions[key];
346
- delete helloStates[key];
347
- }
348
- function rememberConnectDecision({
349
- decision,
350
- projectId,
351
- sessionToken
352
- }) {
353
- connectDecisions[connectDecisionKey(projectId, sessionToken)] = decision;
354
- }
355
- function hashManifest(manifest) {
356
- let hash = 2166136261;
357
- for (let index = 0; index < manifest.length; index += 1) {
358
- hash ^= manifest.charCodeAt(index);
359
- hash = Math.imul(hash, 16777619);
360
- }
361
- return (hash >>> 0).toString(36);
362
- }
363
- function shouldSendHello(input) {
364
- const state = helloStates[connectDecisionKey(input.projectId, input.sessionToken)];
365
- if (!state || state.manifestHash !== input.manifestHash) {
366
- return true;
367
- }
368
- return Date.now() - state.sentAt >= HELLO_INTERVAL_MS;
369
- }
370
- function rememberHello(input) {
371
- helloStates[connectDecisionKey(input.projectId, input.sessionToken)] = {
372
- manifestHash: input.manifestHash,
373
- sentAt: Date.now()
374
- };
375
- }
376
- function deniedDevConnectResult(status) {
377
- if (status === 401) {
378
- return jsonResult(401, { error: "Sign in to Studio to connect local tools." });
379
- }
380
- return jsonResult(403, { error: "Only owners and developers can connect local tools." });
381
- }
382
- async function getDevConnectDenial({
383
- projectId,
384
- sessionToken
385
- }) {
386
- const cached = connectDecisions[connectDecisionKey(projectId, sessionToken)];
387
- if (cached === "allow") {
388
- return null;
389
- }
390
- if (cached === 401 || cached === 403) {
391
- return deniedDevConnectResult(cached);
392
- }
393
- let meResponse;
394
- try {
395
- meResponse = await sessionFetch({
396
- method: "GET",
397
- path: CUSTOMER_TOOLS_ME_PATH,
398
- projectId,
399
- sessionToken
400
- });
401
- } catch {
402
- return jsonResult(503, { error: "Unable to verify Studio session for local tools." });
403
- }
404
- if (meResponse.status === 401 || meResponse.status === 403) {
405
- rememberConnectDecision({ decision: meResponse.status, projectId, sessionToken });
406
- return deniedDevConnectResult(meResponse.status);
407
- }
408
- if (!meResponse.ok) {
409
- return jsonResult(503, { error: "Unable to verify Studio session for local tools." });
410
- }
411
- let payload = {};
412
- try {
413
- payload = await meResponse.json();
414
- } catch {
415
- return jsonResult(503, { error: "Unable to verify Studio session for local tools." });
416
- }
417
- const role = typeof payload.role === "string" ? payload.role : "";
418
- if (isDevConnectRole(role)) {
419
- rememberConnectDecision({ decision: "allow", projectId, sessionToken });
420
- return null;
421
- }
422
- rememberConnectDecision({ decision: 403, projectId, sessionToken });
423
- return deniedDevConnectResult(403);
424
- }
425
- async function executeJob({
426
- actor,
427
- job,
428
- projectId,
429
- sessionToken,
430
- tools
431
- }) {
432
- const tool = tools.find((candidate) => candidate.name === job.name);
433
- let body;
434
- if (!tool) {
435
- body = JSON.stringify({ error: `Unknown tool "${job.name}".`, jobId: job.id });
436
- } else {
437
- const parsed = tool.input.safeParse(job.arguments ?? {});
438
- if (!parsed.success) {
439
- body = JSON.stringify({
440
- error: parsed.error.issues.map((issue) => issue.message).join(", "),
441
- jobId: job.id
442
- });
443
- } else {
444
- try {
445
- const result = await tool.execute(parsed.data, actor);
446
- body = JSON.stringify({ jobId: job.id, result });
447
- } catch (error) {
448
- body = JSON.stringify({
449
- error: error instanceof Error ? error.message : "Tool execution failed.",
450
- jobId: job.id
451
- });
452
- }
453
- }
454
- }
455
- await sessionFetch({
456
- body,
457
- method: "POST",
458
- path: CUSTOMER_TOOLS_RESPOND_PATH,
459
- projectId,
460
- sessionToken
461
- });
462
- }
463
- async function handleDevConnectTick({
464
- projectId,
465
- sessionToken,
466
- skills,
467
- tools
468
- }) {
469
- if (!shouldHandleDevConnectTick()) {
470
- return noContentResult();
471
- }
472
- if (!sessionToken) {
473
- return jsonResult(401, { error: "Sign in to Studio to connect local tools." });
474
- }
475
- if (!projectId || tools.length === 0 && skills === void 0) {
476
- return noContentResult();
477
- }
478
- const denial = await getDevConnectDenial({ projectId, sessionToken });
479
- if (denial) {
480
- return denial;
481
- }
482
- if (tickInFlight) {
483
- return noContentResult();
484
- }
485
- tickInFlight = true;
486
- const helloBody = JSON.stringify({
487
- clientLabel: guessClientLabel(projectId),
488
- ...skills === void 0 ? {} : { skills },
489
- tools: tools.map((tool) => toolToManifest(tool))
490
- });
491
- const manifestHash = hashManifest(helloBody);
492
- try {
493
- if (shouldSendHello({ manifestHash, projectId, sessionToken })) {
494
- const helloResponse = await sessionFetch({
495
- body: helloBody,
496
- method: "POST",
497
- path: CUSTOMER_TOOLS_HELLO_PATH,
498
- projectId,
499
- sessionToken
500
- });
501
- if (helloResponse.status === 401 || helloResponse.status === 403) {
502
- forgetConnectDecision({ projectId, sessionToken });
503
- return jsonResult(helloResponse.status, { error: "Unable to register the local tools runtime." });
504
- }
505
- if (!helloResponse.ok) {
506
- return jsonResult(helloResponse.status, { error: "Unable to register the local tools runtime." });
507
- }
508
- rememberHello({ manifestHash, projectId, sessionToken });
509
- }
510
- const pollResponse = await sessionFetch({
511
- method: "GET",
512
- path: CUSTOMER_TOOLS_POLL_PATH,
513
- projectId,
514
- sessionToken
515
- });
516
- if (pollResponse.status === 401 || pollResponse.status === 403) {
517
- forgetConnectDecision({ projectId, sessionToken });
518
- return jsonResult(pollResponse.status, { error: "Unable to poll for local tool jobs." });
519
- }
520
- if (pollResponse.status !== 200) {
521
- return jsonResult(pollResponse.status, { error: "Unable to poll for local tool jobs." });
522
- }
523
- const { job } = await pollResponse.json();
524
- if (!job) {
525
- return jsonResult(200, { job: null });
526
- }
527
- const actor = parseCustomerToolActor(job.actor);
528
- if (!actor) {
529
- await sessionFetch({
530
- body: JSON.stringify({ error: "A valid Flexkit actor is required.", jobId: job.id }),
531
- method: "POST",
532
- path: CUSTOMER_TOOLS_RESPOND_PATH,
533
- projectId,
534
- sessionToken
535
- });
536
- return jsonResult(200, { job: job.id });
537
- }
538
- await executeJob({ actor, job, projectId, sessionToken, tools });
539
- return jsonResult(200, { job: job.id });
540
- } catch {
541
- return jsonResult(503, { error: "Flexkit is not reachable from this local runtime." });
542
- } finally {
543
- tickInFlight = false;
544
- }
545
- }
546
-
547
- // src/tools/define-skill.ts
548
- var MAX_SKILL_NAME_LENGTH = 120;
549
- var MAX_SKILL_DESCRIPTION_LENGTH = 500;
550
- var MAX_SKILL_CONTENT_LENGTH = 5e4;
551
- function requireValue(value, field) {
552
- const trimmed = value.trim();
553
- if (!trimmed) {
554
- throw new Error(`Custom skill ${field} is required.`);
555
- }
556
- return trimmed;
557
- }
558
- function defineSkill(options) {
559
- const name = requireValue(options.name, "name");
560
- const description = requireValue(options.description, `"${name}" description`);
561
- const content = requireValue(options.content, `"${name}" content`);
562
- const space = options.space === void 0 ? void 0 : requireValue(options.space, `"${name}" space`);
563
- if (name.length > MAX_SKILL_NAME_LENGTH) {
564
- throw new Error(`Custom skill name must be at most ${String(MAX_SKILL_NAME_LENGTH)} characters.`);
565
- }
566
- if (description.length > MAX_SKILL_DESCRIPTION_LENGTH) {
567
- throw new Error(
568
- `Custom skill "${name}" description must be at most ${String(MAX_SKILL_DESCRIPTION_LENGTH)} characters.`
569
- );
570
- }
571
- if (content.length > MAX_SKILL_CONTENT_LENGTH) {
572
- throw new Error(`Custom skill "${name}" content must be at most ${String(MAX_SKILL_CONTENT_LENGTH)} characters.`);
573
- }
574
- return {
575
- content,
576
- description,
577
- name,
578
- ...space === void 0 ? {} : { space }
579
- };
580
- }
581
- function assertUniqueSkillNames(skills) {
582
- const names = /* @__PURE__ */ new Set();
583
- for (const skill of skills) {
584
- if (names.has(skill.name)) {
585
- throw new Error(`Duplicate custom skill name "${skill.name}".`);
586
- }
587
- names.add(skill.name);
588
- }
589
- }
590
-
591
- export {
592
- flexkitDomain,
593
- flexkitApiDomain,
594
- parseCustomerToolActor,
595
- CUSTOM_TOOL_NAME_PREFIX,
596
- isValidToolName,
597
- toAgentToolName,
598
- defineTool,
599
- toolToManifest,
600
- FLEXKIT_TIMESTAMP_HEADER,
601
- FLEXKIT_SIGNATURE_HEADER,
602
- FLEXKIT_SIGNATURE_PREVIOUS_HEADER,
603
- CUSTOMER_TOOLS_SERVE_PATH,
604
- CUSTOMER_TOOLS_HELLO_PATH,
605
- CUSTOMER_TOOLS_POLL_PATH,
606
- CUSTOMER_TOOLS_RESPOND_PATH,
607
- signPayload,
608
- createSignedHeaders,
609
- verifySignedHeaders,
610
- getHeader,
611
- FLEXKIT_STUDIO_RUNTIME_HEADER,
612
- FLEXKIT_STUDIO_RUNTIME_LOCAL,
613
- shouldHandleDevConnectTick,
614
- isDevConnectRole,
615
- isCustomerToolsTickPath,
616
- getCustomerToolsTickPath,
617
- handleDevConnectTick,
618
- MAX_SKILL_NAME_LENGTH,
619
- MAX_SKILL_DESCRIPTION_LENGTH,
620
- MAX_SKILL_CONTENT_LENGTH,
621
- defineSkill,
622
- assertUniqueSkillNames
623
- };
@@ -1,2 +0,0 @@
1
- import'./index.css';import {a}from'./chunk-O2QMYUPS.js';import {jsx}from'react/jsx-runtime';function o({className:r,...i}){return jsx("textarea",{"data-slot":"textarea",className:a("fk:flex fk:field-sizing-content fk:min-h-16 fk:w-full fk:rounded-md fk:border fk:border-input fk:bg-background fk:px-3 fk:py-2 fk:text-base fk:shadow-xs fk:transition-[color,box-shadow] fk:outline-none fk:placeholder:text-muted-foreground fk:focus-visible:border-ring fk:focus-visible:ring-[3px] fk:focus-visible:ring-ring/50 fk:disabled:cursor-not-allowed fk:disabled:opacity-50 fk:aria-invalid:border-destructive fk:aria-invalid:ring-destructive/20 fk:md:text-sm fk:dark:bg-input/30 fk:dark:aria-invalid:ring-destructive/40 fk:corner-squircle",r),...i})}export{o as a};//# sourceMappingURL=chunk-7BOX7HHO.js.map
2
- //# sourceMappingURL=chunk-7BOX7HHO.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/ui/primitives/textarea.tsx"],"names":["Textarea","className","props","jsx","cn"],"mappings":"4FAGA,SAASA,CAAAA,CAAS,CAAE,SAAA,CAAAC,CAAAA,CAAW,GAAGC,CAAM,CAAA,CAAqC,CAC3E,OACEC,GAAAA,CAAC,UAAA,CAAA,CACC,WAAA,CAAU,UAAA,CACV,SAAA,CAAWC,CAAAA,CACT,miBACAH,CACF,CAAA,CACC,GAAGC,CAAAA,CACN,CAEJ","file":"chunk-7BOX7HHO.js","sourcesContent":["import * as React from 'react';\nimport { cn } from '../lib/utils';\n\nfunction Textarea({ className, ...props }: React.ComponentProps<'textarea'>) {\n return (\n <textarea\n data-slot=\"textarea\"\n className={cn(\n 'fk:flex fk:field-sizing-content fk:min-h-16 fk:w-full fk:rounded-md fk:border fk:border-input fk:bg-background fk:px-3 fk:py-2 fk:text-base fk:shadow-xs fk:transition-[color,box-shadow] fk:outline-none fk:placeholder:text-muted-foreground fk:focus-visible:border-ring fk:focus-visible:ring-[3px] fk:focus-visible:ring-ring/50 fk:disabled:cursor-not-allowed fk:disabled:opacity-50 fk:aria-invalid:border-destructive fk:aria-invalid:ring-destructive/20 fk:md:text-sm fk:dark:bg-input/30 fk:dark:aria-invalid:ring-destructive/40 fk:corner-squircle',\n className\n )}\n {...props}\n />\n );\n}\n\nexport { Textarea };\n"]}
@@ -1,2 +0,0 @@
1
- import'./index.css';import {b,c,e}from'./chunk-USNXQOMJ.js';import {a}from'./chunk-O2QMYUPS.js';import {useRef,useState,useEffect}from'react';import {Check,Copy}from'lucide-react';import {jsx,jsxs}from'react/jsx-runtime';var d=500,w=3e3;function O({value:t}){let a$1=useRef(null),n=useRef(null),[r,s]=useState(false),[b$1,i]=useState(false);useEffect(()=>()=>{n.current&&clearTimeout(n.current);},[]);function c$1(){let e=a$1.current;return e?e.scrollWidth>e.clientWidth:false}async function g(e){if(e.preventDefault(),e.stopPropagation(),!!t){try{await navigator.clipboard.writeText(t);}catch{return}s(true),i(true),n.current&&clearTimeout(n.current),n.current=setTimeout(()=>{s(false),i(false);},w);}}function y(){c$1();}function h(e){if(!r){if(e){i(c$1());return}i(false);}}if(!t)return jsx("div",{className:"fk:truncate"});let x=t.length>d?`${t.slice(0,d)}\u2026`:t;return jsxs(b,{open:b$1,onOpenChange:h,children:[jsx(c,{asChild:true,children:jsxs("button",{"aria-label":"Copy value",className:a("fk:group/copyable fk:relative fk:flex fk:w-full fk:min-w-0 fk:items-center fk:rounded-sm fk:border-0 fk:bg-transparent fk:px-0.5 fk:-mx-0.5 fk:py-0.5 fk:text-left fk:text-inherit fk:font-inherit fk:corner-squircle","fk:cursor-pointer fk:transition-[transform,background-color] fk:duration-75 fk:ease-out","fk:hover:bg-muted/50 fk:active:translate-y-px fk:active:scale-[0.98] fk:active:bg-muted/70","fk:focus-visible:outline-hidden fk:focus-visible:ring-1 fk:focus-visible:ring-ring"),onClick:g,onPointerEnter:y,type:"button",children:[jsx("span",{className:"fk:min-w-0 fk:flex-1 fk:truncate fk:pr-4",ref:a$1,children:t}),jsx("span",{"aria-hidden":true,className:a("fk:pointer-events-none fk:absolute fk:right-0.5 fk:top-1/2 fk:flex fk:-translate-y-1/2 fk:items-center fk:justify-center","fk:rounded-sm fk:bg-muted/80 fk:p-0.5 fk:text-muted-foreground fk:shadow-sm fk:ring-1 fk:ring-border/60 fk:corner-squircle","fk:transition-opacity fk:duration-100",r?"fk:opacity-100 fk:text-foreground":"fk:opacity-0 fk:group-hover/copyable:opacity-100 fk:group-focus-visible/copyable:opacity-100"),children:r?jsx(Check,{className:"fk:size-3"}):jsx(Copy,{className:"fk:size-3"})})]})}),jsx(e,{className:"fk:max-w-xs fk:wrap-break-word",children:r?"Copied to clipboard":x})]})}export{O as a};//# sourceMappingURL=chunk-7JFLGBWE.js.map
2
- //# sourceMappingURL=chunk-7JFLGBWE.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/data-grid/preview-components/copyable-truncated-text.tsx"],"names":["TOOLTIP_MAX_LENGTH","COPIED_DISMISS_MS","CopyableTruncatedText","value","textRef","useRef","dismissTimeoutRef","copied","setCopied","useState","tooltipOpen","setTooltipOpen","useEffect","measureTruncation","element","handleClick","event","handlePointerEnter","handleTooltipOpenChange","open","jsx","tooltipText","jsxs","Tooltip","TooltipTrigger","cn","CheckIcon","CopyIcon","TooltipContent"],"mappings":"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","file":"chunk-7JFLGBWE.js","sourcesContent":["'use client';\n\nimport { useEffect, useRef, useState } from 'react';\nimport type { JSX, MouseEvent } from 'react';\nimport { Check as CheckIcon, Copy as CopyIcon } from 'lucide-react';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../../ui/primitives/tooltip';\nimport { cn } from '../../ui/lib/utils';\n\nconst TOOLTIP_MAX_LENGTH = 500;\nconst COPIED_DISMISS_MS = 3000;\n\ntype CopyableTruncatedTextProps = {\n value: string;\n};\n\nexport function CopyableTruncatedText({ value }: CopyableTruncatedTextProps): JSX.Element {\n const textRef = useRef<HTMLSpanElement>(null);\n const dismissTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const [copied, setCopied] = useState(false);\n const [tooltipOpen, setTooltipOpen] = useState(false);\n\n useEffect(() => {\n return () => {\n if (dismissTimeoutRef.current) {\n clearTimeout(dismissTimeoutRef.current);\n }\n };\n }, []);\n\n function measureTruncation(): boolean {\n const element = textRef.current;\n\n if (!element) {\n return false;\n }\n\n return element.scrollWidth > element.clientWidth;\n }\n\n async function handleClick(event: MouseEvent<HTMLButtonElement>): Promise<void> {\n event.preventDefault();\n event.stopPropagation();\n\n if (!value) {\n return;\n }\n\n try {\n await navigator.clipboard.writeText(value);\n } catch {\n return;\n }\n\n setCopied(true);\n setTooltipOpen(true);\n\n if (dismissTimeoutRef.current) {\n clearTimeout(dismissTimeoutRef.current);\n }\n\n dismissTimeoutRef.current = setTimeout(() => {\n setCopied(false);\n setTooltipOpen(false);\n }, COPIED_DISMISS_MS);\n }\n\n function handlePointerEnter(): void {\n measureTruncation();\n }\n\n function handleTooltipOpenChange(open: boolean): void {\n if (copied) {\n return;\n }\n\n if (open) {\n setTooltipOpen(measureTruncation());\n\n return;\n }\n\n setTooltipOpen(false);\n }\n\n if (!value) {\n return <div className=\"fk:truncate\" />;\n }\n\n const tooltipText =\n value.length > TOOLTIP_MAX_LENGTH ? `${value.slice(0, TOOLTIP_MAX_LENGTH)}…` : value;\n\n return (\n <Tooltip open={tooltipOpen} onOpenChange={handleTooltipOpenChange}>\n <TooltipTrigger asChild>\n <button\n aria-label=\"Copy value\"\n className={cn(\n 'fk:group/copyable fk:relative fk:flex fk:w-full fk:min-w-0 fk:items-center fk:rounded-sm fk:border-0 fk:bg-transparent fk:px-0.5 fk:-mx-0.5 fk:py-0.5 fk:text-left fk:text-inherit fk:font-inherit fk:corner-squircle',\n 'fk:cursor-pointer fk:transition-[transform,background-color] fk:duration-75 fk:ease-out',\n 'fk:hover:bg-muted/50 fk:active:translate-y-px fk:active:scale-[0.98] fk:active:bg-muted/70',\n 'fk:focus-visible:outline-hidden fk:focus-visible:ring-1 fk:focus-visible:ring-ring'\n )}\n onClick={handleClick}\n onPointerEnter={handlePointerEnter}\n type=\"button\"\n >\n <span className=\"fk:min-w-0 fk:flex-1 fk:truncate fk:pr-4\" ref={textRef}>\n {value}\n </span>\n <span\n aria-hidden\n className={cn(\n 'fk:pointer-events-none fk:absolute fk:right-0.5 fk:top-1/2 fk:flex fk:-translate-y-1/2 fk:items-center fk:justify-center',\n 'fk:rounded-sm fk:bg-muted/80 fk:p-0.5 fk:text-muted-foreground fk:shadow-sm fk:ring-1 fk:ring-border/60 fk:corner-squircle',\n 'fk:transition-opacity fk:duration-100',\n copied\n ? 'fk:opacity-100 fk:text-foreground'\n : 'fk:opacity-0 fk:group-hover/copyable:opacity-100 fk:group-focus-visible/copyable:opacity-100'\n )}\n >\n {copied ? <CheckIcon className=\"fk:size-3\" /> : <CopyIcon className=\"fk:size-3\" />}\n </span>\n </button>\n </TooltipTrigger>\n <TooltipContent className=\"fk:max-w-xs fk:wrap-break-word\">\n {copied ? 'Copied to clipboard' : tooltipText}\n </TooltipContent>\n </Tooltip>\n );\n}\n"]}