@moxxy/cli 0.14.1 → 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
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { z as z$1, createMutex, defineTunnelProvider, definePlugin, defineProvider, defineTool, MoxxyError, asTurnId, defineMode, asPluginId, defineCommand, defineChannel, defineWorkflowExecutor, toFriendlyError, estimateTextTokens, classifyHttpStatus, createStuckLoopDetector, runCompactionIfNeeded, runElisionIfNeeded, collectProviderStream, usageEventFields, isContextOverflowError, emitRequestsAndDetectStuck, executeToolUses, buildSystemPromptWithSkills, projectMessages, defineCompactor, defineCacheStrategy, denyByDefaultResolver, createAllowListResolver, zodToJsonSchema, fileDiffSummary, runSingleShotTurn, defineSurface, runManualCompaction, isFileDiffDisplay, renderFrontmatter, defineEmbedder, migrateModeName, skillFrontmatterSchema, asSkillId, getInstallHint, parseFrontmatterFile, createDeferredPermissionResolver, encodeLoginPrompt, defineTranscriber, summarizeTokensByModel, countNodes, moxxyPackageSchema, classifyNetworkError, addModelTotals, createJsonFileStore, ISOLATION_RANK, MOXXY_PCM16_24KHZ_MIME, fileDiffVerb, parseFrontmatter, createCallbackResolver, autoAllowResolver, asSessionId, asToolCallId, defineViewRenderer, DEFAULT_VIEW_TAGS, isSafeViewUrl, evaluateToolRule, summarizeSessionTokensFromEvents, toDiffRows, diffGutterNo, computeElisionState, toolResultStubbed, toolResultStub, toolResultBytes, conversationalStubbed, conversationalStub, asEventId } from '@moxxy/sdk';
3
+ import { z as z$1, createMutex, defineTunnelProvider, definePlugin, defineProvider, defineTool, MoxxyError, asTurnId, defineMode, asPluginId, defineCommand, defineChannel, defineWorkflowExecutor, toFriendlyError, estimateTextTokens, classifyHttpStatus, createStuckLoopDetector, runCompactionIfNeeded, runElisionIfNeeded, collectProviderStream, usageEventFields, isContextOverflowError, emitRequestsAndDetectStuck, executeToolUses, buildSystemPromptWithSkills, projectMessages, defineCompactor, defineCacheStrategy, denyByDefaultResolver, createAllowListResolver, zodToJsonSchema, fileDiffSummary, runSingleShotTurn, defineSurface, runManualCompaction, isFileDiffDisplay, renderFrontmatter, defineEmbedder, migrateModeName, skillFrontmatterSchema, asSkillId, startChannelWith, parseFrontmatterFile, createDeferredPermissionResolver, getInstallHint, defineTranscriber, summarizeTokensByModel, countNodes, moxxyPackageSchema, encodeLoginPrompt, classifyNetworkError, addModelTotals, createJsonFileStore, ISOLATION_RANK, MOXXY_PCM16_24KHZ_MIME, fileDiffVerb, parseFrontmatter, createCallbackResolver, autoAllowResolver, asSessionId, asToolCallId, defineViewRenderer, DEFAULT_VIEW_TAGS, isSafeViewUrl, evaluateToolRule, summarizeSessionTokensFromEvents, toDiffRows, diffGutterNo, computeElisionState, toolResultStubbed, toolResultStub, toolResultBytes, conversationalStubbed, conversationalStub, asEventId } from '@moxxy/sdk';
4
4
  import * as fs32 from 'fs';
5
5
  import fs32__default, { existsSync, promises, ReadStream, mkdirSync, statSync, readdirSync, writeFileSync, readFileSync, unlinkSync, chmodSync, watch, createReadStream } from 'fs';
6
6
  import * as path3 from 'path';
@@ -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,6 +146071,13 @@ 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();
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 });
146078
+ } else if (msg.type === "zoom" && typeof msg.factor === "number") {
146079
+ await browserSidecarCall("zoom", { factor: msg.factor }, deps).catch(() => void 0);
146080
+ bump();
145834
146081
  } else if (msg.type === "key" && typeof msg.key === "string") {
145835
146082
  await browserSidecarCall("key", { key: msg.key }, deps).catch(() => void 0);
145836
146083
  bump();
@@ -151228,6 +151475,15 @@ async function probeSession(opts, read, boot = setupSessionWithConfig) {
151228
151475
  }
151229
151476
  }
151230
151477
 
151478
+ // src/setup/close-session.ts
151479
+ async function closeSession(session, persistence) {
151480
+ if (persistence) {
151481
+ await persistence.flush().catch(() => void 0);
151482
+ await persistence.settleWrites().catch(() => void 0);
151483
+ }
151484
+ await session.close("cli-exit").catch(() => void 0);
151485
+ }
151486
+
151231
151487
  // src/argv-helpers.ts
151232
151488
  function argvToSetupOptions(argv, overrides = {}) {
151233
151489
  return {
@@ -151310,7 +151566,7 @@ ${stdinBuf}` : prompt;
151310
151566
  }
151311
151567
  const model = stringFlag(argv, "model");
151312
151568
  const resolver2 = allowAll ? denyByDefaultResolver : allowTools.length > 0 ? createAllowListResolver(allowTools) : denyByDefaultResolver;
151313
- const session = await setupSession({
151569
+ const { session, persistence } = await setupSessionWithConfig({
151314
151570
  ...argvToSetupOptions(argv),
151315
151571
  resolver: resolver2
151316
151572
  });
@@ -151345,7 +151601,9 @@ ${stdinBuf}` : prompt;
151345
151601
  }
151346
151602
  } catch (err) {
151347
151603
  printError(`fatal: ${err instanceof Error ? err.message : String(err)}`);
151348
- return 1;
151604
+ exitCode = 1;
151605
+ } finally {
151606
+ await closeSession(session, persistence);
151349
151607
  }
151350
151608
  return exitCode;
151351
151609
  }
@@ -151370,8 +151628,6 @@ async function readStdinIfPiped() {
151370
151628
  await init_dist9();
151371
151629
  await init_build2();
151372
151630
  var import_react70 = __toESM(require_react());
151373
-
151374
- // src/commands/web-surface.ts
151375
151631
  var REMOTE_CHANNELS = /* @__PURE__ */ new Set(["telegram"]);
151376
151632
  async function coAttachWebSurface(opts) {
151377
151633
  const { primary, session, vault, config } = opts;
@@ -151385,7 +151641,7 @@ async function coAttachWebSurface(opts) {
151385
151641
  await resolveTunnel(primary, session, webCfg, write);
151386
151642
  try {
151387
151643
  const web = def.create({ cwd: process.cwd(), vault, logger: session.logger, options: webCfg });
151388
- const handle2 = await web.start({ session });
151644
+ const handle2 = await startChannelWith(web, { session });
151389
151645
  const url2 = web.shareUrl;
151390
151646
  if (url2) write(` web surface ${url2}
151391
151647
  `);
@@ -151824,14 +152080,21 @@ function renderLogo(width = process.stdout.columns ?? 80, opts = {}) {
151824
152080
  }
151825
152081
  async function runInitCommand(argv) {
151826
152082
  const interactive = Boolean(process.stdin.isTTY);
151827
- const { session, vault } = await bootSessionWithConfig(argv, {
152083
+ const { session, vault, persistence } = await bootSessionWithConfig(argv, {
151828
152084
  skipKeyPrompt: true,
151829
152085
  skipProviderActivation: true,
151830
152086
  ...interactive ? { passphrasePrompt: promptVaultPassphrase } : {}
151831
152087
  });
151832
- if (!interactive) {
151833
- return await runHeadlessInit(session, vault);
152088
+ try {
152089
+ if (!interactive) {
152090
+ return await runHeadlessInit(session, vault);
152091
+ }
152092
+ return await runInteractiveInit(session, vault);
152093
+ } finally {
152094
+ await closeSession(session, persistence);
151834
152095
  }
152096
+ }
152097
+ async function runInteractiveInit(session, vault) {
151835
152098
  process.stdout.write(renderLogo());
151836
152099
  await vault.open();
151837
152100
  const providerDefs = session.providers.list();
@@ -152798,8 +153061,6 @@ function stringFlag2(argv, name) {
152798
153061
  function errorMessage(err) {
152799
153062
  return err instanceof Error ? err.message : String(err);
152800
153063
  }
152801
-
152802
- // src/commands/start-registered-channel.ts
152803
153064
  async function startRegisteredChannel(name, argv) {
152804
153065
  const standalone = hasBoolFlag(argv, "standalone");
152805
153066
  const mode = chooseClientMode({ standalone, runnerUp: standalone ? false : await isRunnerUp() });
@@ -152835,7 +153096,7 @@ async function runAttachedChannel(name, argv) {
152835
153096
  options: { ...configOpts, ...argv.flags }
152836
153097
  });
152837
153098
  remote.setPermissionResolver(channel.permissionResolver);
152838
- const handle2 = await channel.start({
153099
+ const handle2 = await startChannelWith(channel, {
152839
153100
  session: remote,
152840
153101
  model: stringFlag(argv, "model"),
152841
153102
  ...collectExtraFlags(argv)
@@ -152881,7 +153142,7 @@ async function runSelfHostedChannel(name, argv, standalone) {
152881
153142
  runnerServer = null;
152882
153143
  }
152883
153144
  }
152884
- const handle2 = await channel.start({
153145
+ const handle2 = await startChannelWith(channel, {
152885
153146
  session,
152886
153147
  model: stringFlag(argv, "model"),
152887
153148
  ...collectExtraFlags(argv)
@@ -154222,7 +154483,7 @@ async function runScheduleNow(argv) {
154222
154483
  process.stderr.write(colors.red("missing id") + "\n usage: moxxy schedule run <id>\n");
154223
154484
  return 2;
154224
154485
  }
154225
- const { session, scheduler: full } = await setupSessionWithConfig({
154486
+ const { session, scheduler: full, persistence } = await setupSessionWithConfig({
154226
154487
  cwd: process.cwd(),
154227
154488
  skipInitHooks: true
154228
154489
  });
@@ -154253,7 +154514,7 @@ async function runScheduleNow(argv) {
154253
154514
  );
154254
154515
  return outcome.ok ? 0 : 1;
154255
154516
  } finally {
154256
- await session.close("schedule-run").catch(() => void 0);
154517
+ await closeSession(session, persistence);
154257
154518
  }
154258
154519
  }
154259
154520
 
@@ -154334,7 +154595,25 @@ async function runDoctorCommand(argv) {
154334
154595
  });
154335
154596
  return emit(checks, asJson);
154336
154597
  }
154337
- const { session, config, configSources, vault, memory, pluginRegistration } = setupResult.value;
154598
+ const { session, config, configSources, vault, memory, pluginRegistration, persistence } = setupResult.value;
154599
+ try {
154600
+ return await runDoctorChecks({
154601
+ session,
154602
+ config,
154603
+ configSources,
154604
+ vault,
154605
+ memory,
154606
+ pluginRegistration,
154607
+ checks,
154608
+ checkKeys,
154609
+ asJson
154610
+ });
154611
+ } finally {
154612
+ await closeSession(session, persistence);
154613
+ }
154614
+ }
154615
+ async function runDoctorChecks(deps) {
154616
+ const { session, config, configSources, vault, memory, pluginRegistration, checks, checkKeys, asJson } = deps;
154338
154617
  if (configSources.length > 0) {
154339
154618
  const summary = configSources.map((s2) => `${s2.scope}:${s2.path}`).join(", ");
154340
154619
  checks.push({ id: "config", status: "ok", message: `loaded from ${summary}` });
@@ -154407,8 +154686,8 @@ async function runDoctorCommand(argv) {
154407
154686
  checks.push({ id: `provider:${name}`, status: "ok", message: "key resolved" });
154408
154687
  }
154409
154688
  }
154410
- const deps = { cwd: process.cwd(), vault, logger: session.logger, options: {} };
154411
- const channelEntries = await session.channels.listWithAvailability(deps);
154689
+ const channelDeps = { cwd: process.cwd(), vault, logger: session.logger, options: {} };
154690
+ const channelEntries = await session.channels.listWithAvailability(channelDeps);
154412
154691
  for (const { def, availability } of channelEntries) {
154413
154692
  if (availability.ok) {
154414
154693
  checks.push({ id: `channel:${def.name}`, status: "ok", message: "available" });
@@ -154620,12 +154899,18 @@ async function runLoginCommand(argv) {
154620
154899
  if (!sub || sub === "help" || sub === "--help" || sub === "-h") {
154621
154900
  let session = null;
154622
154901
  try {
154623
- const { session: s2 } = await bootSessionWithConfig(argv, {
154902
+ const { session: s2, persistence } = await bootSessionWithConfig(argv, {
154624
154903
  skipKeyPrompt: true,
154625
154904
  skipProviderActivation: true,
154626
154905
  tolerateNoProvider: true
154627
154906
  });
154628
154907
  session = s2;
154908
+ try {
154909
+ process.stdout.write(buildHelp(session));
154910
+ } finally {
154911
+ await closeSession(s2, persistence);
154912
+ }
154913
+ return sub ? 0 : 2;
154629
154914
  } catch {
154630
154915
  }
154631
154916
  process.stdout.write(buildHelp(session));
@@ -154636,11 +154921,18 @@ async function runLoginCommand(argv) {
154636
154921
  return await loginProvider(argv, sub);
154637
154922
  }
154638
154923
  async function loginProvider(argv, providerName2) {
154639
- const { session, vault } = await bootSessionWithConfig(argv, {
154924
+ const { session, vault, persistence } = await bootSessionWithConfig(argv, {
154640
154925
  skipKeyPrompt: true,
154641
154926
  skipProviderActivation: true,
154642
154927
  tolerateNoProvider: true
154643
154928
  });
154929
+ try {
154930
+ return await runLoginProvider(argv, providerName2, session, vault);
154931
+ } finally {
154932
+ await closeSession(session, persistence);
154933
+ }
154934
+ }
154935
+ async function runLoginProvider(argv, providerName2, session, vault) {
154644
154936
  const def = session.providers.list().find((d2) => d2.name === providerName2);
154645
154937
  if (!def) {
154646
154938
  process.stderr.write(
@@ -154691,11 +154983,18 @@ Run \`moxxy init\` to store its key in the vault.
154691
154983
  }
154692
154984
  }
154693
154985
  async function loginStatus(argv) {
154694
- const { session, vault } = await bootSessionWithConfig(argv, {
154986
+ const { session, vault, persistence } = await bootSessionWithConfig(argv, {
154695
154987
  skipKeyPrompt: true,
154696
154988
  skipProviderActivation: true,
154697
154989
  tolerateNoProvider: true
154698
154990
  });
154991
+ try {
154992
+ return await runLoginStatus(argv, session, vault);
154993
+ } finally {
154994
+ await closeSession(session, persistence);
154995
+ }
154996
+ }
154997
+ async function runLoginStatus(argv, session, vault) {
154699
154998
  await vault.open();
154700
154999
  const ctx = buildProviderAuthContext(vault, { headless: true });
154701
155000
  const filter = argv.positional[1];
@@ -154762,11 +155061,18 @@ async function loginLogout(argv) {
154762
155061
  );
154763
155062
  return 2;
154764
155063
  }
154765
- const { session, vault } = await bootSessionWithConfig(argv, {
155064
+ const { session, vault, persistence } = await bootSessionWithConfig(argv, {
154766
155065
  skipKeyPrompt: true,
154767
155066
  skipProviderActivation: true,
154768
155067
  tolerateNoProvider: true
154769
155068
  });
155069
+ try {
155070
+ return await runLoginLogout(providerName2, session, vault);
155071
+ } finally {
155072
+ await closeSession(session, persistence);
155073
+ }
155074
+ }
155075
+ async function runLoginLogout(providerName2, session, vault) {
154770
155076
  await vault.open();
154771
155077
  const def = session.providers.list().find((d2) => d2.name === providerName2);
154772
155078
  if (!def || def.auth?.kind !== "oauth") {
@@ -155202,8 +155508,6 @@ async function runPath(spec) {
155202
155508
  process.stdout.write(s2.unitPath + "\n");
155203
155509
  return 0;
155204
155510
  }
155205
-
155206
- // src/commands/serve.ts
155207
155511
  var BACKGROUND_UNITS = [
155208
155512
  {
155209
155513
  id: "scheduler",
@@ -155452,7 +155756,7 @@ async function startChannel(def, setup, installResolver) {
155452
155756
  if (installResolver) {
155453
155757
  session.setPermissionResolver(channel.permissionResolver);
155454
155758
  }
155455
- return channel.start({ session, ...channelOpts });
155759
+ return startChannelWith(channel, { session, ...channelOpts });
155456
155760
  }
155457
155761
  function failureHint(_name, error2) {
155458
155762
  const e3 = error2.toLowerCase();