@moxxy/cli 0.5.3 → 0.5.5
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/bin.js +58 -189
- package/dist/bin.js.map +1 -1
- package/package.json +2 -2
package/dist/bin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { z as z$1, defineProvider, definePlugin, defineTool, MoxxyError, writeFileAtomic, asTurnId, defineMode, asPluginId, defineChannel, defineTunnelProvider, createMutex, defineWorkflowExecutor, toFriendlyError, estimateTextTokens, classifyHttpStatus, createStuckLoopDetector, runCompactionIfNeeded, runElisionIfNeeded, collectProviderStream, usageEventFields, isContextOverflowError, buildSystemPromptWithSkills, projectMessages, defineCompactor, defineCacheStrategy, denyByDefaultResolver, createAllowListResolver, zodToJsonSchema,
|
|
3
|
+
import { z as z$1, defineProvider, definePlugin, defineTool, MoxxyError, writeFileAtomic, asTurnId, defineMode, asPluginId, defineChannel, defineTunnelProvider, createMutex, defineWorkflowExecutor, toFriendlyError, estimateTextTokens, classifyHttpStatus, createStuckLoopDetector, runCompactionIfNeeded, runElisionIfNeeded, collectProviderStream, usageEventFields, isContextOverflowError, emitRequestsAndDetectStuck, executeToolUses, buildSystemPromptWithSkills, projectMessages, defineCompactor, defineCacheStrategy, denyByDefaultResolver, createAllowListResolver, zodToJsonSchema, runSingleShotTurn, bearerTokenMatches, estimateContextTokens, readRequestBody, moxxyPath, defineEmbedder, skillFrontmatterSchema, asSkillId, getInstallHint, moxxyHome, defineTranscriber, summarizeTokensByModel, migrateModeName, createDeferredPermissionResolver, classifyNetworkError, addModelTotals, ISOLATION_RANK, moxxyPackageSchema, defineCommand, createCallbackResolver, autoAllowResolver, asSessionId, asToolCallId, defineViewRenderer, DEFAULT_VIEW_TAGS, evaluateToolRule, summarizeSessionTokensFromEvents, asEventId } from '@moxxy/sdk';
|
|
4
4
|
import * as fs37 from 'fs';
|
|
5
5
|
import fs37__default, { existsSync, promises, ReadStream, readFileSync, statSync, readdirSync, mkdirSync, writeFileSync, unlinkSync, watch, createReadStream } from 'fs';
|
|
6
6
|
import * as path3 from 'path';
|
|
@@ -105578,7 +105578,11 @@ async function* runDefaultMode(ctx) {
|
|
|
105578
105578
|
continue;
|
|
105579
105579
|
}
|
|
105580
105580
|
reactiveCompactions = 0;
|
|
105581
|
-
const stuck = yield* emitRequestsAndDetectStuck(ctx, toolUses, detector
|
|
105581
|
+
const stuck = yield* emitRequestsAndDetectStuck(ctx, toolUses, detector, {
|
|
105582
|
+
abortedResultMessage: "default mode loop aborted (stuck pattern) before this call ran",
|
|
105583
|
+
nearHint: "against the same target (only volatile args like maxBytes varied)",
|
|
105584
|
+
fatalMessage: ({ toolName, count, how }) => `default mode loop aborted \u2014 detected stuck pattern: tool "${toolName}" called ${count} times ${how}. The model is likely looping on the same call; reset or rephrase.`
|
|
105585
|
+
});
|
|
105582
105586
|
if (stuck)
|
|
105583
105587
|
return;
|
|
105584
105588
|
if (text || stopReason === "end_turn" || toolUses.length === 0) {
|
|
@@ -105606,79 +105610,6 @@ async function* runDefaultMode(ctx) {
|
|
|
105606
105610
|
message: `default mode loop exceeded maxIterations (${maxIterations})`
|
|
105607
105611
|
});
|
|
105608
105612
|
}
|
|
105609
|
-
async function* emitRequestsAndDetectStuck(ctx, toolUses, detector) {
|
|
105610
|
-
const emitted = [];
|
|
105611
|
-
for (const t2 of toolUses) {
|
|
105612
|
-
yield await ctx.emit({
|
|
105613
|
-
type: "tool_call_requested",
|
|
105614
|
-
sessionId: ctx.sessionId,
|
|
105615
|
-
turnId: ctx.turnId,
|
|
105616
|
-
source: "model",
|
|
105617
|
-
callId: asToolCallId(t2.id),
|
|
105618
|
-
name: t2.name,
|
|
105619
|
-
input: t2.input
|
|
105620
|
-
});
|
|
105621
|
-
emitted.push(t2);
|
|
105622
|
-
const sig = detector.record(t2.name, t2.input);
|
|
105623
|
-
if (sig.stuck) {
|
|
105624
|
-
for (const r2 of emitted) {
|
|
105625
|
-
yield await ctx.emit({
|
|
105626
|
-
type: "tool_result",
|
|
105627
|
-
sessionId: ctx.sessionId,
|
|
105628
|
-
turnId: ctx.turnId,
|
|
105629
|
-
source: "tool",
|
|
105630
|
-
callId: asToolCallId(r2.id),
|
|
105631
|
-
ok: false,
|
|
105632
|
-
error: { kind: "aborted", message: "default mode loop aborted (stuck pattern) before this call ran" }
|
|
105633
|
-
});
|
|
105634
|
-
}
|
|
105635
|
-
const how = sig.kind === "near" ? "against the same target (only volatile args like maxBytes varied)" : "with identical input";
|
|
105636
|
-
yield await ctx.emit({
|
|
105637
|
-
type: "error",
|
|
105638
|
-
sessionId: ctx.sessionId,
|
|
105639
|
-
turnId: ctx.turnId,
|
|
105640
|
-
source: "system",
|
|
105641
|
-
kind: "fatal",
|
|
105642
|
-
message: `default mode loop aborted \u2014 detected stuck pattern: tool "${t2.name}" called ${sig.count} times ${how}. The model is likely looping on the same call; reset or rephrase.`
|
|
105643
|
-
});
|
|
105644
|
-
return true;
|
|
105645
|
-
}
|
|
105646
|
-
}
|
|
105647
|
-
return false;
|
|
105648
|
-
}
|
|
105649
|
-
async function* executeToolUses(ctx, toolUses, iteration) {
|
|
105650
|
-
const unresolved = new Set(toolUses.map((t2) => t2.id));
|
|
105651
|
-
for (const t2 of toolUses) {
|
|
105652
|
-
if (ctx.signal.aborted) {
|
|
105653
|
-
for (const orphanId of unresolved) {
|
|
105654
|
-
yield await ctx.emit({
|
|
105655
|
-
type: "tool_result",
|
|
105656
|
-
sessionId: ctx.sessionId,
|
|
105657
|
-
turnId: ctx.turnId,
|
|
105658
|
-
source: "tool",
|
|
105659
|
-
callId: asToolCallId(orphanId),
|
|
105660
|
-
ok: false,
|
|
105661
|
-
error: { kind: "aborted", message: "turn aborted before tool ran" }
|
|
105662
|
-
});
|
|
105663
|
-
}
|
|
105664
|
-
unresolved.clear();
|
|
105665
|
-
yield await ctx.emit({
|
|
105666
|
-
type: "abort",
|
|
105667
|
-
sessionId: ctx.sessionId,
|
|
105668
|
-
turnId: ctx.turnId,
|
|
105669
|
-
source: "system",
|
|
105670
|
-
reason: "signal aborted during tool execution"
|
|
105671
|
-
});
|
|
105672
|
-
return true;
|
|
105673
|
-
}
|
|
105674
|
-
try {
|
|
105675
|
-
yield* dispatchToolCall(ctx, t2, iteration);
|
|
105676
|
-
} finally {
|
|
105677
|
-
unresolved.delete(t2.id);
|
|
105678
|
-
}
|
|
105679
|
-
}
|
|
105680
|
-
return false;
|
|
105681
|
-
}
|
|
105682
105613
|
function buildMessages(ctx) {
|
|
105683
105614
|
const systemPrompt = buildSystemPromptWithSkills(ctx.systemPrompt, ctx.skills.list());
|
|
105684
105615
|
return projectMessages(ctx, { ...systemPrompt ? { systemPrompt } : {} });
|
|
@@ -105914,7 +105845,22 @@ async function* runGoalMode(ctx) {
|
|
|
105914
105845
|
});
|
|
105915
105846
|
return;
|
|
105916
105847
|
}
|
|
105917
|
-
const stuck = yield*
|
|
105848
|
+
const stuck = yield* emitRequestsAndDetectStuck(ctx, toolUses, detector, {
|
|
105849
|
+
abortedResultMessage: "goal mode aborted (stuck pattern) before this call ran",
|
|
105850
|
+
nearHint: "against the same target (only volatile args varied)",
|
|
105851
|
+
extraOnStuck: ({ toolName, count, kind: kind3 }) => [
|
|
105852
|
+
{
|
|
105853
|
+
type: "plugin_event",
|
|
105854
|
+
sessionId: ctx.sessionId,
|
|
105855
|
+
turnId: ctx.turnId,
|
|
105856
|
+
source: "plugin",
|
|
105857
|
+
pluginId: GOAL_PLUGIN_ID,
|
|
105858
|
+
subtype: "goal_stuck",
|
|
105859
|
+
payload: { tool: toolName, count, kind: kind3 }
|
|
105860
|
+
}
|
|
105861
|
+
],
|
|
105862
|
+
fatalMessage: ({ toolName, count, how }) => `goal mode aborted \u2014 stuck pattern: tool "${toolName}" called ${count} times ${how}. The model is looping on the same call; send another message to redirect it.`
|
|
105863
|
+
});
|
|
105918
105864
|
if (stuck)
|
|
105919
105865
|
return;
|
|
105920
105866
|
if (text || stopReason === "end_turn" || toolUses.length === 0) {
|
|
@@ -105952,7 +105898,7 @@ async function* runGoalMode(ctx) {
|
|
|
105952
105898
|
continue;
|
|
105953
105899
|
}
|
|
105954
105900
|
noop3 = 0;
|
|
105955
|
-
const exited = yield*
|
|
105901
|
+
const exited = yield* executeToolUses(goalCtx, toolUses, iteration);
|
|
105956
105902
|
if (exited)
|
|
105957
105903
|
return;
|
|
105958
105904
|
const terminal = detectGoalTerminal(ctx.log.slice(), toolUses);
|
|
@@ -106030,88 +105976,6 @@ function composeSystemPrompts(user, layer) {
|
|
|
106030
105976
|
|
|
106031
105977
|
${user}`;
|
|
106032
105978
|
}
|
|
106033
|
-
async function* emitRequestsAndDetectStuck2(ctx, toolUses, detector) {
|
|
106034
|
-
const emitted = [];
|
|
106035
|
-
for (const t2 of toolUses) {
|
|
106036
|
-
yield await ctx.emit({
|
|
106037
|
-
type: "tool_call_requested",
|
|
106038
|
-
sessionId: ctx.sessionId,
|
|
106039
|
-
turnId: ctx.turnId,
|
|
106040
|
-
source: "model",
|
|
106041
|
-
callId: asToolCallId(t2.id),
|
|
106042
|
-
name: t2.name,
|
|
106043
|
-
input: t2.input
|
|
106044
|
-
});
|
|
106045
|
-
emitted.push(t2);
|
|
106046
|
-
const sig = detector.record(t2.name, t2.input);
|
|
106047
|
-
if (sig.stuck) {
|
|
106048
|
-
for (const r2 of emitted) {
|
|
106049
|
-
yield await ctx.emit({
|
|
106050
|
-
type: "tool_result",
|
|
106051
|
-
sessionId: ctx.sessionId,
|
|
106052
|
-
turnId: ctx.turnId,
|
|
106053
|
-
source: "tool",
|
|
106054
|
-
callId: asToolCallId(r2.id),
|
|
106055
|
-
ok: false,
|
|
106056
|
-
error: { kind: "aborted", message: "goal mode aborted (stuck pattern) before this call ran" }
|
|
106057
|
-
});
|
|
106058
|
-
}
|
|
106059
|
-
const how = sig.kind === "near" ? "against the same target (only volatile args varied)" : "with identical input";
|
|
106060
|
-
yield await ctx.emit({
|
|
106061
|
-
type: "plugin_event",
|
|
106062
|
-
sessionId: ctx.sessionId,
|
|
106063
|
-
turnId: ctx.turnId,
|
|
106064
|
-
source: "plugin",
|
|
106065
|
-
pluginId: GOAL_PLUGIN_ID,
|
|
106066
|
-
subtype: "goal_stuck",
|
|
106067
|
-
payload: { tool: t2.name, count: sig.count, kind: sig.kind }
|
|
106068
|
-
});
|
|
106069
|
-
yield await ctx.emit({
|
|
106070
|
-
type: "error",
|
|
106071
|
-
sessionId: ctx.sessionId,
|
|
106072
|
-
turnId: ctx.turnId,
|
|
106073
|
-
source: "system",
|
|
106074
|
-
kind: "fatal",
|
|
106075
|
-
message: `goal mode aborted \u2014 stuck pattern: tool "${t2.name}" called ${sig.count} times ${how}. The model is looping on the same call; send another message to redirect it.`
|
|
106076
|
-
});
|
|
106077
|
-
return true;
|
|
106078
|
-
}
|
|
106079
|
-
}
|
|
106080
|
-
return false;
|
|
106081
|
-
}
|
|
106082
|
-
async function* executeToolUses2(ctx, toolUses, iteration) {
|
|
106083
|
-
const unresolved = new Set(toolUses.map((t2) => t2.id));
|
|
106084
|
-
for (const t2 of toolUses) {
|
|
106085
|
-
if (ctx.signal.aborted) {
|
|
106086
|
-
for (const orphanId of unresolved) {
|
|
106087
|
-
yield await ctx.emit({
|
|
106088
|
-
type: "tool_result",
|
|
106089
|
-
sessionId: ctx.sessionId,
|
|
106090
|
-
turnId: ctx.turnId,
|
|
106091
|
-
source: "tool",
|
|
106092
|
-
callId: asToolCallId(orphanId),
|
|
106093
|
-
ok: false,
|
|
106094
|
-
error: { kind: "aborted", message: "turn aborted before tool ran" }
|
|
106095
|
-
});
|
|
106096
|
-
}
|
|
106097
|
-
unresolved.clear();
|
|
106098
|
-
yield await ctx.emit({
|
|
106099
|
-
type: "abort",
|
|
106100
|
-
sessionId: ctx.sessionId,
|
|
106101
|
-
turnId: ctx.turnId,
|
|
106102
|
-
source: "system",
|
|
106103
|
-
reason: "signal aborted during tool execution"
|
|
106104
|
-
});
|
|
106105
|
-
return true;
|
|
106106
|
-
}
|
|
106107
|
-
try {
|
|
106108
|
-
yield* dispatchToolCall(ctx, t2, iteration);
|
|
106109
|
-
} finally {
|
|
106110
|
-
unresolved.delete(t2.id);
|
|
106111
|
-
}
|
|
106112
|
-
}
|
|
106113
|
-
return false;
|
|
106114
|
-
}
|
|
106115
105979
|
|
|
106116
105980
|
// ../mode-goal/dist/index.js
|
|
106117
105981
|
var goalMode = defineMode({
|
|
@@ -111353,28 +111217,54 @@ function buildSubagentsPlugin(opts = {}) {
|
|
|
111353
111217
|
});
|
|
111354
111218
|
}
|
|
111355
111219
|
buildSubagentsPlugin();
|
|
111220
|
+
|
|
111221
|
+
// ../plugin-plugins-admin/dist/shared.js
|
|
111222
|
+
var NPM_NAME_RE = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
|
|
111223
|
+
function assertSafeNpmSpec(spec) {
|
|
111224
|
+
const trimmed = spec.trim();
|
|
111225
|
+
if (trimmed.length === 0) {
|
|
111226
|
+
throw new Error("plugin spec must be a non-empty package name, git spec, or path");
|
|
111227
|
+
}
|
|
111228
|
+
if (trimmed.startsWith("-")) {
|
|
111229
|
+
throw new Error(`refusing plugin spec "${spec}": leading "-" would be parsed by npm as an option, not a package`);
|
|
111230
|
+
}
|
|
111231
|
+
return trimmed;
|
|
111232
|
+
}
|
|
111233
|
+
function diffSnapshot2(before, after) {
|
|
111234
|
+
const out = {};
|
|
111235
|
+
for (const key of ["tools", "agents", "providers", "modes", "compactors", "channels"]) {
|
|
111236
|
+
const b3 = new Set(before[key]);
|
|
111237
|
+
const added = after[key].filter((n2) => !b3.has(n2));
|
|
111238
|
+
if (added.length > 0)
|
|
111239
|
+
out[key] = added;
|
|
111240
|
+
}
|
|
111241
|
+
return out;
|
|
111242
|
+
}
|
|
111243
|
+
|
|
111244
|
+
// ../plugin-plugins-admin/dist/install.js
|
|
111356
111245
|
function userPluginsDir() {
|
|
111357
111246
|
return moxxyPath("plugins");
|
|
111358
111247
|
}
|
|
111359
|
-
var NPM_NAME_RE = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
|
|
111360
111248
|
var VERSION_RE = /^[0-9a-z.~^*<=>-]+$/i;
|
|
111361
111249
|
async function installPluginPackage(opts) {
|
|
111250
|
+
const spec = assertSafeNpmSpec(opts.packageName);
|
|
111362
111251
|
const dir = userPluginsDir();
|
|
111363
111252
|
await ensurePackageJson(dir);
|
|
111364
|
-
const { exitCode, stderr } = await runNpm(["install", "--prefix", dir, "--no-fund", "--no-audit", "--save",
|
|
111253
|
+
const { exitCode, stderr } = await runNpm(["install", "--prefix", dir, "--no-fund", "--no-audit", "--save", spec], opts.signal);
|
|
111365
111254
|
if (exitCode !== 0) {
|
|
111366
111255
|
throw new Error(`npm install failed (exit ${exitCode}): ${truncate9(stderr, 400)}`);
|
|
111367
111256
|
}
|
|
111368
|
-
return { installed:
|
|
111257
|
+
return { installed: spec, dir };
|
|
111369
111258
|
}
|
|
111370
111259
|
async function removePluginPackage(opts) {
|
|
111260
|
+
const spec = assertSafeNpmSpec(opts.packageName);
|
|
111371
111261
|
const dir = userPluginsDir();
|
|
111372
111262
|
await ensurePackageJson(dir);
|
|
111373
|
-
const { exitCode, stderr } = await runNpm(["uninstall", "--prefix", dir, "--no-fund", "--no-audit", "--save",
|
|
111263
|
+
const { exitCode, stderr } = await runNpm(["uninstall", "--prefix", dir, "--no-fund", "--no-audit", "--save", spec], opts.signal);
|
|
111374
111264
|
if (exitCode !== 0) {
|
|
111375
111265
|
throw new Error(`npm uninstall failed (exit ${exitCode}): ${truncate9(stderr, 400)}`);
|
|
111376
111266
|
}
|
|
111377
|
-
return { removed:
|
|
111267
|
+
return { removed: spec, dir };
|
|
111378
111268
|
}
|
|
111379
111269
|
function buildInstallPluginTool(deps) {
|
|
111380
111270
|
return defineTool({
|
|
@@ -111491,26 +111381,15 @@ function runNpm(args, signal) {
|
|
|
111491
111381
|
});
|
|
111492
111382
|
});
|
|
111493
111383
|
}
|
|
111494
|
-
function diffSnapshot2(before, after) {
|
|
111495
|
-
const out = {};
|
|
111496
|
-
for (const key of ["tools", "agents", "providers", "modes", "compactors", "channels"]) {
|
|
111497
|
-
const b3 = new Set(before[key]);
|
|
111498
|
-
const added = after[key].filter((n2) => !b3.has(n2));
|
|
111499
|
-
if (added.length > 0)
|
|
111500
|
-
out[key] = added;
|
|
111501
|
-
}
|
|
111502
|
-
return out;
|
|
111503
|
-
}
|
|
111504
111384
|
function truncate9(s2, n2) {
|
|
111505
111385
|
return s2.length <= n2 ? s2 : s2.slice(0, n2 - 1) + "\u2026";
|
|
111506
111386
|
}
|
|
111507
|
-
var NPM_NAME_RE2 = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
|
|
111508
111387
|
function buildDisablePluginTool(deps) {
|
|
111509
111388
|
return defineTool({
|
|
111510
111389
|
name: "disable_plugin",
|
|
111511
111390
|
description: "Disable (unplug) a registered moxxy plugin \u2014 a default builtin or an installed one \u2014 by package name. Persists `plugins[<name>].enabled=false` to ~/.moxxy/config.yaml and unloads it from the running session, so its tools / agents / providers / modes / channels disappear immediately and it stays off across restarts. Reverse with enable_plugin. Use when the user wants to turn a plugin off without uninstalling it.",
|
|
111512
111391
|
inputSchema: z$1.object({
|
|
111513
|
-
packageName: z$1.string().min(1).refine((s2) =>
|
|
111392
|
+
packageName: z$1.string().min(1).refine((s2) => NPM_NAME_RE.test(s2), {
|
|
111514
111393
|
message: "must be a valid moxxy package name (e.g. @moxxy/plugin-browser)"
|
|
111515
111394
|
}).describe("Plugin package name to disable, e.g. @moxxy/plugin-browser.")
|
|
111516
111395
|
}),
|
|
@@ -111519,7 +111398,7 @@ function buildDisablePluginTool(deps) {
|
|
|
111519
111398
|
const before = deps.snapshot();
|
|
111520
111399
|
await deps.setEnabled(packageName, false);
|
|
111521
111400
|
const after = deps.snapshot();
|
|
111522
|
-
return { disabled: packageName, unregistered:
|
|
111401
|
+
return { disabled: packageName, unregistered: diffSnapshot2(after, before) };
|
|
111523
111402
|
}
|
|
111524
111403
|
});
|
|
111525
111404
|
}
|
|
@@ -111528,7 +111407,7 @@ function buildEnablePluginTool(deps) {
|
|
|
111528
111407
|
name: "enable_plugin",
|
|
111529
111408
|
description: "Enable (plug back in) a previously-disabled moxxy plugin by package name. Persists `plugins[<name>].enabled=true` to ~/.moxxy/config.yaml and loads it into the running session (re-registering a default or re-discovering an installed plugin), so its contributions reappear immediately. Reverse with disable_plugin. Use when the user wants to turn a disabled plugin back on.",
|
|
111530
111409
|
inputSchema: z$1.object({
|
|
111531
|
-
packageName: z$1.string().min(1).refine((s2) =>
|
|
111410
|
+
packageName: z$1.string().min(1).refine((s2) => NPM_NAME_RE.test(s2), {
|
|
111532
111411
|
message: "must be a valid moxxy package name (e.g. @moxxy/plugin-browser)"
|
|
111533
111412
|
}).describe("Plugin package name to enable, e.g. @moxxy/plugin-browser.")
|
|
111534
111413
|
}),
|
|
@@ -111537,20 +111416,10 @@ function buildEnablePluginTool(deps) {
|
|
|
111537
111416
|
const before = deps.snapshot();
|
|
111538
111417
|
await deps.setEnabled(packageName, true);
|
|
111539
111418
|
const after = deps.snapshot();
|
|
111540
|
-
return { enabled: packageName, registered:
|
|
111419
|
+
return { enabled: packageName, registered: diffSnapshot2(before, after) };
|
|
111541
111420
|
}
|
|
111542
111421
|
});
|
|
111543
111422
|
}
|
|
111544
|
-
function diffSnapshot3(before, after) {
|
|
111545
|
-
const out = {};
|
|
111546
|
-
for (const key of ["tools", "agents", "providers", "modes", "compactors", "channels"]) {
|
|
111547
|
-
const b3 = new Set(before[key]);
|
|
111548
|
-
const added = after[key].filter((n2) => !b3.has(n2));
|
|
111549
|
-
if (added.length > 0)
|
|
111550
|
-
out[key] = added;
|
|
111551
|
-
}
|
|
111552
|
-
return out;
|
|
111553
|
-
}
|
|
111554
111423
|
|
|
111555
111424
|
// ../plugin-plugins-admin/dist/catalog.js
|
|
111556
111425
|
var INSTALLABLE_PLUGIN_CATALOG = [
|