@moxxy/cli 0.1.5 → 0.1.6

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
@@ -6,8 +6,8 @@ import fs36__default, { existsSync, promises, ReadStream, readFileSync, statSync
6
6
  import * as path3 from 'path';
7
7
  import path3__default, { basename } from 'path';
8
8
  import { z } from 'zod';
9
- import * as os3 from 'os';
10
- import os3__default, { homedir, userInfo } from 'os';
9
+ import * as os5 from 'os';
10
+ import os5__default, { homedir, userInfo } from 'os';
11
11
  import { createRequire as createRequire$1 } from 'module';
12
12
  import Url, { fileURLToPath, pathToFileURL } from 'url';
13
13
  import Stream, { Readable as Readable$1, PassThrough as PassThrough$2, Stream as Stream$1 } from 'stream';
@@ -774,7 +774,7 @@ async function discoverPlugins(opts) {
774
774
  async function candidateRoots(cwd2) {
775
775
  const out = [];
776
776
  let cursor = path3.resolve(cwd2);
777
- for (let i2 = 0; i2 < 8; i2++) {
777
+ for (let i2 = 0; i2 < MAX_NODE_MODULES_WALK_DEPTH; i2++) {
778
778
  out.push(path3.join(cursor, "node_modules"));
779
779
  const parent = path3.dirname(cursor);
780
780
  if (parent === cursor)
@@ -833,8 +833,10 @@ async function readPluginManifest(packagePath, logger) {
833
833
  ...requirements ? { requirements } : {}
834
834
  };
835
835
  }
836
+ var MAX_NODE_MODULES_WALK_DEPTH;
836
837
  var init_discovery = __esm({
837
838
  "../core/dist/plugins/discovery.js"() {
839
+ MAX_NODE_MODULES_WALK_DEPTH = 8;
838
840
  }
839
841
  });
840
842
 
@@ -1057,7 +1059,7 @@ var init_host = __esm({
1057
1059
  applyPlugin(plugin4, manifest) {
1058
1060
  const toolNames = (plugin4.tools ?? []).map((t2) => t2.name);
1059
1061
  const providerNames = (plugin4.providers ?? []).map((p3) => p3.name);
1060
- const modeNames = (plugin4.modes ?? []).map((l2) => l2.name);
1062
+ const modeNames = (plugin4.modes ?? []).map((m3) => m3.name);
1061
1063
  const compactorNames = (plugin4.compactors ?? []).map((c2) => c2.name);
1062
1064
  const cacheStrategyNames = (plugin4.cacheStrategies ?? []).map((c2) => c2.name);
1063
1065
  const viewRendererNames = (plugin4.viewRenderers ?? []).map((v3) => v3.name);
@@ -1073,8 +1075,8 @@ var init_host = __esm({
1073
1075
  this.opts.tools.register(tool);
1074
1076
  for (const provider of plugin4.providers ?? [])
1075
1077
  this.opts.providers.register(provider);
1076
- for (const loop of plugin4.modes ?? [])
1077
- this.opts.modes.register(loop);
1078
+ for (const mode of plugin4.modes ?? [])
1079
+ this.opts.modes.register(mode);
1078
1080
  for (const compactor of plugin4.compactors ?? [])
1079
1081
  this.opts.compactors.register(compactor);
1080
1082
  for (const cacheStrategy of plugin4.cacheStrategies ?? [])
@@ -1225,7 +1227,7 @@ var ModeRegistry;
1225
1227
  var init_modes = __esm({
1226
1228
  "../core/dist/registries/modes.js"() {
1227
1229
  ModeRegistry = class {
1228
- strategies = /* @__PURE__ */ new Map();
1230
+ modes = /* @__PURE__ */ new Map();
1229
1231
  active = null;
1230
1232
  changeListeners = /* @__PURE__ */ new Set();
1231
1233
  /** Observe active-mode changes — used by the runner to broadcast
@@ -1236,54 +1238,54 @@ var init_modes = __esm({
1236
1238
  return () => this.changeListeners.delete(fn);
1237
1239
  }
1238
1240
  /**
1239
- * Register a strategy. Throws on duplicate — use `replace()` for
1241
+ * Register a mode. Throws on duplicate — use `replace()` for
1240
1242
  * overwrite. Auto-activates on first registration (modes need a default
1241
1243
  * for any session to work).
1242
1244
  */
1243
- register(strategy) {
1244
- if (this.strategies.has(strategy.name)) {
1245
- throw new Error(`Mode already registered: ${strategy.name}`);
1245
+ register(mode) {
1246
+ if (this.modes.has(mode.name)) {
1247
+ throw new Error(`Mode already registered: ${mode.name}`);
1246
1248
  }
1247
- this.strategies.set(strategy.name, strategy);
1249
+ this.modes.set(mode.name, mode);
1248
1250
  if (!this.active)
1249
- this.activate(strategy);
1251
+ this.activate(mode);
1250
1252
  }
1251
- replace(strategy) {
1252
- this.strategies.set(strategy.name, strategy);
1253
+ replace(mode) {
1254
+ this.modes.set(mode.name, mode);
1253
1255
  if (!this.active)
1254
- this.activate(strategy);
1256
+ this.activate(mode);
1255
1257
  }
1256
1258
  /**
1257
- * Remove a strategy. If it was active, the active slot is cleared —
1259
+ * Remove a mode. If it was active, the active slot is cleared —
1258
1260
  * callers must `setActive()` explicitly rather than silently picking
1259
- * some arbitrary "next" strategy.
1261
+ * some arbitrary "next" mode.
1260
1262
  */
1261
1263
  unregister(name) {
1262
- this.strategies.delete(name);
1264
+ this.modes.delete(name);
1263
1265
  if (this.active === name)
1264
1266
  this.active = null;
1265
1267
  }
1266
1268
  list() {
1267
- return [...this.strategies.values()];
1269
+ return [...this.modes.values()];
1268
1270
  }
1269
1271
  setActive(name) {
1270
- const strategy = this.strategies.get(name);
1271
- if (!strategy)
1272
+ const mode = this.modes.get(name);
1273
+ if (!mode)
1272
1274
  throw new Error(`Mode not registered: ${name}`);
1273
- this.activate(strategy);
1275
+ this.activate(mode);
1274
1276
  }
1275
1277
  getActive() {
1276
1278
  if (!this.active)
1277
1279
  throw new Error("No active mode registered.");
1278
- const s2 = this.strategies.get(this.active);
1279
- if (!s2)
1280
+ const mode = this.modes.get(this.active);
1281
+ if (!mode)
1280
1282
  throw new Error(`Active mode missing: ${this.active}`);
1281
- return s2;
1283
+ return mode;
1282
1284
  }
1283
- activate(strategy) {
1284
- if (this.active === strategy.name)
1285
+ activate(mode) {
1286
+ if (this.active === mode.name)
1285
1287
  return;
1286
- this.active = strategy.name;
1288
+ this.active = mode.name;
1287
1289
  for (const fn of this.changeListeners)
1288
1290
  fn();
1289
1291
  }
@@ -2518,7 +2520,7 @@ var init_requirements = __esm({
2518
2520
  return def ? { kind: kind3, name, active: this.opts.transcribers.getActiveName() === name } : null;
2519
2521
  }
2520
2522
  case "mode": {
2521
- const def = this.opts.modes.list().find((l2) => l2.name === name);
2523
+ const def = this.opts.modes.list().find((m3) => m3.name === name);
2522
2524
  return def ? { kind: kind3, name, active: activeModeName(this.opts.modes) === name } : null;
2523
2525
  }
2524
2526
  case "compactor": {
@@ -3016,7 +3018,7 @@ var init_session = __esm({
3016
3018
  }
3017
3019
  });
3018
3020
  function preferencesPath() {
3019
- return path3.join(os3.homedir(), ".moxxy", "preferences.json");
3021
+ return path3.join(os5.homedir(), ".moxxy", "preferences.json");
3020
3022
  }
3021
3023
  async function loadPreferences() {
3022
3024
  try {
@@ -3046,7 +3048,7 @@ var init_preferences = __esm({
3046
3048
  }
3047
3049
  });
3048
3050
  function usageStatsPath() {
3049
- return path3.join(os3.homedir(), ".moxxy", "usage.json");
3051
+ return path3.join(os5.homedir(), ".moxxy", "usage.json");
3050
3052
  }
3051
3053
  function emptyStats() {
3052
3054
  return { version: 1, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), models: {} };
@@ -3215,13 +3217,12 @@ __export(loader_exports, {
3215
3217
  discoverSkills: () => discoverSkills
3216
3218
  });
3217
3219
  async function discoverSkills(opts = {}) {
3218
- const home = os3.homedir();
3219
3220
  const sources = [];
3220
3221
  if (opts.builtinDir)
3221
3222
  sources.push({ dir: opts.builtinDir, scope: "builtin" });
3222
3223
  for (const dir of opts.pluginDirs ?? [])
3223
3224
  sources.push({ dir, scope: "plugin" });
3224
- const userDir = opts.userDir ?? path3.join(home, ".moxxy", "skills");
3225
+ const userDir = opts.userDir ?? defaultUserSkillsDir();
3225
3226
  sources.push({ dir: userDir, scope: "user" });
3226
3227
  if (opts.projectDir)
3227
3228
  sources.push({ dir: opts.projectDir, scope: "project" });
@@ -3277,7 +3278,7 @@ function deriveTriggers(name) {
3277
3278
  return [...out];
3278
3279
  }
3279
3280
  function defaultUserSkillsDir() {
3280
- return path3.join(os3.homedir(), ".moxxy", "skills");
3281
+ return path3.join(os5.homedir(), ".moxxy", "skills");
3281
3282
  }
3282
3283
  function defaultProjectSkillsDir(cwd2) {
3283
3284
  return path3.join(cwd2, ".moxxy", "skills");
@@ -3608,7 +3609,7 @@ var init_selectors = __esm({
3608
3609
  }
3609
3610
  });
3610
3611
  function defaultSessionsDir() {
3611
- return path3.join(os3.homedir(), ".moxxy", "sessions");
3612
+ return path3.join(os5.homedir(), ".moxxy", "sessions");
3612
3613
  }
3613
3614
  async function readIndex(dir = defaultSessionsDir()) {
3614
3615
  const byId = /* @__PURE__ */ new Map();
@@ -51827,7 +51828,7 @@ var init_base = __esm({
51827
51828
  if (isBrowser || !isWindows2) {
51828
51829
  return false;
51829
51830
  }
51830
- const parts = os3__default.release().split(".");
51831
+ const parts = os5__default.release().split(".");
51831
51832
  const major = Number(parts[0]);
51832
51833
  const build2 = Number(parts[2] ?? 0);
51833
51834
  if (major < 10) {
@@ -79892,7 +79893,7 @@ function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
79892
79893
  return min;
79893
79894
  }
79894
79895
  if (V3.platform === "win32") {
79895
- const osRelease = os3__default.release().split(".");
79896
+ const osRelease = os5__default.release().split(".");
79896
79897
  if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
79897
79898
  return Number(osRelease[2]) >= 14931 ? 3 : 2;
79898
79899
  }
@@ -84698,12 +84699,14 @@ function isTableSeparator(line) {
84698
84699
  return false;
84699
84700
  return /^\|?\s*:?-+:?\s*(\|\s*:?-+:?\s*)+\|?$/.test(trimmed);
84700
84701
  }
84702
+ function stripOuterPipes(s2) {
84703
+ return s2.trim().replace(/^\|/, "").replace(/\|$/, "");
84704
+ }
84701
84705
  function parseTableCells(line) {
84702
- const trimmed = line.trim().replace(/^\|/, "").replace(/\|$/, "");
84703
- return trimmed.split("|").map((s2) => s2.trim());
84706
+ return stripOuterPipes(line).split("|").map((s2) => s2.trim());
84704
84707
  }
84705
84708
  function parseTableAligns(sep2) {
84706
- const cells = sep2.trim().replace(/^\|/, "").replace(/\|$/, "").split("|");
84709
+ const cells = stripOuterPipes(sep2).split("|");
84707
84710
  return cells.map((c2) => {
84708
84711
  const t2 = c2.trim();
84709
84712
  const left = t2.startsWith(":");
@@ -85009,7 +85012,7 @@ function summarizeArgs(input) {
85009
85012
  if (input == null)
85010
85013
  return "";
85011
85014
  if (typeof input === "string")
85012
- return truncate3(oneLine(input), 60);
85015
+ return truncate3(oneLine(input), STRING_ARG_MAX);
85013
85016
  if (typeof input !== "object")
85014
85017
  return String(input);
85015
85018
  const entries = Object.entries(input);
@@ -85068,15 +85071,17 @@ function compactPreviewLine(call) {
85068
85071
  const input = call.request.input;
85069
85072
  const v3 = input?.[key];
85070
85073
  if (typeof v3 === "string")
85071
- return truncate3(oneLine(v3), 100);
85074
+ return truncate3(oneLine(v3), PREVIEW_LINE_MAX);
85072
85075
  }
85073
85076
  return summarizeArgs(call.request.input);
85074
85077
  }
85075
- var ARG_SUMMARY_MAX, VALUE_MAX, DotColors;
85078
+ var ARG_SUMMARY_MAX, VALUE_MAX, STRING_ARG_MAX, PREVIEW_LINE_MAX, DotColors;
85076
85079
  var init_format = __esm({
85077
85080
  "../chat-model/dist/format.js"() {
85078
85081
  ARG_SUMMARY_MAX = 90;
85079
85082
  VALUE_MAX = 28;
85083
+ STRING_ARG_MAX = 60;
85084
+ PREVIEW_LINE_MAX = 100;
85080
85085
  DotColors = {
85081
85086
  mcp: "cyan",
85082
85087
  skill: "magenta",
@@ -85088,6 +85093,54 @@ var init_format = __esm({
85088
85093
  });
85089
85094
 
85090
85095
  // ../chat-model/dist/pair-events.js
85096
+ function handleSubagentEvent(e3, subagents, root) {
85097
+ const payload = e3.payload ?? {};
85098
+ const childSessionId = String(payload.childSessionId ?? "");
85099
+ if (!childSessionId)
85100
+ return;
85101
+ if (e3.subtype === "subagent_started") {
85102
+ const block2 = {
85103
+ kind: "subagent",
85104
+ id: e3.id,
85105
+ childSessionId,
85106
+ label: String(payload.label ?? "agent"),
85107
+ startedAtMs: new Date(e3.ts).getTime(),
85108
+ completedAtMs: null,
85109
+ toolCallCount: 0,
85110
+ toolCalls: [],
85111
+ stopReason: null,
85112
+ finalPreview: null,
85113
+ error: null
85114
+ };
85115
+ subagents.set(childSessionId, block2);
85116
+ root.push(block2);
85117
+ return;
85118
+ }
85119
+ const block = subagents.get(childSessionId);
85120
+ if (!block)
85121
+ return;
85122
+ if (e3.subtype === "subagent_tool_call") {
85123
+ block.toolCallCount += 1;
85124
+ block.toolCalls.push({ name: String(payload.name ?? "tool"), input: payload.input });
85125
+ return;
85126
+ }
85127
+ if (e3.subtype === "subagent_completed") {
85128
+ block.completedAtMs = new Date(e3.ts).getTime();
85129
+ block.stopReason = String(payload.stopReason ?? "");
85130
+ const text = typeof payload.text === "string" ? payload.text : "";
85131
+ if (text)
85132
+ block.finalPreview = oneLine(text);
85133
+ if (typeof payload.error === "string")
85134
+ block.error = payload.error;
85135
+ return;
85136
+ }
85137
+ if (e3.subtype === "subagent_error" || e3.subtype === "subagent_abort") {
85138
+ block.completedAtMs = new Date(e3.ts).getTime();
85139
+ const reason = typeof payload.message === "string" && payload.message || typeof payload.reason === "string" && payload.reason || "aborted";
85140
+ block.error = reason;
85141
+ return;
85142
+ }
85143
+ }
85091
85144
  function pairToolEvents(events, compactByName = EMPTY_COMPACT_MAP) {
85092
85145
  const root = [];
85093
85146
  const callTargets = /* @__PURE__ */ new Map();
@@ -85237,52 +85290,7 @@ function pairToolEvents(events, compactByName = EMPTY_COMPACT_MAP) {
85237
85290
  continue;
85238
85291
  }
85239
85292
  if (e3.type === "plugin_event" && e3.pluginId === SUBAGENT_PLUGIN_ID2) {
85240
- const payload = e3.payload ?? {};
85241
- const childSessionId = String(payload.childSessionId ?? "");
85242
- if (!childSessionId)
85243
- continue;
85244
- if (e3.subtype === "subagent_started") {
85245
- const block2 = {
85246
- kind: "subagent",
85247
- id: e3.id,
85248
- childSessionId,
85249
- label: String(payload.label ?? "agent"),
85250
- startedAtMs: new Date(e3.ts).getTime(),
85251
- completedAtMs: null,
85252
- toolCallCount: 0,
85253
- toolCalls: [],
85254
- stopReason: null,
85255
- finalPreview: null,
85256
- error: null
85257
- };
85258
- subagents.set(childSessionId, block2);
85259
- root.push(block2);
85260
- continue;
85261
- }
85262
- const block = subagents.get(childSessionId);
85263
- if (!block)
85264
- continue;
85265
- if (e3.subtype === "subagent_tool_call") {
85266
- block.toolCallCount += 1;
85267
- block.toolCalls.push({ name: String(payload.name ?? "tool"), input: payload.input });
85268
- continue;
85269
- }
85270
- if (e3.subtype === "subagent_completed") {
85271
- block.completedAtMs = new Date(e3.ts).getTime();
85272
- block.stopReason = String(payload.stopReason ?? "");
85273
- const text = typeof payload.text === "string" ? payload.text : "";
85274
- if (text)
85275
- block.finalPreview = oneLine(text);
85276
- if (typeof payload.error === "string")
85277
- block.error = payload.error;
85278
- continue;
85279
- }
85280
- if (e3.subtype === "subagent_error" || e3.subtype === "subagent_abort") {
85281
- block.completedAtMs = new Date(e3.ts).getTime();
85282
- const reason = typeof payload.message === "string" && payload.message || typeof payload.reason === "string" && payload.reason || "aborted";
85283
- block.error = reason;
85284
- continue;
85285
- }
85293
+ handleSubagentEvent(e3, subagents, root);
85286
85294
  continue;
85287
85295
  }
85288
85296
  pushBlock({ kind: "event", id: e3.id, event: e3 });
@@ -89957,6 +89965,7 @@ var USER_CONFIG_NAMES = [
89957
89965
  "config.mjs",
89958
89966
  "config.cjs"
89959
89967
  ];
89968
+ var MAX_CONFIG_SEARCH_DEPTH = 12;
89960
89969
  async function loadConfig(opts) {
89961
89970
  const sources = [];
89962
89971
  const configs = [];
@@ -90041,7 +90050,7 @@ function extractDefault(mod) {
90041
90050
  }
90042
90051
  async function findUpward(startDir, names) {
90043
90052
  let cursor = path3.resolve(startDir);
90044
- for (let i2 = 0; i2 < 12; i2++) {
90053
+ for (let i2 = 0; i2 < MAX_CONFIG_SEARCH_DEPTH; i2++) {
90045
90054
  const found = await findFile(cursor, names);
90046
90055
  if (found)
90047
90056
  return found;
@@ -90066,6 +90075,7 @@ async function findFile(dir, names) {
90066
90075
  var scopeSchema = z$1.enum(["user", "project"]);
90067
90076
  var scopeSchemaOptional = scopeSchema.optional().default("project");
90068
90077
  var USER_YAML = () => moxxyPath("config.yaml");
90078
+ var MAX_CONFIG_SEARCH_DEPTH2 = 12;
90069
90079
  async function findScopePath(scope, cwd2) {
90070
90080
  if (scope === "user") {
90071
90081
  const yaml = USER_YAML();
@@ -90077,7 +90087,7 @@ async function findScopePath(scope, cwd2) {
90077
90087
  }
90078
90088
  }
90079
90089
  let cursor = path3.resolve(cwd2);
90080
- for (let i2 = 0; i2 < 12; i2++) {
90090
+ for (let i2 = 0; i2 < MAX_CONFIG_SEARCH_DEPTH2; i2++) {
90081
90091
  for (const name of ["moxxy.config.yaml", "moxxy.config.yml"]) {
90082
90092
  const candidate = path3.join(cursor, name);
90083
90093
  try {
@@ -90105,10 +90115,7 @@ async function readDoc(filePath) {
90105
90115
  function parseDotPath(p3) {
90106
90116
  if (!p3)
90107
90117
  return [];
90108
- return p3.split(".").map((seg) => {
90109
- const asNum = /^\d+$/.test(seg) ? Number(seg) : seg;
90110
- return asNum;
90111
- });
90118
+ return p3.split(".").map((seg) => /^\d+$/.test(seg) ? Number(seg) : seg);
90112
90119
  }
90113
90120
  function parseValue(raw) {
90114
90121
  try {
@@ -90777,11 +90784,13 @@ async function defaultPrompt() {
90777
90784
 
90778
90785
  // ../plugin-memory/dist/parse.js
90779
90786
  var FRONTMATTER_FENCE2 = "---";
90787
+ var OPENING_FENCE_LF = FRONTMATTER_FENCE2 + "\n";
90788
+ var OPENING_FENCE_CRLF = FRONTMATTER_FENCE2 + "\r\n";
90780
90789
  function parseMdFile(content) {
90781
- if (!content.startsWith(FRONTMATTER_FENCE2 + "\n") && !content.startsWith(FRONTMATTER_FENCE2 + "\r\n")) {
90790
+ if (!content.startsWith(OPENING_FENCE_LF) && !content.startsWith(OPENING_FENCE_CRLF)) {
90782
90791
  return { frontmatter: {}, body: content };
90783
90792
  }
90784
- const fenceLen = content.startsWith(FRONTMATTER_FENCE2 + "\r\n") ? 5 : 4;
90793
+ const fenceLen = content.startsWith(OPENING_FENCE_CRLF) ? OPENING_FENCE_CRLF.length : OPENING_FENCE_LF.length;
90785
90794
  const rest = content.slice(fenceLen);
90786
90795
  const m3 = /\r?\n---(?:\r?\n|$)/.exec(rest);
90787
90796
  if (!m3)
@@ -91056,7 +91065,7 @@ var EmbeddingIndex = class _EmbeddingIndex {
91056
91065
  }
91057
91066
  }
91058
91067
  /**
91059
- * For each `(name, body)` pair, return either the cached vector (if the body
91068
+ * For a `(name, body)` pair, return either the cached vector (if the body
91060
91069
  * hash matches) or `null` (miss). Callers re-embed the misses and call
91061
91070
  * `set()` with the fresh vectors.
91062
91071
  */
@@ -91202,12 +91211,10 @@ async function recallVector(all, query, limit2, embedder, index, mutex) {
91202
91211
  const corpus = all.map((e3) => entryForEmbedding(e3));
91203
91212
  if (embedder instanceof TfIdfEmbedder) {
91204
91213
  embedder.fit([...corpus, query]);
91205
- const vectors2 = await embedder.embed([...corpus, query]);
91206
- const queryVec2 = vectors2[vectors2.length - 1];
91207
- return rankCosine(all, vectors2.slice(0, all.length), queryVec2, limit2);
91214
+ return rankAllFresh(all, corpus, query, limit2, embedder);
91208
91215
  }
91209
91216
  if (index) {
91210
- const { vectors: vectors2, queryVec: queryVec2 } = await mutex.run(async () => {
91217
+ const { vectors, queryVec } = await mutex.run(async () => {
91211
91218
  await index.load();
91212
91219
  const cached = [];
91213
91220
  const misses = [];
@@ -91221,19 +91228,26 @@ async function recallVector(all, query, limit2, embedder, index, mutex) {
91221
91228
  const toEmbed = [...misses.map((m3) => m3.text), query];
91222
91229
  const fresh = await embedder.embed(toEmbed);
91223
91230
  const qVec = fresh[queryIdx];
91231
+ const freshByEntryIndex = /* @__PURE__ */ new Map();
91232
+ for (const [j3, m3] of misses.entries()) {
91233
+ freshByEntryIndex.set(m3.index, fresh[j3]);
91234
+ }
91224
91235
  const vecs = [];
91225
91236
  for (let i2 = 0; i2 < all.length; i2++) {
91226
- vecs.push(cached[i2] ?? fresh[misses.findIndex((m3) => m3.index === i2)]);
91237
+ vecs.push(cached[i2] ?? freshByEntryIndex.get(i2));
91227
91238
  }
91228
- for (const m3 of misses) {
91229
- index.set(all[m3.index].frontmatter.name, m3.text, fresh[misses.indexOf(m3)]);
91239
+ for (const [j3, m3] of misses.entries()) {
91240
+ index.set(all[m3.index].frontmatter.name, m3.text, fresh[j3]);
91230
91241
  }
91231
91242
  index.prune(all.map((e3) => e3.frontmatter.name));
91232
91243
  await index.flush();
91233
91244
  return { vectors: vecs, queryVec: qVec };
91234
91245
  });
91235
- return rankCosine(all, vectors2, queryVec2, limit2);
91246
+ return rankCosine(all, vectors, queryVec, limit2);
91236
91247
  }
91248
+ return rankAllFresh(all, corpus, query, limit2, embedder);
91249
+ }
91250
+ async function rankAllFresh(all, corpus, query, limit2, embedder) {
91237
91251
  const vectors = await embedder.embed([...corpus, query]);
91238
91252
  const queryVec = vectors[vectors.length - 1];
91239
91253
  return rankCosine(all, vectors.slice(0, all.length), queryVec, limit2);
@@ -91964,7 +91978,7 @@ async function registerBuiltinEmbedder(session, name, logger) {
91964
91978
  // src/setup/build-session.ts
91965
91979
  init_dist();
91966
91980
  async function buildSession(args) {
91967
- const userPolicyPath = args.config.permissions?.policyPath ?? path3.join(os3.homedir(), ".moxxy", "permissions.json");
91981
+ const userPolicyPath = args.config.permissions?.policyPath ?? path3.join(os5.homedir(), ".moxxy", "permissions.json");
91968
91982
  const permissionEngine = await PermissionEngine.load(userPolicyPath);
91969
91983
  let restoredEvents = [];
91970
91984
  if (args.resumeSessionId) {
@@ -91980,7 +91994,7 @@ async function buildSession(args) {
91980
91994
  });
91981
91995
  }
91982
91996
  }
91983
- const userPluginsDir2 = path3.join(os3.homedir(), ".moxxy", "plugins");
91997
+ const userPluginsDir2 = path3.join(os5.homedir(), ".moxxy", "plugins");
91984
91998
  return new Session({
91985
91999
  cwd: args.cwd,
91986
92000
  logger: args.logger,
@@ -104260,7 +104274,7 @@ function resolvePath(cwd2, target) {
104260
104274
  return path3.normalize(target);
104261
104275
  return path3.resolve(cwd2, target);
104262
104276
  }
104263
- var resolveSafe = resolvePath;
104277
+ var IGNORED_DIR_NAMES = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", ".turbo"]);
104264
104278
  function clampString(s2, max) {
104265
104279
  if (s2.length <= max)
104266
104280
  return s2;
@@ -104371,14 +104385,17 @@ var editTool = defineTool({
104371
104385
  }
104372
104386
  },
104373
104387
  async handler({ file_path, old_string, new_string, replace_all }, ctx) {
104374
- const resolved = resolveSafe(ctx.cwd, file_path);
104388
+ const resolved = resolvePath(ctx.cwd, file_path);
104375
104389
  if (ctx.signal.aborted) {
104376
104390
  throw new MoxxyError({ code: "ABORTED", message: `Edit aborted before start: ${resolved}` });
104377
104391
  }
104378
104392
  const original = await promises.readFile(resolved, "utf8");
104379
104393
  let updated;
104394
+ let replaceAllOccurrences = -1;
104380
104395
  if (replace_all) {
104381
- updated = original.split(old_string).join(new_string);
104396
+ const parts = original.split(old_string);
104397
+ updated = parts.join(new_string);
104398
+ replaceAllOccurrences = parts.length - 1;
104382
104399
  if (updated === original)
104383
104400
  throw new MoxxyError({ code: "TOOL_ERROR", message: `old_string not found in ${resolved}` });
104384
104401
  } else {
@@ -104395,7 +104412,7 @@ var editTool = defineTool({
104395
104412
  updated = original.slice(0, first) + new_string + original.slice(first + old_string.length);
104396
104413
  }
104397
104414
  await writeFileAtomic(resolved, updated);
104398
- const occurrences = replace_all ? original.split(old_string).length - 1 : 1;
104415
+ const occurrences = replace_all ? replaceAllOccurrences : 1;
104399
104416
  return `edited ${resolved}: ${occurrences} replacement${occurrences === 1 ? "" : "s"}`;
104400
104417
  }
104401
104418
  });
@@ -104421,7 +104438,7 @@ var globTool = defineTool({
104421
104438
  }
104422
104439
  },
104423
104440
  async handler({ pattern, cwd: cwd2, max }, ctx) {
104424
- const baseDir = resolveSafe(ctx.cwd, cwd2 ?? ".");
104441
+ const baseDir = resolvePath(ctx.cwd, cwd2 ?? ".");
104425
104442
  const matches = [];
104426
104443
  for await (const entry of fsGlob(baseDir, pattern, ctx.signal)) {
104427
104444
  matches.push(entry);
@@ -104459,7 +104476,7 @@ async function* walk(root, regex2, cursor, signal, visited) {
104459
104476
  for (const entry of entries) {
104460
104477
  if (signal.aborted)
104461
104478
  return;
104462
- if (entry.name === "node_modules" || entry.name === ".git" || entry.name === "dist" || entry.name === ".turbo")
104479
+ if (IGNORED_DIR_NAMES.has(entry.name))
104463
104480
  continue;
104464
104481
  const full = path3.join(cursor, entry.name);
104465
104482
  let isDir = entry.isDirectory();
@@ -104507,7 +104524,7 @@ var grepTool = defineTool({
104507
104524
  }
104508
104525
  },
104509
104526
  async handler({ pattern, cwd: cwd2, glob, caseInsensitive, maxMatches }, ctx) {
104510
- const baseDir = resolveSafe(ctx.cwd, cwd2 ?? ".");
104527
+ const baseDir = resolvePath(ctx.cwd, cwd2 ?? ".");
104511
104528
  let re2;
104512
104529
  try {
104513
104530
  re2 = new RegExp(pattern, caseInsensitive ? "i" : "");
@@ -104535,7 +104552,7 @@ async function walk2(root, cursor, re2, fileRe, matches, max, signal) {
104535
104552
  for (const entry of entries) {
104536
104553
  if (signal.aborted || matches.length >= max)
104537
104554
  return;
104538
- if (entry.name === "node_modules" || entry.name === ".git" || entry.name === "dist" || entry.name === ".turbo")
104555
+ if (IGNORED_DIR_NAMES.has(entry.name))
104539
104556
  continue;
104540
104557
  const full = path3.join(cursor, entry.name);
104541
104558
  if (entry.isDirectory()) {
@@ -104564,7 +104581,7 @@ async function walk2(root, cursor, re2, fileRe, matches, max, signal) {
104564
104581
  }
104565
104582
  async function readHandler(input, ctx) {
104566
104583
  const { file_path, offset = 0, limit: limit2 = 2e3 } = input;
104567
- const resolved = resolveSafe(ctx.cwd, file_path);
104584
+ const resolved = resolvePath(ctx.cwd, file_path);
104568
104585
  const text = ctx.fs ? await ctx.fs.readFile(resolved, { encoding: "utf8" }) : (await promises.readFile(resolved)).toString("utf8");
104569
104586
  const lines = text.split("\n");
104570
104587
  const sliced = lines.slice(offset, offset + limit2);
@@ -104731,7 +104748,7 @@ var writeTool = defineTool({
104731
104748
  }
104732
104749
  },
104733
104750
  async handler({ file_path, content }, ctx) {
104734
- const resolved = resolveSafe(ctx.cwd, file_path);
104751
+ const resolved = resolvePath(ctx.cwd, file_path);
104735
104752
  if (ctx.signal.aborted) {
104736
104753
  throw new MoxxyError({ code: "ABORTED", message: `Write aborted before start: ${resolved}` });
104737
104754
  }
@@ -112639,7 +112656,7 @@ var screenshotTool = defineTool({
112639
112656
  const fmt2 = format ?? DEFAULT_FORMAT;
112640
112657
  const dim3 = maxDim ?? DEFAULT_MAX_DIM;
112641
112658
  const q3 = quality ?? DEFAULT_JPEG_QUALITY;
112642
- const captureTmp = path3.join(os3.tmpdir(), `moxxy-screencap-${process.pid}-${Date.now()}.png`);
112659
+ const captureTmp = path3.join(os5.tmpdir(), `moxxy-screencap-${process.pid}-${Date.now()}.png`);
112643
112660
  const captureArgs = ["-x", "-t", "png"];
112644
112661
  if (region) {
112645
112662
  captureArgs.push("-R", `${region.x},${region.y},${region.width},${region.height}`);
@@ -112657,7 +112674,7 @@ var screenshotTool = defineTool({
112657
112674
  });
112658
112675
  }
112659
112676
  const outExt = fmt2 === "jpeg" ? "jpg" : "png";
112660
- const outTmp = path3.join(os3.tmpdir(), `moxxy-screencap-${process.pid}-${Date.now()}-out.${outExt}`);
112677
+ const outTmp = path3.join(os5.tmpdir(), `moxxy-screencap-${process.pid}-${Date.now()}-out.${outExt}`);
112661
112678
  const sipsArgs = [
112662
112679
  "-Z",
112663
112680
  String(dim3),
@@ -116403,7 +116420,7 @@ function serializeWorkflow(wf) {
116403
116420
  return (0, import_yaml.stringify)(wf, { lineWidth: 0 });
116404
116421
  }
116405
116422
  function defaultUserWorkflowsDir() {
116406
- return path3.join(os3.homedir(), ".moxxy", "workflows");
116423
+ return path3.join(os5.homedir(), ".moxxy", "workflows");
116407
116424
  }
116408
116425
  function defaultProjectWorkflowsDir(cwd2) {
116409
116426
  return path3.join(cwd2, ".moxxy", "workflows");
@@ -117812,7 +117829,7 @@ function buildBuiltinsCore(args) {
117812
117829
  {
117813
117830
  name: "@moxxy/plugin-self-update",
117814
117831
  plugin: buildSelfUpdatePlugin({
117815
- moxxyDir: path3.join(os3.homedir(), ".moxxy"),
117832
+ moxxyDir: path3.join(os5.homedir(), ".moxxy"),
117816
117833
  reload: () => session.pluginHost.reload(),
117817
117834
  unload: (name) => session.pluginHost.unload(name),
117818
117835
  snapshot: () => ({
@@ -118029,7 +118046,7 @@ async function registerPlugins(session, config, builtins, cwd2, logger, opts = {
118029
118046
  return { registered, skipped: session.pluginHost.listSkipped() };
118030
118047
  }
118031
118048
  const loader = createPluginLoader({ cwd: cwd2 });
118032
- const userPluginsDir2 = path3.join(os3.homedir(), ".moxxy", "plugins");
118049
+ const userPluginsDir2 = path3.join(os5.homedir(), ".moxxy", "plugins");
118033
118050
  const userPluginsNodeModules = path3.join(userPluginsDir2, "node_modules");
118034
118051
  try {
118035
118052
  const manifests = await discoverPlugins({
@@ -118902,7 +118919,7 @@ function runnerSocketPath() {
118902
118919
  return override;
118903
118920
  if (process.platform === "win32")
118904
118921
  return "\\\\.\\pipe\\moxxy-serve";
118905
- return path3__default.join(os3__default.homedir(), ".moxxy", "serve.sock");
118922
+ return path3__default.join(os5__default.homedir(), ".moxxy", "serve.sock");
118906
118923
  }
118907
118924
  function isRunnerUp(socketPath = runnerSocketPath()) {
118908
118925
  return new Promise((resolve12) => {
@@ -119078,7 +119095,7 @@ var RunnerServer = class {
119078
119095
  peer.handle(RunnerMethod.ModeSetActive, (raw) => this.handleModeSetActive(raw));
119079
119096
  peer.handle(RunnerMethod.ProviderSetActive, (raw) => this.handleProviderSetActive(raw));
119080
119097
  peer.handle(RunnerMethod.PermissionAddAllow, (raw) => this.handlePermissionAddAllow(raw));
119081
- peer.handle(RunnerMethod.CommandRun, (raw) => this.handleCommandRun(client, raw));
119098
+ peer.handle(RunnerMethod.CommandRun, (raw) => this.handleCommandRun(raw));
119082
119099
  peer.handle(RunnerMethod.Transcribe, (raw) => this.handleTranscribe(raw));
119083
119100
  peer.handle(RunnerMethod.McpListServers, () => this.handleMcpListServers());
119084
119101
  peer.handle(RunnerMethod.McpEnableAndAttach, (raw) => this.handleMcpEnableAndAttach(raw));
@@ -119178,7 +119195,7 @@ var RunnerServer = class {
119178
119195
  await this.session.permissions.addAllow({ name, ...reason ? { reason } : {} });
119179
119196
  return {};
119180
119197
  }
119181
- async handleCommandRun(client, raw) {
119198
+ async handleCommandRun(raw) {
119182
119199
  const { name, args, channel } = commandRunParamsSchema.parse(raw);
119183
119200
  const cmd = this.session.commands.get(name);
119184
119201
  if (!cmd)
@@ -119204,9 +119221,9 @@ var RunnerServer = class {
119204
119221
  if (candidates.length === 0)
119205
119222
  throw new Error("no active transcriber on the runner");
119206
119223
  let lastErr = new Error("no active transcriber on the runner");
119207
- for (const def of candidates) {
119224
+ for (const name of candidates) {
119208
119225
  try {
119209
- const transcriber = this.session.transcribers.setActive(def.name);
119226
+ const transcriber = this.session.transcribers.setActive(name);
119210
119227
  const result = await transcriber.transcribe(audio, opts);
119211
119228
  this.broadcastInfo();
119212
119229
  return result;
@@ -119222,12 +119239,10 @@ var RunnerServer = class {
119222
119239
  * - Then every other registered transcriber. */
119223
119240
  transcribeCandidates() {
119224
119241
  const activeName = this.session.transcribers.getActiveName();
119225
- const all = this.session.transcribers.list();
119226
- if (!activeName)
119227
- return all.map((d2) => ({ name: d2.name }));
119228
- const head = all.find((d2) => d2.name === activeName);
119229
- const tail = all.filter((d2) => d2.name !== activeName);
119230
- return head ? [{ name: head.name }, ...tail.map((d2) => ({ name: d2.name }))] : tail.map((d2) => ({ name: d2.name }));
119242
+ const names = this.session.transcribers.list().map((d2) => d2.name);
119243
+ if (!activeName || !names.includes(activeName))
119244
+ return names;
119245
+ return [activeName, ...names.filter((n2) => n2 !== activeName)];
119231
119246
  }
119232
119247
  // --- MCP (delegates to session.mcpAdmin if the plugin is loaded) ----------
119233
119248
  async handleMcpListServers() {
@@ -119819,14 +119834,14 @@ async function unlinkSocket(socketPath) {
119819
119834
  } catch {
119820
119835
  }
119821
119836
  }
119822
- async function connectWithRetry(socketPath, attempts) {
119837
+ async function connectWithRetry(socketPath, retries) {
119823
119838
  let lastErr;
119824
- for (let i2 = 0; i2 <= attempts; i2++) {
119839
+ for (let i2 = 0; i2 <= retries; i2++) {
119825
119840
  try {
119826
119841
  return await connectUnixSocket(socketPath);
119827
119842
  } catch (err) {
119828
119843
  lastErr = err;
119829
- if (i2 < attempts)
119844
+ if (i2 < retries)
119830
119845
  await new Promise((r2) => setTimeout(r2, 100 * (i2 + 1)));
119831
119846
  }
119832
119847
  }
@@ -120494,7 +120509,7 @@ var HELP2 = formatHelp({
120494
120509
  }
120495
120510
  ]
120496
120511
  });
120497
- var AUDIT_PATH = () => path3.join(os3.homedir(), ".moxxy", "skills", ".meta", "created.jsonl");
120512
+ var AUDIT_PATH = () => path3.join(os5.homedir(), ".moxxy", "skills", ".meta", "created.jsonl");
120498
120513
  async function runSkillsCommand(argv) {
120499
120514
  const sub = argv.positional[0] ?? "list";
120500
120515
  if (sub === "help" || helpRequested(argv)) {
@@ -120706,7 +120721,7 @@ async function runPluginNewCommand(argv) {
120706
120721
  }
120707
120722
  const here = hasBoolFlag(argv, "here");
120708
120723
  const force = hasBoolFlag(argv, "force");
120709
- const root = here ? path3.join(process.cwd(), name) : path3.join(os3.homedir(), ".moxxy", "plugins", name);
120724
+ const root = here ? path3.join(process.cwd(), name) : path3.join(os5.homedir(), ".moxxy", "plugins", name);
120710
120725
  try {
120711
120726
  const stat = await promises.stat(root);
120712
120727
  if (stat.isDirectory() && !force) {
@@ -121175,7 +121190,7 @@ var HELP5 = formatHelp({
121175
121190
  ]
121176
121191
  });
121177
121192
  function policyPath() {
121178
- return path3.join(os3.homedir(), ".moxxy", "permissions.json");
121193
+ return path3.join(os5.homedir(), ".moxxy", "permissions.json");
121179
121194
  }
121180
121195
  async function runPermsCommand(argv) {
121181
121196
  const sub = argv.positional[0];
@@ -122065,7 +122080,7 @@ async function stepAllowTools(tools) {
122065
122080
  `);
122066
122081
  return;
122067
122082
  }
122068
- const policyPath2 = path3.join(os3.homedir(), ".moxxy", "permissions.json");
122083
+ const policyPath2 = path3.join(os5.homedir(), ".moxxy", "permissions.json");
122069
122084
  const engine = await PermissionEngine.load(policyPath2);
122070
122085
  const before = engine.policySnapshot;
122071
122086
  const existingAllowNames = new Set(before.allow.map((r2) => r2.name));
@@ -122435,7 +122450,7 @@ async function runDoctorCommand(argv) {
122435
122450
  }
122436
122451
  checks.push(buildVoiceDoctorCheck(session, await checkVoiceCaptureAvailable()));
122437
122452
  checks.push(...buildPluginDoctorChecks(pluginRegistration));
122438
- const memDir = path3.join(os3.homedir(), ".moxxy", "memory");
122453
+ const memDir = path3.join(os5.homedir(), ".moxxy", "memory");
122439
122454
  const memRes = await tryCatch(async () => {
122440
122455
  await promises.mkdir(memDir, { recursive: true });
122441
122456
  await promises.access(memDir, promises.constants.W_OK);
@@ -122613,6 +122628,7 @@ function buildHelp(session) {
122613
122628
  {
122614
122629
  title: "FLAGS",
122615
122630
  rows: [
122631
+ ["--browser", "force the loopback/browser flow even without a TTY (opens the browser automatically)"],
122616
122632
  ["--no-browser", "force the headless device-code flow (auto when no TTY)"]
122617
122633
  ]
122618
122634
  }
@@ -122669,7 +122685,7 @@ Run \`moxxy init\` to store its key in the vault.
122669
122685
  return 2;
122670
122686
  }
122671
122687
  await vault.open();
122672
- const headless = hasBoolFlag(argv, "no-browser") || process.stdin.isTTY !== true;
122688
+ const headless = hasBoolFlag(argv, "no-browser") || !hasBoolFlag(argv, "browser") && process.stdin.isTTY !== true;
122673
122689
  const ctx = buildProviderAuthContext(vault, { headless });
122674
122690
  try {
122675
122691
  const result = await def.auth.login(ctx);
@@ -123702,7 +123718,7 @@ var HELP13 = formatHelp({
123702
123718
  ]
123703
123719
  });
123704
123720
  function moxxyDir() {
123705
- return path3.join(os3.homedir(), ".moxxy");
123721
+ return path3.join(os5.homedir(), ".moxxy");
123706
123722
  }
123707
123723
  async function runSelfUpdateCommand(argv) {
123708
123724
  const sub = argv.positional[0] ?? "status";
@@ -123954,7 +123970,7 @@ var COMMANDS = {
123954
123970
  };
123955
123971
  async function main() {
123956
123972
  const argv = parseArgv(process.argv.slice(2));
123957
- await finalizeStagedCoreUpdate(path3.join(os3.homedir(), ".moxxy")).catch(() => void 0);
123973
+ await finalizeStagedCoreUpdate(path3.join(os5.homedir(), ".moxxy")).catch(() => void 0);
123958
123974
  const handler = COMMANDS[argv.command];
123959
123975
  if (handler) return handler(argv);
123960
123976
  let isChannel = false;