@chainingintention/pi-web-cn 1.202606.25 → 1.202606.26
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 +84 -277
- package/dist/cli.js +31 -11
- package/dist/cli.js.map +1 -1
- package/dist/client/assets/CodeViewer-CEaJIjgA.js +4 -0
- package/dist/client/assets/{TerminalPanel-6pE_JF7k.js → TerminalPanel-BdMJbtLB.js} +1 -1
- package/dist/client/assets/UnifiedDiffViewer-Dkgg-4fh.js +34 -0
- package/dist/client/assets/index-iRSp25EB.js +2735 -0
- package/dist/client/assets/{vendor-editor-core-Bc1A7SO7.js → vendor-editor-core-C7aWiQy0.js} +2 -2
- package/dist/client/assets/{vendor-editor-languages-D0CnB2js.js → vendor-editor-languages-EW34FfVy.js} +1 -1
- package/dist/client/index.html +6 -3
- package/dist/config.js +9 -1
- package/dist/config.js.map +1 -1
- package/dist/plugin-api.d.ts +30 -2
- package/dist/server/app.js +35 -17
- package/dist/server/app.js.map +1 -1
- package/dist/server/gitRoutes.js +1 -1
- package/dist/server/gitRoutes.js.map +1 -1
- package/dist/server/machines/machineClient.js +33 -5
- package/dist/server/machines/machineClient.js.map +1 -1
- package/dist/server/machines/machineProxyRoutes.js +18 -3
- package/dist/server/machines/machineProxyRoutes.js.map +1 -1
- package/dist/server/managementEmbed.js +42 -22
- package/dist/server/managementEmbed.js.map +1 -1
- package/dist/server/sessiond/sessionProxyRoutes.js +1 -1
- package/dist/server/sessiond/sessionProxyRoutes.js.map +1 -1
- package/dist/server/sessiond.js +2 -2
- package/dist/server/sessiond.js.map +1 -1
- package/dist/server/sessions/attachmentService.js +68 -10
- package/dist/server/sessions/attachmentService.js.map +1 -1
- package/dist/server/sessions/authProviderOptions.js +1 -5
- package/dist/server/sessions/authProviderOptions.js.map +1 -1
- package/dist/server/sessions/piSessionManagerGateway.js +20 -2
- package/dist/server/sessions/piSessionManagerGateway.js.map +1 -1
- package/dist/server/sessions/piSessionService.js +515 -51
- package/dist/server/sessions/piSessionService.js.map +1 -1
- package/dist/server/sessions/sessionCleanup.js +157 -0
- package/dist/server/sessions/sessionCleanup.js.map +1 -0
- package/dist/server/sessions/sessionNameGenerator.js +39 -2
- package/dist/server/sessions/sessionNameGenerator.js.map +1 -1
- package/dist/server/sessions/sessionRoutes.js +17 -0
- package/dist/server/sessions/sessionRoutes.js.map +1 -1
- package/dist/server/sessions/spawnSessionTool.js +7 -2
- package/dist/server/sessions/spawnSessionTool.js.map +1 -1
- package/dist/server/sessions/spawnSubsessionTool.js +14 -4
- package/dist/server/sessions/spawnSubsessionTool.js.map +1 -1
- package/dist/server/workspaceExplorerRoutes.js +74 -24
- package/dist/server/workspaceExplorerRoutes.js.map +1 -1
- package/dist/server/workspaces/effectivePathAccess.js +27 -0
- package/dist/server/workspaces/effectivePathAccess.js.map +1 -0
- package/dist/server/workspaces/fileContentService.js +118 -7
- package/dist/server/workspaces/fileContentService.js.map +1 -1
- package/dist/server/workspaces/fileOperationService.js +1 -19
- package/dist/server/workspaces/fileOperationService.js.map +1 -1
- package/dist/server/workspaces/fileSuggestions.js +311 -23
- package/dist/server/workspaces/fileSuggestions.js.map +1 -1
- package/dist/server/workspaces/fileTreeService.js +16 -7
- package/dist/server/workspaces/fileTreeService.js.map +1 -1
- package/dist/server/workspaces/imagePreviewService.js +5 -5
- package/dist/server/workspaces/imagePreviewService.js.map +1 -1
- package/dist/server/workspaces/pathAccessPolicy.js +90 -0
- package/dist/server/workspaces/pathAccessPolicy.js.map +1 -0
- package/dist/server/workspaces/pathSafety.js +19 -10
- package/dist/server/workspaces/pathSafety.js.map +1 -1
- package/dist/server/workspaces/projectPiWebConfig.js +61 -0
- package/dist/server/workspaces/projectPiWebConfig.js.map +1 -0
- package/dist/server/workspaces/workspaceDeletionRoutes.js +1 -1
- package/dist/server/workspaces/workspaceDeletionRoutes.js.map +1 -1
- package/dist/shared/apiTypes.d.ts +89 -6
- package/dist/shared/apiTypes.js +2 -0
- package/dist/shared/apiTypes.js.map +1 -1
- package/dist/shared/capabilities.js +4 -2
- package/dist/shared/capabilities.js.map +1 -1
- package/dist/shared/federatedRoutes.js +6 -1
- package/dist/shared/federatedRoutes.js.map +1 -1
- package/dist/shared/piWebConfigParsing.js +44 -3
- package/dist/shared/piWebConfigParsing.js.map +1 -1
- package/dist/shared/promptAttachments.js +30 -11
- package/dist/shared/promptAttachments.js.map +1 -1
- package/docs/assets/pi-web-desktop.png +0 -0
- package/docs/assets/pi-web-mobile.png +0 -0
- package/docs/assets/pi-web-tablet.png +0 -0
- package/docs/config.md +203 -0
- package/docs/plugins.md +128 -4
- package/package.json +3 -1
- package/dist/client/assets/CodeViewer-BmIwBtZe.js +0 -4
- package/dist/client/assets/index-FZVnfelo.js +0 -2354
- package/docs/assets/pi-web-demo.gif +0 -0
- package/docs/assets/pi-web-demo.webm +0 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { realpath, stat } from "node:fs/promises";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { isAbsolute, relative, resolve, sep, win32 } from "node:path";
|
|
4
|
+
import { normalizeRelativePath } from "./pathSafety.js";
|
|
5
|
+
export async function createPathAccessPolicy(workspaceRootPath, pathAccess, options = {}) {
|
|
6
|
+
return {
|
|
7
|
+
workspaceRoot: await canonicalDirectory(workspaceRootPath, "Workspace path"),
|
|
8
|
+
allowedRoots: await resolveAllowedRoots(pathAccess?.allowedPaths ?? [], options),
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export async function resolveWorkspacePathAccessTarget(rootPath, requestedPath, pathAccess, options = {}) {
|
|
12
|
+
const request = requestedPath ?? "";
|
|
13
|
+
const workspaceRoot = await canonicalDirectory(rootPath, "Workspace path");
|
|
14
|
+
const allowedRoots = isAbsoluteishPath(request) ? await resolveAllowedRoots(pathAccess?.allowedPaths ?? [], options) : [];
|
|
15
|
+
return resolvePathAccessTarget({ workspaceRoot, allowedRoots }, requestedPath, options);
|
|
16
|
+
}
|
|
17
|
+
export async function resolvePathAccessTarget(policy, requestedPath, options = {}) {
|
|
18
|
+
const request = requestedPath ?? "";
|
|
19
|
+
if (isAbsoluteishPath(request))
|
|
20
|
+
return resolveAllowedTarget(policy, request, options);
|
|
21
|
+
const displayPath = normalizeRelativePath(request);
|
|
22
|
+
const target = await canonicalExistingPath(resolve(policy.workspaceRoot, displayPath));
|
|
23
|
+
ensureInside(policy.workspaceRoot, target, "Path escapes workspace");
|
|
24
|
+
return { kind: "workspace", root: policy.workspaceRoot, target, displayPath };
|
|
25
|
+
}
|
|
26
|
+
export function isAbsoluteishPath(path) {
|
|
27
|
+
return path === "~" || path.startsWith("~/") || path.startsWith("~\\") || isAbsolute(path) || win32.isAbsolute(path);
|
|
28
|
+
}
|
|
29
|
+
async function resolveAllowedRoots(allowedPaths, options) {
|
|
30
|
+
const roots = [];
|
|
31
|
+
for (const source of allowedPaths) {
|
|
32
|
+
const expanded = expandAbsoluteishPath(source, options, `Allowed path must be absolute or start with ~: ${source}`);
|
|
33
|
+
const realPath = await canonicalDirectory(expanded, `Allowed path ${source}`);
|
|
34
|
+
if (roots.some((root) => root.realPath === realPath))
|
|
35
|
+
continue;
|
|
36
|
+
roots.push({ source, path: expanded, realPath });
|
|
37
|
+
}
|
|
38
|
+
return roots;
|
|
39
|
+
}
|
|
40
|
+
async function resolveAllowedTarget(policy, request, options) {
|
|
41
|
+
if (policy.allowedRoots.length === 0)
|
|
42
|
+
throw new Error("Absolute paths are not allowed");
|
|
43
|
+
const displayPath = expandAbsoluteishPath(request, options, `Path is not absolute: ${request}`);
|
|
44
|
+
const target = await canonicalExistingPath(displayPath);
|
|
45
|
+
const root = policy.allowedRoots.find((allowedRoot) => isInsideOrSame(allowedRoot.realPath, target));
|
|
46
|
+
if (root === undefined)
|
|
47
|
+
throw new Error("Path is outside allowed paths");
|
|
48
|
+
return { kind: "allowed", root: root.realPath, target, displayPath };
|
|
49
|
+
}
|
|
50
|
+
function expandAbsoluteishPath(path, options, relativeMessage) {
|
|
51
|
+
const home = options.homeDir ?? homedir();
|
|
52
|
+
if (path === "~")
|
|
53
|
+
return home;
|
|
54
|
+
if (path.startsWith("~/") || path.startsWith("~\\"))
|
|
55
|
+
return resolve(home, path.slice(2));
|
|
56
|
+
if (isAbsolute(path))
|
|
57
|
+
return resolve(path);
|
|
58
|
+
if (win32.isAbsolute(path))
|
|
59
|
+
throw new Error(`Absolute path is not valid on this host: ${path}`);
|
|
60
|
+
throw new Error(relativeMessage);
|
|
61
|
+
}
|
|
62
|
+
async function canonicalDirectory(path, label) {
|
|
63
|
+
const canonical = await canonicalExistingPath(path, `${label} does not exist`);
|
|
64
|
+
const result = await stat(canonical);
|
|
65
|
+
if (!result.isDirectory())
|
|
66
|
+
throw new Error(`${label} must be a directory`);
|
|
67
|
+
return canonical;
|
|
68
|
+
}
|
|
69
|
+
async function canonicalExistingPath(path, missingMessage = "Path does not exist") {
|
|
70
|
+
try {
|
|
71
|
+
return await realpath(path);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
if (isNodeErrorWithCode(error, "ENOENT"))
|
|
75
|
+
throw new Error(missingMessage, { cause: error });
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function ensureInside(root, target, message) {
|
|
80
|
+
if (!isInsideOrSame(root, target))
|
|
81
|
+
throw new Error(message);
|
|
82
|
+
}
|
|
83
|
+
function isInsideOrSame(root, target) {
|
|
84
|
+
const rel = relative(root, target);
|
|
85
|
+
return rel === "" || (!rel.startsWith(`..${sep}`) && rel !== ".." && !isAbsolute(rel));
|
|
86
|
+
}
|
|
87
|
+
function isNodeErrorWithCode(error, code) {
|
|
88
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=pathAccessPolicy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pathAccessPolicy.js","sourceRoot":"","sources":["../../../src/server/workspaces/pathAccessPolicy.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { realpath } from "node:fs/promises";
|
|
2
|
-
import {
|
|
2
|
+
import { dirname, isAbsolute, join, relative, sep } from "node:path";
|
|
3
3
|
export async function resolveInsideWorkspace(rootPath, relativePath) {
|
|
4
4
|
const requested = normalizeRelativePath(relativePath);
|
|
5
5
|
const root = await realpath(rootPath);
|
|
@@ -15,17 +15,26 @@ export async function resolveInsideWorkspace(rootPath, relativePath) {
|
|
|
15
15
|
export async function resolveParentInsideWorkspace(rootPath, relativePath) {
|
|
16
16
|
const requested = normalizeRelativePath(relativePath);
|
|
17
17
|
const root = await realpath(rootPath);
|
|
18
|
-
const
|
|
19
|
-
const parent = await
|
|
20
|
-
if (isNodeErrorWithCode(error, "ENOENT"))
|
|
21
|
-
throw new Error("Path does not exist");
|
|
22
|
-
throw error;
|
|
23
|
-
});
|
|
18
|
+
const target = join(root, requested);
|
|
19
|
+
const parent = await realpathNearestExistingParent(target, root);
|
|
24
20
|
ensureInside(root, parent);
|
|
25
|
-
const target = join(parent, basename(requestedTarget));
|
|
26
21
|
ensureInside(root, target);
|
|
27
22
|
return { root, target, relativePath: requested };
|
|
28
23
|
}
|
|
24
|
+
async function realpathNearestExistingParent(target, root) {
|
|
25
|
+
let parent = target === root ? root : dirname(target);
|
|
26
|
+
while (parent !== root) {
|
|
27
|
+
try {
|
|
28
|
+
return await realpath(parent);
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
if (!isNodeErrorWithCode(error, "ENOENT"))
|
|
32
|
+
throw error;
|
|
33
|
+
parent = dirname(parent);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return realpath(root);
|
|
37
|
+
}
|
|
29
38
|
export function normalizeRelativePath(input) {
|
|
30
39
|
const value = input ?? "";
|
|
31
40
|
if (value === "" || value === ".")
|
|
@@ -37,10 +46,10 @@ export function normalizeRelativePath(input) {
|
|
|
37
46
|
throw new Error("Path traversal is not allowed");
|
|
38
47
|
return parts.join("/");
|
|
39
48
|
}
|
|
40
|
-
function isNodeErrorWithCode(error, code) {
|
|
49
|
+
export function isNodeErrorWithCode(error, code) {
|
|
41
50
|
return typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
42
51
|
}
|
|
43
|
-
function ensureInside(root, target) {
|
|
52
|
+
export function ensureInside(root, target) {
|
|
44
53
|
const rel = relative(root, target);
|
|
45
54
|
if (rel === "")
|
|
46
55
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pathSafety.js","sourceRoot":"","sources":["../../../src/server/workspaces/pathSafety.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"pathSafety.js","sourceRoot":"","sources":["../../../src/server/workspaces/pathSafety.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { effectiveUploadsConfig, parsePathAccessConfig, parseUploadsConfig } from "../../config.js";
|
|
4
|
+
export const PROJECT_PI_WEB_CONFIG_PATH = ".pi-web/config.json";
|
|
5
|
+
export async function loadProjectPiWebConfig(projectPath) {
|
|
6
|
+
const path = join(projectPath, PROJECT_PI_WEB_CONFIG_PATH);
|
|
7
|
+
try {
|
|
8
|
+
const parsed = JSON.parse(await readFile(path, "utf8"));
|
|
9
|
+
if (!isRecord(parsed))
|
|
10
|
+
throw new Error(`PI WEB project config must be a JSON object: ${path}`);
|
|
11
|
+
return { path, exists: true, config: parseProjectPiWebConfig(parsed, path) };
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
if (isNodeErrorWithCode(error, "ENOENT"))
|
|
15
|
+
return { path, exists: false, config: {} };
|
|
16
|
+
throw error;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export async function loadEffectiveProjectPathAccess(projectPath, globalConfig) {
|
|
20
|
+
const projectConfig = await loadProjectPiWebConfig(projectPath);
|
|
21
|
+
return mergePathAccessConfigs(globalConfig.pathAccess, projectConfig.config.pathAccess);
|
|
22
|
+
}
|
|
23
|
+
export async function loadEffectiveProjectUploadsConfig(projectPath, globalConfig) {
|
|
24
|
+
const projectConfig = await loadProjectPiWebConfig(projectPath);
|
|
25
|
+
return effectiveUploadsConfig({ uploads: { ...(globalConfig.uploads ?? {}), ...(projectConfig.config.uploads ?? {}) } });
|
|
26
|
+
}
|
|
27
|
+
export function mergePathAccessConfigs(...configs) {
|
|
28
|
+
const allowedPaths = dedupe(configs.flatMap((config) => config?.allowedPaths ?? []));
|
|
29
|
+
return allowedPaths.length === 0 ? undefined : { allowedPaths };
|
|
30
|
+
}
|
|
31
|
+
function parseProjectPiWebConfig(value, path) {
|
|
32
|
+
const version = value["version"];
|
|
33
|
+
return {
|
|
34
|
+
...(version !== undefined ? { version: parseProjectConfigVersion(version, path) } : {}),
|
|
35
|
+
...(value["pathAccess"] !== undefined ? { pathAccess: parsePathAccessConfig(value["pathAccess"], path) } : {}),
|
|
36
|
+
...(value["uploads"] !== undefined ? { uploads: parseUploadsConfig(value["uploads"], path) } : {}),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function parseProjectConfigVersion(value, path) {
|
|
40
|
+
if (value !== 1)
|
|
41
|
+
throw new Error(`PI WEB project config version must be 1: ${path}`);
|
|
42
|
+
return 1;
|
|
43
|
+
}
|
|
44
|
+
function dedupe(values) {
|
|
45
|
+
const seen = new Set();
|
|
46
|
+
const result = [];
|
|
47
|
+
for (const value of values) {
|
|
48
|
+
if (seen.has(value))
|
|
49
|
+
continue;
|
|
50
|
+
seen.add(value);
|
|
51
|
+
result.push(value);
|
|
52
|
+
}
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
function isNodeErrorWithCode(error, code) {
|
|
56
|
+
return error instanceof Error && "code" in error && error.code === code;
|
|
57
|
+
}
|
|
58
|
+
function isRecord(value) {
|
|
59
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=projectPiWebConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projectPiWebConfig.js","sourceRoot":"","sources":["../../../src/server/workspaces/projectPiWebConfig.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,7 +17,7 @@ export function registerWorkspaceDeletionRoutes(app, projects, workspaces, daemo
|
|
|
17
17
|
async function deleteWorkspace(projects, workspaces, daemon, projectId, workspaceId, managementEmbed, managementContext) {
|
|
18
18
|
const project = managementContext === undefined
|
|
19
19
|
? await projects.requireProject(projectId)
|
|
20
|
-
: await projectFromManagedEmbedContext(managementProjectRoot(managementEmbed), managementContext, projectId);
|
|
20
|
+
: await projectFromManagedEmbedContext(managementProjectRoot(managementEmbed), managementContext, projectId, { create: false });
|
|
21
21
|
const projectWorkspaces = await workspaces.list(project);
|
|
22
22
|
const targetWorkspace = projectWorkspaces.find((workspace) => workspace.id === workspaceId);
|
|
23
23
|
if (targetWorkspace === undefined)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspaceDeletionRoutes.js","sourceRoot":"","sources":["../../../src/server/workspaces/workspaceDeletionRoutes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AAG5E,OAAO,EACL,uBAAuB,EACvB,2BAA2B,EAC3B,qBAAqB,EACrB,+BAA+B,EAC/B,8BAA8B,GAG/B,MAAM,uBAAuB,CAAC;AAG/B,MAAM,UAAU,+BAA+B,CAAC,GAAoB,EAAE,QAAwB,EAAE,UAA4B,EAAE,SAA6B,IAAI,mBAAmB,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,eAAwC;IAC7O,GAAG,CAAC,MAAM,CAAyD,GAAG,MAAM,8CAA8C,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACnJ,IAAI,CAAC;YACH,MAAM,iBAAiB,GAAG,MAAM,2BAA2B,CAAC,OAAO,EAAE,eAAe,EAAE,KAAK,CAAC,CAAC;YAC7F,IAAI,iBAAiB,KAAK,SAAS,IAAI,CAAC,qBAAqB,CAAC,iBAAiB,EAAE,uBAAuB,CAAC;gBAAE,OAAO,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,6DAA6D,EAAE,CAAC,CAAC;YACvN,OAAO,MAAM,eAAe,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,eAAe,EAAE,iBAAiB,CAAC,CAAC;QACvJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACjG,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,QAAwB,EAAE,UAA4B,EAAE,MAA0B,EAAE,SAAiB,EAAE,WAAmB,EAAE,eAAmD,EAAE,iBAAqD;IACnQ,MAAM,OAAO,GAAG,iBAAiB,KAAK,SAAS;QAC7C,CAAC,CAAC,MAAM,QAAQ,CAAC,cAAc,CAAC,SAAS,CAAC;QAC1C,CAAC,CAAC,MAAM,8BAA8B,CAAC,qBAAqB,CAAC,eAAe,CAAC,EAAE,iBAAiB,EAAE,SAAS,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"workspaceDeletionRoutes.js","sourceRoot":"","sources":["../../../src/server/workspaces/workspaceDeletionRoutes.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,8 +2,10 @@ export type MachineKind = "local" | "remote";
|
|
|
2
2
|
export type MachineStatus = "unknown" | "online" | "offline" | "error";
|
|
3
3
|
export declare const PI_WEB_CAPABILITIES: {
|
|
4
4
|
readonly sessionsDeleteArchived: "sessions.deleteArchived";
|
|
5
|
+
readonly sessionsCleanup: "sessions.cleanup";
|
|
5
6
|
readonly sessionsReload: "sessions.reload";
|
|
6
7
|
readonly promptAttachments: "prompt.attachments";
|
|
8
|
+
readonly workspaceFileSuggestions: "workspace.fileSuggestions";
|
|
7
9
|
};
|
|
8
10
|
export type PiWebCapability = typeof PI_WEB_CAPABILITIES[keyof typeof PI_WEB_CAPABILITIES];
|
|
9
11
|
export interface Machine {
|
|
@@ -43,6 +45,12 @@ export interface PiWebPluginConfig {
|
|
|
43
45
|
settings?: PiWebPluginSettings;
|
|
44
46
|
[key: string]: unknown;
|
|
45
47
|
}
|
|
48
|
+
export interface PiWebPathAccessConfig {
|
|
49
|
+
allowedPaths?: string[];
|
|
50
|
+
}
|
|
51
|
+
export interface PiWebUploadsConfig {
|
|
52
|
+
defaultFolder?: string;
|
|
53
|
+
}
|
|
46
54
|
export interface PiWebConfigValues {
|
|
47
55
|
host?: string;
|
|
48
56
|
port?: number;
|
|
@@ -50,6 +58,10 @@ export interface PiWebConfigValues {
|
|
|
50
58
|
shortcuts?: PiWebShortcutConfig;
|
|
51
59
|
plugins?: PiWebPluginConfigMap;
|
|
52
60
|
managementEmbed?: PiWebManagementEmbedConfig;
|
|
61
|
+
/** External filesystem roots PI WEB may expose outside a workspace. */
|
|
62
|
+
pathAccess?: PiWebPathAccessConfig;
|
|
63
|
+
/** Workspace-relative defaults for manual file uploads. */
|
|
64
|
+
uploads?: PiWebUploadsConfig;
|
|
53
65
|
/** Maximum accepted HTTP request body size in bytes (uploads/attachments). */
|
|
54
66
|
maxUploadBytes?: number;
|
|
55
67
|
/** When true, LLMs can start new sessions via the spawn_session tool. */
|
|
@@ -112,6 +124,9 @@ export interface Project {
|
|
|
112
124
|
path: string;
|
|
113
125
|
createdAt: string;
|
|
114
126
|
}
|
|
127
|
+
export interface WorkspaceEffectiveConfig {
|
|
128
|
+
uploads?: PiWebUploadsConfig;
|
|
129
|
+
}
|
|
115
130
|
export interface Workspace {
|
|
116
131
|
id: string;
|
|
117
132
|
projectId: string;
|
|
@@ -121,6 +136,8 @@ export interface Workspace {
|
|
|
121
136
|
isMain: boolean;
|
|
122
137
|
isGitRepo: boolean;
|
|
123
138
|
isGitWorktree: boolean;
|
|
139
|
+
/** Workspace-effective project/global settings needed by workspace UI features. */
|
|
140
|
+
effectiveConfig?: WorkspaceEffectiveConfig;
|
|
124
141
|
}
|
|
125
142
|
export interface SessionRef {
|
|
126
143
|
id: string;
|
|
@@ -143,6 +160,38 @@ export interface ArchiveSessionsResponse {
|
|
|
143
160
|
archivedCount?: number;
|
|
144
161
|
skippedAlreadyArchivedCount?: number;
|
|
145
162
|
}
|
|
163
|
+
export interface SessionCleanupRequest {
|
|
164
|
+
/** Archive non-archived sessions whose modified time is older than this many days. Omit/null to disable. */
|
|
165
|
+
archiveIdleDays?: number | null;
|
|
166
|
+
/** Permanently delete archived sessions whose archivedAt time is older than this many days. Omit/null to disable. */
|
|
167
|
+
deleteArchivedDays?: number | null;
|
|
168
|
+
/** Stored cwd paths selected from a preview. Omit/null to include all discovered project/workspace paths. */
|
|
169
|
+
projectCwds?: string[] | null;
|
|
170
|
+
}
|
|
171
|
+
export interface SessionCleanupThresholds {
|
|
172
|
+
archiveIdleDays?: number;
|
|
173
|
+
deleteArchivedDays?: number;
|
|
174
|
+
}
|
|
175
|
+
export interface SessionCleanupProjectSummary {
|
|
176
|
+
cwd: string;
|
|
177
|
+
archiveCount: number;
|
|
178
|
+
deleteCount: number;
|
|
179
|
+
}
|
|
180
|
+
export interface SessionCleanupTotals {
|
|
181
|
+
archiveCount: number;
|
|
182
|
+
deleteCount: number;
|
|
183
|
+
}
|
|
184
|
+
export interface SessionCleanupPreviewResponse {
|
|
185
|
+
generatedAt: string;
|
|
186
|
+
thresholds: SessionCleanupThresholds;
|
|
187
|
+
projects: SessionCleanupProjectSummary[];
|
|
188
|
+
totals: SessionCleanupTotals;
|
|
189
|
+
skippedBusySessionIds?: string[];
|
|
190
|
+
}
|
|
191
|
+
export interface SessionCleanupExecuteResponse extends SessionCleanupPreviewResponse {
|
|
192
|
+
archivedSessionIds: string[];
|
|
193
|
+
deletedSessionIds: string[];
|
|
194
|
+
}
|
|
146
195
|
export interface SessionActivity {
|
|
147
196
|
sessionId: string;
|
|
148
197
|
phase: "active" | "idle" | "error";
|
|
@@ -165,20 +214,30 @@ export interface PromptInput {
|
|
|
165
214
|
images?: PromptImage[];
|
|
166
215
|
}
|
|
167
216
|
/**
|
|
168
|
-
* A
|
|
169
|
-
* `ImageContent` shape (`{ type: "image", data, mimeType }`) so
|
|
170
|
-
*
|
|
217
|
+
* A pi-native image attachment carried with a prompt. The wire format mirrors
|
|
218
|
+
* pi's own `ImageContent` shape (`{ type: "image", data, mimeType }`) so these
|
|
219
|
+
* attachments are compatible with native multimodal delivery after validation.
|
|
171
220
|
*/
|
|
172
|
-
export interface
|
|
173
|
-
/** Kind of attachment. Only images are supported by pi today. */
|
|
221
|
+
export interface PromptImageAttachment {
|
|
174
222
|
kind: "image";
|
|
175
|
-
/**
|
|
223
|
+
/** Supported image MIME type (image/png, image/jpeg, image/gif, or image/webp). */
|
|
176
224
|
mimeType: string;
|
|
177
225
|
/** Base64-encoded binary payload (no data: URL prefix). */
|
|
178
226
|
data: string;
|
|
179
227
|
/** Optional original filename, used for previews and folder-mode filenames. */
|
|
180
228
|
name?: string;
|
|
181
229
|
}
|
|
230
|
+
/** A general file attachment that must be saved into the workspace before use. */
|
|
231
|
+
export interface PromptFileAttachment {
|
|
232
|
+
kind: "file";
|
|
233
|
+
/** Non-empty IANA MIME type (for example "application/pdf"). */
|
|
234
|
+
mimeType: string;
|
|
235
|
+
/** Base64-encoded binary payload (no data: URL prefix). Empty for zero-byte files. */
|
|
236
|
+
data: string;
|
|
237
|
+
/** Optional original filename, used for previews and folder-mode filenames. */
|
|
238
|
+
name?: string;
|
|
239
|
+
}
|
|
240
|
+
export type PromptAttachment = PromptImageAttachment | PromptFileAttachment;
|
|
182
241
|
/**
|
|
183
242
|
* How prompt attachments should be delivered to the session.
|
|
184
243
|
* - "inline": send the binary to pi as native image content (multimodal input).
|
|
@@ -328,6 +387,30 @@ export interface WorkspaceDeleteResponse {
|
|
|
328
387
|
deleted: true;
|
|
329
388
|
path: string;
|
|
330
389
|
}
|
|
390
|
+
export interface WriteWorkspaceFileOptions {
|
|
391
|
+
createDirs?: boolean;
|
|
392
|
+
overwrite?: boolean;
|
|
393
|
+
}
|
|
394
|
+
export interface WriteWorkspaceFileResponse {
|
|
395
|
+
path: string;
|
|
396
|
+
size: number;
|
|
397
|
+
modifiedAt: string;
|
|
398
|
+
created: boolean;
|
|
399
|
+
}
|
|
400
|
+
export interface DeleteWorkspaceFileResponse {
|
|
401
|
+
path: string;
|
|
402
|
+
existed: boolean;
|
|
403
|
+
}
|
|
404
|
+
export interface MoveWorkspaceFileOptions {
|
|
405
|
+
createDirs?: boolean;
|
|
406
|
+
overwrite?: boolean;
|
|
407
|
+
}
|
|
408
|
+
export interface MoveWorkspaceFileResponse {
|
|
409
|
+
fromPath: string;
|
|
410
|
+
toPath: string;
|
|
411
|
+
size: number;
|
|
412
|
+
modifiedAt: string;
|
|
413
|
+
}
|
|
331
414
|
export type GitFileState = "unmodified" | "modified" | "added" | "deleted" | "renamed" | "copied" | "untracked" | "ignored" | "conflicted";
|
|
332
415
|
export interface GitStatusFile {
|
|
333
416
|
path: string;
|
package/dist/shared/apiTypes.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export const PI_WEB_CAPABILITIES = {
|
|
2
2
|
sessionsDeleteArchived: "sessions.deleteArchived",
|
|
3
|
+
sessionsCleanup: "sessions.cleanup",
|
|
3
4
|
sessionsReload: "sessions.reload",
|
|
4
5
|
promptAttachments: "prompt.attachments",
|
|
6
|
+
workspaceFileSuggestions: "workspace.fileSuggestions",
|
|
5
7
|
};
|
|
6
8
|
//# sourceMappingURL=apiTypes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apiTypes.js","sourceRoot":"","sources":["../../src/shared/apiTypes.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,sBAAsB,EAAE,yBAAyB;IACjD,cAAc,EAAE,iBAAiB;IACjC,iBAAiB,EAAE,oBAAoB;
|
|
1
|
+
{"version":3,"file":"apiTypes.js","sourceRoot":"","sources":["../../src/shared/apiTypes.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,sBAAsB,EAAE,yBAAyB;IACjD,eAAe,EAAE,kBAAkB;IACnC,cAAc,EAAE,iBAAiB;IACjC,iBAAiB,EAAE,oBAAoB;IACvC,wBAAwB,EAAE,2BAA2B;CAC7C,CAAC"}
|
|
@@ -2,12 +2,14 @@ import { PI_WEB_CAPABILITIES } from "./apiTypes.js";
|
|
|
2
2
|
export { PI_WEB_CAPABILITIES };
|
|
3
3
|
export const KNOWN_PI_WEB_CAPABILITIES = Object.values(PI_WEB_CAPABILITIES);
|
|
4
4
|
const knownPiWebCapabilities = new Set(KNOWN_PI_WEB_CAPABILITIES);
|
|
5
|
-
export const WEB_RUNTIME_CAPABILITIES = [PI_WEB_CAPABILITIES.sessionsDeleteArchived, PI_WEB_CAPABILITIES.sessionsReload, PI_WEB_CAPABILITIES.promptAttachments];
|
|
6
|
-
export const SESSIOND_RUNTIME_CAPABILITIES = [PI_WEB_CAPABILITIES.sessionsDeleteArchived, PI_WEB_CAPABILITIES.sessionsReload, PI_WEB_CAPABILITIES.promptAttachments];
|
|
5
|
+
export const WEB_RUNTIME_CAPABILITIES = [PI_WEB_CAPABILITIES.sessionsDeleteArchived, PI_WEB_CAPABILITIES.sessionsCleanup, PI_WEB_CAPABILITIES.sessionsReload, PI_WEB_CAPABILITIES.promptAttachments, PI_WEB_CAPABILITIES.workspaceFileSuggestions];
|
|
6
|
+
export const SESSIOND_RUNTIME_CAPABILITIES = [PI_WEB_CAPABILITIES.sessionsDeleteArchived, PI_WEB_CAPABILITIES.sessionsCleanup, PI_WEB_CAPABILITIES.sessionsReload, PI_WEB_CAPABILITIES.promptAttachments];
|
|
7
7
|
const EFFECTIVE_CAPABILITY_REQUIREMENTS = {
|
|
8
8
|
[PI_WEB_CAPABILITIES.sessionsDeleteArchived]: ["web", "sessiond"],
|
|
9
|
+
[PI_WEB_CAPABILITIES.sessionsCleanup]: ["web", "sessiond"],
|
|
9
10
|
[PI_WEB_CAPABILITIES.sessionsReload]: ["web", "sessiond"],
|
|
10
11
|
[PI_WEB_CAPABILITIES.promptAttachments]: ["web", "sessiond"],
|
|
12
|
+
[PI_WEB_CAPABILITIES.workspaceFileSuggestions]: ["web"],
|
|
11
13
|
};
|
|
12
14
|
export function isPiWebCapability(value) {
|
|
13
15
|
return typeof value === "string" && knownPiWebCapabilities.has(value);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/shared/capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAgF,MAAM,eAAe,CAAC;AAElI,OAAO,EAAE,mBAAmB,EAAE,CAAC;AAG/B,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;AAC5E,MAAM,sBAAsB,GAAwB,IAAI,GAAG,CAAC,yBAAyB,CAAC,CAAC;AAEvF,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,mBAAmB,CAAC,sBAAsB,EAAE,mBAAmB,CAAC,cAAc,EAAE,mBAAmB,CAAC,iBAAiB,CAA+C,CAAC;
|
|
1
|
+
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/shared/capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAgF,MAAM,eAAe,CAAC;AAElI,OAAO,EAAE,mBAAmB,EAAE,CAAC;AAG/B,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;AAC5E,MAAM,sBAAsB,GAAwB,IAAI,GAAG,CAAC,yBAAyB,CAAC,CAAC;AAEvF,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,mBAAmB,CAAC,sBAAsB,EAAE,mBAAmB,CAAC,eAAe,EAAE,mBAAmB,CAAC,cAAc,EAAE,mBAAmB,CAAC,iBAAiB,EAAE,mBAAmB,CAAC,wBAAwB,CAA+C,CAAC;AACjS,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,mBAAmB,CAAC,sBAAsB,EAAE,mBAAmB,CAAC,eAAe,EAAE,mBAAmB,CAAC,cAAc,EAAE,mBAAmB,CAAC,iBAAiB,CAA+C,CAAC;AAExP,MAAM,iCAAiC,GAAG;IACxC,CAAC,mBAAmB,CAAC,sBAAsB,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC;IACjE,CAAC,mBAAmB,CAAC,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC;IAC1D,CAAC,mBAAmB,CAAC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC;IACzD,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC;IAC5D,CAAC,mBAAmB,CAAC,wBAAwB,CAAC,EAAE,CAAC,KAAK,CAAC;CACqB,CAAC;AAE/E,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,sBAAsB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,MAAiE,EAAE,UAA2B;IACpI,OAAO,MAAM,EAAE,YAAY,EAAE,QAAQ,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,UAA6G;IACtJ,OAAO,yBAAyB,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE;QACrD,MAAM,kBAAkB,GAAG,iCAAiC,CAAC,UAAU,CAAC,CAAC;QACzE,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC,SAAS,EAAE,EAAE;YAC5C,MAAM,OAAO,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;YACtC,OAAO,OAAO,EAAE,SAAS,KAAK,IAAI,IAAI,uBAAuB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QACrF,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -9,10 +9,12 @@ export const FEDERATED_HTTP_ROUTES = [
|
|
|
9
9
|
{ method: "GET", path: "/projects/:projectId/workspaces/:workspaceId/tree" },
|
|
10
10
|
{ method: "GET", path: "/projects/:projectId/workspaces/:workspaceId/file" },
|
|
11
11
|
{ method: "POST", path: "/projects/:projectId/workspaces/:workspaceId/file" },
|
|
12
|
-
{ method: "
|
|
12
|
+
{ method: "PUT", path: "/projects/:projectId/workspaces/:workspaceId/file" },
|
|
13
13
|
{ method: "DELETE", path: "/projects/:projectId/workspaces/:workspaceId/file" },
|
|
14
|
+
{ method: "POST", path: "/projects/:projectId/workspaces/:workspaceId/file/move" },
|
|
14
15
|
{ method: "GET", path: "/projects/:projectId/workspaces/:workspaceId/file/download" },
|
|
15
16
|
{ method: "GET", path: "/projects/:projectId/workspaces/:workspaceId/file/preview" },
|
|
17
|
+
{ method: "GET", path: "/projects/:projectId/workspaces/:workspaceId/files" },
|
|
16
18
|
{ method: "POST", path: "/projects/:projectId/workspaces/:workspaceId/directory" },
|
|
17
19
|
{ method: "PATCH", path: "/projects/:projectId/workspaces/:workspaceId/directory" },
|
|
18
20
|
{ method: "DELETE", path: "/projects/:projectId/workspaces/:workspaceId/directory" },
|
|
@@ -31,6 +33,8 @@ export const FEDERATED_HTTP_ROUTES = [
|
|
|
31
33
|
{ method: "GET", path: "/activity" },
|
|
32
34
|
{ method: "GET", path: "/sessions" },
|
|
33
35
|
{ method: "POST", path: "/sessions" },
|
|
36
|
+
{ method: "POST", path: "/sessions/cleanup/preview" },
|
|
37
|
+
{ method: "POST", path: "/sessions/cleanup" },
|
|
34
38
|
{ method: "GET", path: "/sessions/:sessionId/messages" },
|
|
35
39
|
{ method: "GET", path: "/sessions/:sessionId/status" },
|
|
36
40
|
{ method: "GET", path: "/sessions/:sessionId/models" },
|
|
@@ -51,6 +55,7 @@ export const FEDERATED_HTTP_ROUTES = [
|
|
|
51
55
|
{ method: "POST", path: "/sessions/:sessionId/archive-tree" },
|
|
52
56
|
{ method: "POST", path: "/sessions/:sessionId/restore" },
|
|
53
57
|
{ method: "DELETE", path: "/sessions/:sessionId" },
|
|
58
|
+
{ method: "POST", path: "/sessions/:sessionId/reload" },
|
|
54
59
|
{ method: "POST", path: "/sessions/:sessionId/detach-parent" },
|
|
55
60
|
{ method: "GET", path: "/auth/providers" },
|
|
56
61
|
{ method: "POST", path: "/auth/api-key" },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"federatedRoutes.js","sourceRoot":"","sources":["../../src/shared/federatedRoutes.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE;IACzC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE;IACpC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE;IACrC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,sBAAsB,EAAE;IAClD,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,sBAAsB,EAAE;IAC/C,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,iCAAiC,EAAE;IAC1D,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,8CAA8C,EAAE;IAC1E,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,mDAAmD,EAAE;IAC5E,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,mDAAmD,EAAE;IAC5E,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,mDAAmD,EAAE;IAC7E,EAAE,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"federatedRoutes.js","sourceRoot":"","sources":["../../src/shared/federatedRoutes.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,18 +7,20 @@ export function piWebConfigRecord(config) {
|
|
|
7
7
|
...(config.shortcuts !== undefined ? { shortcuts: config.shortcuts } : {}),
|
|
8
8
|
...(config.plugins !== undefined ? { plugins: config.plugins } : {}),
|
|
9
9
|
...(config.managementEmbed !== undefined ? { managementEmbed: config.managementEmbed } : {}),
|
|
10
|
+
...(config.pathAccess !== undefined ? { pathAccess: config.pathAccess } : {}),
|
|
11
|
+
...(config.uploads !== undefined ? { uploads: config.uploads } : {}),
|
|
10
12
|
...(config.maxUploadBytes !== undefined ? { maxUploadBytes: config.maxUploadBytes } : {}),
|
|
11
13
|
...(config.spawnSessions !== undefined ? { spawnSessions: config.spawnSessions } : {}),
|
|
12
14
|
...(config.subsessions !== undefined ? { subsessions: config.subsessions } : {}),
|
|
13
15
|
};
|
|
14
16
|
}
|
|
15
17
|
export function parsePiWebConfig(value, path) {
|
|
16
|
-
return parsePiWebConfigFields(value, { format: "file",
|
|
18
|
+
return parsePiWebConfigFields(value, { format: "file", path });
|
|
17
19
|
}
|
|
18
20
|
export function parsePiWebConfigRequest(value) {
|
|
19
21
|
if (!isRecord(value))
|
|
20
22
|
throw new Error("PI WEB config update must include a config object");
|
|
21
|
-
return parsePiWebConfigFields(value, { format: "request"
|
|
23
|
+
return parsePiWebConfigFields(value, { format: "request" });
|
|
22
24
|
}
|
|
23
25
|
export function parsePort(value, key, path = "environment") {
|
|
24
26
|
const port = typeof value === "number" ? value : typeof value === "string" && value !== "" ? Number(value) : NaN;
|
|
@@ -48,7 +50,9 @@ function parsePiWebConfigFields(value, context) {
|
|
|
48
50
|
...(value["shortcuts"] !== undefined ? { shortcuts: parseShortcuts(value["shortcuts"], context) } : {}),
|
|
49
51
|
...(value["plugins"] !== undefined ? { plugins: parsePlugins(value["plugins"], context) } : {}),
|
|
50
52
|
...(value["managementEmbed"] !== undefined ? { managementEmbed: parseManagementEmbed(value["managementEmbed"], context) } : {}),
|
|
51
|
-
...(
|
|
53
|
+
...(value["pathAccess"] !== undefined ? { pathAccess: parsePathAccessConfig(value["pathAccess"], context.format === "file" ? context.path : "request") } : {}),
|
|
54
|
+
...(value["uploads"] !== undefined ? { uploads: parseUploadsConfig(value["uploads"], context.format === "file" ? context.path : "request") } : {}),
|
|
55
|
+
...(value["maxUploadBytes"] !== undefined ? { maxUploadBytes: parseMaxUploadBytes(value["maxUploadBytes"], "maxUploadBytes", context.format === "file" ? context.path : "request") } : {}),
|
|
52
56
|
...(value["spawnSessions"] !== undefined ? { spawnSessions: parseBoolean(value["spawnSessions"], "spawnSessions", context) } : {}),
|
|
53
57
|
...(value["subsessions"] !== undefined ? { subsessions: parseBoolean(value["subsessions"], "subsessions", context) } : {}),
|
|
54
58
|
};
|
|
@@ -186,6 +190,43 @@ function parseStringArray(value, key, context) {
|
|
|
186
190
|
throw new Error(error(context, `${key} must be an array of non-empty strings`));
|
|
187
191
|
return value;
|
|
188
192
|
}
|
|
193
|
+
export function parsePathAccessConfig(value, path) {
|
|
194
|
+
if (!isRecord(value))
|
|
195
|
+
throw new Error(`PI WEB config pathAccess must be an object: ${path}`);
|
|
196
|
+
const allowedPaths = value["allowedPaths"];
|
|
197
|
+
return {
|
|
198
|
+
...(allowedPaths !== undefined ? { allowedPaths: parseAllowedPaths(allowedPaths, path) } : {}),
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function parseAllowedPaths(value, path) {
|
|
202
|
+
if (!isNonEmptyStringArray(value))
|
|
203
|
+
throw new Error(`PI WEB config pathAccess.allowedPaths must be an array of non-empty strings: ${path}`);
|
|
204
|
+
return value;
|
|
205
|
+
}
|
|
206
|
+
export function parseUploadsConfig(value, path) {
|
|
207
|
+
if (!isRecord(value))
|
|
208
|
+
throw new Error(`PI WEB config uploads must be an object: ${path}`);
|
|
209
|
+
const defaultFolder = value["defaultFolder"];
|
|
210
|
+
return {
|
|
211
|
+
...(defaultFolder !== undefined ? { defaultFolder: parseWorkspaceRelativeFolder(defaultFolder, "uploads.defaultFolder", path) } : {}),
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
function parseWorkspaceRelativeFolder(value, key, path) {
|
|
215
|
+
if (typeof value !== "string" || value.trim() === "")
|
|
216
|
+
throw new Error(`PI WEB config ${key} must be a non-empty workspace-relative path: ${path}`);
|
|
217
|
+
if (isAbsoluteLike(value))
|
|
218
|
+
throw new Error(`PI WEB config ${key} must be workspace-relative: ${path}`);
|
|
219
|
+
const parts = value.split(/[\\/]+/).filter((part) => part !== "" && part !== ".");
|
|
220
|
+
if (parts.length === 0)
|
|
221
|
+
throw new Error(`PI WEB config ${key} must be a non-empty workspace-relative path: ${path}`);
|
|
222
|
+
if (parts.some((part) => part === ".."))
|
|
223
|
+
throw new Error(`PI WEB config ${key} must not contain path traversal: ${path}`);
|
|
224
|
+
return parts.join("/");
|
|
225
|
+
}
|
|
226
|
+
function isAbsoluteLike(value) {
|
|
227
|
+
const withForwardSlashes = value.replace(/\\/g, "/");
|
|
228
|
+
return withForwardSlashes.startsWith("/") || /^[A-Za-z]:\//.test(withForwardSlashes);
|
|
229
|
+
}
|
|
189
230
|
function error(context, message) {
|
|
190
231
|
return context.format === "request" ? `PI WEB config ${message}` : `PI WEB config ${message}: ${context.path}`;
|
|
191
232
|
}
|