@super-one/cli 0.75.4 → 0.75.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/MANIFEST.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@super-one/cli",
3
- "version": "0.75.4",
3
+ "version": "0.75.5",
4
4
  "kind": "npm",
5
5
  "minNodeMajor": 20,
6
- "builtAt": "2026-10-21T04:02:10.353Z"
6
+ "builtAt": "2026-10-22T17:44:54.526Z"
7
7
  }
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.75.4".trim()) {
141
- return "0.75.4".trim();
140
+ if ("0.75.5".trim()) {
141
+ return "0.75.5".trim();
142
142
  }
143
143
  const fromDist = readDistManifestVersion();
144
144
  if (fromDist) return fromDist;
@@ -11786,6 +11786,71 @@ function transcriptLengths(message) {
11786
11786
  items: Object.fromEntries((message.metadata?.codex?.items ?? []).map((item) => [item.id, itemText(item)?.length ?? -1]))
11787
11787
  };
11788
11788
  }
11789
+ function boundaryCursor(boundary, source) {
11790
+ if (boundary.cursor) return boundary;
11791
+ const items = source.metadata?.codex?.items ?? [];
11792
+ const contentEdge = prefixEdge(boundary.content ?? {}, contentKeys(source.content), source.content.map(blockText));
11793
+ const itemEdge = prefixEdge(boundary.items ?? {}, items.map((item) => item.id), items.map(itemText));
11794
+ if (contentEdge === null || itemEdge === null) return boundary;
11795
+ return {
11796
+ messageId: boundary.messageId,
11797
+ order: boundary.order,
11798
+ content: {},
11799
+ items: {},
11800
+ cursor: true,
11801
+ ...contentEdge === "end" ? {} : { at: contentEdge.key, offset: contentEdge.offset },
11802
+ ...itemEdge === "end" ? {} : { atItem: itemEdge.key, itemOffset: itemEdge.offset }
11803
+ };
11804
+ }
11805
+ function expandBoundaryCursor(boundary, source) {
11806
+ if (!boundary.cursor) return boundary;
11807
+ const items = source.metadata?.codex?.items ?? [];
11808
+ return {
11809
+ ...boundary,
11810
+ content: edgeMap(contentKeys(source.content), source.content.map(blockText), boundary.at, boundary.offset ?? 0),
11811
+ items: edgeMap(items.map((item) => item.id), items.map(itemText), boundary.atItem, boundary.itemOffset ?? 0),
11812
+ cursor: false
11813
+ };
11814
+ }
11815
+ function prefixEdge(map2, keys, texts) {
11816
+ let partial2 = null;
11817
+ for (let index = 0; index < keys.length; index++) {
11818
+ const key = keys[index];
11819
+ const saved = map2[key];
11820
+ const text2 = texts[index];
11821
+ if (saved === void 0) {
11822
+ const edge = partial2 ?? { key, offset: 0 };
11823
+ const edgeAt = partial2 ? keys.indexOf(partial2.key) : index;
11824
+ for (let later = edgeAt + 1; later < keys.length; later++) {
11825
+ if (map2[keys[later]] !== void 0) return null;
11826
+ }
11827
+ return edge;
11828
+ }
11829
+ if (text2 !== void 0 && saved < text2.length) {
11830
+ if (partial2 || saved < 0) return null;
11831
+ partial2 = { key, offset: saved };
11832
+ continue;
11833
+ }
11834
+ if (partial2) return null;
11835
+ }
11836
+ return partial2 ?? "end";
11837
+ }
11838
+ function edgeMap(keys, texts, at2, offset) {
11839
+ const map2 = {};
11840
+ const end = at2 === void 0 ? keys.length : keys.indexOf(at2);
11841
+ if (end < 0) return map2;
11842
+ for (let index = 0; index < end; index++) {
11843
+ const key2 = keys[index];
11844
+ const text3 = texts[index];
11845
+ if (key2 === void 0) continue;
11846
+ map2[key2] = text3 === void 0 ? -1 : text3.length;
11847
+ }
11848
+ if (at2 === void 0) return map2;
11849
+ const key = keys[end];
11850
+ const text2 = texts[end];
11851
+ if (key !== void 0 && text2 !== void 0 && offset > 0) map2[key] = offset;
11852
+ return map2;
11853
+ }
11789
11854
  function resolveTranscriptBoundaries(cuts, lengths) {
11790
11855
  let previous = { content: {}, items: {} };
11791
11856
  return cuts.map((cut) => {
@@ -12814,6 +12879,8 @@ var init_agent_types = __esm({
12814
12879
  ENVIRONMENT_LIST_SESSIONS: "environment:listSessions",
12815
12880
  /** Cross-project pinned sessions for one environment (sidebar Pinned section). */
12816
12881
  ENVIRONMENT_LIST_PINNED_SESSIONS: "environment:listPinnedSessions",
12882
+ /** Cross-project session title search for one environment (`@session`, plain `@`). */
12883
+ ENVIRONMENT_SEARCH_SESSIONS: "environment:searchSessionsByTitle",
12817
12884
  /** Unsent composer drafts, stored in the environment that owns the project. */
12818
12885
  ENVIRONMENT_LIST_DRAFTS: "environment:listDrafts",
12819
12886
  ENVIRONMENT_UPSERT_DRAFT: "environment:upsertDraft",
@@ -70247,6 +70314,74 @@ var init_acp_todos = __esm({
70247
70314
  }
70248
70315
  });
70249
70316
 
70317
+ // ../../packages/shared/src/monitor-session-hold.ts
70318
+ var MonitorSessionHold;
70319
+ var init_monitor_session_hold = __esm({
70320
+ "../../packages/shared/src/monitor-session-hold.ts"() {
70321
+ "use strict";
70322
+ MonitorSessionHold = class {
70323
+ ids = /* @__PURE__ */ new Set();
70324
+ holding = false;
70325
+ streaming = false;
70326
+ /** The status event just published was an error; leave it visible. */
70327
+ suppressFollowUp = false;
70328
+ note(event) {
70329
+ if (event.type === "task_started") {
70330
+ if (event.taskType === "monitor" && event.taskId) this.ids.add(event.taskId);
70331
+ return;
70332
+ }
70333
+ if (event.type !== "task_notification") return;
70334
+ const status2 = event.taskStatus;
70335
+ if ((status2 === "completed" || status2 === "stopped" || status2 === "failed") && event.taskId) {
70336
+ this.ids.delete(event.taskId);
70337
+ }
70338
+ }
70339
+ /** Rewrite a terminal idle while a monitor is still running. */
70340
+ adjust(event) {
70341
+ this.suppressFollowUp = false;
70342
+ if (event.type !== "status_change") return event;
70343
+ if (event.status === "streaming") {
70344
+ this.streaming = true;
70345
+ return event;
70346
+ }
70347
+ this.streaming = false;
70348
+ if (event.status === "error") {
70349
+ this.holding = false;
70350
+ this.suppressFollowUp = true;
70351
+ return event;
70352
+ }
70353
+ if (event.status === "idle" && this.ids.size > 0) {
70354
+ this.holding = true;
70355
+ return { ...event, status: "background" };
70356
+ }
70357
+ if (event.status === "idle") this.holding = false;
70358
+ return event;
70359
+ }
70360
+ /**
70361
+ * Status to publish after `event` was noted and published.
70362
+ * Null when the session status should stay as that event left it.
70363
+ */
70364
+ followUp() {
70365
+ if (this.streaming || this.suppressFollowUp) return null;
70366
+ if (this.ids.size > 0) {
70367
+ if (this.holding) return null;
70368
+ this.holding = true;
70369
+ return { type: "status_change", status: "background" };
70370
+ }
70371
+ if (!this.holding) return null;
70372
+ this.holding = false;
70373
+ return { type: "status_change", status: "idle" };
70374
+ }
70375
+ reset() {
70376
+ this.ids.clear();
70377
+ this.holding = false;
70378
+ this.streaming = false;
70379
+ this.suppressFollowUp = false;
70380
+ }
70381
+ };
70382
+ }
70383
+ });
70384
+
70250
70385
  // ../../packages/shared/src/effort-labels.ts
70251
70386
  function isAcpEffortConfigOption(option) {
70252
70387
  const id = option.id?.trim().toLowerCase();
@@ -71788,6 +71923,11 @@ function mapSubagentFinished(u2, state) {
71788
71923
  ...output ? { resultText: output } : error51 ? { resultText: error51 } : {}
71789
71924
  }];
71790
71925
  }
71926
+ function backgroundTaskType(u2, command) {
71927
+ if (strField(u2, "monitor_description", "monitorDescription")) return "monitor";
71928
+ if (command.startsWith("[monitor] ")) return "monitor";
71929
+ return "bash";
71930
+ }
71791
71931
  function mapTaskBackgrounded(u2, state) {
71792
71932
  const taskId = strField(u2, "task_id", "taskId");
71793
71933
  if (!taskId) return [];
@@ -71814,7 +71954,7 @@ function mapTaskBackgrounded(u2, state) {
71814
71954
  taskId,
71815
71955
  ...toolCallId ? { toolUseId: toolCallId } : {},
71816
71956
  description,
71817
- taskType: strField(u2, "monitor_description", "monitorDescription") ? "monitor" : "bash"
71957
+ taskType: backgroundTaskType(u2, command)
71818
71958
  }];
71819
71959
  }
71820
71960
  function mapTaskCompleted(u2, state) {
@@ -72688,8 +72828,15 @@ function createAcpAgentEventMapper(options) {
72688
72828
  let currentMessageId = options.messageId;
72689
72829
  let started = false;
72690
72830
  let terminal = false;
72831
+ const monitorHold = new MonitorSessionHold();
72832
+ const emitHeld = (event) => {
72833
+ monitorHold.note(event);
72834
+ options.emit(monitorHold.adjust(event));
72835
+ const follow = monitorHold.followUp();
72836
+ if (follow) options.emit(follow);
72837
+ };
72691
72838
  const emitMessageStart = (messageId) => {
72692
- options.emit({
72839
+ emitHeld({
72693
72840
  type: "message_start",
72694
72841
  message: {
72695
72842
  id: messageId,
@@ -72705,13 +72852,13 @@ function createAcpAgentEventMapper(options) {
72705
72852
  if (terminal) return;
72706
72853
  terminal = true;
72707
72854
  if (interrupted) {
72708
- for (const event of cancelOpenAcpTools(currentMessageId, openTools)) options.emit(event);
72855
+ for (const event of cancelOpenAcpTools(currentMessageId, openTools)) emitHeld(event);
72709
72856
  }
72710
72857
  const info = interrupted ? void 0 : errorInfo ?? buildAgentErrorInfo(error51);
72711
72858
  for (const messageId of localMessageIds) {
72712
- options.emit(interrupted ? { type: "message_interrupted", messageId } : { type: "message_error", messageId, error: error51, errorInfo: info });
72859
+ emitHeld(interrupted ? { type: "message_interrupted", messageId } : { type: "message_error", messageId, error: error51, errorInfo: info });
72713
72860
  }
72714
- options.emit({ type: "status_change", status: interrupted ? "idle" : "error" });
72861
+ emitHeld({ type: "status_change", status: interrupted ? "idle" : "error" });
72715
72862
  };
72716
72863
  return {
72717
72864
  start(providerSessionId) {
@@ -72719,9 +72866,9 @@ function createAcpAgentEventMapper(options) {
72719
72866
  started = true;
72720
72867
  if (providerSessionId) xaiCorrelation.parentSessionId = providerSessionId;
72721
72868
  emitMessageStart(options.messageId);
72722
- options.emit({ type: "status_change", status: "streaming" });
72869
+ emitHeld({ type: "status_change", status: "streaming" });
72723
72870
  if (providerSessionId) {
72724
- options.emit({ type: "provider_session_id", providerSessionId });
72871
+ emitHeld({ type: "provider_session_id", providerSessionId });
72725
72872
  }
72726
72873
  },
72727
72874
  apply(update, notificationMeta) {
@@ -72768,9 +72915,9 @@ function createAcpAgentEventMapper(options) {
72768
72915
  if (event.type === "content_delta" && event.delta.type === "text" && !event.delta.parentToolUseId) {
72769
72916
  textDelta += event.delta.text;
72770
72917
  }
72771
- options.emit(event);
72918
+ emitHeld(event);
72772
72919
  }
72773
- for (const event of migrate) options.emit(event);
72920
+ for (const event of migrate) emitHeld(event);
72774
72921
  return { textDelta: textDelta || null };
72775
72922
  },
72776
72923
  applyXaiNotification(method, params) {
@@ -72782,8 +72929,8 @@ function createAcpAgentEventMapper(options) {
72782
72929
  );
72783
72930
  trackOpenAcpTools(openTools, events);
72784
72931
  const migrate = noteToolCorrelationFromAgentEvents(events, xaiCorrelation);
72785
- for (const event of events) options.emit(event);
72786
- for (const event of migrate) options.emit(event);
72932
+ for (const event of events) emitHeld(event);
72933
+ for (const event of migrate) emitHeld(event);
72787
72934
  },
72788
72935
  complete(stopReason = "end_turn") {
72789
72936
  if (terminal) return;
@@ -72794,9 +72941,9 @@ function createAcpAgentEventMapper(options) {
72794
72941
  }
72795
72942
  terminal = true;
72796
72943
  for (const messageId of localMessageIds) {
72797
- options.emit({ type: "message_complete", messageId });
72944
+ emitHeld({ type: "message_complete", messageId });
72798
72945
  }
72799
- options.emit({ type: "status_change", status: "idle" });
72946
+ emitHeld({ type: "status_change", status: "idle" });
72800
72947
  },
72801
72948
  fail: fail3
72802
72949
  };
@@ -72805,6 +72952,7 @@ var init_agent_event_mapper3 = __esm({
72805
72952
  "../../packages/acp/src/agent-event-mapper.ts"() {
72806
72953
  "use strict";
72807
72954
  init_acp_todos();
72955
+ init_monitor_session_hold();
72808
72956
  init_agent_error();
72809
72957
  init_fs();
72810
72958
  init_config_map();
@@ -101937,6 +102085,7 @@ function projectEvent(event, messages) {
101937
102085
 
101938
102086
  // ../../packages/runtime/src/stream/delivery/window-views.ts
101939
102087
  init_codex_content();
102088
+ init_transcript_boundary();
101940
102089
 
101941
102090
  // ../../packages/shared/src/transcript-window/content-digest.ts
101942
102091
  function contentDigest(input) {
@@ -102496,7 +102645,12 @@ function transcriptView(messages) {
102496
102645
  rows.push(...cached5.rows);
102497
102646
  continue;
102498
102647
  }
102499
- const cursors = cuts.length ? resolveTranscriptBoundaries(cuts, transcriptLengths(source)) : [];
102648
+ const opened = cuts.map((cut) => {
102649
+ const boundary = cut.metadata?.transcriptBoundary;
102650
+ if (!boundary?.cursor) return cut;
102651
+ return { ...cut, metadata: { ...cut.metadata, transcriptBoundary: expandBoundaryCursor(boundary, source) } };
102652
+ });
102653
+ const cursors = opened.length ? resolveTranscriptBoundaries(opened, transcriptLengths(source)) : [];
102500
102654
  const legacy = isLegacyCodexMessage(source);
102501
102655
  const segmentOf = (message) => legacy ? withCodexContent(message) : message;
102502
102656
  const finalResponse = (content) => content.filter((block) => block.type === "text" && block.id === void 0);
@@ -103733,14 +103887,37 @@ var MAX_HELD = 64;
103733
103887
  var SessionFragments = class {
103734
103888
  /** Times a message was fragmented and planned. A reparsed copy of the same content does not count. */
103735
103889
  plans = 0;
103890
+ /** Transcript the current serve or patch is reading, so a boundary can find the message it cuts. */
103891
+ transcript = null;
103736
103892
  fragmenter = new MessageFragmenter();
103737
103893
  cache = /* @__PURE__ */ new WeakMap();
103738
103894
  foldedCache = /* @__PURE__ */ new WeakMap();
103739
103895
  /** Last plan for a message id, so a newly parsed row does not plan the message again. */
103740
103896
  bySignature = /* @__PURE__ */ new Map();
103897
+ bind(transcript) {
103898
+ this.transcript = transcript;
103899
+ }
103741
103900
  of(message, folds = false, cuts) {
103901
+ const prepared = this.cursorMessage(message);
103902
+ if (prepared !== message) return this.fragmenter.fragment(projectWindowMessage(prepared));
103742
103903
  return folds ? this.folded(message, cuts).fragments : this.entry(message).fragments;
103743
103904
  }
103905
+ /** Wire copy of a boundary row. The stored message, and the cuts fold planning reads, stay the full map. */
103906
+ cursorMessage(message) {
103907
+ const boundary = message.metadata?.transcriptBoundary;
103908
+ if (!boundary || boundary.cursor || !this.transcript) return message;
103909
+ const index = this.transcript.indexOf(boundary.messageId);
103910
+ if (index < 0) return message;
103911
+ let source;
103912
+ try {
103913
+ source = this.transcript.messageAt(index);
103914
+ } catch {
103915
+ return message;
103916
+ }
103917
+ const cursor = boundaryCursor(boundary, source);
103918
+ if (cursor === boundary) return message;
103919
+ return { ...message, metadata: { ...message.metadata, transcriptBoundary: cursor } };
103920
+ }
103744
103921
  /**
103745
103922
  * The message with the process its settled turn collapses cut down to folds.
103746
103923
  * `cuts` are the other rows that split this turn. A later read of the same
@@ -103818,6 +103995,7 @@ var WindowViews = class {
103818
103995
  if (!transcript) throw new Error("transcript window needs messages");
103819
103996
  const folds = input.request.folds === true;
103820
103997
  const session = this.session(input.sessionId);
103998
+ session.fragments.bind(transcript);
103821
103999
  const cuts = boundaryCuts(input.messages ?? transcript.boundaryMessages?.() ?? []);
103822
104000
  const selected = selectTranscriptWindow(session.fragments.source(transcript, folds, cuts), input.request, input.budget);
103823
104001
  const extend2 = input.request.anchor && input.request.direction !== "around" ? input.request.direction ?? "before" : null;
@@ -103849,6 +104027,7 @@ var WindowViews = class {
103849
104027
  patches(sessionId, messages) {
103850
104028
  const session = this.sessions.get(sessionId);
103851
104029
  if (!session) return [];
104030
+ session.fragments.bind(arrayTranscript(messages));
103852
104031
  const cuts = boundaryCuts(messages);
103853
104032
  const out = [];
103854
104033
  for (const [holder, held] of session.holders) {
@@ -104016,7 +104195,7 @@ function diffHeld(held, messages, fragments, cuts) {
104016
104195
  let start = 0;
104017
104196
  for (let r = range.length - 1; r >= 0; r--) {
104018
104197
  const source = messages[range[r]];
104019
- if (held.seen.get(source.id) === source && held.messages.has(source.id)) continue;
104198
+ if (held.seen.get(source.id) === source && held.messages.has(source.id) && !source.metadata?.transcriptBoundary) continue;
104020
104199
  const { message, record: record13 } = diffMessage(held.messages.get(source.id), fragments.of(source, held.folds, cuts.get(source.id)), range[r], Math.max(0, Math.min(LIVE_MESSAGE_BUDGET.maxBytes, remaining)));
104021
104200
  const bytes = message ? patchBytes(message) : 0;
104022
104201
  if (bytes > remaining && changed.length) {
@@ -105409,6 +105588,103 @@ function applySessionTagOp(current, op) {
105409
105588
  return current.filter((tag) => !drop.has(tag));
105410
105589
  }
105411
105590
 
105591
+ // ../../packages/shared/src/mention-match-tier.ts
105592
+ var MENTION_WORD_SEPARATORS = [" ", "/", "-", "_", "."];
105593
+ var SEPARATORS = new Set(MENTION_WORD_SEPARATORS);
105594
+ var IDENTIFIER_KEY = { tier: 0, wholeSegment: 0, segmentLength: 0, textLength: 0 };
105595
+ function mentionMatchKey(text2, query) {
105596
+ const needle = Array.from(query.trim().toLowerCase());
105597
+ const hay = Array.from((text2 ?? "").toLowerCase());
105598
+ if (needle.length === 0) {
105599
+ return { tier: 0, wholeSegment: 0, segmentLength: segmentLengthAt(hay, 0), textLength: hay.length };
105600
+ }
105601
+ if (startsAt(hay, needle, 0)) return keyAt(hay, 0, needle.length, 0);
105602
+ for (let i = 1; i <= hay.length - needle.length; i++) {
105603
+ if (!SEPARATORS.has(hay[i - 1]) || !startsAt(hay, needle, i)) continue;
105604
+ return keyAt(hay, i, needle.length, 1);
105605
+ }
105606
+ for (let i = 0; i <= hay.length - needle.length; i++) {
105607
+ if (!startsAt(hay, needle, i)) continue;
105608
+ return keyAt(hay, i, needle.length, 2);
105609
+ }
105610
+ let at2 = 0;
105611
+ let start = -1;
105612
+ for (let i = 0; i < hay.length; i++) {
105613
+ if (hay[i] !== needle[at2]) continue;
105614
+ if (at2 === 0) start = i;
105615
+ at2 += 1;
105616
+ if (at2 === needle.length) {
105617
+ return { tier: 3, wholeSegment: 1, segmentLength: segmentLengthAt(hay, start), textLength: hay.length };
105618
+ }
105619
+ }
105620
+ return null;
105621
+ }
105622
+ function compareMentionMatchKeys(a, b3) {
105623
+ if (a == null && b3 == null) return 0;
105624
+ if (a == null) return 1;
105625
+ if (b3 == null) return -1;
105626
+ if (a.tier !== b3.tier) return a.tier - b3.tier;
105627
+ if (a.wholeSegment !== b3.wholeSegment) return a.wholeSegment - b3.wholeSegment;
105628
+ if (a.segmentLength !== b3.segmentLength) return a.segmentLength - b3.segmentLength;
105629
+ return a.textLength - b3.textLength;
105630
+ }
105631
+ function mentionMatchTier(text2, query) {
105632
+ return mentionMatchKey(text2, query)?.tier ?? null;
105633
+ }
105634
+ function gitMentionRefMatchKey(ref, query) {
105635
+ const needle = query.trim();
105636
+ if (!needle) return mentionMatchKey(ref.label, "");
105637
+ if (ref.kind === "commit") {
105638
+ if (ref.id.toLowerCase().startsWith(needle.toLowerCase())) return IDENTIFIER_KEY;
105639
+ return mentionMatchKey(ref.detail ?? "", needle);
105640
+ }
105641
+ if (ref.kind === "issue" || ref.kind === "pr") {
105642
+ const number5 = needle.replace(/^#/, "");
105643
+ if (/^\d+$/.test(number5) && ref.id.startsWith(number5)) return IDENTIFIER_KEY;
105644
+ return mentionMatchKey(ref.detail ?? "", needle);
105645
+ }
105646
+ return mentionMatchKey(ref.label, needle);
105647
+ }
105648
+ function keyAt(hay, start, needleLength, tier) {
105649
+ const end = start + needleLength;
105650
+ const boundary = end === hay.length || SEPARATORS.has(hay[end]);
105651
+ return {
105652
+ tier,
105653
+ wholeSegment: boundary ? 0 : 1,
105654
+ segmentLength: segmentLengthAt(hay, start),
105655
+ textLength: hay.length
105656
+ };
105657
+ }
105658
+ function segmentLengthAt(hay, index) {
105659
+ if (hay.length === 0) return 0;
105660
+ let start = Math.min(index, hay.length - 1);
105661
+ while (start > 0 && !SEPARATORS.has(hay[start - 1])) start -= 1;
105662
+ let end = start;
105663
+ while (end < hay.length && !SEPARATORS.has(hay[end])) end += 1;
105664
+ return end - start;
105665
+ }
105666
+ function startsAt(hay, needle, index) {
105667
+ if (index + needle.length > hay.length) return false;
105668
+ for (let i = 0; i < needle.length; i++) {
105669
+ if (hay[index + i] !== needle[i]) return false;
105670
+ }
105671
+ return true;
105672
+ }
105673
+
105674
+ // ../../packages/shared/src/session-title-search.ts
105675
+ var MAX_SESSION_SEARCH_PATHS = 64;
105676
+ var MAX_SESSION_SEARCH_PATH_LENGTH = 4096;
105677
+ function parseSessionSearchProjectPaths(value) {
105678
+ if (value === void 0 || value === null) return void 0;
105679
+ if (!Array.isArray(value) || value.length > MAX_SESSION_SEARCH_PATHS) return null;
105680
+ const paths = [];
105681
+ for (const item of value) {
105682
+ if (typeof item !== "string" || item.length === 0 || item.length > MAX_SESSION_SEARCH_PATH_LENGTH) return null;
105683
+ paths.push(item);
105684
+ }
105685
+ return paths;
105686
+ }
105687
+
105412
105688
  // ../../packages/shared/src/git-clone.ts
105413
105689
  import { spawn } from "node:child_process";
105414
105690
  import { existsSync as existsSync7, mkdirSync as mkdirSync3 } from "node:fs";
@@ -105970,24 +106246,60 @@ var HEX_PREFIX_RE = /^[0-9a-f]{4,40}$/i;
105970
106246
  var ISSUE_NUMBER_RE = /^#?(\d+)$/;
105971
106247
  var GH_ITEM_FIELDS = "number,title,state,author,updatedAt";
105972
106248
  var GH_PR_FIELDS = `${GH_ITEM_FIELDS},isDraft`;
106249
+ function gitMentionRefsFailure(err) {
106250
+ if (isNotGitRepoError(err)) return { ok: false, reason: "not-repo" };
106251
+ return { ok: false, reason: "error", error: err.message };
106252
+ }
106253
+ async function scanGitMentionRefs(kind, runners) {
106254
+ const { git } = typeof runners === "function" ? { git: runners } : runners;
106255
+ switch (kind) {
106256
+ case "branch":
106257
+ return scanBranches(git);
106258
+ case "tag":
106259
+ return scanTags(git);
106260
+ case "worktree":
106261
+ return scanWorktrees(git);
106262
+ }
106263
+ }
106264
+ function filterRankGitMentionRefs(refs, needle, limit2 = GIT_MENTION_REF_LIMIT) {
106265
+ const trimmed2 = needle.trim();
106266
+ const filtered = trimmed2 ? refs.filter((ref) => gitRefMatches(ref, trimmed2)) : refs;
106267
+ return rankGitMentionRefs(filtered, trimmed2).slice(0, limit2);
106268
+ }
106269
+ function rankGitMentionRefs(refs, needle) {
106270
+ const trimmed2 = needle.trim();
106271
+ return refs.map((ref, index) => ({ ref, index, key: trimmed2 ? gitMentionRefMatchKey(ref, trimmed2) : null })).sort((a, b3) => {
106272
+ if (trimmed2) {
106273
+ const cmp = compareMentionMatchKeys(a.key, b3.key);
106274
+ if (cmp !== 0) return cmp;
106275
+ }
106276
+ const current = Number(b3.ref.current === true) - Number(a.ref.current === true);
106277
+ if (current) return current;
106278
+ return a.index - b3.index;
106279
+ }).map((entry3) => entry3.ref);
106280
+ }
105973
106281
  async function listGitMentionRefs(kind, query, runners, limit2 = GIT_MENTION_REF_LIMIT) {
105974
106282
  const { git, gh } = typeof runners === "function" ? { git: runners } : runners;
105975
106283
  const needle = query.trim();
105976
106284
  if (isGitHubRefKind(kind)) {
105977
106285
  if (!gh) return { ok: false, reason: "gh-unavailable" };
105978
106286
  try {
105979
- return { ok: true, refs: (await listGitHubItems(kind, needle, gh)).slice(0, limit2) };
106287
+ const refs = rankGitMentionRefs(await listGitHubItems(kind, needle, gh), needle);
106288
+ return { ok: true, refs: refs.slice(0, limit2) };
105980
106289
  } catch (err) {
105981
106290
  if (isGhMissingError(err)) return { ok: false, reason: "gh-unavailable" };
105982
106291
  return { ok: false, reason: "error", error: ghErrorMessage(err) };
105983
106292
  }
105984
106293
  }
105985
106294
  try {
105986
- const refs = await listRefs(kind, needle, git);
105987
- return { ok: true, refs: refs.slice(0, limit2) };
106295
+ if (kind === "commit") {
106296
+ const refs2 = rankGitMentionRefs(await listCommits(needle, git), needle);
106297
+ return { ok: true, refs: refs2.slice(0, limit2) };
106298
+ }
106299
+ const refs = await scanGitMentionRefs(kind, git);
106300
+ return { ok: true, refs: filterRankGitMentionRefs(refs, needle, limit2) };
105988
106301
  } catch (err) {
105989
- if (isNotGitRepoError(err)) return { ok: false, reason: "not-repo" };
105990
- return { ok: false, reason: "error", error: err.message };
106302
+ return gitMentionRefsFailure(err);
105991
106303
  }
105992
106304
  }
105993
106305
  async function probeGitMentionCapabilities(runners) {
@@ -106010,21 +106322,6 @@ function ghErrorMessage(err) {
106010
106322
  const stderr = e.stderr?.trim();
106011
106323
  return stderr ? stderr.split("\n")[0] : e.message ?? "gh failed";
106012
106324
  }
106013
- async function listRefs(kind, needle, run) {
106014
- switch (kind) {
106015
- case "branch":
106016
- return listBranches(needle, run);
106017
- case "tag":
106018
- return listTags(needle, run);
106019
- case "commit":
106020
- return listCommits(needle, run);
106021
- case "worktree":
106022
- return listWorktrees(needle, run);
106023
- case "issue":
106024
- case "pr":
106025
- throw new Error(`${kind} is a GitHub kind`);
106026
- }
106027
- }
106028
106325
  function ghItemState(item) {
106029
106326
  if (item.isDraft) return "draft";
106030
106327
  const s4 = item.state.toLowerCase();
@@ -106058,7 +106355,7 @@ async function listGitHubItems(kind, needle, gh) {
106058
106355
  const seen = new Set(exact.map((r) => r.id));
106059
106356
  return [...exact, ...searched.filter((r) => !seen.has(r.id))];
106060
106357
  }
106061
- async function listBranches(needle, run) {
106358
+ async function scanBranches(run) {
106062
106359
  const raw = await run([
106063
106360
  "for-each-ref",
106064
106361
  "refs/heads",
@@ -106070,13 +106367,11 @@ async function listBranches(needle, run) {
106070
106367
  for (const line of raw.split("\n")) {
106071
106368
  if (!line) continue;
106072
106369
  const [name = "", , subject = "", date6 = "", head = ""] = line.split("\0");
106073
- const ref = { kind: "branch", id: name, label: name, detail: subject, date: date6, current: head === "*" };
106074
- if (gitRefMatches(ref, needle)) refs.push(ref);
106370
+ refs.push({ kind: "branch", id: name, label: name, detail: subject, date: date6, current: head === "*" });
106075
106371
  }
106076
- refs.sort((a, b3) => Number(b3.current === true) - Number(a.current === true));
106077
106372
  return refs;
106078
106373
  }
106079
- async function listTags(needle, run) {
106374
+ async function scanTags(run) {
106080
106375
  const raw = await run([
106081
106376
  "for-each-ref",
106082
106377
  "refs/tags",
@@ -106088,8 +106383,7 @@ async function listTags(needle, run) {
106088
106383
  for (const line of raw.split("\n")) {
106089
106384
  if (!line) continue;
106090
106385
  const [name = "", , subject = "", date6 = ""] = line.split("\0");
106091
- const ref = { kind: "tag", id: name, label: name, detail: subject, date: date6 };
106092
- if (gitRefMatches(ref, needle)) refs.push(ref);
106386
+ refs.push({ kind: "tag", id: name, label: name, detail: subject, date: date6 });
106093
106387
  }
106094
106388
  return refs;
106095
106389
  }
@@ -106106,7 +106400,7 @@ function parseLog(raw) {
106106
106400
  async function listCommits(needle, run) {
106107
106401
  if (!needle) return parseLog(await run(["log", `-n${GIT_MENTION_REF_LIMIT}`, `--format=${LOG_FORMAT}`]));
106108
106402
  const recent = parseLog(await run(["log", `-n${COMMIT_SCAN_LIMIT}`, `--format=${LOG_FORMAT}`]));
106109
- const byMessage = recent.filter((r) => gitRefMatches(r, needle)).slice(0, GIT_MENTION_REF_LIMIT);
106403
+ const byMessage = recent.filter((r) => gitRefMatches(r, needle));
106110
106404
  if (!HEX_PREFIX_RE.test(needle)) return byMessage;
106111
106405
  let bySha = [];
106112
106406
  try {
@@ -106116,7 +106410,7 @@ async function listCommits(needle, run) {
106116
106410
  const seen = new Set(bySha.map((r) => r.id));
106117
106411
  return [...bySha, ...byMessage.filter((r) => !seen.has(r.id))];
106118
106412
  }
106119
- async function listWorktrees(needle, run) {
106413
+ async function scanWorktrees(run) {
106120
106414
  const [raw, toplevel] = await Promise.all([
106121
106415
  run(["worktree", "list", "--porcelain"]),
106122
106416
  run(["rev-parse", "--show-toplevel"]).catch(() => "")
@@ -106126,16 +106420,14 @@ async function listWorktrees(needle, run) {
106126
106420
  for (const wt2 of parseWorktreePorcelain(raw)) {
106127
106421
  if (wt2.bare) continue;
106128
106422
  const label = wt2.branch ?? (wt2.head ? `detached @ ${wt2.head.slice(0, 7)}` : wt2.path);
106129
- const ref = {
106423
+ refs.push({
106130
106424
  kind: "worktree",
106131
106425
  id: wt2.path,
106132
106426
  label,
106133
106427
  detail: wt2.path,
106134
106428
  current: !!here && wt2.path.replace(/[\\/]+$/, "") === here
106135
- };
106136
- if (gitRefMatches(ref, needle)) refs.push(ref);
106429
+ });
106137
106430
  }
106138
- refs.sort((a, b3) => Number(b3.current === true) - Number(a.current === true));
106139
106431
  return refs;
106140
106432
  }
106141
106433
 
@@ -109977,6 +110269,7 @@ var HANDLERS = {
109977
110269
  "session.get": (payload, ctx) => handleSessionGet(payload, ctx),
109978
110270
  "session.list": (payload, ctx) => handleSessionList(payload, ctx),
109979
110271
  "session.listPinned": (payload, ctx) => handleSessionListPinned(payload, ctx),
110272
+ "session.searchTitle": (payload, ctx) => handleSessionSearchTitle(payload, ctx),
109980
110273
  "session.acquireControl": (payload, ctx) => handleSessionAcquireControl(payload, ctx),
109981
110274
  "session.renewControl": (payload, ctx) => handleSessionRenewControl(payload, ctx),
109982
110275
  "session.releaseControl": (payload, ctx) => handleSessionReleaseControl(payload, ctx),
@@ -111210,6 +111503,40 @@ function handleSessionListPinned(payload, ctx) {
111210
111503
  })
111211
111504
  };
111212
111505
  }
111506
+ function handleSessionSearchTitle(payload, ctx) {
111507
+ const denied = requireScopes(ctx.client, OPERATION_SCOPES.readSession);
111508
+ if (denied) return denied;
111509
+ const p3 = asRecord(payload);
111510
+ if (p3.query !== void 0 && typeof p3.query !== "string") {
111511
+ return { error: { code: "invalid_argument", message: "query must be a string" } };
111512
+ }
111513
+ const query = typeof p3.query === "string" ? p3.query : "";
111514
+ const limit2 = typeof p3.limit === "number" && Number.isFinite(p3.limit) ? Math.min(Math.max(Math.floor(p3.limit), 1), 200) : 50;
111515
+ const projectPaths = parseSessionSearchProjectPaths(p3.projectPaths);
111516
+ if (projectPaths === null) {
111517
+ return { error: { code: "invalid_argument", message: "projectPaths must be a short list of paths" } };
111518
+ }
111519
+ const pathSet = projectPaths && projectPaths.length > 0 ? new Set(projectPaths) : null;
111520
+ const ranked = [];
111521
+ for (const session of ctx.sessions.list(void 0)) {
111522
+ if (session.isHidden === true) continue;
111523
+ const project = session.projectId ? ctx.projects.get(session.projectId) : null;
111524
+ const projectPath = project?.path ?? session.cwd ?? "";
111525
+ if (pathSet && !pathSet.has(projectPath)) continue;
111526
+ const rank = mentionMatchTier(session.title ?? "", query);
111527
+ if (rank == null) continue;
111528
+ ranked.push({
111529
+ rank,
111530
+ row: {
111531
+ ...mapSessionRow(session),
111532
+ projectPath,
111533
+ projectName: project?.name ?? ""
111534
+ }
111535
+ });
111536
+ }
111537
+ ranked.sort((a, b3) => a.rank - b3.rank);
111538
+ return { result: ranked.slice(0, limit2).map((entry3) => entry3.row) };
111539
+ }
111213
111540
  function handleSessionAcquireControl(payload, ctx) {
111214
111541
  const denied = requireScopes(ctx.client, OPERATION_SCOPES.operateSession);
111215
111542
  if (denied) return denied;
@@ -116618,7 +116945,11 @@ function listCollaborationProfiles(deps) {
116618
116945
  name: m3.name || m3.id,
116619
116946
  ...m3.description ? { description: m3.description } : {},
116620
116947
  ...m3.supportsFastMode ? { supportsFastMode: true } : {},
116621
- ...m3.serviceTiers?.length ? { serviceTiers: m3.serviceTiers } : {}
116948
+ ...m3.serviceTiers?.length ? { serviceTiers: m3.serviceTiers } : {},
116949
+ ...m3.supportedEffortLevels?.length ? { supportedEffortLevels: m3.supportedEffortLevels } : {},
116950
+ ...m3.supportedReasoningEfforts?.length ? {
116951
+ supportedReasoningEfforts: m3.supportedReasoningEfforts.map((effort) => ({ value: effort.value }))
116952
+ } : {}
116622
116953
  }));
116623
116954
  const cfg = profileConfig && typeof profileConfig === "object" && !Array.isArray(profileConfig) ? profileConfig : {};
116624
116955
  const acpAgentId = harnessId === "acp" && typeof cfg.agentId === "string" && cfg.agentId.trim() ? cfg.agentId.trim() : null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@super-one/cli",
3
- "version": "0.75.4",
3
+ "version": "0.75.5",
4
4
  "description": "SuperOne headless node CLI — remote execution environment (RPC, workspaces, sessions).",
5
5
  "type": "module",
6
6
  "license": "BUSL-1.1",