@openclaw/acpx 2026.10.10 → 2026.11.5-beta.1
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/.setup/{config-CE-ej7LM.mjs → config-Cplh34lQ.mjs} +15 -23
- package/dist/.setup/{harness-attempt-Bgcm-zBR.mjs → harness-attempt-Co9oLpPg.mjs} +5 -4
- package/dist/.setup/{pi-session-catalog-runtime-Cdf46b05.mjs → pi-session-catalog-runtime-DgzkbadO.mjs} +35 -57
- package/dist/.setup/{pi-session-paths-Co5515li.mjs → pi-session-paths-pUr6hnVA.mjs} +2 -2
- package/dist/.setup/{service-Dr8U5n0S.mjs → service-DmgP1gPb.mjs} +135 -373
- package/dist/.setup/{session-owner-migration-WmiXoSmh.mjs → session-owner-migration-CQA7L68K.mjs} +13 -10
- package/dist/.setup/{session-resource-Cv-RAA6y.mjs → session-resource-D_tXKvcv.mjs} +2 -2
- package/dist/.source-module-urls/9369b1b274d2ba70ea21d859abb3415ad8d63d0a1022a301763b953a5798469e.json +1 -0
- package/dist/doctor-contract-api.js +17 -11
- package/dist/index.js +206 -21
- package/openclaw.plugin.json +28 -1
- package/package.json +9 -9
- package/dist/.setup/register.runtime-CSJY10FS.mjs +0 -195
- package/dist/.source-module-urls/78a9d561eb54d4bf1ca0db6e6d12bb5688647241f2c0b289c611a0effb44d715.json +0 -1
- package/dist/register.runtime.js +0 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { createRequire } from "node:module";
|
|
2
1
|
import { z } from "zod";
|
|
3
2
|
import fs from "node:fs";
|
|
4
3
|
import path from "node:path";
|
|
5
4
|
import { fileURLToPath } from "node:url";
|
|
6
5
|
import { formatPluginConfigIssue } from "openclaw/plugin-sdk/extension-shared";
|
|
6
|
+
import { resolvePackageRuntimeProcessEntrypointUrl, resolveRuntimeWorkerArgv } from "openclaw/plugin-sdk/process-runtime";
|
|
7
7
|
import { resolveStateDir } from "openclaw/plugin-sdk/state-paths";
|
|
8
8
|
import { isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
9
9
|
// extensions/acpx/src/config-schema.ts
|
|
@@ -32,6 +32,11 @@ const ACPX_PERMISSION_MODES = [
|
|
|
32
32
|
];
|
|
33
33
|
const ACPX_NON_INTERACTIVE_POLICIES = ["deny", "fail"];
|
|
34
34
|
const nonEmptyTrimmedString = (message) => z.string({ error: message }).trim().min(1, { error: message });
|
|
35
|
+
const envNameListSchema = (option) => {
|
|
36
|
+
const message = `${option} must be an array of environment variable names`;
|
|
37
|
+
const name = z.string({ error: message }).regex(/^[^=\s]+$/, { error: message }).refine((value) => !value.includes("\0"), { error: message });
|
|
38
|
+
return z.array(name, { error: message }).optional();
|
|
39
|
+
};
|
|
35
40
|
const McpServerConfigSchema = z.object({
|
|
36
41
|
command: nonEmptyTrimmedString("command must be a non-empty string").describe("Command to run the MCP server"),
|
|
37
42
|
args: z.array(z.string({ error: "args must be an array of strings" }), { error: "args must be an array of strings" }).optional().describe("Arguments to pass to the command"),
|
|
@@ -48,6 +53,8 @@ const AcpxPluginConfigSchema = z.strictObject({
|
|
|
48
53
|
pluginToolsMcpBridge: z.boolean({ error: "pluginToolsMcpBridge must be a boolean" }).optional(),
|
|
49
54
|
openClawToolsMcpBridge: z.boolean({ error: "openClawToolsMcpBridge must be a boolean" }).optional(),
|
|
50
55
|
timeoutSeconds: z.number({ error: "timeoutSeconds must be a number >= 0.001" }).min(.001, { error: "timeoutSeconds must be a number >= 0.001" }).default(120),
|
|
56
|
+
agentProcessEnvAllow: envNameListSchema("agentProcessEnvAllow"),
|
|
57
|
+
agentProcessEnvBlock: envNameListSchema("agentProcessEnvBlock"),
|
|
51
58
|
piSessionCatalog: z.strictObject({ enabled: z.boolean({ error: "piSessionCatalog.enabled must be a boolean" }).default(true) }).optional(),
|
|
52
59
|
mcpServers: z.record(z.string(), McpServerConfigSchema).optional(),
|
|
53
60
|
agents: z.record(z.string(), z.strictObject({
|
|
@@ -186,13 +193,12 @@ function resolveAgentCommand(params) {
|
|
|
186
193
|
const MANAGED_MCP_BRIDGES = [[
|
|
187
194
|
"pluginToolsMcpBridge",
|
|
188
195
|
"openclaw-plugin-tools",
|
|
189
|
-
"
|
|
196
|
+
"pluginToolsServe"
|
|
190
197
|
], [
|
|
191
198
|
"openClawToolsMcpBridge",
|
|
192
199
|
"openclaw-tools",
|
|
193
|
-
"
|
|
200
|
+
"openclawToolsServe"
|
|
194
201
|
]];
|
|
195
|
-
const requireFromHere = createRequire(import.meta.url);
|
|
196
202
|
function isAcpxPluginRoot(dir) {
|
|
197
203
|
return fs.existsSync(path.join(dir, "openclaw.plugin.json")) && fs.existsSync(path.join(dir, "package.json"));
|
|
198
204
|
}
|
|
@@ -263,28 +269,12 @@ function resolveHostPackageRoot(argv1) {
|
|
|
263
269
|
cursor = parent;
|
|
264
270
|
}
|
|
265
271
|
}
|
|
266
|
-
function resolveTsxImportSpecifier() {
|
|
267
|
-
try {
|
|
268
|
-
return requireFromHere.resolve("tsx");
|
|
269
|
-
} catch {
|
|
270
|
-
return "tsx";
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
272
|
function resolveManagedToolsMcpServerConfig(entryPoint, moduleUrl = import.meta.url) {
|
|
274
273
|
const openClawRoot = resolveOpenClawRoot(resolveAcpxPluginRoot(moduleUrl));
|
|
275
|
-
const
|
|
276
|
-
if (fs.existsSync(distEntry)) return {
|
|
277
|
-
command: process.execPath,
|
|
278
|
-
args: [distEntry]
|
|
279
|
-
};
|
|
280
|
-
const sourceEntry = path.join(openClawRoot, "src", "mcp", `${entryPoint}.ts`);
|
|
274
|
+
const entry = resolvePackageRuntimeProcessEntrypointUrl(entryPoint, openClawRoot);
|
|
281
275
|
return {
|
|
282
276
|
command: process.execPath,
|
|
283
|
-
args:
|
|
284
|
-
"--import",
|
|
285
|
-
resolveTsxImportSpecifier(),
|
|
286
|
-
sourceEntry
|
|
287
|
-
]
|
|
277
|
+
args: resolveRuntimeWorkerArgv(entry)
|
|
288
278
|
};
|
|
289
279
|
}
|
|
290
280
|
function resolveConfiguredMcpServers(params) {
|
|
@@ -321,7 +311,7 @@ function resolveAcpxPluginConfig(params) {
|
|
|
321
311
|
moduleUrl: params.moduleUrl
|
|
322
312
|
});
|
|
323
313
|
const agents = Object.fromEntries(Object.entries(normalized.agents ?? {}).map(([name, entry]) => {
|
|
324
|
-
const cmd = entry.command
|
|
314
|
+
const cmd = entry.command;
|
|
325
315
|
const command = path.isAbsolute(cmd) && fs.existsSync(cmd) ? [cmd] : splitCommandParts(cmd);
|
|
326
316
|
return [normalizeLowercaseStringOrEmpty(name), [...command, ...entry.args ?? []]];
|
|
327
317
|
}));
|
|
@@ -334,6 +324,8 @@ function resolveAcpxPluginConfig(params) {
|
|
|
334
324
|
pluginToolsMcpBridge,
|
|
335
325
|
openClawToolsMcpBridge,
|
|
336
326
|
timeoutSeconds: normalized.timeoutSeconds,
|
|
327
|
+
agentProcessEnvAllow: normalized.agentProcessEnvAllow,
|
|
328
|
+
agentProcessEnvBlock: normalized.agentProcessEnvBlock,
|
|
337
329
|
mcpServers,
|
|
338
330
|
agents
|
|
339
331
|
};
|
|
@@ -65,12 +65,12 @@ async function runAcpHarnessAttempt(params) {
|
|
|
65
65
|
sourceReplyDeliveryMode: input.sourceReplyDeliveryMode
|
|
66
66
|
};
|
|
67
67
|
let activeRegistered = false;
|
|
68
|
+
let activeAttachment;
|
|
68
69
|
let timer;
|
|
69
70
|
assertActive();
|
|
70
71
|
try {
|
|
71
|
-
setActiveEmbeddedRun(input.sessionId, activeRun, sessionKey, input.sessionFile, agentId);
|
|
72
|
+
activeAttachment = setActiveEmbeddedRun(input.sessionId, activeRun, sessionKey, input.sessionFile, agentId);
|
|
72
73
|
activeRegistered = true;
|
|
73
|
-
input.replyOperation?.attachBackend(activeRun);
|
|
74
74
|
signal.addEventListener("abort", stopDelivery, { once: true });
|
|
75
75
|
timer = setTimeout(() => {
|
|
76
76
|
timedOut = true;
|
|
@@ -143,7 +143,8 @@ async function runAcpHarnessAttempt(params) {
|
|
|
143
143
|
config: input.config,
|
|
144
144
|
trigger: input.trigger,
|
|
145
145
|
modelProviderId: input.provider,
|
|
146
|
-
modelId: input.modelId
|
|
146
|
+
modelId: input.modelId,
|
|
147
|
+
contextTokenBudget: input.contextTokenBudget ?? input.model.contextWindow
|
|
147
148
|
},
|
|
148
149
|
bootstrapContextRunKind: input.bootstrapContextRunKind
|
|
149
150
|
});
|
|
@@ -315,7 +316,7 @@ async function runAcpHarnessAttempt(params) {
|
|
|
315
316
|
settled = true;
|
|
316
317
|
clearTimeout(timer);
|
|
317
318
|
signal.removeEventListener("abort", stopDelivery);
|
|
318
|
-
if (activeRegistered) clearActiveEmbeddedRun(input.sessionId, activeRun, sessionKey, input.sessionFile);
|
|
319
|
+
if (activeRegistered) clearActiveEmbeddedRun(input.sessionId, activeRun, sessionKey, input.sessionFile, void 0, activeAttachment);
|
|
319
320
|
}
|
|
320
321
|
return {
|
|
321
322
|
terminal: timedOut ? {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as PI_SESSION_READ_COMMAND, i as PI_LOCAL_SESSION_HOST_ID, l as PI_TERMINAL_RESUME_COMMAND, n as piSessionStore, o as PI_SESSIONS_LIST_COMMAND, r as piSessionStoreAvailable, s as PI_SESSION_ID_PATTERN, t as piAcpSessionStoreRoot } from "./pi-session-paths-
|
|
1
|
+
import { c as PI_SESSION_READ_COMMAND, i as PI_LOCAL_SESSION_HOST_ID, l as PI_TERMINAL_RESUME_COMMAND, n as piSessionStore, o as PI_SESSIONS_LIST_COMMAND, r as piSessionStoreAvailable, s as PI_SESSION_ID_PATTERN, t as piAcpSessionStoreRoot } from "./pi-session-paths-pUr6hnVA.mjs";
|
|
2
2
|
import { parseDateFirstTimestampMs, timestampMsToIsoString } from "openclaw/plugin-sdk/number-runtime";
|
|
3
3
|
import { createReadStream } from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
@@ -12,6 +12,7 @@ import { createAcpSessionCatalogAdoption, readSessionCatalogJsonlActivity } from
|
|
|
12
12
|
import { sessionCatalogPaging } from "openclaw/plugin-sdk/session-catalog-paging";
|
|
13
13
|
import { safeParseJson, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
14
14
|
import fs$1 from "node:fs/promises";
|
|
15
|
+
import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
|
|
15
16
|
import { runTasksWithConcurrency } from "openclaw/plugin-sdk/concurrency-runtime";
|
|
16
17
|
import { isPathStrictlyInside } from "openclaw/plugin-sdk/file-access-runtime";
|
|
17
18
|
// extensions/acpx/src/pi-session-store.ts
|
|
@@ -131,11 +132,7 @@ async function piFileCandidates(env) {
|
|
|
131
132
|
candidates
|
|
132
133
|
};
|
|
133
134
|
piFileCandidateCache.set(key, entry);
|
|
134
|
-
|
|
135
|
-
const oldest = piFileCandidateCache.keys().next();
|
|
136
|
-
if (oldest.done) break;
|
|
137
|
-
piFileCandidateCache.delete(oldest.value);
|
|
138
|
-
}
|
|
135
|
+
pruneMapToMaxSize(piFileCandidateCache, PI_FILE_CANDIDATE_CACHE_MAX_ENTRIES);
|
|
139
136
|
try {
|
|
140
137
|
return await candidates;
|
|
141
138
|
} catch (error) {
|
|
@@ -150,10 +147,18 @@ function parsePiJsonLines(content) {
|
|
|
150
147
|
return isRecord(value) ? [value] : [];
|
|
151
148
|
});
|
|
152
149
|
}
|
|
153
|
-
function piMessageText(content) {
|
|
150
|
+
function piMessageText(content, includeImages = false) {
|
|
154
151
|
if (typeof content === "string") return content;
|
|
155
152
|
if (!Array.isArray(content)) return "";
|
|
156
|
-
return content.flatMap((part) =>
|
|
153
|
+
return content.flatMap((part) => {
|
|
154
|
+
if (!isRecord(part)) return [];
|
|
155
|
+
if (part.type === "text" && typeof part.text === "string") return [part.text];
|
|
156
|
+
if (includeImages && part.type === "image") {
|
|
157
|
+
const mimeType = normalizeBoundedOptionalString(part.mimeType, 128);
|
|
158
|
+
return [mimeType ? `[image: ${mimeType}]` : "[image]"];
|
|
159
|
+
}
|
|
160
|
+
return [];
|
|
161
|
+
}).join("\n");
|
|
157
162
|
}
|
|
158
163
|
function processSummaryLine(state, line) {
|
|
159
164
|
const entry = parsePiJsonLines((line.at(-1) === 13 ? line.subarray(0, -1) : line).toString("utf8"))[0];
|
|
@@ -214,19 +219,13 @@ async function readPiSessionSummary(candidate) {
|
|
|
214
219
|
let scanState;
|
|
215
220
|
try {
|
|
216
221
|
const resumable = cached?.identity === candidate.identity && cached.size < candidate.size ? cached : void 0;
|
|
217
|
-
scanState = resumable ? {
|
|
218
|
-
...resumable.scanState,
|
|
219
|
-
pending: Buffer.from(resumable.scanState.pending)
|
|
220
|
-
} : {
|
|
222
|
+
scanState = resumable ? { ...resumable.scanState } : {
|
|
221
223
|
pending: Buffer.alloc(0),
|
|
222
224
|
discarding: false,
|
|
223
225
|
invalid: false
|
|
224
226
|
};
|
|
225
227
|
await scanSummaryAppend(candidate, resumable?.size ?? 0, scanState);
|
|
226
|
-
const projectedState = {
|
|
227
|
-
...scanState,
|
|
228
|
-
pending: Buffer.from(scanState.pending)
|
|
229
|
-
};
|
|
228
|
+
const projectedState = { ...scanState };
|
|
230
229
|
if (!projectedState.discarding && projectedState.pending.length > 0) processSummaryLine(projectedState, projectedState.pending);
|
|
231
230
|
const { header, name, firstMessage } = projectedState;
|
|
232
231
|
const version = header?.type === "session" && typeof header.version === "number" ? header.version : 1;
|
|
@@ -254,7 +253,6 @@ async function readPiSessionSummary(candidate) {
|
|
|
254
253
|
} catch {
|
|
255
254
|
return cached?.summary;
|
|
256
255
|
}
|
|
257
|
-
if (cached?.summary?.threadId && cached.summary.threadId !== summary?.threadId) threadFileCache.delete(threadCacheKey(cached.storeRoot, cached.summary.threadId));
|
|
258
256
|
cacheSummary(candidate.file, {
|
|
259
257
|
...candidate,
|
|
260
258
|
summary,
|
|
@@ -269,7 +267,17 @@ function summaryMatches(summary, needle) {
|
|
|
269
267
|
summary.threadId,
|
|
270
268
|
summary.name,
|
|
271
269
|
summary.cwd
|
|
272
|
-
].some((field) => field?.toLocaleLowerCase().includes(needle));
|
|
270
|
+
].some((field) => field?.toLocaleLowerCase().normalize("NFC").includes(needle));
|
|
271
|
+
}
|
|
272
|
+
async function* scanPiSummaries(candidates) {
|
|
273
|
+
for (let index = 0; index < candidates.length; index += SUMMARY_SCAN_BATCH_SIZE) {
|
|
274
|
+
const { results } = await runTasksWithConcurrency({
|
|
275
|
+
tasks: candidates.slice(index, index + SUMMARY_SCAN_BATCH_SIZE).map((candidate) => () => readPiSessionSummary(candidate)),
|
|
276
|
+
limit: IO_CONCURRENCY,
|
|
277
|
+
throwOnError: true
|
|
278
|
+
});
|
|
279
|
+
for (const summary of results) if (summary) yield summary;
|
|
280
|
+
}
|
|
273
281
|
}
|
|
274
282
|
async function listPiSummaryPage(env, params) {
|
|
275
283
|
const candidates = await piFileCandidates(env);
|
|
@@ -277,18 +285,10 @@ async function listPiSummaryPage(env, params) {
|
|
|
277
285
|
for (const file of summaryCache.keys()) if (!activeFiles.has(file)) forgetCachedSummary(file);
|
|
278
286
|
const target = params.offset + params.limit + 1;
|
|
279
287
|
const matches = [];
|
|
280
|
-
const needle = params.searchTerm?.toLocaleLowerCase();
|
|
281
|
-
for (
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
tasks: batch.map((candidate) => () => readPiSessionSummary(candidate)),
|
|
285
|
-
limit: IO_CONCURRENCY,
|
|
286
|
-
throwOnError: true
|
|
287
|
-
});
|
|
288
|
-
for (const summary of summaries) if (summary && summaryMatches(summary, needle)) {
|
|
289
|
-
matches.push(summary);
|
|
290
|
-
if (matches.length >= target) break;
|
|
291
|
-
}
|
|
288
|
+
const needle = params.searchTerm?.toLocaleLowerCase().normalize("NFC");
|
|
289
|
+
for await (const summary of scanPiSummaries(candidates)) if (summaryMatches(summary, needle)) {
|
|
290
|
+
matches.push(summary);
|
|
291
|
+
if (matches.length >= target) break;
|
|
292
292
|
}
|
|
293
293
|
return {
|
|
294
294
|
summaries: matches.slice(params.offset, params.offset + params.limit),
|
|
@@ -296,16 +296,7 @@ async function listPiSummaryPage(env, params) {
|
|
|
296
296
|
};
|
|
297
297
|
}
|
|
298
298
|
async function findPiSummary(threadId, env) {
|
|
299
|
-
const
|
|
300
|
-
for (let index = 0; index < candidates.length; index += SUMMARY_SCAN_BATCH_SIZE) {
|
|
301
|
-
const { results: summaries } = await runTasksWithConcurrency({
|
|
302
|
-
tasks: candidates.slice(index, index + SUMMARY_SCAN_BATCH_SIZE).map((candidate) => () => readPiSessionSummary(candidate)),
|
|
303
|
-
limit: IO_CONCURRENCY,
|
|
304
|
-
throwOnError: true
|
|
305
|
-
});
|
|
306
|
-
const match = summaries.find((summary) => summary?.threadId === threadId);
|
|
307
|
-
if (match) return match;
|
|
308
|
-
}
|
|
299
|
+
for await (const summary of scanPiSummaries(await piFileCandidates(env))) if (summary.threadId === threadId) return summary;
|
|
309
300
|
}
|
|
310
301
|
async function readPiSessionFileBaseline(threadId, env) {
|
|
311
302
|
const summary = await findPiSummary(threadId, env);
|
|
@@ -340,19 +331,6 @@ async function readPiSessionById(threadId, env) {
|
|
|
340
331
|
// extensions/acpx/src/pi-session-catalog.ts
|
|
341
332
|
const MAX_SEARCH_LENGTH = 500;
|
|
342
333
|
const isExactPiSessionCursor = sessionCatalogPaging.isExactCursor;
|
|
343
|
-
function textFromContent(content) {
|
|
344
|
-
if (typeof content === "string") return content;
|
|
345
|
-
if (!Array.isArray(content)) return "";
|
|
346
|
-
return content.flatMap((part) => {
|
|
347
|
-
if (!isRecord(part)) return [];
|
|
348
|
-
if (part.type === "text" && typeof part.text === "string") return [part.text];
|
|
349
|
-
if (part.type === "image") {
|
|
350
|
-
const mimeType = normalizeBoundedOptionalString(part.mimeType, 128);
|
|
351
|
-
return [mimeType ? `[image: ${mimeType}]` : "[image]"];
|
|
352
|
-
}
|
|
353
|
-
return [];
|
|
354
|
-
}).join("\n");
|
|
355
|
-
}
|
|
356
334
|
const PI_PARAMETER_MESSAGES = {
|
|
357
335
|
listNotObject: "Pi session list parameters must be an object",
|
|
358
336
|
unknownListParameter: (key) => `unknown Pi session list parameter: ${key}`,
|
|
@@ -419,7 +397,7 @@ function piMessageItems(entry) {
|
|
|
419
397
|
...modelRef ? { model: modelRef } : {}
|
|
420
398
|
};
|
|
421
399
|
if (role === "user") {
|
|
422
|
-
const text =
|
|
400
|
+
const text = piMessageText(message.content, true);
|
|
423
401
|
return text ? [{
|
|
424
402
|
...common,
|
|
425
403
|
type: "userMessage",
|
|
@@ -428,7 +406,7 @@ function piMessageItems(entry) {
|
|
|
428
406
|
}
|
|
429
407
|
if (role === "toolResult") {
|
|
430
408
|
const toolName = normalizeBoundedOptionalString(message.toolName, 256);
|
|
431
|
-
const text =
|
|
409
|
+
const text = piMessageText(message.content, true);
|
|
432
410
|
return [{
|
|
433
411
|
...common,
|
|
434
412
|
type: "toolResult",
|
|
@@ -453,7 +431,7 @@ function piMessageItems(entry) {
|
|
|
453
431
|
if (role === "custom" || role === "hookMessage") {
|
|
454
432
|
if (message.display !== true) return [];
|
|
455
433
|
const customType = normalizeBoundedOptionalString(message.customType, 256);
|
|
456
|
-
const text =
|
|
434
|
+
const text = piMessageText(message.content, true);
|
|
457
435
|
return text ? [{
|
|
458
436
|
...common,
|
|
459
437
|
type: "other",
|
|
@@ -504,7 +482,7 @@ function piTranscriptItems(entries) {
|
|
|
504
482
|
text: entry.summary
|
|
505
483
|
}];
|
|
506
484
|
if (entry.type === "custom_message" && entry.display === true) {
|
|
507
|
-
const text =
|
|
485
|
+
const text = piMessageText(entry.content, true);
|
|
508
486
|
return text ? [{
|
|
509
487
|
...common,
|
|
510
488
|
type: "other",
|
|
@@ -13,8 +13,8 @@ const PI_SESSION_ID_PATTERN = /^(?!-)[A-Za-z0-9._:-]{1,256}$/u;
|
|
|
13
13
|
function piHome(env) {
|
|
14
14
|
return (process.platform === "win32" ? env.USERPROFILE?.trim() : env.HOME?.trim()) || os.homedir();
|
|
15
15
|
}
|
|
16
|
-
function isPiSessionCatalogPathAbsolute(value
|
|
17
|
-
if (platform !== "win32") return path.posix.isAbsolute(value);
|
|
16
|
+
function isPiSessionCatalogPathAbsolute(value) {
|
|
17
|
+
if (process.platform !== "win32") return path.posix.isAbsolute(value);
|
|
18
18
|
const root = path.win32.parse(value).root;
|
|
19
19
|
return path.win32.isAbsolute(value) && root !== "\\" && root !== "/";
|
|
20
20
|
}
|