@truefoundry/trueforge 0.1.0 → 0.1.2
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/README.md +30 -0
- package/dist/_frontend/assets/{ConnectorSettings-H37ZFC6Z-BoDzRBt-.js → ConnectorSettings-XEO5ZQO5-BXis0tQK.js} +1 -1
- package/dist/_frontend/assets/ConnectorSettings-XEO5ZQO5-BXis0tQK.js.br +0 -0
- package/dist/_frontend/assets/ConnectorSettings-XEO5ZQO5-BXis0tQK.js.gz +0 -0
- package/dist/_frontend/assets/{DockLayout-KEMFRWIR-2H2_fGVk.js → DockLayout-F2KYSY4U-D8P84kCr.js} +1 -1
- package/dist/_frontend/assets/{DrawerLayout-ZVWCKEIS-DFGUqK6q.js → DrawerLayout-FJ7XC2FU-ChH-Qykr.js} +2 -2
- package/dist/_frontend/assets/DrawerLayout-FJ7XC2FU-ChH-Qykr.js.br +0 -0
- package/dist/_frontend/assets/DrawerLayout-FJ7XC2FU-ChH-Qykr.js.gz +0 -0
- package/dist/_frontend/assets/{ModelSettings-QJMYHCMD-DaR_pzAb.js → ModelSettings-2QB7LE22-CDZku4g3.js} +1 -1
- package/dist/_frontend/assets/ModelSettings-2QB7LE22-CDZku4g3.js.br +0 -0
- package/dist/_frontend/assets/ModelSettings-2QB7LE22-CDZku4g3.js.gz +0 -0
- package/dist/_frontend/assets/{SandboxSettings-BUBMLW7Q-ChiNe2Y8.js → SandboxSettings-QDDIPRBP-CImJLa0r.js} +1 -1
- package/dist/_frontend/assets/SandboxSettings-QDDIPRBP-CImJLa0r.js.br +0 -0
- package/dist/_frontend/assets/SandboxSettings-QDDIPRBP-CImJLa0r.js.gz +0 -0
- package/dist/_frontend/assets/SettingsBuilder-4NF3Y7UZ-eXXDLQ6k.js +2 -0
- package/dist/_frontend/assets/SettingsBuilder-4NF3Y7UZ-eXXDLQ6k.js.br +0 -0
- package/dist/_frontend/assets/SettingsBuilder-4NF3Y7UZ-eXXDLQ6k.js.gz +0 -0
- package/dist/_frontend/assets/ShellRouteSync-T4WLY57Q-CetHx5EA.js +1 -0
- package/dist/_frontend/assets/ShellRouteSync-T4WLY57Q-CetHx5EA.js.br +0 -0
- package/dist/_frontend/assets/ShellRouteSync-T4WLY57Q-CetHx5EA.js.gz +0 -0
- package/dist/_frontend/assets/{SidebarLayout-F3XFXW7B-BQV8bkzL.js → SidebarLayout-KX6RSJTP-B8G4CTTb.js} +2 -2
- package/dist/_frontend/assets/SidebarLayout-KX6RSJTP-B8G4CTTb.js.br +0 -0
- package/dist/_frontend/assets/SidebarLayout-KX6RSJTP-B8G4CTTb.js.gz +0 -0
- package/dist/_frontend/assets/{SkillSettings-IRMGDFRG-ChKre3S8.js → SkillSettings-5EETEEDI-DbJE0Ms2.js} +1 -1
- package/dist/_frontend/assets/SkillSettings-5EETEEDI-DbJE0Ms2.js.br +0 -0
- package/dist/_frontend/assets/SkillSettings-5EETEEDI-DbJE0Ms2.js.gz +0 -0
- package/dist/_frontend/assets/TrueForgeUIWithRouter-IAQQTD5V-9G1rELmh.js +1 -0
- package/dist/_frontend/assets/{WidgetLayout-SZMABKIR-BRKArpEm.js → WidgetLayout-S6EK62TZ-BPf7T3wa.js} +1 -1
- package/dist/_frontend/assets/WidgetLayout-S6EK62TZ-BPf7T3wa.js.br +0 -0
- package/dist/_frontend/assets/WidgetLayout-S6EK62TZ-BPf7T3wa.js.gz +0 -0
- package/dist/_frontend/assets/chunk-62JRHF6Z-BUuLA42_.js +12 -0
- package/dist/_frontend/assets/chunk-62JRHF6Z-BUuLA42_.js.br +0 -0
- package/dist/_frontend/assets/chunk-62JRHF6Z-BUuLA42_.js.gz +0 -0
- package/dist/_frontend/assets/{chunk-7EEOWDLE-BIwInB6G.js → chunk-PTYEOSHT-C4gdhLwo.js} +2 -2
- package/dist/_frontend/assets/chunk-PTYEOSHT-C4gdhLwo.js.br +0 -0
- package/dist/_frontend/assets/chunk-PTYEOSHT-C4gdhLwo.js.gz +0 -0
- package/dist/_frontend/assets/chunk-X6U2Q7X5-DDlfUle1.js +4 -0
- package/dist/_frontend/assets/chunk-X6U2Q7X5-DDlfUle1.js.br +0 -0
- package/dist/_frontend/assets/chunk-X6U2Q7X5-DDlfUle1.js.gz +0 -0
- package/dist/_frontend/assets/{cssMode-Bb1lR8Ti.js → cssMode-C1whwlDW.js} +1 -1
- package/dist/_frontend/assets/cssMode-C1whwlDW.js.br +0 -0
- package/dist/_frontend/assets/cssMode-C1whwlDW.js.gz +0 -0
- package/dist/_frontend/assets/{freemarker2-BrrF7mKG.js → freemarker2-CaMIS9bY.js} +1 -1
- package/dist/_frontend/assets/freemarker2-CaMIS9bY.js.br +0 -0
- package/dist/_frontend/assets/freemarker2-CaMIS9bY.js.gz +0 -0
- package/dist/_frontend/assets/{handlebars-WQ7HMT1b.js → handlebars-Donx2d9H.js} +1 -1
- package/dist/_frontend/assets/handlebars-Donx2d9H.js.br +0 -0
- package/dist/_frontend/assets/handlebars-Donx2d9H.js.gz +0 -0
- package/dist/_frontend/assets/{html-CoOPnhCb.js → html-CtI8kZ6e.js} +1 -1
- package/dist/_frontend/assets/html-CtI8kZ6e.js.br +0 -0
- package/dist/_frontend/assets/html-CtI8kZ6e.js.gz +0 -0
- package/dist/_frontend/assets/{htmlMode-BW7taYty.js → htmlMode-B6ky8VkF.js} +1 -1
- package/dist/_frontend/assets/htmlMode-B6ky8VkF.js.br +0 -0
- package/dist/_frontend/assets/htmlMode-B6ky8VkF.js.gz +0 -0
- package/dist/_frontend/assets/{index-DFQqb6R1.js → index-DFmgzNuj.js} +3 -3
- package/dist/_frontend/assets/index-DFmgzNuj.js.br +0 -0
- package/dist/_frontend/assets/index-DFmgzNuj.js.gz +0 -0
- package/dist/_frontend/assets/index-DWr7ad72.js +859 -0
- package/dist/_frontend/assets/index-DWr7ad72.js.br +0 -0
- package/dist/_frontend/assets/index-DWr7ad72.js.gz +0 -0
- package/dist/_frontend/assets/{javascript-CPINtbIt.js → javascript-BDngdIws.js} +1 -1
- package/dist/_frontend/assets/{jsonMode-C8qDzOfb.js → jsonMode-B7OogXWW.js} +1 -1
- package/dist/_frontend/assets/jsonMode-B7OogXWW.js.br +0 -0
- package/dist/_frontend/assets/jsonMode-B7OogXWW.js.gz +0 -0
- package/dist/_frontend/assets/{liquid-zGC9H1Dt.js → liquid-D_8RkuUW.js} +1 -1
- package/dist/_frontend/assets/liquid-D_8RkuUW.js.br +0 -0
- package/dist/_frontend/assets/liquid-D_8RkuUW.js.gz +0 -0
- package/dist/_frontend/assets/{lspLanguageFeatures-B6VPH2Sv.js → lspLanguageFeatures-DJf8_W2N.js} +1 -1
- package/dist/_frontend/assets/lspLanguageFeatures-DJf8_W2N.js.br +0 -0
- package/dist/_frontend/assets/lspLanguageFeatures-DJf8_W2N.js.gz +0 -0
- package/dist/_frontend/assets/{mdx-BrQrGCP9.js → mdx-HcpZSZ2w.js} +1 -1
- package/dist/_frontend/assets/mdx-HcpZSZ2w.js.br +0 -0
- package/dist/_frontend/assets/mdx-HcpZSZ2w.js.gz +0 -0
- package/dist/_frontend/assets/{python-zKGpYLwR.js → python-CPiT1vB4.js} +1 -1
- package/dist/_frontend/assets/python-CPiT1vB4.js.br +0 -0
- package/dist/_frontend/assets/python-CPiT1vB4.js.gz +0 -0
- package/dist/_frontend/assets/{razor-BJ38lYsd.js → razor-oizHS-vq.js} +1 -1
- package/dist/_frontend/assets/razor-oizHS-vq.js.br +0 -0
- package/dist/_frontend/assets/razor-oizHS-vq.js.gz +0 -0
- package/dist/_frontend/assets/{tsMode-dPLqGMg8.js → tsMode-n5kkpKJX.js} +1 -1
- package/dist/_frontend/assets/tsMode-n5kkpKJX.js.br +0 -0
- package/dist/_frontend/assets/tsMode-n5kkpKJX.js.gz +0 -0
- package/dist/_frontend/assets/{typescript-BJlivWry.js → typescript-BfXupYGq.js} +1 -1
- package/dist/_frontend/assets/typescript-BfXupYGq.js.br +0 -0
- package/dist/_frontend/assets/typescript-BfXupYGq.js.gz +0 -0
- package/dist/_frontend/assets/{workers-fMwav4jB.js → workers-DCX6qMOc.js} +1 -1
- package/dist/_frontend/assets/workers-DCX6qMOc.js.br +0 -0
- package/dist/_frontend/assets/workers-DCX6qMOc.js.gz +0 -0
- package/dist/_frontend/assets/{xml-DZW470wi.js → xml-MX-qfsGl.js} +1 -1
- package/dist/_frontend/assets/xml-MX-qfsGl.js.br +0 -0
- package/dist/_frontend/assets/xml-MX-qfsGl.js.gz +0 -0
- package/dist/_frontend/assets/{yaml-Bs1DumYp.js → yaml-DnKyyO9e.js} +1 -1
- package/dist/_frontend/assets/yaml-DnKyyO9e.js.br +0 -0
- package/dist/_frontend/assets/yaml-DnKyyO9e.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/cli.js +23 -1
- package/dist/cli.js.map +1 -1
- package/dist/main.js +525 -178
- package/dist/main.js.map +1 -1
- package/package.json +11 -7
- package/dist/_frontend/assets/ConnectorSettings-H37ZFC6Z-BoDzRBt-.js.br +0 -0
- package/dist/_frontend/assets/ConnectorSettings-H37ZFC6Z-BoDzRBt-.js.gz +0 -0
- package/dist/_frontend/assets/DrawerLayout-ZVWCKEIS-DFGUqK6q.js.br +0 -0
- package/dist/_frontend/assets/DrawerLayout-ZVWCKEIS-DFGUqK6q.js.gz +0 -0
- package/dist/_frontend/assets/ModelSettings-QJMYHCMD-DaR_pzAb.js.br +0 -0
- package/dist/_frontend/assets/ModelSettings-QJMYHCMD-DaR_pzAb.js.gz +0 -0
- package/dist/_frontend/assets/SandboxSettings-BUBMLW7Q-ChiNe2Y8.js.br +0 -0
- package/dist/_frontend/assets/SandboxSettings-BUBMLW7Q-ChiNe2Y8.js.gz +0 -0
- package/dist/_frontend/assets/SettingsBuilder-26XSGIHK-DmgjXL0m.js +0 -2
- package/dist/_frontend/assets/SettingsBuilder-26XSGIHK-DmgjXL0m.js.br +0 -0
- package/dist/_frontend/assets/SettingsBuilder-26XSGIHK-DmgjXL0m.js.gz +0 -0
- package/dist/_frontend/assets/SidebarLayout-F3XFXW7B-BQV8bkzL.js.br +0 -0
- package/dist/_frontend/assets/SidebarLayout-F3XFXW7B-BQV8bkzL.js.gz +0 -0
- package/dist/_frontend/assets/SkillSettings-IRMGDFRG-ChKre3S8.js.br +0 -0
- package/dist/_frontend/assets/SkillSettings-IRMGDFRG-ChKre3S8.js.gz +0 -0
- package/dist/_frontend/assets/WidgetLayout-SZMABKIR-BRKArpEm.js.br +0 -0
- package/dist/_frontend/assets/WidgetLayout-SZMABKIR-BRKArpEm.js.gz +0 -0
- package/dist/_frontend/assets/chunk-7EEOWDLE-BIwInB6G.js.br +0 -0
- package/dist/_frontend/assets/chunk-7EEOWDLE-BIwInB6G.js.gz +0 -0
- package/dist/_frontend/assets/chunk-LRQHHZDX-eb14Z2nA.js +0 -1
- package/dist/_frontend/assets/chunk-LRQHHZDX-eb14Z2nA.js.br +0 -0
- package/dist/_frontend/assets/chunk-LRQHHZDX-eb14Z2nA.js.gz +0 -0
- package/dist/_frontend/assets/cssMode-Bb1lR8Ti.js.br +0 -0
- package/dist/_frontend/assets/cssMode-Bb1lR8Ti.js.gz +0 -0
- package/dist/_frontend/assets/freemarker2-BrrF7mKG.js.br +0 -0
- package/dist/_frontend/assets/freemarker2-BrrF7mKG.js.gz +0 -0
- package/dist/_frontend/assets/handlebars-WQ7HMT1b.js.br +0 -0
- package/dist/_frontend/assets/handlebars-WQ7HMT1b.js.gz +0 -0
- package/dist/_frontend/assets/html-CoOPnhCb.js.br +0 -0
- package/dist/_frontend/assets/html-CoOPnhCb.js.gz +0 -0
- package/dist/_frontend/assets/htmlMode-BW7taYty.js.br +0 -0
- package/dist/_frontend/assets/htmlMode-BW7taYty.js.gz +0 -0
- package/dist/_frontend/assets/index-ChCGltYc.js +0 -857
- package/dist/_frontend/assets/index-ChCGltYc.js.br +0 -0
- package/dist/_frontend/assets/index-ChCGltYc.js.gz +0 -0
- package/dist/_frontend/assets/index-DFQqb6R1.js.br +0 -0
- package/dist/_frontend/assets/index-DFQqb6R1.js.gz +0 -0
- package/dist/_frontend/assets/jsonMode-C8qDzOfb.js.br +0 -0
- package/dist/_frontend/assets/jsonMode-C8qDzOfb.js.gz +0 -0
- package/dist/_frontend/assets/liquid-zGC9H1Dt.js.br +0 -0
- package/dist/_frontend/assets/liquid-zGC9H1Dt.js.gz +0 -0
- package/dist/_frontend/assets/lspLanguageFeatures-B6VPH2Sv.js.br +0 -0
- package/dist/_frontend/assets/lspLanguageFeatures-B6VPH2Sv.js.gz +0 -0
- package/dist/_frontend/assets/mdx-BrQrGCP9.js.br +0 -0
- package/dist/_frontend/assets/mdx-BrQrGCP9.js.gz +0 -0
- package/dist/_frontend/assets/python-zKGpYLwR.js.br +0 -0
- package/dist/_frontend/assets/python-zKGpYLwR.js.gz +0 -0
- package/dist/_frontend/assets/razor-BJ38lYsd.js.br +0 -0
- package/dist/_frontend/assets/razor-BJ38lYsd.js.gz +0 -0
- package/dist/_frontend/assets/tsMode-dPLqGMg8.js.br +0 -0
- package/dist/_frontend/assets/tsMode-dPLqGMg8.js.gz +0 -0
- package/dist/_frontend/assets/typescript-BJlivWry.js.br +0 -0
- package/dist/_frontend/assets/typescript-BJlivWry.js.gz +0 -0
- package/dist/_frontend/assets/workers-fMwav4jB.js.br +0 -0
- package/dist/_frontend/assets/workers-fMwav4jB.js.gz +0 -0
- package/dist/_frontend/assets/xml-DZW470wi.js.br +0 -0
- package/dist/_frontend/assets/xml-DZW470wi.js.gz +0 -0
- package/dist/_frontend/assets/yaml-Bs1DumYp.js.br +0 -0
- package/dist/_frontend/assets/yaml-Bs1DumYp.js.gz +0 -0
package/dist/main.js
CHANGED
|
@@ -92,8 +92,12 @@ function parseBoolean(options) {
|
|
|
92
92
|
return defaultValue;
|
|
93
93
|
}
|
|
94
94
|
const value = raw.trim().toLowerCase();
|
|
95
|
-
if (value === "true")
|
|
96
|
-
|
|
95
|
+
if (value === "true") {
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
if (value === "false") {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
97
101
|
throw new Error(`Environment variable ${envKey} must be "true" or "false", got "${raw}"`);
|
|
98
102
|
}
|
|
99
103
|
function resolveDefaultFrontendDir() {
|
|
@@ -192,11 +196,13 @@ function getPublicBaseUrl(config = configuration) {
|
|
|
192
196
|
}
|
|
193
197
|
return config.PUBLIC_BASE_URL;
|
|
194
198
|
}
|
|
195
|
-
var DEFAULT_PORT, PACKAGE_ROOT, LOCAL_EXECUTOR_ID, ENV_PATHS_APP_NAME, DEFAULT_POSTGRES_USER, DEFAULT_POSTGRES_PASSWORD, DEFAULT_POSTGRES_DB, DEFAULT_POSTGRES_HOST, DEFAULT_POSTGRES_PORT, DEFAULT_REDIS_URL, DEFAULT_OIDC_USER_REFERENCE_CLAIM, DEFAULT_OIDC_USER_ROLE_CLAIM, DEFAULT_OIDC_ADMIN_ROLE_VALUE, DEFAULT_OIDC_SCOPES, serverExecutionTimeoutSeconds, standalone, port, shared, configuration, config_default;
|
|
199
|
+
var DEFAULT_PORT, DEFAULT_HOST, DEFAULT_MAX_REQUEST_BODY_BYTES, PACKAGE_ROOT, LOCAL_EXECUTOR_ID, ENV_PATHS_APP_NAME, DEFAULT_POSTGRES_USER, DEFAULT_POSTGRES_PASSWORD, DEFAULT_POSTGRES_DB, DEFAULT_POSTGRES_HOST, DEFAULT_POSTGRES_PORT, DEFAULT_REDIS_URL, DEFAULT_OIDC_USER_REFERENCE_CLAIM, DEFAULT_OIDC_USER_ROLE_CLAIM, DEFAULT_OIDC_ADMIN_ROLE_VALUE, DEFAULT_OIDC_SCOPES, serverExecutionTimeoutSeconds, standalone, port, host, shared, configuration, config_default;
|
|
196
200
|
var init_config = __esm({
|
|
197
201
|
"src/config.ts"() {
|
|
198
202
|
"use strict";
|
|
199
203
|
DEFAULT_PORT = 8790;
|
|
204
|
+
DEFAULT_HOST = "localhost";
|
|
205
|
+
DEFAULT_MAX_REQUEST_BODY_BYTES = 30 * 1024 * 1024;
|
|
200
206
|
PACKAGE_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
201
207
|
LOCAL_EXECUTOR_ID = "local";
|
|
202
208
|
ENV_PATHS_APP_NAME = "trueforge";
|
|
@@ -221,10 +227,12 @@ var init_config = __esm({
|
|
|
221
227
|
defaultValue: true
|
|
222
228
|
});
|
|
223
229
|
port = parsePort(getEnv("PORT"));
|
|
230
|
+
host = getEnv("HOST", { defaultValue: DEFAULT_HOST }) ?? DEFAULT_HOST;
|
|
224
231
|
shared = {
|
|
225
232
|
LOG_LEVEL: getEnv("LOG_LEVEL", { defaultValue: "info" }) ?? "info",
|
|
226
233
|
NODE_ENV: getEnv("NODE_ENV"),
|
|
227
234
|
PORT: port,
|
|
235
|
+
HOST: host,
|
|
228
236
|
EXECUTOR_ID: standalone ? LOCAL_EXECUTOR_ID : randomAlphanumeric(6),
|
|
229
237
|
MODEL_CATALOG_PATH: resolveOptionalPathEnv("MODEL_CATALOG_PATH"),
|
|
230
238
|
MCP_CATALOG_PATH: resolveOptionalPathEnv("MCP_CATALOG_PATH"),
|
|
@@ -247,6 +255,11 @@ var init_config = __esm({
|
|
|
247
255
|
raw: getEnv("SANDBOX_FILE_MAX_BYTES_FOR_DOWNLOAD"),
|
|
248
256
|
defaultValue: 20971520
|
|
249
257
|
}),
|
|
258
|
+
MAX_REQUEST_BODY_BYTES: parsePositiveInt({
|
|
259
|
+
envKey: "MAX_REQUEST_BODY_BYTES",
|
|
260
|
+
raw: getEnv("MAX_REQUEST_BODY_BYTES"),
|
|
261
|
+
defaultValue: DEFAULT_MAX_REQUEST_BODY_BYTES
|
|
262
|
+
}),
|
|
250
263
|
GRACEFUL_TIMEOUT_SECONDS: parsePositiveInt({
|
|
251
264
|
envKey: "GRACEFUL_TIMEOUT_SECONDS",
|
|
252
265
|
raw: getEnv("GRACEFUL_TIMEOUT_SECONDS"),
|
|
@@ -576,15 +589,15 @@ __export(migrateSqlite_exports, {
|
|
|
576
589
|
migrateSqliteToLatest: () => migrateSqliteToLatest
|
|
577
590
|
});
|
|
578
591
|
import { promises as fs2 } from "fs";
|
|
579
|
-
import
|
|
592
|
+
import path4 from "path";
|
|
580
593
|
import { FileMigrationProvider, Migrator } from "kysely/migration";
|
|
581
594
|
async function migrateSqliteToLatest(db) {
|
|
582
595
|
const migrator = new Migrator({
|
|
583
596
|
db,
|
|
584
597
|
provider: new FileMigrationProvider({
|
|
585
598
|
fs: fs2,
|
|
586
|
-
path:
|
|
587
|
-
migrationFolder:
|
|
599
|
+
path: path4,
|
|
600
|
+
migrationFolder: path4.join(import.meta.dirname, "sqlite", "migrations")
|
|
588
601
|
})
|
|
589
602
|
});
|
|
590
603
|
const { error, results } = await migrator.migrateToLatest();
|
|
@@ -613,8 +626,8 @@ import { sql } from "kysely";
|
|
|
613
626
|
function jsonbBind(value) {
|
|
614
627
|
return sql`jsonb(${JSON.stringify(value)})`;
|
|
615
628
|
}
|
|
616
|
-
function jsonbSet(column,
|
|
617
|
-
return sql`jsonb_set(${column}, ${
|
|
629
|
+
function jsonbSet(column, path7, value) {
|
|
630
|
+
return sql`jsonb_set(${column}, ${path7}, ${jsonbBind(value)})`;
|
|
618
631
|
}
|
|
619
632
|
function jsonText(column) {
|
|
620
633
|
return sql`json(${column})`;
|
|
@@ -642,9 +655,7 @@ var init_sqlExpressions2 = __esm({
|
|
|
642
655
|
});
|
|
643
656
|
|
|
644
657
|
// src/db/sqlite/session-store/queries/turns.ts
|
|
645
|
-
import
|
|
646
|
-
CancellationReason as CancellationReason4
|
|
647
|
-
} from "@truefoundry/trueforge-core/agent-session/schemas/turn";
|
|
658
|
+
import "@truefoundry/trueforge-core/agent-session/schemas/turn";
|
|
648
659
|
import { assertCreateTurnThreadDelta } from "@truefoundry/trueforge-core/agent-session/store/assertCreateTurnThreadDelta";
|
|
649
660
|
import {
|
|
650
661
|
PreviousTurnRunningError,
|
|
@@ -653,7 +664,7 @@ import {
|
|
|
653
664
|
SessionStoreInvariantError as SessionStoreInvariantError2,
|
|
654
665
|
SessionStoreNotFoundError as SessionStoreNotFoundError3,
|
|
655
666
|
TurnAlreadyExistsError,
|
|
656
|
-
TurnNotFoundError,
|
|
667
|
+
TurnNotFoundError as TurnNotFoundError2,
|
|
657
668
|
TurnNotRunningError
|
|
658
669
|
} from "@truefoundry/trueforge-core/agent-session/store/SessionStoreErrors";
|
|
659
670
|
import { getEmptyCurrentContextUsage } from "@truefoundry/trueforge-core/core/runtime/contextUsage";
|
|
@@ -687,14 +698,14 @@ async function loadTurnState(db, keys) {
|
|
|
687
698
|
async function classifyTurnFenceWriteFailure(db, keys) {
|
|
688
699
|
const state = await loadTurnState(db, keys);
|
|
689
700
|
if (!state) {
|
|
690
|
-
throw new
|
|
701
|
+
throw new TurnNotFoundError2(keys.turn_id);
|
|
691
702
|
}
|
|
692
703
|
throw new TurnNotRunningError(keys.turn_id, terminalTurnState(state, keys.turn_id));
|
|
693
704
|
}
|
|
694
705
|
async function classifyTurnThreadWriteFailure(db, keys, thread_id) {
|
|
695
706
|
const state = await loadTurnState(db, keys);
|
|
696
707
|
if (!state) {
|
|
697
|
-
throw new
|
|
708
|
+
throw new TurnNotFoundError2(keys.turn_id);
|
|
698
709
|
}
|
|
699
710
|
if (state.status !== "running") {
|
|
700
711
|
throw new TurnNotRunningError(keys.turn_id, terminalTurnState(state, keys.turn_id));
|
|
@@ -704,7 +715,7 @@ async function classifyTurnThreadWriteFailure(db, keys, thread_id) {
|
|
|
704
715
|
async function assertTurnRunning(db, keys) {
|
|
705
716
|
const state = await loadTurnState(db, keys);
|
|
706
717
|
if (!state) {
|
|
707
|
-
throw new
|
|
718
|
+
throw new TurnNotFoundError2(keys.turn_id);
|
|
708
719
|
}
|
|
709
720
|
if (state.status !== "running") {
|
|
710
721
|
throw new TurnNotRunningError(keys.turn_id, terminalTurnState(state, keys.turn_id));
|
|
@@ -724,7 +735,9 @@ async function assembleTurnRecord(db, args) {
|
|
|
724
735
|
"created_at",
|
|
725
736
|
"updated_at"
|
|
726
737
|
]).where("session_id", "=", args.session_id).where("turn_id", "=", args.turn_id).executeTakeFirst();
|
|
727
|
-
if (!turn)
|
|
738
|
+
if (!turn) {
|
|
739
|
+
return void 0;
|
|
740
|
+
}
|
|
728
741
|
const contextRows = await db.selectFrom("turn_thread as tt").leftJoin(
|
|
729
742
|
"turn_thread_context as ttc",
|
|
730
743
|
(join) => join.on("ttc.session_id", "=", args.session_id).on("ttc.turn_id", "=", args.turn_id).onRef("ttc.thread_id", "=", "tt.thread_id")
|
|
@@ -806,7 +819,9 @@ async function createTurn(db, input) {
|
|
|
806
819
|
try {
|
|
807
820
|
await db.transaction().execute(async (trx) => {
|
|
808
821
|
const locked = await trx.selectFrom("session").select(["last_turn_id"]).where("session_id", "=", input.session_id).executeTakeFirst();
|
|
809
|
-
if (!locked)
|
|
822
|
+
if (!locked) {
|
|
823
|
+
throw new SessionNotFoundError(input.session_id);
|
|
824
|
+
}
|
|
810
825
|
let sessionUpdate = trx.updateTable("session").set({
|
|
811
826
|
last_turn_id: input.turn.turn_id,
|
|
812
827
|
updated_at: nowIso(),
|
|
@@ -845,7 +860,9 @@ async function createTurn(db, input) {
|
|
|
845
860
|
}
|
|
846
861
|
prevCheckpoint = first.turn_checkpoint;
|
|
847
862
|
for (const row of prevRows) {
|
|
848
|
-
if (row.thread_id === null)
|
|
863
|
+
if (row.thread_id === null) {
|
|
864
|
+
continue;
|
|
865
|
+
}
|
|
849
866
|
if (row.thread_checkpoint === null || row.current_context_usage === null) {
|
|
850
867
|
throw new SessionStoreInvariantError2(`previous turn_thread row for ${row.thread_id} is incomplete`);
|
|
851
868
|
}
|
|
@@ -997,7 +1014,9 @@ async function createTurn(db, input) {
|
|
|
997
1014
|
}
|
|
998
1015
|
const capabilityStateRows = [];
|
|
999
1016
|
for (const capability of input.capability_states) {
|
|
1000
|
-
if (capability.capability_state === null)
|
|
1017
|
+
if (capability.capability_state === null) {
|
|
1018
|
+
continue;
|
|
1019
|
+
}
|
|
1001
1020
|
for (const [key, state] of Object.entries(capability.capability_state)) {
|
|
1002
1021
|
capabilityStateRows.push({
|
|
1003
1022
|
session_id: input.session_id,
|
|
@@ -1014,8 +1033,12 @@ async function createTurn(db, input) {
|
|
|
1014
1033
|
}
|
|
1015
1034
|
});
|
|
1016
1035
|
} catch (err) {
|
|
1017
|
-
if (err instanceof SessionStoreNotFoundError3 || err instanceof SessionStoreConflictError3)
|
|
1018
|
-
|
|
1036
|
+
if (err instanceof SessionStoreNotFoundError3 || err instanceof SessionStoreConflictError3) {
|
|
1037
|
+
throw err;
|
|
1038
|
+
}
|
|
1039
|
+
if (isUniqueViolation(err)) {
|
|
1040
|
+
throw new TurnAlreadyExistsError(input.turn.turn_id, { cause: err });
|
|
1041
|
+
}
|
|
1019
1042
|
throw err;
|
|
1020
1043
|
}
|
|
1021
1044
|
}
|
|
@@ -1023,7 +1046,7 @@ async function freezeAndGetTurn(db, input) {
|
|
|
1023
1046
|
return await db.transaction().execute(async (trx) => {
|
|
1024
1047
|
const cancelledState = {
|
|
1025
1048
|
status: "cancelled",
|
|
1026
|
-
reason:
|
|
1049
|
+
reason: input.reason,
|
|
1027
1050
|
completed_at: nowIso()
|
|
1028
1051
|
};
|
|
1029
1052
|
const updateResult = await trx.updateTable("turn").set({
|
|
@@ -1040,7 +1063,9 @@ async function freezeAndGetTurn(db, input) {
|
|
|
1040
1063
|
}).execute();
|
|
1041
1064
|
}
|
|
1042
1065
|
const record = await assembleTurnRecord(trx, input);
|
|
1043
|
-
if (!record)
|
|
1066
|
+
if (!record) {
|
|
1067
|
+
throw new TurnNotFoundError2(input.turn_id);
|
|
1068
|
+
}
|
|
1044
1069
|
return record;
|
|
1045
1070
|
});
|
|
1046
1071
|
}
|
|
@@ -1088,7 +1113,9 @@ async function updateTurnState(db, input) {
|
|
|
1088
1113
|
const numUpdated = Number(result.numUpdatedRows);
|
|
1089
1114
|
if (numUpdated === 0) {
|
|
1090
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();
|
|
1091
|
-
if (!existing)
|
|
1116
|
+
if (!existing) {
|
|
1117
|
+
throw new TurnNotFoundError2(input.turn_id);
|
|
1118
|
+
}
|
|
1092
1119
|
throw new TurnNotRunningError(input.turn_id, terminalTurnState(existing.state, input.turn_id));
|
|
1093
1120
|
}
|
|
1094
1121
|
await trx.insertInto("session_event").values({
|
|
@@ -1153,11 +1180,13 @@ import {
|
|
|
1153
1180
|
} from "@truefoundry/trueforge-core/agent-session/store/SessionEventPageToken";
|
|
1154
1181
|
import {
|
|
1155
1182
|
SessionNotFoundError as SessionNotFoundError2,
|
|
1156
|
-
TurnNotFoundError as
|
|
1183
|
+
TurnNotFoundError as TurnNotFoundError3
|
|
1157
1184
|
} from "@truefoundry/trueforge-core/agent-session/store/SessionStoreErrors";
|
|
1158
1185
|
import { sql as sql4 } from "kysely";
|
|
1159
1186
|
async function appendToEvents(db, input) {
|
|
1160
|
-
if (input.events.length === 0)
|
|
1187
|
+
if (input.events.length === 0) {
|
|
1188
|
+
return;
|
|
1189
|
+
}
|
|
1161
1190
|
const keys = {
|
|
1162
1191
|
session_id: input.session_id,
|
|
1163
1192
|
turn_id: input.turn_id
|
|
@@ -1186,7 +1215,7 @@ async function listTurnEvents(db, input) {
|
|
|
1186
1215
|
(join) => join.onRef("e.session_id", "=", "t.session_id").onRef("e.turn_id", "=", "t.turn_id")
|
|
1187
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();
|
|
1188
1217
|
if (rows.length === 0) {
|
|
1189
|
-
throw new
|
|
1218
|
+
throw new TurnNotFoundError3(input.turn_id);
|
|
1190
1219
|
}
|
|
1191
1220
|
const events = [];
|
|
1192
1221
|
for (const row of rows) {
|
|
@@ -1202,11 +1231,17 @@ async function resolveAncestorChain(db, sessionId, anchor) {
|
|
|
1202
1231
|
let oldestId = chain[0];
|
|
1203
1232
|
while (oldestId && oldestId !== anchor.turn_id) {
|
|
1204
1233
|
const oldest = await db.selectFrom("turn").select([jsonText(sql4.ref("ancestor_ids")).as("ancestor_ids")]).where("session_id", "=", sessionId).where("turn_id", "=", oldestId).executeTakeFirst();
|
|
1205
|
-
if (!oldest)
|
|
1234
|
+
if (!oldest) {
|
|
1235
|
+
break;
|
|
1236
|
+
}
|
|
1206
1237
|
const older = oldest.ancestor_ids.filter((id) => !seen.has(id));
|
|
1207
|
-
if (older.length === 0)
|
|
1238
|
+
if (older.length === 0) {
|
|
1239
|
+
break;
|
|
1240
|
+
}
|
|
1208
1241
|
chain.unshift(...older);
|
|
1209
|
-
for (const id of older)
|
|
1242
|
+
for (const id of older) {
|
|
1243
|
+
seen.add(id);
|
|
1244
|
+
}
|
|
1210
1245
|
oldestId = older[0];
|
|
1211
1246
|
}
|
|
1212
1247
|
return chain;
|
|
@@ -1228,7 +1263,7 @@ async function listSessionEvents(db, input) {
|
|
|
1228
1263
|
};
|
|
1229
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();
|
|
1230
1265
|
if (!anchor) {
|
|
1231
|
-
throw new
|
|
1266
|
+
throw new TurnNotFoundError3(cursor.last_turn_id);
|
|
1232
1267
|
}
|
|
1233
1268
|
const chainIds = await resolveAncestorChain(db, input.session_id, {
|
|
1234
1269
|
turn_id: anchor.turn_id,
|
|
@@ -2067,6 +2102,9 @@ async function consumePendingAuthorization(db, params) {
|
|
|
2067
2102
|
...fromStoredOAuthPendingAuthorizationData(row.auth_data)
|
|
2068
2103
|
};
|
|
2069
2104
|
}
|
|
2105
|
+
async function deletePendingAuthorizationsForServer(db, params) {
|
|
2106
|
+
await db.deleteFrom("oauth_pending_authorization").where("oauth_server_id", "=", params.id).execute();
|
|
2107
|
+
}
|
|
2070
2108
|
var init_pendingAuthorization = __esm({
|
|
2071
2109
|
"src/db/sqlite/token-store/queries/pendingAuthorization.ts"() {
|
|
2072
2110
|
"use strict";
|
|
@@ -2104,6 +2142,9 @@ async function getTokens(db, params) {
|
|
|
2104
2142
|
async function deleteToken(db, params) {
|
|
2105
2143
|
await db.deleteFrom("oauth_token").where("oauth_server_id", "=", params.id).where("user_id", "=", params.userRef).execute();
|
|
2106
2144
|
}
|
|
2145
|
+
async function deleteTokensForServer(db, params) {
|
|
2146
|
+
await db.deleteFrom("oauth_token").where("oauth_server_id", "=", params.id).execute();
|
|
2147
|
+
}
|
|
2107
2148
|
var init_token = __esm({
|
|
2108
2149
|
"src/db/sqlite/token-store/queries/token.ts"() {
|
|
2109
2150
|
"use strict";
|
|
@@ -2152,6 +2193,12 @@ var init_SqliteOAuthTokenStore = __esm({
|
|
|
2152
2193
|
deleteToken(params, transaction) {
|
|
2153
2194
|
return deleteToken(transaction ?? this.db, params);
|
|
2154
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
|
+
}
|
|
2155
2202
|
};
|
|
2156
2203
|
}
|
|
2157
2204
|
});
|
|
@@ -2448,15 +2495,15 @@ __export(migratePostgres_exports, {
|
|
|
2448
2495
|
migrateToLatest: () => migrateToLatest
|
|
2449
2496
|
});
|
|
2450
2497
|
import { promises as fs3 } from "fs";
|
|
2451
|
-
import
|
|
2498
|
+
import path5 from "path";
|
|
2452
2499
|
import { FileMigrationProvider as FileMigrationProvider2, Migrator as Migrator2 } from "kysely/migration";
|
|
2453
2500
|
async function migrateToLatest(db) {
|
|
2454
2501
|
const migrator = new Migrator2({
|
|
2455
2502
|
db,
|
|
2456
2503
|
provider: new FileMigrationProvider2({
|
|
2457
2504
|
fs: fs3,
|
|
2458
|
-
path:
|
|
2459
|
-
migrationFolder:
|
|
2505
|
+
path: path5,
|
|
2506
|
+
migrationFolder: path5.join(import.meta.dirname, "postgres", "migrations")
|
|
2460
2507
|
})
|
|
2461
2508
|
});
|
|
2462
2509
|
const { error, results } = await migrator.migrateToLatest();
|
|
@@ -2485,12 +2532,12 @@ var redis_exports = {};
|
|
|
2485
2532
|
__export(redis_exports, {
|
|
2486
2533
|
connectRedis: () => connectRedis
|
|
2487
2534
|
});
|
|
2488
|
-
import { extractErrorLogFields as
|
|
2535
|
+
import { extractErrorLogFields as extractErrorLogFields8 } from "@truefoundry/trueforge-core/core";
|
|
2489
2536
|
import { createClient } from "redis";
|
|
2490
2537
|
async function connectRedis(input) {
|
|
2491
2538
|
const client = createClient({ url: input.url });
|
|
2492
2539
|
client.on("error", (error) => {
|
|
2493
|
-
input.logger.error("[Redis] Client error",
|
|
2540
|
+
input.logger.error("[Redis] Client error", extractErrorLogFields8(error));
|
|
2494
2541
|
});
|
|
2495
2542
|
await client.connect();
|
|
2496
2543
|
return client;
|
|
@@ -2506,8 +2553,8 @@ import { sql as sql9 } from "kysely";
|
|
|
2506
2553
|
function json(value) {
|
|
2507
2554
|
return sql9`${JSON.stringify(value)}::jsonb`;
|
|
2508
2555
|
}
|
|
2509
|
-
function jsonbSet2(target,
|
|
2510
|
-
return sql9`jsonb_set(${target}, ${
|
|
2556
|
+
function jsonbSet2(target, path7, newValue) {
|
|
2557
|
+
return sql9`jsonb_set(${target}, ${path7}, ${newValue})`;
|
|
2511
2558
|
}
|
|
2512
2559
|
function now() {
|
|
2513
2560
|
return sql9`now()`;
|
|
@@ -2552,9 +2599,7 @@ var init_sqlExpressions4 = __esm({
|
|
|
2552
2599
|
});
|
|
2553
2600
|
|
|
2554
2601
|
// src/db/postgres/session-store/queries/turns.ts
|
|
2555
|
-
import
|
|
2556
|
-
CancellationReason as CancellationReason5
|
|
2557
|
-
} from "@truefoundry/trueforge-core/agent-session/schemas/turn";
|
|
2602
|
+
import "@truefoundry/trueforge-core/agent-session/schemas/turn";
|
|
2558
2603
|
import { assertCreateTurnThreadDelta as assertCreateTurnThreadDelta2 } from "@truefoundry/trueforge-core/agent-session/store/assertCreateTurnThreadDelta";
|
|
2559
2604
|
import {
|
|
2560
2605
|
PreviousTurnRunningError as PreviousTurnRunningError2,
|
|
@@ -2563,7 +2608,7 @@ import {
|
|
|
2563
2608
|
SessionStoreInvariantError as SessionStoreInvariantError4,
|
|
2564
2609
|
SessionStoreNotFoundError as SessionStoreNotFoundError4,
|
|
2565
2610
|
TurnAlreadyExistsError as TurnAlreadyExistsError2,
|
|
2566
|
-
TurnNotFoundError as
|
|
2611
|
+
TurnNotFoundError as TurnNotFoundError4,
|
|
2567
2612
|
TurnNotRunningError as TurnNotRunningError2
|
|
2568
2613
|
} from "@truefoundry/trueforge-core/agent-session/store/SessionStoreErrors";
|
|
2569
2614
|
import { getEmptyCurrentContextUsage as getEmptyCurrentContextUsage2 } from "@truefoundry/trueforge-core/core/runtime/contextUsage";
|
|
@@ -2596,14 +2641,14 @@ function turnRunningFence(db, keys) {
|
|
|
2596
2641
|
async function classifyTurnFenceWriteFailure2(db, keys) {
|
|
2597
2642
|
const row = await db.selectFrom("turn").select("state").where("session_id", "=", keys.session_id).where("turn_id", "=", keys.turn_id).executeTakeFirst();
|
|
2598
2643
|
if (!row) {
|
|
2599
|
-
throw new
|
|
2644
|
+
throw new TurnNotFoundError4(keys.turn_id);
|
|
2600
2645
|
}
|
|
2601
2646
|
throw new TurnNotRunningError2(keys.turn_id, terminalTurnState2(row.state, keys.turn_id));
|
|
2602
2647
|
}
|
|
2603
2648
|
async function classifyTurnThreadWriteFailure2(db, keys, thread_id) {
|
|
2604
2649
|
const row = await db.selectFrom("turn").select("state").where("session_id", "=", keys.session_id).where("turn_id", "=", keys.turn_id).executeTakeFirst();
|
|
2605
2650
|
if (!row) {
|
|
2606
|
-
throw new
|
|
2651
|
+
throw new TurnNotFoundError4(keys.turn_id);
|
|
2607
2652
|
}
|
|
2608
2653
|
if (row.state.status !== "running") {
|
|
2609
2654
|
throw new TurnNotRunningError2(keys.turn_id, terminalTurnState2(row.state, keys.turn_id));
|
|
@@ -2613,7 +2658,7 @@ async function classifyTurnThreadWriteFailure2(db, keys, thread_id) {
|
|
|
2613
2658
|
async function assertTurnRunning2(db, keys) {
|
|
2614
2659
|
const row = await db.selectFrom("turn").select("state").where("session_id", "=", keys.session_id).where("turn_id", "=", keys.turn_id).forShare().executeTakeFirst();
|
|
2615
2660
|
if (!row) {
|
|
2616
|
-
throw new
|
|
2661
|
+
throw new TurnNotFoundError4(keys.turn_id);
|
|
2617
2662
|
}
|
|
2618
2663
|
if (row.state.status !== "running") {
|
|
2619
2664
|
throw new TurnNotRunningError2(keys.turn_id, terminalTurnState2(row.state, keys.turn_id));
|
|
@@ -2621,7 +2666,9 @@ async function assertTurnRunning2(db, keys) {
|
|
|
2621
2666
|
}
|
|
2622
2667
|
async function assembleTurnRecord2(db, args) {
|
|
2623
2668
|
const turn = await db.selectFrom("turn").selectAll().where("session_id", "=", args.session_id).where("turn_id", "=", args.turn_id).executeTakeFirst();
|
|
2624
|
-
if (!turn)
|
|
2669
|
+
if (!turn) {
|
|
2670
|
+
return void 0;
|
|
2671
|
+
}
|
|
2625
2672
|
const contextRows = await db.selectFrom("turn_thread as tt").leftJoin(lateralUnnestBigintArrayWithOrdinality(sql11`tt.context_ids`, "c"), (join) => join.onTrue()).leftJoin(
|
|
2626
2673
|
"thread_context_log as l",
|
|
2627
2674
|
(join) => join.on("l.session_id", "=", args.session_id).onRef("l.thread_id", "=", "tt.thread_id").onRef("l.append_id", "=", "c.append_id")
|
|
@@ -2690,7 +2737,9 @@ async function createTurn2(db, input) {
|
|
|
2690
2737
|
try {
|
|
2691
2738
|
await db.transaction().execute(async (trx) => {
|
|
2692
2739
|
const locked = await trx.selectFrom("session").select(["last_turn_id"]).where("session_id", "=", input.session_id).forUpdate().executeTakeFirst();
|
|
2693
|
-
if (!locked)
|
|
2740
|
+
if (!locked) {
|
|
2741
|
+
throw new SessionNotFoundError4(input.session_id);
|
|
2742
|
+
}
|
|
2694
2743
|
await trx.updateTable("session").set({
|
|
2695
2744
|
last_turn_id: input.turn.turn_id,
|
|
2696
2745
|
updated_at: sql11`now()`,
|
|
@@ -2722,7 +2771,9 @@ async function createTurn2(db, input) {
|
|
|
2722
2771
|
}
|
|
2723
2772
|
prevCheckpoint = first.turn_checkpoint;
|
|
2724
2773
|
for (const row of prevRows) {
|
|
2725
|
-
if (row.thread_id === null)
|
|
2774
|
+
if (row.thread_id === null) {
|
|
2775
|
+
continue;
|
|
2776
|
+
}
|
|
2726
2777
|
if (row.thread_checkpoint === null || row.current_context_usage === null || row.context_ids === null) {
|
|
2727
2778
|
throw new SessionStoreInvariantError4(`previous turn_thread row for ${row.thread_id} is incomplete`);
|
|
2728
2779
|
}
|
|
@@ -2830,7 +2881,9 @@ async function createTurn2(db, input) {
|
|
|
2830
2881
|
}
|
|
2831
2882
|
const capabilityStateRows = [];
|
|
2832
2883
|
for (const capability of input.capability_states) {
|
|
2833
|
-
if (capability.capability_state === null)
|
|
2884
|
+
if (capability.capability_state === null) {
|
|
2885
|
+
continue;
|
|
2886
|
+
}
|
|
2834
2887
|
for (const [key, state] of Object.entries(capability.capability_state)) {
|
|
2835
2888
|
capabilityStateRows.push({
|
|
2836
2889
|
session_id: input.session_id,
|
|
@@ -2847,8 +2900,12 @@ async function createTurn2(db, input) {
|
|
|
2847
2900
|
}
|
|
2848
2901
|
});
|
|
2849
2902
|
} catch (err) {
|
|
2850
|
-
if (err instanceof SessionStoreNotFoundError4 || err instanceof SessionStoreConflictError4)
|
|
2851
|
-
|
|
2903
|
+
if (err instanceof SessionStoreNotFoundError4 || err instanceof SessionStoreConflictError4) {
|
|
2904
|
+
throw err;
|
|
2905
|
+
}
|
|
2906
|
+
if (isUniqueViolation2(err)) {
|
|
2907
|
+
throw new TurnAlreadyExistsError2(input.turn.turn_id, { cause: err });
|
|
2908
|
+
}
|
|
2852
2909
|
throw err;
|
|
2853
2910
|
}
|
|
2854
2911
|
}
|
|
@@ -2856,7 +2913,7 @@ async function freezeAndGetTurn2(db, input) {
|
|
|
2856
2913
|
return await db.transaction().execute(async (trx) => {
|
|
2857
2914
|
const cancelledState = {
|
|
2858
2915
|
status: "cancelled",
|
|
2859
|
-
reason:
|
|
2916
|
+
reason: input.reason,
|
|
2860
2917
|
completed_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
2861
2918
|
};
|
|
2862
2919
|
const updateResult = await trx.updateTable("turn").set({
|
|
@@ -2873,7 +2930,9 @@ async function freezeAndGetTurn2(db, input) {
|
|
|
2873
2930
|
}).execute();
|
|
2874
2931
|
}
|
|
2875
2932
|
const record = await assembleTurnRecord2(trx, input);
|
|
2876
|
-
if (!record)
|
|
2933
|
+
if (!record) {
|
|
2934
|
+
throw new TurnNotFoundError4(input.turn_id);
|
|
2935
|
+
}
|
|
2877
2936
|
return record;
|
|
2878
2937
|
});
|
|
2879
2938
|
}
|
|
@@ -2912,7 +2971,9 @@ async function updateTurnState2(db, input) {
|
|
|
2912
2971
|
const numUpdated = Number(result.numUpdatedRows);
|
|
2913
2972
|
if (numUpdated === 0) {
|
|
2914
2973
|
const existing = await trx.selectFrom("turn").select("state").where("session_id", "=", input.session_id).where("turn_id", "=", input.turn_id).executeTakeFirst();
|
|
2915
|
-
if (!existing)
|
|
2974
|
+
if (!existing) {
|
|
2975
|
+
throw new TurnNotFoundError4(input.turn_id);
|
|
2976
|
+
}
|
|
2916
2977
|
throw new TurnNotRunningError2(input.turn_id, terminalTurnState2(existing.state, input.turn_id));
|
|
2917
2978
|
}
|
|
2918
2979
|
await trx.insertInto("session_event").values({
|
|
@@ -2979,11 +3040,13 @@ import {
|
|
|
2979
3040
|
} from "@truefoundry/trueforge-core/agent-session/store/SessionEventPageToken";
|
|
2980
3041
|
import {
|
|
2981
3042
|
SessionNotFoundError as SessionNotFoundError5,
|
|
2982
|
-
TurnNotFoundError as
|
|
3043
|
+
TurnNotFoundError as TurnNotFoundError5
|
|
2983
3044
|
} from "@truefoundry/trueforge-core/agent-session/store/SessionStoreErrors";
|
|
2984
3045
|
import { sql as sql13 } from "kysely";
|
|
2985
3046
|
async function appendToEvents2(db, input) {
|
|
2986
|
-
if (input.events.length === 0)
|
|
3047
|
+
if (input.events.length === 0) {
|
|
3048
|
+
return;
|
|
3049
|
+
}
|
|
2987
3050
|
const keys = {
|
|
2988
3051
|
session_id: input.session_id,
|
|
2989
3052
|
turn_id: input.turn_id
|
|
@@ -3016,7 +3079,7 @@ async function listTurnEvents2(db, input) {
|
|
|
3016
3079
|
(join) => join.onRef("e.session_id", "=", "t.session_id").onRef("e.turn_id", "=", "t.turn_id")
|
|
3017
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();
|
|
3018
3081
|
if (rows.length === 0) {
|
|
3019
|
-
throw new
|
|
3082
|
+
throw new TurnNotFoundError5(input.turn_id);
|
|
3020
3083
|
}
|
|
3021
3084
|
const events = [];
|
|
3022
3085
|
for (const row of rows) {
|
|
@@ -3043,7 +3106,7 @@ async function listSessionEvents2(db, input) {
|
|
|
3043
3106
|
};
|
|
3044
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();
|
|
3045
3108
|
if (!anchor) {
|
|
3046
|
-
throw new
|
|
3109
|
+
throw new TurnNotFoundError5(cursor.last_turn_id);
|
|
3047
3110
|
}
|
|
3048
3111
|
const chainIds = await resolveAncestorChain2(db, input.session_id, anchor);
|
|
3049
3112
|
const rows = await db.selectFrom(unnestWithOrdinality(chainIds, "c")).innerJoin(
|
|
@@ -3058,11 +3121,17 @@ async function resolveAncestorChain2(db, sessionId, anchor) {
|
|
|
3058
3121
|
let oldestId = chain[0];
|
|
3059
3122
|
while (oldestId && oldestId !== anchor.turn_id) {
|
|
3060
3123
|
const oldest = await db.selectFrom("turn").select(["ancestor_ids"]).where("session_id", "=", sessionId).where("turn_id", "=", oldestId).executeTakeFirst();
|
|
3061
|
-
if (!oldest)
|
|
3124
|
+
if (!oldest) {
|
|
3125
|
+
break;
|
|
3126
|
+
}
|
|
3062
3127
|
const older = oldest.ancestor_ids.filter((id) => !seen.has(id));
|
|
3063
|
-
if (older.length === 0)
|
|
3128
|
+
if (older.length === 0) {
|
|
3129
|
+
break;
|
|
3130
|
+
}
|
|
3064
3131
|
chain.unshift(...older);
|
|
3065
|
-
for (const id of older)
|
|
3132
|
+
for (const id of older) {
|
|
3133
|
+
seen.add(id);
|
|
3134
|
+
}
|
|
3066
3135
|
oldestId = older[0];
|
|
3067
3136
|
}
|
|
3068
3137
|
return chain;
|
|
@@ -3816,6 +3885,9 @@ async function consumePendingAuthorization2(db, params) {
|
|
|
3816
3885
|
...fromStoredOAuthPendingAuthorizationData(row.auth_data)
|
|
3817
3886
|
};
|
|
3818
3887
|
}
|
|
3888
|
+
async function deletePendingAuthorizationsForServer2(db, params) {
|
|
3889
|
+
await db.deleteFrom("oauth_pending_authorization").where("oauth_server_id", "=", params.id).execute();
|
|
3890
|
+
}
|
|
3819
3891
|
var init_pendingAuthorization2 = __esm({
|
|
3820
3892
|
"src/db/postgres/token-store/queries/pendingAuthorization.ts"() {
|
|
3821
3893
|
"use strict";
|
|
@@ -3853,6 +3925,9 @@ async function getTokens2(db, params) {
|
|
|
3853
3925
|
async function deleteToken2(db, params) {
|
|
3854
3926
|
await db.deleteFrom("oauth_token").where("oauth_server_id", "=", params.id).where("user_id", "=", params.userRef).execute();
|
|
3855
3927
|
}
|
|
3928
|
+
async function deleteTokensForServer2(db, params) {
|
|
3929
|
+
await db.deleteFrom("oauth_token").where("oauth_server_id", "=", params.id).execute();
|
|
3930
|
+
}
|
|
3856
3931
|
var init_token2 = __esm({
|
|
3857
3932
|
"src/db/postgres/token-store/queries/token.ts"() {
|
|
3858
3933
|
"use strict";
|
|
@@ -3901,6 +3976,12 @@ var init_PostgresOAuthTokenStore = __esm({
|
|
|
3901
3976
|
deleteToken(params, transaction) {
|
|
3902
3977
|
return deleteToken2(transaction ?? this.db, params);
|
|
3903
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
|
+
}
|
|
3904
3985
|
};
|
|
3905
3986
|
}
|
|
3906
3987
|
});
|
|
@@ -4136,22 +4217,22 @@ var init_PostgresAgentStore = __esm({
|
|
|
4136
4217
|
});
|
|
4137
4218
|
|
|
4138
4219
|
// src/main.ts
|
|
4139
|
-
import { extractErrorLogFields as
|
|
4220
|
+
import { extractErrorLogFields as extractErrorLogFields9 } from "@truefoundry/trueforge-core/core";
|
|
4140
4221
|
import { mkdir } from "fs/promises";
|
|
4141
|
-
import
|
|
4222
|
+
import path6 from "path";
|
|
4142
4223
|
import { serve } from "@hono/node-server";
|
|
4143
4224
|
import {
|
|
4144
|
-
CancellationReason as
|
|
4225
|
+
CancellationReason as CancellationReason4,
|
|
4145
4226
|
Sessions
|
|
4146
4227
|
} from "@truefoundry/trueforge-core/agent-session";
|
|
4147
4228
|
import { RequestReplyExecutor, RequestReplyRouter } from "@truefoundry/trueforge-core/request-reply";
|
|
4148
|
-
import winston from "winston";
|
|
4149
4229
|
|
|
4150
4230
|
// src/app.ts
|
|
4151
4231
|
import { swaggerUI } from "@hono/swagger-ui";
|
|
4152
4232
|
import { OpenAPIHono as OpenAPIHono14, z as z24 } from "@hono/zod-openapi";
|
|
4153
|
-
import { extractErrorLogFields as
|
|
4154
|
-
import {
|
|
4233
|
+
import { extractErrorLogFields as extractErrorLogFields7 } from "@truefoundry/trueforge-core/core";
|
|
4234
|
+
import { bodyLimit } from "hono/body-limit";
|
|
4235
|
+
import { HTTPException as HTTPException5 } from "hono/http-exception";
|
|
4155
4236
|
|
|
4156
4237
|
// src/apis/agents.ts
|
|
4157
4238
|
init_agentStore();
|
|
@@ -4744,6 +4825,7 @@ function toDaytonaSandboxProvider({
|
|
|
4744
4825
|
const { apiKey, ...settings } = toDaytonaSandboxProviderInput(manifest);
|
|
4745
4826
|
return new DaytonaSandboxProvider({
|
|
4746
4827
|
client: new Daytona({ apiKey }),
|
|
4828
|
+
apiKey,
|
|
4747
4829
|
...settings,
|
|
4748
4830
|
tenantName: tenant_id,
|
|
4749
4831
|
sandboxImage: build_metadata?.["image_uri"] ?? SANDBOX_IMAGE_URI,
|
|
@@ -4759,6 +4841,13 @@ function toSandboxStatus(build) {
|
|
|
4759
4841
|
build_metadata: build.metadata
|
|
4760
4842
|
};
|
|
4761
4843
|
}
|
|
4844
|
+
function sandboxStatusFromRecord(record) {
|
|
4845
|
+
return {
|
|
4846
|
+
status: record.status,
|
|
4847
|
+
status_reason: record.status_reason,
|
|
4848
|
+
build_metadata: record.build_metadata
|
|
4849
|
+
};
|
|
4850
|
+
}
|
|
4762
4851
|
var READY_REVALIDATE_INTERVAL_MS = 13 * 24 * 60 * 60 * 1e3;
|
|
4763
4852
|
async function checkSnapshotStatus({
|
|
4764
4853
|
store,
|
|
@@ -4769,11 +4858,7 @@ async function checkSnapshotStatus({
|
|
|
4769
4858
|
if (!record) {
|
|
4770
4859
|
return void 0;
|
|
4771
4860
|
}
|
|
4772
|
-
const persisted =
|
|
4773
|
-
status: record.status,
|
|
4774
|
-
status_reason: record.status_reason,
|
|
4775
|
-
build_metadata: record.build_metadata
|
|
4776
|
-
};
|
|
4861
|
+
const persisted = sandboxStatusFromRecord(record);
|
|
4777
4862
|
const readyIsFresh = record.status === "ready" && Date.now() - Date.parse(record.updated_at) < READY_REVALIDATE_INTERVAL_MS;
|
|
4778
4863
|
if (record.status === "failed" || readyIsFresh) {
|
|
4779
4864
|
return persisted;
|
|
@@ -4791,8 +4876,8 @@ async function checkSnapshotStatus({
|
|
|
4791
4876
|
build = await provider.getImageBuildStatus();
|
|
4792
4877
|
}
|
|
4793
4878
|
const next = toSandboxStatus(build);
|
|
4794
|
-
await store.updateSandboxStatus({ tenant_id, ...next });
|
|
4795
|
-
return next;
|
|
4879
|
+
const updated = await store.updateSandboxStatus({ tenant_id, ...next });
|
|
4880
|
+
return updated ? sandboxStatusFromRecord(updated) : next;
|
|
4796
4881
|
}
|
|
4797
4882
|
|
|
4798
4883
|
// src/schemas/mcpServer.ts
|
|
@@ -5105,10 +5190,14 @@ import {
|
|
|
5105
5190
|
CancellationReason,
|
|
5106
5191
|
SessionStoreConflictError,
|
|
5107
5192
|
SessionStoreInvariantError,
|
|
5108
|
-
SessionStoreNotFoundError
|
|
5193
|
+
SessionStoreNotFoundError,
|
|
5194
|
+
TurnNotFoundError
|
|
5109
5195
|
} from "@truefoundry/trueforge-core/agent-session";
|
|
5110
|
-
import {
|
|
5111
|
-
import {
|
|
5196
|
+
import { extractErrorLogFields } from "@truefoundry/trueforge-core/core";
|
|
5197
|
+
import {
|
|
5198
|
+
redisRequest,
|
|
5199
|
+
RequestTimeoutError
|
|
5200
|
+
} from "@truefoundry/trueforge-core/request-reply";
|
|
5112
5201
|
import { ulid as ulid2 } from "ulid";
|
|
5113
5202
|
import { z as z11 } from "zod";
|
|
5114
5203
|
|
|
@@ -5529,7 +5618,8 @@ function cancelSessionTurnPeerHandler(activeTurns) {
|
|
|
5529
5618
|
};
|
|
5530
5619
|
}
|
|
5531
5620
|
async function cancelSessionTurn(deps, input) {
|
|
5532
|
-
const {
|
|
5621
|
+
const { turnId, reason = CancellationReason.ClientCancelled } = input;
|
|
5622
|
+
const sessionId = deps.session.session_id;
|
|
5533
5623
|
const turn = await deps.sessionStore.getTurn({
|
|
5534
5624
|
session_id: sessionId,
|
|
5535
5625
|
turn_id: turnId
|
|
@@ -5552,33 +5642,39 @@ async function cancelSessionTurn(deps, input) {
|
|
|
5552
5642
|
pollIntervalMs: config_default.REDIS_REQUEST_REPLY_POLL_INTERVAL_MS
|
|
5553
5643
|
}
|
|
5554
5644
|
});
|
|
5555
|
-
if (reply.status
|
|
5556
|
-
|
|
5645
|
+
if (reply.status === 200) {
|
|
5646
|
+
return;
|
|
5557
5647
|
}
|
|
5558
5648
|
} catch (error) {
|
|
5559
|
-
|
|
5560
|
-
|
|
5561
|
-
|
|
5562
|
-
|
|
5563
|
-
|
|
5564
|
-
}
|
|
5649
|
+
const fields = {
|
|
5650
|
+
sessionId,
|
|
5651
|
+
turnId,
|
|
5652
|
+
owner,
|
|
5653
|
+
...extractErrorLogFields(error)
|
|
5654
|
+
};
|
|
5565
5655
|
if (error instanceof RequestTimeoutError) {
|
|
5566
|
-
|
|
5567
|
-
|
|
5568
|
-
|
|
5569
|
-
});
|
|
5570
|
-
}
|
|
5571
|
-
if (error instanceof HTTPException3) {
|
|
5572
|
-
throw error;
|
|
5656
|
+
deps.logger.warn("Timed out waiting for owning executor to cancel; freezing the running turn", fields);
|
|
5657
|
+
} else {
|
|
5658
|
+
deps.logger.warn("Failed to reach owning executor over Redis; freezing the running turn", fields);
|
|
5573
5659
|
}
|
|
5574
|
-
throw new HTTPException3(500, {
|
|
5575
|
-
message: `Unexpected error while cancelling the turn on the owning executor: ${owner}`,
|
|
5576
|
-
cause: error
|
|
5577
|
-
});
|
|
5578
5660
|
}
|
|
5661
|
+
await freezeTurnIgnoringMissing(deps.session, { turnId, reason });
|
|
5579
5662
|
return;
|
|
5580
5663
|
}
|
|
5581
|
-
cancelTurnOnThisExecutor(deps.activeTurns, { sessionId, turnId, reason });
|
|
5664
|
+
const aborted = cancelTurnOnThisExecutor(deps.activeTurns, { sessionId, turnId, reason });
|
|
5665
|
+
if (!aborted) {
|
|
5666
|
+
await freezeTurnIgnoringMissing(deps.session, { turnId, reason });
|
|
5667
|
+
}
|
|
5668
|
+
}
|
|
5669
|
+
async function freezeTurnIgnoringMissing(session, input) {
|
|
5670
|
+
try {
|
|
5671
|
+
await session.freezeTurn({ turn_id: input.turnId, reason: input.reason });
|
|
5672
|
+
} catch (error) {
|
|
5673
|
+
if (error instanceof TurnNotFoundError) {
|
|
5674
|
+
return;
|
|
5675
|
+
}
|
|
5676
|
+
throw error;
|
|
5677
|
+
}
|
|
5582
5678
|
}
|
|
5583
5679
|
var FORBIDDEN_SESSION_ACCESS = "Only the session creator can access this session";
|
|
5584
5680
|
function checkSessionAccess({ userRef, createdBy }) {
|
|
@@ -5708,18 +5804,18 @@ function createSessionsRouter(deps) {
|
|
|
5708
5804
|
};
|
|
5709
5805
|
const cancelSessionHandler = async (c) => {
|
|
5710
5806
|
const { session_id: sessionId } = c.req.valid("param");
|
|
5711
|
-
const
|
|
5712
|
-
if (!
|
|
5807
|
+
const session = await deps.sessions.get({ tenant_id: TENANT_ID, session_id: sessionId });
|
|
5808
|
+
if (!session) {
|
|
5713
5809
|
return c.json({ error: { message: `Session not found: ${sessionId}` } }, 404);
|
|
5714
5810
|
}
|
|
5715
|
-
if (!checkSessionAccess({ userRef: deps.resolveUserContext(c).userRef, createdBy: record.created_by })) {
|
|
5811
|
+
if (!checkSessionAccess({ userRef: deps.resolveUserContext(c).userRef, createdBy: session.record.created_by })) {
|
|
5716
5812
|
return c.json({ error: { message: FORBIDDEN_SESSION_ACCESS } }, 403);
|
|
5717
5813
|
}
|
|
5718
|
-
const turnId = record.last_turn_id;
|
|
5814
|
+
const turnId = session.record.last_turn_id;
|
|
5719
5815
|
if (!turnId) {
|
|
5720
5816
|
return c.json({}, 200);
|
|
5721
5817
|
}
|
|
5722
|
-
await cancelSessionTurn(deps,
|
|
5818
|
+
await cancelSessionTurn({ ...deps, session }, { turnId });
|
|
5723
5819
|
return c.json({}, 200);
|
|
5724
5820
|
};
|
|
5725
5821
|
const listSessionEventsHandler = async (c) => {
|
|
@@ -5843,7 +5939,7 @@ function createAgentsRouter(deps) {
|
|
|
5843
5939
|
|
|
5844
5940
|
// src/apis/auth.ts
|
|
5845
5941
|
import { OpenAPIHono as OpenAPIHono3 } from "@hono/zod-openapi";
|
|
5846
|
-
import { extractErrorLogFields } from "@truefoundry/trueforge-core/core";
|
|
5942
|
+
import { extractErrorLogFields as extractErrorLogFields2 } from "@truefoundry/trueforge-core/core";
|
|
5847
5943
|
|
|
5848
5944
|
// src/auth/cookies.ts
|
|
5849
5945
|
init_config();
|
|
@@ -6061,7 +6157,7 @@ function resolveUserContext(c) {
|
|
|
6061
6157
|
}
|
|
6062
6158
|
|
|
6063
6159
|
// src/auth/middleware.ts
|
|
6064
|
-
import { HTTPException as
|
|
6160
|
+
import { HTTPException as HTTPException3 } from "hono/http-exception";
|
|
6065
6161
|
import { jwtVerify } from "jose";
|
|
6066
6162
|
var AUTH_HEADER_TYPE = "Bearer";
|
|
6067
6163
|
function readBearerIdToken(c) {
|
|
@@ -6108,14 +6204,14 @@ var authMiddleware = async (c, next) => {
|
|
|
6108
6204
|
try {
|
|
6109
6205
|
const user = await resolveAuthUser(c);
|
|
6110
6206
|
if (!user) {
|
|
6111
|
-
throw new
|
|
6207
|
+
throw new HTTPException3(401, { message: "Authentication required" });
|
|
6112
6208
|
}
|
|
6113
6209
|
c.set("user_context", user);
|
|
6114
6210
|
} catch (error) {
|
|
6115
|
-
if (error instanceof
|
|
6211
|
+
if (error instanceof HTTPException3) {
|
|
6116
6212
|
throw error;
|
|
6117
6213
|
}
|
|
6118
|
-
throw new
|
|
6214
|
+
throw new HTTPException3(401, { message: "Authentication required", cause: error });
|
|
6119
6215
|
}
|
|
6120
6216
|
return next();
|
|
6121
6217
|
};
|
|
@@ -6127,17 +6223,17 @@ var adminAuthMiddleware = async (c, next) => {
|
|
|
6127
6223
|
try {
|
|
6128
6224
|
const user = await resolveAuthUser(c);
|
|
6129
6225
|
if (!user) {
|
|
6130
|
-
throw new
|
|
6226
|
+
throw new HTTPException3(401, { message: "Authentication required" });
|
|
6131
6227
|
}
|
|
6132
6228
|
if (!isAdmin(user)) {
|
|
6133
|
-
throw new
|
|
6229
|
+
throw new HTTPException3(403, { message: "Admin access required" });
|
|
6134
6230
|
}
|
|
6135
6231
|
c.set("user_context", user);
|
|
6136
6232
|
} catch (error) {
|
|
6137
|
-
if (error instanceof
|
|
6233
|
+
if (error instanceof HTTPException3) {
|
|
6138
6234
|
throw error;
|
|
6139
6235
|
}
|
|
6140
|
-
throw new
|
|
6236
|
+
throw new HTTPException3(401, { message: "Authentication required", cause: error });
|
|
6141
6237
|
}
|
|
6142
6238
|
return next();
|
|
6143
6239
|
};
|
|
@@ -6243,7 +6339,7 @@ function createAuthRouter(params) {
|
|
|
6243
6339
|
});
|
|
6244
6340
|
return c.redirect(authorizationUrl, 302);
|
|
6245
6341
|
} catch (error) {
|
|
6246
|
-
params.logger.error("Failed to build login authorization",
|
|
6342
|
+
params.logger.error("Failed to build login authorization", extractErrorLogFields2(error));
|
|
6247
6343
|
return c.redirect(oauthErrorRedirect("login_failed"), 302);
|
|
6248
6344
|
}
|
|
6249
6345
|
});
|
|
@@ -6269,7 +6365,7 @@ function createAuthRouter(params) {
|
|
|
6269
6365
|
});
|
|
6270
6366
|
return c.redirect(safeReturnTo(pending.return_to), 302);
|
|
6271
6367
|
} catch (error) {
|
|
6272
|
-
params.logger.error("Failed to exchange authorization code",
|
|
6368
|
+
params.logger.error("Failed to exchange authorization code", extractErrorLogFields2(error));
|
|
6273
6369
|
const reason = error instanceof Error ? error.message : "login_failed";
|
|
6274
6370
|
return c.redirect(oauthErrorRedirect(reason), 302);
|
|
6275
6371
|
}
|
|
@@ -6291,7 +6387,7 @@ function createAuthRouter(params) {
|
|
|
6291
6387
|
|
|
6292
6388
|
// src/apis/capabilities.ts
|
|
6293
6389
|
import { OpenAPIHono as OpenAPIHono4 } from "@hono/zod-openapi";
|
|
6294
|
-
import { extractErrorLogFields as
|
|
6390
|
+
import { extractErrorLogFields as extractErrorLogFields3 } from "@truefoundry/trueforge-core/core";
|
|
6295
6391
|
|
|
6296
6392
|
// src/routes/capabilityRoutes.ts
|
|
6297
6393
|
import { createRoute as createRoute4, z as z14 } from "@hono/zod-openapi";
|
|
@@ -6348,7 +6444,7 @@ function createCapabilitiesRouter(deps) {
|
|
|
6348
6444
|
});
|
|
6349
6445
|
status = refreshed?.status;
|
|
6350
6446
|
} catch (error) {
|
|
6351
|
-
deps.logger.warn("Sandbox image status check failed; reporting sandbox disabled",
|
|
6447
|
+
deps.logger.warn("Sandbox image status check failed; reporting sandbox disabled", extractErrorLogFields3(error));
|
|
6352
6448
|
}
|
|
6353
6449
|
const sandboxEnabled = status === "ready";
|
|
6354
6450
|
const settingsEnabled = isAdmin(resolveUserContext(c));
|
|
@@ -6732,7 +6828,7 @@ function createCatalogRouter(deps) {
|
|
|
6732
6828
|
|
|
6733
6829
|
// src/apis/mcpOAuth.ts
|
|
6734
6830
|
import { OpenAPIHono as OpenAPIHono6 } from "@hono/zod-openapi";
|
|
6735
|
-
import { extractErrorLogFields as
|
|
6831
|
+
import { extractErrorLogFields as extractErrorLogFields4, McpConnectionError as McpConnectionError3 } from "@truefoundry/trueforge-core/core";
|
|
6736
6832
|
|
|
6737
6833
|
// src/routes/mcpOAuthRoutes.ts
|
|
6738
6834
|
import { createRoute as createRoute6 } from "@hono/zod-openapi";
|
|
@@ -6814,10 +6910,10 @@ function createMcpOAuthRouter(deps) {
|
|
|
6814
6910
|
});
|
|
6815
6911
|
} catch (err) {
|
|
6816
6912
|
if (err instanceof McpConnectionError3) {
|
|
6817
|
-
deps.logger.warn("MCP OAuth callback token exchange failed",
|
|
6913
|
+
deps.logger.warn("MCP OAuth callback token exchange failed", extractErrorLogFields4(err));
|
|
6818
6914
|
return callbackFailure({ c, pending, message: err.message });
|
|
6819
6915
|
}
|
|
6820
|
-
deps.logger.error("MCP OAuth callback unexpected failure",
|
|
6916
|
+
deps.logger.error("MCP OAuth callback unexpected failure", extractErrorLogFields4(err));
|
|
6821
6917
|
return callbackFailure({ c, pending, message: "Internal server error", jsonStatus: 500 });
|
|
6822
6918
|
}
|
|
6823
6919
|
return callbackSuccess({ c, pending });
|
|
@@ -6831,7 +6927,7 @@ function createMcpOAuthRouter(deps) {
|
|
|
6831
6927
|
init_config();
|
|
6832
6928
|
init_mcpServerStore();
|
|
6833
6929
|
import { OpenAPIHono as OpenAPIHono7 } from "@hono/zod-openapi";
|
|
6834
|
-
import { extractErrorLogFields as
|
|
6930
|
+
import { extractErrorLogFields as extractErrorLogFields5, isAuthRequired, McpConnectionError as McpConnectionError4, RemoteMCP } from "@truefoundry/trueforge-core/core";
|
|
6835
6931
|
|
|
6836
6932
|
// src/routes/mcpServerRoutes.ts
|
|
6837
6933
|
import { createRoute as createRoute7, z as z21 } from "@hono/zod-openapi";
|
|
@@ -7209,7 +7305,7 @@ function createSettingsMcpServersRouter(deps) {
|
|
|
7209
7305
|
} catch (error) {
|
|
7210
7306
|
deps.logger.error(
|
|
7211
7307
|
`DCR client registration failed for "${incomingManifest.name}"; rejecting create`,
|
|
7212
|
-
|
|
7308
|
+
extractErrorLogFields5(error)
|
|
7213
7309
|
);
|
|
7214
7310
|
const message = error instanceof Error ? error.message : "Failed to register OAuth client for this MCP server";
|
|
7215
7311
|
return c.json({ error: { message } }, 422);
|
|
@@ -7265,9 +7361,9 @@ function createSettingsMcpServersRouter(deps) {
|
|
|
7265
7361
|
existing: existing?.manifest
|
|
7266
7362
|
});
|
|
7267
7363
|
let dcrClientToSave;
|
|
7364
|
+
const urlChanged = existing !== void 0 && existing.manifest.url !== manifest.url && manifest.auth?.type === "dcr";
|
|
7268
7365
|
if (manifest.auth?.type === "dcr") {
|
|
7269
7366
|
const existingClient = existing ? await deps.mcpServerStore.getClient({ id: existing.id }, transaction) : void 0;
|
|
7270
|
-
const urlChanged = existing && existing.manifest.url !== manifest.url;
|
|
7271
7367
|
const needsDcr = existingClient === void 0 || urlChanged;
|
|
7272
7368
|
if (needsDcr) {
|
|
7273
7369
|
dcrClientToSave = await createMcpOAuthClient({
|
|
@@ -7289,6 +7385,10 @@ function createSettingsMcpServersRouter(deps) {
|
|
|
7289
7385
|
if (dcrClientToSave !== void 0) {
|
|
7290
7386
|
await deps.mcpServerStore.saveClient({ id: saved.id, record: dcrClientToSave }, transaction);
|
|
7291
7387
|
}
|
|
7388
|
+
if (urlChanged) {
|
|
7389
|
+
await deps.tokenStore.deleteTokensForServer({ id: saved.id }, transaction);
|
|
7390
|
+
await deps.tokenStore.deletePendingAuthorizationsForServer({ id: saved.id }, transaction);
|
|
7391
|
+
}
|
|
7292
7392
|
return saved;
|
|
7293
7393
|
});
|
|
7294
7394
|
const token = record.manifest.auth?.type === "dcr" ? await deps.tokenStore.getToken({ id: record.id, userRef }) : void 0;
|
|
@@ -7300,7 +7400,7 @@ function createSettingsMcpServersRouter(deps) {
|
|
|
7300
7400
|
if (error instanceof McpConnectionError4) {
|
|
7301
7401
|
deps.logger.error(
|
|
7302
7402
|
`DCR client registration failed for "${incomingManifest.name}"; rejecting upsert`,
|
|
7303
|
-
|
|
7403
|
+
extractErrorLogFields5(error)
|
|
7304
7404
|
);
|
|
7305
7405
|
return c.json({ error: { message: error.message } }, 422);
|
|
7306
7406
|
}
|
|
@@ -7340,7 +7440,7 @@ function createSettingsMcpServersRouter(deps) {
|
|
|
7340
7440
|
return c.json({ data }, 200);
|
|
7341
7441
|
} catch (error) {
|
|
7342
7442
|
if (error instanceof McpConnectionError4) {
|
|
7343
|
-
deps.logger.warn(`MCP tools/list failed for "${name}"`,
|
|
7443
|
+
deps.logger.warn(`MCP tools/list failed for "${name}"`, extractErrorLogFields5(error));
|
|
7344
7444
|
if (error.statusCode === 401) {
|
|
7345
7445
|
return c.json({ error: { message: error.message } }, 422);
|
|
7346
7446
|
}
|
|
@@ -7387,7 +7487,7 @@ function createMcpServersRouter(deps) {
|
|
|
7387
7487
|
return c.json(authStatus, 200);
|
|
7388
7488
|
} catch (error) {
|
|
7389
7489
|
if (error instanceof McpConnectionError4) {
|
|
7390
|
-
deps.logger.warn(`MCP authorize failed for "${name}"`,
|
|
7490
|
+
deps.logger.warn(`MCP authorize failed for "${name}"`, extractErrorLogFields5(error));
|
|
7391
7491
|
if (error.statusCode === 400) {
|
|
7392
7492
|
return c.json({ error: { message: error.message } }, 400);
|
|
7393
7493
|
}
|
|
@@ -7399,7 +7499,7 @@ function createMcpServersRouter(deps) {
|
|
|
7399
7499
|
}
|
|
7400
7500
|
return c.json({ error: { message: error.message } }, 500);
|
|
7401
7501
|
}
|
|
7402
|
-
deps.logger.error(`MCP authorize unexpected failure for "${name}"`,
|
|
7502
|
+
deps.logger.error(`MCP authorize unexpected failure for "${name}"`, extractErrorLogFields5(error));
|
|
7403
7503
|
return c.json({ error: { message: "Internal server error" } }, 500);
|
|
7404
7504
|
}
|
|
7405
7505
|
};
|
|
@@ -8002,7 +8102,7 @@ import {
|
|
|
8002
8102
|
} from "@truefoundry/trueforge-core/agent-session";
|
|
8003
8103
|
import {
|
|
8004
8104
|
AgentHarnessError,
|
|
8005
|
-
extractErrorLogFields as
|
|
8105
|
+
extractErrorLogFields as extractErrorLogFields6,
|
|
8006
8106
|
isAgentInputUserMessage,
|
|
8007
8107
|
isFileContentPart,
|
|
8008
8108
|
McpConnectionError as McpConnectionError5,
|
|
@@ -8010,7 +8110,7 @@ import {
|
|
|
8010
8110
|
validateSandboxOwnedByTenant,
|
|
8011
8111
|
VercelAILLM
|
|
8012
8112
|
} from "@truefoundry/trueforge-core/core";
|
|
8013
|
-
import { HTTPException as
|
|
8113
|
+
import { HTTPException as HTTPException4 } from "hono/http-exception";
|
|
8014
8114
|
import { streamSSE } from "hono/streaming";
|
|
8015
8115
|
|
|
8016
8116
|
// src/routes/turnRoutes.ts
|
|
@@ -8210,6 +8310,10 @@ Use \`previous_turn_id\` to chain to the session's last turn (defaults to \`auto
|
|
|
8210
8310
|
content: { "application/json": { schema: RequestErrorResponseSchema } },
|
|
8211
8311
|
description: "Requested action cannot be performed on the session because it is no longer usable."
|
|
8212
8312
|
},
|
|
8313
|
+
413: {
|
|
8314
|
+
content: { "application/json": { schema: RequestErrorResponseSchema } },
|
|
8315
|
+
description: "Request body exceeds the configured maximum size (MAX_REQUEST_BODY_BYTES)."
|
|
8316
|
+
},
|
|
8213
8317
|
422: {
|
|
8214
8318
|
content: { "application/json": { schema: RequestErrorResponseSchema } },
|
|
8215
8319
|
description: "The request is well-formed but cannot be processed: a referenced resource is missing (named agent, model, MCP server, skill, or sandbox provider), sandbox is required but unavailable (e.g. file uploads), or the turn input conflicts with current state (e.g. unresolved tool calls or approvals, tool name collision)."
|
|
@@ -8503,30 +8607,30 @@ var StreamGoneError = class extends Error {
|
|
|
8503
8607
|
import { SandboxError, validateNoPathTraversal } from "@truefoundry/trueforge-core/core";
|
|
8504
8608
|
var SandboxInvalidPathError = class extends SandboxError {
|
|
8505
8609
|
statusCode = 400;
|
|
8506
|
-
constructor({ path:
|
|
8507
|
-
super(`Path ${reason}: ${
|
|
8610
|
+
constructor({ path: path7, reason }) {
|
|
8611
|
+
super(`Path ${reason}: ${path7}`);
|
|
8508
8612
|
this.name = "SandboxInvalidPathError";
|
|
8509
8613
|
}
|
|
8510
8614
|
};
|
|
8511
8615
|
var MAX_PATH_BYTES = 4095;
|
|
8512
8616
|
var MAX_SEGMENT_BYTES = 255;
|
|
8513
|
-
function validateSandboxFilePath(
|
|
8514
|
-
if (!
|
|
8515
|
-
throw new SandboxInvalidPathError({ path:
|
|
8617
|
+
function validateSandboxFilePath(path7) {
|
|
8618
|
+
if (!path7.startsWith("/")) {
|
|
8619
|
+
throw new SandboxInvalidPathError({ path: path7, reason: "must be absolute" });
|
|
8516
8620
|
}
|
|
8517
|
-
if (
|
|
8518
|
-
throw new SandboxInvalidPathError({ path:
|
|
8621
|
+
if (path7.includes("\0")) {
|
|
8622
|
+
throw new SandboxInvalidPathError({ path: path7, reason: "must not contain a NUL byte" });
|
|
8519
8623
|
}
|
|
8520
|
-
if (Buffer.byteLength(
|
|
8521
|
-
throw new SandboxInvalidPathError({ path:
|
|
8624
|
+
if (Buffer.byteLength(path7) > MAX_PATH_BYTES) {
|
|
8625
|
+
throw new SandboxInvalidPathError({ path: path7, reason: `must be at most ${String(MAX_PATH_BYTES)} bytes` });
|
|
8522
8626
|
}
|
|
8523
|
-
if (
|
|
8627
|
+
if (path7.split("/").some((segment) => Buffer.byteLength(segment) > MAX_SEGMENT_BYTES)) {
|
|
8524
8628
|
throw new SandboxInvalidPathError({
|
|
8525
|
-
path:
|
|
8629
|
+
path: path7,
|
|
8526
8630
|
reason: `must not have a segment longer than ${String(MAX_SEGMENT_BYTES)} bytes`
|
|
8527
8631
|
});
|
|
8528
8632
|
}
|
|
8529
|
-
validateNoPathTraversal(
|
|
8633
|
+
validateNoPathTraversal(path7);
|
|
8530
8634
|
}
|
|
8531
8635
|
|
|
8532
8636
|
// src/apis/turns.ts
|
|
@@ -8545,8 +8649,8 @@ function toArrayBuffer(content) {
|
|
|
8545
8649
|
new Uint8Array(buffer).set(content);
|
|
8546
8650
|
return buffer;
|
|
8547
8651
|
}
|
|
8548
|
-
function toContentDisposition(
|
|
8549
|
-
const fileName =
|
|
8652
|
+
function toContentDisposition(path7) {
|
|
8653
|
+
const fileName = path7.split("/").filter(Boolean).pop() ?? "download";
|
|
8550
8654
|
const encoded = encodeURIComponent(fileName).replace(
|
|
8551
8655
|
/['()*]/g,
|
|
8552
8656
|
(char) => `%${char.charCodeAt(0).toString(16).toUpperCase()}`
|
|
@@ -8591,7 +8695,7 @@ function createTurnResolver(deps) {
|
|
|
8591
8695
|
userRef
|
|
8592
8696
|
});
|
|
8593
8697
|
if (connection === void 0) {
|
|
8594
|
-
throw new
|
|
8698
|
+
throw new HTTPException4(422, {
|
|
8595
8699
|
message: `Unknown MCP server "${name}" \u2014 not configured`
|
|
8596
8700
|
});
|
|
8597
8701
|
}
|
|
@@ -8606,14 +8710,14 @@ function createTurnResolver(deps) {
|
|
|
8606
8710
|
logger
|
|
8607
8711
|
});
|
|
8608
8712
|
if (provider === void 0) {
|
|
8609
|
-
throw new
|
|
8713
|
+
throw new HTTPException4(422, {
|
|
8610
8714
|
message: "no sandbox provider configured \u2014 PUT /settings/sandbox-providers"
|
|
8611
8715
|
});
|
|
8612
8716
|
}
|
|
8613
8717
|
if (existingSandboxId === void 0) {
|
|
8614
8718
|
const status = await checkSnapshotStatus({ store: sandboxProviderStore, tenant_id: TENANT_ID, logger });
|
|
8615
8719
|
if (status?.status !== "ready") {
|
|
8616
|
-
throw new
|
|
8720
|
+
throw new HTTPException4(422, {
|
|
8617
8721
|
message: status?.status === "failed" ? `sandbox image build failed (${status.status_reason ?? "unknown error"})` : "sandbox image is activating \u2014 retry shortly"
|
|
8618
8722
|
});
|
|
8619
8723
|
}
|
|
@@ -8636,7 +8740,7 @@ function createTurnResolver(deps) {
|
|
|
8636
8740
|
agent: async (agentId) => {
|
|
8637
8741
|
const record = await agentStore.getAgent({ tenant_id: TENANT_ID, id: agentId });
|
|
8638
8742
|
if (record === void 0) {
|
|
8639
|
-
throw new
|
|
8743
|
+
throw new HTTPException4(422, { message: `Agent not found: ${agentId}` });
|
|
8640
8744
|
}
|
|
8641
8745
|
return record.manifest;
|
|
8642
8746
|
},
|
|
@@ -8688,13 +8792,13 @@ async function drainTurnEvents(input) {
|
|
|
8688
8792
|
logger.warn("Turn stream ended after session/turn was removed", {
|
|
8689
8793
|
sessionId,
|
|
8690
8794
|
turnId,
|
|
8691
|
-
...
|
|
8795
|
+
...extractErrorLogFields6(error)
|
|
8692
8796
|
});
|
|
8693
8797
|
} else {
|
|
8694
8798
|
logger.error("Unexpected error in turn event drain", {
|
|
8695
8799
|
sessionId,
|
|
8696
8800
|
turnId,
|
|
8697
|
-
...
|
|
8801
|
+
...extractErrorLogFields6(error)
|
|
8698
8802
|
});
|
|
8699
8803
|
}
|
|
8700
8804
|
} finally {
|
|
@@ -8706,7 +8810,7 @@ function resolveAfterSequenceNumber(c, bodyAfterSequenceNumber) {
|
|
|
8706
8810
|
if (lastEventId) {
|
|
8707
8811
|
const sequenceNumber = Number(lastEventId);
|
|
8708
8812
|
if (!Number.isInteger(sequenceNumber) || sequenceNumber < 0) {
|
|
8709
|
-
throw new
|
|
8813
|
+
throw new HTTPException4(400, { message: "Invalid Last-Event-Id header" });
|
|
8710
8814
|
}
|
|
8711
8815
|
return sequenceNumber;
|
|
8712
8816
|
}
|
|
@@ -8758,10 +8862,10 @@ function createTurnsRouter(deps) {
|
|
|
8758
8862
|
};
|
|
8759
8863
|
const downloadSandboxFileHandler = async (c) => {
|
|
8760
8864
|
const { session_id: sessionId, turn_id: turnId } = c.req.valid("param");
|
|
8761
|
-
const { path:
|
|
8865
|
+
const { path: path7 } = c.req.valid("query");
|
|
8762
8866
|
let sandboxId;
|
|
8763
8867
|
try {
|
|
8764
|
-
validateSandboxFilePath(
|
|
8868
|
+
validateSandboxFilePath(path7);
|
|
8765
8869
|
const session = await deps.sessions.get({ tenant_id: TENANT_ID, session_id: sessionId });
|
|
8766
8870
|
if (!session) {
|
|
8767
8871
|
return c.json({ error: { message: `Session not found: ${sessionId}` } }, 404);
|
|
@@ -8786,11 +8890,11 @@ function createTurnsRouter(deps) {
|
|
|
8786
8890
|
return c.json({ error: { message: "No sandbox provider configured" } }, 412);
|
|
8787
8891
|
}
|
|
8788
8892
|
validateSandboxOwnedByTenant(sandboxId, TENANT_ID);
|
|
8789
|
-
const content = await provider.downloadFile({ sandboxId, path:
|
|
8893
|
+
const content = await provider.downloadFile({ sandboxId, path: path7 });
|
|
8790
8894
|
return c.body(toArrayBuffer(content), 200, {
|
|
8791
8895
|
"Content-Type": "application/octet-stream",
|
|
8792
8896
|
"Content-Length": String(content.byteLength),
|
|
8793
|
-
"Content-Disposition": toContentDisposition(
|
|
8897
|
+
"Content-Disposition": toContentDisposition(path7),
|
|
8794
8898
|
"Cache-Control": "private, no-store"
|
|
8795
8899
|
});
|
|
8796
8900
|
} catch (error) {
|
|
@@ -8798,11 +8902,11 @@ function createTurnsRouter(deps) {
|
|
|
8798
8902
|
return c.json({ error: { message: error.message } }, error.statusCode);
|
|
8799
8903
|
}
|
|
8800
8904
|
deps.logger.error("Sandbox file download failed", {
|
|
8801
|
-
...
|
|
8905
|
+
...extractErrorLogFields6(error),
|
|
8802
8906
|
sessionId,
|
|
8803
8907
|
turnId,
|
|
8804
8908
|
sandboxId,
|
|
8805
|
-
path:
|
|
8909
|
+
path: path7
|
|
8806
8910
|
});
|
|
8807
8911
|
return c.json({ error: { message: "Failed to download file from sandbox" } }, 424);
|
|
8808
8912
|
}
|
|
@@ -8934,7 +9038,7 @@ function createTurnsRouter(deps) {
|
|
|
8934
9038
|
try {
|
|
8935
9039
|
await stream.writeSSE(turnEventSsePayload(event, sequenceNumber));
|
|
8936
9040
|
} catch (error) {
|
|
8937
|
-
deps.logger.error("SSE stream write error",
|
|
9041
|
+
deps.logger.error("SSE stream write error", extractErrorLogFields6(error));
|
|
8938
9042
|
shouldWriteToSSEStream = false;
|
|
8939
9043
|
}
|
|
8940
9044
|
}
|
|
@@ -8963,7 +9067,7 @@ function createTurnsRouter(deps) {
|
|
|
8963
9067
|
await turnEventStream.assertSubscribable();
|
|
8964
9068
|
} catch (error) {
|
|
8965
9069
|
if (error instanceof StreamGoneError) {
|
|
8966
|
-
throw new
|
|
9070
|
+
throw new HTTPException4(412, { message: error.message, cause: error });
|
|
8967
9071
|
}
|
|
8968
9072
|
throw error;
|
|
8969
9073
|
}
|
|
@@ -8992,7 +9096,7 @@ function createTurnsRouter(deps) {
|
|
|
8992
9096
|
}
|
|
8993
9097
|
} catch (error) {
|
|
8994
9098
|
if (!subscribeAbort.signal.aborted) {
|
|
8995
|
-
deps.logger.error("Unexpected error in turn subscribe SSE loop",
|
|
9099
|
+
deps.logger.error("Unexpected error in turn subscribe SSE loop", extractErrorLogFields6(error));
|
|
8996
9100
|
}
|
|
8997
9101
|
} finally {
|
|
8998
9102
|
clearTimeout(timeoutHandler);
|
|
@@ -9012,6 +9116,28 @@ function createTurnsRouter(deps) {
|
|
|
9012
9116
|
return router;
|
|
9013
9117
|
}
|
|
9014
9118
|
|
|
9119
|
+
// src/app.ts
|
|
9120
|
+
init_config();
|
|
9121
|
+
|
|
9122
|
+
// src/packageVersion.ts
|
|
9123
|
+
import { readFileSync } from "fs";
|
|
9124
|
+
import path2 from "path";
|
|
9125
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9126
|
+
var PACKAGE_ROOT2 = path2.resolve(path2.dirname(fileURLToPath2(import.meta.url)), "..");
|
|
9127
|
+
function readPackageVersion() {
|
|
9128
|
+
const packageJsonPath = path2.join(PACKAGE_ROOT2, "package.json");
|
|
9129
|
+
const parsed = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
9130
|
+
if (typeof parsed !== "object" || parsed === null || !("version" in parsed)) {
|
|
9131
|
+
throw new Error(`${packageJsonPath} is missing a version field`);
|
|
9132
|
+
}
|
|
9133
|
+
const { version } = parsed;
|
|
9134
|
+
if (typeof version !== "string" || version.length === 0) {
|
|
9135
|
+
throw new Error(`${packageJsonPath} version must be a non-empty string`);
|
|
9136
|
+
}
|
|
9137
|
+
return version;
|
|
9138
|
+
}
|
|
9139
|
+
var PACKAGE_VERSION = readPackageVersion();
|
|
9140
|
+
|
|
9015
9141
|
// src/zodErrorResponse.ts
|
|
9016
9142
|
import { z as z23 } from "@hono/zod-openapi";
|
|
9017
9143
|
function zodErrorResponse(c, error) {
|
|
@@ -9026,21 +9152,27 @@ var zodValidationHook = (result, c) => {
|
|
|
9026
9152
|
|
|
9027
9153
|
// src/app.ts
|
|
9028
9154
|
var BEARER_AUTH_SCHEME = "BearerAuth";
|
|
9155
|
+
function createRequestBodyLimitMiddleware(maxSize) {
|
|
9156
|
+
return bodyLimit({
|
|
9157
|
+
maxSize,
|
|
9158
|
+
onError: (c) => c.json({ error: { message: `Request body exceeds the maximum size of ${String(maxSize)} bytes` } }, 413)
|
|
9159
|
+
});
|
|
9160
|
+
}
|
|
9029
9161
|
function createAppErrorHandler(params) {
|
|
9030
9162
|
return (error, c) => {
|
|
9031
9163
|
if (error instanceof z24.ZodError) {
|
|
9032
9164
|
return zodErrorResponse(c, error);
|
|
9033
9165
|
}
|
|
9034
|
-
if (error instanceof
|
|
9166
|
+
if (error instanceof HTTPException5) {
|
|
9035
9167
|
if (error.status >= 500) {
|
|
9036
9168
|
params.logger.error("Server API error", {
|
|
9037
9169
|
status: error.status,
|
|
9038
|
-
...
|
|
9170
|
+
...extractErrorLogFields7(error)
|
|
9039
9171
|
});
|
|
9040
9172
|
}
|
|
9041
9173
|
return c.json({ error: { message: error.message } }, error.status);
|
|
9042
9174
|
}
|
|
9043
|
-
params.logger.error("Unhandled error",
|
|
9175
|
+
params.logger.error("Unhandled error", extractErrorLogFields7(error));
|
|
9044
9176
|
return c.json({ error: { message: "Internal server error" } }, 500);
|
|
9045
9177
|
};
|
|
9046
9178
|
}
|
|
@@ -9049,7 +9181,7 @@ var openApiDocConfig = {
|
|
|
9049
9181
|
info: {
|
|
9050
9182
|
title: "TrueForge API",
|
|
9051
9183
|
description: "HTTP API for the TrueForge agent server (`/api/v1`). Interactive docs are served at `/api/v1/docs` (OpenAPI JSON at `/api/v1/openapi.json`).\n\n**Authentication:** Standalone deployments (no OIDC) accept requests without credentials \u2014 middleware stamps a local default user. When OIDC is configured, protected routes require a valid `id_token` cookie or `Authorization: Bearer` ID token. There is no built-in API-key scheme; pass custom headers only if your reverse proxy or IdP layer requires them.\n\nCovers DB-backed sessions, the agent registry, settings catalogs, and model/MCP/skill/sandbox providers.",
|
|
9052
|
-
version:
|
|
9184
|
+
version: PACKAGE_VERSION
|
|
9053
9185
|
}
|
|
9054
9186
|
};
|
|
9055
9187
|
function registerOpenApiBearerAuth(app) {
|
|
@@ -9088,6 +9220,7 @@ function withAdminAuth(router) {
|
|
|
9088
9220
|
function createServerApp(deps) {
|
|
9089
9221
|
const app = new OpenAPIHono14({ defaultHook: zodValidationHook });
|
|
9090
9222
|
const authEnabled = deps.oidcClient != null;
|
|
9223
|
+
app.use("*", createRequestBodyLimitMiddleware(config_default.MAX_REQUEST_BODY_BYTES));
|
|
9091
9224
|
app.get("/healthz", (c) => c.text("OK!"));
|
|
9092
9225
|
app.route("/api/v1/auth", createAuthRouter({ oidcClient: deps.oidcClient, logger: deps.logger }));
|
|
9093
9226
|
app.route(
|
|
@@ -9191,7 +9324,8 @@ function createServerApp(deps) {
|
|
|
9191
9324
|
sandboxProviderStore: deps.sandboxProviderStore,
|
|
9192
9325
|
redis: deps.redis,
|
|
9193
9326
|
requestReplyRouter: deps.requestReplyRouter,
|
|
9194
|
-
resolveUserContext
|
|
9327
|
+
resolveUserContext,
|
|
9328
|
+
logger: deps.logger
|
|
9195
9329
|
})
|
|
9196
9330
|
)
|
|
9197
9331
|
);
|
|
@@ -9480,7 +9614,7 @@ import { serveStatic } from "@hono/node-server/serve-static";
|
|
|
9480
9614
|
import { every } from "hono/combine";
|
|
9481
9615
|
import { compress } from "hono/compress";
|
|
9482
9616
|
import { existsSync as existsSync2 } from "fs";
|
|
9483
|
-
import
|
|
9617
|
+
import path3 from "path";
|
|
9484
9618
|
var SERVER_PATH_PREFIXES = ["/api", "/healthz"];
|
|
9485
9619
|
var HASHED_ASSET_PREFIX = "/assets/";
|
|
9486
9620
|
var IMMUTABLE_CACHE_CONTROL = "public, max-age=31536000, immutable";
|
|
@@ -9489,7 +9623,7 @@ function isServerPath(pathname) {
|
|
|
9489
9623
|
return SERVER_PATH_PREFIXES.some((prefix) => pathname === prefix || pathname.startsWith(`${prefix}/`));
|
|
9490
9624
|
}
|
|
9491
9625
|
function mountFrontend(app, dir) {
|
|
9492
|
-
if (!existsSync2(
|
|
9626
|
+
if (!existsSync2(path3.join(dir, "index.html"))) {
|
|
9493
9627
|
return false;
|
|
9494
9628
|
}
|
|
9495
9629
|
const serveFile = serveStatic({ root: dir, precompressed: true });
|
|
@@ -9504,14 +9638,108 @@ function mountFrontend(app, dir) {
|
|
|
9504
9638
|
};
|
|
9505
9639
|
const serveCompressed = every(compress(), serveWithCacheHeaders);
|
|
9506
9640
|
const serveBuild = async (c, next) => {
|
|
9507
|
-
if (isServerPath(c.req.path))
|
|
9508
|
-
|
|
9641
|
+
if (isServerPath(c.req.path)) {
|
|
9642
|
+
return next();
|
|
9643
|
+
}
|
|
9644
|
+
if (c.req.method !== "GET" && c.req.method !== "HEAD") {
|
|
9645
|
+
return next();
|
|
9646
|
+
}
|
|
9509
9647
|
return serveCompressed(c, next);
|
|
9510
9648
|
};
|
|
9649
|
+
const serveAppShell = serveStatic({ root: dir, rewriteRequestPath: () => "/index.html", precompressed: true });
|
|
9650
|
+
const serveSpaFallback = async (c, next) => {
|
|
9651
|
+
if (isServerPath(c.req.path)) {
|
|
9652
|
+
return next();
|
|
9653
|
+
}
|
|
9654
|
+
if (c.req.method !== "GET" && c.req.method !== "HEAD") {
|
|
9655
|
+
return next();
|
|
9656
|
+
}
|
|
9657
|
+
if (c.req.header("accept")?.includes("text/html") !== true) {
|
|
9658
|
+
return next();
|
|
9659
|
+
}
|
|
9660
|
+
const response = await serveAppShell(c, next);
|
|
9661
|
+
if (response instanceof Response) {
|
|
9662
|
+
response.headers.set("Cache-Control", REVALIDATE_CACHE_CONTROL);
|
|
9663
|
+
response.headers.set("Vary", "Accept-Encoding");
|
|
9664
|
+
}
|
|
9665
|
+
return response;
|
|
9666
|
+
};
|
|
9511
9667
|
app.use("/*", serveBuild);
|
|
9668
|
+
app.use("/*", serveSpaFallback);
|
|
9512
9669
|
return true;
|
|
9513
9670
|
}
|
|
9514
9671
|
|
|
9672
|
+
// src/logger.ts
|
|
9673
|
+
import winston from "winston";
|
|
9674
|
+
var STANDALONE_META_SKIP = /* @__PURE__ */ new Set(["level", "message", "timestamp", "version", "stack", "splat"]);
|
|
9675
|
+
function shouldColorize() {
|
|
9676
|
+
const noColor = process.env["NO_COLOR"];
|
|
9677
|
+
if (noColor !== void 0 && noColor !== "") {
|
|
9678
|
+
return false;
|
|
9679
|
+
}
|
|
9680
|
+
const forceColor = process.env["FORCE_COLOR"];
|
|
9681
|
+
if (forceColor === "0") {
|
|
9682
|
+
return false;
|
|
9683
|
+
}
|
|
9684
|
+
if (forceColor !== void 0 && forceColor !== "") {
|
|
9685
|
+
return true;
|
|
9686
|
+
}
|
|
9687
|
+
return process.stderr.isTTY;
|
|
9688
|
+
}
|
|
9689
|
+
function standaloneMeta(info) {
|
|
9690
|
+
const copied = { ...info };
|
|
9691
|
+
const meta = {};
|
|
9692
|
+
for (const key of Object.keys(copied)) {
|
|
9693
|
+
if (STANDALONE_META_SKIP.has(key)) {
|
|
9694
|
+
continue;
|
|
9695
|
+
}
|
|
9696
|
+
meta[key] = copied[key];
|
|
9697
|
+
}
|
|
9698
|
+
if (Object.keys(meta).length === 0) {
|
|
9699
|
+
return "";
|
|
9700
|
+
}
|
|
9701
|
+
return ` ${JSON.stringify(meta)}`;
|
|
9702
|
+
}
|
|
9703
|
+
function standaloneFormat(color) {
|
|
9704
|
+
const parts = [
|
|
9705
|
+
winston.format.timestamp({ format: "HH:mm:ss" }),
|
|
9706
|
+
winston.format.errors({ stack: true })
|
|
9707
|
+
];
|
|
9708
|
+
if (color) {
|
|
9709
|
+
parts.push(winston.format.colorize({ level: true }));
|
|
9710
|
+
}
|
|
9711
|
+
parts.push(
|
|
9712
|
+
winston.format.printf((info) => {
|
|
9713
|
+
const extra = standaloneMeta(info);
|
|
9714
|
+
const stack = typeof info["stack"] === "string" ? `
|
|
9715
|
+
${info["stack"]}` : "";
|
|
9716
|
+
return `${String(info["timestamp"])} ${info.level} ${String(info.message)}${extra}${stack}`;
|
|
9717
|
+
})
|
|
9718
|
+
);
|
|
9719
|
+
return winston.format.combine(...parts);
|
|
9720
|
+
}
|
|
9721
|
+
function jsonFormat() {
|
|
9722
|
+
return winston.format.combine(
|
|
9723
|
+
winston.format.timestamp(),
|
|
9724
|
+
winston.format.errors({ stack: true }),
|
|
9725
|
+
winston.format.json()
|
|
9726
|
+
);
|
|
9727
|
+
}
|
|
9728
|
+
function serverLogFormat(options) {
|
|
9729
|
+
if (options.standalone) {
|
|
9730
|
+
return standaloneFormat(shouldColorize());
|
|
9731
|
+
}
|
|
9732
|
+
return jsonFormat();
|
|
9733
|
+
}
|
|
9734
|
+
function createServerLogger(options) {
|
|
9735
|
+
return winston.createLogger({
|
|
9736
|
+
level: options.level,
|
|
9737
|
+
defaultMeta: { version: options.version },
|
|
9738
|
+
format: serverLogFormat({ standalone: options.standalone }),
|
|
9739
|
+
transports: [new winston.transports.Console()]
|
|
9740
|
+
});
|
|
9741
|
+
}
|
|
9742
|
+
|
|
9515
9743
|
// src/runtime/activeTurns.ts
|
|
9516
9744
|
import "@truefoundry/trueforge-core/agent-session";
|
|
9517
9745
|
function activeTurnKey(sessionId, turnId) {
|
|
@@ -9594,6 +9822,118 @@ var ActiveTurnRegistry = class {
|
|
|
9594
9822
|
}
|
|
9595
9823
|
};
|
|
9596
9824
|
|
|
9825
|
+
// src/startupBanner.ts
|
|
9826
|
+
var STANDALONE_MODE_DISCLAIMER = "Standalone mode is intended for local use on your own machine. It is not hardened for production or shared internet access \u2014 please keep it on localhost. We cannot take responsibility for data loss or unauthorized access if this mode is used beyond that.";
|
|
9827
|
+
var ANSI_SHADOW = {
|
|
9828
|
+
T: ["\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557", "\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D", " \u2588\u2588\u2551 ", " \u2588\u2588\u2551 ", " \u2588\u2588\u2551 ", " \u255A\u2550\u255D "],
|
|
9829
|
+
R: ["\u2588\u2588\u2588\u2588\u2588\u2588\u2557 ", "\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557", "\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D", "\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u255A\u2550\u255D \u255A\u2550\u255D"],
|
|
9830
|
+
U: ["\u2588\u2588\u2557 \u2588\u2588\u2557", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D", " \u255A\u2550\u2550\u2550\u2550\u2550\u255D "],
|
|
9831
|
+
E: ["\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557", "\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D", "\u2588\u2588\u2588\u2588\u2588\u2557 ", "\u2588\u2588\u2554\u2550\u2550\u255D ", "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557", "\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D"],
|
|
9832
|
+
F: ["\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557", "\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D", "\u2588\u2588\u2588\u2588\u2588\u2557 ", "\u2588\u2588\u2554\u2550\u2550\u255D ", "\u2588\u2588\u2551 ", "\u255A\u2550\u255D "],
|
|
9833
|
+
O: [" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ", "\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D", " \u255A\u2550\u2550\u2550\u2550\u2550\u255D "],
|
|
9834
|
+
G: [" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ", "\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D ", "\u2588\u2588\u2551 \u2588\u2588\u2588\u2557", "\u2588\u2588\u2551 \u2588\u2588\u2551", "\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D", " \u255A\u2550\u2550\u2550\u2550\u2550\u255D "]
|
|
9835
|
+
};
|
|
9836
|
+
var WORDMARK_TEXT = "TRUEFORGE";
|
|
9837
|
+
var WARNING_INNER_WIDTH = 72;
|
|
9838
|
+
var BRAND_COLOR = "\x1B[38;5;99m";
|
|
9839
|
+
var YELLOW = "\x1B[33m";
|
|
9840
|
+
var BOLD = "\x1B[1m";
|
|
9841
|
+
var DIM = "\x1B[2m";
|
|
9842
|
+
var RESET = "\x1B[0m";
|
|
9843
|
+
function glyphFor(ch) {
|
|
9844
|
+
const glyph = ANSI_SHADOW[ch];
|
|
9845
|
+
if (glyph === void 0) {
|
|
9846
|
+
throw new Error(`No ASCII glyph for ${JSON.stringify(ch)}`);
|
|
9847
|
+
}
|
|
9848
|
+
return glyph;
|
|
9849
|
+
}
|
|
9850
|
+
function rowOf(glyph, row) {
|
|
9851
|
+
const cell = glyph[row];
|
|
9852
|
+
if (cell === void 0) {
|
|
9853
|
+
throw new Error(`Glyph is missing row ${String(row)}`);
|
|
9854
|
+
}
|
|
9855
|
+
return cell;
|
|
9856
|
+
}
|
|
9857
|
+
function renderTrueForgeWordmark() {
|
|
9858
|
+
const glyphs = [];
|
|
9859
|
+
for (let i = 0; i < WORDMARK_TEXT.length; i += 1) {
|
|
9860
|
+
const ch = WORDMARK_TEXT[i];
|
|
9861
|
+
if (ch === void 0) {
|
|
9862
|
+
throw new Error(`Missing character at index ${String(i)}`);
|
|
9863
|
+
}
|
|
9864
|
+
glyphs.push(glyphFor(ch));
|
|
9865
|
+
}
|
|
9866
|
+
const rowCount = glyphs[0]?.length;
|
|
9867
|
+
if (rowCount === void 0) {
|
|
9868
|
+
throw new Error("Wordmark text must not be empty");
|
|
9869
|
+
}
|
|
9870
|
+
const rows = [];
|
|
9871
|
+
for (let row = 0; row < rowCount; row += 1) {
|
|
9872
|
+
rows.push(glyphs.map((glyph) => rowOf(glyph, row)).join(""));
|
|
9873
|
+
}
|
|
9874
|
+
return rows.join("\n");
|
|
9875
|
+
}
|
|
9876
|
+
function wrapText(text, width) {
|
|
9877
|
+
const words = text.split(/\s+/).filter((word) => word.length > 0);
|
|
9878
|
+
const lines = [];
|
|
9879
|
+
let current = "";
|
|
9880
|
+
for (const word of words) {
|
|
9881
|
+
if (current.length === 0) {
|
|
9882
|
+
if (word.length > width) {
|
|
9883
|
+
lines.push(word);
|
|
9884
|
+
} else {
|
|
9885
|
+
current = word;
|
|
9886
|
+
}
|
|
9887
|
+
continue;
|
|
9888
|
+
}
|
|
9889
|
+
const next = `${current} ${word}`;
|
|
9890
|
+
if (next.length <= width) {
|
|
9891
|
+
current = next;
|
|
9892
|
+
} else {
|
|
9893
|
+
lines.push(current);
|
|
9894
|
+
current = word.length > width ? "" : word;
|
|
9895
|
+
if (word.length > width) {
|
|
9896
|
+
lines.push(word);
|
|
9897
|
+
}
|
|
9898
|
+
}
|
|
9899
|
+
}
|
|
9900
|
+
if (current.length > 0) {
|
|
9901
|
+
lines.push(current);
|
|
9902
|
+
}
|
|
9903
|
+
return lines;
|
|
9904
|
+
}
|
|
9905
|
+
function paint(options) {
|
|
9906
|
+
if (!options.enabled) {
|
|
9907
|
+
return options.text;
|
|
9908
|
+
}
|
|
9909
|
+
return `${options.color}${options.text}${RESET}`;
|
|
9910
|
+
}
|
|
9911
|
+
function warningBox(message) {
|
|
9912
|
+
const label = " WARNING ";
|
|
9913
|
+
const inner = wrapText(message, WARNING_INNER_WIDTH);
|
|
9914
|
+
const width = Math.max(WARNING_INNER_WIDTH, ...inner.map((line) => line.length), label.length);
|
|
9915
|
+
const topPad = width + 1 - label.length;
|
|
9916
|
+
const top = `\u250C\u2500${label}${"\u2500".repeat(topPad)}\u2510`;
|
|
9917
|
+
const body = inner.map((line) => `\u2502 ${line.padEnd(width)} \u2502`);
|
|
9918
|
+
const bottom = `\u2514${"\u2500".repeat(width + 2)}\u2518`;
|
|
9919
|
+
return [top, ...body, bottom].join("\n");
|
|
9920
|
+
}
|
|
9921
|
+
function formatStandaloneStartupBanner(options) {
|
|
9922
|
+
const { version, color } = options;
|
|
9923
|
+
const wordmark = paint({ text: renderTrueForgeWordmark(), color: `${BOLD}${BRAND_COLOR}`, enabled: color });
|
|
9924
|
+
const subtitle = paint({ text: ` TrueForge v${version} \xB7 standalone`, color: DIM, enabled: color });
|
|
9925
|
+
const warning = paint({ text: warningBox(STANDALONE_MODE_DISCLAIMER), color: `${BOLD}${YELLOW}`, enabled: color });
|
|
9926
|
+
return { wordmark: `
|
|
9927
|
+
${wordmark}
|
|
9928
|
+
${subtitle}
|
|
9929
|
+
`, warning };
|
|
9930
|
+
}
|
|
9931
|
+
function printStandaloneStartupBanner(options) {
|
|
9932
|
+
const { wordmark, warning } = formatStandaloneStartupBanner(options);
|
|
9933
|
+
console.log(wordmark);
|
|
9934
|
+
console.warn(warning);
|
|
9935
|
+
}
|
|
9936
|
+
|
|
9597
9937
|
// src/main.ts
|
|
9598
9938
|
var configuration2;
|
|
9599
9939
|
var isOidcConfigured2;
|
|
@@ -9608,7 +9948,7 @@ try {
|
|
|
9608
9948
|
}
|
|
9609
9949
|
async function createStandalonePersistence(options) {
|
|
9610
9950
|
const { sqlitePath, logger } = options;
|
|
9611
|
-
await mkdir(
|
|
9951
|
+
await mkdir(path6.dirname(sqlitePath), { recursive: true });
|
|
9612
9952
|
const [{ createSqliteDb: createSqliteDb2 }, { migrateSqliteToLatest: migrateSqliteToLatest2 }, sqliteStores] = await Promise.all([
|
|
9613
9953
|
Promise.resolve().then(() => (init_client(), client_exports)),
|
|
9614
9954
|
Promise.resolve().then(() => (init_migrateSqlite(), migrateSqlite_exports)),
|
|
@@ -9750,11 +10090,16 @@ async function createServerRuntime(persistence, logger) {
|
|
|
9750
10090
|
return { activeTurns, app, destroyDb, redis, requestReplyRouter };
|
|
9751
10091
|
}
|
|
9752
10092
|
try {
|
|
9753
|
-
const logger =
|
|
10093
|
+
const logger = createServerLogger({
|
|
9754
10094
|
level: configuration2.LOG_LEVEL,
|
|
9755
|
-
|
|
9756
|
-
|
|
10095
|
+
standalone: configuration2.STANDALONE,
|
|
10096
|
+
version: PACKAGE_VERSION
|
|
9757
10097
|
});
|
|
10098
|
+
if (configuration2.STANDALONE) {
|
|
10099
|
+
printStandaloneStartupBanner({ version: PACKAGE_VERSION, color: shouldColorize() });
|
|
10100
|
+
} else {
|
|
10101
|
+
logger.info("TrueForge starting", { mode: "distributed" });
|
|
10102
|
+
}
|
|
9758
10103
|
const { activeTurns, app, destroyDb, redis, requestReplyRouter } = configuration2.STANDALONE ? await createServerRuntime(
|
|
9759
10104
|
await createStandalonePersistence({ sqlitePath: configuration2.SQLITE_PATH, logger }),
|
|
9760
10105
|
logger
|
|
@@ -9771,7 +10116,7 @@ try {
|
|
|
9771
10116
|
if (redis) {
|
|
9772
10117
|
requestReplySubscriber = redis.duplicate();
|
|
9773
10118
|
requestReplySubscriber.on("error", (error) => {
|
|
9774
|
-
logger.error("[RedisSubscriber] Client error",
|
|
10119
|
+
logger.error("[RedisSubscriber] Client error", extractErrorLogFields9(error));
|
|
9775
10120
|
});
|
|
9776
10121
|
await requestReplySubscriber.connect();
|
|
9777
10122
|
requestReplyExecutor = new RequestReplyExecutor({
|
|
@@ -9787,8 +10132,8 @@ try {
|
|
|
9787
10132
|
});
|
|
9788
10133
|
await requestReplyExecutor.init();
|
|
9789
10134
|
}
|
|
9790
|
-
const server = serve({ fetch: app.fetch, port: configuration2.PORT }, (info) => {
|
|
9791
|
-
|
|
10135
|
+
const server = serve({ fetch: app.fetch, port: configuration2.PORT, hostname: configuration2.HOST }, (info) => {
|
|
10136
|
+
logger.info(`Agent server listening on http://${configuration2.HOST}:${String(info.port)} (docs at /api/v1/docs)`);
|
|
9792
10137
|
});
|
|
9793
10138
|
server.on("error", (error) => {
|
|
9794
10139
|
console.error("Failed to start server:", error instanceof Error ? error.message : error);
|
|
@@ -9797,7 +10142,9 @@ try {
|
|
|
9797
10142
|
if (configuration2.NODE_ENV !== "development") {
|
|
9798
10143
|
let shuttingDown = false;
|
|
9799
10144
|
const shutdown = async (signal) => {
|
|
9800
|
-
if (shuttingDown)
|
|
10145
|
+
if (shuttingDown) {
|
|
10146
|
+
return;
|
|
10147
|
+
}
|
|
9801
10148
|
shuttingDown = true;
|
|
9802
10149
|
logger.info(`Received ${signal}, draining connections before shutdown`);
|
|
9803
10150
|
setTimeout(() => {
|
|
@@ -9809,14 +10156,14 @@ try {
|
|
|
9809
10156
|
resolve();
|
|
9810
10157
|
});
|
|
9811
10158
|
});
|
|
9812
|
-
await activeTurns.shutdownAndWait(
|
|
10159
|
+
await activeTurns.shutdownAndWait(CancellationReason4.Abandoned);
|
|
9813
10160
|
await closed;
|
|
9814
10161
|
await requestReplyExecutor?.drain();
|
|
9815
10162
|
await requestReplySubscriber?.close().catch((error) => {
|
|
9816
|
-
logger.warn("[Redis] Error closing subscriber client during shutdown",
|
|
10163
|
+
logger.warn("[Redis] Error closing subscriber client during shutdown", extractErrorLogFields9(error));
|
|
9817
10164
|
});
|
|
9818
10165
|
await redis?.close().catch((error) => {
|
|
9819
|
-
logger.warn("[Redis] Error closing client during shutdown",
|
|
10166
|
+
logger.warn("[Redis] Error closing client during shutdown", extractErrorLogFields9(error));
|
|
9820
10167
|
});
|
|
9821
10168
|
await destroyDb();
|
|
9822
10169
|
process.exit(0);
|