memshell-party-cli 0.8.0 → 0.8.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/index.d.ts CHANGED
@@ -20,7 +20,10 @@ interface ShellConfig {
20
20
  obfuscation?: ObfuscationConfig;
21
21
  obfuscationScope?: "ALL" | "MEMSHELL_INJECTOR" | "INJECTOR" | "MEMSHELL";
22
22
  }
23
+ type ShellToolConfigObject = Record<string, unknown>;
24
+ type ShellToolConfigValue = string | ShellToolConfigObject;
23
25
  interface ShellToolConfig {
26
+ [key: string]: ShellToolConfigValue | undefined;
24
27
  shellClassName?: string;
25
28
  pass?: string;
26
29
  key?: string;
@@ -156,17 +159,39 @@ interface CommandConfigVO {
156
159
  }
157
160
  interface ToolConfigParam {
158
161
  name: string;
159
- type: "string" | "enum";
162
+ type: "string" | "enum" | "object";
160
163
  options: string[];
161
164
  group?: string;
162
165
  label?: string;
163
166
  placeholder?: string;
167
+ ui?: RemoteSelectUiHint;
164
168
  }
165
169
  interface ToolConfigDescriptor {
166
170
  tool: string;
167
171
  params: ToolConfigParam[];
168
172
  }
169
173
  type ObfuscationOption = Record<string, unknown>;
174
+ interface RemoteSelectUiHint {
175
+ kind: "remote-select";
176
+ urlQueryParam: string;
177
+ itemsPath: string;
178
+ labelPath: string;
179
+ valuePath?: string;
180
+ required: boolean;
181
+ }
182
+ interface PluginDescriptor {
183
+ jarFileName: string;
184
+ name: string;
185
+ version?: string | null;
186
+ author?: string | null;
187
+ description?: string | null;
188
+ homepage?: string | null;
189
+ license?: string | null;
190
+ source?: string | null;
191
+ spiServices: string[];
192
+ loaded: boolean;
193
+ loadError?: string | null;
194
+ }
170
195
  interface VersionInfo {
171
196
  currentVersion: string;
172
197
  latestVersion: string;
@@ -211,6 +236,7 @@ declare class MemPartyClient {
211
236
  getObfuscationOptions(): Promise<ObfuscationOption[]>;
212
237
  getProbeResponseServers(): Promise<string[]>;
213
238
  getVersion(): Promise<VersionInfo>;
239
+ getPlugins(): Promise<PluginDescriptor[]>;
214
240
  generateMemShell(req: MemShellGenerateRequest): Promise<MemShellGenerateResponse>;
215
241
  private getGenerationApiVersion;
216
242
  generateProbe(req: ProbeShellGenerateRequest): Promise<ProbeShellGenerateResponse>;
@@ -238,6 +264,8 @@ interface MemShellOptions {
238
264
  obfuscationOptions?: Record<string, unknown>;
239
265
  obfuscationScope?: "ALL" | "MEMSHELL_INJECTOR" | "INJECTOR" | "MEMSHELL";
240
266
  shellClassName?: string;
267
+ shellToolConfig?: Record<string, ShellToolConfigValue>;
268
+ shellToolParams?: ToolConfigParam[];
241
269
  godzillaPass?: string;
242
270
  godzillaKey?: string;
243
271
  commandParamName?: string;
@@ -333,6 +361,19 @@ declare const JDK_VERSIONS: Record<string, number>;
333
361
  */
334
362
  declare function resolveJreVersion(input: string | number | undefined): number | undefined;
335
363
 
364
+ declare function toolConfigForTool(configs: ToolConfigDescriptor[], tool: string): ToolConfigDescriptor | undefined;
365
+ declare function parseShellToolConfig(assignments: string[] | undefined, params: ToolConfigParam[] | undefined): Record<string, ShellToolConfigValue>;
366
+ declare function parseToolConfigFile(source: string, params: ToolConfigParam[] | undefined): Record<string, ShellToolConfigValue>;
367
+ declare function validateRequiredRemoteOptions(config: Record<string, ShellToolConfigValue>, params: ToolConfigParam[] | undefined): void;
368
+ interface RemoteOption {
369
+ label: string;
370
+ value: ShellToolConfigValue;
371
+ }
372
+ declare function readRemotePath(value: unknown, path: string): unknown;
373
+ declare function normalizeRemoteOptions(payload: unknown, hint: RemoteSelectUiHint, objectMode: boolean): RemoteOption[];
374
+ declare function validateRemoteOptionsUrl(value: string): string;
375
+ declare function fetchRemoteOptions(sourceUrl: string, hint: RemoteSelectUiHint, objectMode: boolean, fetchImpl?: typeof fetch, signal?: AbortSignal): Promise<RemoteOption[]>;
376
+
336
377
  type OpCategory = "gen" | "probe" | "connect" | "exec" | "download" | "upload" | "save" | "note" | "remove";
337
378
  interface OpLogEntry {
338
379
  /** ISO timestamp. */
@@ -828,4 +869,4 @@ declare function testSuo5(url: string, options?: Suo5ConnectOptions): Promise<Co
828
869
 
829
870
  declare const CLI_VERSION: string;
830
871
 
831
- export { ApiError, type ApiErrorResponse, type BehinderConnectOptions, type BuildDeps, type BytecodeResult, type BytecodeTransformRequest, type BytecodeTransformResponse, CLI_VERSION, type CommandConfigVO, type CommonConnectOptions, type ConnectTestResult, type ConnectTool, type ConnectionFlags, type CustomBuildInput, type CustomBuildResult, DEFAULT_API_URL, ENV_VAR, type ExecResult, type FetchLike, type FilterTemplateOptions, type GenerateClient, type GodzillaExecOptions, type InjectorConfig, type InstallSkillOptions, JDK_VERSIONS, LEGACY_CIPHER, type MainConfig, MemPartyClient, type MemPartyClientOptions, type MemShellGenerateRequest, type MemShellGenerateResponse, type MemShellOptions, type MemShellResult, type MimicCipher, OUTPUT_LIMIT, type ObfuscationConfig, type ObfuscationOption, type OpCategory, type OpFilter, type OpLogEntry, type OutputOptions, type OutputResult, type PackerOption, type PackerTree, type ProbeConfig, type ProbeContent, type ProbeContentConfig, type ProbeMethod, type ProbeOptions, type ProbeShellGenerateRequest, type ProbeShellGenerateResponse, type ProbeShellResult, type ResolvedConnection, SKILL_NAME, type ServerConfig, type ShellConfig, type ShellInput, type ShellToolConfig, type SkillInstallResult, type SkillScope, type StoredProject, type StoredShell, type Suo5ConnectOptions, type Suo5Mode, type ToolConfigDescriptor, type ToolConfigParam, type VersionInfo, autoSaveShell, buildCustomMemshell, buildMemShellRequest, buildProbeRequest, createMcpServer, defaultClassName, deriveMarkers, emitPayload, execBehinder, execGodzilla, formatOp, getProject, hasJavac, installSkill, listProjects, logOp, marshalFrameBase64, marshalSuo5Map, opLogPath, profileSecretFields, readOps, removeProject, removeShell, renderCryptoProbe, renderFilterJava, resolveApiUrl, resolveCipher, resolveConnection, resolveJreVersion, saveProjectMeta, saveShell, saveShellMeta, shouldDecode, skillSourceDir, skillTargetDir, startMcpStdio, targetStorePath, testBehinder, testGodzilla, testSuo5, truncateOutput, unmarshalFrameBase64, unmarshalSuo5Map };
872
+ export { ApiError, type ApiErrorResponse, type BehinderConnectOptions, type BuildDeps, type BytecodeResult, type BytecodeTransformRequest, type BytecodeTransformResponse, CLI_VERSION, type CommandConfigVO, type CommonConnectOptions, type ConnectTestResult, type ConnectTool, type ConnectionFlags, type CustomBuildInput, type CustomBuildResult, DEFAULT_API_URL, ENV_VAR, type ExecResult, type FetchLike, type FilterTemplateOptions, type GenerateClient, type GodzillaExecOptions, type InjectorConfig, type InstallSkillOptions, JDK_VERSIONS, LEGACY_CIPHER, type MainConfig, MemPartyClient, type MemPartyClientOptions, type MemShellGenerateRequest, type MemShellGenerateResponse, type MemShellOptions, type MemShellResult, type MimicCipher, OUTPUT_LIMIT, type ObfuscationConfig, type ObfuscationOption, type OpCategory, type OpFilter, type OpLogEntry, type OutputOptions, type OutputResult, type PackerOption, type PackerTree, type PluginDescriptor, type ProbeConfig, type ProbeContent, type ProbeContentConfig, type ProbeMethod, type ProbeOptions, type ProbeShellGenerateRequest, type ProbeShellGenerateResponse, type ProbeShellResult, type RemoteOption, type RemoteSelectUiHint, type ResolvedConnection, SKILL_NAME, type ServerConfig, type ShellConfig, type ShellInput, type ShellToolConfig, type ShellToolConfigObject, type ShellToolConfigValue, type SkillInstallResult, type SkillScope, type StoredProject, type StoredShell, type Suo5ConnectOptions, type Suo5Mode, type ToolConfigDescriptor, type ToolConfigParam, type VersionInfo, autoSaveShell, buildCustomMemshell, buildMemShellRequest, buildProbeRequest, createMcpServer, defaultClassName, deriveMarkers, emitPayload, execBehinder, execGodzilla, fetchRemoteOptions, formatOp, getProject, hasJavac, installSkill, listProjects, logOp, marshalFrameBase64, marshalSuo5Map, normalizeRemoteOptions, opLogPath, parseShellToolConfig, parseToolConfigFile, profileSecretFields, readOps, readRemotePath, removeProject, removeShell, renderCryptoProbe, renderFilterJava, resolveApiUrl, resolveCipher, resolveConnection, resolveJreVersion, saveProjectMeta, saveShell, saveShellMeta, shouldDecode, skillSourceDir, skillTargetDir, startMcpStdio, targetStorePath, testBehinder, testGodzilla, testSuo5, toolConfigForTool, truncateOutput, unmarshalFrameBase64, unmarshalSuo5Map, validateRemoteOptionsUrl, validateRequiredRemoteOptions };
package/dist/index.js CHANGED
@@ -83,6 +83,14 @@ var MemPartyClient = class {
83
83
  getVersion() {
84
84
  return this.request("GET", "/api/version");
85
85
  }
86
+ async getPlugins() {
87
+ try {
88
+ return await this.request("GET", "/api/plugins");
89
+ } catch (err) {
90
+ if (err instanceof ApiError && err.status === 404) return [];
91
+ throw err;
92
+ }
93
+ }
86
94
  // ---------- generation ----------
87
95
  async generateMemShell(req) {
88
96
  const apiVersion = await this.getGenerationApiVersion();
@@ -204,6 +212,127 @@ function toLegacyMemShellRequest(req) {
204
212
  // src/core/request-builder.ts
205
213
  import { randomInt } from "crypto";
206
214
 
215
+ // src/core/shell-tool-config.ts
216
+ function toolConfigForTool(configs, tool) {
217
+ return configs.find((config) => config.tool === tool);
218
+ }
219
+ function parseShellToolConfig(assignments, params) {
220
+ const result = {};
221
+ for (const assignment of assignments ?? []) {
222
+ const separator = assignment.indexOf("=");
223
+ if (separator <= 0) {
224
+ throw new Error(`Invalid --tool-option "${assignment}". Expected name=value.`);
225
+ }
226
+ const name = assignment.slice(0, separator).trim();
227
+ const rawValue = assignment.slice(separator + 1);
228
+ if (!name) throw new Error(`Invalid --tool-option "${assignment}". Expected name=value.`);
229
+ const param = params?.find((candidate) => candidate.name === name);
230
+ if (params !== void 0 && param === void 0) {
231
+ throw new Error(
232
+ `Unknown shell tool option "${name}". Available options: ${params.map((item) => item.name).join(", ") || "(none)"}.`
233
+ );
234
+ }
235
+ if (param?.type === "object") {
236
+ result[name] = parseJsonObject(rawValue, `--tool-option ${name}`);
237
+ } else if (rawValue.startsWith("{")) {
238
+ result[name] = parseJsonObject(rawValue, `--tool-option ${name}`);
239
+ } else {
240
+ result[name] = rawValue;
241
+ }
242
+ }
243
+ return result;
244
+ }
245
+ function parseToolConfigFile(source, params) {
246
+ const parsed = parseJsonObject(source, "--tool-config");
247
+ const assignments = Object.entries(parsed).map(([name, value]) => {
248
+ if (typeof value === "string") return `${name}=${value}`;
249
+ return `${name}=${JSON.stringify(value)}`;
250
+ });
251
+ return parseShellToolConfig(assignments, params);
252
+ }
253
+ function validateRequiredRemoteOptions(config, params) {
254
+ const missing = (params ?? []).filter((param) => param.ui?.kind === "remote-select" && param.ui.required).filter((param) => {
255
+ const value = config[param.name];
256
+ return value === void 0 || typeof value === "string" && value.trim() === "";
257
+ }).map((param) => param.name);
258
+ if (missing.length > 0) {
259
+ throw new Error(
260
+ `Missing required remote shell tool option(s): ${missing.join(", ")}. Provide them with --tool-option or --tool-config.`
261
+ );
262
+ }
263
+ }
264
+ function parseJsonObject(source, label) {
265
+ let parsed;
266
+ try {
267
+ parsed = JSON.parse(source);
268
+ } catch (err) {
269
+ throw new Error(`${label} must be valid JSON: ${err.message}`);
270
+ }
271
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
272
+ throw new Error(`${label} must be a JSON object.`);
273
+ }
274
+ return parsed;
275
+ }
276
+ function readRemotePath(value, path) {
277
+ if (!path) return value;
278
+ let current = value;
279
+ for (const segment of path.split(".")) {
280
+ if (!segment || typeof current !== "object" || current === null || Array.isArray(current) || !(segment in current)) {
281
+ return void 0;
282
+ }
283
+ current = current[segment];
284
+ }
285
+ return current;
286
+ }
287
+ function normalizeRemoteOptions(payload, hint, objectMode) {
288
+ const items = readRemotePath(payload, hint.itemsPath);
289
+ if (!Array.isArray(items)) {
290
+ throw new Error("Remote options response does not contain an array at itemsPath.");
291
+ }
292
+ return items.map((item) => {
293
+ if (typeof item !== "object" || item === null || Array.isArray(item)) {
294
+ throw new Error("Remote option items must be objects.");
295
+ }
296
+ const rawLabel = readRemotePath(item, hint.labelPath);
297
+ if (typeof rawLabel !== "string" && typeof rawLabel !== "number") {
298
+ throw new Error("Remote option labels must be strings or numbers.");
299
+ }
300
+ if (objectMode) return { label: String(rawLabel), value: item };
301
+ if (!hint.valuePath) throw new Error("String remote options require valuePath.");
302
+ const rawValue = readRemotePath(item, hint.valuePath);
303
+ if (typeof rawValue !== "string" && typeof rawValue !== "number") {
304
+ throw new Error("Remote option values must be strings or numbers.");
305
+ }
306
+ return { label: String(rawLabel), value: String(rawValue) };
307
+ });
308
+ }
309
+ function validateRemoteOptionsUrl(value) {
310
+ const url = new URL(value);
311
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
312
+ throw new Error("Remote options URL must use HTTP or HTTPS.");
313
+ }
314
+ return url.toString();
315
+ }
316
+ async function fetchRemoteOptions(sourceUrl, hint, objectMode, fetchImpl = globalThis.fetch, signal) {
317
+ const url = validateRemoteOptionsUrl(sourceUrl);
318
+ const response = await fetchImpl(url, {
319
+ method: "GET",
320
+ headers: { Accept: "application/json" },
321
+ redirect: "follow",
322
+ signal
323
+ });
324
+ if (!response.ok) {
325
+ throw new Error(`Remote options request failed (${response.status} ${response.statusText}).`);
326
+ }
327
+ let payload;
328
+ try {
329
+ payload = await response.json();
330
+ } catch {
331
+ throw new Error("Remote options response must be valid JSON.");
332
+ }
333
+ return normalizeRemoteOptions(payload, hint, objectMode);
334
+ }
335
+
207
336
  // src/core/jdk.ts
208
337
  var JDK_VERSIONS = {
209
338
  java6: 50,
@@ -247,6 +376,7 @@ function generateSpringExpressionInjectorClassName() {
247
376
  return `org.springframework.expression.${randomChar(UPPERCASE_LETTERS)}${randomName}Util`;
248
377
  }
249
378
  function buildMemShellRequest(opts) {
379
+ validateRequiredRemoteOptions(opts.shellToolConfig ?? {}, opts.shellToolParams);
250
380
  const injectorClassName = SPRING_GZIP_JDK17_RELATED_PACKERS.has(opts.packer) ? generateSpringExpressionInjectorClassName() : opts.injectorClassName;
251
381
  return {
252
382
  shellConfig: {
@@ -273,7 +403,8 @@ function buildMemShellRequest(opts) {
273
403
  headerValue: opts.headerValue,
274
404
  shellClassBase64: opts.shellClassBase64,
275
405
  encryptor: opts.encryptor,
276
- implementationClass: opts.implementationClass
406
+ implementationClass: opts.implementationClass,
407
+ ...opts.shellToolConfig
277
408
  },
278
409
  injectorConfig: {
279
410
  injectorClassName,
@@ -2692,6 +2823,10 @@ var memShellInput = {
2692
2823
  obfuscationOptions: z.string().optional().describe("obfuscation overrides: key=value, comma-separated"),
2693
2824
  obfuscationScope: z.enum(["ALL", "MEMSHELL_INJECTOR", "INJECTOR", "MEMSHELL"]).optional(),
2694
2825
  shellClassName: z.string().optional(),
2826
+ toolOptions: z.record(z.union([z.string(), z.record(z.unknown())])).optional().describe(
2827
+ "Additional shell-tool fields from list_shell_tool_configs, including plugin fields. String/enum fields use strings; v3.1+ object fields use JSON objects. These override matching built-in convenience arguments."
2828
+ ),
2829
+ toolOptionJson: z.record(z.string()).optional().describe("String-encoded shell-tool fields (name -> value); object fields contain JSON text."),
2695
2830
  godzillaPass: z.string().optional(),
2696
2831
  godzillaKey: z.string().optional(),
2697
2832
  behinderPass: z.string().optional(),
@@ -2966,6 +3101,50 @@ function createMcpServer(client) {
2966
3101
  }
2967
3102
  }
2968
3103
  );
3104
+ server.registerTool(
3105
+ "list_plugins",
3106
+ {
3107
+ title: "List external plugins",
3108
+ description: "List v3.1+ external plugin metadata, SPI services, load status and load errors. An empty list means no plugins or a backend older than v3.1."
3109
+ },
3110
+ async () => {
3111
+ try {
3112
+ return jsonContent(await client.getPlugins());
3113
+ } catch (err) {
3114
+ return errorContent(err);
3115
+ }
3116
+ }
3117
+ );
3118
+ server.registerTool(
3119
+ "list_remote_options",
3120
+ {
3121
+ title: "Resolve remote shell tool options",
3122
+ description: "Fetch and normalize a v3.1 remote-select field. Returns labels and string IDs or complete objects ready to pass to generate_memshell toolOptions.",
3123
+ inputSchema: {
3124
+ tool: z.string(),
3125
+ param: z.string(),
3126
+ url: z.string().optional().describe("Remote HTTP(S) endpoint; falls back to the urlQueryParam environment variable."),
3127
+ object: z.boolean().optional().describe("Override object mode; normally inferred from the field type.")
3128
+ }
3129
+ },
3130
+ async (args) => {
3131
+ try {
3132
+ const descriptor = (await client.getShellToolConfigs()).find((config) => config.tool === args.tool);
3133
+ const param = descriptor?.params.find((candidate) => candidate.name === args.param);
3134
+ if (!param?.ui || param.ui.kind !== "remote-select") {
3135
+ throw new Error(`${args.tool}.${args.param} is not a remote-select shell tool option.`);
3136
+ }
3137
+ const sourceUrl = args.url ?? process.env[param.ui.urlQueryParam];
3138
+ if (!sourceUrl) {
3139
+ throw new Error(`Provide url or set the ${param.ui.urlQueryParam} environment variable.`);
3140
+ }
3141
+ const options = await fetchRemoteOptions(sourceUrl, param.ui, args.object ?? param.type === "object");
3142
+ return jsonContent({ tool: args.tool, param: args.param, sourceUrl, options });
3143
+ } catch (err) {
3144
+ return errorContent(err);
3145
+ }
3146
+ }
3147
+ );
2969
3148
  server.registerTool(
2970
3149
  "list_obfuscation_options",
2971
3150
  {
@@ -3003,9 +3182,21 @@ function createMcpServer(client) {
3003
3182
  "agentArgs requires an Agent* shell type and an AgentJar, AgentJarWithJDKAttacher, or AgentJarWithJREAttacher packer."
3004
3183
  );
3005
3184
  }
3185
+ const hasPluginOptions = args.toolOptions !== void 0 || args.toolOptionJson !== void 0;
3186
+ const toolConfigs = hasPluginOptions ? await client.getShellToolConfigs() : [];
3187
+ const shellToolParams = hasPluginOptions ? toolConfigs.find((config) => config.tool === args.shellTool)?.params : void 0;
3188
+ const shellToolConfig = {
3189
+ ...args.toolOptions,
3190
+ ...parseShellToolConfig(
3191
+ Object.entries(args.toolOptionJson ?? {}).map(([name, value]) => `${name}=${value}`),
3192
+ shellToolParams
3193
+ )
3194
+ };
3006
3195
  const response = await client.generateMemShell(
3007
3196
  buildMemShellRequest({
3008
3197
  ...args,
3198
+ shellToolConfig: hasPluginOptions ? shellToolConfig : void 0,
3199
+ shellToolParams,
3009
3200
  obfuscationOptions: parseObfuscationOptions(args.obfuscationOptions)
3010
3201
  })
3011
3202
  );
@@ -4229,6 +4420,7 @@ export {
4229
4420
  emitPayload,
4230
4421
  execBehinder,
4231
4422
  execGodzilla,
4423
+ fetchRemoteOptions,
4232
4424
  formatOp,
4233
4425
  getProject,
4234
4426
  hasJavac,
@@ -4237,9 +4429,13 @@ export {
4237
4429
  logOp,
4238
4430
  marshalFrameBase64,
4239
4431
  marshalSuo5Map,
4432
+ normalizeRemoteOptions,
4240
4433
  opLogPath,
4434
+ parseShellToolConfig,
4435
+ parseToolConfigFile,
4241
4436
  profileSecretFields,
4242
4437
  readOps,
4438
+ readRemotePath,
4243
4439
  removeProject,
4244
4440
  removeShell,
4245
4441
  renderCryptoProbe,
@@ -4259,8 +4455,11 @@ export {
4259
4455
  testBehinder,
4260
4456
  testGodzilla,
4261
4457
  testSuo5,
4458
+ toolConfigForTool,
4262
4459
  truncateOutput,
4263
4460
  unmarshalFrameBase64,
4264
- unmarshalSuo5Map
4461
+ unmarshalSuo5Map,
4462
+ validateRemoteOptionsUrl,
4463
+ validateRequiredRemoteOptions
4265
4464
  };
4266
4465
  //# sourceMappingURL=index.js.map