@truefoundry/trueforge-ui 0.3.0-rc.0 → 0.3.0-rc.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +191 -0
- package/README.md +35 -12
- package/dist/AgentCodeSnippets-RJBB4DDE.js +89 -0
- package/dist/AgentCodeSnippets-RJBB4DDE.js.map +1 -0
- package/dist/AgentMetricChart-UPGSJ2WP.js +15 -0
- package/dist/AgentOverview-U5WIQXZN.js +169 -0
- package/dist/AgentOverview-U5WIQXZN.js.map +1 -0
- package/dist/AgentSessionEventTimeline-GRGIQTRE.js +88 -0
- package/dist/AgentSessionEventTimeline-GRGIQTRE.js.map +1 -0
- package/dist/AgentSessionEventTimelineChart-GNF4VOUT.js +591 -0
- package/dist/AgentSessionEventTimelineChart-GNF4VOUT.js.map +1 -0
- package/dist/AgentSessions-5OTF2BUW.js +323 -0
- package/dist/AgentSessions-5OTF2BUW.js.map +1 -0
- package/dist/{ConnectorSettings-FXQ5B7TN.js → ConnectorSettings-HDKGLDCY.js} +163 -125
- package/dist/ConnectorSettings-HDKGLDCY.js.map +1 -0
- package/dist/{DockLayout-LBNQJZNF.js → DockLayout-D2FPQCAL.js} +11 -10
- package/dist/{DockLayout-LBNQJZNF.js.map → DockLayout-D2FPQCAL.js.map} +1 -1
- package/dist/DrawerLayout-HUV7RAWL.js +186 -0
- package/dist/DrawerLayout-HUV7RAWL.js.map +1 -0
- package/dist/{ModelSettings-4L4LOQJA.js → ModelSettings-VNQ7HPKH.js} +23 -27
- package/dist/ModelSettings-VNQ7HPKH.js.map +1 -0
- package/dist/OpenUiFenceBlock-KPZFLUSC.js +9 -0
- package/dist/OpenUiFenceBlock-KPZFLUSC.js.map +1 -0
- package/dist/{SandboxSettings-Z4ZG6ZX4.js → SandboxSettings-ZLXGMFBF.js} +18 -20
- package/dist/SandboxSettings-ZLXGMFBF.js.map +1 -0
- package/dist/SchedulesPage-QKYI2Z3A.js +15 -0
- package/dist/SchedulesPage-QKYI2Z3A.js.map +1 -0
- package/dist/{SettingsBuilder-WF7ZWKQW.js → SettingsBuilder-RVVYXOJW.js} +27 -23
- package/dist/SettingsBuilder-RVVYXOJW.js.map +1 -0
- package/dist/ShellRouteSync-SJXFKUAJ.js +390 -0
- package/dist/ShellRouteSync-SJXFKUAJ.js.map +1 -0
- package/dist/SidebarLayout-KYA76FQ7.js +330 -0
- package/dist/SidebarLayout-KYA76FQ7.js.map +1 -0
- package/dist/{SkillSettings-3EPPC3IT.js → SkillSettings-7OHT7FPI.js} +25 -21
- package/dist/SkillSettings-7OHT7FPI.js.map +1 -0
- package/dist/{TrueForgeUIWithRouter-NZ4FGPE4.js → TrueForgeUIWithRouter-LKG4XLW6.js} +14 -10
- package/dist/{TrueForgeUIWithRouter-NZ4FGPE4.js.map → TrueForgeUIWithRouter-LKG4XLW6.js.map} +1 -1
- package/dist/{WidgetLayout-3QZ357FL.js → WidgetLayout-W2RGGOQ3.js} +17 -13
- package/dist/WidgetLayout-W2RGGOQ3.js.map +1 -0
- package/dist/chunk-2GIZY3JJ.js +1062 -0
- package/dist/chunk-2GIZY3JJ.js.map +1 -0
- package/dist/chunk-2QTH6JHX.js +217 -0
- package/dist/chunk-2QTH6JHX.js.map +1 -0
- package/dist/{chunk-FJ5RSSMA.js → chunk-3ZW74FHC.js} +118 -164
- package/dist/chunk-3ZW74FHC.js.map +1 -0
- package/dist/chunk-67ZO7Z2W.js +184 -0
- package/dist/chunk-67ZO7Z2W.js.map +1 -0
- package/dist/{chunk-CFLVPV5M.js → chunk-7AAO4UDQ.js} +8 -2
- package/dist/chunk-7AAO4UDQ.js.map +1 -0
- package/dist/{chunk-B52K63AW.js → chunk-CG75X77Q.js} +2 -2
- package/dist/chunk-DJUFS2BW.js +27 -0
- package/dist/chunk-DJUFS2BW.js.map +1 -0
- package/dist/chunk-DPPOEFBD.js +517 -0
- package/dist/chunk-DPPOEFBD.js.map +1 -0
- package/dist/chunk-EPAL2HD5.js +1629 -0
- package/dist/chunk-EPAL2HD5.js.map +1 -0
- package/dist/chunk-GG23N2GW.js +15018 -0
- package/dist/chunk-GG23N2GW.js.map +1 -0
- package/dist/chunk-JCL3Q7RW.js +587 -0
- package/dist/chunk-JCL3Q7RW.js.map +1 -0
- package/dist/chunk-JKEBMGLH.js +682 -0
- package/dist/chunk-JKEBMGLH.js.map +1 -0
- package/dist/chunk-KSGNKS2D.js +296 -0
- package/dist/chunk-KSGNKS2D.js.map +1 -0
- package/dist/{chunk-WREC7D54.js → chunk-PCI6VMB5.js} +268 -48
- package/dist/chunk-PCI6VMB5.js.map +1 -0
- package/dist/chunk-PQ7VWBQQ.js +121 -0
- package/dist/chunk-PQ7VWBQQ.js.map +1 -0
- package/dist/chunk-RDXBMTP5.js +32 -0
- package/dist/chunk-RDXBMTP5.js.map +1 -0
- package/dist/chunk-T6QQV5LK.js +238 -0
- package/dist/chunk-T6QQV5LK.js.map +1 -0
- package/dist/chunk-Y6S4OVVQ.js +16 -0
- package/dist/chunk-Y6S4OVVQ.js.map +1 -0
- package/dist/{createTrueFoundryServer-B72bU-J7.d.ts → createTrueFoundryServer-B_FYhSdn.d.ts} +18 -4
- package/dist/index.d.ts +1287 -46
- package/dist/index.js +266 -63
- package/dist/index.js.map +1 -1
- package/dist/plugins/trueforge-agent-server-adapter/index.d.ts +590 -11
- package/dist/plugins/trueforge-agent-server-adapter/index.js +607 -204
- package/dist/plugins/trueforge-agent-server-adapter/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +10 -8
- package/dist/ConnectorSettings-FXQ5B7TN.js.map +0 -1
- package/dist/DrawerLayout-Q6UK4VMI.js +0 -159
- package/dist/DrawerLayout-Q6UK4VMI.js.map +0 -1
- package/dist/ModelSettings-4L4LOQJA.js.map +0 -1
- package/dist/OpenUiFenceBlock-6UIIAVBX.js +0 -9
- package/dist/SandboxSettings-Z4ZG6ZX4.js.map +0 -1
- package/dist/SettingsBuilder-WF7ZWKQW.js.map +0 -1
- package/dist/ShellRouteSync-T4WLY57Q.js +0 -172
- package/dist/ShellRouteSync-T4WLY57Q.js.map +0 -1
- package/dist/SidebarLayout-3WZ3CVON.js +0 -256
- package/dist/SidebarLayout-3WZ3CVON.js.map +0 -1
- package/dist/SkillSettings-3EPPC3IT.js.map +0 -1
- package/dist/WidgetLayout-3QZ357FL.js.map +0 -1
- package/dist/chunk-36KOSC2J.js +0 -567
- package/dist/chunk-36KOSC2J.js.map +0 -1
- package/dist/chunk-3S6KHO7H.js +0 -2121
- package/dist/chunk-3S6KHO7H.js.map +0 -1
- package/dist/chunk-7L63OK3O.js +0 -91
- package/dist/chunk-7L63OK3O.js.map +0 -1
- package/dist/chunk-CFLVPV5M.js.map +0 -1
- package/dist/chunk-FJ5RSSMA.js.map +0 -1
- package/dist/chunk-OSV3HI5M.js +0 -6891
- package/dist/chunk-OSV3HI5M.js.map +0 -1
- package/dist/chunk-WQULF5AT.js +0 -460
- package/dist/chunk-WQULF5AT.js.map +0 -1
- package/dist/chunk-WREC7D54.js.map +0 -1
- package/dist/chunk-YIWUG6MC.js +0 -101
- package/dist/chunk-YIWUG6MC.js.map +0 -1
- package/dist/chunk-ZXOADNF3.js +0 -75
- package/dist/chunk-ZXOADNF3.js.map +0 -1
- /package/dist/{OpenUiFenceBlock-6UIIAVBX.js.map → AgentMetricChart-UPGSJ2WP.js.map} +0 -0
- /package/dist/{chunk-B52K63AW.js.map → chunk-CG75X77Q.js.map} +0 -0
|
@@ -1,195 +1,111 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createTrueFoundryServer
|
|
3
|
-
} from "../../chunk-
|
|
3
|
+
} from "../../chunk-7AAO4UDQ.js";
|
|
4
|
+
import {
|
|
5
|
+
readSessionIsCreateAgent
|
|
6
|
+
} from "../../chunk-RDXBMTP5.js";
|
|
4
7
|
|
|
5
|
-
// src/plugins/trueforge-agent-server-adapter/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
if (
|
|
12
|
-
return
|
|
8
|
+
// src/plugins/trueforge-agent-server-adapter/client.ts
|
|
9
|
+
import { TrueForge } from "@truefoundry/trueforge-sdk";
|
|
10
|
+
var DEFAULT_BASE_URL = "/";
|
|
11
|
+
function resolveTrueForgeBaseUrl(baseUrl) {
|
|
12
|
+
if (/^https?:\/\//i.test(baseUrl)) return baseUrl;
|
|
13
|
+
const origin = globalThis.location?.origin;
|
|
14
|
+
if (typeof origin === "string" && origin.length > 0 && origin !== "null") {
|
|
15
|
+
return new URL(baseUrl, origin).href;
|
|
13
16
|
}
|
|
14
|
-
|
|
15
|
-
return {
|
|
16
|
-
type: "header",
|
|
17
|
-
...headerName === void 0 ? {} : { headerName }
|
|
18
|
-
};
|
|
17
|
+
return baseUrl;
|
|
19
18
|
}
|
|
20
|
-
function
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
};
|
|
19
|
+
function createTrueForgeClient(options = {}) {
|
|
20
|
+
return new TrueForge({
|
|
21
|
+
baseUrl: resolveTrueForgeBaseUrl(options.baseUrl ?? DEFAULT_BASE_URL),
|
|
22
|
+
...options.token === void 0 ? {} : { token: options.token },
|
|
23
|
+
...options.fetch === void 0 ? {} : { fetch: options.fetch }
|
|
24
|
+
});
|
|
84
25
|
}
|
|
85
|
-
function
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
if (existing === void 0) {
|
|
90
|
-
throw new Error(`MCP server "${name}" not found`);
|
|
91
|
-
}
|
|
92
|
-
return existing;
|
|
26
|
+
function parseIsoDate(value) {
|
|
27
|
+
const date = new Date(value);
|
|
28
|
+
if (Number.isNaN(date.getTime())) {
|
|
29
|
+
throw new Error(`Invalid ISO timestamp: ${value}`);
|
|
93
30
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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 };
|
|
31
|
+
return date;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// src/plugins/trueforge-agent-server-adapter/agentMetricsServer.ts
|
|
35
|
+
function toHarnessChartName(name) {
|
|
36
|
+
if (name === "sessions_over_time" || name === "sessions_cost_over_time" || name === "turns_over_time") {
|
|
37
|
+
return name;
|
|
117
38
|
}
|
|
39
|
+
throw new Error(`Unsupported Harness metrics chart: ${name}`);
|
|
40
|
+
}
|
|
41
|
+
function createHarnessAgentMetricsServer(options = {}) {
|
|
42
|
+
const client = options.client ?? createTrueForgeClient(options);
|
|
118
43
|
return {
|
|
119
|
-
|
|
120
|
-
const
|
|
121
|
-
return
|
|
44
|
+
async getCharts() {
|
|
45
|
+
const { data } = await client.internal.metrics.listCharts();
|
|
46
|
+
return data.charts;
|
|
122
47
|
},
|
|
123
|
-
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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.mcpServers.listTools(id);
|
|
140
|
-
return body.data.map(toUiTool);
|
|
141
|
-
},
|
|
142
|
-
createConnector: async (req) => {
|
|
143
|
-
const auth = await resolveWriteAuth({ auth: req.auth });
|
|
144
|
-
const body = await client.settings.mcpServers.create({
|
|
145
|
-
manifest: toHarnessManifest({
|
|
146
|
-
name: req.name,
|
|
147
|
-
url: req.url,
|
|
148
|
-
auth,
|
|
149
|
-
description: req.description
|
|
150
|
-
})
|
|
48
|
+
async getMeters({ agentId, startTimestamp, endTimestamp }) {
|
|
49
|
+
const { data } = await client.internal.metrics.getMeters({
|
|
50
|
+
agentId,
|
|
51
|
+
startTimestamp: parseIsoDate(startTimestamp),
|
|
52
|
+
endTimestamp: parseIsoDate(endTimestamp)
|
|
151
53
|
});
|
|
152
|
-
return
|
|
54
|
+
return data.meters;
|
|
153
55
|
},
|
|
154
|
-
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
auth,
|
|
161
|
-
description: req.description
|
|
162
|
-
})
|
|
56
|
+
async getChartData({ agentId, startTimestamp, endTimestamp, chartName }) {
|
|
57
|
+
const { data } = await client.internal.metrics.getChartData({
|
|
58
|
+
agentId,
|
|
59
|
+
startTimestamp: parseIsoDate(startTimestamp),
|
|
60
|
+
endTimestamp: parseIsoDate(endTimestamp),
|
|
61
|
+
chartName: toHarnessChartName(chartName)
|
|
163
62
|
});
|
|
164
|
-
return
|
|
165
|
-
},
|
|
166
|
-
authenticateConnector: async (req) => {
|
|
167
|
-
const result = await client.mcpServers.authorize(
|
|
168
|
-
req.id,
|
|
169
|
-
req.returnTo === void 0 ? {} : { returnTo: req.returnTo }
|
|
170
|
-
);
|
|
171
|
-
return { status: result.status, authorization_endpoint: result.authorizationUrl };
|
|
172
|
-
},
|
|
173
|
-
disconnectConnector: async (req) => {
|
|
174
|
-
const existing = await getConfigured(req.id);
|
|
175
|
-
if (existing.manifest.auth?.type !== "dcr") {
|
|
176
|
-
throw new Error(`Disconnect is only supported for OAuth MCP servers`);
|
|
177
|
-
}
|
|
178
|
-
const body = await client.mcpServers.deleteAuthorization(req.id);
|
|
179
|
-
return toUiConnector(body.data);
|
|
63
|
+
return data;
|
|
180
64
|
}
|
|
181
65
|
};
|
|
182
66
|
}
|
|
183
67
|
|
|
184
|
-
// src/plugins/trueforge-agent-server-adapter/
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
68
|
+
// src/plugins/trueforge-agent-server-adapter/toUiTurnState.ts
|
|
69
|
+
function toUiTurnDoneMetrics(metrics) {
|
|
70
|
+
return {
|
|
71
|
+
totalInputTokens: metrics.totalInputTokens ?? 0,
|
|
72
|
+
totalOutputTokens: metrics.totalOutputTokens ?? 0,
|
|
73
|
+
totalTokens: metrics.totalTokens ?? 0,
|
|
74
|
+
totalCacheReadTokens: metrics.totalCacheReadTokens ?? 0,
|
|
75
|
+
totalCacheWriteTokens: metrics.totalCacheWriteTokens ?? 0,
|
|
76
|
+
totalReasoningTokens: metrics.totalReasoningTokens ?? 0,
|
|
77
|
+
...metrics.totalCostInUsd == null ? {} : { totalCostInUsd: metrics.totalCostInUsd }
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function toUiTurnState(state) {
|
|
81
|
+
return state.status === "running" ? { status: "running" } : toUiTerminalTurnState(state);
|
|
82
|
+
}
|
|
83
|
+
function toUiTerminalTurnState(state) {
|
|
84
|
+
switch (state.status) {
|
|
85
|
+
case "cancelled":
|
|
86
|
+
return { status: "cancelled", reason: state.reason, completedAt: state.completedAt };
|
|
87
|
+
case "error":
|
|
88
|
+
return { status: "error", message: state.message, completedAt: state.completedAt };
|
|
89
|
+
case "done":
|
|
90
|
+
return {
|
|
91
|
+
status: "done",
|
|
92
|
+
completedAt: state.completedAt,
|
|
93
|
+
requiredActions: state.requiredActions,
|
|
94
|
+
...state.output == null ? {} : { output: state.output },
|
|
95
|
+
...state.metrics == null ? {} : { metrics: toUiTurnDoneMetrics(state.metrics) }
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function toUiSessionEvent(event) {
|
|
100
|
+
if (event.type !== "turn.done") return { ...event };
|
|
101
|
+
return { ...event, state: toUiTerminalTurnState(event.state) };
|
|
102
|
+
}
|
|
103
|
+
function toUiStreamingEvent(event) {
|
|
104
|
+
if (event.type !== "turn.done") return { ...event };
|
|
105
|
+
return { ...event, state: toUiTerminalTurnState(event.state) };
|
|
106
|
+
}
|
|
107
|
+
function toUiEventItem(item) {
|
|
108
|
+
return { turnId: item.turnId, event: toUiSessionEvent(item.event) };
|
|
193
109
|
}
|
|
194
110
|
|
|
195
111
|
// src/plugins/trueforge-agent-server-adapter/chatServer.ts
|
|
@@ -197,7 +113,10 @@ function toUiMcpServer(server) {
|
|
|
197
113
|
return server;
|
|
198
114
|
}
|
|
199
115
|
function toUiSkill(skill) {
|
|
200
|
-
return { name: skill.name };
|
|
116
|
+
return { name: skill.name, preload: skill.preload === true };
|
|
117
|
+
}
|
|
118
|
+
function toHarnessSkill(skill) {
|
|
119
|
+
return { name: skill.id ?? skill.name, preload: skill.preload === true };
|
|
201
120
|
}
|
|
202
121
|
function toHarnessAgentSpec(spec) {
|
|
203
122
|
const { skills, mcpServers, ...rest } = spec;
|
|
@@ -213,7 +132,7 @@ function toHarnessAgentSpec(spec) {
|
|
|
213
132
|
return server;
|
|
214
133
|
})
|
|
215
134
|
},
|
|
216
|
-
...skills === void 0 ? {} : { skills: skills.map(
|
|
135
|
+
...skills === void 0 ? {} : { skills: skills.map(toHarnessSkill) }
|
|
217
136
|
};
|
|
218
137
|
}
|
|
219
138
|
function toUiAgentSpec(spec) {
|
|
@@ -228,6 +147,7 @@ function toUiSession(session) {
|
|
|
228
147
|
return {
|
|
229
148
|
id: session.id,
|
|
230
149
|
isMutable: session.agent.type === "inline",
|
|
150
|
+
isCreateAgent: readSessionIsCreateAgent(session.metadata),
|
|
231
151
|
createdAt: session.createdAt,
|
|
232
152
|
updatedAt: session.updatedAt,
|
|
233
153
|
...session.title === null ? {} : { title: session.title },
|
|
@@ -237,6 +157,10 @@ function toUiSession(session) {
|
|
|
237
157
|
...session.agent.type === "inline" ? { agentSpec: toUiAgentSpec(session.agent.spec) } : {}
|
|
238
158
|
};
|
|
239
159
|
}
|
|
160
|
+
function createSessionMetadata(request) {
|
|
161
|
+
if (request.metadata === void 0) return void 0;
|
|
162
|
+
return request.metadata;
|
|
163
|
+
}
|
|
240
164
|
function toUiContent(content) {
|
|
241
165
|
return typeof content === "string" ? content : content.map((part) => ({ ...part }));
|
|
242
166
|
}
|
|
@@ -244,16 +168,14 @@ function toUiInput(input) {
|
|
|
244
168
|
return input.map((item) => item.type === "user.message" ? { ...item, content: toUiContent(item.content) } : item);
|
|
245
169
|
}
|
|
246
170
|
function toUiTurn(turn) {
|
|
247
|
-
const { previousTurnId, input, ...rest } = turn;
|
|
171
|
+
const { previousTurnId, input, state, ...rest } = turn;
|
|
248
172
|
return {
|
|
249
173
|
...rest,
|
|
174
|
+
state: toUiTurnState(state),
|
|
250
175
|
...previousTurnId === null ? {} : { previousTurnId },
|
|
251
176
|
...input === void 0 ? {} : { input: toUiInput(input) }
|
|
252
177
|
};
|
|
253
178
|
}
|
|
254
|
-
function toUiEventItem(item) {
|
|
255
|
-
return { turnId: item.turnId, event: { ...item.event } };
|
|
256
|
-
}
|
|
257
179
|
function toListResult(page, map) {
|
|
258
180
|
const data = page.data.map(map);
|
|
259
181
|
const token = page.response.pagination.nextPageToken;
|
|
@@ -293,15 +215,18 @@ function createHarnessChatServer(options = {}) {
|
|
|
293
215
|
return response.blob();
|
|
294
216
|
},
|
|
295
217
|
async createSession(request) {
|
|
218
|
+
const metadata = createSessionMetadata(request);
|
|
296
219
|
if (request.agentName !== void 0 && request.agentName.length > 0) {
|
|
297
220
|
const created = await client.sessions.create({
|
|
298
|
-
agent: { name: request.agentName }
|
|
221
|
+
agent: { name: request.agentName },
|
|
222
|
+
...metadata === void 0 ? {} : { metadata }
|
|
299
223
|
});
|
|
300
224
|
return toUiSession(created.data);
|
|
301
225
|
}
|
|
302
226
|
if (request.agentSpec !== void 0) {
|
|
303
227
|
const created = await client.sessions.create({
|
|
304
|
-
agent: { spec: toHarnessAgentSpec(request.agentSpec) }
|
|
228
|
+
agent: { spec: toHarnessAgentSpec(request.agentSpec) },
|
|
229
|
+
...metadata === void 0 ? {} : { metadata }
|
|
305
230
|
});
|
|
306
231
|
return toUiSession(created.data);
|
|
307
232
|
}
|
|
@@ -312,7 +237,8 @@ function createHarnessChatServer(options = {}) {
|
|
|
312
237
|
...request.limit === void 0 ? {} : { limit: request.limit },
|
|
313
238
|
...request.order === void 0 ? {} : { order: request.order },
|
|
314
239
|
...request.pageToken === void 0 ? {} : { pageToken: request.pageToken },
|
|
315
|
-
...request.agentId === void 0 || request.agentId.length === 0 ? {} : { agentId: request.agentId }
|
|
240
|
+
...request.agentId === void 0 || request.agentId.length === 0 ? {} : { agentId: request.agentId },
|
|
241
|
+
...request.createdByMe === void 0 ? {} : { createdByMe: request.createdByMe }
|
|
316
242
|
});
|
|
317
243
|
return toListResult(page, toUiSession);
|
|
318
244
|
},
|
|
@@ -342,7 +268,7 @@ function createHarnessChatServer(options = {}) {
|
|
|
342
268
|
for await (const item of stream.withMetadata()) {
|
|
343
269
|
yield {
|
|
344
270
|
sequenceNumber: sequenceNumber(item.id, fallbackSequence),
|
|
345
|
-
event:
|
|
271
|
+
event: toUiStreamingEvent(item.data)
|
|
346
272
|
};
|
|
347
273
|
fallbackSequence += 1;
|
|
348
274
|
}
|
|
@@ -360,7 +286,7 @@ function createHarnessChatServer(options = {}) {
|
|
|
360
286
|
for await (const item of stream.withMetadata()) {
|
|
361
287
|
yield {
|
|
362
288
|
sequenceNumber: sequenceNumber(item.id, fallbackSequence),
|
|
363
|
-
event:
|
|
289
|
+
event: toUiStreamingEvent(item.data)
|
|
364
290
|
};
|
|
365
291
|
fallbackSequence += 1;
|
|
366
292
|
}
|
|
@@ -390,6 +316,295 @@ function createHarnessChatServer(options = {}) {
|
|
|
390
316
|
};
|
|
391
317
|
}
|
|
392
318
|
|
|
319
|
+
// src/plugins/trueforge-agent-server-adapter/agentSessionsServer.ts
|
|
320
|
+
function toSessionListEntry(session) {
|
|
321
|
+
return {
|
|
322
|
+
id: session.id,
|
|
323
|
+
createdAt: session.createdAt,
|
|
324
|
+
updatedAt: session.updatedAt,
|
|
325
|
+
lastActivityAt: session.updatedAt,
|
|
326
|
+
isCreateAgent: readSessionIsCreateAgent(session.metadata),
|
|
327
|
+
isMutable: session.agent.type === "inline",
|
|
328
|
+
metrics: {
|
|
329
|
+
totalTurns: session.metrics.totalTurns,
|
|
330
|
+
...session.metrics.totalCostInUsd == null ? {} : { totalCostInUsd: session.metrics.totalCostInUsd },
|
|
331
|
+
totalDurationMs: session.metrics.totalDurationMs
|
|
332
|
+
},
|
|
333
|
+
...session.title === null ? {} : { title: session.title },
|
|
334
|
+
...session.agent.type === "reference" && session.agent.name !== null ? { agentName: session.agent.name } : {},
|
|
335
|
+
...session.agent.type === "inline" ? { agentSpec: toUiAgentSpec(session.agent.spec) } : {},
|
|
336
|
+
...session.source?.type === "schedule" ? { sourceType: session.source.type } : {}
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
function createHarnessAgentSessionsServer(options = {}) {
|
|
340
|
+
const client = options.client ?? createTrueForgeClient(options);
|
|
341
|
+
return {
|
|
342
|
+
async getAgent({ agentId }) {
|
|
343
|
+
const { data } = await client.agents.get(agentId);
|
|
344
|
+
return {
|
|
345
|
+
agentId: data.id,
|
|
346
|
+
name: data.name,
|
|
347
|
+
description: data.description,
|
|
348
|
+
agentSpec: toUiAgentSpec(data.manifest)
|
|
349
|
+
};
|
|
350
|
+
},
|
|
351
|
+
async getCodeSnippets({ agentId }) {
|
|
352
|
+
const absoluteBaseUrl = resolveTrueForgeBaseUrl(options.baseUrl ?? "/").replace(/\/$/, "");
|
|
353
|
+
const { data } = await client.internal.agents.getCodeSnippets(
|
|
354
|
+
agentId,
|
|
355
|
+
/^https?:\/\//i.test(absoluteBaseUrl) ? { baseUrl: absoluteBaseUrl } : void 0
|
|
356
|
+
);
|
|
357
|
+
return data.snippets;
|
|
358
|
+
},
|
|
359
|
+
async listSessions(requestParams = {}) {
|
|
360
|
+
const page = await client.sessions.list({
|
|
361
|
+
...requestParams.limit === void 0 ? {} : { limit: requestParams.limit },
|
|
362
|
+
...requestParams.order === void 0 ? {} : { order: requestParams.order },
|
|
363
|
+
...requestParams.pageToken === void 0 ? {} : { pageToken: requestParams.pageToken },
|
|
364
|
+
...requestParams.startTimestamp === void 0 ? {} : { startTimestamp: parseIsoDate(requestParams.startTimestamp) },
|
|
365
|
+
...requestParams.endTimestamp === void 0 ? {} : { endTimestamp: parseIsoDate(requestParams.endTimestamp) },
|
|
366
|
+
...requestParams.agentId === void 0 || requestParams.agentId.length === 0 ? {} : { agentId: requestParams.agentId },
|
|
367
|
+
...requestParams.createdByMe === void 0 ? {} : { createdByMe: requestParams.createdByMe }
|
|
368
|
+
});
|
|
369
|
+
return toListResult(page, toSessionListEntry);
|
|
370
|
+
},
|
|
371
|
+
async listSessionEvents({ sessionId, pageToken, limit }) {
|
|
372
|
+
const page = await client.sessions.listEvents(sessionId, {
|
|
373
|
+
...pageToken === void 0 ? {} : { pageToken },
|
|
374
|
+
...limit === void 0 ? {} : { limit }
|
|
375
|
+
});
|
|
376
|
+
return toListResult(page, toUiEventItem);
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// src/plugins/trueforge-agent-server-adapter/agentsList.ts
|
|
382
|
+
var AGENTS_PAGE_DEFAULT = 50;
|
|
383
|
+
var AGENTS_PAGE_LIMIT = 100;
|
|
384
|
+
function clampAgentsPageSize(size) {
|
|
385
|
+
return Math.min(Math.max(size, 1), AGENTS_PAGE_LIMIT);
|
|
386
|
+
}
|
|
387
|
+
async function listAgentsPage({
|
|
388
|
+
client,
|
|
389
|
+
limit,
|
|
390
|
+
offset = 0,
|
|
391
|
+
agentName
|
|
392
|
+
}) {
|
|
393
|
+
const pageSize = clampAgentsPageSize(limit);
|
|
394
|
+
const start = Math.max(0, offset);
|
|
395
|
+
const page = await client.agents.list({
|
|
396
|
+
limit: pageSize,
|
|
397
|
+
...agentName === void 0 ? {} : { agentName }
|
|
398
|
+
});
|
|
399
|
+
let at = 0;
|
|
400
|
+
while (at < start) {
|
|
401
|
+
if (!page.hasNextPage()) return [];
|
|
402
|
+
await page.getNextPage();
|
|
403
|
+
at += pageSize;
|
|
404
|
+
}
|
|
405
|
+
return [...page.data];
|
|
406
|
+
}
|
|
407
|
+
async function drainAgentsList(client) {
|
|
408
|
+
const items = [];
|
|
409
|
+
const page = await client.agents.list({ limit: AGENTS_PAGE_DEFAULT });
|
|
410
|
+
for (; ; ) {
|
|
411
|
+
items.push(...page.data);
|
|
412
|
+
if (!page.hasNextPage()) break;
|
|
413
|
+
await page.getNextPage();
|
|
414
|
+
}
|
|
415
|
+
return items;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// src/plugins/trueforge-agent-server-adapter/catalogs/connectorCatalog.ts
|
|
419
|
+
var DEFAULT_API_KEY_HEADER = "Authorization";
|
|
420
|
+
function toUiAuthPublic(auth) {
|
|
421
|
+
if (auth === void 0) {
|
|
422
|
+
return { type: "none" };
|
|
423
|
+
}
|
|
424
|
+
if (auth.type === "dcr") {
|
|
425
|
+
return { type: "dcr" };
|
|
426
|
+
}
|
|
427
|
+
const headerName = Object.keys(auth.headers)[0];
|
|
428
|
+
return {
|
|
429
|
+
type: "header",
|
|
430
|
+
...headerName === void 0 ? {} : { headerName }
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
function toHarnessAuth(auth) {
|
|
434
|
+
if (auth.type === "none") {
|
|
435
|
+
return void 0;
|
|
436
|
+
}
|
|
437
|
+
if (auth.type === "dcr") {
|
|
438
|
+
return { type: "dcr" };
|
|
439
|
+
}
|
|
440
|
+
const apiKey = auth.apiKey?.trim();
|
|
441
|
+
if (apiKey === void 0 || apiKey === "") {
|
|
442
|
+
throw new Error("API key is required for header-authenticated MCP servers");
|
|
443
|
+
}
|
|
444
|
+
const trimmedHeader = auth.headerName?.trim();
|
|
445
|
+
const headerName = trimmedHeader !== void 0 && trimmedHeader !== "" ? trimmedHeader : DEFAULT_API_KEY_HEADER;
|
|
446
|
+
return { type: "header", headers: { [headerName]: apiKey } };
|
|
447
|
+
}
|
|
448
|
+
function toUiCatalogEntry(server) {
|
|
449
|
+
return {
|
|
450
|
+
id: server.name,
|
|
451
|
+
name: server.name,
|
|
452
|
+
url: server.url,
|
|
453
|
+
description: server.description,
|
|
454
|
+
...server.logo === void 0 ? {} : { logo: server.logo },
|
|
455
|
+
auth: toUiAuthPublic(server.auth)
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
function toUiToolAnnotations(value) {
|
|
459
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
460
|
+
const readOnlyHint = Reflect.get(value, "readOnlyHint");
|
|
461
|
+
const destructiveHint = Reflect.get(value, "destructiveHint");
|
|
462
|
+
const annotations = {
|
|
463
|
+
...typeof readOnlyHint === "boolean" ? { readOnlyHint } : {},
|
|
464
|
+
...typeof destructiveHint === "boolean" ? { destructiveHint } : {}
|
|
465
|
+
};
|
|
466
|
+
return Object.keys(annotations).length > 0 ? annotations : void 0;
|
|
467
|
+
}
|
|
468
|
+
function toUiTool(tool) {
|
|
469
|
+
const name = typeof tool.name === "string" && tool.name !== "" ? tool.name : "tool";
|
|
470
|
+
const description = typeof tool.description === "string" ? tool.description : "";
|
|
471
|
+
const annotations = toUiToolAnnotations(Reflect.get(tool, "annotations"));
|
|
472
|
+
return annotations === void 0 ? { id: name, name, description } : { id: name, name, description, annotations };
|
|
473
|
+
}
|
|
474
|
+
function toUiConnector(server) {
|
|
475
|
+
const auth = toUiAuthPublic(server.manifest.auth);
|
|
476
|
+
return {
|
|
477
|
+
id: server.name,
|
|
478
|
+
name: server.name,
|
|
479
|
+
description: server.manifest.description,
|
|
480
|
+
url: server.manifest.url,
|
|
481
|
+
auth,
|
|
482
|
+
requiresAuth: server.authStatus.status === "auth_required",
|
|
483
|
+
authenticated: server.authStatus.status !== "auth_required"
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
function toUiConnectorFromReadEntry(server) {
|
|
487
|
+
const auth = server.auth?.type ? { type: server.auth.type } : { type: "none" };
|
|
488
|
+
return {
|
|
489
|
+
id: server.name,
|
|
490
|
+
name: server.name,
|
|
491
|
+
description: server.url,
|
|
492
|
+
url: server.url,
|
|
493
|
+
auth,
|
|
494
|
+
requiresAuth: server.authStatus.status === "auth_required",
|
|
495
|
+
authenticated: server.authStatus.status !== "auth_required"
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
function toHarnessManifest(req) {
|
|
499
|
+
const auth = toHarnessAuth(req.auth);
|
|
500
|
+
const trimmed = req.description?.trim();
|
|
501
|
+
return {
|
|
502
|
+
type: "remote",
|
|
503
|
+
name: req.name,
|
|
504
|
+
url: req.url,
|
|
505
|
+
description: trimmed !== void 0 && trimmed !== "" ? trimmed : `${req.name} MCP server`,
|
|
506
|
+
...auth === void 0 ? {} : { auth }
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
function createConnectorCatalog(client) {
|
|
510
|
+
async function getConfigured(name) {
|
|
511
|
+
const listed = await client.settings.mcpServers.list();
|
|
512
|
+
const existing = listed.data.find((server) => server.name === name);
|
|
513
|
+
if (existing === void 0) {
|
|
514
|
+
throw new Error(`MCP server "${name}" not found`);
|
|
515
|
+
}
|
|
516
|
+
return existing;
|
|
517
|
+
}
|
|
518
|
+
async function resolveWriteAuth(req) {
|
|
519
|
+
if (req.auth.type !== "header") {
|
|
520
|
+
return req.auth;
|
|
521
|
+
}
|
|
522
|
+
const apiKey = req.auth.apiKey?.trim();
|
|
523
|
+
if (apiKey !== void 0 && apiKey !== "") {
|
|
524
|
+
return req.auth;
|
|
525
|
+
}
|
|
526
|
+
if (req.id === void 0) {
|
|
527
|
+
throw new Error("API key is required for header-authenticated MCP servers");
|
|
528
|
+
}
|
|
529
|
+
const existing = await getConfigured(req.id);
|
|
530
|
+
if (existing.manifest.auth?.type !== "header") {
|
|
531
|
+
throw new Error(`MCP server "${req.id}" has no stored header credentials to reuse`);
|
|
532
|
+
}
|
|
533
|
+
const preferredHeader = req.auth.headerName?.trim();
|
|
534
|
+
const storedHeaderName = Object.keys(existing.manifest.auth.headers)[0];
|
|
535
|
+
const headerName = preferredHeader !== void 0 && preferredHeader !== "" ? preferredHeader : storedHeaderName ?? DEFAULT_API_KEY_HEADER;
|
|
536
|
+
const stored = existing.manifest.auth.headers[headerName] ?? Object.values(existing.manifest.auth.headers)[0];
|
|
537
|
+
if (stored === void 0) {
|
|
538
|
+
throw new Error(`MCP server "${req.id}" has no stored header credentials to reuse`);
|
|
539
|
+
}
|
|
540
|
+
return { type: "header", apiKey: stored, headerName };
|
|
541
|
+
}
|
|
542
|
+
return {
|
|
543
|
+
getConnectorCatalog: async () => {
|
|
544
|
+
const body = await client.catalogs.mcpServers.list();
|
|
545
|
+
return body.data.map(toUiCatalogEntry);
|
|
546
|
+
},
|
|
547
|
+
getConnector: async (req) => {
|
|
548
|
+
const body = await client.settings.mcpServers.get(req.id);
|
|
549
|
+
return toUiConnector(body.data);
|
|
550
|
+
},
|
|
551
|
+
listConnectors: async (req) => {
|
|
552
|
+
const body = await client.settings.mcpServers.list();
|
|
553
|
+
const connectors = body.data.map(toUiConnector);
|
|
554
|
+
const query = req?.query?.trim().toLowerCase();
|
|
555
|
+
if (query === void 0 || query === "") {
|
|
556
|
+
return connectors;
|
|
557
|
+
}
|
|
558
|
+
return connectors.filter(
|
|
559
|
+
(connector) => connector.name.toLowerCase().includes(query) || connector.description.toLowerCase().includes(query) || connector.url.toLowerCase().includes(query)
|
|
560
|
+
);
|
|
561
|
+
},
|
|
562
|
+
getToolsByConnectorId: async ({ id }) => {
|
|
563
|
+
const body = await client.mcpServers.listTools(id);
|
|
564
|
+
return body.data.map(toUiTool);
|
|
565
|
+
},
|
|
566
|
+
createConnector: async (req) => {
|
|
567
|
+
const auth = await resolveWriteAuth({ auth: req.auth });
|
|
568
|
+
const body = await client.settings.mcpServers.create({
|
|
569
|
+
manifest: toHarnessManifest({
|
|
570
|
+
name: req.name,
|
|
571
|
+
url: req.url,
|
|
572
|
+
auth,
|
|
573
|
+
description: req.description
|
|
574
|
+
})
|
|
575
|
+
});
|
|
576
|
+
return toUiConnector(body.data);
|
|
577
|
+
},
|
|
578
|
+
updateConnector: async (req) => {
|
|
579
|
+
const auth = await resolveWriteAuth({ id: req.id, auth: req.auth });
|
|
580
|
+
const body = await client.settings.mcpServers.createOrUpdate({
|
|
581
|
+
manifest: toHarnessManifest({
|
|
582
|
+
name: req.id,
|
|
583
|
+
url: req.url,
|
|
584
|
+
auth,
|
|
585
|
+
description: req.description
|
|
586
|
+
})
|
|
587
|
+
});
|
|
588
|
+
return toUiConnector(body.data);
|
|
589
|
+
},
|
|
590
|
+
authenticateConnector: async (req) => {
|
|
591
|
+
const result = await client.mcpServers.authorize(
|
|
592
|
+
req.id,
|
|
593
|
+
req.returnTo === void 0 ? {} : { returnTo: req.returnTo }
|
|
594
|
+
);
|
|
595
|
+
return { status: result.status, authorization_endpoint: result.authorizationUrl };
|
|
596
|
+
},
|
|
597
|
+
disconnectConnector: async (req) => {
|
|
598
|
+
const existing = await getConfigured(req.id);
|
|
599
|
+
if (existing.manifest.auth?.type !== "dcr") {
|
|
600
|
+
throw new Error(`Disconnect is only supported for OAuth MCP servers`);
|
|
601
|
+
}
|
|
602
|
+
const body = await client.mcpServers.deleteAuthorization(req.id);
|
|
603
|
+
return toUiConnector(body.data);
|
|
604
|
+
}
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
|
|
393
608
|
// src/plugins/trueforge-agent-server-adapter/lists.ts
|
|
394
609
|
async function listModels(client) {
|
|
395
610
|
const body = await client.models.list();
|
|
@@ -423,7 +638,7 @@ function toModelSelection({
|
|
|
423
638
|
model,
|
|
424
639
|
logo
|
|
425
640
|
}) {
|
|
426
|
-
const
|
|
641
|
+
const { contextLength, maxOutputTokens, reasoningEfforts } = model.properties;
|
|
427
642
|
return {
|
|
428
643
|
id: model.modelId,
|
|
429
644
|
name: model.name,
|
|
@@ -432,7 +647,9 @@ function toModelSelection({
|
|
|
432
647
|
...logo === void 0 ? {} : { logo }
|
|
433
648
|
},
|
|
434
649
|
properties: {
|
|
435
|
-
...
|
|
650
|
+
...contextLength === void 0 ? {} : { contextLength },
|
|
651
|
+
...maxOutputTokens === void 0 ? {} : { maxOutputTokens },
|
|
652
|
+
...reasoningEfforts === void 0 ? {} : { reasoningEfforts: [...reasoningEfforts] }
|
|
436
653
|
}
|
|
437
654
|
};
|
|
438
655
|
}
|
|
@@ -440,7 +657,9 @@ function toLibraryEntry(agent) {
|
|
|
440
657
|
return {
|
|
441
658
|
name: agent.name,
|
|
442
659
|
agentId: agent.id,
|
|
443
|
-
|
|
660
|
+
description: agent.description,
|
|
661
|
+
agentSpec: toUiAgentSpec(agent.manifest),
|
|
662
|
+
createdBySubject: agent.createdBySubject
|
|
444
663
|
};
|
|
445
664
|
}
|
|
446
665
|
function createHarnessBuilderServer(options = {}) {
|
|
@@ -462,32 +681,77 @@ function createHarnessBuilderServer(options = {}) {
|
|
|
462
681
|
});
|
|
463
682
|
},
|
|
464
683
|
// Skills require a configured sandbox provider; keep the picker empty when skill capability is off.
|
|
684
|
+
// Catalog AvailableSkill.name is store identity (FQN in TFY). Picker `id` copies that
|
|
685
|
+
// attach key; `name` is displayName so the draft can show a label without losing the wire key.
|
|
686
|
+
// Draft mounts `{ id, name }`; toHarnessSkill admits AgentSpec.skills[].name = id ?? name.
|
|
465
687
|
getSkills: async () => {
|
|
466
688
|
const skills = await listSkills(client);
|
|
467
|
-
return skills.map((skill) =>
|
|
689
|
+
return skills.map((skill) => {
|
|
690
|
+
const { display_name, repository_name, version: versionRaw } = skill.metadata ?? {};
|
|
691
|
+
const version = Number(versionRaw);
|
|
692
|
+
const hasVersion = Number.isInteger(version) && version > 0;
|
|
693
|
+
return {
|
|
694
|
+
id: skill.name,
|
|
695
|
+
name: display_name ?? skill.name,
|
|
696
|
+
description: skill.description,
|
|
697
|
+
...repository_name === void 0 ? {} : { skillRepoName: repository_name },
|
|
698
|
+
...hasVersion ? {
|
|
699
|
+
version,
|
|
700
|
+
loadVersions: async () => (await client.skills.listVersions({ name: skill.name })).data
|
|
701
|
+
} : {}
|
|
702
|
+
};
|
|
703
|
+
});
|
|
468
704
|
},
|
|
469
705
|
getMcp: async () => (await listConfiguredMcpServers(client)).map(toUiConnectorFromReadEntry),
|
|
706
|
+
getMcpConnector: async ({ connectorId }) => {
|
|
707
|
+
const body = await client.mcpServers.get(connectorId);
|
|
708
|
+
return toUiConnectorFromReadEntry(body.data);
|
|
709
|
+
},
|
|
710
|
+
getMcpTools: async ({ connectorId }) => {
|
|
711
|
+
const body = await client.mcpServers.listTools(connectorId);
|
|
712
|
+
return body.data.flatMap(
|
|
713
|
+
(tool) => typeof tool.name === "string" && tool.name.trim() !== "" ? [toUiTool(tool)] : []
|
|
714
|
+
);
|
|
715
|
+
},
|
|
470
716
|
async searchAgents(req) {
|
|
471
|
-
const
|
|
472
|
-
const query = req?.query?.trim().toLowerCase();
|
|
473
|
-
const filtered = query === void 0 || query === "" ? data : data.filter((agent) => agent.name.toLowerCase().includes(query));
|
|
717
|
+
const limit = clampAgentsPageSize(req?.limit ?? AGENTS_PAGE_DEFAULT);
|
|
474
718
|
const offset = req?.offset ?? 0;
|
|
475
|
-
const
|
|
476
|
-
|
|
719
|
+
const query = req?.query?.trim();
|
|
720
|
+
const rows = await listAgentsPage({
|
|
721
|
+
client,
|
|
722
|
+
limit,
|
|
723
|
+
offset,
|
|
724
|
+
...query === void 0 || query === "" ? {} : { agentName: query }
|
|
725
|
+
});
|
|
726
|
+
return rows.map(toLibraryEntry);
|
|
477
727
|
},
|
|
478
|
-
async saveAgent({ agentName, agentSpec, intent }) {
|
|
728
|
+
async saveAgent({ agentName, description: descriptionRaw, agentSpec, intent }) {
|
|
479
729
|
const manifest = toHarnessAgentSpec(agentSpec);
|
|
730
|
+
const description = descriptionRaw?.trim();
|
|
480
731
|
if (intent === "update") {
|
|
481
|
-
const
|
|
482
|
-
const existing =
|
|
732
|
+
const agents = await drainAgentsList(client);
|
|
733
|
+
const existing = agents.find((agent) => agent.name === agentName);
|
|
483
734
|
if (!existing) {
|
|
484
735
|
return {};
|
|
485
736
|
}
|
|
486
|
-
await client.agents.update(existing.id, {
|
|
737
|
+
await client.agents.update(existing.id, {
|
|
738
|
+
...description ? { description } : {},
|
|
739
|
+
manifest
|
|
740
|
+
});
|
|
487
741
|
return { agentId: existing.id };
|
|
488
742
|
}
|
|
489
|
-
const created = await client.agents.create({
|
|
743
|
+
const created = await client.agents.create({
|
|
744
|
+
name: agentName,
|
|
745
|
+
description: description || agentName,
|
|
746
|
+
manifest
|
|
747
|
+
});
|
|
490
748
|
return { agentId: created.data.id };
|
|
749
|
+
},
|
|
750
|
+
async deleteAgent({ agentName }) {
|
|
751
|
+
const agents = await drainAgentsList(client);
|
|
752
|
+
const existing = agents.find((agent) => agent.name === agentName);
|
|
753
|
+
if (!existing) return;
|
|
754
|
+
await client.agents.delete(existing.id);
|
|
491
755
|
}
|
|
492
756
|
};
|
|
493
757
|
}
|
|
@@ -769,10 +1033,12 @@ function toHarnessManifest3(req) {
|
|
|
769
1033
|
};
|
|
770
1034
|
}
|
|
771
1035
|
function toUiSkill2(skill, catalogNames) {
|
|
1036
|
+
const manifest = skill.manifest;
|
|
1037
|
+
const displayName = "displayName" in manifest && typeof manifest.displayName === "string" ? manifest.displayName : manifest.name;
|
|
772
1038
|
const base = {
|
|
773
1039
|
id: skill.name,
|
|
774
|
-
name:
|
|
775
|
-
description:
|
|
1040
|
+
name: displayName,
|
|
1041
|
+
description: manifest.description
|
|
776
1042
|
};
|
|
777
1043
|
if (catalogNames.has(skill.name)) {
|
|
778
1044
|
return { ...base, catalogId: skill.name };
|
|
@@ -817,9 +1083,138 @@ function createSkillCatalog(client) {
|
|
|
817
1083
|
};
|
|
818
1084
|
}
|
|
819
1085
|
|
|
1086
|
+
// src/plugins/trueforge-agent-server-adapter/permissionsServer.ts
|
|
1087
|
+
function createHarnessPermissionsServer(options = {}) {
|
|
1088
|
+
const client = options.client ?? createTrueForgeClient(options);
|
|
1089
|
+
return {
|
|
1090
|
+
listPermissions: async (request) => client.internal.listPermissions(request)
|
|
1091
|
+
};
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
// src/plugins/trueforge-agent-server-adapter/schedules/scheduleServer.ts
|
|
1095
|
+
var SCHEDULES_PAGE_LIMIT = 25;
|
|
1096
|
+
async function loadAgentIndex(client) {
|
|
1097
|
+
const agents = await drainAgentsList(client);
|
|
1098
|
+
const idToName = /* @__PURE__ */ new Map();
|
|
1099
|
+
const nameToId = /* @__PURE__ */ new Map();
|
|
1100
|
+
for (const agent of agents) {
|
|
1101
|
+
idToName.set(agent.id, agent.name);
|
|
1102
|
+
nameToId.set(agent.name, agent.id);
|
|
1103
|
+
}
|
|
1104
|
+
return { idToName, nameToId };
|
|
1105
|
+
}
|
|
1106
|
+
function resolveAgentName(agentId, index) {
|
|
1107
|
+
const byId = index.idToName.get(agentId);
|
|
1108
|
+
if (byId != null) return byId;
|
|
1109
|
+
if (index.nameToId.has(agentId)) return agentId;
|
|
1110
|
+
throw new Error(`Unknown agent: ${agentId}`);
|
|
1111
|
+
}
|
|
1112
|
+
function collectAgentIds(req) {
|
|
1113
|
+
const ids = [];
|
|
1114
|
+
if (req?.agentIds != null) {
|
|
1115
|
+
for (const id of req.agentIds) {
|
|
1116
|
+
if (id !== "") ids.push(id);
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
if (req?.agentId != null && req.agentId !== "") ids.push(req.agentId);
|
|
1120
|
+
return [...new Set(ids)];
|
|
1121
|
+
}
|
|
1122
|
+
function wireStatus(manifest) {
|
|
1123
|
+
return manifest.status ?? "active";
|
|
1124
|
+
}
|
|
1125
|
+
function toUiSchedule(wire, index) {
|
|
1126
|
+
const agentId = index.nameToId.get(wire.agentName) ?? wire.agentName;
|
|
1127
|
+
return {
|
|
1128
|
+
id: wire.id,
|
|
1129
|
+
name: wire.name,
|
|
1130
|
+
agentId,
|
|
1131
|
+
agentName: wire.agentName,
|
|
1132
|
+
task: wire.manifest.task,
|
|
1133
|
+
cron: wire.manifest.cron,
|
|
1134
|
+
timezone: wire.manifest.timezone ?? "UTC",
|
|
1135
|
+
status: wireStatus(wire.manifest),
|
|
1136
|
+
lastRunAt: null,
|
|
1137
|
+
createdBySubject: wire.createdBySubject
|
|
1138
|
+
};
|
|
1139
|
+
}
|
|
1140
|
+
function toWireManifest(input) {
|
|
1141
|
+
return {
|
|
1142
|
+
task: input.task,
|
|
1143
|
+
cron: input.cron,
|
|
1144
|
+
timezone: input.timezone ?? "UTC",
|
|
1145
|
+
status: input.status ?? "active"
|
|
1146
|
+
};
|
|
1147
|
+
}
|
|
1148
|
+
function toIsoInstant(value) {
|
|
1149
|
+
if (value instanceof Date) return value.toISOString();
|
|
1150
|
+
return value;
|
|
1151
|
+
}
|
|
1152
|
+
function toUiScheduleRun(wire) {
|
|
1153
|
+
return {
|
|
1154
|
+
id: wire.id,
|
|
1155
|
+
scheduleId: wire.scheduleId,
|
|
1156
|
+
name: wire.name,
|
|
1157
|
+
scheduledFor: toIsoInstant(wire.scheduledFor),
|
|
1158
|
+
status: wire.status,
|
|
1159
|
+
triggeredAt: wire.triggeredAt == null ? null : toIsoInstant(wire.triggeredAt),
|
|
1160
|
+
triggeredBy: wire.createdBySubject.subjectDisplayName || wire.createdBySubject.subjectId
|
|
1161
|
+
};
|
|
1162
|
+
}
|
|
1163
|
+
function createScheduleServer(options) {
|
|
1164
|
+
const { client } = options;
|
|
1165
|
+
return {
|
|
1166
|
+
async listSchedules(req) {
|
|
1167
|
+
const index = await loadAgentIndex(client);
|
|
1168
|
+
const agentIds = collectAgentIds(req);
|
|
1169
|
+
const agentNames = agentIds.length === 0 ? void 0 : agentIds.map((id) => resolveAgentName(id, index)).join(",");
|
|
1170
|
+
const limit = Math.min(Math.max(req?.limit ?? SCHEDULES_PAGE_LIMIT, 1), SCHEDULES_PAGE_LIMIT);
|
|
1171
|
+
const page = await client.schedules.list({
|
|
1172
|
+
limit,
|
|
1173
|
+
...req?.pageToken === void 0 || req.pageToken === "" ? {} : { pageToken: req.pageToken },
|
|
1174
|
+
...agentNames === void 0 ? {} : { agentNames }
|
|
1175
|
+
});
|
|
1176
|
+
return toListResult(page, (row) => toUiSchedule(row, index));
|
|
1177
|
+
},
|
|
1178
|
+
async getSchedule({ id }) {
|
|
1179
|
+
const index = await loadAgentIndex(client);
|
|
1180
|
+
const { data } = await client.schedules.get(id);
|
|
1181
|
+
return toUiSchedule(data, index);
|
|
1182
|
+
},
|
|
1183
|
+
async createSchedule(req) {
|
|
1184
|
+
const index = await loadAgentIndex(client);
|
|
1185
|
+
const agentName = resolveAgentName(req.agentId, index);
|
|
1186
|
+
const { data } = await client.schedules.create({
|
|
1187
|
+
agentName,
|
|
1188
|
+
name: req.name,
|
|
1189
|
+
manifest: toWireManifest(req)
|
|
1190
|
+
});
|
|
1191
|
+
return toUiSchedule(data, index);
|
|
1192
|
+
},
|
|
1193
|
+
async updateSchedule(req) {
|
|
1194
|
+
const index = await loadAgentIndex(client);
|
|
1195
|
+
const { data } = await client.schedules.update(req.id, {
|
|
1196
|
+
name: req.name,
|
|
1197
|
+
manifest: toWireManifest(req)
|
|
1198
|
+
});
|
|
1199
|
+
return toUiSchedule(data, index);
|
|
1200
|
+
},
|
|
1201
|
+
async deleteSchedule({ id }) {
|
|
1202
|
+
await client.schedules.delete(id);
|
|
1203
|
+
},
|
|
1204
|
+
async listScheduleRuns({ scheduleId }) {
|
|
1205
|
+
const { data } = await client.schedules.listRuns(scheduleId);
|
|
1206
|
+
return data.map(toUiScheduleRun);
|
|
1207
|
+
},
|
|
1208
|
+
async createScheduleRun(req) {
|
|
1209
|
+
const { data } = await client.schedules.createRun({ scheduleId: req.scheduleId });
|
|
1210
|
+
return toUiScheduleRun(data);
|
|
1211
|
+
}
|
|
1212
|
+
};
|
|
1213
|
+
}
|
|
1214
|
+
|
|
820
1215
|
// src/plugins/trueforge-agent-server-adapter/index.ts
|
|
821
1216
|
function createTrueForgeAgentUIServer(options = {}) {
|
|
822
|
-
const { catalog: catalogOverride, ...clientOptions } = options;
|
|
1217
|
+
const { catalog: catalogOverride, permissions, ...clientOptions } = options;
|
|
823
1218
|
const client = createTrueForgeClient(clientOptions);
|
|
824
1219
|
const catalog = catalogOverride ?? {
|
|
825
1220
|
modelCatalog: createModelProviderCatalog(client),
|
|
@@ -830,16 +1225,24 @@ function createTrueForgeAgentUIServer(options = {}) {
|
|
|
830
1225
|
return createTrueFoundryServer({
|
|
831
1226
|
chatServer: createHarnessChatServer({ client }),
|
|
832
1227
|
...createHarnessBuilderServer({ client }),
|
|
833
|
-
catalog
|
|
1228
|
+
catalog,
|
|
1229
|
+
sessions: createHarnessAgentSessionsServer({ ...clientOptions, client }),
|
|
1230
|
+
metrics: createHarnessAgentMetricsServer({ ...clientOptions, client }),
|
|
1231
|
+
schedules: createScheduleServer({ client }),
|
|
1232
|
+
permissions: permissions ?? createHarnessPermissionsServer({ client })
|
|
834
1233
|
});
|
|
835
1234
|
}
|
|
836
1235
|
export {
|
|
837
1236
|
configFromHarness,
|
|
838
1237
|
createConnectorCatalog,
|
|
1238
|
+
createHarnessAgentMetricsServer,
|
|
1239
|
+
createHarnessAgentSessionsServer,
|
|
839
1240
|
createHarnessBuilderServer,
|
|
840
1241
|
createHarnessChatServer,
|
|
1242
|
+
createHarnessPermissionsServer,
|
|
841
1243
|
createModelProviderCatalog,
|
|
842
1244
|
createSandboxProviderCatalog,
|
|
1245
|
+
createScheduleServer,
|
|
843
1246
|
createSkillCatalog,
|
|
844
1247
|
createTrueForgeAgentUIServer,
|
|
845
1248
|
createTrueForgeClient,
|