@deepseek-ai/dsh-api-session-controller 0.2.0-rc.2 → 0.2.1-alpha.2
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/README.i18n.yaml +8 -8
- package/README.md +7 -3
- package/README.zh.md +7 -3
- package/lib/client.js +666 -20
- package/lib/index.js +76 -23
- package/lib/typert.host.js +376 -90
- package/lib/typert.remote-client.js +311 -69
- package/lib/types/client/contract/sessions.d.ts +4 -2
- package/lib/types/client/sessions/lineage.d.ts +2 -0
- package/lib/types/client/sessions/manager.d.ts +7 -5
- package/lib/types/client/sessions/manager.js +36 -11
- package/lib/types/client/sessions/projection-store.d.ts +3 -3
- package/lib/types/client/sessions/projection-store.js +1 -1
- package/lib/types/client/sessions/service.d.ts +8 -4
- package/lib/types/client/sessions/service.js +7 -3
- package/lib/types/index.d.ts +14 -7
- package/lib/types/index.js +45 -13
- package/lib/types/list.d.ts +7 -3
- package/lib/types/list.js +33 -10
- package/lib/types/skill-catalog.js +7 -6
- package/lib/types/types.d.ts +14 -2
- package/package.json +79 -76
package/lib/client.js
CHANGED
|
@@ -193,6 +193,7 @@ window.__ModuleLoader__.load({
|
|
|
193
193
|
"turn/start",
|
|
194
194
|
"user/message",
|
|
195
195
|
"web/deepseek-search-llm-request",
|
|
196
|
+
"working-directory/change",
|
|
196
197
|
"workspace/changes"
|
|
197
198
|
]);
|
|
198
199
|
//#endregion
|
|
@@ -580,6 +581,628 @@ window.__ModuleLoader__.load({
|
|
|
580
581
|
}
|
|
581
582
|
//#endregion
|
|
582
583
|
//#region ../../util/values/lib/index.js
|
|
584
|
+
/**
|
|
585
|
+
* Lazily scanned view of one JSON object's top-level fields, built from text
|
|
586
|
+
* that may still be streaming or from an already parsed object. Nothing is
|
|
587
|
+
* scanned until a reader asks; the view remembers every question it answered
|
|
588
|
+
* and reports changed answers when the owner refreshes for publication.
|
|
589
|
+
* Used for model tool-call arguments: a row reads the fields it
|
|
590
|
+
* cares about at whatever granularity it displays, at every stage of the call.
|
|
591
|
+
* @module @deepseek-ai/dsh-util-values/src/partial-json
|
|
592
|
+
*/
|
|
593
|
+
const SIMPLE_ESCAPES = {
|
|
594
|
+
"\"": "\"",
|
|
595
|
+
"\\": "\\",
|
|
596
|
+
"/": "/",
|
|
597
|
+
b: "\b",
|
|
598
|
+
f: "\f",
|
|
599
|
+
n: "\n",
|
|
600
|
+
r: "\r",
|
|
601
|
+
t: " "
|
|
602
|
+
};
|
|
603
|
+
const CONTENT_ESCAPE = /[\\\u0000-\u001f]/u;
|
|
604
|
+
function isWhitespace(c) {
|
|
605
|
+
return c === " " || c === "\n" || c === "\r" || c === " ";
|
|
606
|
+
}
|
|
607
|
+
function isHex(c) {
|
|
608
|
+
return c >= "0" && c <= "9" || c >= "a" && c <= "f" || c >= "A" && c <= "F";
|
|
609
|
+
}
|
|
610
|
+
(class PartialArguments {
|
|
611
|
+
/** The view of a call with no arguments available. */
|
|
612
|
+
static EMPTY = PartialArguments.fromObject({});
|
|
613
|
+
/**
|
|
614
|
+
* View finished argument text without scanning it until a reader asks.
|
|
615
|
+
* @param text - the complete argument JSON text.
|
|
616
|
+
* @returns a sealed view.
|
|
617
|
+
*/
|
|
618
|
+
static fromText(text) {
|
|
619
|
+
const view = new PartialArguments();
|
|
620
|
+
view.append(text);
|
|
621
|
+
view.sealed = true;
|
|
622
|
+
return view;
|
|
623
|
+
}
|
|
624
|
+
/**
|
|
625
|
+
* View an already parsed argument payload, such as a PTC dispatch object.
|
|
626
|
+
* @param value - the parsed argument value.
|
|
627
|
+
* @returns a sealed view; a non-object payload has no fields.
|
|
628
|
+
*/
|
|
629
|
+
static fromObject(value) {
|
|
630
|
+
const view = new PartialArguments();
|
|
631
|
+
view.object = typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
|
|
632
|
+
view.sealed = true;
|
|
633
|
+
return view;
|
|
634
|
+
}
|
|
635
|
+
/**
|
|
636
|
+
* The source: text so far or a parsed object, plus whether it can still grow.
|
|
637
|
+
* These are the only enumerable fields, so two views over the same source
|
|
638
|
+
* compare equal structurally however far each has been read.
|
|
639
|
+
*/
|
|
640
|
+
chunks = [];
|
|
641
|
+
object;
|
|
642
|
+
sealed = false;
|
|
643
|
+
#ends = [];
|
|
644
|
+
#size = 0;
|
|
645
|
+
#consumed = 0;
|
|
646
|
+
#mode = "root";
|
|
647
|
+
#escape = false;
|
|
648
|
+
#keyStart = 0;
|
|
649
|
+
#keyEscaped = false;
|
|
650
|
+
#key = "";
|
|
651
|
+
#current = null;
|
|
652
|
+
#nestedEnds = [];
|
|
653
|
+
#nestedInString = false;
|
|
654
|
+
#invalidAt;
|
|
655
|
+
#invalidValue = false;
|
|
656
|
+
#entries = /* @__PURE__ */ new Map();
|
|
657
|
+
#order = [];
|
|
658
|
+
#reads = /* @__PURE__ */ new Map();
|
|
659
|
+
/** Whether this view rejects further appends; does not scan text or register reads. */
|
|
660
|
+
get isSealed() {
|
|
661
|
+
return this.sealed;
|
|
662
|
+
}
|
|
663
|
+
/** Whether indexing or a content read found invalid JSON; unread value contents are not validated. */
|
|
664
|
+
get invalid() {
|
|
665
|
+
this.scan();
|
|
666
|
+
return this.#mode === "invalid" || this.#invalidValue;
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* Retain streamed argument text without scanning or comparing observed answers.
|
|
670
|
+
* @param fragment - the text following every fragment appended before.
|
|
671
|
+
*/
|
|
672
|
+
append(fragment) {
|
|
673
|
+
if (this.sealed) throw new Error("PartialArguments: cannot append to a sealed view");
|
|
674
|
+
if (fragment.length === 0) return;
|
|
675
|
+
this.chunks.push(fragment);
|
|
676
|
+
this.#size += fragment.length;
|
|
677
|
+
this.#ends.push(this.#size);
|
|
678
|
+
}
|
|
679
|
+
/**
|
|
680
|
+
* Reconcile a streamed prefix with authoritative complete text without joining the fragments.
|
|
681
|
+
* @param text - the final argument text, which replaces missing or conflicting deltas.
|
|
682
|
+
* @returns this view sealed with its caches retained when every character matches; otherwise a new sealed view.
|
|
683
|
+
*/
|
|
684
|
+
settle(text) {
|
|
685
|
+
if (this.object !== void 0 || text.length !== this.#size) return PartialArguments.fromText(text);
|
|
686
|
+
let offset = 0;
|
|
687
|
+
for (const chunk of this.chunks) {
|
|
688
|
+
if (!text.startsWith(chunk, offset)) return PartialArguments.fromText(text);
|
|
689
|
+
offset += chunk.length;
|
|
690
|
+
}
|
|
691
|
+
this.chunks = text.length === 0 ? [] : [text];
|
|
692
|
+
this.#ends = text.length === 0 ? [] : [text.length];
|
|
693
|
+
this.sealed = true;
|
|
694
|
+
return this;
|
|
695
|
+
}
|
|
696
|
+
/**
|
|
697
|
+
* Compare observed answers and advance their publication baseline. Unread views remain unscanned.
|
|
698
|
+
* @returns whether any observed answer changed since its first read or the preceding refresh.
|
|
699
|
+
*/
|
|
700
|
+
refresh() {
|
|
701
|
+
if (this.#reads.size === 0) return false;
|
|
702
|
+
this.scan();
|
|
703
|
+
let changed = false;
|
|
704
|
+
let completions = false;
|
|
705
|
+
for (const read of this.#reads.values()) {
|
|
706
|
+
if (read.completion) {
|
|
707
|
+
completions = true;
|
|
708
|
+
continue;
|
|
709
|
+
}
|
|
710
|
+
changed = this.refreshRead(read) || changed;
|
|
711
|
+
}
|
|
712
|
+
if (completions) {
|
|
713
|
+
for (const read of this.#reads.values()) if (read.completion) changed = this.refreshRead(read) || changed;
|
|
714
|
+
}
|
|
715
|
+
if (this.sealed) this.#reads.clear();
|
|
716
|
+
return changed;
|
|
717
|
+
}
|
|
718
|
+
refreshRead(read) {
|
|
719
|
+
const now = read.answer();
|
|
720
|
+
if (Object.is(now, read.last)) return false;
|
|
721
|
+
read.last = now;
|
|
722
|
+
return true;
|
|
723
|
+
}
|
|
724
|
+
/**
|
|
725
|
+
* Check whether no further fields can arrive.
|
|
726
|
+
* @returns whether the outer object closed, indexing failed, or the view is sealed; unread values are not validated.
|
|
727
|
+
*/
|
|
728
|
+
closed() {
|
|
729
|
+
return this.remember("closed", "", () => this.closedNow());
|
|
730
|
+
}
|
|
731
|
+
/**
|
|
732
|
+
* List discovered fields in first-appearance order.
|
|
733
|
+
* @returns top-level keys seen so far, in first-appearance order.
|
|
734
|
+
*/
|
|
735
|
+
keys() {
|
|
736
|
+
return this.remember("keys", "", () => this.keysNow(), (keys) => keys.length);
|
|
737
|
+
}
|
|
738
|
+
/**
|
|
739
|
+
* Check whether a top-level field has appeared.
|
|
740
|
+
* @param key - argument name.
|
|
741
|
+
* @returns whether the field has appeared (a string opened or another value began).
|
|
742
|
+
*/
|
|
743
|
+
has(key) {
|
|
744
|
+
return this.remember("has", key, () => this.hasNow(key));
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* Check whether a field's closing delimiter has arrived, without validating its contents.
|
|
748
|
+
* @param key - argument name.
|
|
749
|
+
* @returns whether its delimiter arrived and no content reader has reported an error for this value.
|
|
750
|
+
*/
|
|
751
|
+
complete(key) {
|
|
752
|
+
return this.remember("complete", key, () => this.completeNow(key));
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Read string length without materializing its text.
|
|
756
|
+
* @param key - argument name.
|
|
757
|
+
* @param options - change granularity for a streaming string.
|
|
758
|
+
* @returns decoded UTF-16 length of the string field so far; undefined when absent or not a string.
|
|
759
|
+
*/
|
|
760
|
+
stringLength(key, options) {
|
|
761
|
+
const step = Math.max(1, Math.floor(options?.step ?? 1));
|
|
762
|
+
const offset = options?.offset ?? 0;
|
|
763
|
+
return this.remember(`length:${step}:${offset}`, key, () => this.lengthNow(key), (length) => length === void 0 ? void 0 : Math.ceil((length + offset) / step));
|
|
764
|
+
}
|
|
765
|
+
/**
|
|
766
|
+
* Check a string against a decoded UTF-16 length limit without materializing it.
|
|
767
|
+
* @param key - argument name.
|
|
768
|
+
* @param maxLength - decoded UTF-16 limit, floored to at least zero.
|
|
769
|
+
* @returns whether the string is longer than the limit; false when absent or not a string.
|
|
770
|
+
*/
|
|
771
|
+
stringExceeds(key, maxLength) {
|
|
772
|
+
const limit = Math.max(0, Math.floor(maxLength));
|
|
773
|
+
return this.remember(`exceeds:${limit}`, key, () => (this.lengthNow(key, limit + 1) ?? 0) > limit);
|
|
774
|
+
}
|
|
775
|
+
/**
|
|
776
|
+
* Read a decoded string, including a streaming prefix.
|
|
777
|
+
* @param key - argument name.
|
|
778
|
+
* @returns the string field's decoded text so far; undefined when absent or not a string.
|
|
779
|
+
*/
|
|
780
|
+
text(key) {
|
|
781
|
+
return this.remember("text", key, () => this.textNow(key));
|
|
782
|
+
}
|
|
783
|
+
/**
|
|
784
|
+
* Read at most the first decoded UTF-16 units of a string.
|
|
785
|
+
* @param key - argument name.
|
|
786
|
+
* @param maxLength - maximum decoded UTF-16 length, floored to at least one.
|
|
787
|
+
* @returns the bounded string prefix; undefined when absent or not a string.
|
|
788
|
+
*/
|
|
789
|
+
textPrefix(key, maxLength) {
|
|
790
|
+
const limit = Math.max(1, Math.floor(maxLength));
|
|
791
|
+
return this.remember(`prefix:${limit}`, key, () => this.textPrefixNow(key, limit));
|
|
792
|
+
}
|
|
793
|
+
/**
|
|
794
|
+
* Read a completed non-string argument.
|
|
795
|
+
* @param key - argument name.
|
|
796
|
+
* @returns the parsed non-string value once it closed; undefined while open, absent, or a string.
|
|
797
|
+
*/
|
|
798
|
+
value(key) {
|
|
799
|
+
return this.remember("value", key, () => this.valueNow(key));
|
|
800
|
+
}
|
|
801
|
+
/** Answer a question and, on a streaming view, remember it for change detection. */
|
|
802
|
+
remember(kind, key, read, comparison) {
|
|
803
|
+
this.scan();
|
|
804
|
+
const result = read();
|
|
805
|
+
if (!this.sealed) {
|
|
806
|
+
const id = `${kind}/${key}`;
|
|
807
|
+
if (!this.#reads.has(id)) this.#reads.set(id, {
|
|
808
|
+
completion: kind === "complete",
|
|
809
|
+
answer: comparison === void 0 ? read : () => comparison(read()),
|
|
810
|
+
last: comparison === void 0 ? result : comparison(result)
|
|
811
|
+
});
|
|
812
|
+
}
|
|
813
|
+
return result;
|
|
814
|
+
}
|
|
815
|
+
closedNow() {
|
|
816
|
+
return this.sealed || this.#mode === "closed" || this.#mode === "invalid";
|
|
817
|
+
}
|
|
818
|
+
keysNow() {
|
|
819
|
+
return this.object === void 0 ? this.#order : Object.keys(this.object);
|
|
820
|
+
}
|
|
821
|
+
hasNow(key) {
|
|
822
|
+
return this.object === void 0 ? this.#entries.has(key) : Object.hasOwn(this.object, key);
|
|
823
|
+
}
|
|
824
|
+
completeNow(key) {
|
|
825
|
+
if (this.object !== void 0) return Object.hasOwn(this.object, key);
|
|
826
|
+
const entry = this.#entries.get(key);
|
|
827
|
+
return entry !== void 0 && entry.end >= 0 && (entry.kind === "string" ? entry.invalidAt === void 0 : !entry.invalid);
|
|
828
|
+
}
|
|
829
|
+
lengthNow(key, limit = Number.POSITIVE_INFINITY) {
|
|
830
|
+
if (this.object !== void 0) {
|
|
831
|
+
const field = Object.hasOwn(this.object, key) ? this.object[key] : void 0;
|
|
832
|
+
return typeof field === "string" ? field.length : void 0;
|
|
833
|
+
}
|
|
834
|
+
const entry = this.#entries.get(key);
|
|
835
|
+
if (entry?.kind !== "string") return void 0;
|
|
836
|
+
if (entry.text !== void 0 && entry.text.at === entry.end) return entry.text.length;
|
|
837
|
+
const read = entry.length ??= {
|
|
838
|
+
at: entry.start,
|
|
839
|
+
length: 0,
|
|
840
|
+
text: ""
|
|
841
|
+
};
|
|
842
|
+
this.readString(entry, read, limit, false);
|
|
843
|
+
return read.length;
|
|
844
|
+
}
|
|
845
|
+
textNow(key) {
|
|
846
|
+
if (this.object !== void 0) {
|
|
847
|
+
const field = Object.hasOwn(this.object, key) ? this.object[key] : void 0;
|
|
848
|
+
return typeof field === "string" ? field : void 0;
|
|
849
|
+
}
|
|
850
|
+
const entry = this.#entries.get(key);
|
|
851
|
+
if (entry?.kind !== "string") return void 0;
|
|
852
|
+
if (entry.text === void 0 && entry.end >= 0 && entry.needsDecoding && entry.invalidAt === void 0) {
|
|
853
|
+
let text;
|
|
854
|
+
try {
|
|
855
|
+
text = JSON.parse(`"${this.slice(entry.start, entry.end)}"`);
|
|
856
|
+
} catch (_error) {}
|
|
857
|
+
if (text !== void 0) entry.text = {
|
|
858
|
+
at: entry.end,
|
|
859
|
+
length: text.length,
|
|
860
|
+
text
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
const read = entry.text ??= {
|
|
864
|
+
at: entry.start,
|
|
865
|
+
length: 0,
|
|
866
|
+
text: ""
|
|
867
|
+
};
|
|
868
|
+
this.readString(entry, read, Number.POSITIVE_INFINITY, true);
|
|
869
|
+
return read.text;
|
|
870
|
+
}
|
|
871
|
+
textPrefixNow(key, maxLength) {
|
|
872
|
+
if (this.object !== void 0) {
|
|
873
|
+
const field = Object.hasOwn(this.object, key) ? this.object[key] : void 0;
|
|
874
|
+
return typeof field === "string" ? field.slice(0, maxLength) : void 0;
|
|
875
|
+
}
|
|
876
|
+
const entry = this.#entries.get(key);
|
|
877
|
+
if (entry?.kind !== "string") return void 0;
|
|
878
|
+
const prefixes = entry.prefixes ??= /* @__PURE__ */ new Map();
|
|
879
|
+
let read = prefixes.get(maxLength);
|
|
880
|
+
if (read === void 0) {
|
|
881
|
+
read = {
|
|
882
|
+
at: entry.start,
|
|
883
|
+
length: 0,
|
|
884
|
+
text: ""
|
|
885
|
+
};
|
|
886
|
+
prefixes.set(maxLength, read);
|
|
887
|
+
}
|
|
888
|
+
this.readString(entry, read, maxLength, true);
|
|
889
|
+
return read.text;
|
|
890
|
+
}
|
|
891
|
+
valueNow(key) {
|
|
892
|
+
if (this.object !== void 0) {
|
|
893
|
+
if (!Object.hasOwn(this.object, key)) return void 0;
|
|
894
|
+
const field = this.object[key];
|
|
895
|
+
return typeof field === "string" ? void 0 : field;
|
|
896
|
+
}
|
|
897
|
+
const entry = this.#entries.get(key);
|
|
898
|
+
if (entry?.kind !== "value" || entry.end < 0 || entry.invalid) return void 0;
|
|
899
|
+
if (entry.parsed === void 0) try {
|
|
900
|
+
entry.parsed = JSON.parse(this.slice(entry.start, entry.end));
|
|
901
|
+
} catch (_error) {
|
|
902
|
+
entry.invalid = true;
|
|
903
|
+
this.#invalidValue = true;
|
|
904
|
+
}
|
|
905
|
+
return entry.parsed;
|
|
906
|
+
}
|
|
907
|
+
chunkAt(at) {
|
|
908
|
+
let low = 0;
|
|
909
|
+
let high = this.#ends.length;
|
|
910
|
+
while (low < high) {
|
|
911
|
+
const mid = low + high >>> 1;
|
|
912
|
+
if (this.#ends[mid] <= at) low = mid + 1;
|
|
913
|
+
else high = mid;
|
|
914
|
+
}
|
|
915
|
+
return low;
|
|
916
|
+
}
|
|
917
|
+
/** Materialize only a requested range, never the cumulative source. */
|
|
918
|
+
slice(start, end) {
|
|
919
|
+
if (start >= end) return "";
|
|
920
|
+
const first = this.chunkAt(start);
|
|
921
|
+
const last = this.chunkAt(end - 1);
|
|
922
|
+
const base = first === 0 ? 0 : this.#ends[first - 1];
|
|
923
|
+
if (first === last) return this.chunks[first].slice(start - base, end - base);
|
|
924
|
+
const parts = [this.chunks[first].slice(start - base)];
|
|
925
|
+
for (let i = first + 1; i < last; i++) parts.push(this.chunks[i]);
|
|
926
|
+
parts.push(this.chunks[last].slice(0, end - this.#ends[last - 1]));
|
|
927
|
+
return parts.join("");
|
|
928
|
+
}
|
|
929
|
+
readString(entry, read, limit, materialize) {
|
|
930
|
+
const end = Math.min(entry.end < 0 ? this.#consumed : entry.end, entry.invalidAt ?? Number.POSITIVE_INFINITY, this.#invalidAt ?? Number.POSITIVE_INFINITY);
|
|
931
|
+
if (!entry.needsDecoding) {
|
|
932
|
+
const length = Math.min(end - read.at, limit - read.length);
|
|
933
|
+
if (length <= 0) return;
|
|
934
|
+
if (materialize) read.text += this.slice(read.at, read.at + length);
|
|
935
|
+
read.at += length;
|
|
936
|
+
read.length += length;
|
|
937
|
+
return;
|
|
938
|
+
}
|
|
939
|
+
let chunkIndex = this.chunkAt(read.at);
|
|
940
|
+
while (read.at < end && read.length < limit) {
|
|
941
|
+
const base = chunkIndex === 0 ? 0 : this.#ends[chunkIndex - 1];
|
|
942
|
+
const chunk = this.chunks[chunkIndex];
|
|
943
|
+
const remaining = chunk.slice(read.at - base, Math.min(chunk.length, end - base));
|
|
944
|
+
const boundary = remaining.search(CONTENT_ESCAPE);
|
|
945
|
+
const length = Math.min(boundary < 0 ? remaining.length : boundary, limit - read.length);
|
|
946
|
+
if (length > 0) {
|
|
947
|
+
if (materialize) read.text += remaining.slice(0, length);
|
|
948
|
+
read.at += length;
|
|
949
|
+
read.length += length;
|
|
950
|
+
if (read.at === base + chunk.length) chunkIndex++;
|
|
951
|
+
continue;
|
|
952
|
+
}
|
|
953
|
+
const type = remaining.length > 1 ? remaining[1] : read.at + 1 < end ? this.chunks[chunkIndex + 1][0] : void 0;
|
|
954
|
+
let decoded;
|
|
955
|
+
let width = 2;
|
|
956
|
+
if (remaining[0] === "\\" && type === void 0 && entry.end < 0) return;
|
|
957
|
+
if (remaining[0] === "\\" && type === "u") {
|
|
958
|
+
const hex = this.slice(read.at + 2, Math.min(end, read.at + 6));
|
|
959
|
+
let valid = true;
|
|
960
|
+
for (let i = 0; i < hex.length; i++) if (!isHex(hex[i])) valid = false;
|
|
961
|
+
if (valid) {
|
|
962
|
+
if (hex.length < 4 && entry.end < 0) return;
|
|
963
|
+
if (hex.length === 4) decoded = String.fromCharCode(Number.parseInt(hex, 16));
|
|
964
|
+
}
|
|
965
|
+
width = 6;
|
|
966
|
+
} else if (remaining[0] === "\\" && type !== void 0) decoded = SIMPLE_ESCAPES[type];
|
|
967
|
+
if (decoded === void 0) {
|
|
968
|
+
entry.invalidAt = read.at;
|
|
969
|
+
this.#invalidValue = true;
|
|
970
|
+
return;
|
|
971
|
+
}
|
|
972
|
+
if (materialize) read.text += decoded;
|
|
973
|
+
read.length++;
|
|
974
|
+
read.at += width;
|
|
975
|
+
while (chunkIndex < this.chunks.length && read.at >= this.#ends[chunkIndex]) chunkIndex++;
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
/** Locate new field ranges without decoding or parsing their contents. */
|
|
979
|
+
scan() {
|
|
980
|
+
if (this.object !== void 0 || this.#consumed === this.#size) return;
|
|
981
|
+
for (let i = this.chunkAt(this.#consumed); i < this.chunks.length && this.#invalidAt === void 0; i++) {
|
|
982
|
+
const pending = this.chunks[i];
|
|
983
|
+
const base = i === 0 ? 0 : this.#ends[i - 1];
|
|
984
|
+
for (let index = this.#consumed - base; index < pending.length && this.#mode !== "invalid"; index++) {
|
|
985
|
+
if (this.#mode === "string" || this.#mode === "nested" && this.#nestedInString) {
|
|
986
|
+
const end = this.stringBoundary(pending, index);
|
|
987
|
+
this.#consumed += end - index;
|
|
988
|
+
index = end;
|
|
989
|
+
if (index === pending.length) break;
|
|
990
|
+
}
|
|
991
|
+
this.step(pending[index], this.#consumed);
|
|
992
|
+
this.#consumed++;
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
/** Only raw quotes and their preceding backslash runs can terminate a string. */
|
|
997
|
+
stringBoundary(fragment, start) {
|
|
998
|
+
let at = start;
|
|
999
|
+
while (true) {
|
|
1000
|
+
const quote = fragment.indexOf("\"", at);
|
|
1001
|
+
const end = quote < 0 ? fragment.length : quote;
|
|
1002
|
+
if (this.#mode === "string") {
|
|
1003
|
+
const entry = this.#current;
|
|
1004
|
+
if (!entry.needsDecoding && CONTENT_ESCAPE.test(fragment.slice(at, end))) entry.needsDecoding = true;
|
|
1005
|
+
}
|
|
1006
|
+
let slashStart = end;
|
|
1007
|
+
while (slashStart > at && fragment[slashStart - 1] === "\\") slashStart--;
|
|
1008
|
+
const escaped = (end - slashStart) % 2 === 1 !== (slashStart === at && this.#escape);
|
|
1009
|
+
this.#escape = quote < 0 && escaped;
|
|
1010
|
+
if (quote < 0 || !escaped) return end;
|
|
1011
|
+
at = quote + 1;
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
step(c, at) {
|
|
1015
|
+
switch (this.#mode) {
|
|
1016
|
+
case "root":
|
|
1017
|
+
if (isWhitespace(c)) return;
|
|
1018
|
+
if (c === "{") {
|
|
1019
|
+
this.#mode = "key-or-end";
|
|
1020
|
+
return;
|
|
1021
|
+
}
|
|
1022
|
+
this.fail();
|
|
1023
|
+
return;
|
|
1024
|
+
case "key-or-end":
|
|
1025
|
+
if (isWhitespace(c)) return;
|
|
1026
|
+
if (c === "}") {
|
|
1027
|
+
this.#mode = "closed";
|
|
1028
|
+
return;
|
|
1029
|
+
}
|
|
1030
|
+
if (c === "\"") {
|
|
1031
|
+
this.beginKey(at);
|
|
1032
|
+
return;
|
|
1033
|
+
}
|
|
1034
|
+
this.fail();
|
|
1035
|
+
return;
|
|
1036
|
+
case "key-only":
|
|
1037
|
+
if (isWhitespace(c)) return;
|
|
1038
|
+
if (c === "\"") {
|
|
1039
|
+
this.beginKey(at);
|
|
1040
|
+
return;
|
|
1041
|
+
}
|
|
1042
|
+
this.fail();
|
|
1043
|
+
return;
|
|
1044
|
+
case "key":
|
|
1045
|
+
this.stepKey(c, at);
|
|
1046
|
+
return;
|
|
1047
|
+
case "colon":
|
|
1048
|
+
if (isWhitespace(c)) return;
|
|
1049
|
+
if (c === ":") {
|
|
1050
|
+
this.#mode = "value";
|
|
1051
|
+
return;
|
|
1052
|
+
}
|
|
1053
|
+
this.fail();
|
|
1054
|
+
return;
|
|
1055
|
+
case "value":
|
|
1056
|
+
this.beginValue(c, at);
|
|
1057
|
+
return;
|
|
1058
|
+
case "string": {
|
|
1059
|
+
const entry = this.#current;
|
|
1060
|
+
entry.end = at;
|
|
1061
|
+
this.#current = null;
|
|
1062
|
+
this.#mode = "comma-or-end";
|
|
1063
|
+
return;
|
|
1064
|
+
}
|
|
1065
|
+
case "scalar":
|
|
1066
|
+
this.stepScalar(c, at);
|
|
1067
|
+
return;
|
|
1068
|
+
case "nested":
|
|
1069
|
+
this.stepNested(c, at);
|
|
1070
|
+
return;
|
|
1071
|
+
case "comma-or-end":
|
|
1072
|
+
if (isWhitespace(c)) return;
|
|
1073
|
+
if (c === ",") {
|
|
1074
|
+
this.#mode = "key-only";
|
|
1075
|
+
return;
|
|
1076
|
+
}
|
|
1077
|
+
if (c === "}") {
|
|
1078
|
+
this.#mode = "closed";
|
|
1079
|
+
return;
|
|
1080
|
+
}
|
|
1081
|
+
this.fail();
|
|
1082
|
+
return;
|
|
1083
|
+
case "closed":
|
|
1084
|
+
if (isWhitespace(c)) return;
|
|
1085
|
+
this.fail();
|
|
1086
|
+
return;
|
|
1087
|
+
/* v8 ignore next 2 -- scan() stops stepping once the view is invalid. */
|
|
1088
|
+
case "invalid": return;
|
|
1089
|
+
/* v8 ignore next 2 -- Every scanner mode has a handler above. */
|
|
1090
|
+
default: assertNever(this.#mode);
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
fail() {
|
|
1094
|
+
this.#invalidAt = this.#consumed;
|
|
1095
|
+
this.#mode = "invalid";
|
|
1096
|
+
this.#current = null;
|
|
1097
|
+
}
|
|
1098
|
+
beginKey(at) {
|
|
1099
|
+
this.#mode = "key";
|
|
1100
|
+
this.#keyStart = at + 1;
|
|
1101
|
+
this.#keyEscaped = false;
|
|
1102
|
+
this.#escape = false;
|
|
1103
|
+
}
|
|
1104
|
+
stepKey(c, at) {
|
|
1105
|
+
if (c < " ") {
|
|
1106
|
+
this.fail();
|
|
1107
|
+
return;
|
|
1108
|
+
}
|
|
1109
|
+
if (this.#escape) {
|
|
1110
|
+
this.#escape = false;
|
|
1111
|
+
return;
|
|
1112
|
+
}
|
|
1113
|
+
if (c === "\\") {
|
|
1114
|
+
this.#escape = true;
|
|
1115
|
+
this.#keyEscaped = true;
|
|
1116
|
+
return;
|
|
1117
|
+
}
|
|
1118
|
+
if (c !== "\"") return;
|
|
1119
|
+
const raw = this.slice(this.#keyStart, at);
|
|
1120
|
+
if (this.#keyEscaped) try {
|
|
1121
|
+
this.#key = JSON.parse(`"${raw}"`);
|
|
1122
|
+
} catch (_error) {
|
|
1123
|
+
this.fail();
|
|
1124
|
+
return;
|
|
1125
|
+
}
|
|
1126
|
+
else this.#key = raw;
|
|
1127
|
+
this.#mode = "colon";
|
|
1128
|
+
}
|
|
1129
|
+
open(entry) {
|
|
1130
|
+
if (!this.#entries.has(this.#key)) this.#order.push(this.#key);
|
|
1131
|
+
this.#entries.set(this.#key, entry);
|
|
1132
|
+
this.#current = entry;
|
|
1133
|
+
}
|
|
1134
|
+
beginValue(c, at) {
|
|
1135
|
+
if (isWhitespace(c)) return;
|
|
1136
|
+
if (c === "\"") {
|
|
1137
|
+
this.open({
|
|
1138
|
+
kind: "string",
|
|
1139
|
+
start: at + 1,
|
|
1140
|
+
end: -1,
|
|
1141
|
+
needsDecoding: false,
|
|
1142
|
+
invalidAt: void 0,
|
|
1143
|
+
length: void 0,
|
|
1144
|
+
text: void 0,
|
|
1145
|
+
prefixes: void 0
|
|
1146
|
+
});
|
|
1147
|
+
this.#escape = false;
|
|
1148
|
+
this.#mode = "string";
|
|
1149
|
+
return;
|
|
1150
|
+
}
|
|
1151
|
+
if (c === "}" || c === "," || c === ":" || c === "]") {
|
|
1152
|
+
this.fail();
|
|
1153
|
+
return;
|
|
1154
|
+
}
|
|
1155
|
+
this.open({
|
|
1156
|
+
kind: "value",
|
|
1157
|
+
start: at,
|
|
1158
|
+
end: -1,
|
|
1159
|
+
parsed: void 0,
|
|
1160
|
+
invalid: false
|
|
1161
|
+
});
|
|
1162
|
+
if (c === "{" || c === "[") {
|
|
1163
|
+
this.#mode = "nested";
|
|
1164
|
+
this.#nestedEnds = [c === "{" ? "}" : "]"];
|
|
1165
|
+
this.#nestedInString = false;
|
|
1166
|
+
this.#escape = false;
|
|
1167
|
+
return;
|
|
1168
|
+
}
|
|
1169
|
+
this.#mode = "scalar";
|
|
1170
|
+
}
|
|
1171
|
+
stepScalar(c, at) {
|
|
1172
|
+
if (c !== "," && c !== "}" && !isWhitespace(c)) return;
|
|
1173
|
+
this.closeValue(at);
|
|
1174
|
+
this.#mode = c === "," ? "key-only" : c === "}" ? "closed" : "comma-or-end";
|
|
1175
|
+
}
|
|
1176
|
+
stepNested(c, at) {
|
|
1177
|
+
if (this.#nestedInString) {
|
|
1178
|
+
this.#nestedInString = false;
|
|
1179
|
+
return;
|
|
1180
|
+
}
|
|
1181
|
+
if (c === "\"") {
|
|
1182
|
+
this.#nestedInString = true;
|
|
1183
|
+
return;
|
|
1184
|
+
}
|
|
1185
|
+
if (c === "{" || c === "[") {
|
|
1186
|
+
this.#nestedEnds.push(c === "{" ? "}" : "]");
|
|
1187
|
+
return;
|
|
1188
|
+
}
|
|
1189
|
+
if (c === "}" || c === "]") {
|
|
1190
|
+
if (this.#nestedEnds.pop() !== c) {
|
|
1191
|
+
this.fail();
|
|
1192
|
+
return;
|
|
1193
|
+
}
|
|
1194
|
+
if (this.#nestedEnds.length === 0) {
|
|
1195
|
+
this.closeValue(at + 1);
|
|
1196
|
+
this.#mode = "comma-or-end";
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
closeValue(end) {
|
|
1201
|
+
const entry = this.#current;
|
|
1202
|
+
entry.end = end;
|
|
1203
|
+
this.#current = null;
|
|
1204
|
+
}
|
|
1205
|
+
});
|
|
583
1206
|
/** Duplicate-install-safe JSON and immutable-value helpers. @module @deepseek-ai/dsh-util-values */
|
|
584
1207
|
/**
|
|
585
1208
|
* Mark an unreachable closed-union branch.
|
|
@@ -994,7 +1617,7 @@ window.__ModuleLoader__.load({
|
|
|
994
1617
|
this.changed(key);
|
|
995
1618
|
}
|
|
996
1619
|
/**
|
|
997
|
-
* Fill keys from a
|
|
1620
|
+
* Fill keys from a Host block labeled `cached`: a zero-I/O
|
|
998
1621
|
* view of the persisted checkpoint. A cached value lands only where no
|
|
999
1622
|
* sequenced row exists: a connected Session has already answered for such
|
|
1000
1623
|
* a key, and the list's view of the persisted checkpoint cannot be newer
|
|
@@ -2389,20 +3012,28 @@ window.__ModuleLoader__.load({
|
|
|
2389
3012
|
}
|
|
2390
3013
|
/**
|
|
2391
3014
|
* Resolve an address for breadcrumb navigation without retaining transport authority.
|
|
2392
|
-
* @param sessionId - possible child id in
|
|
2393
|
-
* @returns A retained
|
|
3015
|
+
* @param sessionId - possible child id in received Session metadata.
|
|
3016
|
+
* @returns A retained address, then a catalog address, then an unknown-mode address
|
|
3017
|
+
* from a listed subagent header; undefined without that evidence.
|
|
2394
3018
|
*/
|
|
2395
3019
|
subagentAddress(sessionId) {
|
|
2396
3020
|
const retained = this.addresses.get(sessionId);
|
|
2397
3021
|
if (retained !== void 0) return retained;
|
|
2398
3022
|
for (const parentSessionId of this.projectionStores.keys()) {
|
|
2399
3023
|
const child = this.projectionStores.get(parentSessionId)?.values().subagentCatalog?.find((entry) => entry.id === sessionId);
|
|
2400
|
-
if (child !== void 0) return {
|
|
3024
|
+
if (child !== void 0 && child.mode !== "external") return {
|
|
2401
3025
|
parentSessionId,
|
|
2402
3026
|
childSessionId: sessionId,
|
|
2403
3027
|
mode: child.mode
|
|
2404
3028
|
};
|
|
2405
3029
|
}
|
|
3030
|
+
const summary = this.summaries.find((summary) => summary.sessionId === sessionId);
|
|
3031
|
+
if (summary?.origin !== "subagent" || summary.parentSessionId === void 0) return void 0;
|
|
3032
|
+
return {
|
|
3033
|
+
parentSessionId: summary.parentSessionId,
|
|
3034
|
+
childSessionId: sessionId,
|
|
3035
|
+
mode: "unknown"
|
|
3036
|
+
};
|
|
2406
3037
|
}
|
|
2407
3038
|
/**
|
|
2408
3039
|
* Withdraw an exact Client instance before running its teardown callbacks.
|
|
@@ -2468,7 +3099,8 @@ window.__ModuleLoader__.load({
|
|
|
2468
3099
|
session.handleRunning(summary.running);
|
|
2469
3100
|
} else {
|
|
2470
3101
|
const address = this.addresses.get(sessionId);
|
|
2471
|
-
|
|
3102
|
+
const child = address === void 0 ? void 0 : this.projectionStores.get(address.parentSessionId)?.values().subagentCatalog?.find((entry) => entry.id === sessionId);
|
|
3103
|
+
if (child !== void 0 && child.mode !== "external") {
|
|
2472
3104
|
session.handleBlank(false);
|
|
2473
3105
|
session.handleRunning(false);
|
|
2474
3106
|
} else session.handleBlank(true);
|
|
@@ -2536,7 +3168,7 @@ window.__ModuleLoader__.load({
|
|
|
2536
3168
|
return store;
|
|
2537
3169
|
}
|
|
2538
3170
|
/**
|
|
2539
|
-
*
|
|
3171
|
+
* Read projections without starting migration; retry failed or migration-deferred reads.
|
|
2540
3172
|
* @param sessionId - Session to inspect without opening its conversation.
|
|
2541
3173
|
* @returns completion of the current or newly started read.
|
|
2542
3174
|
*/
|
|
@@ -2557,13 +3189,22 @@ window.__ModuleLoader__.load({
|
|
|
2557
3189
|
const result = await this.remote.session.projections({ sessionId }, controller.signal);
|
|
2558
3190
|
if (controller.signal.aborted) return;
|
|
2559
3191
|
if (result.ok) {
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
3192
|
+
const value = result.value;
|
|
3193
|
+
if (value !== null) switch (value.kind) {
|
|
3194
|
+
case "sequenced":
|
|
3195
|
+
store.seed({
|
|
3196
|
+
values: value.values,
|
|
3197
|
+
asOfSeq: sessionSeqCursor(value.asOfSeq)
|
|
3198
|
+
});
|
|
3199
|
+
break;
|
|
3200
|
+
case "migration-required":
|
|
3201
|
+
store.applyCached(value.values);
|
|
3202
|
+
break;
|
|
3203
|
+
default: assertNever(value, "session projections result");
|
|
3204
|
+
}
|
|
2564
3205
|
else if (store.values() === initialValues) store.clear();
|
|
2565
3206
|
this.projectionLoads.set(sessionId, {
|
|
2566
|
-
state: "ready",
|
|
3207
|
+
state: value?.kind === "migration-required" ? "migration-required" : "ready",
|
|
2567
3208
|
error: null
|
|
2568
3209
|
});
|
|
2569
3210
|
} else this.projectionLoads.set(sessionId, {
|
|
@@ -2718,14 +3359,15 @@ window.__ModuleLoader__.load({
|
|
|
2718
3359
|
* preserve it or lower it after an exact cut before the first `turn/start`;
|
|
2719
3360
|
* lineage rides parentSessionId. A child published before Workspace
|
|
2720
3361
|
* attachment fails is also reconciled into the list.
|
|
2721
|
-
* @param opts - source session
|
|
3362
|
+
* @param opts - source session, optional exact inclusive boundary seq, and permission to start migration.
|
|
2722
3363
|
* @returns the fork result (the child session id).
|
|
2723
3364
|
*/
|
|
2724
3365
|
async fork(opts) {
|
|
2725
3366
|
const source = this.summaries.find((s) => s.sessionId === opts.sessionId);
|
|
2726
3367
|
const result = await this.remote.session.fork({
|
|
2727
3368
|
sessionId: opts.sessionId,
|
|
2728
|
-
...opts.atSeq === void 0 ? {} : { atSeq: opts.atSeq }
|
|
3369
|
+
...opts.atSeq === void 0 ? {} : { atSeq: opts.atSeq },
|
|
3370
|
+
...opts.allowMigration === void 0 ? {} : { allowMigration: opts.allowMigration }
|
|
2729
3371
|
});
|
|
2730
3372
|
const childId = result.ok ? result.value.sessionId : workspaceAttachSessionId(result.error);
|
|
2731
3373
|
if (childId !== void 0) this.recordMutation({
|
|
@@ -2950,7 +3592,7 @@ window.__ModuleLoader__.load({
|
|
|
2950
3592
|
};
|
|
2951
3593
|
})).map((entry) => {
|
|
2952
3594
|
const prev = this.entryCache.get(entry.sessionId);
|
|
2953
|
-
if (prev !== void 0 && prev.updatedAt === entry.updatedAt && prev.running === entry.running && prev.blank === entry.blank && prev.parentSessionId === entry.parentSessionId && prev.cwd === entry.cwd && prev.origin === entry.origin && prev.title === entry.title && prev.depth === entry.depth && prev.projectionValues === entry.projectionValues) return prev;
|
|
3595
|
+
if (prev !== void 0 && prev.updatedAt === entry.updatedAt && prev.running === entry.running && prev.blank === entry.blank && prev.parentSessionId === entry.parentSessionId && prev.cwd === entry.cwd && prev.origin === entry.origin && prev.title === entry.title && prev.depth === entry.depth && prev.formatStatus === entry.formatStatus && prev.projectionValues === entry.projectionValues) return prev;
|
|
2954
3596
|
this.entryCache.set(entry.sessionId, entry);
|
|
2955
3597
|
return entry;
|
|
2956
3598
|
});
|
|
@@ -2983,13 +3625,14 @@ window.__ModuleLoader__.load({
|
|
|
2983
3625
|
blank: existing.blank && mutation.summary.blank,
|
|
2984
3626
|
...mutation.kind === "upsert" ? {
|
|
2985
3627
|
agentAvailable: mutation.summary.agentAvailable,
|
|
2986
|
-
running: mutation.summary.running
|
|
3628
|
+
running: mutation.summary.running,
|
|
3629
|
+
...mutation.summary.formatStatus === void 0 ? {} : { formatStatus: mutation.summary.formatStatus }
|
|
2987
3630
|
} : {},
|
|
2988
3631
|
...existing.cwd === void 0 && mutation.summary.cwd !== void 0 ? { cwd: mutation.summary.cwd } : {},
|
|
2989
3632
|
...existing.parentSessionId === void 0 && mutation.summary.parentSessionId !== void 0 ? { parentSessionId: mutation.summary.parentSessionId } : {},
|
|
2990
3633
|
...existing.origin === void 0 && mutation.summary.origin !== void 0 ? { origin: mutation.summary.origin } : {}
|
|
2991
3634
|
};
|
|
2992
|
-
if (filled.cwd === existing.cwd && filled.parentSessionId === existing.parentSessionId && filled.origin === existing.origin && filled.blank === existing.blank && filled.agentAvailable === existing.agentAvailable && filled.running === existing.running) return [...summaries];
|
|
3635
|
+
if (filled.cwd === existing.cwd && filled.parentSessionId === existing.parentSessionId && filled.origin === existing.origin && filled.blank === existing.blank && filled.agentAvailable === existing.agentAvailable && filled.running === existing.running && filled.formatStatus === existing.formatStatus) return [...summaries];
|
|
2993
3636
|
return summaries.map((summary) => summary.sessionId === mutation.summary.sessionId ? filled : summary);
|
|
2994
3637
|
}
|
|
2995
3638
|
case "remove": return summaries.filter((summary) => summary.sessionId !== mutation.sessionId);
|
|
@@ -3239,13 +3882,13 @@ window.__ModuleLoader__.load({
|
|
|
3239
3882
|
* Resolve an already discovered direct-parent address without opening it.
|
|
3240
3883
|
* Feature plugins use this to avoid Agent-bound RPCs in persisted child views.
|
|
3241
3884
|
* @param id - possible addressed child id.
|
|
3242
|
-
* @returns A retained or
|
|
3885
|
+
* @returns A retained, catalog-derived, or unknown-mode listed address, without retaining a new selection or scope.
|
|
3243
3886
|
*/
|
|
3244
3887
|
subagentAddress(id) {
|
|
3245
3888
|
return this.manager.subagentAddress(id);
|
|
3246
3889
|
}
|
|
3247
3890
|
/**
|
|
3248
|
-
*
|
|
3891
|
+
* Read projections without starting migration; retry failed or migration-deferred reads.
|
|
3249
3892
|
* @param sessionId - Session to inspect without opening its conversation.
|
|
3250
3893
|
*/
|
|
3251
3894
|
refreshProjections(sessionId) {
|
|
@@ -3335,7 +3978,7 @@ window.__ModuleLoader__.load({
|
|
|
3335
3978
|
* seq (a real event seq the caller already knows; a cut inside an open
|
|
3336
3979
|
* turn is balanced Host-side with synthetic closers, and omission selects
|
|
3337
3980
|
* the latest completed-turn prefix), and whether to increment an
|
|
3338
|
-
* inherited durable title before resolving.
|
|
3981
|
+
* inherited durable title before resolving, plus permission to start source migration.
|
|
3339
3982
|
* @returns the child session id.
|
|
3340
3983
|
* @throws {SessionForkError} with the source id.
|
|
3341
3984
|
* @throws {Error} when a requested child-title rename fails after creation.
|
|
@@ -3344,7 +3987,8 @@ window.__ModuleLoader__.load({
|
|
|
3344
3987
|
const sourceTitle = opts.increaseTitle ? this.list.getSnapshot().byId[opts.sessionId]?.title : void 0;
|
|
3345
3988
|
const result = await this.manager.fork({
|
|
3346
3989
|
sessionId: opts.sessionId,
|
|
3347
|
-
...opts.atSeq === void 0 ? {} : { atSeq: SessionSeq(opts.atSeq) }
|
|
3990
|
+
...opts.atSeq === void 0 ? {} : { atSeq: SessionSeq(opts.atSeq) },
|
|
3991
|
+
...opts.allowMigration === void 0 ? {} : { allowMigration: opts.allowMigration }
|
|
3348
3992
|
});
|
|
3349
3993
|
if (!result.ok) throw new SessionForkError(result.error, opts.sessionId);
|
|
3350
3994
|
this.projectList();
|
|
@@ -3508,6 +4152,7 @@ window.__ModuleLoader__.load({
|
|
|
3508
4152
|
retainedBy: this.retentionSnapshot(entry.sessionId).retainedBy,
|
|
3509
4153
|
blank: entry.blank,
|
|
3510
4154
|
updatedAt: entry.updatedAt,
|
|
4155
|
+
formatStatus: entry.formatStatus,
|
|
3511
4156
|
...entry.projectionValues === void 0 ? {} : { projectionValues: entry.projectionValues },
|
|
3512
4157
|
...entry.title !== void 0 ? { title: entry.title } : {},
|
|
3513
4158
|
...entry.cwd !== void 0 ? { cwd: entry.cwd } : {},
|
|
@@ -3516,6 +4161,7 @@ window.__ModuleLoader__.load({
|
|
|
3516
4161
|
};
|
|
3517
4162
|
}
|
|
3518
4163
|
for (const [parentId, projection] of Object.entries(projectionsBySession)) for (const child of projection.values.subagentCatalog ?? []) {
|
|
4164
|
+
if (child.mode === "external") continue;
|
|
3519
4165
|
const childId = child.id;
|
|
3520
4166
|
const summary = byId[childId];
|
|
3521
4167
|
const projectionValues = summary?.projectionValues ?? this.manager.projectionValues(childId);
|