@super-one/cli 0.71.0-alpha.1 → 0.71.0-alpha.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.
Files changed (3) hide show
  1. package/MANIFEST.json +2 -2
  2. package/lib/cli.mjs +723 -169
  3. package/package.json +10 -10
package/lib/cli.mjs CHANGED
@@ -137,8 +137,8 @@ import { fileURLToPath } from "node:url";
137
137
  function resolveCliReleaseVersion() {
138
138
  const fromEnv = process.env.SUPERONE_CLI_VERSION?.trim();
139
139
  if (fromEnv) return fromEnv;
140
- if ("0.71.0-alpha.1".trim()) {
141
- return "0.71.0-alpha.1".trim();
140
+ if ("0.71.0-alpha.3".trim()) {
141
+ return "0.71.0-alpha.3".trim();
142
142
  }
143
143
  const fromDist = readDistManifestVersion();
144
144
  if (fromDist) return fromDist;
@@ -12908,6 +12908,40 @@ var init_src = __esm({
12908
12908
  }
12909
12909
  });
12910
12910
 
12911
+ // ../../packages/shared/src/mod-ui.ts
12912
+ function nodeModClientId(clientId, clientSessionId) {
12913
+ return `${clientId}.${clientSessionId}`;
12914
+ }
12915
+ function asNodeCallerModUiRequest(request, clientSessionId) {
12916
+ if (!("clientId" in request)) return request;
12917
+ return { ...request, clientId: nodeModClientId(String(request.clientId), clientSessionId) };
12918
+ }
12919
+ function asNodeReaderModEvent(event, clientSessionId) {
12920
+ if (!("clientId" in event) || !event.type.startsWith("mod_")) return event;
12921
+ const suffix = nodeModClientId("", clientSessionId);
12922
+ return event.clientId.endsWith(suffix) ? { ...event, clientId: event.clientId.slice(0, -suffix.length) } : event;
12923
+ }
12924
+ var MOD_UI_MUTATING_OPS, MOD_UI_UNAVAILABLE;
12925
+ var init_mod_ui = __esm({
12926
+ "../../packages/shared/src/mod-ui.ts"() {
12927
+ "use strict";
12928
+ MOD_UI_MUTATING_OPS = /* @__PURE__ */ new Set([
12929
+ "press",
12930
+ "input",
12931
+ "select",
12932
+ "paneShow",
12933
+ "paneFocus",
12934
+ "close",
12935
+ "scroll",
12936
+ "focus",
12937
+ "clientPress",
12938
+ "message",
12939
+ "promptEdit"
12940
+ ]);
12941
+ MOD_UI_UNAVAILABLE = "mod-ui-unavailable";
12942
+ }
12943
+ });
12944
+
12911
12945
  // ../../packages/runtime/src/mcp-apps/identity.ts
12912
12946
  import { createHash as createHash3 } from "node:crypto";
12913
12947
  function mcpServerConfigFingerprint(config2) {
@@ -13240,11 +13274,31 @@ var init_model_fallback_wire = __esm({
13240
13274
  });
13241
13275
 
13242
13276
  // ../../packages/shared/src/slash-commands.ts
13277
+ function slashCommandKey(name) {
13278
+ return name.startsWith("/") ? name.slice(1) : name;
13279
+ }
13280
+ function sdkSlashCommands(commands, terminalNames) {
13281
+ return markTerminalBoundSlashCommands(
13282
+ commands.map((c) => ({ name: c.name, description: c.description, argumentHint: c.argumentHint ?? "", isSkill: false })),
13283
+ terminalNames
13284
+ );
13285
+ }
13243
13286
  function readTerminalSlashCommands(value) {
13244
13287
  if (!Array.isArray(value)) return void 0;
13245
13288
  const names = value.filter((item) => typeof item === "string" && item.length > 0);
13246
13289
  return names.length > 0 ? names : void 0;
13247
13290
  }
13291
+ function markTerminalBoundSlashCommands(commands, terminalNames) {
13292
+ if (!terminalNames?.length) return commands;
13293
+ const tagged = new Set(terminalNames.map(slashCommandKey));
13294
+ let changed = false;
13295
+ const next = commands.map((command) => {
13296
+ if (command.terminalBound || !tagged.has(slashCommandKey(command.name))) return command;
13297
+ changed = true;
13298
+ return { ...command, terminalBound: true };
13299
+ });
13300
+ return changed ? next : commands;
13301
+ }
13248
13302
  var init_slash_commands = __esm({
13249
13303
  "../../packages/shared/src/slash-commands.ts"() {
13250
13304
  "use strict";
@@ -13314,6 +13368,7 @@ var init_harness_capabilities = __esm({
13314
13368
  // the goal is either live or cleared.
13315
13369
  goal: { lifecycleArgs: ["clear"], canPause: false, transport: "slash", semantics: "condition" },
13316
13370
  terminalCommandApproval: "harness",
13371
+ modUi: true,
13317
13372
  displayName: "Claude"
13318
13373
  },
13319
13374
  codex: {
@@ -13334,6 +13389,7 @@ var init_harness_capabilities = __esm({
13334
13389
  // follow-up turns itself, so every transition is an explicit RPC.
13335
13390
  goal: { lifecycleArgs: [], canPause: true, transport: "rpc", semantics: "objective" },
13336
13391
  terminalCommandApproval: "harness",
13392
+ modUi: false,
13337
13393
  displayName: "Codex"
13338
13394
  },
13339
13395
  acp: {
@@ -13367,6 +13423,7 @@ var init_harness_capabilities = __esm({
13367
13423
  semantics: "objective"
13368
13424
  },
13369
13425
  terminalCommandApproval: "harness",
13426
+ modUi: false,
13370
13427
  displayName: "Others"
13371
13428
  },
13372
13429
  opencode: {
@@ -13384,6 +13441,7 @@ var init_harness_capabilities = __esm({
13384
13441
  supportsFork: true,
13385
13442
  goal: null,
13386
13443
  terminalCommandApproval: "harness",
13444
+ modUi: false,
13387
13445
  displayName: "OpenCode"
13388
13446
  },
13389
13447
  cursor: {
@@ -13403,6 +13461,7 @@ var init_harness_capabilities = __esm({
13403
13461
  goal: null,
13404
13462
  // The @cursor/sdk local executor auto-approves custom tools with no host hook.
13405
13463
  terminalCommandApproval: "executor",
13464
+ modUi: false,
13406
13465
  displayName: "Cursor"
13407
13466
  },
13408
13467
  dsh: {
@@ -13435,6 +13494,7 @@ var init_harness_capabilities = __esm({
13435
13494
  supportsFork: true,
13436
13495
  goal: null,
13437
13496
  terminalCommandApproval: "harness",
13497
+ modUi: false,
13438
13498
  displayName: "DeepSeek"
13439
13499
  }
13440
13500
  };
@@ -13667,6 +13727,7 @@ function createClaudeAgentEventMapper(options) {
13667
13727
  const subagentTracking = /* @__PURE__ */ new Map();
13668
13728
  const activeBackgroundTasks = /* @__PURE__ */ new Map();
13669
13729
  const reportedPluginErrors = options.reportedPluginErrors ?? /* @__PURE__ */ new Set();
13730
+ const terminalNames = options.terminalSlashCommands ?? { names: void 0 };
13670
13731
  let lastAssistantUsage = null;
13671
13732
  let lastTopLevelAssistantUuid = "";
13672
13733
  const retractions = createRetractionLedger();
@@ -13680,6 +13741,7 @@ function createClaudeAgentEventMapper(options) {
13680
13741
  let rejectedRateLimitResetsAt;
13681
13742
  let hasRejectedRateLimit = false;
13682
13743
  let pendingSlashOutput = "";
13744
+ let pendingSlashCommand;
13683
13745
  let messageInputTokens = 0;
13684
13746
  let messageOutputTokens = 0;
13685
13747
  let resultSeen = false;
@@ -13717,12 +13779,17 @@ function createClaudeAgentEventMapper(options) {
13717
13779
  });
13718
13780
  };
13719
13781
  const applySystem = (system) => {
13782
+ if (options.onSystem?.(system)) return;
13720
13783
  switch (system.subtype) {
13784
+ case "commands_changed":
13785
+ if (Array.isArray(system.commands)) emit({ type: "session_commands", commands: sdkSlashCommands(system.commands, terminalNames.names) });
13786
+ break;
13721
13787
  case "init": {
13722
13788
  if (typeof system.session_id === "string" && system.session_id) {
13723
13789
  options.onSessionId?.(system.session_id);
13724
13790
  }
13725
13791
  const terminalSlashCommands = readTerminalSlashCommands(system.terminal_slash_commands);
13792
+ terminalNames.names = terminalSlashCommands;
13726
13793
  emit({
13727
13794
  type: "session_init",
13728
13795
  session: {
@@ -14046,6 +14113,7 @@ function createClaudeAgentEventMapper(options) {
14046
14113
  const text2 = blocks.filter((block) => block.type === "text").map((block) => block.text ?? "").join("").trim();
14047
14114
  if (text2) pendingSlashOutput = pendingSlashOutput ? `${pendingSlashOutput}
14048
14115
  ${text2}` : text2;
14116
+ if (typeof raw.local_command_run?.command === "string") pendingSlashCommand = raw.local_command_run.command;
14049
14117
  }
14050
14118
  for (const block of blocks) {
14051
14119
  if (block.type === "text" && assistantParent && block.text) {
@@ -14190,7 +14258,14 @@ ${text2}` : text2;
14190
14258
  emit({ type: "message_interrupted", messageId, metadata });
14191
14259
  activeBackgroundTasks.clear();
14192
14260
  } else if (!resultIsError) {
14193
- if (pendingSlashOutput) emit({ type: "slash_command_output", messageId, content: pendingSlashOutput });
14261
+ if (pendingSlashOutput) {
14262
+ emit({
14263
+ type: "slash_command_output",
14264
+ messageId,
14265
+ content: pendingSlashOutput,
14266
+ ...pendingSlashCommand ? { command: pendingSlashCommand } : {}
14267
+ });
14268
+ }
14194
14269
  emit({ type: "message_complete", messageId, metadata });
14195
14270
  } else {
14196
14271
  metadata.errorInfo = failure.errorInfo;
@@ -14204,6 +14279,7 @@ ${text2}` : text2;
14204
14279
  hasRejectedRateLimit = false;
14205
14280
  rejectedRateLimitResetsAt = void 0;
14206
14281
  pendingSlashOutput = "";
14282
+ pendingSlashCommand = void 0;
14207
14283
  resultSeen = true;
14208
14284
  options.onStepBoundary?.();
14209
14285
  emit({ type: "status_change", status: activeBackgroundTasks.size === 0 ? "idle" : "background" });
@@ -15298,6 +15374,7 @@ var init_claude_live_session = __esm({
15298
15374
  backgroundTaskIds = /* @__PURE__ */ new Set();
15299
15375
  idleSystemMapper = null;
15300
15376
  reportedPluginErrors = /* @__PURE__ */ new Set();
15377
+ terminalNames = { names: void 0 };
15301
15378
  sdkSessionId;
15302
15379
  closed = false;
15303
15380
  iterationDone;
@@ -15312,6 +15389,10 @@ var init_claude_live_session = __esm({
15312
15389
  * provider). Null when a test `queryFn` yields a bare message stream.
15313
15390
  */
15314
15391
  query;
15392
+ /** The terminal-bound command names the latest init gave, to tag a reloaded command list. */
15393
+ get terminalSlashCommands() {
15394
+ return this.terminalNames.names;
15395
+ }
15315
15396
  static open(opts) {
15316
15397
  const binary = (opts.binaryPath && existsSync6(opts.binaryPath) ? opts.binaryPath : null) ?? resolveSdkClaudeBinary();
15317
15398
  if (opts.binaryPath && !existsSync6(opts.binaryPath)) {
@@ -15462,7 +15543,7 @@ var init_claude_live_session = __esm({
15462
15543
  this.opts.onAmbientEvent?.({ type: "status_change", status: "streaming" });
15463
15544
  this.ambient = {
15464
15545
  messageId,
15465
- mapper: createClaudeAgentEventMapper({ messageId, emit: (event) => this.opts.onAmbientEvent?.(event), toolApps: this.opts.toolApps, reportedPluginErrors: this.reportedPluginErrors })
15546
+ mapper: createClaudeAgentEventMapper({ messageId, emit: (event) => this.opts.onAmbientEvent?.(event), toolApps: this.opts.toolApps, reportedPluginErrors: this.reportedPluginErrors, terminalSlashCommands: this.terminalNames, onSystem: this.opts.onSystem })
15466
15547
  };
15467
15548
  }
15468
15549
  if (!this.ambient) return;
@@ -15490,7 +15571,9 @@ var init_claude_live_session = __esm({
15490
15571
  this.idleSystemMapper ??= createClaudeAgentEventMapper({
15491
15572
  messageId: "",
15492
15573
  emit: (event) => this.opts.onAmbientEvent?.(event),
15493
- reportedPluginErrors: this.reportedPluginErrors
15574
+ reportedPluginErrors: this.reportedPluginErrors,
15575
+ terminalSlashCommands: this.terminalNames,
15576
+ onSystem: this.opts.onSystem
15494
15577
  });
15495
15578
  this.idleSystemMapper.apply(msg);
15496
15579
  } else {
@@ -15509,6 +15592,7 @@ var init_claude_live_session = __esm({
15509
15592
  if (!uuids && this.opts.sessionId && result.num_turns === 0 && result.is_error === false && !cur.sawResult && !cur.streamedText) continue;
15510
15593
  }
15511
15594
  if (cur.cancelled) {
15595
+ if (msg.type === "system") this.opts.onSystem?.(msg);
15512
15596
  if (msg.type === "result") {
15513
15597
  this.active = null;
15514
15598
  this.permissionHandler = void 0;
@@ -15530,7 +15614,9 @@ var init_claude_live_session = __esm({
15530
15614
  pausedMs: () => this.timing.pausedMs,
15531
15615
  isInterrupted: () => cur.input.signal?.aborted === true,
15532
15616
  toolApps: this.opts.toolApps,
15533
- reportedPluginErrors: this.reportedPluginErrors
15617
+ reportedPluginErrors: this.reportedPluginErrors,
15618
+ terminalSlashCommands: this.terminalNames,
15619
+ onSystem: this.opts.onSystem
15534
15620
  });
15535
15621
  } else {
15536
15622
  holder2._state = createSdkMapState(cur.messageId);
@@ -15763,6 +15849,299 @@ var init_src2 = __esm({
15763
15849
  }
15764
15850
  });
15765
15851
 
15852
+ // ../../packages/claude/src/mod-surface/wire.ts
15853
+ function renameKeys(obj, names) {
15854
+ const out = {};
15855
+ for (const [key, value] of Object.entries(obj)) {
15856
+ if (value === void 0) continue;
15857
+ out[names[key] ?? key] = value;
15858
+ }
15859
+ return out;
15860
+ }
15861
+ function toWireRequest(op, request) {
15862
+ const body = renameKeys(request, WIRE_KEY);
15863
+ if (op === "attach" && Array.isArray(request.answers)) {
15864
+ body.answers = request.answers.map((kind) => HOST_REQUEST_SUBTYPE[kind]);
15865
+ }
15866
+ return { subtype: OP_SUBTYPE[op], ...body };
15867
+ }
15868
+ function fromWireResponse(op, response) {
15869
+ if (!response || typeof response !== "object") return response;
15870
+ const raw = response;
15871
+ if (op === "panes") return toRoster(raw);
15872
+ const out = renameKeys(raw, LOCAL_KEY);
15873
+ delete out.bench;
15874
+ delete out.rewritten;
15875
+ return out;
15876
+ }
15877
+ function toPane(raw) {
15878
+ if (!raw || typeof raw !== "object") return null;
15879
+ const pane = renameKeys(raw, LOCAL_KEY);
15880
+ return typeof pane.id === "string" && typeof pane.plugin === "string" ? { ...pane, title: typeof pane.title === "string" ? pane.title : pane.id } : null;
15881
+ }
15882
+ function toRoster(raw) {
15883
+ const panes = Array.isArray(raw.panes) ? raw.panes.map(toPane).filter((p3) => p3 !== null) : [];
15884
+ const id = (value) => typeof value === "string" ? value : null;
15885
+ return { panes, shownId: id(raw.shown_id), focusedId: id(raw.focused_id), focusRequestedId: id(raw.focus_requested_id) };
15886
+ }
15887
+ function mapModSystemMessage(sys) {
15888
+ switch (sys.subtype) {
15889
+ case "ui_invalidate": {
15890
+ if (!Array.isArray(sys.instances)) return { type: "mod_invalidate" };
15891
+ const instances2 = sys.instances.filter((i) => !!i && typeof i === "object" && typeof i.instance_id === "string").map((i) => ({ surface: i.surface, component: i.component, instanceId: i.instance_id }));
15892
+ return { type: "mod_invalidate", instances: instances2 };
15893
+ }
15894
+ case "ui_panes":
15895
+ return { type: "mod_panes", roster: toRoster(sys) };
15896
+ case "ui_scroll":
15897
+ if (typeof sys.client_id !== "string" || typeof sys.instance_id !== "string" || typeof sys.offset !== "number") return null;
15898
+ return {
15899
+ type: "mod_scroll",
15900
+ clientId: sys.client_id,
15901
+ component: sys.component === "AbovePrompt" ? "AbovePrompt" : "Pane",
15902
+ instanceId: sys.instance_id,
15903
+ offset: sys.offset,
15904
+ ...sys.follow_end === true ? { followEnd: true } : {}
15905
+ };
15906
+ case "ui_focus":
15907
+ if (typeof sys.client_id !== "string" || typeof sys.instance_id !== "string" || typeof sys.plugin !== "string" || typeof sys.key !== "string") return null;
15908
+ return {
15909
+ type: "mod_focus",
15910
+ clientId: sys.client_id,
15911
+ component: sys.component === "AbovePrompt" ? "AbovePrompt" : "Pane",
15912
+ instanceId: sys.instance_id,
15913
+ plugin: sys.plugin,
15914
+ key: sys.key
15915
+ };
15916
+ default:
15917
+ return null;
15918
+ }
15919
+ }
15920
+ function toHostRequest(kind, req) {
15921
+ switch (kind) {
15922
+ case "copy":
15923
+ return { kind, plugin: String(req.plugin ?? ""), text: String(req.text ?? "") };
15924
+ case "promptRead":
15925
+ return { kind };
15926
+ case "promptFill": {
15927
+ const mode = req.mode === "append" || req.mode === "insert" ? req.mode : "replace";
15928
+ return {
15929
+ kind,
15930
+ text: String(req.text ?? ""),
15931
+ mode,
15932
+ ...Array.isArray(req.decorations) ? { decorations: req.decorations } : {}
15933
+ };
15934
+ }
15935
+ case "promptSuggest":
15936
+ return { kind, text: String(req.text ?? "") };
15937
+ }
15938
+ }
15939
+ function toWireHostReply(kind, reply) {
15940
+ switch (kind) {
15941
+ case "copy":
15942
+ return { copied: reply?.kind === "copy" && reply.copied };
15943
+ case "promptRead":
15944
+ return reply?.kind === "promptRead" ? { text: reply.text, cursor: reply.cursor } : { text: "", cursor: 0 };
15945
+ case "promptFill":
15946
+ return { filled: reply?.kind === "promptFill" && reply.filled };
15947
+ case "promptSuggest":
15948
+ return { shown: reply?.kind === "promptSuggest" && reply.shown };
15949
+ }
15950
+ }
15951
+ var OP_SUBTYPE, HOST_REQUEST_SUBTYPE, WIRE_KEY, LOCAL_KEY;
15952
+ var init_wire = __esm({
15953
+ "../../packages/claude/src/mod-surface/wire.ts"() {
15954
+ "use strict";
15955
+ OP_SUBTYPE = {
15956
+ attach: "ui_attach",
15957
+ detach: "ui_detach",
15958
+ render: "ui_render",
15959
+ press: "ui_press",
15960
+ input: "ui_input",
15961
+ select: "ui_select",
15962
+ panes: "ui_panes",
15963
+ paneShow: "ui_pane_show",
15964
+ paneFocus: "ui_pane_focus",
15965
+ close: "ui_close",
15966
+ scroll: "ui_scroll",
15967
+ focus: "ui_focus",
15968
+ clientModule: "ui_client_module",
15969
+ clientPress: "ui_client_press",
15970
+ message: "ui_message",
15971
+ promptEdit: "ui_prompt_edit"
15972
+ };
15973
+ HOST_REQUEST_SUBTYPE = {
15974
+ copy: "ui_copy",
15975
+ promptRead: "ui_prompt_read",
15976
+ promptFill: "ui_prompt_fill",
15977
+ promptSuggest: "ui_prompt_suggest"
15978
+ };
15979
+ WIRE_KEY = {
15980
+ clientId: "client_id",
15981
+ instanceId: "instance_id",
15982
+ onScreen: "on_screen",
15983
+ contentRows: "content_rows",
15984
+ bodyRows: "body_rows",
15985
+ isHeld: "is_held"
15986
+ };
15987
+ LOCAL_KEY = {
15988
+ shown_id: "shownId",
15989
+ focused_id: "focusedId",
15990
+ focus_requested_id: "focusRequestedId",
15991
+ follow_end: "followEnd",
15992
+ client_modules: "clientModules",
15993
+ close_on_escape: "closeOnEscape",
15994
+ hold_toasts: "holdToasts"
15995
+ };
15996
+ }
15997
+ });
15998
+
15999
+ // ../../packages/claude/src/mod-surface/mod-surface.ts
16000
+ import { randomUUID as randomUUID4 } from "node:crypto";
16001
+ var UI_SURFACE_CAPABILITY, ModUiUnavailableError, ModSurface;
16002
+ var init_mod_surface = __esm({
16003
+ "../../packages/claude/src/mod-surface/mod-surface.ts"() {
16004
+ "use strict";
16005
+ init_mod_ui();
16006
+ init_wire();
16007
+ UI_SURFACE_CAPABILITY = "ui_surface_v1";
16008
+ ModUiUnavailableError = class extends Error {
16009
+ name = MOD_UI_UNAVAILABLE;
16010
+ };
16011
+ ModSurface = class {
16012
+ constructor(opts) {
16013
+ this.opts = opts;
16014
+ this.requestTimeoutMs = opts.requestTimeoutMs ?? 15e3;
16015
+ this.hostReplyTimeoutMs = opts.hostReplyTimeoutMs ?? 4500;
16016
+ const { query } = opts;
16017
+ if (typeof query.request !== "function" || typeof query.setUiHost !== "function") return;
16018
+ query.setUiHost({
16019
+ copy: (req) => this.relayHostRequest("copy", req),
16020
+ promptRead: (req) => this.relayHostRequest("promptRead", req),
16021
+ promptFill: (req) => this.relayHostRequest("promptFill", req),
16022
+ promptSuggest: (req) => this.relayHostRequest("promptSuggest", req)
16023
+ });
16024
+ void query.initializationResult?.().then(
16025
+ (init) => this.setAvailable(Array.isArray(init?.capabilities) && init.capabilities.includes(UI_SURFACE_CAPABILITY)),
16026
+ () => this.setAvailable(false)
16027
+ );
16028
+ }
16029
+ opts;
16030
+ available = false;
16031
+ /** The CLI serves remote surfaces; `available` also needs the user's preference. */
16032
+ capable = false;
16033
+ decided = false;
16034
+ disposed = false;
16035
+ clientAnswers = /* @__PURE__ */ new Map();
16036
+ pendingHost = /* @__PURE__ */ new Map();
16037
+ requestTimeoutMs;
16038
+ hostReplyTimeoutMs;
16039
+ get isAvailable() {
16040
+ return this.available;
16041
+ }
16042
+ /** Re-reads the user preference (after it changed) and re-announces availability. */
16043
+ refreshEnabled() {
16044
+ if (this.capable) this.setAvailable(true);
16045
+ }
16046
+ setAvailable(capable) {
16047
+ if (this.disposed) return;
16048
+ this.capable = capable;
16049
+ const next = capable && (this.opts.enabled?.() ?? true);
16050
+ if (this.decided && next === this.available && !next) return;
16051
+ this.decided = true;
16052
+ this.available = next;
16053
+ if (!next) this.clientAnswers.clear();
16054
+ this.opts.emit({ type: "mod_ui_state", available: next });
16055
+ }
16056
+ async call(op, request) {
16057
+ if (op === "hostReply") return this.acceptHostReply(request);
16058
+ if (!this.available || this.disposed) throw new ModUiUnavailableError("This session cannot draw mod interfaces");
16059
+ const wireOp = op;
16060
+ if (wireOp === "attach") {
16061
+ const { clientId, answers } = request;
16062
+ if (answers) this.clientAnswers.set(clientId, new Set(answers));
16063
+ } else if (wireOp === "detach") {
16064
+ this.clientAnswers.delete(request.clientId);
16065
+ }
16066
+ const signal = AbortSignal.timeout(this.requestTimeoutMs);
16067
+ const response = await this.opts.query.request(toWireRequest(wireOp, request), { signal });
16068
+ const payload = response && typeof response === "object" && "response" in response ? response.response : response;
16069
+ return fromWireResponse(wireOp, payload);
16070
+ }
16071
+ /** Consumes a mod push; false when `sys` is not one. */
16072
+ handleSystem(sys) {
16073
+ const event = mapModSystemMessage(sys);
16074
+ if (!event) return false;
16075
+ if (this.available) this.opts.emit(event);
16076
+ return true;
16077
+ }
16078
+ dispose() {
16079
+ if (this.disposed) return;
16080
+ this.disposed = true;
16081
+ if (this.available) this.opts.emit({ type: "mod_ui_state", available: false });
16082
+ this.available = false;
16083
+ for (const pending2 of this.pendingHost.values()) pending2.resolve(null);
16084
+ this.pendingHost.clear();
16085
+ }
16086
+ /**
16087
+ * A plugin asked a client to act (clipboard, composer). The CLI names the
16088
+ * client; the request goes out as `mod_host_request` and waits for that
16089
+ * client's `hostReply`. Never throws: an error reply would make the CLI wait
16090
+ * its full 5 s, so a missing answer resolves the safe default instead.
16091
+ */
16092
+ async relayHostRequest(kind, req) {
16093
+ const clientId = typeof req.client_id === "string" ? req.client_id : "";
16094
+ if (!this.available || !this.clientAnswers.get(clientId)?.has(kind)) return toWireHostReply(kind, null);
16095
+ const requestId = randomUUID4();
16096
+ const reply = await new Promise((resolve18) => {
16097
+ const timer = setTimeout(() => {
16098
+ this.pendingHost.delete(requestId);
16099
+ resolve18(null);
16100
+ }, this.hostReplyTimeoutMs);
16101
+ this.pendingHost.set(requestId, {
16102
+ kind,
16103
+ clientId,
16104
+ resolve: (value) => {
16105
+ clearTimeout(timer);
16106
+ resolve18(value);
16107
+ }
16108
+ });
16109
+ this.opts.emit({ type: "mod_host_request", clientId, requestId, request: toHostRequest(kind, req) });
16110
+ });
16111
+ return toWireHostReply(kind, reply);
16112
+ }
16113
+ /** Whether a `mod_host_request` still waits for its client; a delivered copy of a finished one must not be acted on. */
16114
+ isHostRequestPending(requestId) {
16115
+ return this.pendingHost.has(requestId);
16116
+ }
16117
+ acceptHostReply({ requestId, clientId, reply }) {
16118
+ const pending2 = this.pendingHost.get(requestId);
16119
+ if (!pending2 || pending2.kind !== reply.kind || pending2.clientId !== clientId) return { accepted: false };
16120
+ this.pendingHost.delete(requestId);
16121
+ pending2.resolve(reply);
16122
+ return { accepted: true };
16123
+ }
16124
+ };
16125
+ }
16126
+ });
16127
+
16128
+ // ../../packages/claude/src/mod-surface/dev-folders.ts
16129
+ var init_dev_folders = __esm({
16130
+ "../../packages/claude/src/mod-surface/dev-folders.ts"() {
16131
+ "use strict";
16132
+ }
16133
+ });
16134
+
16135
+ // ../../packages/claude/src/mod-surface.ts
16136
+ var init_mod_surface2 = __esm({
16137
+ "../../packages/claude/src/mod-surface.ts"() {
16138
+ "use strict";
16139
+ init_mod_surface();
16140
+ init_wire();
16141
+ init_dev_folders();
16142
+ }
16143
+ });
16144
+
15766
16145
  // ../../packages/runtime/src/mcp-apps/resource-gc.ts
15767
16146
  function createMcpAppResourceGc(store, references, graceMs = 5 * 6e4) {
15768
16147
  let immediate;
@@ -17590,7 +17969,7 @@ var init_host_wake = __esm({
17590
17969
  });
17591
17970
 
17592
17971
  // ../../packages/runtime/src/session/host-action-store.ts
17593
- import { createHash as createHash4, randomBytes as randomBytes2, randomUUID as randomUUID4, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
17972
+ import { createHash as createHash4, randomBytes as randomBytes2, randomUUID as randomUUID5, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
17594
17973
  function hashToken(token) {
17595
17974
  return createHash4("sha256").update(token).digest("hex");
17596
17975
  }
@@ -17777,7 +18156,7 @@ function createSqliteHostActionStore(db) {
17777
18156
  const now = input.now ?? Date.now();
17778
18157
  const deadlineMs = input.deadlineMs ?? DEFAULT_HOST_ACTION_DEADLINE_MS;
17779
18158
  const row = {
17780
- actionId: randomUUID4(),
18159
+ actionId: randomUUID5(),
17781
18160
  sessionId: input.sessionId,
17782
18161
  turnId: input.turnId ?? null,
17783
18162
  controllerClientSessionId: input.controllerClientSessionId,
@@ -18325,7 +18704,7 @@ var init_runtime_policy = __esm({
18325
18704
  });
18326
18705
 
18327
18706
  // ../../packages/runtime/src/session/session-runtime.ts
18328
- import { randomUUID as randomUUID5 } from "node:crypto";
18707
+ import { randomUUID as randomUUID6 } from "node:crypto";
18329
18708
  function deriveSessionTitleFromUserText(text2) {
18330
18709
  const cleaned = stripMiniAppMarkup(text2).trim().replace(/\s+/g, " ");
18331
18710
  if (!cleaned) return null;
@@ -18349,7 +18728,7 @@ function createSimulatedTurnRunner(opts) {
18349
18728
  onEvent?.({ kind: "status", status: "streaming" });
18350
18729
  if (opts?.requestPermission && onPermission) {
18351
18730
  const decision = await onPermission({
18352
- interactionId: randomUUID5(),
18731
+ interactionId: randomUUID6(),
18353
18732
  kind: "permission",
18354
18733
  toolName: "shell",
18355
18734
  createdAt: Date.now()
@@ -18361,7 +18740,7 @@ function createSimulatedTurnRunner(opts) {
18361
18740
  }
18362
18741
  if (opts?.requestQuestion && onQuestion) {
18363
18742
  await onQuestion({
18364
- interactionId: randomUUID5(),
18743
+ interactionId: randomUUID6(),
18365
18744
  kind: "question",
18366
18745
  toolName: "AskUserQuestion",
18367
18746
  input: {
@@ -18372,7 +18751,7 @@ function createSimulatedTurnRunner(opts) {
18372
18751
  }
18373
18752
  if (opts?.requestPlan && onPlan) {
18374
18753
  const plan = await onPlan({
18375
- interactionId: randomUUID5(),
18754
+ interactionId: randomUUID6(),
18376
18755
  kind: "plan",
18377
18756
  toolName: "ExitPlanMode",
18378
18757
  input: { plan: "Do the work" },
@@ -18384,7 +18763,7 @@ function createSimulatedTurnRunner(opts) {
18384
18763
  }
18385
18764
  }
18386
18765
  if (opts?.emitStructuredEvents && onEvent) {
18387
- const toolUseId = randomUUID5();
18766
+ const toolUseId = randomUUID6();
18388
18767
  onEvent({
18389
18768
  kind: "tool",
18390
18769
  phase: "started",
@@ -18401,7 +18780,7 @@ function createSimulatedTurnRunner(opts) {
18401
18780
  });
18402
18781
  }
18403
18782
  let finalText = "";
18404
- const blockId = randomUUID5();
18783
+ const blockId = randomUUID6();
18405
18784
  for (const chunk of chunks) {
18406
18785
  if (signal.aborted) throw new Error("aborted");
18407
18786
  await new Promise((r) => setTimeout(r, delayMs));
@@ -18417,7 +18796,7 @@ function createSimulatedTurnRunner(opts) {
18417
18796
  onEvent?.({ kind: "text", blockId, final: true, text: finalText });
18418
18797
  }
18419
18798
  onEvent?.({ kind: "status", status: "idle" });
18420
- return { finalText, providerResume: `resume-${randomUUID5()}` };
18799
+ return { finalText, providerResume: `resume-${randomUUID6()}` };
18421
18800
  };
18422
18801
  }
18423
18802
  var DEFAULT_AGENTS_CONFIRM_TIMEOUT_MS, SessionRuntime, createSimulatedCodexRunner;
@@ -18430,6 +18809,7 @@ var init_session_runtime = __esm({
18430
18809
  init_mcp_apps_state();
18431
18810
  init_mcp_apps_index();
18432
18811
  init_codex_accounts();
18812
+ init_mod_ui();
18433
18813
  init_schema_form();
18434
18814
  init_environment();
18435
18815
  init_message_catalog();
@@ -18513,6 +18893,28 @@ var init_session_runtime = __esm({
18513
18893
  onElicitation: (interaction, signal) => this.requestElicitation(session.sessionId, interaction, signal)
18514
18894
  });
18515
18895
  }
18896
+ /**
18897
+ * A view's op on the session's mod surface. Ops that change what a plugin
18898
+ * sees or does need the control lease; drawing does not.
18899
+ */
18900
+ async modUi(input) {
18901
+ const session = this.live.get(input.sessionId);
18902
+ if (!session) throw Object.assign(new Error("session not found"), { code: "not_found" });
18903
+ if (MOD_UI_MUTATING_OPS.has(input.op)) {
18904
+ this.leases.assertValid({
18905
+ resource: { environmentId: this.environmentId, sessionId: input.sessionId },
18906
+ leaseId: input.leaseId ?? "",
18907
+ generation: input.generation ?? "",
18908
+ holderClientId: input.client.clientSessionId
18909
+ });
18910
+ }
18911
+ if (!this.turnRunner.modUi) throw Object.assign(new Error("This harness draws no mod interfaces"), { name: MOD_UI_UNAVAILABLE, code: "unavailable" });
18912
+ return this.turnRunner.modUi(session, input.op, asNodeCallerModUiRequest(input.request, input.client.clientSessionId));
18913
+ }
18914
+ /** Live runtimes pick up a plugin change on disk; released ones load it at their next start. */
18915
+ async reloadPlugins() {
18916
+ await this.turnRunner.reloadPlugins?.();
18917
+ }
18516
18918
  runtimeReleases = /* @__PURE__ */ new Set();
18517
18919
  /**
18518
18920
  * Per-session FIFO of turns accepted while status is streaming for harnesses
@@ -18669,7 +19071,7 @@ var init_session_runtime = __esm({
18669
19071
  const automationId = typeof input.automationId === "string" && input.automationId.trim() ? input.automationId.trim() : null;
18670
19072
  const isAutomation = input.isAutomation === true || !!automationId;
18671
19073
  const session = {
18672
- sessionId: randomUUID5(),
19074
+ sessionId: randomUUID6(),
18673
19075
  projectId: input.projectId,
18674
19076
  harnessId: input.harnessId ?? "claude",
18675
19077
  providerId: input.providerId ?? input.harnessId ?? "claude",
@@ -18862,7 +19264,7 @@ var init_session_runtime = __esm({
18862
19264
  const cwd = input.cwd !== void 0 ? input.cwd && input.cwd.trim() ? input.cwd.trim() : null : source.cwd;
18863
19265
  const providerResume = input.providerResume !== void 0 ? input.providerResume && input.providerResume.trim() ? input.providerResume.trim() : null : null;
18864
19266
  const session = {
18865
- sessionId: randomUUID5(),
19267
+ sessionId: randomUUID6(),
18866
19268
  projectId: source.projectId,
18867
19269
  harnessId: source.harnessId,
18868
19270
  providerId: source.providerId,
@@ -18922,8 +19324,24 @@ var init_session_runtime = __esm({
18922
19324
  snapshotSequence() {
18923
19325
  return this.events.headSequence();
18924
19326
  }
18925
- listEventsAfter(afterSequence) {
18926
- return this.events.listAfter(afterSequence);
19327
+ /**
19328
+ * Events after a cursor, as `reader` sees them. Mod events are delivered
19329
+ * through this durable log although only their moment matters: a host
19330
+ * request that no longer waits for its client is read without its event
19331
+ * (the envelope stays so the cursor moves past it), so a clipboard write or
19332
+ * composer fill is never replayed; mod client ids read as the reader's own.
19333
+ */
19334
+ listEventsAfter(afterSequence, reader) {
19335
+ return this.events.listAfter(afterSequence).map((envelope) => {
19336
+ if (envelope.aggregateType !== "session" || envelope.eventType !== SESSION_DURABLE_EVENT.agentEvent) return envelope;
19337
+ const payload = envelope.payload;
19338
+ const event = payload?.event;
19339
+ if (!event?.type.startsWith("mod_")) return envelope;
19340
+ if (event.type === "mod_host_request" && !this.turnRunner.isModHostRequestPending?.(envelope.aggregateId, event.requestId)) {
19341
+ return { ...envelope, payload: {} };
19342
+ }
19343
+ return reader ? { ...envelope, payload: { ...payload, event: asNodeReaderModEvent(event, reader.clientSessionId) } } : envelope;
19344
+ });
18927
19345
  }
18928
19346
  /**
18929
19347
  * Paged denser message catalog for remote UI hydrate.
@@ -19154,7 +19572,7 @@ var init_session_runtime = __esm({
19154
19572
  appendUserMessage(session, opts) {
19155
19573
  if (opts.source === "task-notification" && isModelOnlyHostWake(opts.text)) return;
19156
19574
  const userBlock = {
19157
- id: randomUUID5(),
19575
+ id: randomUUID6(),
19158
19576
  role: "user",
19159
19577
  text: opts.text,
19160
19578
  ...opts.userMessageContent ? { userMessageContent: opts.userMessageContent } : {},
@@ -19221,6 +19639,10 @@ var init_session_runtime = __esm({
19221
19639
  handleAmbientEvent(sessionId, event) {
19222
19640
  const session = this.live.get(sessionId);
19223
19641
  if (!session || session.closed || this.disposing) return;
19642
+ if (event.type.startsWith("mod_")) {
19643
+ this.events.appendSession({ sessionId, eventType: SESSION_DURABLE_EVENT.agentEvent, payload: { event } });
19644
+ return;
19645
+ }
19224
19646
  const activeUsers = this.activeTurnCounts.get(sessionId) ?? 0;
19225
19647
  if (event.type === "status_change" && event.status === "idle" && activeUsers > 0) return;
19226
19648
  if (event.type === "message_start") {
@@ -19261,7 +19683,7 @@ var init_session_runtime = __esm({
19261
19683
  this.persist(session);
19262
19684
  }
19263
19685
  async runTurn(session, opts, abort) {
19264
- const assistantId = randomUUID5();
19686
+ const assistantId = randomUUID6();
19265
19687
  let assistantText = "";
19266
19688
  const requestId = opts.requestId;
19267
19689
  const permissionMode = typeof opts.permissionMode === "string" && opts.permissionMode.trim() ? opts.permissionMode.trim() : void 0;
@@ -19954,7 +20376,7 @@ var init_session_runtime = __esm({
19954
20376
  this.rejectPendingPermission(session);
19955
20377
  }
19956
20378
  const interaction = {
19957
- interactionId: `sessionagents_${Date.now()}_${randomUUID5().slice(0, 8)}`,
20379
+ interactionId: `sessionagents_${Date.now()}_${randomUUID6().slice(0, 8)}`,
19958
20380
  kind: "session_agents_confirm",
19959
20381
  toolName: "session_collab_request",
19960
20382
  toolUseId: void 0,
@@ -20390,7 +20812,7 @@ var init_session_runtime = __esm({
20390
20812
  });
20391
20813
 
20392
20814
  // ../../packages/runtime/src/session/event-log.ts
20393
- import { randomUUID as randomUUID6 } from "node:crypto";
20815
+ import { randomUUID as randomUUID7 } from "node:crypto";
20394
20816
  var EventLog;
20395
20817
  var init_event_log = __esm({
20396
20818
  "../../packages/runtime/src/session/event-log.ts"() {
@@ -20403,7 +20825,7 @@ var init_event_log = __esm({
20403
20825
  db;
20404
20826
  environmentId;
20405
20827
  append(input) {
20406
- const eventId = randomUUID6();
20828
+ const eventId = randomUUID7();
20407
20829
  const timestamp = Date.now();
20408
20830
  const eventVersion = input.eventVersion ?? 1;
20409
20831
  const payloadJson = JSON.stringify(input.payload);
@@ -20701,7 +21123,7 @@ var init_session_provider_definitions = __esm({
20701
21123
  });
20702
21124
 
20703
21125
  // ../../packages/runtime/src/session/session-provider-store.ts
20704
- import { randomUUID as randomUUID7 } from "node:crypto";
21126
+ import { randomUUID as randomUUID8 } from "node:crypto";
20705
21127
  function assertHarnessId(raw) {
20706
21128
  if (!VALID_HARNESS_IDS.has(raw)) {
20707
21129
  throw Object.assign(new Error(`Unknown harness: ${raw}`), { code: "invalid_argument" });
@@ -20809,7 +21231,7 @@ function createSessionProviderStore(db) {
20809
21231
  throw Object.assign(new Error("name required"), { code: "invalid_argument" });
20810
21232
  }
20811
21233
  const config2 = normalizeConfig(input.config);
20812
- const id = input.id?.trim() || `${harnessId}-${randomUUID7()}`;
21234
+ const id = input.id?.trim() || `${harnessId}-${randomUUID8()}`;
20813
21235
  if (get3(id)) {
20814
21236
  throw Object.assign(new Error(`Provider already exists: ${id}`), { code: "conflict" });
20815
21237
  }
@@ -25875,7 +26297,7 @@ var init_resolve_service = __esm({
25875
26297
  import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync3 } from "node:fs";
25876
26298
  import { tmpdir } from "node:os";
25877
26299
  import { join as join11 } from "node:path";
25878
- import { randomUUID as randomUUID8 } from "node:crypto";
26300
+ import { randomUUID as randomUUID9 } from "node:crypto";
25879
26301
  function resolveAttachmentsDir() {
25880
26302
  const override = process.env.SUPERONE_ATTACHMENTS_DIR?.trim();
25881
26303
  if (override) return override;
@@ -25904,8 +26326,8 @@ function decodeBase64(base643) {
25904
26326
  }
25905
26327
  }
25906
26328
  function safeFileBase(name, mimeType) {
25907
- const cleaned = (name || `attachment-${randomUUID8()}`).replace(/[^\w.\-]+/g, "_").slice(0, 80);
25908
- const base = cleaned || `attachment-${randomUUID8()}`;
26329
+ const cleaned = (name || `attachment-${randomUUID9()}`).replace(/[^\w.\-]+/g, "_").slice(0, 80);
26330
+ const base = cleaned || `attachment-${randomUUID9()}`;
25909
26331
  if (/\.\w{2,5}$/.test(base)) return base;
25910
26332
  return `${base}.${extForAttachmentMime(mimeType)}`;
25911
26333
  }
@@ -25915,7 +26337,7 @@ function persistAttachment(base643, mimeType, opts) {
25915
26337
  try {
25916
26338
  const dir = resolveAttachmentsDir();
25917
26339
  mkdirSync4(dir, { recursive: true });
25918
- const fileName = `${randomUUID8()}-${safeFileBase(opts?.name, mimeType)}`;
26340
+ const fileName = `${randomUUID9()}-${safeFileBase(opts?.name, mimeType)}`;
25919
26341
  const filePath = join11(dir, fileName);
25920
26342
  writeFileSync3(filePath, buf);
25921
26343
  return filePath;
@@ -35705,6 +36127,29 @@ function findPluginSourceDir(mpDir, pluginName) {
35705
36127
  }
35706
36128
  return null;
35707
36129
  }
36130
+ function enabledPluginsSources(cwd, opts) {
36131
+ return cwd ? [getUserSettingsPath(opts), getProjectSettingsPath2(cwd), getLocalSettingsPath(cwd)] : [getUserSettingsPath(opts)];
36132
+ }
36133
+ function enabledPluginsEntry(filePath, key) {
36134
+ const map2 = readJsonObject(filePath).enabledPlugins;
36135
+ return map2 && typeof map2 === "object" && !Array.isArray(map2) ? map2[key] : void 0;
36136
+ }
36137
+ function isPluginEnabled(cwd, key, defaultEnabled, opts) {
36138
+ let value;
36139
+ for (const file2 of enabledPluginsSources(cwd, opts)) {
36140
+ const entry = enabledPluginsEntry(file2, key);
36141
+ if (entry !== void 0) value = entry;
36142
+ }
36143
+ return value === void 0 ? defaultEnabled !== false : value === true || Array.isArray(value);
36144
+ }
36145
+ function setPluginEnabled(cwd, key, scope, enabled, opts) {
36146
+ const sources = enabledPluginsSources(cwd, opts);
36147
+ const deciding = [...sources].reverse().find((file2) => enabledPluginsEntry(file2, key) !== void 0);
36148
+ const target = deciding ?? (scope === "user" || !cwd ? getUserSettingsPath(opts) : getProjectSettingsPath2(cwd));
36149
+ const data = readJsonObject(target);
36150
+ const map2 = data.enabledPlugins && typeof data.enabledPlugins === "object" && !Array.isArray(data.enabledPlugins) ? data.enabledPlugins : {};
36151
+ writeSettingsJson(target, { ...data, enabledPlugins: { ...map2, [key]: enabled } });
36152
+ }
35708
36153
  function listPlugins(cwd, opts) {
35709
36154
  const data = readJson2(installedFile(opts));
35710
36155
  if (!data?.plugins) return [];
@@ -35734,6 +36179,7 @@ function listPlugins(cwd, opts) {
35734
36179
  version: version2,
35735
36180
  installPath: entry.installPath,
35736
36181
  installedAt: entry.installedAt,
36182
+ enabled: isPluginEnabled(cwd, pluginKey, manifest?.defaultEnabled, opts),
35737
36183
  ...contents,
35738
36184
  latestVersion,
35739
36185
  hasUpdate
@@ -36066,6 +36512,13 @@ var init_plugins_manage = __esm({
36066
36512
  }
36067
36513
  });
36068
36514
 
36515
+ // ../../packages/runtime/src/fs/plugin-review.ts
36516
+ var init_plugin_review = __esm({
36517
+ "../../packages/runtime/src/fs/plugin-review.ts"() {
36518
+ "use strict";
36519
+ }
36520
+ });
36521
+
36069
36522
  // ../../packages/runtime/src/fs/hooks-config.ts
36070
36523
  import { existsSync as existsSync18, mkdirSync as mkdirSync10, readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "node:fs";
36071
36524
  import { dirname as dirname9, join as join19 } from "node:path";
@@ -36204,6 +36657,7 @@ var init_fs = __esm({
36204
36657
  init_mcp_merge();
36205
36658
  init_fuzzy();
36206
36659
  init_plugins_manage();
36660
+ init_plugin_review();
36207
36661
  init_hooks_config();
36208
36662
  init_agents_discover();
36209
36663
  }
@@ -36263,6 +36717,7 @@ function createNodeClaudeTurnRunner(opts) {
36263
36717
  const disposeEntry = async (sessionKey) => {
36264
36718
  const entry = lives.get(sessionKey);
36265
36719
  if (!entry) return;
36720
+ entry.modSurface?.dispose();
36266
36721
  lives.delete(sessionKey);
36267
36722
  await entry.live.dispose().catch(() => void 0);
36268
36723
  await entry.hostActionDispose?.().catch(() => void 0);
@@ -36353,7 +36808,8 @@ function createNodeClaudeTurnRunner(opts) {
36353
36808
  env: p3.authEnv,
36354
36809
  queryFn: opts.queryFn,
36355
36810
  options: mcpOptions,
36356
- toolApps
36811
+ toolApps,
36812
+ onSystem: (system) => lives.get(sessionKey)?.modSurface?.handleSystem(system) ?? false
36357
36813
  });
36358
36814
  const entry = {
36359
36815
  live,
@@ -36364,10 +36820,22 @@ function createNodeClaudeTurnRunner(opts) {
36364
36820
  mcpServers: merged.claudeMcpServers,
36365
36821
  mcpAppsCatalog,
36366
36822
  refreshMcpAppsCatalog: refreshCatalog,
36823
+ modSurface: null,
36824
+ modBacklog: [],
36367
36825
  busyCount: 0,
36368
36826
  lastActivityAt: Date.now()
36369
36827
  };
36370
36828
  lives.set(sessionKey, entry);
36829
+ if (live.query) {
36830
+ entry.modSurface = new ModSurface({
36831
+ query: live.query,
36832
+ emit: (event) => {
36833
+ if (lives.get(sessionKey) !== entry) return;
36834
+ if (entry.onAmbientEvent) entry.onAmbientEvent(event);
36835
+ else entry.modBacklog.push(event);
36836
+ }
36837
+ });
36838
+ }
36371
36839
  return entry;
36372
36840
  };
36373
36841
  const runner = async (input) => {
@@ -36408,9 +36876,7 @@ function createNodeClaudeTurnRunner(opts) {
36408
36876
  const nextAdditionalDirsKey = additionalDirsKeyOf(input.additionalDirectories?.filter(Boolean));
36409
36877
  let entry = lives.get(sessionKey);
36410
36878
  if (entry && (entry.cwd !== cwd || entry.mcpDiskKey !== nextMcpDiskKey || entry.additionalDirsKey !== nextAdditionalDirsKey)) {
36411
- await entry.live.dispose().catch(() => void 0);
36412
- await entry.hostActionDispose?.().catch(() => void 0);
36413
- lives.delete(sessionKey);
36879
+ await disposeEntry(sessionKey);
36414
36880
  entry = void 0;
36415
36881
  }
36416
36882
  entry ??= openEntry({
@@ -36429,6 +36895,7 @@ function createNodeClaudeTurnRunner(opts) {
36429
36895
  apiProviderId: input.apiProviderId
36430
36896
  });
36431
36897
  entry.onAmbientEvent = input.onAmbientEvent;
36898
+ if (input.onAmbientEvent) for (const event of entry.modBacklog.splice(0)) input.onAmbientEvent(event);
36432
36899
  const prepared = prepareTurnPrompt(input.text, cwd, input.images);
36433
36900
  const content = prepared.kind === "text" ? prepared.text : prepared.content;
36434
36901
  const activeEntry = entry;
@@ -36542,6 +37009,19 @@ function createNodeClaudeTurnRunner(opts) {
36542
37009
  runner.disposeSession = async (sessionId) => {
36543
37010
  await disposeEntry(sessionId);
36544
37011
  };
37012
+ runner.reloadPlugins = async () => {
37013
+ await Promise.all([...lives.values()].map(async (entry) => {
37014
+ const result = await entry.live.query?.reloadPlugins().catch(() => null);
37015
+ if (result) entry.onAmbientEvent?.({ type: "session_commands", commands: sdkSlashCommands(result.commands, entry.live.terminalSlashCommands) });
37016
+ }));
37017
+ };
37018
+ runner.modUi = async (session, op, request) => {
37019
+ const entry = lives.get(session.sessionId);
37020
+ if (!entry?.modSurface) throw Object.assign(new Error("No live Claude runtime for this session"), { name: MOD_UI_UNAVAILABLE, code: "unavailable" });
37021
+ if (MOD_UI_MUTATING_OPS.has(op)) entry.lastActivityAt = Date.now();
37022
+ return entry.modSurface.call(op, request);
37023
+ };
37024
+ runner.isModHostRequestPending = (sessionId, requestId) => lives.get(sessionId)?.modSurface?.isHostRequestPending(requestId) ?? false;
36545
37025
  runner.disposeAll = async () => {
36546
37026
  const keys = [...lives.keys()];
36547
37027
  await Promise.all(keys.map((id) => disposeEntry(id)));
@@ -36562,6 +37042,9 @@ var init_claude_turn_runner = __esm({
36562
37042
  init_mcp_apps3();
36563
37043
  init_identity();
36564
37044
  init_mcp_apps();
37045
+ init_mod_ui();
37046
+ init_slash_commands();
37047
+ init_mod_surface2();
36565
37048
  init_session();
36566
37049
  init_resolve_service();
36567
37050
  init_turn_attachments();
@@ -37535,8 +38018,8 @@ var init_managed_official = __esm({
37535
38018
  "../../packages/runtime/src/harness/managed-official.ts"() {
37536
38019
  "use strict";
37537
38020
  init_managed_layout();
37538
- OFFICIAL_CLAUDE_SDK_VERSION = "0.3.287";
37539
- OFFICIAL_CODEX_NPM_VERSION = "0.159.0";
38021
+ OFFICIAL_CLAUDE_SDK_VERSION = "0.3.289";
38022
+ OFFICIAL_CODEX_NPM_VERSION = "0.160.0";
37540
38023
  OFFICIAL_CODEX_PACKAGE = "@openai/codex";
37541
38024
  }
37542
38025
  });
@@ -74118,7 +74601,7 @@ var init_mcp_app_elicitation = __esm({
74118
74601
 
74119
74602
  // src/session/codex-turn-runner.ts
74120
74603
  import { existsSync as existsSync32 } from "node:fs";
74121
- import { randomUUID as randomUUID9 } from "node:crypto";
74604
+ import { randomUUID as randomUUID10 } from "node:crypto";
74122
74605
  function mapCodexReasoningEffort(effort) {
74123
74606
  if (!effort) return void 0;
74124
74607
  const e = effort.trim().toLowerCase();
@@ -74186,7 +74669,7 @@ function createNodeCodexTurnRunner(opts) {
74186
74669
  }
74187
74670
  const threadId = request.params.threadId ?? request.params.thread_id;
74188
74671
  if (!live2?.onElicitation || typeof threadId === "string" && live2.threadId && threadId !== live2.threadId) return { action: "cancel", content: null, _meta: null };
74189
- const permission = codexElicitationRequest(`codex-elicitation-${randomUUID9()}`, request.params);
74672
+ const permission = codexElicitationRequest(`codex-elicitation-${randomUUID10()}`, request.params);
74190
74673
  if (!permission) return { action: "cancel", content: null, _meta: null };
74191
74674
  live2.busyCount += 1;
74192
74675
  try {
@@ -74427,7 +74910,7 @@ function createNodeCodexTurnRunner(opts) {
74427
74910
  const provider = createCodexMcpAppsProvider(binding, live.threadId, live.client.request.bind(live.client), live.client.request);
74428
74911
  if (!host) return provider;
74429
74912
  return withCodexMcpAppElicitation(provider, live.client, live.threadId, async (request, signal) => {
74430
- const permission = codexElicitationRequest(`codex-elicitation-${randomUUID9()}`, request.params);
74913
+ const permission = codexElicitationRequest(`codex-elicitation-${randomUUID10()}`, request.params);
74431
74914
  if (!permission) return { action: "cancel", content: null, _meta: null };
74432
74915
  live.busyCount += 1;
74433
74916
  try {
@@ -74499,6 +74982,16 @@ function createProductionTurnRunner(opts) {
74499
74982
  if (!native?.getMcpAppsProvider) throw new McpAppsError("not_connected", "Harness does not support MCP Apps");
74500
74983
  return native.getMcpAppsProvider(session, binding, origin, host);
74501
74984
  };
74985
+ runner.reloadPlugins = async () => {
74986
+ await claude.reloadPlugins?.();
74987
+ };
74988
+ runner.modUi = (session, op, request) => {
74989
+ if (session.harnessId !== "claude" || !claude.modUi) {
74990
+ return Promise.reject(Object.assign(new Error("This harness draws no mod interfaces"), { name: MOD_UI_UNAVAILABLE, code: "unavailable" }));
74991
+ }
74992
+ return claude.modUi(session, op, request);
74993
+ };
74994
+ runner.isModHostRequestPending = (sessionId, requestId) => claude.isModHostRequestPending?.(sessionId, requestId) ?? false;
74502
74995
  runner.disposeSession = async (sessionId) => {
74503
74996
  await Promise.all([
74504
74997
  claude.disposeSession?.(sessionId),
@@ -74518,6 +75011,7 @@ var init_codex_turn_runner = __esm({
74518
75011
  "src/session/codex-turn-runner.ts"() {
74519
75012
  "use strict";
74520
75013
  init_mcp_apps2();
75014
+ init_mod_ui();
74521
75015
  init_mcp_apps();
74522
75016
  init_identity();
74523
75017
  init_codex_accounts();
@@ -83529,6 +84023,7 @@ CREATE INDEX IF NOT EXISTS idx_session_providers_harness ON session_providers(ha
83529
84023
 
83530
84024
  // src/rpc/handlers.ts
83531
84025
  init_message_display();
84026
+ init_mod_ui();
83532
84027
 
83533
84028
  // src/rpc/mcp-apps-handlers.ts
83534
84029
  init_environment();
@@ -84003,6 +84498,111 @@ async function probeSandboxRpc() {
84003
84498
  };
84004
84499
  }
84005
84500
 
84501
+ // ../../packages/runtime/src/server/rpc-mutating-methods.ts
84502
+ init_mod_ui();
84503
+ var NODE_MUTATING_METHODS = /* @__PURE__ */ new Set([
84504
+ "terminal.create",
84505
+ "terminal.write",
84506
+ "terminal.resize",
84507
+ "terminal.kill",
84508
+ "project.open",
84509
+ "project.update",
84510
+ "project.remove",
84511
+ "workspace.writeFile",
84512
+ "workspace.rename",
84513
+ "workspace.move",
84514
+ "workspace.delete",
84515
+ "workspace.mkdir",
84516
+ "workspace.watchStart",
84517
+ "workspace.watchStop",
84518
+ "workspace.tailWatchStart",
84519
+ "workspace.tailWatchStop",
84520
+ "git.clone",
84521
+ "git.switchBranch",
84522
+ "git.createBranch",
84523
+ "git.worktreeActivate",
84524
+ "git.worktreeAssignBranch",
84525
+ "git.worktreeHandoff",
84526
+ "session.create",
84527
+ "session.setCwd",
84528
+ "session.patchSettings",
84529
+ "session.fork",
84530
+ "session.send",
84531
+ "session.interrupt",
84532
+ "session.respondPermission",
84533
+ "session.respondQuestion",
84534
+ "session.respondPlan",
84535
+ "session.claimHostAction",
84536
+ "session.respondHostAction",
84537
+ "harness.probe",
84538
+ "session.acquireControl",
84539
+ "session.renewControl",
84540
+ "session.releaseControl",
84541
+ "session.close",
84542
+ "session.remove",
84543
+ "session.rename",
84544
+ "session.setTags",
84545
+ "session.setUiFlags",
84546
+ // pin/hide
84547
+ "terminal.acquireControl",
84548
+ "terminal.renewControl",
84549
+ "terminal.releaseControl",
84550
+ "collaboration.request",
84551
+ "collaboration.start",
84552
+ "collaboration.send",
84553
+ "provider.createCredential",
84554
+ "provider.updateCredential",
84555
+ "provider.deleteCredential",
84556
+ "provider.setBinding",
84557
+ "provider.clearBinding",
84558
+ "provider.upsertCustomPlatform",
84559
+ "provider.deleteCustomPlatform",
84560
+ "provider.importBundle",
84561
+ "settings.patch",
84562
+ // Skills, MCP, plugins, hooks
84563
+ "skills.delete",
84564
+ "skills.install",
84565
+ "mcp.save",
84566
+ "mcp.toggle",
84567
+ "mcp.delete",
84568
+ "plugins.delete",
84569
+ "plugins.setEnabled",
84570
+ "plugins.install",
84571
+ "plugins.update",
84572
+ "plugins.addMarketplace",
84573
+ "plugins.removeMarketplace",
84574
+ "plugins.updateMarketplace",
84575
+ "hooks.save",
84576
+ "hooks.delete",
84577
+ "automation.create",
84578
+ "automation.update",
84579
+ "automation.delete",
84580
+ "automation.runNow",
84581
+ "sessionProviders.create",
84582
+ "sessionProviders.update",
84583
+ "sessionProviders.delete",
84584
+ "codex.setDefaultAccount",
84585
+ "codex.setAuth",
84586
+ "codex.accountLoginStart",
84587
+ "codex.accountLoginCancel",
84588
+ "codex.accountLogout",
84589
+ "codex.consumeRateLimitReset",
84590
+ "codex.loginMcpOauth",
84591
+ "codex.importExternalAgent",
84592
+ "codex.plugins.install",
84593
+ "codex.plugins.uninstall",
84594
+ "codex.marketplace.add",
84595
+ "codex.marketplace.remove",
84596
+ "codex.marketplace.upgrade"
84597
+ ]);
84598
+ function isNodeMutatingCall(method, payload) {
84599
+ if (method === "session.modUi") {
84600
+ const op = payload?.op;
84601
+ return typeof op === "string" && MOD_UI_MUTATING_OPS.has(op);
84602
+ }
84603
+ return NODE_MUTATING_METHODS.has(method);
84604
+ }
84605
+
84006
84606
  // ../../packages/shared/src/git-clone.ts
84007
84607
  import { execFile as execFile2 } from "node:child_process";
84008
84608
  import { existsSync as existsSync34, mkdirSync as mkdirSync19 } from "node:fs";
@@ -84590,6 +85190,34 @@ function handlePluginsDelete(payload, ctx) {
84590
85190
  return mapThrown(err);
84591
85191
  }
84592
85192
  }
85193
+ function handlePluginsSetEnabled(payload, ctx) {
85194
+ const baseDenied = requireScopes(ctx.client, OPERATION_SCOPES.writeWorkspace);
85195
+ if (baseDenied) return baseDenied;
85196
+ const p3 = asRecord17(payload);
85197
+ try {
85198
+ const projectId = String(p3.projectId ?? "");
85199
+ const cwd = projectRoot(ctx.projects, projectId);
85200
+ const provider = parseClaudeProvider(p3.provider);
85201
+ if (!provider) {
85202
+ return { error: { code: "invalid_argument", message: "provider must be claude" } };
85203
+ }
85204
+ const scope = parseScope(p3.scope);
85205
+ if (!scope) {
85206
+ return { error: { code: "invalid_argument", message: "scope must be user or project" } };
85207
+ }
85208
+ const denied = requireResourceWrite(ctx.client, scope);
85209
+ if (denied) return denied;
85210
+ const key = String(p3.key ?? "");
85211
+ if (!key || typeof p3.enabled !== "boolean") {
85212
+ return { error: { code: "invalid_argument", message: "key and enabled are required" } };
85213
+ }
85214
+ setPluginEnabled(cwd, key, scope, p3.enabled, manageOpts(ctx));
85215
+ ctx.projects.touch(projectId);
85216
+ return { result: { ok: true, provider } };
85217
+ } catch (err) {
85218
+ return mapThrown(err);
85219
+ }
85220
+ }
84593
85221
  async function handlePluginsInstall(payload, ctx) {
84594
85222
  const baseDenied = requireScopes(ctx.client, OPERATION_SCOPES.writeWorkspace);
84595
85223
  if (baseDenied) return baseDenied;
@@ -84950,6 +85578,8 @@ function dispatchResourceRpc(method, payload, ctx) {
84950
85578
  return handlePluginsReadFile(payload, ctx);
84951
85579
  case "plugins.delete":
84952
85580
  return handlePluginsDelete(payload, ctx);
85581
+ case "plugins.setEnabled":
85582
+ return handlePluginsSetEnabled(payload, ctx);
84953
85583
  case "plugins.install":
84954
85584
  return handlePluginsInstall(payload, ctx);
84955
85585
  case "plugins.update":
@@ -84980,21 +85610,6 @@ function dispatchResourceRpc(method, payload, ctx) {
84980
85610
  return null;
84981
85611
  }
84982
85612
  }
84983
- var RESOURCE_MUTATING_METHODS = [
84984
- "skills.delete",
84985
- "skills.install",
84986
- "mcp.save",
84987
- "mcp.toggle",
84988
- "mcp.delete",
84989
- "plugins.delete",
84990
- "plugins.install",
84991
- "plugins.update",
84992
- "plugins.addMarketplace",
84993
- "plugins.removeMarketplace",
84994
- "plugins.updateMarketplace",
84995
- "hooks.save",
84996
- "hooks.delete"
84997
- ];
84998
85613
 
84999
85614
  // src/rpc/automation-handlers.ts
85000
85615
  init_environment();
@@ -85263,12 +85878,6 @@ function dispatchAutomationRpc(method, payload, ctx) {
85263
85878
  return null;
85264
85879
  }
85265
85880
  }
85266
- var AUTOMATION_MUTATING_METHODS = [
85267
- "automation.create",
85268
- "automation.update",
85269
- "automation.delete",
85270
- "automation.runNow"
85271
- ];
85272
85881
 
85273
85882
  // src/rpc/draft-handlers.ts
85274
85883
  init_environment();
@@ -85592,21 +86201,6 @@ async function dispatchCodexRpc(method, payload, ctx) {
85592
86201
  };
85593
86202
  }
85594
86203
  }
85595
- var CODEX_MUTATING_METHODS = [
85596
- "codex.setDefaultAccount",
85597
- "codex.setAuth",
85598
- "codex.accountLoginStart",
85599
- "codex.accountLoginCancel",
85600
- "codex.accountLogout",
85601
- "codex.consumeRateLimitReset",
85602
- "codex.loginMcpOauth",
85603
- "codex.importExternalAgent",
85604
- "codex.plugins.install",
85605
- "codex.plugins.uninstall",
85606
- "codex.marketplace.add",
85607
- "codex.marketplace.remove",
85608
- "codex.marketplace.upgrade"
85609
- ];
85610
86204
  function handleGetAuthStatus(payload, ctx) {
85611
86205
  const denied = requireScopes5(ctx.client, OPERATION_SCOPES.readEnvironment);
85612
86206
  if (denied) return denied;
@@ -86028,11 +86622,6 @@ async function handleAccounts(method, payload, ctx) {
86028
86622
 
86029
86623
  // src/rpc/session-provider-handlers.ts
86030
86624
  init_environment();
86031
- var SESSION_PROVIDER_MUTATING_METHODS = [
86032
- "sessionProviders.create",
86033
- "sessionProviders.update",
86034
- "sessionProviders.delete"
86035
- ];
86036
86625
  function requireScopes6(client3, scopes) {
86037
86626
  if (!hasAllScopes(client3.scopes, scopes)) {
86038
86627
  return { error: { code: "forbidden", message: `missing scopes: ${scopes.join(", ")}` } };
@@ -86282,72 +86871,8 @@ function clearWatchBuffersForClient(clientSessionId) {
86282
86871
  }
86283
86872
  }
86284
86873
  var MAX_TURN_ADDITIONAL_DIRS = 64;
86285
- var MUTATING_METHODS = /* @__PURE__ */ new Set([
86286
- "terminal.create",
86287
- "terminal.write",
86288
- "terminal.resize",
86289
- "terminal.kill",
86290
- "project.open",
86291
- "project.update",
86292
- "project.remove",
86293
- "workspace.writeFile",
86294
- "workspace.rename",
86295
- "workspace.move",
86296
- "workspace.delete",
86297
- "workspace.mkdir",
86298
- "workspace.watchStart",
86299
- "workspace.watchStop",
86300
- "workspace.tailWatchStart",
86301
- "workspace.tailWatchStop",
86302
- "git.clone",
86303
- "git.switchBranch",
86304
- "git.createBranch",
86305
- "git.worktreeActivate",
86306
- "git.worktreeAssignBranch",
86307
- "git.worktreeHandoff",
86308
- "session.create",
86309
- "session.setCwd",
86310
- "session.patchSettings",
86311
- "session.fork",
86312
- "session.send",
86313
- "session.interrupt",
86314
- "session.respondPermission",
86315
- "session.respondQuestion",
86316
- "session.respondPlan",
86317
- "session.claimHostAction",
86318
- "session.respondHostAction",
86319
- "harness.probe",
86320
- "session.acquireControl",
86321
- "session.renewControl",
86322
- "session.releaseControl",
86323
- "session.close",
86324
- "session.remove",
86325
- "session.rename",
86326
- "session.setTags",
86327
- "session.setUiFlags",
86328
- // pin/hide
86329
- "terminal.acquireControl",
86330
- "terminal.renewControl",
86331
- "terminal.releaseControl",
86332
- "collaboration.request",
86333
- "collaboration.start",
86334
- "collaboration.send",
86335
- "provider.createCredential",
86336
- "provider.updateCredential",
86337
- "provider.deleteCredential",
86338
- "provider.setBinding",
86339
- "provider.clearBinding",
86340
- "provider.upsertCustomPlatform",
86341
- "provider.deleteCustomPlatform",
86342
- "provider.importBundle",
86343
- "settings.patch",
86344
- ...RESOURCE_MUTATING_METHODS,
86345
- ...AUTOMATION_MUTATING_METHODS,
86346
- ...SESSION_PROVIDER_MUTATING_METHODS,
86347
- ...CODEX_MUTATING_METHODS
86348
- ]);
86349
86874
  async function dispatchRpc(method, payload, ctx) {
86350
- if (MUTATING_METHODS.has(method)) {
86875
+ if (isNodeMutatingCall(method, payload)) {
86351
86876
  if (!ctx.idempotencyKey) {
86352
86877
  return {
86353
86878
  error: {
@@ -86405,6 +86930,7 @@ async function dispatchRpc(method, payload, ctx) {
86405
86930
  }
86406
86931
  return dispatchRpcInner(method, payload, ctx);
86407
86932
  }
86933
+ var PLUGIN_RELOAD_METHODS = /* @__PURE__ */ new Set(["plugins.setEnabled", "plugins.install", "plugins.update", "plugins.delete"]);
86408
86934
  async function dispatchRpcInner(method, payload, ctx) {
86409
86935
  const resource = dispatchResourceRpc(method, payload, {
86410
86936
  client: ctx.client,
@@ -86412,7 +86938,11 @@ async function dispatchRpcInner(method, payload, ctx) {
86412
86938
  harnesses: ctx.harnesses,
86413
86939
  providers: ctx.providers
86414
86940
  });
86415
- if (resource) return await resource;
86941
+ if (resource) {
86942
+ const result = await resource;
86943
+ if (!result.error && PLUGIN_RELOAD_METHODS.has(method)) void ctx.sessions.reloadPlugins();
86944
+ return result;
86945
+ }
86416
86946
  const automation = dispatchAutomationRpc(method, payload, {
86417
86947
  client: ctx.client,
86418
86948
  projects: ctx.projects,
@@ -86588,6 +87118,8 @@ async function dispatchRpcInner(method, payload, ctx) {
86588
87118
  return handleTerminalReleaseControl(payload, ctx);
86589
87119
  case "session.send":
86590
87120
  return handleSessionSend(payload, ctx);
87121
+ case "session.modUi":
87122
+ return handleSessionModUi(payload, ctx);
86591
87123
  case "session.interrupt":
86592
87124
  return handleSessionInterrupt(payload, ctx);
86593
87125
  case "session.respondPermission":
@@ -88347,6 +88879,28 @@ async function handleSessionSend(payload, ctx) {
88347
88879
  return mapThrown8(err);
88348
88880
  }
88349
88881
  }
88882
+ async function handleSessionModUi(payload, ctx) {
88883
+ const p3 = asRecord24(payload);
88884
+ const op = String(p3.op ?? "");
88885
+ const denied = requireScopes8(ctx.client, MOD_UI_MUTATING_OPS.has(op) ? OPERATION_SCOPES.operateSession : OPERATION_SCOPES.readSession);
88886
+ if (denied) return denied;
88887
+ try {
88888
+ const result = await ctx.sessions.modUi({
88889
+ sessionId: String(p3.sessionId ?? ""),
88890
+ op,
88891
+ request: asRecord24(p3.request),
88892
+ client: { clientSessionId: ctx.client.clientSessionId },
88893
+ leaseId: typeof p3.leaseId === "string" ? p3.leaseId : void 0,
88894
+ generation: typeof p3.generation === "string" ? p3.generation : void 0
88895
+ });
88896
+ return { result };
88897
+ } catch (err) {
88898
+ if (err.name === MOD_UI_UNAVAILABLE) {
88899
+ return { error: { code: "unavailable", message: `${MOD_UI_UNAVAILABLE}: ${err.message}` } };
88900
+ }
88901
+ return mapThrown8(err);
88902
+ }
88903
+ }
88350
88904
  function handleSessionInterrupt(payload, ctx) {
88351
88905
  const denied = requireScopes8(ctx.client, OPERATION_SCOPES.operateSession);
88352
88906
  if (denied) return denied;
@@ -88545,7 +89099,7 @@ function handleSessionEvents(payload, ctx) {
88545
89099
  if (denied) return denied;
88546
89100
  const p3 = asRecord24(payload);
88547
89101
  const after = String(p3.afterSequence ?? "0");
88548
- return { result: { events: ctx.sessions.listEventsAfter(after) } };
89102
+ return { result: { events: ctx.sessions.listEventsAfter(after, ctx.client) } };
88549
89103
  }
88550
89104
  function handleSessionMessagesList(payload, ctx) {
88551
89105
  const denied = requireScopes8(ctx.client, OPERATION_SCOPES.readSession);
@@ -89648,7 +90202,7 @@ function hashFileBounded(absolutePath, size) {
89648
90202
  import { existsSync as existsSync40, mkdirSync as mkdirSync22, realpathSync as realpathSync5, rmSync as rmSync8, writeFileSync as writeFileSync17 } from "node:fs";
89649
90203
  import { join as join35, resolve as resolve14 } from "node:path";
89650
90204
  import { tmpdir as tmpdir2 } from "node:os";
89651
- import { randomUUID as randomUUID10 } from "node:crypto";
90205
+ import { randomUUID as randomUUID11 } from "node:crypto";
89652
90206
 
89653
90207
  // ../../packages/runtime/src/git/sanitize-ref.ts
89654
90208
  var CONTROL_CHAR_RE = /[\x00-\x1f\x7f]/;
@@ -90317,7 +90871,7 @@ var WorkspaceGitService = class {
90317
90871
  const mainStatus = git(diff.mainDir, ["status", "--porcelain"]).trim();
90318
90872
  if (mainStatus) return { ok: false, reason: "main-dirty" };
90319
90873
  const patch = git(diff.worktreePath, ["diff", "--binary", diff.base, diff.tree]);
90320
- const patchFile = join35(tmpdir2(), `s1-handoff-${randomUUID10()}.patch`);
90874
+ const patchFile = join35(tmpdir2(), `s1-handoff-${randomUUID11()}.patch`);
90321
90875
  writeFileSync17(patchFile, `${patch}
90322
90876
  `);
90323
90877
  if (git(diff.mainDir, ["status", "--porcelain"]).trim()) {
@@ -90379,7 +90933,7 @@ var WorkspaceGitService = class {
90379
90933
  };
90380
90934
  }
90381
90935
  writeWorkingTree(worktreePath) {
90382
- const tmpIndex = join35(tmpdir2(), `s1-handoff-${randomUUID10()}.index`);
90936
+ const tmpIndex = join35(tmpdir2(), `s1-handoff-${randomUUID11()}.index`);
90383
90937
  const env = { GIT_INDEX_FILE: tmpIndex };
90384
90938
  try {
90385
90939
  git(worktreePath, ["read-tree", "HEAD"], env);
@@ -90425,7 +90979,7 @@ function parseBranchPorcelain(raw) {
90425
90979
  init_session();
90426
90980
 
90427
90981
  // ../../packages/runtime/src/lease/control-lease.ts
90428
- import { randomUUID as randomUUID11 } from "node:crypto";
90982
+ import { randomUUID as randomUUID12 } from "node:crypto";
90429
90983
  var DEFAULT_TTL_MS = 3e4;
90430
90984
  var MAX_TTL_MS = 15 * 60 * 1e3;
90431
90985
  function resourceKey(resource) {
@@ -90442,7 +90996,7 @@ function clampTtlMs(ttlMs) {
90442
90996
  var ControlLeaseService = class {
90443
90997
  constructor(db) {
90444
90998
  this.db = db;
90445
- this.leaseEpoch = randomUUID11();
90999
+ this.leaseEpoch = randomUUID12();
90446
91000
  }
90447
91001
  db;
90448
91002
  leaseEpoch;
@@ -90473,7 +91027,7 @@ var ControlLeaseService = class {
90473
91027
  expiresAt: new Date(expiresAt2).toISOString()
90474
91028
  };
90475
91029
  }
90476
- const leaseId = randomUUID11();
91030
+ const leaseId = randomUUID12();
90477
91031
  const generation = existing && existing.epoch === this.leaseEpoch ? String(Number(existing.generation || "0") + 1) : "1";
90478
91032
  const expiresAt = now + ttl;
90479
91033
  this.db.prepare(
@@ -90562,7 +91116,7 @@ import { dirname as dirname20, join as join37 } from "node:path";
90562
91116
  // ../../packages/runtime/src/mcp-apps/resource-store.ts
90563
91117
  init_mcp_apps();
90564
91118
  init_mcp_app_resource();
90565
- import { createHash as createHash11, randomUUID as randomUUID12 } from "node:crypto";
91119
+ import { createHash as createHash11, randomUUID as randomUUID13 } from "node:crypto";
90566
91120
  import { existsSync as existsSync41, mkdirSync as mkdirSync23, readFileSync as readFileSync21, readdirSync as readdirSync13, renameSync as renameSync7, rmSync as rmSync9, statSync as statSync15, utimesSync, writeFileSync as writeFileSync18 } from "node:fs";
90567
91121
  import { join as join36 } from "node:path";
90568
91122
  function createMcpAppResourceStore(directory) {
@@ -90578,7 +91132,7 @@ function createMcpAppResourceStore(directory) {
90578
91132
  const hash2 = digest(snapshot.html), file2 = path(hash2);
90579
91133
  if (!existsSync41(file2) || statSync15(file2).size > MCP_APP_HTML_MAX_BYTES || digest(readFileSync21(file2, "utf8")) !== hash2) {
90580
91134
  mkdirSync23(directory, { recursive: true });
90581
- const temporary = join36(directory, `${hash2}.${randomUUID12()}.tmp`);
91135
+ const temporary = join36(directory, `${hash2}.${randomUUID13()}.tmp`);
90582
91136
  try {
90583
91137
  writeFileSync18(temporary, snapshot.html, { encoding: "utf8", mode: 384, flag: "wx" });
90584
91138
  renameSync7(temporary, file2);
@@ -91033,7 +91587,7 @@ function prepareLaunchStart(store, callerSessionId, input) {
91033
91587
  }
91034
91588
 
91035
91589
  // ../../packages/runtime/src/collaboration/store.ts
91036
- import { randomUUID as randomUUID13 } from "node:crypto";
91590
+ import { randomUUID as randomUUID14 } from "node:crypto";
91037
91591
  var GRANT_COLUMNS = `credential_hash AS grant_id, parent_session_id, child_session_id,
91038
91592
  agent_id, task, config_json, task_sent, COALESCE(kind, 'spawn') AS kind, started_at`;
91039
91593
  var MESSAGE_COLUMNS = `id, sequence, sender_session_id, recipient_session_id, client_message_id, content, created_at`;
@@ -91116,7 +91670,7 @@ var CollaborationStore = class {
91116
91670
  * handoff grants bind their session on start. The brief arrives on start.
91117
91671
  */
91118
91672
  createGrant(input) {
91119
- const grantId = randomUUID13();
91673
+ const grantId = randomUUID14();
91120
91674
  try {
91121
91675
  this.db.prepare(`
91122
91676
  INSERT INTO session_collaboration_grants
@@ -91188,7 +91742,7 @@ var CollaborationStore = class {
91188
91742
  }
91189
91743
  insertMessage(grantId, input) {
91190
91744
  const row = {
91191
- id: randomUUID13(),
91745
+ id: randomUUID14(),
91192
91746
  sequence: this.nextSequence(grantId),
91193
91747
  sender_session_id: input.senderSessionId,
91194
91748
  recipient_session_id: input.recipientSessionId,
@@ -91412,7 +91966,7 @@ function listCollaborationProfiles(deps) {
91412
91966
  }
91413
91967
 
91414
91968
  // src/session/collaboration-request.ts
91415
- import { randomUUID as randomUUID14 } from "node:crypto";
91969
+ import { randomUUID as randomUUID15 } from "node:crypto";
91416
91970
 
91417
91971
  // src/session/collaboration-context.ts
91418
91972
  init_environment();
@@ -91448,7 +92002,7 @@ function normalizeLaunches(ctx, input, profileList) {
91448
92002
  const profiles = new Map(profileList.map((p3) => [p3.id, p3]));
91449
92003
  return input.launches.map((launch2) => {
91450
92004
  const mode = resolveLaunchMode(launch2.mode);
91451
- const launchId = launch2.launchId?.trim() || randomUUID14();
92005
+ const launchId = launch2.launchId?.trim() || randomUUID15();
91452
92006
  if (mode === "link") {
91453
92007
  const peerSessionId = launch2.sessionId?.trim();
91454
92008
  if (!peerSessionId) {
@@ -92206,7 +92760,7 @@ var IdempotencyService = class {
92206
92760
  };
92207
92761
 
92208
92762
  // src/provider/provider-store.ts
92209
- import { randomUUID as randomUUID15 } from "node:crypto";
92763
+ import { randomUUID as randomUUID16 } from "node:crypto";
92210
92764
 
92211
92765
  // src/provider/secret-crypto.ts
92212
92766
  import { existsSync as existsSync44, mkdirSync as mkdirSync24, readFileSync as readFileSync22, writeFileSync as writeFileSync19, chmodSync as chmodSync2 } from "node:fs";
@@ -92293,7 +92847,7 @@ var ProviderStore = class {
92293
92847
  }
92294
92848
  createCredential(input) {
92295
92849
  const now = (/* @__PURE__ */ new Date()).toISOString();
92296
- const id = input.id?.trim() || randomUUID15();
92850
+ const id = input.id?.trim() || randomUUID16();
92297
92851
  const maxOrder = this.db.prepare("SELECT MAX(sort_order) as m FROM provider_credentials").get()?.m ?? -1;
92298
92852
  this.db.prepare(
92299
92853
  `INSERT INTO provider_credentials
@@ -92489,7 +93043,7 @@ var ProviderStore = class {
92489
93043
  };
92490
93044
 
92491
93045
  // src/session/host-action-mcp-server.ts
92492
- import { randomUUID as randomUUID17 } from "node:crypto";
93046
+ import { randomUUID as randomUUID18 } from "node:crypto";
92493
93047
  import {
92494
93048
  createServer as createHttpServer
92495
93049
  } from "node:http";
@@ -96084,7 +96638,7 @@ init_interaction_memory();
96084
96638
  // ../../packages/runtime/src/fs/interaction-memory.ts
96085
96639
  init_superone_home();
96086
96640
  init_interaction_memory();
96087
- import { createHash as createHash13, randomUUID as randomUUID16 } from "node:crypto";
96641
+ import { createHash as createHash13, randomUUID as randomUUID17 } from "node:crypto";
96088
96642
  import { lstat, mkdir, open, readdir, rename, rm } from "node:fs/promises";
96089
96643
  import { constants as constants4 } from "node:fs";
96090
96644
  import { join as join38 } from "node:path";
@@ -96280,7 +96834,7 @@ function indexEntry(note) {
96280
96834
  };
96281
96835
  }
96282
96836
  async function writeAtomic(dir, name, raw) {
96283
- const temp = join38(dir, `.${name}.${randomUUID16()}.tmp`);
96837
+ const temp = join38(dir, `.${name}.${randomUUID17()}.tmp`);
96284
96838
  try {
96285
96839
  const file2 = await open(temp, "wx", 384);
96286
96840
  try {
@@ -104766,7 +105320,7 @@ function headerValue(req, name) {
104766
105320
  return typeof value === "string" && value.length > 0 ? value : null;
104767
105321
  }
104768
105322
  async function startHostActionMcpServer(opts) {
104769
- const masterToken = opts.masterToken ?? randomUUID17();
105323
+ const masterToken = opts.masterToken ?? randomUUID18();
104770
105324
  const httpSessions = /* @__PURE__ */ new Map();
104771
105325
  const httpSessionsBySuperone = /* @__PURE__ */ new Map();
104772
105326
  let httpUrl2 = "";
@@ -104834,7 +105388,7 @@ async function startHostActionMcpServer(opts) {
104834
105388
  });
104835
105389
  let sessionRef;
104836
105390
  const transport = new StreamableHTTPServerTransport({
104837
- sessionIdGenerator: randomUUID17,
105391
+ sessionIdGenerator: randomUUID18,
104838
105392
  onsessioninitialized: (id) => {
104839
105393
  if (sessionRef) httpSessions.set(id, sessionRef);
104840
105394
  },
@@ -105618,7 +106172,7 @@ function computeNextRunAt(schedule) {
105618
106172
  }
105619
106173
 
105620
106174
  // ../../packages/runtime/src/automations/store.ts
105621
- import { randomUUID as randomUUID18 } from "node:crypto";
106175
+ import { randomUUID as randomUUID19 } from "node:crypto";
105622
106176
  function toRecord(row, projectPath) {
105623
106177
  return {
105624
106178
  id: row.id,
@@ -105650,7 +106204,7 @@ function createAutomationStore(db, resolveProjectPath2) {
105650
106204
  return { ...toRecord(row, path), projectId: row.project_id };
105651
106205
  },
105652
106206
  create(projectId, projectPath, data) {
105653
- const id = randomUUID18();
106207
+ const id = randomUUID19();
105654
106208
  const now = (/* @__PURE__ */ new Date()).toISOString();
105655
106209
  const nextRunAt = computeNextRunAt(data.schedule);
105656
106210
  db.prepare(