@truefoundry/trueforge-ui 0.0.0 → 0.1.0-rc.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.
Files changed (55) hide show
  1. package/CHANGELOG.md +348 -0
  2. package/LICENSE +21 -0
  3. package/NOTICE +17 -0
  4. package/README.md +640 -3
  5. package/dist/ConnectorSettings-ADACLWQI.js +898 -0
  6. package/dist/ConnectorSettings-ADACLWQI.js.map +1 -0
  7. package/dist/DockLayout-BH5XX2AQ.js +35 -0
  8. package/dist/DockLayout-BH5XX2AQ.js.map +1 -0
  9. package/dist/DrawerLayout-O2XZQCG4.js +156 -0
  10. package/dist/DrawerLayout-O2XZQCG4.js.map +1 -0
  11. package/dist/ModelSettings-LKFJVUYQ.js +1082 -0
  12. package/dist/ModelSettings-LKFJVUYQ.js.map +1 -0
  13. package/dist/OpenUiFenceBlock-A2CWCPOP.js +9 -0
  14. package/dist/OpenUiFenceBlock-A2CWCPOP.js.map +1 -0
  15. package/dist/SandboxSettings-H5MDAE47.js +505 -0
  16. package/dist/SandboxSettings-H5MDAE47.js.map +1 -0
  17. package/dist/SettingsBuilder-3JOLC56Z.js +136 -0
  18. package/dist/SettingsBuilder-3JOLC56Z.js.map +1 -0
  19. package/dist/SidebarLayout-G6BGD7EY.js +236 -0
  20. package/dist/SidebarLayout-G6BGD7EY.js.map +1 -0
  21. package/dist/SkillSettings-4VB42CVG.js +389 -0
  22. package/dist/SkillSettings-4VB42CVG.js.map +1 -0
  23. package/dist/WidgetLayout-ABSXZUSQ.js +101 -0
  24. package/dist/WidgetLayout-ABSXZUSQ.js.map +1 -0
  25. package/dist/assistant-ui.d.ts +1 -0
  26. package/dist/assistant-ui.js +9 -0
  27. package/dist/assistant-ui.js.map +1 -0
  28. package/dist/chunk-3PTFNAQK.js +2088 -0
  29. package/dist/chunk-3PTFNAQK.js.map +1 -0
  30. package/dist/chunk-CFLVPV5M.js +29 -0
  31. package/dist/chunk-CFLVPV5M.js.map +1 -0
  32. package/dist/chunk-EFGSH3MO.js +89 -0
  33. package/dist/chunk-EFGSH3MO.js.map +1 -0
  34. package/dist/chunk-FDBJNXH2.js +24 -0
  35. package/dist/chunk-FDBJNXH2.js.map +1 -0
  36. package/dist/chunk-M6MHLVSO.js +8 -0
  37. package/dist/chunk-M6MHLVSO.js.map +1 -0
  38. package/dist/chunk-U5GBGEGN.js +788 -0
  39. package/dist/chunk-U5GBGEGN.js.map +1 -0
  40. package/dist/chunk-VJTCFZNM.js +73 -0
  41. package/dist/chunk-VJTCFZNM.js.map +1 -0
  42. package/dist/chunk-WMRZSULD.js +567 -0
  43. package/dist/chunk-WMRZSULD.js.map +1 -0
  44. package/dist/chunk-Z27F4LBZ.js +6719 -0
  45. package/dist/chunk-Z27F4LBZ.js.map +1 -0
  46. package/dist/createTrueFoundryServer-B72bU-J7.d.ts +28 -0
  47. package/dist/index.d.ts +1573 -0
  48. package/dist/index.js +781 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/plugins/trueforge-agent-server-adapter/index.d.ts +475 -0
  51. package/dist/plugins/trueforge-agent-server-adapter/index.js +851 -0
  52. package/dist/plugins/trueforge-agent-server-adapter/index.js.map +1 -0
  53. package/dist/styles.css +2 -0
  54. package/package.json +129 -6
  55. package/index.js +0 -1
@@ -0,0 +1,851 @@
1
+ import {
2
+ createTrueFoundryServer
3
+ } from "../../chunk-CFLVPV5M.js";
4
+
5
+ // src/plugins/trueforge-agent-server-adapter/catalogs/connectorCatalog.ts
6
+ var DEFAULT_API_KEY_HEADER = "Authorization";
7
+ function toUiAuthPublic(auth) {
8
+ if (auth === void 0) {
9
+ return { type: "none" };
10
+ }
11
+ if (auth.type === "dcr") {
12
+ return { type: "dcr" };
13
+ }
14
+ const headerName = Object.keys(auth.headers)[0];
15
+ return {
16
+ type: "header",
17
+ ...headerName === void 0 ? {} : { headerName }
18
+ };
19
+ }
20
+ function toHarnessAuth(auth) {
21
+ if (auth.type === "none") {
22
+ return void 0;
23
+ }
24
+ if (auth.type === "dcr") {
25
+ return { type: "dcr" };
26
+ }
27
+ const apiKey = auth.apiKey?.trim();
28
+ if (apiKey === void 0 || apiKey === "") {
29
+ throw new Error("API key is required for header-authenticated MCP servers");
30
+ }
31
+ const trimmedHeader = auth.headerName?.trim();
32
+ const headerName = trimmedHeader !== void 0 && trimmedHeader !== "" ? trimmedHeader : DEFAULT_API_KEY_HEADER;
33
+ return { type: "header", headers: { [headerName]: apiKey } };
34
+ }
35
+ function toUiCatalogEntry(server) {
36
+ return {
37
+ id: server.name,
38
+ name: server.name,
39
+ url: server.url,
40
+ description: server.description,
41
+ ...server.logo === void 0 ? {} : { logo: server.logo },
42
+ auth: toUiAuthPublic(server.auth)
43
+ };
44
+ }
45
+ function toUiTool(tool) {
46
+ const name = typeof tool.name === "string" && tool.name !== "" ? tool.name : "tool";
47
+ const description = typeof tool.description === "string" ? tool.description : "";
48
+ return { id: name, name, description };
49
+ }
50
+ function toUiConnector(server) {
51
+ const auth = toUiAuthPublic(server.manifest.auth);
52
+ return {
53
+ id: server.name,
54
+ name: server.name,
55
+ description: server.manifest.description,
56
+ url: server.manifest.url,
57
+ auth,
58
+ requiresAuth: server.authStatus.status === "auth_required",
59
+ authenticated: server.authStatus.status !== "auth_required"
60
+ };
61
+ }
62
+ function toUiConnectorFromReadEntry(server) {
63
+ const auth = server.auth?.type ? { type: server.auth.type } : { type: "none" };
64
+ return {
65
+ id: server.name,
66
+ name: server.name,
67
+ description: server.url,
68
+ url: server.url,
69
+ auth,
70
+ requiresAuth: server.authStatus.status === "auth_required",
71
+ authenticated: server.authStatus.status !== "auth_required"
72
+ };
73
+ }
74
+ function toHarnessManifest(req) {
75
+ const auth = toHarnessAuth(req.auth);
76
+ const trimmed = req.description?.trim();
77
+ return {
78
+ type: "remote",
79
+ name: req.name,
80
+ url: req.url,
81
+ description: trimmed !== void 0 && trimmed !== "" ? trimmed : `${req.name} MCP server`,
82
+ ...auth === void 0 ? {} : { auth }
83
+ };
84
+ }
85
+ function createConnectorCatalog(client) {
86
+ async function getConfigured(name) {
87
+ const listed = await client.settings.mcpServers.list();
88
+ const existing = listed.data.find((server) => server.name === name);
89
+ if (existing === void 0) {
90
+ throw new Error(`MCP server "${name}" not found`);
91
+ }
92
+ return existing;
93
+ }
94
+ async function resolveWriteAuth(req) {
95
+ if (req.auth.type !== "header") {
96
+ return req.auth;
97
+ }
98
+ const apiKey = req.auth.apiKey?.trim();
99
+ if (apiKey !== void 0 && apiKey !== "") {
100
+ return req.auth;
101
+ }
102
+ if (req.id === void 0) {
103
+ throw new Error("API key is required for header-authenticated MCP servers");
104
+ }
105
+ const existing = await getConfigured(req.id);
106
+ if (existing.manifest.auth?.type !== "header") {
107
+ throw new Error(`MCP server "${req.id}" has no stored header credentials to reuse`);
108
+ }
109
+ const preferredHeader = req.auth.headerName?.trim();
110
+ const storedHeaderName = Object.keys(existing.manifest.auth.headers)[0];
111
+ const headerName = preferredHeader !== void 0 && preferredHeader !== "" ? preferredHeader : storedHeaderName ?? DEFAULT_API_KEY_HEADER;
112
+ const stored = existing.manifest.auth.headers[headerName] ?? Object.values(existing.manifest.auth.headers)[0];
113
+ if (stored === void 0) {
114
+ throw new Error(`MCP server "${req.id}" has no stored header credentials to reuse`);
115
+ }
116
+ return { type: "header", apiKey: stored, headerName };
117
+ }
118
+ return {
119
+ getConnectorCatalog: async () => {
120
+ const body = await client.catalog.mcpServers.list();
121
+ return body.data.map(toUiCatalogEntry);
122
+ },
123
+ getConnector: async (req) => {
124
+ const body = await client.settings.mcpServers.get(req.id);
125
+ return toUiConnector(body.data);
126
+ },
127
+ listConnectors: async (req) => {
128
+ const body = await client.settings.mcpServers.list();
129
+ const connectors = body.data.map(toUiConnector);
130
+ const query = req?.query?.trim().toLowerCase();
131
+ if (query === void 0 || query === "") {
132
+ return connectors;
133
+ }
134
+ return connectors.filter(
135
+ (connector) => connector.name.toLowerCase().includes(query) || connector.description.toLowerCase().includes(query) || connector.url.toLowerCase().includes(query)
136
+ );
137
+ },
138
+ getToolsByConnectorId: async ({ id }) => {
139
+ const body = await client.settings.mcpServers.listTools(id);
140
+ return body.data.map(toUiTool);
141
+ },
142
+ createConnector: async (req) => {
143
+ const auth = await resolveWriteAuth({ auth: req.auth });
144
+ const catalog = await client.catalog.mcpServers.list();
145
+ const preset = catalog.data.find((server) => server.name === req.name);
146
+ const body = await client.settings.mcpServers.create({
147
+ manifest: toHarnessManifest({
148
+ name: req.name,
149
+ url: req.url,
150
+ auth,
151
+ description: preset?.description
152
+ })
153
+ });
154
+ return toUiConnector(body.data);
155
+ },
156
+ updateConnector: async (req) => {
157
+ const existing = await getConfigured(req.id);
158
+ const auth = await resolveWriteAuth({ id: req.id, auth: req.auth });
159
+ const body = await client.settings.mcpServers.upsert({
160
+ manifest: toHarnessManifest({
161
+ name: req.id,
162
+ url: req.url,
163
+ auth,
164
+ description: existing.manifest.description
165
+ })
166
+ });
167
+ return toUiConnector(body.data);
168
+ },
169
+ authenticateConnector: async (req) => {
170
+ const result = await client.mcpServers.authorize(
171
+ req.id,
172
+ req.redirectURL === void 0 ? {} : { redirectUrl: req.redirectURL }
173
+ );
174
+ return { status: result.status, authorization_endpoint: result.authorizationUrl };
175
+ },
176
+ disconnectConnector: async (req) => {
177
+ const existing = await getConfigured(req.id);
178
+ if (existing.manifest.auth?.type !== "dcr") {
179
+ throw new Error(`Disconnect is only supported for OAuth MCP servers`);
180
+ }
181
+ const body = await client.mcpServers.deleteAuthorize(req.id);
182
+ return toUiConnector(body.data);
183
+ }
184
+ };
185
+ }
186
+
187
+ // src/plugins/trueforge-agent-server-adapter/client.ts
188
+ import { TrueForge } from "@truefoundry/trueforge-sdk";
189
+ var DEFAULT_BASE_URL = "/";
190
+ function createTrueForgeClient(options = {}) {
191
+ return new TrueForge({
192
+ baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,
193
+ ...options.token === void 0 ? {} : { token: options.token },
194
+ ...options.fetch === void 0 ? {} : { fetch: options.fetch }
195
+ });
196
+ }
197
+
198
+ // src/plugins/trueforge-agent-server-adapter/chatServer.ts
199
+ function toUiMcpServer(server) {
200
+ return server;
201
+ }
202
+ function toUiSkill(skill) {
203
+ return { name: skill.name };
204
+ }
205
+ function toHarnessAgentSpec(spec) {
206
+ const { skills, mcpServers, ...rest } = spec;
207
+ return {
208
+ ...rest,
209
+ ...mcpServers === void 0 ? {} : {
210
+ mcpServers: mcpServers.map((server) => {
211
+ if ("id" in server) {
212
+ const { id, ...mount } = server;
213
+ void id;
214
+ return mount;
215
+ }
216
+ return server;
217
+ })
218
+ },
219
+ ...skills === void 0 ? {} : { skills: skills.map(({ name }) => ({ name })) }
220
+ };
221
+ }
222
+ function toUiAgentSpec(spec) {
223
+ const { mcpServers, skills, ...rest } = spec;
224
+ return {
225
+ ...rest,
226
+ ...mcpServers ? { mcpServers: mcpServers.map(toUiMcpServer) } : {},
227
+ ...skills ? { skills: skills.map(toUiSkill) } : {}
228
+ };
229
+ }
230
+ function toUiSession(session) {
231
+ return {
232
+ id: session.id,
233
+ isMutable: session.agent.type === "inline",
234
+ createdAt: session.createdAt,
235
+ updatedAt: session.updatedAt,
236
+ ...session.title === null ? {} : { title: session.title },
237
+ // `name` is a create-time snapshot, so references whose agent predates it stay
238
+ // unlabelled; `isMutable` alone keeps them out of the composer.
239
+ ...session.agent.type === "reference" && session.agent.name !== null ? { agentName: session.agent.name } : {},
240
+ ...session.agent.type === "inline" ? { agentSpec: toUiAgentSpec(session.agent.spec) } : {}
241
+ };
242
+ }
243
+ function toUiContent(content) {
244
+ return typeof content === "string" ? content : content.map((part) => ({ ...part }));
245
+ }
246
+ function toUiInput(input) {
247
+ return input.map((item) => item.type === "user.message" ? { ...item, content: toUiContent(item.content) } : item);
248
+ }
249
+ function toUiTurn(turn) {
250
+ const { previousTurnId, input, ...rest } = turn;
251
+ return {
252
+ ...rest,
253
+ ...previousTurnId === null ? {} : { previousTurnId },
254
+ ...input === void 0 ? {} : { input: toUiInput(input) }
255
+ };
256
+ }
257
+ function toUiEventItem(item) {
258
+ return { turnId: item.turnId, event: { ...item.event } };
259
+ }
260
+ function toListResult(page, map) {
261
+ const data = page.data.map(map);
262
+ const token = page.response.pagination.nextPageToken;
263
+ return {
264
+ data,
265
+ ...token === void 0 ? {} : { nextPageToken: token }
266
+ };
267
+ }
268
+ function sequenceNumber(id, fallback) {
269
+ if (id === void 0) return fallback;
270
+ const parsed = Number(id);
271
+ return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : fallback;
272
+ }
273
+ function toHarnessContent(content) {
274
+ if (typeof content === "string") return content;
275
+ return content.map((part) => {
276
+ if (part.type === "text") return part;
277
+ const { name, data } = part;
278
+ if (typeof name !== "string" || typeof data !== "string") {
279
+ throw new Error("File attachment must carry a string `name` and a data-URI `data`");
280
+ }
281
+ return { type: "file", name, data };
282
+ });
283
+ }
284
+ function toHarnessInput(input) {
285
+ return input.map(
286
+ (item) => item.type === "user.message" ? { ...item, content: toHarnessContent(item.content) } : item
287
+ );
288
+ }
289
+ function createHarnessChatServer(options = {}) {
290
+ const client = options.client ?? createTrueForgeClient(options);
291
+ return {
292
+ // The sandbox is resolved server-side from the turn, so `sandboxId` is accepted for parity
293
+ // with hosts that address sandboxes directly and deliberately not forwarded.
294
+ async downloadSandboxFile({ sessionId, turnId, path }) {
295
+ const response = await client.sessions.downloadSandboxFile(sessionId, turnId, { path });
296
+ return response.blob();
297
+ },
298
+ async createSession(request) {
299
+ if (request.agentName !== void 0 && request.agentName.length > 0) {
300
+ const created = await client.sessions.create({
301
+ agent: { name: request.agentName }
302
+ });
303
+ return toUiSession(created.data);
304
+ }
305
+ if (request.agentSpec !== void 0) {
306
+ const created = await client.sessions.create({
307
+ agent: { spec: toHarnessAgentSpec(request.agentSpec) }
308
+ });
309
+ return toUiSession(created.data);
310
+ }
311
+ throw new Error("createSession requires agentName or agentSpec");
312
+ },
313
+ async listSessions(request = {}) {
314
+ const page = await client.sessions.list({
315
+ ...request.limit === void 0 ? {} : { limit: request.limit },
316
+ ...request.order === void 0 ? {} : { order: request.order },
317
+ ...request.pageToken === void 0 ? {} : { pageToken: request.pageToken },
318
+ ...request.agentId === void 0 || request.agentId.length === 0 ? {} : { agentId: request.agentId }
319
+ });
320
+ return toListResult(page, toUiSession);
321
+ },
322
+ async getSession({ sessionId }) {
323
+ const response = await client.sessions.get(sessionId);
324
+ return toUiSession(response.data);
325
+ },
326
+ async updateSession({ sessionId, agentSpec }) {
327
+ const response = await client.sessions.update(sessionId, {
328
+ ...agentSpec === void 0 ? {} : { agent: { spec: toHarnessAgentSpec(agentSpec) } }
329
+ });
330
+ return toUiSession(response.data);
331
+ },
332
+ async *createTurn({
333
+ sessionId,
334
+ input,
335
+ previousTurnId
336
+ }) {
337
+ const stream = await client.sessions.createTurnStream(sessionId, {
338
+ ...input === void 0 ? {} : { input: toHarnessInput(input) },
339
+ ...previousTurnId === void 0 ? {} : { previousTurnId }
340
+ });
341
+ let fallbackSequence = 0;
342
+ for await (const item of stream.withMetadata()) {
343
+ yield {
344
+ sequenceNumber: sequenceNumber(item.id, fallbackSequence),
345
+ event: { ...item.data }
346
+ };
347
+ fallbackSequence += 1;
348
+ }
349
+ },
350
+ /** Resume a live turn; omitted/0 `afterSequenceNumber` replays from the start. */
351
+ async *subscribeToTurn({
352
+ sessionId,
353
+ turnId,
354
+ afterSequenceNumber
355
+ }) {
356
+ const stream = await client.sessions.subscribeToTurn(sessionId, turnId, {
357
+ ...afterSequenceNumber === void 0 ? {} : { afterSequenceNumber }
358
+ });
359
+ let fallbackSequence = 0;
360
+ for await (const item of stream.withMetadata()) {
361
+ yield {
362
+ sequenceNumber: sequenceNumber(item.id, fallbackSequence),
363
+ event: { ...item.data }
364
+ };
365
+ fallbackSequence += 1;
366
+ }
367
+ },
368
+ async cancelSession({ sessionId }) {
369
+ await client.sessions.cancel(sessionId);
370
+ },
371
+ async listTurns({ sessionId, limit, pageToken }) {
372
+ const page = await client.sessions.listTurns(sessionId, {
373
+ ...limit === void 0 ? {} : { limit },
374
+ ...pageToken === void 0 ? {} : { pageToken }
375
+ });
376
+ return toListResult(page, toUiTurn);
377
+ },
378
+ async getTurn({ sessionId, turnId }) {
379
+ const response = await client.sessions.getTurn(sessionId, turnId);
380
+ return toUiTurn(response.data);
381
+ },
382
+ async listEvents({ sessionId, pageToken, lastTurnId, limit }) {
383
+ const page = await client.sessions.listEvents(sessionId, {
384
+ ...pageToken === void 0 ? {} : { pageToken },
385
+ ...lastTurnId === void 0 ? {} : { lastTurnId },
386
+ ...limit === void 0 ? {} : { limit }
387
+ });
388
+ return toListResult(page, toUiEventItem);
389
+ }
390
+ };
391
+ }
392
+
393
+ // src/plugins/trueforge-agent-server-adapter/lists.ts
394
+ async function listModels(client) {
395
+ const body = await client.models.list();
396
+ return body.data;
397
+ }
398
+ async function listConfiguredMcpServers(client) {
399
+ const body = await client.mcpServers.list();
400
+ return body.data;
401
+ }
402
+ async function listSkills(client) {
403
+ const body = await client.skills.list();
404
+ return body.data;
405
+ }
406
+ async function getCapabilities(client) {
407
+ const body = await client.server.getCapabilities();
408
+ return body.data;
409
+ }
410
+
411
+ // src/plugins/trueforge-agent-server-adapter/builderServer.ts
412
+ function modelProviderLogosByName(catalog) {
413
+ const logos = /* @__PURE__ */ new Map();
414
+ for (const entry of catalog) {
415
+ if (entry.type === "custom" || entry.logo === void 0) {
416
+ continue;
417
+ }
418
+ logos.set(entry.type, entry.logo);
419
+ }
420
+ return logos;
421
+ }
422
+ function toModelSelection({ model, logo }) {
423
+ const efforts = model.properties.reasoningEfforts;
424
+ return {
425
+ id: model.modelId,
426
+ name: model.name,
427
+ provider: {
428
+ name: model.provider.name,
429
+ ...logo === void 0 ? {} : { logo }
430
+ },
431
+ properties: {
432
+ ...efforts !== void 0 && efforts.length > 0 ? { reasoningEfforts: [...efforts] } : {}
433
+ }
434
+ };
435
+ }
436
+ function toLibraryEntry(agent) {
437
+ return {
438
+ name: agent.name,
439
+ agentId: agent.id,
440
+ agentSpec: toUiAgentSpec(agent.manifest)
441
+ };
442
+ }
443
+ function createHarnessBuilderServer(options = {}) {
444
+ const client = options.client ?? createTrueForgeClient(options);
445
+ return {
446
+ getCapabilities: () => client.server.getCapabilities(),
447
+ getModels: async () => {
448
+ const [modelsBody, catalogEntries] = await Promise.all([
449
+ client.models.list(),
450
+ client.catalog.modelProviders.list().then(
451
+ (body) => body.data,
452
+ () => []
453
+ )
454
+ ]);
455
+ const logosByName = modelProviderLogosByName(catalogEntries);
456
+ return modelsBody.data.map((model) => {
457
+ const logo = logosByName.get(model.provider.name);
458
+ return toModelSelection(logo === void 0 ? { model } : { model, logo });
459
+ });
460
+ },
461
+ // Skills require a configured sandbox provider; keep the picker empty when skill capability is off.
462
+ getSkills: async () => {
463
+ const skills = await listSkills(client);
464
+ return skills.map((skill) => ({ id: skill.name, name: skill.name, description: skill.description }));
465
+ },
466
+ getMcp: async () => (await listConfiguredMcpServers(client)).map(toUiConnectorFromReadEntry),
467
+ async searchAgents(req) {
468
+ const { data } = await client.agents.list();
469
+ const query = req?.query?.trim().toLowerCase();
470
+ const filtered = query === void 0 || query === "" ? data : data.filter((agent) => agent.name.toLowerCase().includes(query));
471
+ const offset = req?.offset ?? 0;
472
+ const limit = req?.limit ?? 50;
473
+ return filtered.slice(offset, offset + limit).map(toLibraryEntry);
474
+ },
475
+ async saveAgent({ agentName, agentSpec, intent }) {
476
+ const manifest = toHarnessAgentSpec(agentSpec);
477
+ if (intent === "update") {
478
+ const { data } = await client.agents.list();
479
+ const existing = data.find((agent) => agent.name === agentName);
480
+ if (!existing) {
481
+ return {};
482
+ }
483
+ await client.agents.update(existing.id, { manifest });
484
+ return { agentId: existing.id };
485
+ }
486
+ const created = await client.agents.create({ name: agentName, manifest });
487
+ return { agentId: created.data.id };
488
+ }
489
+ };
490
+ }
491
+
492
+ // src/plugins/trueforge-agent-server-adapter/catalogs/modelProviderCatalog.ts
493
+ import { TrueForgeApi } from "@truefoundry/trueforge-sdk";
494
+ function toUiModelEntry(model) {
495
+ return {
496
+ id: model.modelId,
497
+ name: model.name,
498
+ properties: model.properties
499
+ };
500
+ }
501
+ function toHarnessModelEntry(model) {
502
+ return {
503
+ modelId: model.id,
504
+ name: model.name,
505
+ properties: model.properties ?? {}
506
+ };
507
+ }
508
+ function toUiModelProvider(provider) {
509
+ const { name, manifest } = provider;
510
+ return {
511
+ id: name,
512
+ type: manifest.type,
513
+ name,
514
+ ...manifest.baseUrl === void 0 ? {} : { baseUrl: manifest.baseUrl },
515
+ models: manifest.models.map(toUiModelEntry)
516
+ };
517
+ }
518
+ function toUiCatalogModelProviderEntry(provider) {
519
+ if (provider.type === "custom") {
520
+ return {
521
+ type: provider.type,
522
+ name: provider.type,
523
+ supportedReasoningEfforts: provider.supportedReasoningEfforts,
524
+ models: []
525
+ };
526
+ }
527
+ return {
528
+ type: provider.type,
529
+ name: provider.type,
530
+ ...provider.logo === void 0 ? {} : { logo: provider.logo },
531
+ models: provider.models.map(toUiModelEntry)
532
+ };
533
+ }
534
+ var PROVIDER_TYPES = [...Object.values(TrueForgeApi.CatalogWellKnownModelProviderType), "custom"];
535
+ function isProviderType(type) {
536
+ return PROVIDER_TYPES.includes(type);
537
+ }
538
+ function toHarnessModelProvider(req) {
539
+ const models = req.models.map(toHarnessModelEntry);
540
+ if (!isProviderType(req.type)) {
541
+ throw new Error(`Unsupported model provider type: ${req.type}`);
542
+ }
543
+ const baseUrl = req.baseUrl?.trim() === "" ? void 0 : req.baseUrl;
544
+ if (req.type === "custom") {
545
+ if (baseUrl === void 0) {
546
+ throw new Error(`Model providers of type "${req.type}" require a base URL`);
547
+ }
548
+ return {
549
+ type: req.type,
550
+ name: req.name,
551
+ models,
552
+ baseUrl,
553
+ ...req.apiKey === "" ? {} : { auth: { apiKey: req.apiKey } }
554
+ };
555
+ }
556
+ const auth = { apiKey: req.apiKey };
557
+ if (baseUrl !== void 0) {
558
+ return { type: req.type, auth, models, baseUrl };
559
+ }
560
+ return { type: req.type, auth, models };
561
+ }
562
+ function createModelProviderCatalog(client) {
563
+ async function resolveApiKey(req) {
564
+ const trimmed = req.apiKey.trim();
565
+ if (trimmed !== "") {
566
+ return trimmed;
567
+ }
568
+ if (req.id === void 0) {
569
+ if (req.type === "custom") {
570
+ return "";
571
+ }
572
+ throw new Error("API key is required");
573
+ }
574
+ const listed = await client.settings.modelProviders.list();
575
+ const existing = listed.data.find((provider) => provider.name === req.id);
576
+ if (existing === void 0) {
577
+ throw new Error(`Model provider "${req.id}" not found`);
578
+ }
579
+ return existing.manifest.auth?.apiKey ?? "";
580
+ }
581
+ return {
582
+ getModelProviderCatalog: async () => {
583
+ const body = await client.catalog.modelProviders.list();
584
+ return body.data.map(toUiCatalogModelProviderEntry);
585
+ },
586
+ listModelProviders: async () => {
587
+ const body = await client.settings.modelProviders.list();
588
+ return body.data.map(toUiModelProvider);
589
+ },
590
+ createModelProvider: async (req) => {
591
+ const apiKey = await resolveApiKey({ type: req.type, apiKey: req.apiKey });
592
+ const body = await client.settings.modelProviders.create({
593
+ manifest: toHarnessModelProvider({
594
+ type: req.type,
595
+ name: req.name,
596
+ apiKey,
597
+ ...req.baseUrl === void 0 ? {} : { baseUrl: req.baseUrl },
598
+ models: req.models
599
+ })
600
+ });
601
+ return toUiModelProvider(body.data);
602
+ },
603
+ updateModelProvider: async (req) => {
604
+ const apiKey = await resolveApiKey({ id: req.id, type: req.type, apiKey: req.apiKey });
605
+ const body = await client.settings.modelProviders.upsert({
606
+ manifest: toHarnessModelProvider({
607
+ type: req.type,
608
+ name: req.id,
609
+ apiKey,
610
+ ...req.baseUrl === void 0 ? {} : { baseUrl: req.baseUrl },
611
+ models: req.models
612
+ })
613
+ });
614
+ return toUiModelProvider(body.data);
615
+ }
616
+ };
617
+ }
618
+
619
+ // src/plugins/trueforge-agent-server-adapter/catalogs/sandboxProviderCatalog.ts
620
+ import { TrueForgeApi as TrueForgeApi2 } from "@truefoundry/trueforge-sdk";
621
+ var DAYTONA_TYPE = "daytona";
622
+ var DAYTONA_DISPLAY_NAME = "Daytona";
623
+ function displayNameForType(type) {
624
+ if (type === DAYTONA_TYPE) {
625
+ return DAYTONA_DISPLAY_NAME;
626
+ }
627
+ return type;
628
+ }
629
+ function configFromHarness(provider) {
630
+ return {
631
+ // Snapshot/image is now release-owned; the field is gone from the backend. The external
632
+ // SandboxProviderConfig still requires it, so send an empty placeholder until that type drops it.
633
+ snapshotName: "",
634
+ execTimeoutMs: provider.execTimeoutMs,
635
+ autoStopIntervalInMinutes: provider.autoStopIntervalInMinutes,
636
+ autoArchiveIntervalInMinutes: provider.autoArchiveIntervalInMinutes,
637
+ autoDeleteIntervalInMinutes: provider.autoDeleteIntervalInMinutes
638
+ };
639
+ }
640
+ function toUiCatalogEntry2(provider) {
641
+ return {
642
+ id: provider.type,
643
+ name: displayNameForType(provider.type),
644
+ type: provider.type,
645
+ ...configFromHarness(provider)
646
+ };
647
+ }
648
+ function toUiSandboxProvider(provider) {
649
+ return {
650
+ id: provider.type,
651
+ name: displayNameForType(provider.type),
652
+ catalogId: provider.type,
653
+ isConnected: true,
654
+ ...configFromHarness(provider)
655
+ };
656
+ }
657
+ function toHarnessManifest2(req) {
658
+ if (req.type !== DAYTONA_TYPE) {
659
+ throw new Error(`Unsupported sandbox provider type: ${req.type}`);
660
+ }
661
+ return {
662
+ type: DAYTONA_TYPE,
663
+ execTimeoutMs: req.execTimeoutMs,
664
+ autoStopIntervalInMinutes: req.autoStopIntervalInMinutes,
665
+ autoArchiveIntervalInMinutes: req.autoArchiveIntervalInMinutes,
666
+ autoDeleteIntervalInMinutes: req.autoDeleteIntervalInMinutes,
667
+ auth: { apiKey: req.apiKey }
668
+ };
669
+ }
670
+ function createSandboxProviderCatalog(client) {
671
+ async function resolveApiKey(apiKey) {
672
+ const trimmed = apiKey?.trim();
673
+ if (trimmed !== void 0 && trimmed !== "") {
674
+ return trimmed;
675
+ }
676
+ const existing = await client.settings.sandboxProviders.get();
677
+ return existing.data.manifest.auth.apiKey;
678
+ }
679
+ return {
680
+ getSandboxProviderCatalog: async () => {
681
+ const body = await client.catalog.sandboxProviders.list();
682
+ return body.data.map(toUiCatalogEntry2);
683
+ },
684
+ listSandboxProviders: async (req) => {
685
+ let providers;
686
+ try {
687
+ const body = await client.settings.sandboxProviders.get();
688
+ providers = [toUiSandboxProvider(body.data.manifest)];
689
+ } catch (err) {
690
+ if (err instanceof TrueForgeApi2.NotFoundError) {
691
+ providers = [];
692
+ } else {
693
+ throw err;
694
+ }
695
+ }
696
+ const query = req?.query?.trim().toLowerCase();
697
+ if (query === void 0 || query === "") {
698
+ return providers;
699
+ }
700
+ return providers.filter(
701
+ (provider) => provider.name.toLowerCase().includes(query) || provider.id.toLowerCase().includes(query)
702
+ );
703
+ },
704
+ createSandboxProvider: async (req) => {
705
+ const body = await client.settings.sandboxProviders.upsert({
706
+ manifest: toHarnessManifest2({
707
+ type: req.type,
708
+ apiKey: req.apiKey,
709
+ execTimeoutMs: req.execTimeoutMs,
710
+ autoStopIntervalInMinutes: req.autoStopIntervalInMinutes,
711
+ autoArchiveIntervalInMinutes: req.autoArchiveIntervalInMinutes,
712
+ autoDeleteIntervalInMinutes: req.autoDeleteIntervalInMinutes
713
+ })
714
+ });
715
+ return toUiSandboxProvider(body.data.manifest);
716
+ },
717
+ updateSandboxProvider: async (req) => {
718
+ const apiKey = await resolveApiKey(req.apiKey);
719
+ const body = await client.settings.sandboxProviders.upsert({
720
+ manifest: toHarnessManifest2({
721
+ type: DAYTONA_TYPE,
722
+ apiKey,
723
+ execTimeoutMs: req.execTimeoutMs,
724
+ autoStopIntervalInMinutes: req.autoStopIntervalInMinutes,
725
+ autoArchiveIntervalInMinutes: req.autoArchiveIntervalInMinutes,
726
+ autoDeleteIntervalInMinutes: req.autoDeleteIntervalInMinutes
727
+ })
728
+ });
729
+ return toUiSandboxProvider(body.data.manifest);
730
+ }
731
+ };
732
+ }
733
+
734
+ // src/plugins/trueforge-agent-server-adapter/catalogs/skillCatalog.ts
735
+ function toUiCatalogEntry3(skill) {
736
+ return {
737
+ id: skill.name,
738
+ name: skill.name,
739
+ description: skill.description,
740
+ repoURL: skill.url,
741
+ path: skill.path ?? "",
742
+ ref: skill.ref
743
+ };
744
+ }
745
+ function toHarnessManifest3(req) {
746
+ const path = req.path.trim();
747
+ return {
748
+ type: "git",
749
+ name: req.name,
750
+ url: req.repoURL,
751
+ ...path === "" ? {} : { path },
752
+ ref: req.ref,
753
+ description: req.description
754
+ };
755
+ }
756
+ function toUiSkill2(skill, catalogNames) {
757
+ const base = {
758
+ id: skill.name,
759
+ name: skill.name,
760
+ description: skill.manifest.description
761
+ };
762
+ if (catalogNames.has(skill.name)) {
763
+ return { ...base, catalogId: skill.name };
764
+ }
765
+ return base;
766
+ }
767
+ function createSkillCatalog(client) {
768
+ return {
769
+ getSkillCatalog: async () => {
770
+ const body = await client.catalog.skills.list();
771
+ return body.data.map(toUiCatalogEntry3);
772
+ },
773
+ listSkills: async (req) => {
774
+ const [listed, catalog] = await Promise.all([client.settings.skills.list(), client.catalog.skills.list()]);
775
+ const catalogNames = new Set(catalog.data.map((entry) => entry.name));
776
+ const skills = listed.data.map((skill) => toUiSkill2(skill, catalogNames));
777
+ const query = req?.query?.trim().toLowerCase();
778
+ if (query === void 0 || query === "") {
779
+ return skills;
780
+ }
781
+ return skills.filter(
782
+ (skill) => skill.name.toLowerCase().includes(query) || skill.description.toLowerCase().includes(query)
783
+ );
784
+ },
785
+ createSkill: async (req) => {
786
+ const body = await client.settings.skills.create({ manifest: toHarnessManifest3(req) });
787
+ const catalogId = "catalogId" in req ? req.catalogId : void 0;
788
+ if (catalogId !== void 0) {
789
+ return {
790
+ id: body.data.name,
791
+ name: body.data.name,
792
+ description: body.data.manifest.description,
793
+ catalogId
794
+ };
795
+ }
796
+ return {
797
+ id: body.data.name,
798
+ name: body.data.name,
799
+ description: body.data.manifest.description
800
+ };
801
+ }
802
+ };
803
+ }
804
+
805
+ // src/plugins/trueforge-agent-server-adapter/index.ts
806
+ function createTrueForgeAgentUIServer(options = {}) {
807
+ const { catalog: catalogOverride, ...clientOptions } = options;
808
+ const client = createTrueForgeClient(clientOptions);
809
+ const catalog = catalogOverride ?? {
810
+ modelCatalog: createModelProviderCatalog(client),
811
+ connectorCatalog: createConnectorCatalog(client),
812
+ skillCatalog: createSkillCatalog(client),
813
+ sandboxCatalog: createSandboxProviderCatalog(client)
814
+ };
815
+ return createTrueFoundryServer({
816
+ chatServer: createHarnessChatServer({ client }),
817
+ ...createHarnessBuilderServer({ client }),
818
+ catalog
819
+ });
820
+ }
821
+ export {
822
+ configFromHarness,
823
+ createConnectorCatalog,
824
+ createHarnessBuilderServer,
825
+ createHarnessChatServer,
826
+ createModelProviderCatalog,
827
+ createSandboxProviderCatalog,
828
+ createSkillCatalog,
829
+ createTrueForgeAgentUIServer,
830
+ createTrueForgeClient,
831
+ getCapabilities,
832
+ listConfiguredMcpServers,
833
+ listModels,
834
+ listSkills,
835
+ modelProviderLogosByName,
836
+ toHarnessAgentSpec,
837
+ toHarnessAuth,
838
+ toHarnessManifest as toHarnessConnectorManifest,
839
+ toHarnessModelProvider,
840
+ toHarnessManifest2 as toHarnessSandboxManifest,
841
+ toHarnessManifest3 as toHarnessSkillManifest,
842
+ toModelSelection,
843
+ toUiAgentSpec,
844
+ toUiCatalogModelProviderEntry,
845
+ toUiConnector,
846
+ toUiConnectorFromReadEntry,
847
+ toUiModelProvider,
848
+ toUiSandboxProvider,
849
+ toUiSkill2 as toUiSkill
850
+ };
851
+ //# sourceMappingURL=index.js.map