@moxxy/cli 0.14.2 → 0.14.3

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
@@ -3666,6 +3666,107 @@ var init_session = __esm({
3666
3666
  };
3667
3667
  }
3668
3668
  });
3669
+
3670
+ // ../core/dist/setup-agent.js
3671
+ function resolvePermissions(p3) {
3672
+ if (p3 === "deny")
3673
+ return denyByDefaultResolver;
3674
+ if (p3 === void 0 || p3 === "auto")
3675
+ return autoAllowResolver;
3676
+ return p3;
3677
+ }
3678
+ function finalText(events) {
3679
+ for (let i2 = events.length - 1; i2 >= 0; i2 -= 1) {
3680
+ const e3 = events[i2];
3681
+ if (e3.type === "assistant_message")
3682
+ return e3.content;
3683
+ }
3684
+ return "";
3685
+ }
3686
+ function mergePresets(presets) {
3687
+ const plugins = [];
3688
+ const seen = /* @__PURE__ */ new Set();
3689
+ const tools = [];
3690
+ let provider;
3691
+ let cwd2;
3692
+ let permissions;
3693
+ let session;
3694
+ for (const p3 of presets) {
3695
+ for (const pl of p3.plugins ?? []) {
3696
+ if (seen.has(pl.name))
3697
+ continue;
3698
+ seen.add(pl.name);
3699
+ plugins.push(pl);
3700
+ }
3701
+ if (p3.tools)
3702
+ tools.push(...p3.tools);
3703
+ if (!provider && p3.provider)
3704
+ provider = p3.provider;
3705
+ cwd2 ??= p3.cwd;
3706
+ permissions ??= p3.permissions;
3707
+ if (p3.session)
3708
+ session = { ...session, ...p3.session };
3709
+ }
3710
+ return { plugins, tools, provider, cwd: cwd2, permissions, session };
3711
+ }
3712
+ function setupAgent(input = {}) {
3713
+ const opts = Array.isArray(input) ? mergePresets(input) : input;
3714
+ const session = new Session({
3715
+ cwd: opts.cwd ?? process.cwd(),
3716
+ permissionResolver: resolvePermissions(opts.permissions),
3717
+ ...opts.session
3718
+ });
3719
+ for (const plugin5 of opts.plugins ?? [])
3720
+ session.pluginHost.registerStatic(plugin5);
3721
+ for (const tool of opts.tools ?? [])
3722
+ session.tools.register(tool);
3723
+ if (opts.provider)
3724
+ session.providers.setActive(opts.provider.name, opts.provider.config);
3725
+ const agent = {
3726
+ session,
3727
+ async *stream(prompt, runOpts) {
3728
+ yield* runTurn(session, prompt, runOpts);
3729
+ },
3730
+ async ask(prompt, runOpts) {
3731
+ return finalText(await collectTurn(session, prompt, runOpts));
3732
+ },
3733
+ collect(prompt, runOpts) {
3734
+ return collectTurn(session, prompt, runOpts);
3735
+ },
3736
+ async discover() {
3737
+ await session.pluginHost.discoverAndLoad();
3738
+ return agent;
3739
+ },
3740
+ use(plugin5) {
3741
+ session.pluginHost.registerStatic(plugin5);
3742
+ return agent;
3743
+ },
3744
+ addTool(tool) {
3745
+ session.tools.register(tool);
3746
+ return agent;
3747
+ },
3748
+ removeTool(name) {
3749
+ session.tools.unregister(name);
3750
+ return agent;
3751
+ },
3752
+ setProvider(name, config) {
3753
+ session.providers.setActive(name, config);
3754
+ return agent;
3755
+ },
3756
+ setMode(name) {
3757
+ session.modes.setActive(name);
3758
+ return agent;
3759
+ }
3760
+ };
3761
+ return agent;
3762
+ }
3763
+ var init_setup_agent = __esm({
3764
+ "../core/dist/setup-agent.js"() {
3765
+ init_session();
3766
+ init_run_turn();
3767
+ init_resolvers();
3768
+ }
3769
+ });
3669
3770
  function preferencesPath() {
3670
3771
  return path3.join(os5.homedir(), ".moxxy", "preferences.json");
3671
3772
  }
@@ -4149,6 +4250,45 @@ async function restoreEvents(sessionId, dir = defaultSessionsDir(), logger = cre
4149
4250
  }
4150
4251
  return events;
4151
4252
  }
4253
+ async function readEventPage(sessionId, opts, dir = defaultSessionsDir()) {
4254
+ const logPath = path3.join(dir, `${sessionId}.jsonl`);
4255
+ let raw;
4256
+ try {
4257
+ raw = await promises.readFile(logPath, "utf8");
4258
+ } catch {
4259
+ return { events: [], prevCursor: null };
4260
+ }
4261
+ const all = [];
4262
+ for (const line of raw.split("\n")) {
4263
+ if (!line.trim())
4264
+ continue;
4265
+ try {
4266
+ all.push(JSON.parse(line));
4267
+ } catch {
4268
+ }
4269
+ }
4270
+ return pageEvents(all, opts.before, opts.limit);
4271
+ }
4272
+ function pageEvents(events, before, limit2) {
4273
+ const cap = Math.max(0, Math.floor(limit2));
4274
+ if (cap === 0 || events.length === 0) {
4275
+ return { events: [], prevCursor: events.length === 0 ? null : before };
4276
+ }
4277
+ let end = events.length;
4278
+ if (before !== null) {
4279
+ end = 0;
4280
+ for (let i2 = 0; i2 < events.length; i2 += 1) {
4281
+ if (events[i2].seq < before)
4282
+ end = i2 + 1;
4283
+ else
4284
+ break;
4285
+ }
4286
+ }
4287
+ const start = Math.max(0, end - cap);
4288
+ const page = events.slice(start, end);
4289
+ const prevCursor = start <= 0 ? null : page[0].seq;
4290
+ return { events: page, prevCursor };
4291
+ }
4152
4292
  async function deleteSession(sessionId, dir = defaultSessionsDir()) {
4153
4293
  await promises.rm(path3.join(dir, `${sessionId}.jsonl`), { force: true });
4154
4294
  await promises.rm(metaPath(dir, sessionId), { force: true });
@@ -8414,16 +8554,19 @@ __export(dist_exports, {
8414
8554
  mergeUsageStats: () => mergeUsageStats,
8415
8555
  newSessionId: () => newSessionId,
8416
8556
  newTurnId: () => newTurnId,
8557
+ pageEvents: () => pageEvents,
8417
8558
  parseFrontmatter: () => parseFrontmatter,
8418
8559
  parseSkillFile: () => parseSkillFile,
8419
8560
  parseView: () => parseView,
8420
8561
  permissionPolicySchema: () => permissionPolicySchema,
8421
8562
  preferencesPath: () => preferencesPath,
8422
8563
  readPackageMoxxyRequirements: () => readPackageMoxxyRequirements,
8564
+ readSessionEventPage: () => readEventPage,
8423
8565
  readSessionIndex: () => readIndex,
8424
8566
  restoreSessionEvents: () => restoreEvents,
8425
8567
  runTurn: () => runTurn,
8426
8568
  savePreferences: () => savePreferences,
8569
+ setupAgent: () => setupAgent,
8427
8570
  silentLogger: () => silentLogger,
8428
8571
  synthesizeSkill: () => synthesizeSkill,
8429
8572
  toposortPluginManifests: () => toposortPluginManifests,
@@ -8434,6 +8577,7 @@ var init_dist = __esm({
8434
8577
  "../core/dist/index.js"() {
8435
8578
  init_session();
8436
8579
  init_run_turn();
8580
+ init_setup_agent();
8437
8581
  init_subagents();
8438
8582
  init_preferences();
8439
8583
  init_usage_stats();
@@ -136266,7 +136410,7 @@ async function reclaimStaleSocket(socketPath) {
136266
136410
 
136267
136411
  // ../runner/dist/server.js
136268
136412
  init_dist();
136269
- var RUNNER_PROTOCOL_VERSION = 9;
136413
+ var RUNNER_PROTOCOL_VERSION = 10;
136270
136414
  var MIN_COMPATIBLE_PROTOCOL_VERSION = 1;
136271
136415
  var RunnerMethod = {
136272
136416
  /** client->server: handshake; returns the initial info snapshot. */
@@ -136285,6 +136429,13 @@ var RunnerMethod = {
136285
136429
  * attached clients so every mirror clears in lockstep.
136286
136430
  */
136287
136431
  SessionReset: "session.reset",
136432
+ /**
136433
+ * client->server: page the runner's authoritative event history (v10).
136434
+ * `{ before, limit }` → `{ events, prevCursor }`, newest-first. Backs the
136435
+ * desktop dual-history retirement; a v10 client gates it on the server's
136436
+ * reported version and falls back to its NDJSON store against an older runner.
136437
+ */
136438
+ SessionLoadHistory: "session.loadHistory",
136288
136439
  /** client->server: declare which resolvers this client will answer. */
136289
136440
  SetResolver: "setResolver",
136290
136441
  /** client->server: switch the active mode. */
@@ -136410,6 +136561,11 @@ var modeSetActiveParamsSchema = z.object({ name: z.string() });
136410
136561
  var sessionSetReasoningParamsSchema = z.object({
136411
136562
  effort: z.enum(["off", "low", "medium", "high"])
136412
136563
  });
136564
+ var MAX_HISTORY_PAGE_LIMIT = 2e3;
136565
+ var sessionLoadHistoryParamsSchema = z.object({
136566
+ before: z.number().int().nonnegative().nullable(),
136567
+ limit: z.number().int().positive().max(MAX_HISTORY_PAGE_LIMIT)
136568
+ });
136413
136569
  var providerSetActiveParamsSchema = z.object({
136414
136570
  name: z.string(),
136415
136571
  config: z.record(z.unknown()).optional()
@@ -136734,6 +136890,7 @@ async function handleSurfaceClose(ctx, raw) {
136734
136890
  }
136735
136891
 
136736
136892
  // ../runner/dist/handlers/session-handlers.js
136893
+ init_dist();
136737
136894
  function handleModeSetActive(ctx, raw) {
136738
136895
  const { name } = modeSetActiveParamsSchema.parse(raw);
136739
136896
  ctx.session.modes.setActive(name);
@@ -136745,6 +136902,14 @@ function handleSessionSetReasoning(ctx, raw) {
136745
136902
  ctx.broadcastInfo();
136746
136903
  return {};
136747
136904
  }
136905
+ async function handleSessionLoadHistory(ctx, raw) {
136906
+ const { before, limit: limit2 } = sessionLoadHistoryParamsSchema.parse(raw);
136907
+ const log = ctx.session.log;
136908
+ if (log.baseSeq === 0) {
136909
+ return pageEvents(log.toJSON(), before, limit2);
136910
+ }
136911
+ return readEventPage(String(ctx.session.id), { before, limit: limit2 }, ctx.sessionsDir);
136912
+ }
136748
136913
  async function handlePermissionAddAllow(ctx, raw) {
136749
136914
  const { name, reason } = permissionAddAllowParamsSchema.parse(raw);
136750
136915
  await ctx.session.permissions.addAllow({ name, ...reason ? { reason } : {} });
@@ -136863,6 +137028,7 @@ var RunnerServer = class {
136863
137028
  peer.handle(RunnerMethod.RunTurn, (raw) => this.handleRunTurn(client, raw));
136864
137029
  peer.handle(RunnerMethod.Abort, (raw) => this.handleAbort(client, raw));
136865
137030
  peer.handle(RunnerMethod.SessionReset, () => this.handleSessionReset());
137031
+ peer.handle(RunnerMethod.SessionLoadHistory, (raw) => handleSessionLoadHistory(ctx, raw));
136866
137032
  peer.handle(RunnerMethod.SetResolver, (raw) => this.handleSetResolver(client, raw));
136867
137033
  peer.handle(RunnerMethod.ModeSetActive, (raw) => handleModeSetActive(ctx, raw));
136868
137034
  peer.handle(RunnerMethod.SessionSetReasoning, (raw) => handleSessionSetReasoning(ctx, raw));
@@ -136946,6 +137112,7 @@ var RunnerServer = class {
136946
137112
  } finally {
136947
137113
  this.turnControllers.delete(turnId);
136948
137114
  client.turns.delete(turnId);
137115
+ await this.sealUnsealedStreamedText(turnId);
136949
137116
  this.broadcast(RunnerNotification.TurnComplete, {
136950
137117
  turnId,
136951
137118
  ...error2 ? { error: error2 } : {}
@@ -136990,6 +137157,59 @@ var RunnerServer = class {
136990
137157
  this.session.log.clear();
136991
137158
  return {};
136992
137159
  }
137160
+ /**
137161
+ * If this turn streamed assistant text (`assistant_chunk`) that no
137162
+ * `assistant_message` ever sealed, append a REAL `assistant_message` to the
137163
+ * authoritative log so it persists + replays like any other reply. It
137164
+ * accumulates chunk deltas and seals whatever text remains at turn end — so a
137165
+ * cleanly sealed reply (the normal path) leaves an empty remainder and this is
137166
+ * a no-op.
137167
+ *
137168
+ * The accumulator resets on BOTH per-iteration boundaries — an
137169
+ * `assistant_message` (a reply was sealed) AND a `provider_request` (a fresh
137170
+ * provider iteration begins). Resetting on `provider_request` is what scopes
137171
+ * the seal to the FINAL iteration: a retryable provider error can abandon a
137172
+ * partially-streamed iteration WITHOUT sealing it (the mode loop emits the
137173
+ * error and `continue`s), and a later iteration then streams fresh text and
137174
+ * may itself end unsealed (a fatal error / abort / max-iterations). Without
137175
+ * the `provider_request` reset, the abandoned attempt's chunks would be
137176
+ * concatenated INTO the sealed reply ("ABANDONED-final" instead of "final"),
137177
+ * durably corrupting authoritative/replayed history. (This is a deliberate
137178
+ * improvement over the desktop renderer's old turn-complete synthesis, which
137179
+ * accumulated across iterations and had exactly that defect — and which this
137180
+ * seal retires.)
137181
+ *
137182
+ * The append flows through `session.log` → persistence + the broadcast stream,
137183
+ * so mirrors ingest it as a normal event and never need to synthesize their
137184
+ * own.
137185
+ */
137186
+ async sealUnsealedStreamedText(turnId) {
137187
+ const events = this.session.log.byTurn(turnId);
137188
+ if (events.length === 0)
137189
+ return;
137190
+ let unsealed = "";
137191
+ for (const event of events) {
137192
+ if (event.type === "assistant_message" || event.type === "provider_request")
137193
+ unsealed = "";
137194
+ else if (event.type === "assistant_chunk")
137195
+ unsealed += event.delta;
137196
+ }
137197
+ if (!unsealed.trim())
137198
+ return;
137199
+ try {
137200
+ await this.session.log.append({
137201
+ type: "assistant_message",
137202
+ sessionId: this.session.id,
137203
+ turnId,
137204
+ source: "model",
137205
+ content: unsealed,
137206
+ // The turn ended without the provider sealing the message (error/abort
137207
+ // after partial text); record it as a normal completed reply.
137208
+ stopReason: "end_turn"
137209
+ });
137210
+ } catch {
137211
+ }
137212
+ }
136993
137213
  handleSetResolver(client, raw) {
136994
137214
  const params = setResolverParamsSchema.parse(raw);
136995
137215
  if (params.permission !== void 0)
@@ -137602,6 +137822,26 @@ var RemoteSession = class {
137602
137822
  async reset() {
137603
137823
  await this.peer.request(RunnerMethod.SessionReset, {});
137604
137824
  }
137825
+ /**
137826
+ * Page the runner's AUTHORITATIVE event history (protocol v10). Backs the
137827
+ * desktop's dual-history retirement — the renderer reads transcript history
137828
+ * from the runner instead of its own NDJSON chat store. Newest-first paging:
137829
+ * pass `before: null` for the newest page, then feed each result's
137830
+ * `prevCursor` back as `before` to walk older pages until `prevCursor` is
137831
+ * `null` (start of history).
137832
+ *
137833
+ * GATED on the server reporting protocol v10+. Against an OLDER runner this
137834
+ * throws a clear, actionable error (not a raw method-not-found) — the desktop
137835
+ * CATCHES it and falls back to its existing NDJSON path, so no transcript
137836
+ * ever goes blank when the runner predates this method.
137837
+ */
137838
+ async loadHistory(before, limit2) {
137839
+ this.requireServerProtocol(10, "Loading session history from the runner");
137840
+ return this.peer.request(RunnerMethod.SessionLoadHistory, {
137841
+ before,
137842
+ limit: limit2
137843
+ });
137844
+ }
137605
137845
  getInfo() {
137606
137846
  return this.requireInfo();
137607
137847
  }
@@ -145703,8 +145943,8 @@ function runProcess(cmd, args, opts) {
145703
145943
  }
145704
145944
 
145705
145945
  // ../plugin-browser/dist/browser-surface.js
145706
- var FRAME_INTERVAL_MS = 450;
145707
- var FAIL_GRACE = 4;
145946
+ var FRAME_INTERVAL_MS = 300;
145947
+ var FAIL_GRACE = 6;
145708
145948
  function buildBrowserSurface(deps) {
145709
145949
  return defineSurface({
145710
145950
  kind: "browser",
@@ -145831,9 +146071,10 @@ function buildBrowserSurface(deps) {
145831
146071
  } else if (msg.type === "move" && typeof msg.fx === "number" && typeof msg.fy === "number") {
145832
146072
  await browserSidecarCall("mousemove", { x: msg.fx * vw, y: msg.fy * vh }, deps).catch(() => void 0);
145833
146073
  void tick();
145834
- } else if (msg.type === "pick" && typeof msg.fx === "number" && typeof msg.fy === "number") {
145835
- const element = await browserSidecarCall("pick", { x: msg.fx * vw, y: msg.fy * vh }, deps).catch(() => null);
145836
- emit2({ type: "picked", element });
146074
+ } else if (msg.type === "capture" && typeof msg.fx === "number" && typeof msg.fy === "number" && typeof msg.fw === "number" && typeof msg.fh === "number") {
146075
+ const shot = await browserSidecarCall("capture", { x: msg.fx * vw, y: msg.fy * vh, width: msg.fw * vw, height: msg.fh * vh }, deps).catch(() => null);
146076
+ if (shot)
146077
+ emit2({ type: "captured", base64: shot.base64, mediaType: shot.mediaType });
145837
146078
  } else if (msg.type === "zoom" && typeof msg.factor === "number") {
145838
146079
  await browserSidecarCall("zoom", { factor: msg.factor }, deps).catch(() => void 0);
145839
146080
  bump();