@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 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, asToolCallId, dispatchToolCall, runSingleShotTurn, bearerTokenMatches, estimateContextTokens, readRequestBody, moxxyPath, defineEmbedder, skillFrontmatterSchema, asSkillId, getInstallHint, moxxyHome, defineTranscriber, summarizeTokensByModel, migrateModeName, createDeferredPermissionResolver, classifyNetworkError, addModelTotals, ISOLATION_RANK, moxxyPackageSchema, defineCommand, createCallbackResolver, autoAllowResolver, asSessionId, defineViewRenderer, DEFAULT_VIEW_TAGS, evaluateToolRule, summarizeSessionTokensFromEvents, asEventId } from '@moxxy/sdk';
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* emitRequestsAndDetectStuck2(ctx, toolUses, detector);
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* executeToolUses2(goalCtx, toolUses, iteration);
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", opts.packageName], opts.signal);
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: opts.packageName, dir };
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", opts.packageName], opts.signal);
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: opts.packageName, dir };
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) => NPM_NAME_RE2.test(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: diffSnapshot3(after, before) };
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) => NPM_NAME_RE2.test(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: diffSnapshot3(before, after) };
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 = [