@openclaw/acpx 2026.11.3 → 2026.11.5-beta.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/dist/.setup/{config-D0ATuiVJ.mjs → config-DZaY96RI.mjs} +15 -23
- package/dist/.setup/{harness-attempt-lu4_bMfd.mjs → harness-attempt-CR7gvC_C.mjs} +5 -4
- package/dist/.setup/{pi-session-catalog-runtime-BAM1pEMw.mjs → pi-session-catalog-runtime-hFy095NF.mjs} +35 -57
- package/dist/.setup/{pi-session-paths-CIvyk6KB.mjs → pi-session-paths-Cn5bsvi0.mjs} +2 -2
- package/dist/.setup/{service-D_e2JAUG.mjs → service-By25n8eI.mjs} +135 -373
- package/dist/.setup/{session-owner-migration-BA3DJKb2.mjs → session-owner-migration-BmfOUj9h.mjs} +3 -3
- package/dist/.setup/{session-resource-DKJsUJPu.mjs → session-resource-BI93OF1C.mjs} +2 -2
- package/dist/.source-module-urls/9369b1b274d2ba70ea21d859abb3415ad8d63d0a1022a301763b953a5798469e.json +1 -0
- package/dist/doctor-contract-api.js +17 -11
- package/dist/index.js +207 -21
- package/openclaw.plugin.json +28 -1
- package/package.json +9 -9
- package/dist/.setup/register.runtime-D685iYx-.mjs +0 -197
- package/dist/register.runtime.js +0 -2
|
@@ -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
|
//#region 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({
|
|
@@ -189,13 +196,12 @@ function resolveAgentCommand(params) {
|
|
|
189
196
|
const MANAGED_MCP_BRIDGES = [[
|
|
190
197
|
"pluginToolsMcpBridge",
|
|
191
198
|
"openclaw-plugin-tools",
|
|
192
|
-
"
|
|
199
|
+
"pluginToolsServe"
|
|
193
200
|
], [
|
|
194
201
|
"openClawToolsMcpBridge",
|
|
195
202
|
"openclaw-tools",
|
|
196
|
-
"
|
|
203
|
+
"openclawToolsServe"
|
|
197
204
|
]];
|
|
198
|
-
const requireFromHere = createRequire(import.meta.url);
|
|
199
205
|
function isAcpxPluginRoot(dir) {
|
|
200
206
|
return fs.existsSync(path.join(dir, "openclaw.plugin.json")) && fs.existsSync(path.join(dir, "package.json"));
|
|
201
207
|
}
|
|
@@ -266,28 +272,12 @@ function resolveHostPackageRoot(argv1) {
|
|
|
266
272
|
cursor = parent;
|
|
267
273
|
}
|
|
268
274
|
}
|
|
269
|
-
function resolveTsxImportSpecifier() {
|
|
270
|
-
try {
|
|
271
|
-
return requireFromHere.resolve("tsx");
|
|
272
|
-
} catch {
|
|
273
|
-
return "tsx";
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
275
|
function resolveManagedToolsMcpServerConfig(entryPoint, moduleUrl = import.meta.url) {
|
|
277
276
|
const openClawRoot = resolveOpenClawRoot(resolveAcpxPluginRoot(moduleUrl));
|
|
278
|
-
const
|
|
279
|
-
if (fs.existsSync(distEntry)) return {
|
|
280
|
-
command: process.execPath,
|
|
281
|
-
args: [distEntry]
|
|
282
|
-
};
|
|
283
|
-
const sourceEntry = path.join(openClawRoot, "src", "mcp", `${entryPoint}.ts`);
|
|
277
|
+
const entry = resolvePackageRuntimeProcessEntrypointUrl(entryPoint, openClawRoot);
|
|
284
278
|
return {
|
|
285
279
|
command: process.execPath,
|
|
286
|
-
args:
|
|
287
|
-
"--import",
|
|
288
|
-
resolveTsxImportSpecifier(),
|
|
289
|
-
sourceEntry
|
|
290
|
-
]
|
|
280
|
+
args: resolveRuntimeWorkerArgv(entry)
|
|
291
281
|
};
|
|
292
282
|
}
|
|
293
283
|
function resolveConfiguredMcpServers(params) {
|
|
@@ -324,7 +314,7 @@ function resolveAcpxPluginConfig(params) {
|
|
|
324
314
|
moduleUrl: params.moduleUrl
|
|
325
315
|
});
|
|
326
316
|
const agents = Object.fromEntries(Object.entries(normalized.agents ?? {}).map(([name, entry]) => {
|
|
327
|
-
const cmd = entry.command
|
|
317
|
+
const cmd = entry.command;
|
|
328
318
|
const command = path.isAbsolute(cmd) && fs.existsSync(cmd) ? [cmd] : splitCommandParts(cmd);
|
|
329
319
|
return [normalizeLowercaseStringOrEmpty(name), [...command, ...entry.args ?? []]];
|
|
330
320
|
}));
|
|
@@ -337,6 +327,8 @@ function resolveAcpxPluginConfig(params) {
|
|
|
337
327
|
pluginToolsMcpBridge,
|
|
338
328
|
openClawToolsMcpBridge,
|
|
339
329
|
timeoutSeconds: normalized.timeoutSeconds,
|
|
330
|
+
agentProcessEnvAllow: normalized.agentProcessEnvAllow,
|
|
331
|
+
agentProcessEnvBlock: normalized.agentProcessEnvBlock,
|
|
340
332
|
mcpServers,
|
|
341
333
|
agents
|
|
342
334
|
};
|
|
@@ -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-Cn5bsvi0.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
|
//#region 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);
|
|
@@ -341,19 +332,6 @@ async function readPiSessionById(threadId, env) {
|
|
|
341
332
|
//#region extensions/acpx/src/pi-session-catalog.ts
|
|
342
333
|
const MAX_SEARCH_LENGTH = 500;
|
|
343
334
|
const isExactPiSessionCursor = sessionCatalogPaging.isExactCursor;
|
|
344
|
-
function textFromContent(content) {
|
|
345
|
-
if (typeof content === "string") return content;
|
|
346
|
-
if (!Array.isArray(content)) return "";
|
|
347
|
-
return content.flatMap((part) => {
|
|
348
|
-
if (!isRecord(part)) return [];
|
|
349
|
-
if (part.type === "text" && typeof part.text === "string") return [part.text];
|
|
350
|
-
if (part.type === "image") {
|
|
351
|
-
const mimeType = normalizeBoundedOptionalString(part.mimeType, 128);
|
|
352
|
-
return [mimeType ? `[image: ${mimeType}]` : "[image]"];
|
|
353
|
-
}
|
|
354
|
-
return [];
|
|
355
|
-
}).join("\n");
|
|
356
|
-
}
|
|
357
335
|
const PI_PARAMETER_MESSAGES = {
|
|
358
336
|
listNotObject: "Pi session list parameters must be an object",
|
|
359
337
|
unknownListParameter: (key) => `unknown Pi session list parameter: ${key}`,
|
|
@@ -420,7 +398,7 @@ function piMessageItems(entry) {
|
|
|
420
398
|
...modelRef ? { model: modelRef } : {}
|
|
421
399
|
};
|
|
422
400
|
if (role === "user") {
|
|
423
|
-
const text =
|
|
401
|
+
const text = piMessageText(message.content, true);
|
|
424
402
|
return text ? [{
|
|
425
403
|
...common,
|
|
426
404
|
type: "userMessage",
|
|
@@ -429,7 +407,7 @@ function piMessageItems(entry) {
|
|
|
429
407
|
}
|
|
430
408
|
if (role === "toolResult") {
|
|
431
409
|
const toolName = normalizeBoundedOptionalString(message.toolName, 256);
|
|
432
|
-
const text =
|
|
410
|
+
const text = piMessageText(message.content, true);
|
|
433
411
|
return [{
|
|
434
412
|
...common,
|
|
435
413
|
type: "toolResult",
|
|
@@ -454,7 +432,7 @@ function piMessageItems(entry) {
|
|
|
454
432
|
if (role === "custom" || role === "hookMessage") {
|
|
455
433
|
if (message.display !== true) return [];
|
|
456
434
|
const customType = normalizeBoundedOptionalString(message.customType, 256);
|
|
457
|
-
const text =
|
|
435
|
+
const text = piMessageText(message.content, true);
|
|
458
436
|
return text ? [{
|
|
459
437
|
...common,
|
|
460
438
|
type: "other",
|
|
@@ -505,7 +483,7 @@ function piTranscriptItems(entries) {
|
|
|
505
483
|
text: entry.summary
|
|
506
484
|
}];
|
|
507
485
|
if (entry.type === "custom_message" && entry.display === true) {
|
|
508
|
-
const text =
|
|
486
|
+
const text = piMessageText(entry.content, true);
|
|
509
487
|
return text ? [{
|
|
510
488
|
...common,
|
|
511
489
|
type: "other",
|
|
@@ -14,8 +14,8 @@ const PI_SESSION_ID_PATTERN = /^(?!-)[A-Za-z0-9._:-]{1,256}$/u;
|
|
|
14
14
|
function piHome(env) {
|
|
15
15
|
return (process.platform === "win32" ? env.USERPROFILE?.trim() : env.HOME?.trim()) || os.homedir();
|
|
16
16
|
}
|
|
17
|
-
function isPiSessionCatalogPathAbsolute(value
|
|
18
|
-
if (platform !== "win32") return path.posix.isAbsolute(value);
|
|
17
|
+
function isPiSessionCatalogPathAbsolute(value) {
|
|
18
|
+
if (process.platform !== "win32") return path.posix.isAbsolute(value);
|
|
19
19
|
const root = path.win32.parse(value).root;
|
|
20
20
|
return path.win32.isAbsolute(value) && root !== "\\" && root !== "/";
|
|
21
21
|
}
|