@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 +2 -2
- package/lib/cli.mjs +382 -51
- package/package.json +1 -1
package/MANIFEST.json
CHANGED
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.
|
|
141
|
-
return "0.75.
|
|
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:
|
|
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
|
-
|
|
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))
|
|
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
|
-
|
|
72859
|
+
emitHeld(interrupted ? { type: "message_interrupted", messageId } : { type: "message_error", messageId, error: error51, errorInfo: info });
|
|
72713
72860
|
}
|
|
72714
|
-
|
|
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
|
-
|
|
72869
|
+
emitHeld({ type: "status_change", status: "streaming" });
|
|
72723
72870
|
if (providerSessionId) {
|
|
72724
|
-
|
|
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
|
-
|
|
72918
|
+
emitHeld(event);
|
|
72772
72919
|
}
|
|
72773
|
-
for (const event of migrate)
|
|
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)
|
|
72786
|
-
for (const event of migrate)
|
|
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
|
-
|
|
72944
|
+
emitHeld({ type: "message_complete", messageId });
|
|
72798
72945
|
}
|
|
72799
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
105987
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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))
|
|
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
|
|
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
|
-
|
|
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;
|