@truefoundry/trueforge 0.1.1 → 0.1.3
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/dist/_frontend/assets/{ConnectorSettings-4CYGRWPH-EWp5lwOt.js → ConnectorSettings-EYOQ72OS-DdSqeM08.js} +1 -1
- package/dist/_frontend/assets/ConnectorSettings-EYOQ72OS-DdSqeM08.js.br +0 -0
- package/dist/_frontend/assets/ConnectorSettings-EYOQ72OS-DdSqeM08.js.gz +0 -0
- package/dist/_frontend/assets/{DockLayout-FEDQX2UT-DbN-pvPO.js → DockLayout-XIOJZ2YM-htVfvSLo.js} +1 -1
- package/dist/_frontend/assets/{DrawerLayout-NMA7P64K-0IGRaUAW.js → DrawerLayout-CNKNNVI7-CQ7wZgB6.js} +2 -2
- package/dist/_frontend/assets/DrawerLayout-CNKNNVI7-CQ7wZgB6.js.br +0 -0
- package/dist/_frontend/assets/DrawerLayout-CNKNNVI7-CQ7wZgB6.js.gz +0 -0
- package/dist/_frontend/assets/{ModelSettings-H5FKRZLK-CEQWPDWn.js → ModelSettings-WBDPLI6O-CYfqXYXo.js} +1 -1
- package/dist/_frontend/assets/ModelSettings-WBDPLI6O-CYfqXYXo.js.br +0 -0
- package/dist/_frontend/assets/ModelSettings-WBDPLI6O-CYfqXYXo.js.gz +0 -0
- package/dist/_frontend/assets/{SandboxSettings-CBSC3C3G-PWbj0tIQ.js → SandboxSettings-4GHBXULN-BPT3vPku.js} +1 -1
- package/dist/_frontend/assets/SandboxSettings-4GHBXULN-BPT3vPku.js.br +0 -0
- package/dist/_frontend/assets/SandboxSettings-4GHBXULN-BPT3vPku.js.gz +0 -0
- package/dist/_frontend/assets/{SettingsBuilder-EGSH7BUA-Cvx-hLzU.js → SettingsBuilder-TD42LCIU-COZb69Wb.js} +2 -2
- package/dist/_frontend/assets/SettingsBuilder-TD42LCIU-COZb69Wb.js.br +0 -0
- package/dist/_frontend/assets/SettingsBuilder-TD42LCIU-COZb69Wb.js.gz +0 -0
- package/dist/_frontend/assets/{ShellRouteSync-53FTXNZZ-BIksLzSL.js → ShellRouteSync-T4WLY57Q-BKbLAZEv.js} +1 -1
- package/dist/_frontend/assets/ShellRouteSync-T4WLY57Q-BKbLAZEv.js.br +0 -0
- package/dist/_frontend/assets/ShellRouteSync-T4WLY57Q-BKbLAZEv.js.gz +0 -0
- package/dist/_frontend/assets/{SidebarLayout-5WM2BHZG-Ceb_9WvC.js → SidebarLayout-JGLTENB3-BiZz45he.js} +2 -2
- package/dist/_frontend/assets/SidebarLayout-JGLTENB3-BiZz45he.js.br +0 -0
- package/dist/_frontend/assets/SidebarLayout-JGLTENB3-BiZz45he.js.gz +0 -0
- package/dist/_frontend/assets/{SkillSettings-A2OQSQUT-C-AShr7L.js → SkillSettings-UG6USX4N-DhQTOueg.js} +1 -1
- package/dist/_frontend/assets/SkillSettings-UG6USX4N-DhQTOueg.js.br +0 -0
- package/dist/_frontend/assets/SkillSettings-UG6USX4N-DhQTOueg.js.gz +0 -0
- package/dist/_frontend/assets/{TrueForgeUIWithRouter-2AQ3HW6L-DexVXzlD.js → TrueForgeUIWithRouter-CTC5XRSY-BnWelV-R.js} +1 -1
- package/dist/_frontend/assets/{WidgetLayout-IKGVAZFV-Q2dDfnNQ.js → WidgetLayout-6P6OUUTG-B1G5uZ4_.js} +1 -1
- package/dist/_frontend/assets/WidgetLayout-6P6OUUTG-B1G5uZ4_.js.br +0 -0
- package/dist/_frontend/assets/WidgetLayout-6P6OUUTG-B1G5uZ4_.js.gz +0 -0
- package/dist/_frontend/assets/{chunk-BMLCISMH-BtIzChti.js → chunk-27MKI3HF-CVw53aeu.js} +1 -1
- package/dist/_frontend/assets/chunk-27MKI3HF-CVw53aeu.js.br +0 -0
- package/dist/_frontend/assets/chunk-27MKI3HF-CVw53aeu.js.gz +0 -0
- package/dist/_frontend/assets/{chunk-62JRHF6Z-BpHQergm.js → chunk-62JRHF6Z-yJ2twjOf.js} +1 -1
- package/dist/_frontend/assets/chunk-62JRHF6Z-yJ2twjOf.js.br +0 -0
- package/dist/_frontend/assets/chunk-62JRHF6Z-yJ2twjOf.js.gz +0 -0
- package/dist/_frontend/assets/{chunk-4STVL6W6-DO6mK5-E.js → chunk-H75C5ETA-CX-fQN0e.js} +2 -2
- package/dist/_frontend/assets/chunk-H75C5ETA-CX-fQN0e.js.br +0 -0
- package/dist/_frontend/assets/chunk-H75C5ETA-CX-fQN0e.js.gz +0 -0
- package/dist/_frontend/assets/{cssMode-tBxiXBbi.js → cssMode-CEpMXY8Z.js} +1 -1
- package/dist/_frontend/assets/cssMode-CEpMXY8Z.js.br +0 -0
- package/dist/_frontend/assets/cssMode-CEpMXY8Z.js.gz +0 -0
- package/dist/_frontend/assets/{freemarker2-C8-_g6KH.js → freemarker2-cQSgojlC.js} +1 -1
- package/dist/_frontend/assets/freemarker2-cQSgojlC.js.br +0 -0
- package/dist/_frontend/assets/freemarker2-cQSgojlC.js.gz +0 -0
- package/dist/_frontend/assets/{handlebars-CVTAyJx2.js → handlebars-BQ-clQ7_.js} +1 -1
- package/dist/_frontend/assets/handlebars-BQ-clQ7_.js.br +0 -0
- package/dist/_frontend/assets/handlebars-BQ-clQ7_.js.gz +0 -0
- package/dist/_frontend/assets/{html-CFO-PVK6.js → html-ChfWgJt-.js} +1 -1
- package/dist/_frontend/assets/html-ChfWgJt-.js.br +0 -0
- package/dist/_frontend/assets/html-ChfWgJt-.js.gz +0 -0
- package/dist/_frontend/assets/{htmlMode-CFCanlO-.js → htmlMode-D1PmpoAx.js} +1 -1
- package/dist/_frontend/assets/htmlMode-D1PmpoAx.js.br +0 -0
- package/dist/_frontend/assets/htmlMode-D1PmpoAx.js.gz +0 -0
- package/dist/_frontend/assets/{index-CSSyjy0I.js → index-BRS0kvLQ.js} +202 -197
- package/dist/_frontend/assets/index-BRS0kvLQ.js.br +0 -0
- package/dist/_frontend/assets/index-BRS0kvLQ.js.gz +0 -0
- package/dist/_frontend/assets/{index-BIWWiCC7.js → index-aEojVaVa.js} +3 -3
- package/dist/_frontend/assets/index-aEojVaVa.js.br +0 -0
- package/dist/_frontend/assets/index-aEojVaVa.js.gz +0 -0
- package/dist/_frontend/assets/{javascript-MIQGaM22.js → javascript-DFHGvkjD.js} +1 -1
- package/dist/_frontend/assets/{jsonMode-D5gVPPeB.js → jsonMode-DWo0prLv.js} +1 -1
- package/dist/_frontend/assets/jsonMode-DWo0prLv.js.br +0 -0
- package/dist/_frontend/assets/jsonMode-DWo0prLv.js.gz +0 -0
- package/dist/_frontend/assets/{liquid-DHNaEubO.js → liquid-Bs2__P9v.js} +1 -1
- package/dist/_frontend/assets/liquid-Bs2__P9v.js.br +0 -0
- package/dist/_frontend/assets/liquid-Bs2__P9v.js.gz +0 -0
- package/dist/_frontend/assets/{lspLanguageFeatures-QCSfugnT.js → lspLanguageFeatures-zZ0stYf4.js} +1 -1
- package/dist/_frontend/assets/lspLanguageFeatures-zZ0stYf4.js.br +0 -0
- package/dist/_frontend/assets/lspLanguageFeatures-zZ0stYf4.js.gz +0 -0
- package/dist/_frontend/assets/{mdx-BXTfxgKC.js → mdx-C7c8MDI_.js} +1 -1
- package/dist/_frontend/assets/mdx-C7c8MDI_.js.br +0 -0
- package/dist/_frontend/assets/mdx-C7c8MDI_.js.gz +0 -0
- package/dist/_frontend/assets/{python-2xJ5-a_I.js → python-CLO39XAV.js} +1 -1
- package/dist/_frontend/assets/python-CLO39XAV.js.br +0 -0
- package/dist/_frontend/assets/python-CLO39XAV.js.gz +0 -0
- package/dist/_frontend/assets/{razor-pc2nnHiH.js → razor-efddsYhk.js} +1 -1
- package/dist/_frontend/assets/razor-efddsYhk.js.br +0 -0
- package/dist/_frontend/assets/razor-efddsYhk.js.gz +0 -0
- package/dist/_frontend/assets/{tsMode-DDOTqjiA.js → tsMode-xfchPgTX.js} +1 -1
- package/dist/_frontend/assets/tsMode-xfchPgTX.js.br +0 -0
- package/dist/_frontend/assets/tsMode-xfchPgTX.js.gz +0 -0
- package/dist/_frontend/assets/{typescript-B8kVUDuw.js → typescript-BFzaCQP8.js} +1 -1
- package/dist/_frontend/assets/typescript-BFzaCQP8.js.br +0 -0
- package/dist/_frontend/assets/typescript-BFzaCQP8.js.gz +0 -0
- package/dist/_frontend/assets/{workers-BKOSx8Az.js → workers-DKwMBzKS.js} +1 -1
- package/dist/_frontend/assets/workers-DKwMBzKS.js.br +0 -0
- package/dist/_frontend/assets/workers-DKwMBzKS.js.gz +0 -0
- package/dist/_frontend/assets/{xml--HuG4XfW.js → xml-Cx6gHwq3.js} +1 -1
- package/dist/_frontend/assets/xml-Cx6gHwq3.js.br +0 -0
- package/dist/_frontend/assets/xml-Cx6gHwq3.js.gz +0 -0
- package/dist/_frontend/assets/{yaml-BM2qwYh9.js → yaml-DyrfMWlf.js} +1 -1
- package/dist/_frontend/assets/yaml-DyrfMWlf.js.br +0 -0
- package/dist/_frontend/assets/yaml-DyrfMWlf.js.gz +0 -0
- package/dist/_frontend/index.html +1 -1
- package/dist/_frontend/index.html.br +0 -0
- package/dist/_frontend/index.html.gz +0 -0
- package/dist/main.js +189 -158
- package/dist/main.js.map +1 -1
- package/dist/postgres/migrations/20260818_000001_mcp_pending_auth_return_to.js +17 -0
- package/dist/postgres/migrations/20260818_000001_mcp_pending_auth_return_to.js.map +1 -0
- package/dist/sqlite/migrations/20260818_000001_mcp_pending_auth_return_to.js +19 -0
- package/dist/sqlite/migrations/20260818_000001_mcp_pending_auth_return_to.js.map +1 -0
- package/package.json +2 -2
- package/dist/_frontend/assets/ConnectorSettings-4CYGRWPH-EWp5lwOt.js.br +0 -0
- package/dist/_frontend/assets/ConnectorSettings-4CYGRWPH-EWp5lwOt.js.gz +0 -0
- package/dist/_frontend/assets/DrawerLayout-NMA7P64K-0IGRaUAW.js.br +0 -0
- package/dist/_frontend/assets/DrawerLayout-NMA7P64K-0IGRaUAW.js.gz +0 -0
- package/dist/_frontend/assets/ModelSettings-H5FKRZLK-CEQWPDWn.js.br +0 -0
- package/dist/_frontend/assets/ModelSettings-H5FKRZLK-CEQWPDWn.js.gz +0 -0
- package/dist/_frontend/assets/SandboxSettings-CBSC3C3G-PWbj0tIQ.js.br +0 -0
- package/dist/_frontend/assets/SandboxSettings-CBSC3C3G-PWbj0tIQ.js.gz +0 -0
- package/dist/_frontend/assets/SettingsBuilder-EGSH7BUA-Cvx-hLzU.js.br +0 -0
- package/dist/_frontend/assets/SettingsBuilder-EGSH7BUA-Cvx-hLzU.js.gz +0 -0
- package/dist/_frontend/assets/ShellRouteSync-53FTXNZZ-BIksLzSL.js.br +0 -0
- package/dist/_frontend/assets/ShellRouteSync-53FTXNZZ-BIksLzSL.js.gz +0 -0
- package/dist/_frontend/assets/SidebarLayout-5WM2BHZG-Ceb_9WvC.js.br +0 -0
- package/dist/_frontend/assets/SidebarLayout-5WM2BHZG-Ceb_9WvC.js.gz +0 -0
- package/dist/_frontend/assets/SkillSettings-A2OQSQUT-C-AShr7L.js.br +0 -0
- package/dist/_frontend/assets/SkillSettings-A2OQSQUT-C-AShr7L.js.gz +0 -0
- package/dist/_frontend/assets/WidgetLayout-IKGVAZFV-Q2dDfnNQ.js.br +0 -0
- package/dist/_frontend/assets/WidgetLayout-IKGVAZFV-Q2dDfnNQ.js.gz +0 -0
- package/dist/_frontend/assets/chunk-4STVL6W6-DO6mK5-E.js.br +0 -0
- package/dist/_frontend/assets/chunk-4STVL6W6-DO6mK5-E.js.gz +0 -0
- package/dist/_frontend/assets/chunk-62JRHF6Z-BpHQergm.js.br +0 -0
- package/dist/_frontend/assets/chunk-62JRHF6Z-BpHQergm.js.gz +0 -0
- package/dist/_frontend/assets/chunk-BMLCISMH-BtIzChti.js.br +0 -0
- package/dist/_frontend/assets/chunk-BMLCISMH-BtIzChti.js.gz +0 -0
- package/dist/_frontend/assets/cssMode-tBxiXBbi.js.br +0 -0
- package/dist/_frontend/assets/cssMode-tBxiXBbi.js.gz +0 -0
- package/dist/_frontend/assets/freemarker2-C8-_g6KH.js.br +0 -0
- package/dist/_frontend/assets/freemarker2-C8-_g6KH.js.gz +0 -0
- package/dist/_frontend/assets/handlebars-CVTAyJx2.js.br +0 -0
- package/dist/_frontend/assets/handlebars-CVTAyJx2.js.gz +0 -0
- package/dist/_frontend/assets/html-CFO-PVK6.js.br +0 -0
- package/dist/_frontend/assets/html-CFO-PVK6.js.gz +0 -0
- package/dist/_frontend/assets/htmlMode-CFCanlO-.js.br +0 -0
- package/dist/_frontend/assets/htmlMode-CFCanlO-.js.gz +0 -0
- package/dist/_frontend/assets/index-BIWWiCC7.js.br +0 -0
- package/dist/_frontend/assets/index-BIWWiCC7.js.gz +0 -0
- package/dist/_frontend/assets/index-CSSyjy0I.js.br +0 -0
- package/dist/_frontend/assets/index-CSSyjy0I.js.gz +0 -0
- package/dist/_frontend/assets/jsonMode-D5gVPPeB.js.br +0 -0
- package/dist/_frontend/assets/jsonMode-D5gVPPeB.js.gz +0 -0
- package/dist/_frontend/assets/liquid-DHNaEubO.js.br +0 -0
- package/dist/_frontend/assets/liquid-DHNaEubO.js.gz +0 -0
- package/dist/_frontend/assets/lspLanguageFeatures-QCSfugnT.js.br +0 -0
- package/dist/_frontend/assets/lspLanguageFeatures-QCSfugnT.js.gz +0 -0
- package/dist/_frontend/assets/mdx-BXTfxgKC.js.br +0 -0
- package/dist/_frontend/assets/mdx-BXTfxgKC.js.gz +0 -0
- package/dist/_frontend/assets/python-2xJ5-a_I.js.br +0 -0
- package/dist/_frontend/assets/python-2xJ5-a_I.js.gz +0 -0
- package/dist/_frontend/assets/razor-pc2nnHiH.js.br +0 -0
- package/dist/_frontend/assets/razor-pc2nnHiH.js.gz +0 -0
- package/dist/_frontend/assets/tsMode-DDOTqjiA.js.br +0 -0
- package/dist/_frontend/assets/tsMode-DDOTqjiA.js.gz +0 -0
- package/dist/_frontend/assets/typescript-B8kVUDuw.js.br +0 -0
- package/dist/_frontend/assets/typescript-B8kVUDuw.js.gz +0 -0
- package/dist/_frontend/assets/workers-BKOSx8Az.js.br +0 -0
- package/dist/_frontend/assets/workers-BKOSx8Az.js.gz +0 -0
- package/dist/_frontend/assets/xml--HuG4XfW.js.br +0 -0
- package/dist/_frontend/assets/xml--HuG4XfW.js.gz +0 -0
- package/dist/_frontend/assets/yaml-BM2qwYh9.js.br +0 -0
- package/dist/_frontend/assets/yaml-BM2qwYh9.js.gz +0 -0
package/dist/main.js
CHANGED
|
@@ -380,14 +380,14 @@ function toStoredOAuthPendingAuthorizationData(pending) {
|
|
|
380
380
|
return {
|
|
381
381
|
mcp_server_url: pending.mcpServerUrl,
|
|
382
382
|
code_verifier: pending.codeVerifier,
|
|
383
|
-
|
|
383
|
+
return_to: pending.returnTo
|
|
384
384
|
};
|
|
385
385
|
}
|
|
386
386
|
function fromStoredOAuthPendingAuthorizationData(stored) {
|
|
387
387
|
return {
|
|
388
388
|
mcpServerUrl: stored.mcp_server_url,
|
|
389
389
|
codeVerifier: stored.code_verifier,
|
|
390
|
-
|
|
390
|
+
returnTo: stored.return_to
|
|
391
391
|
};
|
|
392
392
|
}
|
|
393
393
|
var McpServerNameConflictError, PENDING_AUTHORIZATION_TTL_MS;
|
|
@@ -655,9 +655,7 @@ var init_sqlExpressions2 = __esm({
|
|
|
655
655
|
});
|
|
656
656
|
|
|
657
657
|
// src/db/sqlite/session-store/queries/turns.ts
|
|
658
|
-
import
|
|
659
|
-
CancellationReason as CancellationReason4
|
|
660
|
-
} from "@truefoundry/trueforge-core/agent-session/schemas/turn";
|
|
658
|
+
import "@truefoundry/trueforge-core/agent-session/schemas/turn";
|
|
661
659
|
import { assertCreateTurnThreadDelta } from "@truefoundry/trueforge-core/agent-session/store/assertCreateTurnThreadDelta";
|
|
662
660
|
import {
|
|
663
661
|
PreviousTurnRunningError,
|
|
@@ -666,7 +664,7 @@ import {
|
|
|
666
664
|
SessionStoreInvariantError as SessionStoreInvariantError2,
|
|
667
665
|
SessionStoreNotFoundError as SessionStoreNotFoundError3,
|
|
668
666
|
TurnAlreadyExistsError,
|
|
669
|
-
TurnNotFoundError,
|
|
667
|
+
TurnNotFoundError as TurnNotFoundError2,
|
|
670
668
|
TurnNotRunningError
|
|
671
669
|
} from "@truefoundry/trueforge-core/agent-session/store/SessionStoreErrors";
|
|
672
670
|
import { getEmptyCurrentContextUsage } from "@truefoundry/trueforge-core/core/runtime/contextUsage";
|
|
@@ -700,14 +698,14 @@ async function loadTurnState(db, keys) {
|
|
|
700
698
|
async function classifyTurnFenceWriteFailure(db, keys) {
|
|
701
699
|
const state = await loadTurnState(db, keys);
|
|
702
700
|
if (!state) {
|
|
703
|
-
throw new
|
|
701
|
+
throw new TurnNotFoundError2(keys.turn_id);
|
|
704
702
|
}
|
|
705
703
|
throw new TurnNotRunningError(keys.turn_id, terminalTurnState(state, keys.turn_id));
|
|
706
704
|
}
|
|
707
705
|
async function classifyTurnThreadWriteFailure(db, keys, thread_id) {
|
|
708
706
|
const state = await loadTurnState(db, keys);
|
|
709
707
|
if (!state) {
|
|
710
|
-
throw new
|
|
708
|
+
throw new TurnNotFoundError2(keys.turn_id);
|
|
711
709
|
}
|
|
712
710
|
if (state.status !== "running") {
|
|
713
711
|
throw new TurnNotRunningError(keys.turn_id, terminalTurnState(state, keys.turn_id));
|
|
@@ -717,7 +715,7 @@ async function classifyTurnThreadWriteFailure(db, keys, thread_id) {
|
|
|
717
715
|
async function assertTurnRunning(db, keys) {
|
|
718
716
|
const state = await loadTurnState(db, keys);
|
|
719
717
|
if (!state) {
|
|
720
|
-
throw new
|
|
718
|
+
throw new TurnNotFoundError2(keys.turn_id);
|
|
721
719
|
}
|
|
722
720
|
if (state.status !== "running") {
|
|
723
721
|
throw new TurnNotRunningError(keys.turn_id, terminalTurnState(state, keys.turn_id));
|
|
@@ -1048,7 +1046,7 @@ async function freezeAndGetTurn(db, input) {
|
|
|
1048
1046
|
return await db.transaction().execute(async (trx) => {
|
|
1049
1047
|
const cancelledState = {
|
|
1050
1048
|
status: "cancelled",
|
|
1051
|
-
reason:
|
|
1049
|
+
reason: input.reason,
|
|
1052
1050
|
completed_at: nowIso()
|
|
1053
1051
|
};
|
|
1054
1052
|
const updateResult = await trx.updateTable("turn").set({
|
|
@@ -1066,7 +1064,7 @@ async function freezeAndGetTurn(db, input) {
|
|
|
1066
1064
|
}
|
|
1067
1065
|
const record = await assembleTurnRecord(trx, input);
|
|
1068
1066
|
if (!record) {
|
|
1069
|
-
throw new
|
|
1067
|
+
throw new TurnNotFoundError2(input.turn_id);
|
|
1070
1068
|
}
|
|
1071
1069
|
return record;
|
|
1072
1070
|
});
|
|
@@ -1116,7 +1114,7 @@ async function updateTurnState(db, input) {
|
|
|
1116
1114
|
if (numUpdated === 0) {
|
|
1117
1115
|
const existing = await trx.selectFrom("turn").select([jsonText(sql2.ref("state")).as("state")]).where("session_id", "=", input.session_id).where("turn_id", "=", input.turn_id).executeTakeFirst();
|
|
1118
1116
|
if (!existing) {
|
|
1119
|
-
throw new
|
|
1117
|
+
throw new TurnNotFoundError2(input.turn_id);
|
|
1120
1118
|
}
|
|
1121
1119
|
throw new TurnNotRunningError(input.turn_id, terminalTurnState(existing.state, input.turn_id));
|
|
1122
1120
|
}
|
|
@@ -1182,7 +1180,7 @@ import {
|
|
|
1182
1180
|
} from "@truefoundry/trueforge-core/agent-session/store/SessionEventPageToken";
|
|
1183
1181
|
import {
|
|
1184
1182
|
SessionNotFoundError as SessionNotFoundError2,
|
|
1185
|
-
TurnNotFoundError as
|
|
1183
|
+
TurnNotFoundError as TurnNotFoundError3
|
|
1186
1184
|
} from "@truefoundry/trueforge-core/agent-session/store/SessionStoreErrors";
|
|
1187
1185
|
import { sql as sql4 } from "kysely";
|
|
1188
1186
|
async function appendToEvents(db, input) {
|
|
@@ -1217,7 +1215,7 @@ async function listTurnEvents(db, input) {
|
|
|
1217
1215
|
(join) => join.onRef("e.session_id", "=", "t.session_id").onRef("e.turn_id", "=", "t.turn_id")
|
|
1218
1216
|
).select(["t.turn_id", "e.event"]).where("t.session_id", "=", input.session_id).where("t.turn_id", "=", input.turn_id).orderBy("e.event_id", eventOrder).execute();
|
|
1219
1217
|
if (rows.length === 0) {
|
|
1220
|
-
throw new
|
|
1218
|
+
throw new TurnNotFoundError3(input.turn_id);
|
|
1221
1219
|
}
|
|
1222
1220
|
const events = [];
|
|
1223
1221
|
for (const row of rows) {
|
|
@@ -1265,7 +1263,7 @@ async function listSessionEvents(db, input) {
|
|
|
1265
1263
|
};
|
|
1266
1264
|
const anchor = await db.selectFrom("turn").select(["turn_id", jsonText(sql4.ref("ancestor_ids")).as("ancestor_ids")]).where("session_id", "=", input.session_id).where("turn_id", "=", cursor.last_turn_id).executeTakeFirst();
|
|
1267
1265
|
if (!anchor) {
|
|
1268
|
-
throw new
|
|
1266
|
+
throw new TurnNotFoundError3(cursor.last_turn_id);
|
|
1269
1267
|
}
|
|
1270
1268
|
const chainIds = await resolveAncestorChain(db, input.session_id, {
|
|
1271
1269
|
turn_id: anchor.turn_id,
|
|
@@ -2104,6 +2102,9 @@ async function consumePendingAuthorization(db, params) {
|
|
|
2104
2102
|
...fromStoredOAuthPendingAuthorizationData(row.auth_data)
|
|
2105
2103
|
};
|
|
2106
2104
|
}
|
|
2105
|
+
async function deletePendingAuthorizationsForServer(db, params) {
|
|
2106
|
+
await db.deleteFrom("oauth_pending_authorization").where("oauth_server_id", "=", params.id).execute();
|
|
2107
|
+
}
|
|
2107
2108
|
var init_pendingAuthorization = __esm({
|
|
2108
2109
|
"src/db/sqlite/token-store/queries/pendingAuthorization.ts"() {
|
|
2109
2110
|
"use strict";
|
|
@@ -2141,6 +2142,9 @@ async function getTokens(db, params) {
|
|
|
2141
2142
|
async function deleteToken(db, params) {
|
|
2142
2143
|
await db.deleteFrom("oauth_token").where("oauth_server_id", "=", params.id).where("user_id", "=", params.userRef).execute();
|
|
2143
2144
|
}
|
|
2145
|
+
async function deleteTokensForServer(db, params) {
|
|
2146
|
+
await db.deleteFrom("oauth_token").where("oauth_server_id", "=", params.id).execute();
|
|
2147
|
+
}
|
|
2144
2148
|
var init_token = __esm({
|
|
2145
2149
|
"src/db/sqlite/token-store/queries/token.ts"() {
|
|
2146
2150
|
"use strict";
|
|
@@ -2189,6 +2193,12 @@ var init_SqliteOAuthTokenStore = __esm({
|
|
|
2189
2193
|
deleteToken(params, transaction) {
|
|
2190
2194
|
return deleteToken(transaction ?? this.db, params);
|
|
2191
2195
|
}
|
|
2196
|
+
deleteTokensForServer(params, transaction) {
|
|
2197
|
+
return deleteTokensForServer(transaction ?? this.db, params);
|
|
2198
|
+
}
|
|
2199
|
+
deletePendingAuthorizationsForServer(params, transaction) {
|
|
2200
|
+
return deletePendingAuthorizationsForServer(transaction ?? this.db, params);
|
|
2201
|
+
}
|
|
2192
2202
|
};
|
|
2193
2203
|
}
|
|
2194
2204
|
});
|
|
@@ -2522,12 +2532,12 @@ var redis_exports = {};
|
|
|
2522
2532
|
__export(redis_exports, {
|
|
2523
2533
|
connectRedis: () => connectRedis
|
|
2524
2534
|
});
|
|
2525
|
-
import { extractErrorLogFields as
|
|
2535
|
+
import { extractErrorLogFields as extractErrorLogFields8 } from "@truefoundry/trueforge-core/core";
|
|
2526
2536
|
import { createClient } from "redis";
|
|
2527
2537
|
async function connectRedis(input) {
|
|
2528
2538
|
const client = createClient({ url: input.url });
|
|
2529
2539
|
client.on("error", (error) => {
|
|
2530
|
-
input.logger.error("[Redis] Client error",
|
|
2540
|
+
input.logger.error("[Redis] Client error", extractErrorLogFields8(error));
|
|
2531
2541
|
});
|
|
2532
2542
|
await client.connect();
|
|
2533
2543
|
return client;
|
|
@@ -2589,9 +2599,7 @@ var init_sqlExpressions4 = __esm({
|
|
|
2589
2599
|
});
|
|
2590
2600
|
|
|
2591
2601
|
// src/db/postgres/session-store/queries/turns.ts
|
|
2592
|
-
import
|
|
2593
|
-
CancellationReason as CancellationReason5
|
|
2594
|
-
} from "@truefoundry/trueforge-core/agent-session/schemas/turn";
|
|
2602
|
+
import "@truefoundry/trueforge-core/agent-session/schemas/turn";
|
|
2595
2603
|
import { assertCreateTurnThreadDelta as assertCreateTurnThreadDelta2 } from "@truefoundry/trueforge-core/agent-session/store/assertCreateTurnThreadDelta";
|
|
2596
2604
|
import {
|
|
2597
2605
|
PreviousTurnRunningError as PreviousTurnRunningError2,
|
|
@@ -2600,7 +2608,7 @@ import {
|
|
|
2600
2608
|
SessionStoreInvariantError as SessionStoreInvariantError4,
|
|
2601
2609
|
SessionStoreNotFoundError as SessionStoreNotFoundError4,
|
|
2602
2610
|
TurnAlreadyExistsError as TurnAlreadyExistsError2,
|
|
2603
|
-
TurnNotFoundError as
|
|
2611
|
+
TurnNotFoundError as TurnNotFoundError4,
|
|
2604
2612
|
TurnNotRunningError as TurnNotRunningError2
|
|
2605
2613
|
} from "@truefoundry/trueforge-core/agent-session/store/SessionStoreErrors";
|
|
2606
2614
|
import { getEmptyCurrentContextUsage as getEmptyCurrentContextUsage2 } from "@truefoundry/trueforge-core/core/runtime/contextUsage";
|
|
@@ -2633,14 +2641,14 @@ function turnRunningFence(db, keys) {
|
|
|
2633
2641
|
async function classifyTurnFenceWriteFailure2(db, keys) {
|
|
2634
2642
|
const row = await db.selectFrom("turn").select("state").where("session_id", "=", keys.session_id).where("turn_id", "=", keys.turn_id).executeTakeFirst();
|
|
2635
2643
|
if (!row) {
|
|
2636
|
-
throw new
|
|
2644
|
+
throw new TurnNotFoundError4(keys.turn_id);
|
|
2637
2645
|
}
|
|
2638
2646
|
throw new TurnNotRunningError2(keys.turn_id, terminalTurnState2(row.state, keys.turn_id));
|
|
2639
2647
|
}
|
|
2640
2648
|
async function classifyTurnThreadWriteFailure2(db, keys, thread_id) {
|
|
2641
2649
|
const row = await db.selectFrom("turn").select("state").where("session_id", "=", keys.session_id).where("turn_id", "=", keys.turn_id).executeTakeFirst();
|
|
2642
2650
|
if (!row) {
|
|
2643
|
-
throw new
|
|
2651
|
+
throw new TurnNotFoundError4(keys.turn_id);
|
|
2644
2652
|
}
|
|
2645
2653
|
if (row.state.status !== "running") {
|
|
2646
2654
|
throw new TurnNotRunningError2(keys.turn_id, terminalTurnState2(row.state, keys.turn_id));
|
|
@@ -2650,7 +2658,7 @@ async function classifyTurnThreadWriteFailure2(db, keys, thread_id) {
|
|
|
2650
2658
|
async function assertTurnRunning2(db, keys) {
|
|
2651
2659
|
const row = await db.selectFrom("turn").select("state").where("session_id", "=", keys.session_id).where("turn_id", "=", keys.turn_id).forShare().executeTakeFirst();
|
|
2652
2660
|
if (!row) {
|
|
2653
|
-
throw new
|
|
2661
|
+
throw new TurnNotFoundError4(keys.turn_id);
|
|
2654
2662
|
}
|
|
2655
2663
|
if (row.state.status !== "running") {
|
|
2656
2664
|
throw new TurnNotRunningError2(keys.turn_id, terminalTurnState2(row.state, keys.turn_id));
|
|
@@ -2905,7 +2913,7 @@ async function freezeAndGetTurn2(db, input) {
|
|
|
2905
2913
|
return await db.transaction().execute(async (trx) => {
|
|
2906
2914
|
const cancelledState = {
|
|
2907
2915
|
status: "cancelled",
|
|
2908
|
-
reason:
|
|
2916
|
+
reason: input.reason,
|
|
2909
2917
|
completed_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
2910
2918
|
};
|
|
2911
2919
|
const updateResult = await trx.updateTable("turn").set({
|
|
@@ -2923,7 +2931,7 @@ async function freezeAndGetTurn2(db, input) {
|
|
|
2923
2931
|
}
|
|
2924
2932
|
const record = await assembleTurnRecord2(trx, input);
|
|
2925
2933
|
if (!record) {
|
|
2926
|
-
throw new
|
|
2934
|
+
throw new TurnNotFoundError4(input.turn_id);
|
|
2927
2935
|
}
|
|
2928
2936
|
return record;
|
|
2929
2937
|
});
|
|
@@ -2964,7 +2972,7 @@ async function updateTurnState2(db, input) {
|
|
|
2964
2972
|
if (numUpdated === 0) {
|
|
2965
2973
|
const existing = await trx.selectFrom("turn").select("state").where("session_id", "=", input.session_id).where("turn_id", "=", input.turn_id).executeTakeFirst();
|
|
2966
2974
|
if (!existing) {
|
|
2967
|
-
throw new
|
|
2975
|
+
throw new TurnNotFoundError4(input.turn_id);
|
|
2968
2976
|
}
|
|
2969
2977
|
throw new TurnNotRunningError2(input.turn_id, terminalTurnState2(existing.state, input.turn_id));
|
|
2970
2978
|
}
|
|
@@ -3032,7 +3040,7 @@ import {
|
|
|
3032
3040
|
} from "@truefoundry/trueforge-core/agent-session/store/SessionEventPageToken";
|
|
3033
3041
|
import {
|
|
3034
3042
|
SessionNotFoundError as SessionNotFoundError5,
|
|
3035
|
-
TurnNotFoundError as
|
|
3043
|
+
TurnNotFoundError as TurnNotFoundError5
|
|
3036
3044
|
} from "@truefoundry/trueforge-core/agent-session/store/SessionStoreErrors";
|
|
3037
3045
|
import { sql as sql13 } from "kysely";
|
|
3038
3046
|
async function appendToEvents2(db, input) {
|
|
@@ -3071,7 +3079,7 @@ async function listTurnEvents2(db, input) {
|
|
|
3071
3079
|
(join) => join.onRef("e.session_id", "=", "t.session_id").onRef("e.turn_id", "=", "t.turn_id")
|
|
3072
3080
|
).select(["t.turn_id", "e.event"]).where("t.session_id", "=", input.session_id).where("t.turn_id", "=", input.turn_id).orderBy("e.event_id", eventOrder).execute();
|
|
3073
3081
|
if (rows.length === 0) {
|
|
3074
|
-
throw new
|
|
3082
|
+
throw new TurnNotFoundError5(input.turn_id);
|
|
3075
3083
|
}
|
|
3076
3084
|
const events = [];
|
|
3077
3085
|
for (const row of rows) {
|
|
@@ -3098,7 +3106,7 @@ async function listSessionEvents2(db, input) {
|
|
|
3098
3106
|
};
|
|
3099
3107
|
const anchor = await db.selectFrom("turn").select(["turn_id", "ancestor_ids"]).where("session_id", "=", input.session_id).where("turn_id", "=", cursor.last_turn_id).executeTakeFirst();
|
|
3100
3108
|
if (!anchor) {
|
|
3101
|
-
throw new
|
|
3109
|
+
throw new TurnNotFoundError5(cursor.last_turn_id);
|
|
3102
3110
|
}
|
|
3103
3111
|
const chainIds = await resolveAncestorChain2(db, input.session_id, anchor);
|
|
3104
3112
|
const rows = await db.selectFrom(unnestWithOrdinality(chainIds, "c")).innerJoin(
|
|
@@ -3877,6 +3885,9 @@ async function consumePendingAuthorization2(db, params) {
|
|
|
3877
3885
|
...fromStoredOAuthPendingAuthorizationData(row.auth_data)
|
|
3878
3886
|
};
|
|
3879
3887
|
}
|
|
3888
|
+
async function deletePendingAuthorizationsForServer2(db, params) {
|
|
3889
|
+
await db.deleteFrom("oauth_pending_authorization").where("oauth_server_id", "=", params.id).execute();
|
|
3890
|
+
}
|
|
3880
3891
|
var init_pendingAuthorization2 = __esm({
|
|
3881
3892
|
"src/db/postgres/token-store/queries/pendingAuthorization.ts"() {
|
|
3882
3893
|
"use strict";
|
|
@@ -3914,6 +3925,9 @@ async function getTokens2(db, params) {
|
|
|
3914
3925
|
async function deleteToken2(db, params) {
|
|
3915
3926
|
await db.deleteFrom("oauth_token").where("oauth_server_id", "=", params.id).where("user_id", "=", params.userRef).execute();
|
|
3916
3927
|
}
|
|
3928
|
+
async function deleteTokensForServer2(db, params) {
|
|
3929
|
+
await db.deleteFrom("oauth_token").where("oauth_server_id", "=", params.id).execute();
|
|
3930
|
+
}
|
|
3917
3931
|
var init_token2 = __esm({
|
|
3918
3932
|
"src/db/postgres/token-store/queries/token.ts"() {
|
|
3919
3933
|
"use strict";
|
|
@@ -3962,6 +3976,12 @@ var init_PostgresOAuthTokenStore = __esm({
|
|
|
3962
3976
|
deleteToken(params, transaction) {
|
|
3963
3977
|
return deleteToken2(transaction ?? this.db, params);
|
|
3964
3978
|
}
|
|
3979
|
+
deleteTokensForServer(params, transaction) {
|
|
3980
|
+
return deleteTokensForServer2(transaction ?? this.db, params);
|
|
3981
|
+
}
|
|
3982
|
+
deletePendingAuthorizationsForServer(params, transaction) {
|
|
3983
|
+
return deletePendingAuthorizationsForServer2(transaction ?? this.db, params);
|
|
3984
|
+
}
|
|
3965
3985
|
};
|
|
3966
3986
|
}
|
|
3967
3987
|
});
|
|
@@ -4197,12 +4217,12 @@ var init_PostgresAgentStore = __esm({
|
|
|
4197
4217
|
});
|
|
4198
4218
|
|
|
4199
4219
|
// src/main.ts
|
|
4200
|
-
import { extractErrorLogFields as
|
|
4220
|
+
import { extractErrorLogFields as extractErrorLogFields9 } from "@truefoundry/trueforge-core/core";
|
|
4201
4221
|
import { mkdir } from "fs/promises";
|
|
4202
4222
|
import path6 from "path";
|
|
4203
4223
|
import { serve } from "@hono/node-server";
|
|
4204
4224
|
import {
|
|
4205
|
-
CancellationReason as
|
|
4225
|
+
CancellationReason as CancellationReason4,
|
|
4206
4226
|
Sessions
|
|
4207
4227
|
} from "@truefoundry/trueforge-core/agent-session";
|
|
4208
4228
|
import { RequestReplyExecutor, RequestReplyRouter } from "@truefoundry/trueforge-core/request-reply";
|
|
@@ -4210,9 +4230,9 @@ import { RequestReplyExecutor, RequestReplyRouter } from "@truefoundry/trueforge
|
|
|
4210
4230
|
// src/app.ts
|
|
4211
4231
|
import { swaggerUI } from "@hono/swagger-ui";
|
|
4212
4232
|
import { OpenAPIHono as OpenAPIHono14, z as z24 } from "@hono/zod-openapi";
|
|
4213
|
-
import { extractErrorLogFields as
|
|
4233
|
+
import { extractErrorLogFields as extractErrorLogFields7 } from "@truefoundry/trueforge-core/core";
|
|
4214
4234
|
import { bodyLimit } from "hono/body-limit";
|
|
4215
|
-
import { HTTPException as
|
|
4235
|
+
import { HTTPException as HTTPException5 } from "hono/http-exception";
|
|
4216
4236
|
|
|
4217
4237
|
// src/apis/agents.ts
|
|
4218
4238
|
init_agentStore();
|
|
@@ -4491,19 +4511,6 @@ function isOAuthAccessTokenUsable(expiresAtIso, nowMs) {
|
|
|
4491
4511
|
const expiresAtMs = Date.parse(expiresAtIso);
|
|
4492
4512
|
return !Number.isNaN(expiresAtMs) && expiresAtMs > nowMs;
|
|
4493
4513
|
}
|
|
4494
|
-
function validateRedirectUris({ redirectUris }) {
|
|
4495
|
-
for (const redirectUri of redirectUris) {
|
|
4496
|
-
let parsed;
|
|
4497
|
-
try {
|
|
4498
|
-
parsed = new URL(redirectUri);
|
|
4499
|
-
} catch (error) {
|
|
4500
|
-
throw new McpConnectionError(`Invalid redirect URI: ${redirectUri}. Must be a valid URL.`, 400, { cause: error });
|
|
4501
|
-
}
|
|
4502
|
-
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
4503
|
-
throw new McpConnectionError(`Invalid redirect URI: ${redirectUri}. Must be a valid URL.`, 400);
|
|
4504
|
-
}
|
|
4505
|
-
}
|
|
4506
|
-
}
|
|
4507
4514
|
|
|
4508
4515
|
// src/mcp/auth/mcpDcr.ts
|
|
4509
4516
|
var MCP_OAUTH_HTTP_TIMEOUT_MS = 15e3;
|
|
@@ -4654,7 +4661,7 @@ async function buildMcpAuthorizationUrl(params) {
|
|
|
4654
4661
|
userRef: params.userRef,
|
|
4655
4662
|
mcpServerUrl: params.mcpServerUrl,
|
|
4656
4663
|
codeVerifier: started.codeVerifier,
|
|
4657
|
-
|
|
4664
|
+
returnTo: params.returnTo ?? null
|
|
4658
4665
|
});
|
|
4659
4666
|
return started.authorizationUrl;
|
|
4660
4667
|
}
|
|
@@ -4697,7 +4704,7 @@ async function resolveMcpAuth(params) {
|
|
|
4697
4704
|
userRef: params.userRef,
|
|
4698
4705
|
mcpServerUrl: params.mcpServerUrl,
|
|
4699
4706
|
mcpServerName: params.mcpServerName,
|
|
4700
|
-
...params.
|
|
4707
|
+
...params.returnTo !== void 0 ? { returnTo: params.returnTo } : {}
|
|
4701
4708
|
});
|
|
4702
4709
|
return { authUrl };
|
|
4703
4710
|
}
|
|
@@ -5084,9 +5091,7 @@ function buildTurnSandbox(input) {
|
|
|
5084
5091
|
blockDestructiveToolsInCodeMode: true,
|
|
5085
5092
|
mcpRequestTimeoutMs: config_default.MCP_REQUEST_TIMEOUT_MS,
|
|
5086
5093
|
mcpConnectTimeoutMs: config_default.MCP_CONNECT_TIMEOUT_MS,
|
|
5087
|
-
|
|
5088
|
-
// against provider-created sandbox ids (`<tenant>.<uuid>`).
|
|
5089
|
-
execExtraEnv: { TFY_TENANT_NAME: input.tenantName },
|
|
5094
|
+
tenantName: input.tenantName,
|
|
5090
5095
|
...skillMounter ? { skillMounter } : {},
|
|
5091
5096
|
tracing: input.tracing,
|
|
5092
5097
|
logger: input.logger
|
|
@@ -5170,10 +5175,14 @@ import {
|
|
|
5170
5175
|
CancellationReason,
|
|
5171
5176
|
SessionStoreConflictError,
|
|
5172
5177
|
SessionStoreInvariantError,
|
|
5173
|
-
SessionStoreNotFoundError
|
|
5178
|
+
SessionStoreNotFoundError,
|
|
5179
|
+
TurnNotFoundError
|
|
5174
5180
|
} from "@truefoundry/trueforge-core/agent-session";
|
|
5175
|
-
import {
|
|
5176
|
-
import {
|
|
5181
|
+
import { extractErrorLogFields } from "@truefoundry/trueforge-core/core";
|
|
5182
|
+
import {
|
|
5183
|
+
redisRequest,
|
|
5184
|
+
RequestTimeoutError
|
|
5185
|
+
} from "@truefoundry/trueforge-core/request-reply";
|
|
5177
5186
|
import { ulid as ulid2 } from "ulid";
|
|
5178
5187
|
import { z as z11 } from "zod";
|
|
5179
5188
|
|
|
@@ -5594,7 +5603,8 @@ function cancelSessionTurnPeerHandler(activeTurns) {
|
|
|
5594
5603
|
};
|
|
5595
5604
|
}
|
|
5596
5605
|
async function cancelSessionTurn(deps, input) {
|
|
5597
|
-
const {
|
|
5606
|
+
const { turnId, reason = CancellationReason.ClientCancelled } = input;
|
|
5607
|
+
const sessionId = deps.session.session_id;
|
|
5598
5608
|
const turn = await deps.sessionStore.getTurn({
|
|
5599
5609
|
session_id: sessionId,
|
|
5600
5610
|
turn_id: turnId
|
|
@@ -5617,33 +5627,39 @@ async function cancelSessionTurn(deps, input) {
|
|
|
5617
5627
|
pollIntervalMs: config_default.REDIS_REQUEST_REPLY_POLL_INTERVAL_MS
|
|
5618
5628
|
}
|
|
5619
5629
|
});
|
|
5620
|
-
if (reply.status
|
|
5621
|
-
|
|
5630
|
+
if (reply.status === 200) {
|
|
5631
|
+
return;
|
|
5622
5632
|
}
|
|
5623
5633
|
} catch (error) {
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
}
|
|
5634
|
+
const fields = {
|
|
5635
|
+
sessionId,
|
|
5636
|
+
turnId,
|
|
5637
|
+
owner,
|
|
5638
|
+
...extractErrorLogFields(error)
|
|
5639
|
+
};
|
|
5630
5640
|
if (error instanceof RequestTimeoutError) {
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
});
|
|
5635
|
-
}
|
|
5636
|
-
if (error instanceof HTTPException3) {
|
|
5637
|
-
throw error;
|
|
5641
|
+
deps.logger.warn("Timed out waiting for owning executor to cancel; freezing the running turn", fields);
|
|
5642
|
+
} else {
|
|
5643
|
+
deps.logger.warn("Failed to reach owning executor over Redis; freezing the running turn", fields);
|
|
5638
5644
|
}
|
|
5639
|
-
throw new HTTPException3(500, {
|
|
5640
|
-
message: `Unexpected error while cancelling the turn on the owning executor: ${owner}`,
|
|
5641
|
-
cause: error
|
|
5642
|
-
});
|
|
5643
5645
|
}
|
|
5646
|
+
await freezeTurnIgnoringMissing(deps.session, { turnId, reason });
|
|
5644
5647
|
return;
|
|
5645
5648
|
}
|
|
5646
|
-
cancelTurnOnThisExecutor(deps.activeTurns, { sessionId, turnId, reason });
|
|
5649
|
+
const aborted = cancelTurnOnThisExecutor(deps.activeTurns, { sessionId, turnId, reason });
|
|
5650
|
+
if (!aborted) {
|
|
5651
|
+
await freezeTurnIgnoringMissing(deps.session, { turnId, reason });
|
|
5652
|
+
}
|
|
5653
|
+
}
|
|
5654
|
+
async function freezeTurnIgnoringMissing(session, input) {
|
|
5655
|
+
try {
|
|
5656
|
+
await session.freezeTurn({ turn_id: input.turnId, reason: input.reason });
|
|
5657
|
+
} catch (error) {
|
|
5658
|
+
if (error instanceof TurnNotFoundError) {
|
|
5659
|
+
return;
|
|
5660
|
+
}
|
|
5661
|
+
throw error;
|
|
5662
|
+
}
|
|
5647
5663
|
}
|
|
5648
5664
|
var FORBIDDEN_SESSION_ACCESS = "Only the session creator can access this session";
|
|
5649
5665
|
function checkSessionAccess({ userRef, createdBy }) {
|
|
@@ -5773,18 +5789,18 @@ function createSessionsRouter(deps) {
|
|
|
5773
5789
|
};
|
|
5774
5790
|
const cancelSessionHandler = async (c) => {
|
|
5775
5791
|
const { session_id: sessionId } = c.req.valid("param");
|
|
5776
|
-
const
|
|
5777
|
-
if (!
|
|
5792
|
+
const session = await deps.sessions.get({ tenant_id: TENANT_ID, session_id: sessionId });
|
|
5793
|
+
if (!session) {
|
|
5778
5794
|
return c.json({ error: { message: `Session not found: ${sessionId}` } }, 404);
|
|
5779
5795
|
}
|
|
5780
|
-
if (!checkSessionAccess({ userRef: deps.resolveUserContext(c).userRef, createdBy: record.created_by })) {
|
|
5796
|
+
if (!checkSessionAccess({ userRef: deps.resolveUserContext(c).userRef, createdBy: session.record.created_by })) {
|
|
5781
5797
|
return c.json({ error: { message: FORBIDDEN_SESSION_ACCESS } }, 403);
|
|
5782
5798
|
}
|
|
5783
|
-
const turnId = record.last_turn_id;
|
|
5799
|
+
const turnId = session.record.last_turn_id;
|
|
5784
5800
|
if (!turnId) {
|
|
5785
5801
|
return c.json({}, 200);
|
|
5786
5802
|
}
|
|
5787
|
-
await cancelSessionTurn(deps,
|
|
5803
|
+
await cancelSessionTurn({ ...deps, session }, { turnId });
|
|
5788
5804
|
return c.json({}, 200);
|
|
5789
5805
|
};
|
|
5790
5806
|
const listSessionEventsHandler = async (c) => {
|
|
@@ -5908,7 +5924,7 @@ function createAgentsRouter(deps) {
|
|
|
5908
5924
|
|
|
5909
5925
|
// src/apis/auth.ts
|
|
5910
5926
|
import { OpenAPIHono as OpenAPIHono3 } from "@hono/zod-openapi";
|
|
5911
|
-
import { extractErrorLogFields } from "@truefoundry/trueforge-core/core";
|
|
5927
|
+
import { extractErrorLogFields as extractErrorLogFields2 } from "@truefoundry/trueforge-core/core";
|
|
5912
5928
|
|
|
5913
5929
|
// src/auth/cookies.ts
|
|
5914
5930
|
init_config();
|
|
@@ -6013,6 +6029,18 @@ function buildAuthorizationRequestParams(config) {
|
|
|
6013
6029
|
};
|
|
6014
6030
|
}
|
|
6015
6031
|
|
|
6032
|
+
// src/auth/safeReturnTo.ts
|
|
6033
|
+
var SAFE_RETURN_TO = /^\/(?!\/|api(?:\/|$)).*/;
|
|
6034
|
+
function isSafeReturnTo(value) {
|
|
6035
|
+
return SAFE_RETURN_TO.test(value);
|
|
6036
|
+
}
|
|
6037
|
+
function safeReturnTo(value) {
|
|
6038
|
+
if (value && isSafeReturnTo(value)) {
|
|
6039
|
+
return value;
|
|
6040
|
+
}
|
|
6041
|
+
return "/";
|
|
6042
|
+
}
|
|
6043
|
+
|
|
6016
6044
|
// src/auth/oidc.ts
|
|
6017
6045
|
var CALLBACK_PATH = "/api/v1/auth/callback";
|
|
6018
6046
|
var OAUTH_STATE_MAX_AGE_SECONDS = 10 * 60;
|
|
@@ -6049,13 +6077,6 @@ function authCallbackUrl() {
|
|
|
6049
6077
|
const publicBaseUrl = getPublicBaseUrl();
|
|
6050
6078
|
return `${publicBaseUrl}${CALLBACK_PATH}`;
|
|
6051
6079
|
}
|
|
6052
|
-
var SAFE_RETURN_TO = /^\/(?!\/|api(?:\/|$)).*/;
|
|
6053
|
-
function safeReturnTo(value) {
|
|
6054
|
-
if (value && SAFE_RETURN_TO.test(value)) {
|
|
6055
|
-
return value;
|
|
6056
|
-
}
|
|
6057
|
-
return "/";
|
|
6058
|
-
}
|
|
6059
6080
|
async function buildLoginAuthorization(params) {
|
|
6060
6081
|
const oidcConfig = getOidcVerify()?.oidcConfig;
|
|
6061
6082
|
if (!oidcConfig) {
|
|
@@ -6126,7 +6147,7 @@ function resolveUserContext(c) {
|
|
|
6126
6147
|
}
|
|
6127
6148
|
|
|
6128
6149
|
// src/auth/middleware.ts
|
|
6129
|
-
import { HTTPException as
|
|
6150
|
+
import { HTTPException as HTTPException3 } from "hono/http-exception";
|
|
6130
6151
|
import { jwtVerify } from "jose";
|
|
6131
6152
|
var AUTH_HEADER_TYPE = "Bearer";
|
|
6132
6153
|
function readBearerIdToken(c) {
|
|
@@ -6173,14 +6194,14 @@ var authMiddleware = async (c, next) => {
|
|
|
6173
6194
|
try {
|
|
6174
6195
|
const user = await resolveAuthUser(c);
|
|
6175
6196
|
if (!user) {
|
|
6176
|
-
throw new
|
|
6197
|
+
throw new HTTPException3(401, { message: "Authentication required" });
|
|
6177
6198
|
}
|
|
6178
6199
|
c.set("user_context", user);
|
|
6179
6200
|
} catch (error) {
|
|
6180
|
-
if (error instanceof
|
|
6201
|
+
if (error instanceof HTTPException3) {
|
|
6181
6202
|
throw error;
|
|
6182
6203
|
}
|
|
6183
|
-
throw new
|
|
6204
|
+
throw new HTTPException3(401, { message: "Authentication required", cause: error });
|
|
6184
6205
|
}
|
|
6185
6206
|
return next();
|
|
6186
6207
|
};
|
|
@@ -6192,17 +6213,17 @@ var adminAuthMiddleware = async (c, next) => {
|
|
|
6192
6213
|
try {
|
|
6193
6214
|
const user = await resolveAuthUser(c);
|
|
6194
6215
|
if (!user) {
|
|
6195
|
-
throw new
|
|
6216
|
+
throw new HTTPException3(401, { message: "Authentication required" });
|
|
6196
6217
|
}
|
|
6197
6218
|
if (!isAdmin(user)) {
|
|
6198
|
-
throw new
|
|
6219
|
+
throw new HTTPException3(403, { message: "Admin access required" });
|
|
6199
6220
|
}
|
|
6200
6221
|
c.set("user_context", user);
|
|
6201
6222
|
} catch (error) {
|
|
6202
|
-
if (error instanceof
|
|
6223
|
+
if (error instanceof HTTPException3) {
|
|
6203
6224
|
throw error;
|
|
6204
6225
|
}
|
|
6205
|
-
throw new
|
|
6226
|
+
throw new HTTPException3(401, { message: "Authentication required", cause: error });
|
|
6206
6227
|
}
|
|
6207
6228
|
return next();
|
|
6208
6229
|
};
|
|
@@ -6222,7 +6243,7 @@ var OAuthCallbackQuerySchema = z13.object({
|
|
|
6222
6243
|
error_description: z13.string().optional().describe("Human-readable error detail from the identity provider when `error` is set.")
|
|
6223
6244
|
});
|
|
6224
6245
|
var OAuthCallbackSuccessSchema = z13.object({
|
|
6225
|
-
success: z13.literal(true).describe("Present when the OAuth callback completed without a
|
|
6246
|
+
success: z13.literal(true).describe("Present when the OAuth callback completed without a return_to.")
|
|
6226
6247
|
});
|
|
6227
6248
|
var MeResponseSchema = z13.object({
|
|
6228
6249
|
type: z13.enum(["default", "oidc-connected"]).describe(
|
|
@@ -6308,7 +6329,7 @@ function createAuthRouter(params) {
|
|
|
6308
6329
|
});
|
|
6309
6330
|
return c.redirect(authorizationUrl, 302);
|
|
6310
6331
|
} catch (error) {
|
|
6311
|
-
params.logger.error("Failed to build login authorization",
|
|
6332
|
+
params.logger.error("Failed to build login authorization", extractErrorLogFields2(error));
|
|
6312
6333
|
return c.redirect(oauthErrorRedirect("login_failed"), 302);
|
|
6313
6334
|
}
|
|
6314
6335
|
});
|
|
@@ -6334,7 +6355,7 @@ function createAuthRouter(params) {
|
|
|
6334
6355
|
});
|
|
6335
6356
|
return c.redirect(safeReturnTo(pending.return_to), 302);
|
|
6336
6357
|
} catch (error) {
|
|
6337
|
-
params.logger.error("Failed to exchange authorization code",
|
|
6358
|
+
params.logger.error("Failed to exchange authorization code", extractErrorLogFields2(error));
|
|
6338
6359
|
const reason = error instanceof Error ? error.message : "login_failed";
|
|
6339
6360
|
return c.redirect(oauthErrorRedirect(reason), 302);
|
|
6340
6361
|
}
|
|
@@ -6356,7 +6377,7 @@ function createAuthRouter(params) {
|
|
|
6356
6377
|
|
|
6357
6378
|
// src/apis/capabilities.ts
|
|
6358
6379
|
import { OpenAPIHono as OpenAPIHono4 } from "@hono/zod-openapi";
|
|
6359
|
-
import { extractErrorLogFields as
|
|
6380
|
+
import { extractErrorLogFields as extractErrorLogFields3 } from "@truefoundry/trueforge-core/core";
|
|
6360
6381
|
|
|
6361
6382
|
// src/routes/capabilityRoutes.ts
|
|
6362
6383
|
import { createRoute as createRoute4, z as z14 } from "@hono/zod-openapi";
|
|
@@ -6413,7 +6434,7 @@ function createCapabilitiesRouter(deps) {
|
|
|
6413
6434
|
});
|
|
6414
6435
|
status = refreshed?.status;
|
|
6415
6436
|
} catch (error) {
|
|
6416
|
-
deps.logger.warn("Sandbox image status check failed; reporting sandbox disabled",
|
|
6437
|
+
deps.logger.warn("Sandbox image status check failed; reporting sandbox disabled", extractErrorLogFields3(error));
|
|
6417
6438
|
}
|
|
6418
6439
|
const sandboxEnabled = status === "ready";
|
|
6419
6440
|
const settingsEnabled = isAdmin(resolveUserContext(c));
|
|
@@ -6797,7 +6818,7 @@ function createCatalogRouter(deps) {
|
|
|
6797
6818
|
|
|
6798
6819
|
// src/apis/mcpOAuth.ts
|
|
6799
6820
|
import { OpenAPIHono as OpenAPIHono6 } from "@hono/zod-openapi";
|
|
6800
|
-
import { extractErrorLogFields as
|
|
6821
|
+
import { extractErrorLogFields as extractErrorLogFields4, McpConnectionError as McpConnectionError3 } from "@truefoundry/trueforge-core/core";
|
|
6801
6822
|
|
|
6802
6823
|
// src/routes/mcpOAuthRoutes.ts
|
|
6803
6824
|
import { createRoute as createRoute6 } from "@hono/zod-openapi";
|
|
@@ -6807,7 +6828,7 @@ var mcpOAuthCallbackRoute = createRoute6({
|
|
|
6807
6828
|
path: "/callback",
|
|
6808
6829
|
tags: [MCP_OAUTH_TAG],
|
|
6809
6830
|
summary: "OAuth callback for MCP authorization",
|
|
6810
|
-
description: "Browser redirect target for MCP server OAuth. The authorization server redirects here with `code`/`state` (or `error`). Exchanges the code for tokens, then either returns JSON or redirects to the `
|
|
6831
|
+
description: "Browser redirect target for MCP server OAuth. The authorization server redirects here with `code`/`state` (or `error`). Exchanges the code for tokens, then either returns JSON or redirects to the `return_to` path supplied at authorize time. Not called by the SDK \u2014 browsers hit this URL directly.",
|
|
6811
6832
|
// Browser-redirect target hit directly by the authorization server, never called by SDK.
|
|
6812
6833
|
"x-fern-ignore": true,
|
|
6813
6834
|
request: {
|
|
@@ -6816,10 +6837,10 @@ var mcpOAuthCallbackRoute = createRoute6({
|
|
|
6816
6837
|
responses: {
|
|
6817
6838
|
200: {
|
|
6818
6839
|
content: { "application/json": { schema: OAuthCallbackSuccessSchema } },
|
|
6819
|
-
description: "Token exchanged successfully and no `
|
|
6840
|
+
description: "Token exchanged successfully and no `return_to` was given at authorize time."
|
|
6820
6841
|
},
|
|
6821
6842
|
302: {
|
|
6822
|
-
description: "Redirect to the `
|
|
6843
|
+
description: "Redirect to the `return_to` path given at authorize time, with `isSuccess` (and `reason` when it failed) appended to its existing query params."
|
|
6823
6844
|
},
|
|
6824
6845
|
400: {
|
|
6825
6846
|
content: { "application/json": { schema: RequestErrorResponseSchema } },
|
|
@@ -6833,25 +6854,28 @@ var mcpOAuthCallbackRoute = createRoute6({
|
|
|
6833
6854
|
});
|
|
6834
6855
|
|
|
6835
6856
|
// src/apis/mcpOAuth.ts
|
|
6836
|
-
function
|
|
6837
|
-
const url = new URL(params.
|
|
6857
|
+
function callbackLandingPath(params) {
|
|
6858
|
+
const url = new URL(params.returnTo, params.c.req.url);
|
|
6838
6859
|
url.searchParams.set("isSuccess", String(params.isSuccess));
|
|
6839
6860
|
if (params.reason) {
|
|
6840
6861
|
url.searchParams.set("reason", params.reason);
|
|
6841
6862
|
}
|
|
6842
|
-
return url.
|
|
6863
|
+
return `${url.pathname}${url.search}`;
|
|
6843
6864
|
}
|
|
6844
6865
|
function callbackSuccess(params) {
|
|
6845
|
-
const
|
|
6846
|
-
if (
|
|
6847
|
-
return params.c.redirect(
|
|
6866
|
+
const returnTo = params.pending.returnTo;
|
|
6867
|
+
if (returnTo) {
|
|
6868
|
+
return params.c.redirect(callbackLandingPath({ c: params.c, returnTo, isSuccess: true }), 302);
|
|
6848
6869
|
}
|
|
6849
6870
|
return params.c.json({ success: true }, 200);
|
|
6850
6871
|
}
|
|
6851
6872
|
function callbackFailure(params) {
|
|
6852
|
-
const
|
|
6853
|
-
if (
|
|
6854
|
-
return params.c.redirect(
|
|
6873
|
+
const returnTo = params.pending?.returnTo;
|
|
6874
|
+
if (returnTo) {
|
|
6875
|
+
return params.c.redirect(
|
|
6876
|
+
callbackLandingPath({ c: params.c, returnTo, isSuccess: false, reason: params.message }),
|
|
6877
|
+
302
|
|
6878
|
+
);
|
|
6855
6879
|
}
|
|
6856
6880
|
return params.c.json({ error: { message: params.message } }, params.jsonStatus ?? 400);
|
|
6857
6881
|
}
|
|
@@ -6879,10 +6903,10 @@ function createMcpOAuthRouter(deps) {
|
|
|
6879
6903
|
});
|
|
6880
6904
|
} catch (err) {
|
|
6881
6905
|
if (err instanceof McpConnectionError3) {
|
|
6882
|
-
deps.logger.warn("MCP OAuth callback token exchange failed",
|
|
6906
|
+
deps.logger.warn("MCP OAuth callback token exchange failed", extractErrorLogFields4(err));
|
|
6883
6907
|
return callbackFailure({ c, pending, message: err.message });
|
|
6884
6908
|
}
|
|
6885
|
-
deps.logger.error("MCP OAuth callback unexpected failure",
|
|
6909
|
+
deps.logger.error("MCP OAuth callback unexpected failure", extractErrorLogFields4(err));
|
|
6886
6910
|
return callbackFailure({ c, pending, message: "Internal server error", jsonStatus: 500 });
|
|
6887
6911
|
}
|
|
6888
6912
|
return callbackSuccess({ c, pending });
|
|
@@ -6893,10 +6917,10 @@ function createMcpOAuthRouter(deps) {
|
|
|
6893
6917
|
}
|
|
6894
6918
|
|
|
6895
6919
|
// src/apis/mcpServers.ts
|
|
6920
|
+
import { OpenAPIHono as OpenAPIHono7 } from "@hono/zod-openapi";
|
|
6921
|
+
import { extractErrorLogFields as extractErrorLogFields5, isAuthRequired, McpConnectionError as McpConnectionError4, RemoteMCP } from "@truefoundry/trueforge-core/core";
|
|
6896
6922
|
init_config();
|
|
6897
6923
|
init_mcpServerStore();
|
|
6898
|
-
import { OpenAPIHono as OpenAPIHono7 } from "@hono/zod-openapi";
|
|
6899
|
-
import { extractErrorLogFields as extractErrorLogFields4, isAuthRequired, McpConnectionError as McpConnectionError4, RemoteMCP } from "@truefoundry/trueforge-core/core";
|
|
6900
6924
|
|
|
6901
6925
|
// src/routes/mcpServerRoutes.ts
|
|
6902
6926
|
import { createRoute as createRoute7, z as z21 } from "@hono/zod-openapi";
|
|
@@ -7069,7 +7093,9 @@ var listMcpServerToolsRoute = createRoute7({
|
|
|
7069
7093
|
}
|
|
7070
7094
|
});
|
|
7071
7095
|
var McpAuthorizeQuerySchema = z21.object({
|
|
7072
|
-
|
|
7096
|
+
return_to: z21.string().optional().describe(
|
|
7097
|
+
"Optional path to return to after OAuth. Must be a same-origin relative path; the OAuth callback redirects here with `isSuccess`/`reason` appended."
|
|
7098
|
+
)
|
|
7073
7099
|
});
|
|
7074
7100
|
var authorizeMcpServerRoute = createRoute7({
|
|
7075
7101
|
method: "get",
|
|
@@ -7078,7 +7104,7 @@ var authorizeMcpServerRoute = createRoute7({
|
|
|
7078
7104
|
summary: "Start (or short-circuit) the auth flow for an MCP server",
|
|
7079
7105
|
"x-fern-sdk-group-name": ["mcpServers"],
|
|
7080
7106
|
"x-fern-sdk-method-name": "authorize",
|
|
7081
|
-
description: "For servers without auth returns not_required, and for header credentials returns authenticated (no browser flow). For auth.type dcr, returns authenticated when a usable (or refreshable) token exists; otherwise runs DCR if needed and returns auth_required with an authorization URL. Optional
|
|
7107
|
+
description: "For servers without auth returns not_required, and for header credentials returns authenticated (no browser flow). For auth.type dcr, returns authenticated when a usable (or refreshable) token exists; otherwise runs DCR if needed and returns auth_required with an authorization URL. Optional return_to is where the OAuth callback then redirects the browser; without it the callback returns JSON.",
|
|
7082
7108
|
request: {
|
|
7083
7109
|
params: McpServerNameParamsSchema,
|
|
7084
7110
|
query: McpAuthorizeQuerySchema
|
|
@@ -7090,7 +7116,7 @@ var authorizeMcpServerRoute = createRoute7({
|
|
|
7090
7116
|
},
|
|
7091
7117
|
400: {
|
|
7092
7118
|
content: { "application/json": { schema: RequestErrorResponseSchema } },
|
|
7093
|
-
description: "Invalid
|
|
7119
|
+
description: "Invalid return_to."
|
|
7094
7120
|
},
|
|
7095
7121
|
404: {
|
|
7096
7122
|
content: { "application/json": { schema: RequestErrorResponseSchema } },
|
|
@@ -7110,13 +7136,13 @@ var authorizeMcpServerRoute = createRoute7({
|
|
|
7110
7136
|
}
|
|
7111
7137
|
}
|
|
7112
7138
|
});
|
|
7113
|
-
var
|
|
7139
|
+
var deleteAuthorizationMcpServerRoute = createRoute7({
|
|
7114
7140
|
method: "delete",
|
|
7115
7141
|
path: "/{name}/authorize",
|
|
7116
7142
|
tags: [MCP_SERVERS_TAG],
|
|
7117
7143
|
summary: "Disconnect OAuth for an MCP server",
|
|
7118
7144
|
"x-fern-sdk-group-name": ["mcpServers"],
|
|
7119
|
-
"x-fern-sdk-method-name": "
|
|
7145
|
+
"x-fern-sdk-method-name": "delete_authorization",
|
|
7120
7146
|
description: "For auth.type dcr, deletes the stored OAuth token and returns the server with auth_status auth_required, keeping the dynamically registered OAuth client so the next authorize can reuse it. No-op for header or no-auth servers (returns the server unchanged).",
|
|
7121
7147
|
request: {
|
|
7122
7148
|
params: McpServerNameParamsSchema
|
|
@@ -7274,7 +7300,7 @@ function createSettingsMcpServersRouter(deps) {
|
|
|
7274
7300
|
} catch (error) {
|
|
7275
7301
|
deps.logger.error(
|
|
7276
7302
|
`DCR client registration failed for "${incomingManifest.name}"; rejecting create`,
|
|
7277
|
-
|
|
7303
|
+
extractErrorLogFields5(error)
|
|
7278
7304
|
);
|
|
7279
7305
|
const message = error instanceof Error ? error.message : "Failed to register OAuth client for this MCP server";
|
|
7280
7306
|
return c.json({ error: { message } }, 422);
|
|
@@ -7330,9 +7356,9 @@ function createSettingsMcpServersRouter(deps) {
|
|
|
7330
7356
|
existing: existing?.manifest
|
|
7331
7357
|
});
|
|
7332
7358
|
let dcrClientToSave;
|
|
7359
|
+
const urlChanged = existing !== void 0 && existing.manifest.url !== manifest.url && manifest.auth?.type === "dcr";
|
|
7333
7360
|
if (manifest.auth?.type === "dcr") {
|
|
7334
7361
|
const existingClient = existing ? await deps.mcpServerStore.getClient({ id: existing.id }, transaction) : void 0;
|
|
7335
|
-
const urlChanged = existing && existing.manifest.url !== manifest.url;
|
|
7336
7362
|
const needsDcr = existingClient === void 0 || urlChanged;
|
|
7337
7363
|
if (needsDcr) {
|
|
7338
7364
|
dcrClientToSave = await createMcpOAuthClient({
|
|
@@ -7354,6 +7380,10 @@ function createSettingsMcpServersRouter(deps) {
|
|
|
7354
7380
|
if (dcrClientToSave !== void 0) {
|
|
7355
7381
|
await deps.mcpServerStore.saveClient({ id: saved.id, record: dcrClientToSave }, transaction);
|
|
7356
7382
|
}
|
|
7383
|
+
if (urlChanged) {
|
|
7384
|
+
await deps.tokenStore.deleteTokensForServer({ id: saved.id }, transaction);
|
|
7385
|
+
await deps.tokenStore.deletePendingAuthorizationsForServer({ id: saved.id }, transaction);
|
|
7386
|
+
}
|
|
7357
7387
|
return saved;
|
|
7358
7388
|
});
|
|
7359
7389
|
const token = record.manifest.auth?.type === "dcr" ? await deps.tokenStore.getToken({ id: record.id, userRef }) : void 0;
|
|
@@ -7365,7 +7395,7 @@ function createSettingsMcpServersRouter(deps) {
|
|
|
7365
7395
|
if (error instanceof McpConnectionError4) {
|
|
7366
7396
|
deps.logger.error(
|
|
7367
7397
|
`DCR client registration failed for "${incomingManifest.name}"; rejecting upsert`,
|
|
7368
|
-
|
|
7398
|
+
extractErrorLogFields5(error)
|
|
7369
7399
|
);
|
|
7370
7400
|
return c.json({ error: { message: error.message } }, 422);
|
|
7371
7401
|
}
|
|
@@ -7405,7 +7435,7 @@ function createSettingsMcpServersRouter(deps) {
|
|
|
7405
7435
|
return c.json({ data }, 200);
|
|
7406
7436
|
} catch (error) {
|
|
7407
7437
|
if (error instanceof McpConnectionError4) {
|
|
7408
|
-
deps.logger.warn(`MCP tools/list failed for "${name}"`,
|
|
7438
|
+
deps.logger.warn(`MCP tools/list failed for "${name}"`, extractErrorLogFields5(error));
|
|
7409
7439
|
if (error.statusCode === 401) {
|
|
7410
7440
|
return c.json({ error: { message: error.message } }, 422);
|
|
7411
7441
|
}
|
|
@@ -7425,7 +7455,7 @@ function createSettingsMcpServersRouter(deps) {
|
|
|
7425
7455
|
function createMcpServersRouter(deps) {
|
|
7426
7456
|
const authorizeHandler = async (c) => {
|
|
7427
7457
|
const { name } = c.req.valid("param");
|
|
7428
|
-
const {
|
|
7458
|
+
const { return_to: returnTo } = c.req.valid("query");
|
|
7429
7459
|
const userRef = deps.resolveUserContext(c).userRef;
|
|
7430
7460
|
const record = await deps.mcpServerStore.getServer({ tenant_id: TENANT_ID, name });
|
|
7431
7461
|
if (!record) {
|
|
@@ -7434,10 +7464,10 @@ function createMcpServersRouter(deps) {
|
|
|
7434
7464
|
if (record.manifest.auth?.type !== "dcr") {
|
|
7435
7465
|
return c.json(resolveMcpAuthStatus({ manifest: record.manifest }), 200);
|
|
7436
7466
|
}
|
|
7467
|
+
if (returnTo && safeReturnTo(returnTo) !== returnTo) {
|
|
7468
|
+
return c.json({ error: { message: "Invalid return_to: must be a same-origin relative path" } }, 400);
|
|
7469
|
+
}
|
|
7437
7470
|
try {
|
|
7438
|
-
if (redirectUrl) {
|
|
7439
|
-
validateRedirectUris({ redirectUris: [redirectUrl] });
|
|
7440
|
-
}
|
|
7441
7471
|
const result = await resolveMcpAuth({
|
|
7442
7472
|
tokenStore: deps.tokenStore,
|
|
7443
7473
|
mcpServerStore: deps.mcpServerStore,
|
|
@@ -7446,13 +7476,13 @@ function createMcpServersRouter(deps) {
|
|
|
7446
7476
|
mcpServerUrl: record.manifest.url,
|
|
7447
7477
|
mcpServerName: record.name,
|
|
7448
7478
|
clientName: config_default.MCP_DCR_OAUTH_CLIENT_NAME,
|
|
7449
|
-
...
|
|
7479
|
+
...returnTo !== void 0 ? { returnTo } : {}
|
|
7450
7480
|
});
|
|
7451
7481
|
const authStatus = isMcpAuthRequired(result) ? { status: "auth_required", authorization_url: result.authUrl.href } : { status: "authenticated" };
|
|
7452
7482
|
return c.json(authStatus, 200);
|
|
7453
7483
|
} catch (error) {
|
|
7454
7484
|
if (error instanceof McpConnectionError4) {
|
|
7455
|
-
deps.logger.warn(`MCP authorize failed for "${name}"`,
|
|
7485
|
+
deps.logger.warn(`MCP authorize failed for "${name}"`, extractErrorLogFields5(error));
|
|
7456
7486
|
if (error.statusCode === 400) {
|
|
7457
7487
|
return c.json({ error: { message: error.message } }, 400);
|
|
7458
7488
|
}
|
|
@@ -7464,11 +7494,11 @@ function createMcpServersRouter(deps) {
|
|
|
7464
7494
|
}
|
|
7465
7495
|
return c.json({ error: { message: error.message } }, 500);
|
|
7466
7496
|
}
|
|
7467
|
-
deps.logger.error(`MCP authorize unexpected failure for "${name}"`,
|
|
7497
|
+
deps.logger.error(`MCP authorize unexpected failure for "${name}"`, extractErrorLogFields5(error));
|
|
7468
7498
|
return c.json({ error: { message: "Internal server error" } }, 500);
|
|
7469
7499
|
}
|
|
7470
7500
|
};
|
|
7471
|
-
const
|
|
7501
|
+
const deleteAuthorizationHandler = async (c) => {
|
|
7472
7502
|
const { name } = c.req.valid("param");
|
|
7473
7503
|
const userRef = deps.resolveUserContext(c).userRef;
|
|
7474
7504
|
const record = await deps.mcpServerStore.getServer({ tenant_id: TENANT_ID, name });
|
|
@@ -7494,7 +7524,7 @@ function createMcpServersRouter(deps) {
|
|
|
7494
7524
|
);
|
|
7495
7525
|
});
|
|
7496
7526
|
router.openapi(authorizeMcpServerRoute, authorizeHandler);
|
|
7497
|
-
router.openapi(
|
|
7527
|
+
router.openapi(deleteAuthorizationMcpServerRoute, deleteAuthorizationHandler);
|
|
7498
7528
|
return router;
|
|
7499
7529
|
}
|
|
7500
7530
|
|
|
@@ -8067,7 +8097,7 @@ import {
|
|
|
8067
8097
|
} from "@truefoundry/trueforge-core/agent-session";
|
|
8068
8098
|
import {
|
|
8069
8099
|
AgentHarnessError,
|
|
8070
|
-
extractErrorLogFields as
|
|
8100
|
+
extractErrorLogFields as extractErrorLogFields6,
|
|
8071
8101
|
isAgentInputUserMessage,
|
|
8072
8102
|
isFileContentPart,
|
|
8073
8103
|
McpConnectionError as McpConnectionError5,
|
|
@@ -8075,7 +8105,7 @@ import {
|
|
|
8075
8105
|
validateSandboxOwnedByTenant,
|
|
8076
8106
|
VercelAILLM
|
|
8077
8107
|
} from "@truefoundry/trueforge-core/core";
|
|
8078
|
-
import { HTTPException as
|
|
8108
|
+
import { HTTPException as HTTPException4 } from "hono/http-exception";
|
|
8079
8109
|
import { streamSSE } from "hono/streaming";
|
|
8080
8110
|
|
|
8081
8111
|
// src/routes/turnRoutes.ts
|
|
@@ -8660,7 +8690,7 @@ function createTurnResolver(deps) {
|
|
|
8660
8690
|
userRef
|
|
8661
8691
|
});
|
|
8662
8692
|
if (connection === void 0) {
|
|
8663
|
-
throw new
|
|
8693
|
+
throw new HTTPException4(422, {
|
|
8664
8694
|
message: `Unknown MCP server "${name}" \u2014 not configured`
|
|
8665
8695
|
});
|
|
8666
8696
|
}
|
|
@@ -8675,14 +8705,14 @@ function createTurnResolver(deps) {
|
|
|
8675
8705
|
logger
|
|
8676
8706
|
});
|
|
8677
8707
|
if (provider === void 0) {
|
|
8678
|
-
throw new
|
|
8708
|
+
throw new HTTPException4(422, {
|
|
8679
8709
|
message: "no sandbox provider configured \u2014 PUT /settings/sandbox-providers"
|
|
8680
8710
|
});
|
|
8681
8711
|
}
|
|
8682
8712
|
if (existingSandboxId === void 0) {
|
|
8683
8713
|
const status = await checkSnapshotStatus({ store: sandboxProviderStore, tenant_id: TENANT_ID, logger });
|
|
8684
8714
|
if (status?.status !== "ready") {
|
|
8685
|
-
throw new
|
|
8715
|
+
throw new HTTPException4(422, {
|
|
8686
8716
|
message: status?.status === "failed" ? `sandbox image build failed (${status.status_reason ?? "unknown error"})` : "sandbox image is activating \u2014 retry shortly"
|
|
8687
8717
|
});
|
|
8688
8718
|
}
|
|
@@ -8705,7 +8735,7 @@ function createTurnResolver(deps) {
|
|
|
8705
8735
|
agent: async (agentId) => {
|
|
8706
8736
|
const record = await agentStore.getAgent({ tenant_id: TENANT_ID, id: agentId });
|
|
8707
8737
|
if (record === void 0) {
|
|
8708
|
-
throw new
|
|
8738
|
+
throw new HTTPException4(422, { message: `Agent not found: ${agentId}` });
|
|
8709
8739
|
}
|
|
8710
8740
|
return record.manifest;
|
|
8711
8741
|
},
|
|
@@ -8757,13 +8787,13 @@ async function drainTurnEvents(input) {
|
|
|
8757
8787
|
logger.warn("Turn stream ended after session/turn was removed", {
|
|
8758
8788
|
sessionId,
|
|
8759
8789
|
turnId,
|
|
8760
|
-
...
|
|
8790
|
+
...extractErrorLogFields6(error)
|
|
8761
8791
|
});
|
|
8762
8792
|
} else {
|
|
8763
8793
|
logger.error("Unexpected error in turn event drain", {
|
|
8764
8794
|
sessionId,
|
|
8765
8795
|
turnId,
|
|
8766
|
-
...
|
|
8796
|
+
...extractErrorLogFields6(error)
|
|
8767
8797
|
});
|
|
8768
8798
|
}
|
|
8769
8799
|
} finally {
|
|
@@ -8775,7 +8805,7 @@ function resolveAfterSequenceNumber(c, bodyAfterSequenceNumber) {
|
|
|
8775
8805
|
if (lastEventId) {
|
|
8776
8806
|
const sequenceNumber = Number(lastEventId);
|
|
8777
8807
|
if (!Number.isInteger(sequenceNumber) || sequenceNumber < 0) {
|
|
8778
|
-
throw new
|
|
8808
|
+
throw new HTTPException4(400, { message: "Invalid Last-Event-Id header" });
|
|
8779
8809
|
}
|
|
8780
8810
|
return sequenceNumber;
|
|
8781
8811
|
}
|
|
@@ -8867,7 +8897,7 @@ function createTurnsRouter(deps) {
|
|
|
8867
8897
|
return c.json({ error: { message: error.message } }, error.statusCode);
|
|
8868
8898
|
}
|
|
8869
8899
|
deps.logger.error("Sandbox file download failed", {
|
|
8870
|
-
...
|
|
8900
|
+
...extractErrorLogFields6(error),
|
|
8871
8901
|
sessionId,
|
|
8872
8902
|
turnId,
|
|
8873
8903
|
sandboxId,
|
|
@@ -9003,7 +9033,7 @@ function createTurnsRouter(deps) {
|
|
|
9003
9033
|
try {
|
|
9004
9034
|
await stream.writeSSE(turnEventSsePayload(event, sequenceNumber));
|
|
9005
9035
|
} catch (error) {
|
|
9006
|
-
deps.logger.error("SSE stream write error",
|
|
9036
|
+
deps.logger.error("SSE stream write error", extractErrorLogFields6(error));
|
|
9007
9037
|
shouldWriteToSSEStream = false;
|
|
9008
9038
|
}
|
|
9009
9039
|
}
|
|
@@ -9032,7 +9062,7 @@ function createTurnsRouter(deps) {
|
|
|
9032
9062
|
await turnEventStream.assertSubscribable();
|
|
9033
9063
|
} catch (error) {
|
|
9034
9064
|
if (error instanceof StreamGoneError) {
|
|
9035
|
-
throw new
|
|
9065
|
+
throw new HTTPException4(412, { message: error.message, cause: error });
|
|
9036
9066
|
}
|
|
9037
9067
|
throw error;
|
|
9038
9068
|
}
|
|
@@ -9061,7 +9091,7 @@ function createTurnsRouter(deps) {
|
|
|
9061
9091
|
}
|
|
9062
9092
|
} catch (error) {
|
|
9063
9093
|
if (!subscribeAbort.signal.aborted) {
|
|
9064
|
-
deps.logger.error("Unexpected error in turn subscribe SSE loop",
|
|
9094
|
+
deps.logger.error("Unexpected error in turn subscribe SSE loop", extractErrorLogFields6(error));
|
|
9065
9095
|
}
|
|
9066
9096
|
} finally {
|
|
9067
9097
|
clearTimeout(timeoutHandler);
|
|
@@ -9128,16 +9158,16 @@ function createAppErrorHandler(params) {
|
|
|
9128
9158
|
if (error instanceof z24.ZodError) {
|
|
9129
9159
|
return zodErrorResponse(c, error);
|
|
9130
9160
|
}
|
|
9131
|
-
if (error instanceof
|
|
9161
|
+
if (error instanceof HTTPException5) {
|
|
9132
9162
|
if (error.status >= 500) {
|
|
9133
9163
|
params.logger.error("Server API error", {
|
|
9134
9164
|
status: error.status,
|
|
9135
|
-
...
|
|
9165
|
+
...extractErrorLogFields7(error)
|
|
9136
9166
|
});
|
|
9137
9167
|
}
|
|
9138
9168
|
return c.json({ error: { message: error.message } }, error.status);
|
|
9139
9169
|
}
|
|
9140
|
-
params.logger.error("Unhandled error",
|
|
9170
|
+
params.logger.error("Unhandled error", extractErrorLogFields7(error));
|
|
9141
9171
|
return c.json({ error: { message: "Internal server error" } }, 500);
|
|
9142
9172
|
};
|
|
9143
9173
|
}
|
|
@@ -9289,7 +9319,8 @@ function createServerApp(deps) {
|
|
|
9289
9319
|
sandboxProviderStore: deps.sandboxProviderStore,
|
|
9290
9320
|
redis: deps.redis,
|
|
9291
9321
|
requestReplyRouter: deps.requestReplyRouter,
|
|
9292
|
-
resolveUserContext
|
|
9322
|
+
resolveUserContext,
|
|
9323
|
+
logger: deps.logger
|
|
9293
9324
|
})
|
|
9294
9325
|
)
|
|
9295
9326
|
);
|
|
@@ -10080,7 +10111,7 @@ try {
|
|
|
10080
10111
|
if (redis) {
|
|
10081
10112
|
requestReplySubscriber = redis.duplicate();
|
|
10082
10113
|
requestReplySubscriber.on("error", (error) => {
|
|
10083
|
-
logger.error("[RedisSubscriber] Client error",
|
|
10114
|
+
logger.error("[RedisSubscriber] Client error", extractErrorLogFields9(error));
|
|
10084
10115
|
});
|
|
10085
10116
|
await requestReplySubscriber.connect();
|
|
10086
10117
|
requestReplyExecutor = new RequestReplyExecutor({
|
|
@@ -10120,14 +10151,14 @@ try {
|
|
|
10120
10151
|
resolve();
|
|
10121
10152
|
});
|
|
10122
10153
|
});
|
|
10123
|
-
await activeTurns.shutdownAndWait(
|
|
10154
|
+
await activeTurns.shutdownAndWait(CancellationReason4.Abandoned);
|
|
10124
10155
|
await closed;
|
|
10125
10156
|
await requestReplyExecutor?.drain();
|
|
10126
10157
|
await requestReplySubscriber?.close().catch((error) => {
|
|
10127
|
-
logger.warn("[Redis] Error closing subscriber client during shutdown",
|
|
10158
|
+
logger.warn("[Redis] Error closing subscriber client during shutdown", extractErrorLogFields9(error));
|
|
10128
10159
|
});
|
|
10129
10160
|
await redis?.close().catch((error) => {
|
|
10130
|
-
logger.warn("[Redis] Error closing client during shutdown",
|
|
10161
|
+
logger.warn("[Redis] Error closing client during shutdown", extractErrorLogFields9(error));
|
|
10131
10162
|
});
|
|
10132
10163
|
await destroyDb();
|
|
10133
10164
|
process.exit(0);
|