@exulu/backend 2.2.0 → 2.3.0
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/index.js
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
LITELLM_UI_PATH,
|
|
15
15
|
LiteLLMAdminError,
|
|
16
16
|
OAUTH_CALLBACK_PATH,
|
|
17
|
+
PreviewRenderError,
|
|
17
18
|
ResolveModelError,
|
|
18
19
|
STATISTICS_TYPE_ENUM,
|
|
19
20
|
authentication,
|
|
@@ -37,6 +38,7 @@ import {
|
|
|
37
38
|
exchangeCodeForTokens,
|
|
38
39
|
exuluApp,
|
|
39
40
|
getBudgetSettings,
|
|
41
|
+
getPdfPreviewBytes,
|
|
40
42
|
getPresignedUrl,
|
|
41
43
|
getS3ObjectBytes,
|
|
42
44
|
getS3ObjectContent,
|
|
@@ -47,6 +49,7 @@ import {
|
|
|
47
49
|
getToken,
|
|
48
50
|
getUserBudgetView,
|
|
49
51
|
guardExtractedFileText,
|
|
52
|
+
imageAttachmentGuard,
|
|
50
53
|
invalidateBudgetCaches,
|
|
51
54
|
isLiteLLMEnabled,
|
|
52
55
|
listS3ObjectsByPrefix,
|
|
@@ -74,7 +77,7 @@ import {
|
|
|
74
77
|
upsertBudget,
|
|
75
78
|
waitForLiteLLMReady,
|
|
76
79
|
withRetry
|
|
77
|
-
} from "./chunk-
|
|
80
|
+
} from "./chunk-2242AI5L.js";
|
|
78
81
|
import {
|
|
79
82
|
findLiteLLMModel
|
|
80
83
|
} from "./chunk-7CCMW3IW.js";
|
|
@@ -11279,76 +11282,6 @@ async function parseSkillFrontmatter(zipBytes) {
|
|
|
11279
11282
|
return { name: fm.name, description: fm.description };
|
|
11280
11283
|
}
|
|
11281
11284
|
|
|
11282
|
-
// src/sessions/pdf-preview-cache.ts
|
|
11283
|
-
import { exec } from "child_process";
|
|
11284
|
-
import { existsSync as existsSync3 } from "fs";
|
|
11285
|
-
import { mkdir, readFile, rename, rm, writeFile } from "fs/promises";
|
|
11286
|
-
import { extname, join } from "path";
|
|
11287
|
-
import { promisify } from "util";
|
|
11288
|
-
var execAsync = promisify(exec);
|
|
11289
|
-
var CACHE_ROOT = "/tmp/exulu-pdf-cache";
|
|
11290
|
-
var CACHE_IN = join(CACHE_ROOT, "_in");
|
|
11291
|
-
var CACHE_OUT = join(CACHE_ROOT, "_out");
|
|
11292
|
-
var inFlight = /* @__PURE__ */ new Map();
|
|
11293
|
-
var PreviewRenderError = class extends Error {
|
|
11294
|
-
constructor(message) {
|
|
11295
|
-
super(message);
|
|
11296
|
-
this.name = "PreviewRenderError";
|
|
11297
|
-
}
|
|
11298
|
-
};
|
|
11299
|
-
function sanitizeEtag(raw) {
|
|
11300
|
-
return raw.replace(/^"|"$/g, "").replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
11301
|
-
}
|
|
11302
|
-
async function getPdfPreviewBytes(opts) {
|
|
11303
|
-
const { sourceKey, etag, config } = opts;
|
|
11304
|
-
const safeEtag = sanitizeEtag(etag);
|
|
11305
|
-
if (!safeEtag) {
|
|
11306
|
-
throw new PreviewRenderError(`Invalid ETag for ${sourceKey}`);
|
|
11307
|
-
}
|
|
11308
|
-
const cachedPath = join(CACHE_ROOT, `${safeEtag}.pdf`);
|
|
11309
|
-
if (existsSync3(cachedPath)) {
|
|
11310
|
-
return readFile(cachedPath);
|
|
11311
|
-
}
|
|
11312
|
-
const existing = inFlight.get(safeEtag);
|
|
11313
|
-
if (existing) return existing;
|
|
11314
|
-
const promise = (async () => {
|
|
11315
|
-
try {
|
|
11316
|
-
await mkdir(CACHE_IN, { recursive: true });
|
|
11317
|
-
await mkdir(CACHE_OUT, { recursive: true });
|
|
11318
|
-
const ext = (extname(sourceKey) || ".docx").toLowerCase();
|
|
11319
|
-
const inputPath = join(CACHE_IN, `${safeEtag}${ext}`);
|
|
11320
|
-
const outputPath = join(CACHE_OUT, `${safeEtag}.pdf`);
|
|
11321
|
-
try {
|
|
11322
|
-
const bytes = await getS3ObjectBytes(sourceKey, config);
|
|
11323
|
-
await writeFile(inputPath, bytes);
|
|
11324
|
-
try {
|
|
11325
|
-
await execAsync(
|
|
11326
|
-
`soffice --headless --convert-to pdf "${inputPath}" --outdir "${CACHE_OUT}"`,
|
|
11327
|
-
{ timeout: 6e4, maxBuffer: 16 * 1024 * 1024 }
|
|
11328
|
-
);
|
|
11329
|
-
} catch (err) {
|
|
11330
|
-
throw new PreviewRenderError(
|
|
11331
|
-
`LibreOffice conversion failed for ${sourceKey} (etag ${etag}): ${err?.stderr ?? err?.message ?? "unknown error"}`
|
|
11332
|
-
);
|
|
11333
|
-
}
|
|
11334
|
-
if (!existsSync3(outputPath)) {
|
|
11335
|
-
throw new PreviewRenderError(
|
|
11336
|
-
`LibreOffice produced no output for ${sourceKey} (etag ${etag})`
|
|
11337
|
-
);
|
|
11338
|
-
}
|
|
11339
|
-
await rename(outputPath, cachedPath);
|
|
11340
|
-
return await readFile(cachedPath);
|
|
11341
|
-
} finally {
|
|
11342
|
-
await rm(inputPath, { force: true });
|
|
11343
|
-
}
|
|
11344
|
-
} finally {
|
|
11345
|
-
inFlight.delete(safeEtag);
|
|
11346
|
-
}
|
|
11347
|
-
})();
|
|
11348
|
-
inFlight.set(safeEtag, promise);
|
|
11349
|
-
return promise;
|
|
11350
|
-
}
|
|
11351
|
-
|
|
11352
11285
|
// src/exulu/routes.ts
|
|
11353
11286
|
import { InMemoryLRUCache } from "@apollo/utils.keyvaluecache";
|
|
11354
11287
|
import bodyParser from "body-parser";
|
|
@@ -11964,7 +11897,7 @@ When a tool execution is not approved by the user, do not retry it unless explic
|
|
|
11964
11897
|
// Stop after the image_generation tool fires — the widget IS the
|
|
11965
11898
|
// assistant's response, no follow-up text turn is wanted (same
|
|
11966
11899
|
// reasoning as question_ask: the UI artifact is the message).
|
|
11967
|
-
prepareStep: composePrepareSteps(contextGuard(contextWindow), retrievalGuard, finalAnswerGuard(turnBudget)),
|
|
11900
|
+
prepareStep: composePrepareSteps(contextGuard(contextWindow), retrievalGuard, finalAnswerGuard(turnBudget), imageAttachmentGuard()),
|
|
11968
11901
|
stopWhen: [stepCountIs(turnBudget), hasToolCall("image_generation")]
|
|
11969
11902
|
});
|
|
11970
11903
|
console.log("[EXULU] Output: " + JSON.stringify(output, null, 2));
|
|
@@ -12027,7 +11960,7 @@ When a tool execution is not approved by the user, do not retry it unless explic
|
|
|
12027
11960
|
}),
|
|
12028
11961
|
maxRetries: 2,
|
|
12029
11962
|
tools,
|
|
12030
|
-
prepareStep: composePrepareSteps(contextGuard(contextWindow), retrievalGuard, finalAnswerGuard(turnBudget)),
|
|
11963
|
+
prepareStep: composePrepareSteps(contextGuard(contextWindow), retrievalGuard, finalAnswerGuard(turnBudget), imageAttachmentGuard()),
|
|
12031
11964
|
stopWhen: [stepCountIs(turnBudget), hasToolCall("image_generation")]
|
|
12032
11965
|
});
|
|
12033
11966
|
if (statistics) {
|
|
@@ -12442,7 +12375,7 @@ When a tool execution is not approved by the user, do not retry it unless explic
|
|
|
12442
12375
|
);
|
|
12443
12376
|
},
|
|
12444
12377
|
// todo allow configuring the step budget per skill
|
|
12445
|
-
prepareStep: composePrepareSteps(contextGuard(contextWindow), retrievalGuard, finalAnswerGuard(turnBudget)),
|
|
12378
|
+
prepareStep: composePrepareSteps(contextGuard(contextWindow), retrievalGuard, finalAnswerGuard(turnBudget), imageAttachmentGuard()),
|
|
12446
12379
|
stopWhen: [stepCountIs(turnBudget), hasToolCall("image_generation")]
|
|
12447
12380
|
});
|
|
12448
12381
|
return {
|
|
@@ -12926,7 +12859,7 @@ async function editImage(args) {
|
|
|
12926
12859
|
}
|
|
12927
12860
|
|
|
12928
12861
|
// src/exulu/litellm/parse-image-models.ts
|
|
12929
|
-
import { existsSync as
|
|
12862
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
12930
12863
|
var stripComment3 = (line) => {
|
|
12931
12864
|
const idx = line.indexOf("#");
|
|
12932
12865
|
return idx >= 0 ? line.slice(0, idx) : line;
|
|
@@ -12949,7 +12882,7 @@ var parseInt103 = (raw) => {
|
|
|
12949
12882
|
return Number.isInteger(n) ? n : void 0;
|
|
12950
12883
|
};
|
|
12951
12884
|
var parseImageGenerationModels = (configPath) => {
|
|
12952
|
-
if (!
|
|
12885
|
+
if (!existsSync3(configPath)) return [];
|
|
12953
12886
|
const text = readFileSync3(configPath, "utf8");
|
|
12954
12887
|
const lines = text.split("\n");
|
|
12955
12888
|
const entries = [];
|
|
@@ -13573,7 +13506,7 @@ ${project.description}` : ""}` : "",
|
|
|
13573
13506
|
messages: coreMessages,
|
|
13574
13507
|
tools: hasTools ? activeTools : void 0,
|
|
13575
13508
|
maxRetries: 2,
|
|
13576
|
-
prepareStep: clientTools.length > 0 ? void 0 : composePrepareSteps(contextGuard(contextWindow), gatewayRetrievalGuard, finalAnswerGuard(turnBudget)),
|
|
13509
|
+
prepareStep: clientTools.length > 0 ? void 0 : composePrepareSteps(contextGuard(contextWindow), gatewayRetrievalGuard, finalAnswerGuard(turnBudget), imageAttachmentGuard()),
|
|
13577
13510
|
stopWhen: clientTools.length > 0 ? void 0 : [stepCountIs2(turnBudget)],
|
|
13578
13511
|
onError: (error) => {
|
|
13579
13512
|
console.error("[OPENAI GATEWAY] stream error:", error);
|
|
@@ -13613,7 +13546,7 @@ ${project.description}` : ""}` : "",
|
|
|
13613
13546
|
messages: coreMessages,
|
|
13614
13547
|
tools: hasTools ? activeTools : void 0,
|
|
13615
13548
|
maxRetries: 2,
|
|
13616
|
-
prepareStep: clientTools.length > 0 ? void 0 : composePrepareSteps(contextGuard(contextWindow), gatewayRetrievalGuard, finalAnswerGuard(turnBudget)),
|
|
13549
|
+
prepareStep: clientTools.length > 0 ? void 0 : composePrepareSteps(contextGuard(contextWindow), gatewayRetrievalGuard, finalAnswerGuard(turnBudget), imageAttachmentGuard()),
|
|
13617
13550
|
stopWhen: clientTools.length > 0 ? void 0 : [stepCountIs2(turnBudget)]
|
|
13618
13551
|
});
|
|
13619
13552
|
res.json(transformCompletion(text, usage.inputTokens ?? 0, usage.outputTokens ?? 0, ctx));
|
|
@@ -13885,34 +13818,34 @@ var CLIENT_MANIFEST = [
|
|
|
13885
13818
|
// exception: nested under agent/
|
|
13886
13819
|
];
|
|
13887
13820
|
|
|
13888
|
-
// src/skills/bootstrap/
|
|
13889
|
-
var EXULU_SH_B64 = "IyEvYmluL3NoCiMgZXh1bHUg4oCUIGhlbHBlciBmb3IgdGhlIEV4dWx1IGNlbnRyYWwgc2tpbGwgbGlicmFyeS4gVGhlIGFnZW50IGludm9rZXMgdGhpcwojIChuZXZlciByYXcgY3VybCk6IHRoZSB0b2tlbiBpcyByZWFkIGZyb20gdGhlIGNvbmZpZyBmaWxlIGhlcmUgYW5kIHNlbnQgdmlhCiMgYHgtYXBpLWtleTogQmVhcmVyYCwgc28gaXQgbmV2ZXIgZW50ZXJzIHRoZSBtb2RlbCBjb250ZXh0LiBDbGllbnQgZmFuLW91dAojIChjb3B5L3N5bWxpbmsgYWNyb3NzIGFnZW50IGNsaWVudHMpIGlzIGRldGVybWluaXN0aWMuCnNldCAtZXUKCkNPTkZJR19ESVI9IiRIT01FLy5jb25maWcvZXh1bHUiCkNPTkZJR19GSUxFPSIkQ09ORklHX0RJUi9za2lsbHMuanNvbiIKCmRpZSgpIHsgcHJpbnRmICdleHVsdTogJXNcbicgIiQqIiA+JjI7IGV4aXQgMTsgfQppbmZvKCkgeyBwcmludGYgJyVzXG4nICIkKiIgPiYyOyB9Cgpqc29uX3N0cigpIHsgIyBqc29uX3N0ciA8a2V5PiA8ZmlsZT4g4oCUIGZsYXQgImtleSI6InZhbHVlIgogIHNlZCAtbiAicy8uKlwiJDFcIltbOnNwYWNlOl1dKjpbWzpzcGFjZTpdXSpcIlxcKFteXCJdKlxcKVwiLiovXFwxL3AiICIkMiIgfCBoZWFkIC1uMQp9CgpbIC1mICIkQ09ORklHX0ZJTEUiIF0gfHwgZGllICJub3QgY29uZmlndXJlZCDigJQgcnVuOiBjdXJsIC1mc1NMIDxiYXNlX3VybD4vYXBpL3NraWxscy9pbnN0YWxsLnNoIHwgc2giCgpCQVNFX1VSTD0iJChqc29uX3N0ciBiYXNlX3VybCAiJENPTkZJR19GSUxFIikiCkJBQ0tFTkQ9IiQoanNvbl9zdHIgYmFja2VuZCAiJENPTkZJR19GSUxFIikiCkFQSV9LRVk9IiQoanNvbl9zdHIgYXBpX2tleSAiJENPTkZJR19GSUxFIikiCkxJTktfTU9ERT0iJChqc29uX3N0ciBsaW5rX21vZGUgIiRDT05GSUdfRklMRSIpIgpTQ09QRT0iJChqc29uX3N0ciBzY29wZSAiJENPTkZJR19GSUxFIikiCkNMSUVOVFM9IiQoc2VkIC1uICdzLy4qImNsaWVudHMiW1s6c3BhY2U6XV0qOltbOnNwYWNlOl1dKlxbXChbXl1dKlwpXF0uKi9cMS9wJyAiJENPTkZJR19GSUxFIiB8IHRyICcsJyAnICcgfCB0ciAtZCAnIicgfCB0ciAtcyAnICcpIgoKWyAtbiAiJENMSUVOVFMiIF0gfHwgQ0xJRU5UUz0iYWdlbnRzIgpbIC1uICIkTElOS19NT0RFIiBdIHx8IExJTktfTU9ERT0iY29weSIKWyAtbiAiJFNDT1BFIiBdIHx8IFNDT1BFPSJwcm9qZWN0IgoKaWYgWyAteiAiJEJBQ0tFTkQiIF07IHRoZW4KICBbIC1uICIkQkFTRV9VUkwiIF0gfHwgZGllICJjb25maWcgaGFzIG5vIGJhY2tlbmQgYW5kIG5vIGJhc2VfdXJsIgogIEJBQ0tFTkQ9IiQoY3VybCAtZnNTTCAiJEJBU0VfVVJML2FwaS9jb25maWciIHwgc2VkIC1uICdzLy4qImJhY2tlbmQiW1s6c3BhY2U6XV0qOltbOnNwYWNlOl1dKiJcKFteIl0qXCkiLiovXDEvcCcgfCBoZWFkIC1uMSkiCiAgWyAtbiAiJEJBQ0tFTkQiIF0gfHwgZGllICJjb3VsZCBub3QgcmVzb2x2ZSBiYWNrZW5kIGZyb20gJEJBU0VfVVJML2FwaS9jb25maWciCmZpCkJBQ0tFTkQ9IiQocHJpbnRmICclcycgIiRCQUNLRU5EIiB8IHNlZCAnczovKiQ6OicpIgoKUk9PVD0iJFBXRCIKWyAiJFNDT1BFIiA9ICJob21lIiBdICYmIFJPT1Q9IiRIT01FIgoKIyBkaXJfZm9yIENMSUVOVF9JRCAtPiByZWxhdGl2ZSBza2lsbCBkaXIgKGdlbmVyYXRlZCBmcm9tIHRoZSBtYW5pZmVzdCBpbiB0aGUKIyByZWFsIGJ1aWxkOyBhIHJlcHJlc2VudGF0aXZlIHN1YnNldCBoZXJlIGZvciBsb2NhbCB0ZXN0aW5nKS4KZGlyX2ZvcigpIHsKICBjYXNlICIkMSIgaW4KX19ESVJfRk9SX0NBU0VTX18KICAgICopIHJldHVybiAxIDs7CiAgZXNhYwp9CgphcGkoKSB7ICMgYXBpIDxNRVRIT0Q+IDxwYXRoPiBbZXh0cmEgY3VybCBhcmdzLi4uXSAtPiBib2R5IG9uIHN0ZG91dAogIG09IiQxIjsgcD0iJDIiOyBzaGlmdCAyCiAgY3VybCAtZnNTIC1YICIkbSIgIiRCQUNLRU5EJHAiIC1IICJ4LWFwaS1rZXk6IEJlYXJlciAkQVBJX0tFWSIgIiRAIgp9CgptZXRhX3ZlcnNpb24oKSB7ICMgbWV0YV92ZXJzaW9uIDxuYW1lPiAtPiBjdXJyZW50X3ZlcnNpb24gZnJvbSByZWdpc3RyeQogIGFwaSBHRVQgIi9za2lsbHMvcmVnaXN0cnkvJDEiIDI+L2Rldi9udWxsIFwKICAgIHwgc2VkIC1uICdzLy4qImN1cnJlbnRfdmVyc2lvbiJbWzpzcGFjZTpdXSo6W1s6c3BhY2U6XV0qXChbMC05XVswLTldKlwpLiovXDEvcCcgfCBoZWFkIC1uMQp9CgpfbWFuYWdlZCgpIHsgIyBfbWFuYWdlZCA8ZGlyPiAtPiAwIGlmIHNhZmUgdG8gb3ZlcndyaXRlIChvdXJzIG9yIHN5bWxpbmsgb3IgYWJzZW50KQogIGQ9IiQxIgogIGlmIFsgLWUgIiRkIiBdICYmIFsgISAtTCAiJGQiIF0gJiYgWyAhIC1mICIkZC8uZXh1bHUtc2tpbGwuanNvbiIgXTsgdGhlbgogICAgaW5mbyAic2tpcCAkZCAoZXhpc3RzLCBub3QgbWFuYWdlZCBieSBleHVsdSkiOyByZXR1cm4gMQogIGZpCiAgcmV0dXJuIDAKfQoKX3B1dF9yZWFsKCkgeyAjIF9wdXRfcmVhbCA8ZGVzdD4gPHNyY2Rpcj4gPG1hcmtlci1qc29uPgogIF9tYW5hZ2VkICIkMSIgfHwgcmV0dXJuIDAKICBybSAtcmYgIiQxIjsgbWtkaXIgLXAgIiQxIjsgY3AgLVIgIiQyLy4iICIkMS8iCiAgcHJpbnRmICclc1xuJyAiJDMiID4gIiQxLy5leHVsdS1za2lsbC5qc29uIgp9CgpwbGFjZV9za2lsbCgpIHsgIyBwbGFjZV9za2lsbCA8bmFtZT4gPHNyY2Rpcj4gPHZlcnNpb24+CiAgcG5hbWU9IiQxIjsgcHNyYz0iJDIiOyBwdmVyPSIkezM6LTF9IgogIG1hcmtlcj0neyAibmFtZSI6ICInIiRwbmFtZSInIiwgInZlcnNpb24iOiAnIiRwdmVyIicsICJzb3VyY2UiOiAiJyIkQkFDS0VORCInIiB9JwogIGNhbm9uPSIkUk9PVC8uYWdlbnRzL3NraWxscy8kcG5hbWUiCiAgWyAiJExJTktfTU9ERSIgPSAic3ltbGluayIgXSAmJiBfcHV0X3JlYWwgIiRjYW5vbiIgIiRwc3JjIiAiJG1hcmtlciIKICBmb3IgaWQgaW4gJENMSUVOVFM7IGRvCiAgICBkPSIkKGRpcl9mb3IgIiRpZCIpIiB8fCB7IGluZm8gInVua25vd24gY2xpZW50OiAkaWQiOyBjb250aW51ZTsgfQogICAgcGFyZW50PSIkUk9PVC8kZCI7IGRlc3Q9IiRwYXJlbnQvJHBuYW1lIgogICAgaWYgWyAiJExJTktfTU9ERSIgPSAic3ltbGluayIgXSAmJiBbICIkaWQiICE9ICJhZ2VudHMiIF07IHRoZW4KICAgICAgX21hbmFnZWQgIiRkZXN0IiB8fCBjb250aW51ZQogICAgICBta2RpciAtcCAiJHBhcmVudCI7IHJtIC1yZiAiJGRlc3QiCiAgICAgIGlmIGxuIC1zICIkY2Fub24iICIkZGVzdCIgMj4vZGV2L251bGw7IHRoZW4KICAgICAgICBpbmZvICJsaW5rZWQgJGRlc3QgLT4gJGNhbm9uIgogICAgICBlbHNlCiAgICAgICAgaW5mbyAic3ltbGluayB1bnN1cHBvcnRlZCBhdCAkZGVzdDsgY29weWluZyIKICAgICAgICBfcHV0X3JlYWwgIiRkZXN0IiAiJHBzcmMiICIkbWFya2VyIgogICAgICBmaQogICAgZWxpZiBbICIkTElOS19NT0RFIiA9ICJjb3B5IiBdOyB0aGVuCiAgICAgIF9wdXRfcmVhbCAiJGRlc3QiICIkcHNyYyIgIiRtYXJrZXIiCiAgICBmaQogICAgIyBzeW1saW5rICsgYWdlbnRzOiBhbHJlYWR5IHBsYWNlZCBhcyB0aGUgY2Fub25pY2FsIHN0b3JlIGFib3ZlLgogIGRvbmUKfQoKaW5zdGFsbGVkX25hbWVzKCkgeyAjIHVuaXF1ZSBza2lsbCBuYW1lcyB0aGF0IGNhcnJ5IG91ciBtYXJrZXIgdW5kZXIgUk9PVAogIHsgZmluZCAiJFJPT1QvLmFnZW50cy9za2lsbHMiIC1tYXhkZXB0aCAyIC1uYW1lIC5leHVsdS1za2lsbC5qc29uIDI+L2Rldi9udWxsCiAgICBmb3IgaWQgaW4gJENMSUVOVFM7IGRvCiAgICAgIGQ9IiQoZGlyX2ZvciAiJGlkIikiIHx8IGNvbnRpbnVlCiAgICAgIGZpbmQgIiRST09ULyRkIiAtbWF4ZGVwdGggMiAtbmFtZSAuZXh1bHUtc2tpbGwuanNvbiAyPi9kZXYvbnVsbAogICAgZG9uZQogIH0gfCB3aGlsZSByZWFkIC1yIG07IGRvIGpzb25fc3RyIG5hbWUgIiRtIjsgZG9uZSB8IHNvcnQgLXUKfQoKbWFya2VyX3ZlcnNpb24oKSB7ICMgbWFya2VyX3ZlcnNpb24gPG5hbWU+CiAgZm9yIGJhc2UgaW4gIiRST09ULy5hZ2VudHMvc2tpbGxzIjsgZG8KICAgIFsgLWYgIiRiYXNlLyQxLy5leHVsdS1za2lsbC5qc29uIiBdICYmIHsganNvbl9zdHIgdmVyc2lvbiAiJGJhc2UvJDEvLmV4dWx1LXNraWxsLmpzb24iOyByZXR1cm47IH0KICBkb25lCiAgZm9yIGlkIGluICRDTElFTlRTOyBkbwogICAgZD0iJChkaXJfZm9yICIkaWQiKSIgfHwgY29udGludWUKICAgIGY9IiRST09ULyRkLyQxLy5leHVsdS1za2lsbC5qc29uIgogICAgWyAtZiAiJGYiIF0gJiYgeyBqc29uX3N0ciB2ZXJzaW9uICIkZiI7IHJldHVybjsgfQogIGRvbmUKfQoKZG9faW5zdGFsbCgpIHsgIyBkb19pbnN0YWxsIDxuYW1lPgogIG5hbWU9IiQxIgogIFRNUD0iJChta3RlbXAgLWQpIgogIGFwaSBHRVQgIi9za2lsbHMvcmVnaXN0cnkvJG5hbWUvZG93bmxvYWQiIC0tb3V0cHV0ICIkVE1QL3NraWxsLnppcCIgXAogICAgfHwgeyBybSAtcmYgIiRUTVAiOyBkaWUgImRvd25sb2FkIGZhaWxlZCBmb3IgJyRuYW1lJyAoNDAzID0gbm8gYWNjZXNzLCA0MDQgPSB1bmtub3duKSI7IH0KICBta2RpciAtcCAiJFRNUC94IgogIHVuemlwIC1xICIkVE1QL3NraWxsLnppcCIgLWQgIiRUTVAveCIgfHwgeyBybSAtcmYgIiRUTVAiOyBkaWUgImJhZCBhcmNoaXZlIGZvciAnJG5hbWUnIjsgfQogIHNyYz0iJChmaW5kICIkVE1QL3giIC1taW5kZXB0aCAxIC1tYXhkZXB0aCAxIC10eXBlIGQgfCBoZWFkIC1uMSkiCiAgWyAtbiAiJHNyYyIgXSB8fCB7IHJtIC1yZiAiJFRNUCI7IGRpZSAidW5leHBlY3RlZCBhcmNoaXZlIGxheW91dCBmb3IgJyRuYW1lJyI7IH0KICB2ZXI9IiQobWV0YV92ZXJzaW9uICIkbmFtZSIpIgogIHBsYWNlX3NraWxsICIkbmFtZSIgIiRzcmMiICIke3ZlcjotMX0iCiAgcm0gLXJmICIkVE1QIgogIGluZm8gImluc3RhbGxlZCAkbmFtZSAodiR7dmVyOi0xfSkgWyRMSU5LX01PREVdIGludG86ICRDTElFTlRTIgp9Cgp1c2FnZSgpIHsKICBjYXQgPiYyIDw8RU9GCmV4dWx1IOKAlCBFeHVsdSBza2lsbCBsaWJyYXJ5IGhlbHBlcgogIGV4dWx1IGxpc3QgICAgICAgICAgICAgICAgIGxpc3Qgc2tpbGxzIHlvdSBjYW4gYWNjZXNzIChKU09OKQogIGV4dWx1IGdldCA8bmFtZT4gICAgICAgICAgIHNob3cgb25lIHNraWxsJ3MgbWV0YWRhdGEgKEpTT04pCiAgZXh1bHUgaW5zdGFsbCA8bmFtZT4gICAgICAgaW5zdGFsbC9yZWZyZXNoIGEgc2tpbGwgaW50byB5b3VyIGFnZW50IGNsaWVudHMKICBleHVsdSB1cGRhdGUgWzxuYW1lPl0gICAgICB1cGRhdGUgaW5zdGFsbGVkIHNraWxscyAoYWxsLCBvciBvbmUpIHRvIGxhdGVzdAogIGV4dWx1IHB1Ymxpc2ggPG5hbWU+IDxkaXI+IHB1Ymxpc2ggYSBsb2NhbCBza2lsbCBmb2xkZXIgYXMgPG5hbWU+CiAgZXh1bHUgY29uZmlnICAgICAgICAgICAgICAgc2hvdyByZXNvbHZlZCBiYWNrZW5kIC8gc2NvcGUgLyBjbGllbnRzIChubyBzZWNyZXRzKQpFT0YKfQoKY21kPSIkezE6LWhlbHB9IgpbICQjIC1ndCAwIF0gJiYgc2hpZnQgfHwgdHJ1ZQoKY2FzZSAiJGNtZCIgaW4KICBsaXN0KSBhcGkgR0VUICIvc2tpbGxzL3JlZ2lzdHJ5IiA7OwogIGdldCkgWyAkIyAtZ2UgMSBdIHx8IGRpZSAidXNhZ2U6IGV4dWx1IGdldCA8bmFtZT4iOyBhcGkgR0VUICIvc2tpbGxzL3JlZ2lzdHJ5LyQxIiA7OwogIGluc3RhbGwpIFsgJCMgLWdlIDEgXSB8fCBkaWUgInVzYWdlOiBleHVsdSBpbnN0YWxsIDxuYW1lPiI7IGRvX2luc3RhbGwgIiQxIiA7OwogIHVwZGF0ZSkKICAgIGlmIFsgJCMgLWdlIDEgXTsgdGhlbiBuYW1lcz0iJDEiOyBlbHNlIG5hbWVzPSIkKGluc3RhbGxlZF9uYW1lcykiOyBmaQogICAgWyAtbiAiJG5hbWVzIiBdIHx8IHsgaW5mbyAibm8gZXh1bHUtbWFuYWdlZCBza2lsbHMgZm91bmQgdW5kZXIgJFJPT1QiOyBleGl0IDA7IH0KICAgIGZvciBuIGluICRuYW1lczsgZG8KICAgICAgY3VyPSIkKG1hcmtlcl92ZXJzaW9uICIkbiIpIgogICAgICBsYXRlc3Q9IiQobWV0YV92ZXJzaW9uICIkbiIpIgogICAgICBbIC1uICIkbGF0ZXN0IiBdIHx8IHsgaW5mbyAic2tpcCAkbiAobm90IGluIHJlZ2lzdHJ5KSI7IGNvbnRpbnVlOyB9CiAgICAgIGlmIFsgLXogIiRjdXIiIF0gfHwgWyAiJGxhdGVzdCIgLWd0ICIkY3VyIiBdIDI+L2Rldi9udWxsOyB0aGVuCiAgICAgICAgaW5mbyAidXBkYXRpbmcgJG46IHYke2N1cjotP30gLT4gdiRsYXRlc3QiOyBkb19pbnN0YWxsICIkbiIKICAgICAgZWxzZQogICAgICAgIGluZm8gIiRuIHVwIHRvIGRhdGUgKHYkY3VyKSIKICAgICAgZmkKICAgIGRvbmUKICAgIDs7CiAgcHVibGlzaCkKICAgIFsgJCMgLWdlIDIgXSB8fCBkaWUgInVzYWdlOiBleHVsdSBwdWJsaXNoIDxuYW1lPiA8ZGlyPiIKICAgIG5hbWU9IiQxIjsgZm9sZGVyPSIkMiIKICAgIFsgLWQgIiRmb2xkZXIiIF0gfHwgZGllICJubyBzdWNoIGZvbGRlcjogJGZvbGRlciIKICAgIFsgLWYgIiRmb2xkZXIvU0tJTEwubWQiIF0gfHwgZGllICIkZm9sZGVyIGhhcyBubyBTS0lMTC5tZCBhdCBpdHMgcm9vdCIKICAgIGNvbW1hbmQgLXYgemlwID4vZGV2L251bGwgMj4mMSB8fCBkaWUgInRoZSAnemlwJyBjb21tYW5kIGlzIHJlcXVpcmVkIHRvIHB1Ymxpc2giCiAgICBUTVA9IiQobWt0ZW1wIC1kKSIKICAgICggY2QgIiQoZGlybmFtZSAiJGZvbGRlciIpIiBcCiAgICAgICYmIHppcCAtcSAtciAtWCAiJFRNUC9za2lsbC56aXAiICIkKGJhc2VuYW1lICIkZm9sZGVyIikiIFwKICAgICAgICAgICAteCAnKi8uZXh1bHUtc2tpbGwuanNvbicgJyovLmdpdC8qJyAnKi5EU19TdG9yZScgJyovX19NQUNPU1gvKicgKSBcCiAgICAgIHx8IHsgcm0gLXJmICIkVE1QIjsgZGllICJjb3VsZCBub3QgemlwICRmb2xkZXIiOyB9CiAgICBhcGkgUE9TVCAiL3NraWxscy9yZWdpc3RyeS8kbmFtZSIgLUggIkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vemlwIiBcCiAgICAgIC0tZGF0YS1iaW5hcnkgQCIkVE1QL3NraWxsLnppcCIgXAogICAgICB8fCB7IHJtIC1yZiAiJFRNUCI7IGRpZSAicHVibGlzaCBmYWlsZWQgKDQwMyA9IG5vIHdyaXRlIGFjY2VzcywgNDA5ID0gbmFtZSB0YWtlbikiOyB9CiAgICBybSAtcmYgIiRUTVAiCiAgICBpbmZvICJwdWJsaXNoZWQgJG5hbWUiCiAgICA7OwogIGNvbmZpZykKICAgIHByaW50ZiAnYmFja2VuZD0lc1xuc2NvcGU9JXNcbmxpbmtfbW9kZT0lc1xuY2xpZW50cz0lc1xuYXBpX2tleT0lc1xuJyBcCiAgICAgICIkQkFDS0VORCIgIiRTQ09QRSIgIiRMSU5LX01PREUiICIkQ0xJRU5UUyIgXAogICAgICAiJChbIC1uICIkQVBJX0tFWSIgXSAmJiBlY2hvIHNldCB8fCBlY2hvIE1JU1NJTkcpIgogICAgOzsKICBoZWxwfC0taGVscHwtaCkgdXNhZ2UgOzsKICAqKSBpbmZvICJ1bmtub3duIGNvbW1hbmQ6ICRjbWQiOyB1c2FnZTsgZXhpdCAyIDs7CmVzYWMK";
|
|
13821
|
+
// src/skills/bootstrap/imp-sh.generated.ts
|
|
13822
|
+
var IMP_SH_B64 = "IyEvYmluL3NoCiMgaW1wIOKAlCBoZWxwZXIgZm9yIHRoZSBjZW50cmFsIHNraWxsIGxpYnJhcnkuIFRoZSBhZ2VudCBpbnZva2VzIHRoaXMKIyAobmV2ZXIgcmF3IGN1cmwpOiB0aGUgdG9rZW4gaXMgcmVhZCBmcm9tIHRoZSBjb25maWcgZmlsZSBoZXJlIGFuZCBzZW50IHZpYQojIGB4LWFwaS1rZXk6IEJlYXJlcmAsIHNvIGl0IG5ldmVyIGVudGVycyB0aGUgbW9kZWwgY29udGV4dC4gQ2xpZW50IGZhbi1vdXQKIyAoY29weS9zeW1saW5rIGFjcm9zcyBhZ2VudCBjbGllbnRzKSBpcyBkZXRlcm1pbmlzdGljLgpzZXQgLWV1CgpDT05GSUdfRElSPSIkSE9NRS8uY29uZmlnL2ltcCIKQ09ORklHX0ZJTEU9IiRDT05GSUdfRElSL3NraWxscy5qc29uIgoKZGllKCkgeyBwcmludGYgJ2ltcDogJXNcbicgIiQqIiA+JjI7IGV4aXQgMTsgfQppbmZvKCkgeyBwcmludGYgJyVzXG4nICIkKiIgPiYyOyB9Cgpqc29uX3N0cigpIHsgIyBqc29uX3N0ciA8a2V5PiA8ZmlsZT4g4oCUIGZsYXQgImtleSI6InZhbHVlIgogIHNlZCAtbiAicy8uKlwiJDFcIltbOnNwYWNlOl1dKjpbWzpzcGFjZTpdXSpcIlxcKFteXCJdKlxcKVwiLiovXFwxL3AiICIkMiIgfCBoZWFkIC1uMQp9CgpbIC1mICIkQ09ORklHX0ZJTEUiIF0gfHwgZGllICJub3QgY29uZmlndXJlZCDigJQgcnVuOiBjdXJsIC1mc1NMIDxiYXNlX3VybD4vYXBpL3NraWxscy9pbnN0YWxsLnNoIHwgc2giCgpCQVNFX1VSTD0iJChqc29uX3N0ciBiYXNlX3VybCAiJENPTkZJR19GSUxFIikiCkJBQ0tFTkQ9IiQoanNvbl9zdHIgYmFja2VuZCAiJENPTkZJR19GSUxFIikiCkFQSV9LRVk9IiQoanNvbl9zdHIgYXBpX2tleSAiJENPTkZJR19GSUxFIikiCkxJTktfTU9ERT0iJChqc29uX3N0ciBsaW5rX21vZGUgIiRDT05GSUdfRklMRSIpIgpTQ09QRT0iJChqc29uX3N0ciBzY29wZSAiJENPTkZJR19GSUxFIikiCkNMSUVOVFM9IiQoc2VkIC1uICdzLy4qImNsaWVudHMiW1s6c3BhY2U6XV0qOltbOnNwYWNlOl1dKlxbXChbXl1dKlwpXF0uKi9cMS9wJyAiJENPTkZJR19GSUxFIiB8IHRyICcsJyAnICcgfCB0ciAtZCAnIicgfCB0ciAtcyAnICcpIgoKWyAtbiAiJENMSUVOVFMiIF0gfHwgQ0xJRU5UUz0iYWdlbnRzIgpbIC1uICIkTElOS19NT0RFIiBdIHx8IExJTktfTU9ERT0iY29weSIKWyAtbiAiJFNDT1BFIiBdIHx8IFNDT1BFPSJwcm9qZWN0IgoKaWYgWyAteiAiJEJBQ0tFTkQiIF07IHRoZW4KICBbIC1uICIkQkFTRV9VUkwiIF0gfHwgZGllICJjb25maWcgaGFzIG5vIGJhY2tlbmQgYW5kIG5vIGJhc2VfdXJsIgogIEJBQ0tFTkQ9IiQoY3VybCAtZnNTTCAiJEJBU0VfVVJML2FwaS9jb25maWciIHwgc2VkIC1uICdzLy4qImJhY2tlbmQiW1s6c3BhY2U6XV0qOltbOnNwYWNlOl1dKiJcKFteIl0qXCkiLiovXDEvcCcgfCBoZWFkIC1uMSkiCiAgWyAtbiAiJEJBQ0tFTkQiIF0gfHwgZGllICJjb3VsZCBub3QgcmVzb2x2ZSBiYWNrZW5kIGZyb20gJEJBU0VfVVJML2FwaS9jb25maWciCmZpCkJBQ0tFTkQ9IiQocHJpbnRmICclcycgIiRCQUNLRU5EIiB8IHNlZCAnczovKiQ6OicpIgoKUk9PVD0iJFBXRCIKWyAiJFNDT1BFIiA9ICJob21lIiBdICYmIFJPT1Q9IiRIT01FIgoKIyBkaXJfZm9yIENMSUVOVF9JRCAtPiByZWxhdGl2ZSBza2lsbCBkaXIgKGdlbmVyYXRlZCBmcm9tIHRoZSBtYW5pZmVzdCBpbiB0aGUKIyByZWFsIGJ1aWxkOyBhIHJlcHJlc2VudGF0aXZlIHN1YnNldCBoZXJlIGZvciBsb2NhbCB0ZXN0aW5nKS4KZGlyX2ZvcigpIHsKICBjYXNlICIkMSIgaW4KX19ESVJfRk9SX0NBU0VTX18KICAgICopIHJldHVybiAxIDs7CiAgZXNhYwp9CgojIE9uZSAiLi4vIiBwZXIgcGF0aCBjb21wb25lbnQgb2YgJDEgKGEgY2xpZW50IGRpciByZWxhdGl2ZSB0byBST09UKSwgc28KIyBzeW1saW5rcyBhcmUgcmVsYXRpdmUgYW5kIHN1cnZpdmUgYmVpbmcgY29tbWl0dGVkIGFuZCBjaGVja2VkIG91dCBlbHNld2hlcmUuCnJlbF90b19yb290KCkgewogIF91cD0iIjsgX29sZGlmcz0kSUZTOyBJRlM9LwogIGZvciBfc2VnIGluICQxOyBkbyBbIC1uICIkX3NlZyIgXSAmJiBfdXA9Ii4uLyRfdXAiOyBkb25lCiAgSUZTPSRfb2xkaWZzOyBwcmludGYgJyVzJyAiJF91cCIKfQoKYXBpKCkgeyAjIGFwaSA8TUVUSE9EPiA8cGF0aD4gW2V4dHJhIGN1cmwgYXJncy4uLl0gLT4gYm9keSBvbiBzdGRvdXQKICBtPSIkMSI7IHA9IiQyIjsgc2hpZnQgMgogIGN1cmwgLWZzUyAtWCAiJG0iICIkQkFDS0VORCRwIiAtSCAieC1hcGkta2V5OiBCZWFyZXIgJEFQSV9LRVkiICIkQCIKfQoKbWV0YV92ZXJzaW9uKCkgeyAjIG1ldGFfdmVyc2lvbiA8bmFtZT4gLT4gY3VycmVudF92ZXJzaW9uIGZyb20gcmVnaXN0cnkKICBhcGkgR0VUICIvc2tpbGxzL3JlZ2lzdHJ5LyQxIiAyPi9kZXYvbnVsbCBcCiAgICB8IHNlZCAtbiAncy8uKiJjdXJyZW50X3ZlcnNpb24iW1s6c3BhY2U6XV0qOltbOnNwYWNlOl1dKlwoWzAtOV1bMC05XSpcKS4qL1wxL3AnIHwgaGVhZCAtbjEKfQoKX21hbmFnZWQoKSB7ICMgX21hbmFnZWQgPGRpcj4gLT4gMCBpZiBzYWZlIHRvIG92ZXJ3cml0ZSAob3VycyBvciBzeW1saW5rIG9yIGFic2VudCkKICBkPSIkMSIKICBpZiBbIC1lICIkZCIgXSAmJiBbICEgLUwgIiRkIiBdICYmIFsgISAtZiAiJGQvLmltcC1za2lsbC5qc29uIiBdOyB0aGVuCiAgICBpbmZvICJza2lwICRkIChleGlzdHMsIG5vdCBtYW5hZ2VkIGJ5IGltcCkiOyByZXR1cm4gMQogIGZpCiAgcmV0dXJuIDAKfQoKX3B1dF9yZWFsKCkgeyAjIF9wdXRfcmVhbCA8ZGVzdD4gPHNyY2Rpcj4gPG1hcmtlci1qc29uPgogIF9tYW5hZ2VkICIkMSIgfHwgcmV0dXJuIDAKICBybSAtcmYgIiQxIjsgbWtkaXIgLXAgIiQxIjsgY3AgLVIgIiQyLy4iICIkMS8iCiAgcHJpbnRmICclc1xuJyAiJDMiID4gIiQxLy5pbXAtc2tpbGwuanNvbiIKfQoKcGxhY2Vfc2tpbGwoKSB7ICMgcGxhY2Vfc2tpbGwgPG5hbWU+IDxzcmNkaXI+IDx2ZXJzaW9uPgogIHBuYW1lPSIkMSI7IHBzcmM9IiQyIjsgcHZlcj0iJHszOi0xfSIKICBtYXJrZXI9J3sgIm5hbWUiOiAiJyIkcG5hbWUiJyIsICJ2ZXJzaW9uIjogJyIkcHZlciInLCAic291cmNlIjogIiciJEJBQ0tFTkQiJyIgfScKICBjYW5vbj0iJFJPT1QvLmFnZW50cy9za2lsbHMvJHBuYW1lIgogIFsgIiRMSU5LX01PREUiID0gInN5bWxpbmsiIF0gJiYgX3B1dF9yZWFsICIkY2Fub24iICIkcHNyYyIgIiRtYXJrZXIiCiAgZm9yIGlkIGluICRDTElFTlRTOyBkbwogICAgZD0iJChkaXJfZm9yICIkaWQiKSIgfHwgeyBpbmZvICJ1bmtub3duIGNsaWVudDogJGlkIjsgY29udGludWU7IH0KICAgIHBhcmVudD0iJFJPT1QvJGQiOyBkZXN0PSIkcGFyZW50LyRwbmFtZSIKICAgIGlmIFsgIiRMSU5LX01PREUiID0gInN5bWxpbmsiIF0gJiYgWyAiJGlkIiAhPSAiYWdlbnRzIiBdOyB0aGVuCiAgICAgIF9tYW5hZ2VkICIkZGVzdCIgfHwgY29udGludWUKICAgICAgbWtkaXIgLXAgIiRwYXJlbnQiOyBybSAtcmYgIiRkZXN0IgogICAgICByZWw9IiQocmVsX3RvX3Jvb3QgIiRkIikuYWdlbnRzL3NraWxscy8kcG5hbWUiCiAgICAgIGlmIGxuIC1zICIkcmVsIiAiJGRlc3QiIDI+L2Rldi9udWxsOyB0aGVuCiAgICAgICAgaW5mbyAibGlua2VkICRkZXN0IC0+ICRyZWwiCiAgICAgIGVsc2UKICAgICAgICBpbmZvICJzeW1saW5rIHVuc3VwcG9ydGVkIGF0ICRkZXN0OyBjb3B5aW5nIgogICAgICAgIF9wdXRfcmVhbCAiJGRlc3QiICIkcHNyYyIgIiRtYXJrZXIiCiAgICAgIGZpCiAgICBlbGlmIFsgIiRMSU5LX01PREUiID0gImNvcHkiIF07IHRoZW4KICAgICAgX3B1dF9yZWFsICIkZGVzdCIgIiRwc3JjIiAiJG1hcmtlciIKICAgIGZpCiAgICAjIHN5bWxpbmsgKyBhZ2VudHM6IGFscmVhZHkgcGxhY2VkIGFzIHRoZSBjYW5vbmljYWwgc3RvcmUgYWJvdmUuCiAgZG9uZQp9CgppbnN0YWxsZWRfbmFtZXMoKSB7ICMgdW5pcXVlIHNraWxsIG5hbWVzIHRoYXQgY2Fycnkgb3VyIG1hcmtlciB1bmRlciBST09UCiAgeyBmaW5kICIkUk9PVC8uYWdlbnRzL3NraWxscyIgLW1heGRlcHRoIDIgLW5hbWUgLmltcC1za2lsbC5qc29uIDI+L2Rldi9udWxsCiAgICBmb3IgaWQgaW4gJENMSUVOVFM7IGRvCiAgICAgIGQ9IiQoZGlyX2ZvciAiJGlkIikiIHx8IGNvbnRpbnVlCiAgICAgIGZpbmQgIiRST09ULyRkIiAtbWF4ZGVwdGggMiAtbmFtZSAuaW1wLXNraWxsLmpzb24gMj4vZGV2L251bGwKICAgIGRvbmUKICB9IHwgd2hpbGUgcmVhZCAtciBtOyBkbyBqc29uX3N0ciBuYW1lICIkbSI7IGRvbmUgfCBzb3J0IC11Cn0KCm1hcmtlcl92ZXJzaW9uKCkgeyAjIG1hcmtlcl92ZXJzaW9uIDxuYW1lPgogIGZvciBiYXNlIGluICIkUk9PVC8uYWdlbnRzL3NraWxscyI7IGRvCiAgICBbIC1mICIkYmFzZS8kMS8uaW1wLXNraWxsLmpzb24iIF0gJiYgeyBqc29uX3N0ciB2ZXJzaW9uICIkYmFzZS8kMS8uaW1wLXNraWxsLmpzb24iOyByZXR1cm47IH0KICBkb25lCiAgZm9yIGlkIGluICRDTElFTlRTOyBkbwogICAgZD0iJChkaXJfZm9yICIkaWQiKSIgfHwgY29udGludWUKICAgIGY9IiRST09ULyRkLyQxLy5pbXAtc2tpbGwuanNvbiIKICAgIFsgLWYgIiRmIiBdICYmIHsganNvbl9zdHIgdmVyc2lvbiAiJGYiOyByZXR1cm47IH0KICBkb25lCn0KCmRvX2luc3RhbGwoKSB7ICMgZG9faW5zdGFsbCA8bmFtZT4KICBuYW1lPSIkMSIKICBUTVA9IiQobWt0ZW1wIC1kKSIKICBhcGkgR0VUICIvc2tpbGxzL3JlZ2lzdHJ5LyRuYW1lL2Rvd25sb2FkIiAtLW91dHB1dCAiJFRNUC9za2lsbC56aXAiIFwKICAgIHx8IHsgcm0gLXJmICIkVE1QIjsgZGllICJkb3dubG9hZCBmYWlsZWQgZm9yICckbmFtZScgKDQwMyA9IG5vIGFjY2VzcywgNDA0ID0gdW5rbm93bikiOyB9CiAgbWtkaXIgLXAgIiRUTVAveCIKICB1bnppcCAtcSAiJFRNUC9za2lsbC56aXAiIC1kICIkVE1QL3giIHx8IHsgcm0gLXJmICIkVE1QIjsgZGllICJiYWQgYXJjaGl2ZSBmb3IgJyRuYW1lJyI7IH0KICBzcmM9IiQoZmluZCAiJFRNUC94IiAtbWluZGVwdGggMSAtbWF4ZGVwdGggMSAtdHlwZSBkIHwgaGVhZCAtbjEpIgogIFsgLW4gIiRzcmMiIF0gfHwgeyBybSAtcmYgIiRUTVAiOyBkaWUgInVuZXhwZWN0ZWQgYXJjaGl2ZSBsYXlvdXQgZm9yICckbmFtZSciOyB9CiAgdmVyPSIkKG1ldGFfdmVyc2lvbiAiJG5hbWUiKSIKICBwbGFjZV9za2lsbCAiJG5hbWUiICIkc3JjIiAiJHt2ZXI6LTF9IgogIHJtIC1yZiAiJFRNUCIKICBpbmZvICJpbnN0YWxsZWQgJG5hbWUgKHYke3ZlcjotMX0pIFskTElOS19NT0RFXSBpbnRvOiAkQ0xJRU5UUyIKfQoKdXNhZ2UoKSB7CiAgY2F0ID4mMiA8PEVPRgppbXAg4oCUIHNraWxsIGxpYnJhcnkgaGVscGVyCiAgaW1wIGxpc3QgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0IHNraWxscyB5b3UgY2FuIGFjY2VzcyAoSlNPTikKICBpbXAgZ2V0IDxuYW1lPiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3cgb25lIHNraWxsJ3MgbWV0YWRhdGEgKEpTT04pCiAgaW1wIGluc3RhbGwgPG5hbWU+ICAgICAgICAgICAgICAgICAgICAgICBpbnN0YWxsL3JlZnJlc2ggYSBza2lsbCBpbnRvIHlvdXIgYWdlbnQgY2xpZW50cwogIGltcCB1cGRhdGUgWzxuYW1lPl0gICAgICAgICAgICAgICAgICAgICAgdXBkYXRlIGluc3RhbGxlZCBza2lsbHMgKGFsbCwgb3Igb25lKSB0byBsYXRlc3QKICBpbXAgcHVibGlzaCA8bmFtZT4gPGRpcj4gPHB1YmxpY3xwcml2YXRlPiBwdWJsaXNoIGEgbG9jYWwgc2tpbGwgZm9sZGVyIGFzIDxuYW1lPgogIGltcCBjb25maWcgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvdyByZXNvbHZlZCBiYWNrZW5kIC8gc2NvcGUgLyBjbGllbnRzIChubyBzZWNyZXRzKQpFT0YKfQoKY21kPSIkezE6LWhlbHB9IgpbICQjIC1ndCAwIF0gJiYgc2hpZnQgfHwgdHJ1ZQoKY2FzZSAiJGNtZCIgaW4KICBsaXN0KSBhcGkgR0VUICIvc2tpbGxzL3JlZ2lzdHJ5IiA7OwogIGdldCkgWyAkIyAtZ2UgMSBdIHx8IGRpZSAidXNhZ2U6IGltcCBnZXQgPG5hbWU+IjsgYXBpIEdFVCAiL3NraWxscy9yZWdpc3RyeS8kMSIgOzsKICBpbnN0YWxsKSBbICQjIC1nZSAxIF0gfHwgZGllICJ1c2FnZTogaW1wIGluc3RhbGwgPG5hbWU+IjsgZG9faW5zdGFsbCAiJDEiIDs7CiAgdXBkYXRlKQogICAgaWYgWyAkIyAtZ2UgMSBdOyB0aGVuIG5hbWVzPSIkMSI7IGVsc2UgbmFtZXM9IiQoaW5zdGFsbGVkX25hbWVzKSI7IGZpCiAgICBbIC1uICIkbmFtZXMiIF0gfHwgeyBpbmZvICJubyBpbXAtbWFuYWdlZCBza2lsbHMgZm91bmQgdW5kZXIgJFJPT1QiOyBleGl0IDA7IH0KICAgIGZvciBuIGluICRuYW1lczsgZG8KICAgICAgY3VyPSIkKG1hcmtlcl92ZXJzaW9uICIkbiIpIgogICAgICBsYXRlc3Q9IiQobWV0YV92ZXJzaW9uICIkbiIpIgogICAgICBbIC1uICIkbGF0ZXN0IiBdIHx8IHsgaW5mbyAic2tpcCAkbiAobm90IGluIHJlZ2lzdHJ5KSI7IGNvbnRpbnVlOyB9CiAgICAgIGlmIFsgLXogIiRjdXIiIF0gfHwgWyAiJGxhdGVzdCIgLWd0ICIkY3VyIiBdIDI+L2Rldi9udWxsOyB0aGVuCiAgICAgICAgaW5mbyAidXBkYXRpbmcgJG46IHYke2N1cjotP30gLT4gdiRsYXRlc3QiOyBkb19pbnN0YWxsICIkbiIKICAgICAgZWxzZQogICAgICAgIGluZm8gIiRuIHVwIHRvIGRhdGUgKHYkY3VyKSIKICAgICAgZmkKICAgIGRvbmUKICAgIDs7CiAgcHVibGlzaCkKICAgIFsgJCMgLWdlIDMgXSB8fCBkaWUgInVzYWdlOiBpbXAgcHVibGlzaCA8bmFtZT4gPGRpcj4gPHB1YmxpY3xwcml2YXRlPiIKICAgIG5hbWU9IiQxIjsgZm9sZGVyPSIkMiI7IHZpc2liaWxpdHk9IiQzIgogICAgY2FzZSAiJHZpc2liaWxpdHkiIGluCiAgICAgIHB1YmxpY3xwcml2YXRlKSA7OwogICAgICAqKSBkaWUgInZpc2liaWxpdHkgbXVzdCBiZSAncHVibGljJyBvciAncHJpdmF0ZScgKGFzayB0aGUgdXNlciB3aGljaCB0aGV5IHdhbnQpIiA7OwogICAgZXNhYwogICAgWyAtZCAiJGZvbGRlciIgXSB8fCBkaWUgIm5vIHN1Y2ggZm9sZGVyOiAkZm9sZGVyIgogICAgWyAtZiAiJGZvbGRlci9TS0lMTC5tZCIgXSB8fCBkaWUgIiRmb2xkZXIgaGFzIG5vIFNLSUxMLm1kIGF0IGl0cyByb290IgogICAgY29tbWFuZCAtdiB6aXAgPi9kZXYvbnVsbCAyPiYxIHx8IGRpZSAidGhlICd6aXAnIGNvbW1hbmQgaXMgcmVxdWlyZWQgdG8gcHVibGlzaCIKICAgIFRNUD0iJChta3RlbXAgLWQpIgogICAgKCBjZCAiJChkaXJuYW1lICIkZm9sZGVyIikiIFwKICAgICAgJiYgemlwIC1xIC1yIC1YICIkVE1QL3NraWxsLnppcCIgIiQoYmFzZW5hbWUgIiRmb2xkZXIiKSIgXAogICAgICAgICAgIC14ICcqLy5pbXAtc2tpbGwuanNvbicgJyovLmdpdC8qJyAnKi5EU19TdG9yZScgJyovX19NQUNPU1gvKicgKSBcCiAgICAgIHx8IHsgcm0gLXJmICIkVE1QIjsgZGllICJjb3VsZCBub3QgemlwICRmb2xkZXIiOyB9CiAgICBhcGkgUE9TVCAiL3NraWxscy9yZWdpc3RyeS8kbmFtZT92aXNpYmlsaXR5PSR2aXNpYmlsaXR5IiAtSCAiQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi96aXAiIFwKICAgICAgLS1kYXRhLWJpbmFyeSBAIiRUTVAvc2tpbGwuemlwIiBcCiAgICAgIHx8IHsgcm0gLXJmICIkVE1QIjsgZGllICJwdWJsaXNoIGZhaWxlZCAoNDAzID0gbm8gd3JpdGUgYWNjZXNzLCA0MDkgPSBuYW1lIHRha2VuKSI7IH0KICAgIHJtIC1yZiAiJFRNUCIKICAgIGluZm8gInB1Ymxpc2hlZCAkbmFtZSAoJHZpc2liaWxpdHkpIgogICAgOzsKICBjb25maWcpCiAgICBwcmludGYgJ2JhY2tlbmQ9JXNcbnNjb3BlPSVzXG5saW5rX21vZGU9JXNcbmNsaWVudHM9JXNcbmFwaV9rZXk9JXNcbicgXAogICAgICAiJEJBQ0tFTkQiICIkU0NPUEUiICIkTElOS19NT0RFIiAiJENMSUVOVFMiIFwKICAgICAgIiQoWyAtbiAiJEFQSV9LRVkiIF0gJiYgZWNobyBzZXQgfHwgZWNobyBNSVNTSU5HKSIKICAgIDs7CiAgaGVscHwtLWhlbHB8LWgpIHVzYWdlIDs7CiAgKikgaW5mbyAidW5rbm93biBjb21tYW5kOiAkY21kIjsgdXNhZ2U7IGV4aXQgMiA7Owplc2FjCg==";
|
|
13890
13823
|
|
|
13891
|
-
// src/skills/bootstrap/
|
|
13824
|
+
// src/skills/bootstrap/imp-skills.ts
|
|
13892
13825
|
var BOOTSTRAP_CLIENTS_JSON = JSON.stringify(CLIENT_MANIFEST, null, 2);
|
|
13893
13826
|
var DIR_FOR_CASES = CLIENT_MANIFEST.map(
|
|
13894
13827
|
(c) => ` ${c.id}) printf '%s' '${c.dir}' ;;`
|
|
13895
13828
|
).join("\n");
|
|
13896
|
-
var
|
|
13829
|
+
var BOOTSTRAP_IMP_SH = Buffer.from(IMP_SH_B64, "base64").toString("utf8").replace("__DIR_FOR_CASES__", DIR_FOR_CASES);
|
|
13897
13830
|
var BOOTSTRAP_SKILL_MD = `---
|
|
13898
|
-
name:
|
|
13899
|
-
description: Install, update, and publish skills from this
|
|
13831
|
+
name: imp-skills
|
|
13832
|
+
description: Install, update, and publish skills from this instance's central skill library. Use when the user asks to install a skill, get the latest version of a skill, list IMP skills, or publish a skill to IMP.
|
|
13900
13833
|
---
|
|
13901
13834
|
|
|
13902
|
-
#
|
|
13835
|
+
# IMP Skills
|
|
13903
13836
|
|
|
13904
|
-
Bridge to the
|
|
13837
|
+
Bridge to the IMP central skill library. **All operations go through the
|
|
13905
13838
|
bundled helper script \u2014 do not hand-write curl or copy files yourself.** The
|
|
13906
13839
|
script reads the API token from config (keeping it out of this conversation) and
|
|
13907
13840
|
handles the multi-client copy/symlink fan-out deterministically.
|
|
13908
13841
|
|
|
13909
13842
|
## The helper
|
|
13910
13843
|
|
|
13911
|
-
Run the script next to this file, \`scripts/
|
|
13844
|
+
Run the script next to this file, \`scripts/imp\`, with \`sh\` and the absolute
|
|
13912
13845
|
path of this skill's directory:
|
|
13913
13846
|
|
|
13914
13847
|
\`\`\`
|
|
13915
|
-
sh "<this-skill-dir>/scripts/
|
|
13848
|
+
sh "<this-skill-dir>/scripts/imp" <command>
|
|
13916
13849
|
\`\`\`
|
|
13917
13850
|
|
|
13918
13851
|
Commands:
|
|
@@ -13920,25 +13853,27 @@ Commands:
|
|
|
13920
13853
|
- \`get <name>\` \u2014 one skill's metadata (JSON)
|
|
13921
13854
|
- \`install <name>\` \u2014 install/refresh a skill into the user's agent clients
|
|
13922
13855
|
- \`update [<name>]\` \u2014 update every installed skill, or just \`<name>\`, to latest
|
|
13923
|
-
- \`publish <name> <folder>\` \u2014 publish a local skill folder as \`<name>\`
|
|
13856
|
+
- \`publish <name> <folder> <public|private>\` \u2014 publish a local skill folder as \`<name>\`
|
|
13924
13857
|
- \`config\` \u2014 show resolved backend / scope / clients (prints no secrets)
|
|
13925
13858
|
|
|
13926
13859
|
The token, backend URL, target clients, copy-vs-symlink mode, and scope all come
|
|
13927
|
-
from \`~/.config/
|
|
13860
|
+
from \`~/.config/imp/skills.json\` (written by the installer). Never print the
|
|
13928
13861
|
\`api_key\` or read it into your reply \u2014 the script uses it internally.
|
|
13929
13862
|
|
|
13930
13863
|
## Requests \u2192 commands
|
|
13931
13864
|
|
|
13932
|
-
- "list / search skills" \u2192 \`
|
|
13933
|
-
- "install skill X" / "add the X skill" \u2192 \`
|
|
13934
|
-
- "update / get the latest version [of X]" \u2192 \`
|
|
13865
|
+
- "list / search skills" \u2192 \`imp list\`, then filter the JSON for the user.
|
|
13866
|
+
- "install skill X" / "add the X skill" \u2192 \`imp install X\`.
|
|
13867
|
+
- "update / get the latest version [of X]" \u2192 \`imp update [X]\`.
|
|
13935
13868
|
- "publish / upload this skill as X" \u2192 confirm the target name with the user; for
|
|
13936
|
-
an existing skill run \`
|
|
13937
|
-
|
|
13869
|
+
an existing skill run \`imp get X\` first and confirm a new version is intended.
|
|
13870
|
+
For a NEW skill you MUST ask the user whether it should be \`public\` (visible
|
|
13871
|
+
to everyone on the instance) or \`private\` (only them) \u2014 never pick a
|
|
13872
|
+
visibility yourself; then \`imp publish X <folder> <public|private>\`.
|
|
13938
13873
|
|
|
13939
13874
|
## Not configured yet?
|
|
13940
13875
|
|
|
13941
|
-
If \`
|
|
13876
|
+
If \`imp config\` reports it's not configured (or \`~/.config/imp/skills.json\`
|
|
13942
13877
|
is missing), tell the user to run the installer \u2014 it sets everything up
|
|
13943
13878
|
interactively (base URL, API key, target clients, copy/symlink):
|
|
13944
13879
|
|
|
@@ -13946,14 +13881,15 @@ interactively (base URL, API key, target clients, copy/symlink):
|
|
|
13946
13881
|
curl -fsSL <base_url>/api/skills/install.sh | sh
|
|
13947
13882
|
\`\`\`
|
|
13948
13883
|
|
|
13949
|
-
\`<base_url>\` is their
|
|
13950
|
-
create an API key at \`<base_url>/token\`.
|
|
13884
|
+
\`<base_url>\` is their instance's frontend URL (e.g. https://ai.open.de). They
|
|
13885
|
+
can create an API key at \`<base_url>/token\`.
|
|
13951
13886
|
|
|
13952
13887
|
## Errors
|
|
13953
13888
|
|
|
13954
13889
|
- install: \`403\` = no access to that skill; \`404\` = unknown name.
|
|
13955
|
-
- publish: \`
|
|
13956
|
-
|
|
13890
|
+
- publish: \`400\` = missing/invalid visibility (new skills need public|private);
|
|
13891
|
+
\`403\` = you can see it but lack write access; \`409\` = the name is taken by a
|
|
13892
|
+
skill you can't access.
|
|
13957
13893
|
`;
|
|
13958
13894
|
|
|
13959
13895
|
// src/exulu/routes.ts
|
|
@@ -16262,9 +16198,9 @@ ${style.markdown}` : params.prompt;
|
|
|
16262
16198
|
app.get("/skills/agent/bootstrap", async (_req, res) => {
|
|
16263
16199
|
try {
|
|
16264
16200
|
const zip = new JSZip3();
|
|
16265
|
-
zip.file("
|
|
16266
|
-
zip.file("
|
|
16267
|
-
zip.file("
|
|
16201
|
+
zip.file("imp-skills/SKILL.md", BOOTSTRAP_SKILL_MD);
|
|
16202
|
+
zip.file("imp-skills/references/clients.json", BOOTSTRAP_CLIENTS_JSON);
|
|
16203
|
+
zip.file("imp-skills/scripts/imp", BOOTSTRAP_IMP_SH, {
|
|
16268
16204
|
unixPermissions: 493
|
|
16269
16205
|
});
|
|
16270
16206
|
const buffer = await zip.generateAsync({
|
|
@@ -16272,7 +16208,7 @@ ${style.markdown}` : params.prompt;
|
|
|
16272
16208
|
platform: "UNIX"
|
|
16273
16209
|
});
|
|
16274
16210
|
res.setHeader("Content-Type", "application/zip");
|
|
16275
|
-
res.setHeader("Content-Disposition", 'attachment; filename="
|
|
16211
|
+
res.setHeader("Content-Disposition", 'attachment; filename="imp-skills.zip"');
|
|
16276
16212
|
res.send(buffer);
|
|
16277
16213
|
} catch (err) {
|
|
16278
16214
|
console.error("[SKILLS] Failed to build bootstrap zip", err);
|
|
@@ -16393,6 +16329,13 @@ ${style.markdown}` : params.prompt;
|
|
|
16393
16329
|
return;
|
|
16394
16330
|
}
|
|
16395
16331
|
}
|
|
16332
|
+
const visibility = req.query.visibility;
|
|
16333
|
+
if (visibility !== "public" && visibility !== "private") {
|
|
16334
|
+
res.status(400).json({
|
|
16335
|
+
detail: "Missing or invalid 'visibility'. New skills require ?visibility=public or ?visibility=private \u2014 ask the user which they want."
|
|
16336
|
+
});
|
|
16337
|
+
return;
|
|
16338
|
+
}
|
|
16396
16339
|
const meta = await parseSkillFrontmatter(bytes);
|
|
16397
16340
|
const skillId = randomUUID3();
|
|
16398
16341
|
try {
|
|
@@ -16419,7 +16362,7 @@ ${style.markdown}` : params.prompt;
|
|
|
16419
16362
|
history: JSON.stringify([
|
|
16420
16363
|
{ version: 1, created_at: (/* @__PURE__ */ new Date()).toISOString(), label: "Published from agent" }
|
|
16421
16364
|
]),
|
|
16422
|
-
rights_mode:
|
|
16365
|
+
rights_mode: visibility,
|
|
16423
16366
|
created_by: authResult.user.id
|
|
16424
16367
|
});
|
|
16425
16368
|
} catch (err) {
|
|
@@ -21297,15 +21240,15 @@ var execute = async ({ contexts }) => {
|
|
|
21297
21240
|
};
|
|
21298
21241
|
|
|
21299
21242
|
// src/exulu/litellm/db-init.ts
|
|
21300
|
-
import { existsSync as
|
|
21243
|
+
import { existsSync as existsSync5, readdirSync } from "fs";
|
|
21301
21244
|
import { resolve as resolve3 } from "path";
|
|
21302
21245
|
import { spawnSync } from "child_process";
|
|
21303
21246
|
import { Client } from "pg";
|
|
21304
21247
|
|
|
21305
21248
|
// src/exulu/litellm/db-setup-check.ts
|
|
21306
|
-
import { readFileSync as readFileSync4, existsSync as
|
|
21249
|
+
import { readFileSync as readFileSync4, existsSync as existsSync4 } from "fs";
|
|
21307
21250
|
var readLiteLLMDatabaseUrl = (configPath) => {
|
|
21308
|
-
if (!
|
|
21251
|
+
if (!existsSync4(configPath)) return void 0;
|
|
21309
21252
|
const text = readFileSync4(configPath, "utf8");
|
|
21310
21253
|
const match = text.match(
|
|
21311
21254
|
/^\s*database_url:\s*["']?([^"'\n#]+?)["']?\s*(#.*)?$/m
|
|
@@ -21508,7 +21451,7 @@ var initLiteLLMDatabase = async (packageRoot) => {
|
|
|
21508
21451
|
const venvBin = resolve3(packageRoot, "ee/python/.venv/bin");
|
|
21509
21452
|
const prismaCli = resolve3(venvBin, "prisma");
|
|
21510
21453
|
const venvLibDir = resolve3(packageRoot, "ee/python/.venv/lib");
|
|
21511
|
-
const pythonVersionDir =
|
|
21454
|
+
const pythonVersionDir = existsSync5(venvLibDir) ? readdirSync(venvLibDir).find((entry) => /^python3\.\d+$/.test(entry)) : void 0;
|
|
21512
21455
|
if (!pythonVersionDir) {
|
|
21513
21456
|
warn2([
|
|
21514
21457
|
`Could not find a python3.* directory under ${venvLibDir}.`,
|
|
@@ -21523,7 +21466,7 @@ var initLiteLLMDatabase = async (packageRoot) => {
|
|
|
21523
21466
|
"site-packages/litellm/proxy"
|
|
21524
21467
|
);
|
|
21525
21468
|
const schemaPath = resolve3(litellmProxyDir, "schema.prisma");
|
|
21526
|
-
if (!
|
|
21469
|
+
if (!existsSync5(prismaCli)) {
|
|
21527
21470
|
warn2([
|
|
21528
21471
|
`Prisma CLI not found at ${prismaCli}.`,
|
|
21529
21472
|
`Run \`npm run python:setup\` to create the venv and install prisma.`,
|
|
@@ -21531,7 +21474,7 @@ var initLiteLLMDatabase = async (packageRoot) => {
|
|
|
21531
21474
|
]);
|
|
21532
21475
|
return;
|
|
21533
21476
|
}
|
|
21534
|
-
if (!
|
|
21477
|
+
if (!existsSync5(schemaPath)) {
|
|
21535
21478
|
warn2([
|
|
21536
21479
|
`LiteLLM Prisma schema not found at ${schemaPath}.`,
|
|
21537
21480
|
`Re-run \`npm run python:setup\`. Skipping LiteLLM database setup.`
|
|
@@ -22114,20 +22057,20 @@ import WordExtractor from "word-extractor";
|
|
|
22114
22057
|
import { parseOfficeAsync as parseOfficeAsync2 } from "officeparser";
|
|
22115
22058
|
|
|
22116
22059
|
// src/utils/python-executor.ts
|
|
22117
|
-
import { exec
|
|
22118
|
-
import { promisify
|
|
22119
|
-
import { resolve as resolve4, join
|
|
22120
|
-
import { existsSync as
|
|
22060
|
+
import { exec } from "child_process";
|
|
22061
|
+
import { promisify } from "util";
|
|
22062
|
+
import { resolve as resolve4, join, dirname } from "path";
|
|
22063
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
|
|
22121
22064
|
import { fileURLToPath } from "url";
|
|
22122
|
-
var
|
|
22065
|
+
var execAsync = promisify(exec);
|
|
22123
22066
|
function getPackageRoot2() {
|
|
22124
22067
|
const currentFile = fileURLToPath(import.meta.url);
|
|
22125
22068
|
let currentDir = dirname(currentFile);
|
|
22126
22069
|
let attempts = 0;
|
|
22127
22070
|
const maxAttempts = 10;
|
|
22128
22071
|
while (attempts < maxAttempts) {
|
|
22129
|
-
const packageJsonPath =
|
|
22130
|
-
if (
|
|
22072
|
+
const packageJsonPath = join(currentDir, "package.json");
|
|
22073
|
+
if (existsSync6(packageJsonPath)) {
|
|
22131
22074
|
try {
|
|
22132
22075
|
const packageJson = JSON.parse(readFileSync5(packageJsonPath, "utf-8"));
|
|
22133
22076
|
if (packageJson.name === "@exulu/backend") {
|
|
@@ -22168,7 +22111,7 @@ function getVenvPath(packageRoot) {
|
|
|
22168
22111
|
}
|
|
22169
22112
|
function getPythonExecutable(packageRoot) {
|
|
22170
22113
|
const venvPath = getVenvPath(packageRoot);
|
|
22171
|
-
return
|
|
22114
|
+
return join(venvPath, "bin", "python");
|
|
22172
22115
|
}
|
|
22173
22116
|
async function validatePythonEnvironmentForExecution(packageRoot) {
|
|
22174
22117
|
const validation = await validatePythonEnvironment(packageRoot);
|
|
@@ -22191,7 +22134,7 @@ async function executePythonScript(config) {
|
|
|
22191
22134
|
await validatePythonEnvironmentForExecution(packageRoot);
|
|
22192
22135
|
}
|
|
22193
22136
|
const resolvedScriptPath = resolve4(packageRoot, scriptPath);
|
|
22194
|
-
if (!
|
|
22137
|
+
if (!existsSync6(resolvedScriptPath)) {
|
|
22195
22138
|
throw new PythonExecutionError(
|
|
22196
22139
|
`Python script not found: ${resolvedScriptPath}`,
|
|
22197
22140
|
"",
|
|
@@ -22205,7 +22148,7 @@ async function executePythonScript(config) {
|
|
|
22205
22148
|
});
|
|
22206
22149
|
const command = `${pythonExecutable} "${resolvedScriptPath}" ${quotedArgs.join(" ")}`;
|
|
22207
22150
|
try {
|
|
22208
|
-
const { stdout, stderr } = await
|
|
22151
|
+
const { stdout, stderr } = await execAsync(command, {
|
|
22209
22152
|
cwd,
|
|
22210
22153
|
timeout,
|
|
22211
22154
|
env: {
|