@exulu/backend 3.7.2 → 3.7.4
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/{chunk-T6JVFT7L.js → chunk-27K2CO47.js} +5 -0
- package/dist/{chunk-BNTL6LYY.js → chunk-AWMU6QXB.js} +109 -22
- package/dist/cli/start-whisper.js +1 -1
- package/dist/{convert-exulu-tools-to-ai-sdk-tools-UQSLJDXE.js → convert-exulu-tools-to-ai-sdk-tools-XNQ6Q3X6.js} +1 -1
- package/dist/index.cjs +439 -248
- package/dist/index.d.cts +0 -5
- package/dist/index.d.ts +0 -5
- package/dist/index.js +66 -5
- package/dist/python-setup-JZGHWQCG.js +17 -0
- package/ee/invoke-skills/artifact-filter.test.ts +49 -0
- package/ee/invoke-skills/artifact-filter.ts +38 -0
- package/ee/invoke-skills/create-sandbox.ts +56 -4
- package/ee/python/requirements.txt +5 -0
- package/package.json +1 -1
|
@@ -39,6 +39,10 @@ function getSetupScriptPath(packageRoot) {
|
|
|
39
39
|
function getVenvPath(packageRoot) {
|
|
40
40
|
return resolve(packageRoot, "ee/python/.venv");
|
|
41
41
|
}
|
|
42
|
+
function getPythonVenvPath(packageRoot) {
|
|
43
|
+
const root = packageRoot ?? getPackageRoot();
|
|
44
|
+
return isPythonEnvironmentSetup(root) ? getVenvPath(root) : void 0;
|
|
45
|
+
}
|
|
42
46
|
function isPythonEnvironmentSetup(packageRoot) {
|
|
43
47
|
const root = packageRoot ?? getPackageRoot();
|
|
44
48
|
const venvPath = getVenvPath(root);
|
|
@@ -205,6 +209,7 @@ Or manually run the setup script:
|
|
|
205
209
|
|
|
206
210
|
export {
|
|
207
211
|
getPackageRoot,
|
|
212
|
+
getPythonVenvPath,
|
|
208
213
|
isPythonEnvironmentSetup,
|
|
209
214
|
setupPythonEnvironment,
|
|
210
215
|
getPythonSetupInstructions,
|
|
@@ -1716,7 +1716,7 @@ var ExuluTool = class _ExuluTool {
|
|
|
1716
1716
|
if (!agent) {
|
|
1717
1717
|
throw new Error("Agent not found.");
|
|
1718
1718
|
}
|
|
1719
|
-
const { convertExuluToolsToAiSdkTools: convertExuluToolsToAiSdkTools2 } = await import("./convert-exulu-tools-to-ai-sdk-tools-
|
|
1719
|
+
const { convertExuluToolsToAiSdkTools: convertExuluToolsToAiSdkTools2 } = await import("./convert-exulu-tools-to-ai-sdk-tools-XNQ6Q3X6.js");
|
|
1720
1720
|
const tools = await convertExuluToolsToAiSdkTools2(
|
|
1721
1721
|
[this],
|
|
1722
1722
|
[],
|
|
@@ -5723,6 +5723,33 @@ var createUppyRoutes = async (app, config) => {
|
|
|
5723
5723
|
return app;
|
|
5724
5724
|
};
|
|
5725
5725
|
|
|
5726
|
+
// ee/invoke-skills/artifact-filter.ts
|
|
5727
|
+
var IGNORED_SEGMENTS = /* @__PURE__ */ new Set([
|
|
5728
|
+
"venv",
|
|
5729
|
+
".venv",
|
|
5730
|
+
"env",
|
|
5731
|
+
"node_modules",
|
|
5732
|
+
"__pycache__",
|
|
5733
|
+
"site-packages",
|
|
5734
|
+
"dist-packages",
|
|
5735
|
+
".cache",
|
|
5736
|
+
".git",
|
|
5737
|
+
".pytest_cache",
|
|
5738
|
+
".mypy_cache",
|
|
5739
|
+
".ipynb_checkpoints"
|
|
5740
|
+
]);
|
|
5741
|
+
function isIgnoredArtifactPath(relativePath) {
|
|
5742
|
+
return relativePath.split(/[\\/]+/).some((segment) => IGNORED_SEGMENTS.has(segment));
|
|
5743
|
+
}
|
|
5744
|
+
var DEFAULT_ARTIFACT_CAP = 50;
|
|
5745
|
+
function capArtifacts(artifacts, max = DEFAULT_ARTIFACT_CAP) {
|
|
5746
|
+
if (artifacts.length <= max) return { kept: artifacts, omitted: 0 };
|
|
5747
|
+
return { kept: artifacts.slice(0, max), omitted: artifacts.length - max };
|
|
5748
|
+
}
|
|
5749
|
+
function needsDownload(localSize, remoteSize) {
|
|
5750
|
+
return localSize === void 0 || localSize !== remoteSize;
|
|
5751
|
+
}
|
|
5752
|
+
|
|
5726
5753
|
// src/exulu/system-dependencies.ts
|
|
5727
5754
|
import { exec } from "child_process";
|
|
5728
5755
|
import { existsSync as existsSync2 } from "fs";
|
|
@@ -5959,7 +5986,7 @@ function resolveSessionPath(inputPath, sessionDir) {
|
|
|
5959
5986
|
}
|
|
5960
5987
|
return resolved;
|
|
5961
5988
|
}
|
|
5962
|
-
async function restoreArtifactsFromS3(sessionDir, sessionId, userId, config) {
|
|
5989
|
+
async function restoreArtifactsFromS3(sessionDir, sessionId, userId, config, opts = {}) {
|
|
5963
5990
|
const userPrefix = `user_${userId}/sessions/${sessionId}/`;
|
|
5964
5991
|
let objects;
|
|
5965
5992
|
try {
|
|
@@ -5979,7 +6006,17 @@ async function restoreArtifactsFromS3(sessionDir, sessionId, userId, config) {
|
|
|
5979
6006
|
const idx = obj.key.indexOf(userPrefix);
|
|
5980
6007
|
const relativePath = idx >= 0 ? obj.key.slice(idx + userPrefix.length) : "";
|
|
5981
6008
|
if (!relativePath) continue;
|
|
6009
|
+
if (isIgnoredArtifactPath(relativePath)) continue;
|
|
5982
6010
|
const localPath = join2(sessionDir, relativePath);
|
|
6011
|
+
if (opts.onlyMissing) {
|
|
6012
|
+
let localSize;
|
|
6013
|
+
try {
|
|
6014
|
+
localSize = (await stat(localPath)).size;
|
|
6015
|
+
} catch {
|
|
6016
|
+
localSize = void 0;
|
|
6017
|
+
}
|
|
6018
|
+
if (!needsDownload(localSize, obj.size)) continue;
|
|
6019
|
+
}
|
|
5983
6020
|
try {
|
|
5984
6021
|
const bytes = await getS3ObjectBytes(obj.key, config);
|
|
5985
6022
|
await mkdir(dirname(localPath), { recursive: true });
|
|
@@ -6013,6 +6050,15 @@ async function downloadKeyIntoSandbox(opts) {
|
|
|
6013
6050
|
await writeFile(localPath, bytes);
|
|
6014
6051
|
return { written: true, localPath };
|
|
6015
6052
|
}
|
|
6053
|
+
async function resolvePythonVenvPath() {
|
|
6054
|
+
try {
|
|
6055
|
+
const { getPythonVenvPath } = await import("./python-setup-JZGHWQCG.js");
|
|
6056
|
+
return getPythonVenvPath();
|
|
6057
|
+
} catch (err) {
|
|
6058
|
+
console.warn("[SKILLS] Could not resolve the Python venv for the session sandbox; skill scripts fall back to the system python.", err);
|
|
6059
|
+
return void 0;
|
|
6060
|
+
}
|
|
6061
|
+
}
|
|
6016
6062
|
async function createSessionSandbox(sessionId, skills, config, userId) {
|
|
6017
6063
|
const cached = sandboxCache.get(sessionId);
|
|
6018
6064
|
if (cached) {
|
|
@@ -6026,6 +6072,13 @@ async function createSessionSandbox(sessionId, skills, config, userId) {
|
|
|
6026
6072
|
await downloadSkill(skill, skillsDirectory2, config);
|
|
6027
6073
|
cached.installedSkills.set(skill.id, skill.current_version);
|
|
6028
6074
|
}
|
|
6075
|
+
if (userId && config.fileUploads) {
|
|
6076
|
+
try {
|
|
6077
|
+
await restoreArtifactsFromS3(cached.handle.sessionDir, sessionId, userId, config, { onlyMissing: true });
|
|
6078
|
+
} catch (err) {
|
|
6079
|
+
console.error(`[SKILLS] Failed to re-sync S3 session files for session ${sessionId}; continuing.`, err);
|
|
6080
|
+
}
|
|
6081
|
+
}
|
|
6029
6082
|
return cached.handle;
|
|
6030
6083
|
}
|
|
6031
6084
|
const sessionDir = join2("/tmp", "exulu-sessions", sessionId);
|
|
@@ -6043,8 +6096,8 @@ async function createSessionSandbox(sessionId, skills, config, userId) {
|
|
|
6043
6096
|
`[SKILLS] S3 artifact persistence disabled for session ${sessionId} (userId=${userId ?? "missing"}, fileUploads=${config.fileUploads ? "configured" : "missing"})`
|
|
6044
6097
|
);
|
|
6045
6098
|
}
|
|
6046
|
-
if (userId && config.fileUploads
|
|
6047
|
-
await restoreArtifactsFromS3(sessionDir, sessionId, userId, config);
|
|
6099
|
+
if (userId && config.fileUploads) {
|
|
6100
|
+
await restoreArtifactsFromS3(sessionDir, sessionId, userId, config, { onlyMissing: dirExisted });
|
|
6048
6101
|
}
|
|
6049
6102
|
const probe = await probeSandboxSupport();
|
|
6050
6103
|
const useDirectExec = !probe.canSandbox;
|
|
@@ -6079,6 +6132,7 @@ Probe error: ${probe.reason ?? "(no detail)"}`
|
|
|
6079
6132
|
await SandboxManager.initialize(baselineSandboxConfig);
|
|
6080
6133
|
}
|
|
6081
6134
|
const npmGlobalRoot = await getNpmGlobalRoot();
|
|
6135
|
+
const pythonVenvPath = await resolvePythonVenvPath();
|
|
6082
6136
|
const sessionSandboxConfig = {
|
|
6083
6137
|
network: {
|
|
6084
6138
|
allowedDomains: [],
|
|
@@ -6093,7 +6147,8 @@ Probe error: ${probe.reason ?? "(no detail)"}`
|
|
|
6093
6147
|
// Allow Node to read globally-installed packages from inside
|
|
6094
6148
|
// the sandbox. Without this, `require('docx')` fails with
|
|
6095
6149
|
// EPERM even when NODE_PATH points the resolver here.
|
|
6096
|
-
...npmGlobalRoot ? [npmGlobalRoot] : []
|
|
6150
|
+
...npmGlobalRoot ? [npmGlobalRoot] : [],
|
|
6151
|
+
...pythonVenvPath ? [pythonVenvPath] : []
|
|
6097
6152
|
],
|
|
6098
6153
|
allowWrite: [sessionDir],
|
|
6099
6154
|
denyWrite: []
|
|
@@ -6111,7 +6166,8 @@ Probe error: ${probe.reason ?? "(no detail)"}`
|
|
|
6111
6166
|
const sandboxedExecEnv = {
|
|
6112
6167
|
...configuredVariables,
|
|
6113
6168
|
...process.env,
|
|
6114
|
-
...npmGlobalRoot ? { NODE_PATH: npmGlobalRoot } : {}
|
|
6169
|
+
...npmGlobalRoot ? { NODE_PATH: npmGlobalRoot } : {},
|
|
6170
|
+
...pythonVenvPath ? { PATH: `${join2(pythonVenvPath, "bin")}:${process.env.PATH ?? ""}`, VIRTUAL_ENV: pythonVenvPath } : {}
|
|
6115
6171
|
};
|
|
6116
6172
|
const wrapIfNeeded = async (command) => {
|
|
6117
6173
|
if (useDirectExec) return command;
|
|
@@ -6236,6 +6292,7 @@ Probe error: ${probe.reason ?? "(no detail)"}`
|
|
|
6236
6292
|
for (const entry of entries) {
|
|
6237
6293
|
const full = join2(dir, entry.name);
|
|
6238
6294
|
if (full === skillsDir) continue;
|
|
6295
|
+
if (isIgnoredArtifactPath(relative(sessionDir, full))) continue;
|
|
6239
6296
|
if (entry.isDirectory()) {
|
|
6240
6297
|
await walk(full);
|
|
6241
6298
|
} else if (entry.isFile()) {
|
|
@@ -6331,19 +6388,24 @@ Probe error: ${probe.reason ?? "(no detail)"}`
|
|
|
6331
6388
|
}
|
|
6332
6389
|
}
|
|
6333
6390
|
let stdout = result?.stdout ?? "";
|
|
6334
|
-
const
|
|
6391
|
+
const { kept, omitted } = capArtifacts(artifacts);
|
|
6392
|
+
const withUrls = kept.filter((a) => a.url);
|
|
6335
6393
|
if (withUrls.length > 0) {
|
|
6336
6394
|
const lines = ["", "[exulu-artifacts]"];
|
|
6337
6395
|
for (const a of withUrls) {
|
|
6338
6396
|
lines.push(` ${a.relativePath}: ${a.url}`);
|
|
6339
6397
|
}
|
|
6398
|
+
if (omitted > 0) {
|
|
6399
|
+
lines.push(` \u2026 ${omitted} more file(s) were created and mirrored but are not listed here.`);
|
|
6400
|
+
}
|
|
6340
6401
|
stdout = `${stdout}
|
|
6341
6402
|
${lines.join("\n")}`;
|
|
6342
6403
|
}
|
|
6343
6404
|
return {
|
|
6344
6405
|
...result,
|
|
6345
6406
|
stdout,
|
|
6346
|
-
artifacts
|
|
6407
|
+
artifacts: kept,
|
|
6408
|
+
...omitted > 0 ? { artifactsOmitted: omitted } : {}
|
|
6347
6409
|
};
|
|
6348
6410
|
}
|
|
6349
6411
|
});
|
|
@@ -6561,12 +6623,21 @@ var buildAuthToolModelOutput = (tool3) => ({ output }) => {
|
|
|
6561
6623
|
|
|
6562
6624
|
// src/templates/tools/session-file-read-tool.ts
|
|
6563
6625
|
import { z as z12 } from "zod";
|
|
6626
|
+
|
|
6627
|
+
// src/exulu/session-files.ts
|
|
6628
|
+
function sessionFilePrefix(ownerId, sessionId, s3prefix) {
|
|
6629
|
+
const general = s3prefix ? `${s3prefix.replace(/\/+$/, "")}/` : "";
|
|
6630
|
+
return `${general}user_${ownerId}/sessions/${sessionId}/`;
|
|
6631
|
+
}
|
|
6632
|
+
|
|
6633
|
+
// src/templates/tools/session-file-read-tool.ts
|
|
6564
6634
|
var DEFAULT_LIMIT = 250;
|
|
6565
6635
|
var MAX_CONTENT_CHARS = 16e3;
|
|
6566
6636
|
var createSessionFileReadTool = ({
|
|
6567
6637
|
sessionID,
|
|
6568
6638
|
user,
|
|
6569
|
-
exuluConfig
|
|
6639
|
+
exuluConfig,
|
|
6640
|
+
ownerId
|
|
6570
6641
|
}) => {
|
|
6571
6642
|
if (!sessionID || !exuluConfig?.fileUploads?.s3Bucket) return void 0;
|
|
6572
6643
|
const readSessionFileExecute = async ({ filename, offset, limit }) => {
|
|
@@ -6577,8 +6648,7 @@ var createSessionFileReadTool = ({
|
|
|
6577
6648
|
};
|
|
6578
6649
|
}
|
|
6579
6650
|
const uploads = exuluConfig.fileUploads;
|
|
6580
|
-
const
|
|
6581
|
-
const key = `${generalPrefix}user_${user?.id ?? "api"}/sessions/${sessionID}/${safeName}`;
|
|
6651
|
+
const key = `${sessionFilePrefix(ownerId ?? user?.id ?? "api", sessionID, uploads.s3prefix)}${safeName}`;
|
|
6582
6652
|
try {
|
|
6583
6653
|
const url = await getPresignedUrl(uploads.s3Bucket, key, exuluConfig);
|
|
6584
6654
|
const res = await fetch(url);
|
|
@@ -6681,6 +6751,18 @@ async function renderPdfPageToPng(pdf, page, scaleTo) {
|
|
|
6681
6751
|
var DEFAULT_LIMIT2 = 250;
|
|
6682
6752
|
var MAX_CONTENT_CHARS2 = 16e3;
|
|
6683
6753
|
var MIN_CHARS_PER_PAGE = 20;
|
|
6754
|
+
function looksLikeGarbledTextLayer(text) {
|
|
6755
|
+
let control = 0;
|
|
6756
|
+
let visible = 0;
|
|
6757
|
+
for (const ch of text) {
|
|
6758
|
+
const code = ch.charCodeAt(0);
|
|
6759
|
+
if (code === 9 || code === 10 || code === 12 || code === 13 || code === 32) continue;
|
|
6760
|
+
visible++;
|
|
6761
|
+
if (code < 32 || code === 127) control++;
|
|
6762
|
+
}
|
|
6763
|
+
if (visible < 40) return false;
|
|
6764
|
+
return control / visible > 0.01;
|
|
6765
|
+
}
|
|
6684
6766
|
var OFFICE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
6685
6767
|
".docx",
|
|
6686
6768
|
".doc",
|
|
@@ -6697,7 +6779,8 @@ var pagesPattern = /^(\d+)(?:-(\d+))?$/;
|
|
|
6697
6779
|
var createParseDocumentTool = ({
|
|
6698
6780
|
sessionID,
|
|
6699
6781
|
user,
|
|
6700
|
-
exuluConfig
|
|
6782
|
+
exuluConfig,
|
|
6783
|
+
ownerId
|
|
6701
6784
|
}) => {
|
|
6702
6785
|
if (!sessionID || !exuluConfig?.fileUploads?.s3Bucket) return void 0;
|
|
6703
6786
|
const parseDocumentExecute = async ({
|
|
@@ -6722,8 +6805,7 @@ var createParseDocumentTool = ({
|
|
|
6722
6805
|
return { error: `The pages option is only supported for PDF files \u2014 "${ext}" documents are extracted whole.` };
|
|
6723
6806
|
}
|
|
6724
6807
|
const uploads = exuluConfig.fileUploads;
|
|
6725
|
-
const
|
|
6726
|
-
const key = `${generalPrefix}user_${user?.id ?? "api"}/sessions/${sessionID}/${safeName}`;
|
|
6808
|
+
const key = `${sessionFilePrefix(ownerId ?? user?.id ?? "api", sessionID, uploads.s3prefix)}${safeName}`;
|
|
6727
6809
|
try {
|
|
6728
6810
|
const url = await getPresignedUrl(uploads.s3Bucket, key, exuluConfig);
|
|
6729
6811
|
const res = await fetch(url);
|
|
@@ -6738,6 +6820,11 @@ var createParseDocumentTool = ({
|
|
|
6738
6820
|
const pageTexts = raw.replace(/\f$/, "").split("\f");
|
|
6739
6821
|
totalPages = pageTexts.length;
|
|
6740
6822
|
const nonWhitespace = raw.replace(/\s/g, "").length;
|
|
6823
|
+
if (looksLikeGarbledTextLayer(raw)) {
|
|
6824
|
+
return {
|
|
6825
|
+
error: `"${safeName}" has a text layer that is unreadable (its font encoding maps glyphs to the wrong characters, so words and especially numbers come out wrong or vanish). Do not use extracted text from this file. Use view_document_page to read the pages visually, or suggest the user add the document to a knowledge base with a document processor for full OCR.`
|
|
6826
|
+
};
|
|
6827
|
+
}
|
|
6741
6828
|
if (nonWhitespace < totalPages * MIN_CHARS_PER_PAGE) {
|
|
6742
6829
|
return {
|
|
6743
6830
|
error: `"${safeName}" has no extractable text layer (likely a scan or image-based PDF). Use view_document_page to look at pages visually, or suggest the user add the document to a knowledge base with a document processor for full OCR.`
|
|
@@ -6985,7 +7072,8 @@ var OFFICE_EXTENSIONS2 = /* @__PURE__ */ new Set([
|
|
|
6985
7072
|
var createViewDocumentPageTool = ({
|
|
6986
7073
|
sessionID,
|
|
6987
7074
|
user,
|
|
6988
|
-
exuluConfig
|
|
7075
|
+
exuluConfig,
|
|
7076
|
+
ownerId
|
|
6989
7077
|
}) => {
|
|
6990
7078
|
if (!sessionID || !exuluConfig?.fileUploads?.s3Bucket) return void 0;
|
|
6991
7079
|
const viewDocumentPageExecute = async ({ filename, page, model }, options) => {
|
|
@@ -7018,8 +7106,7 @@ var createViewDocumentPageTool = ({
|
|
|
7018
7106
|
}
|
|
7019
7107
|
}
|
|
7020
7108
|
const uploads = exuluConfig.fileUploads;
|
|
7021
|
-
const
|
|
7022
|
-
const key = `${generalPrefix}user_${user?.id ?? "api"}/sessions/${sessionID}/${safeName}`;
|
|
7109
|
+
const key = `${sessionFilePrefix(ownerId ?? user?.id ?? "api", sessionID, uploads.s3prefix)}${safeName}`;
|
|
7023
7110
|
const pageNumber = page ?? 1;
|
|
7024
7111
|
try {
|
|
7025
7112
|
let imageBytes;
|
|
@@ -7704,7 +7791,7 @@ var hydrateVariables = async (tool3) => {
|
|
|
7704
7791
|
await Promise.all(promises);
|
|
7705
7792
|
return tool3;
|
|
7706
7793
|
};
|
|
7707
|
-
var convertExuluToolsToAiSdkTools = async (currentTools, currentSkills, approvedTools, allExuluTools, configs, contexts, user, exuluConfig, sessionID, req, project, sessionItems, model, agent, memoryItems, contextWindow, disabledTools) => {
|
|
7794
|
+
var convertExuluToolsToAiSdkTools = async (currentTools, currentSkills, approvedTools, allExuluTools, configs, contexts, user, exuluConfig, sessionID, req, project, sessionItems, model, agent, memoryItems, contextWindow, disabledTools, sessionOwnerId) => {
|
|
7708
7795
|
if (!currentTools) return {};
|
|
7709
7796
|
if (!allExuluTools) {
|
|
7710
7797
|
allExuluTools = [];
|
|
@@ -7721,7 +7808,7 @@ var convertExuluToolsToAiSdkTools = async (currentTools, currentSkills, approved
|
|
|
7721
7808
|
sessionID,
|
|
7722
7809
|
currentSkills || [],
|
|
7723
7810
|
exuluConfig,
|
|
7724
|
-
user?.id
|
|
7811
|
+
sessionOwnerId ?? user?.id
|
|
7725
7812
|
);
|
|
7726
7813
|
} catch (err) {
|
|
7727
7814
|
console.error(
|
|
@@ -7786,15 +7873,15 @@ var convertExuluToolsToAiSdkTools = async (currentTools, currentSkills, approved
|
|
|
7786
7873
|
currentTools.push(sessionItemsRetrievalTool);
|
|
7787
7874
|
}
|
|
7788
7875
|
}
|
|
7789
|
-
const sessionFileReadTool = createSessionFileReadTool({ sessionID, user, exuluConfig });
|
|
7876
|
+
const sessionFileReadTool = createSessionFileReadTool({ sessionID, user, exuluConfig, ownerId: sessionOwnerId });
|
|
7790
7877
|
if (sessionFileReadTool && !disabled.has(sessionFileReadTool.id)) {
|
|
7791
7878
|
currentTools.push(sessionFileReadTool);
|
|
7792
7879
|
}
|
|
7793
|
-
const parseDocumentTool = createParseDocumentTool({ sessionID, user, exuluConfig });
|
|
7880
|
+
const parseDocumentTool = createParseDocumentTool({ sessionID, user, exuluConfig, ownerId: sessionOwnerId });
|
|
7794
7881
|
if (parseDocumentTool && !disabled.has(parseDocumentTool.id)) {
|
|
7795
7882
|
currentTools.push(parseDocumentTool);
|
|
7796
7883
|
}
|
|
7797
|
-
const viewDocumentPageTool = createViewDocumentPageTool({ sessionID, user, exuluConfig });
|
|
7884
|
+
const viewDocumentPageTool = createViewDocumentPageTool({ sessionID, user, exuluConfig, ownerId: sessionOwnerId });
|
|
7798
7885
|
if (viewDocumentPageTool && !disabled.has(viewDocumentPageTool.id)) {
|
|
7799
7886
|
currentTools.push(viewDocumentPageTool);
|
|
7800
7887
|
}
|