dsh-context 0.66.1 → 0.68.0
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.md +16 -7
- package/lib/client.js +10 -10
- package/lib/index.d.ts +186 -661
- package/lib/index.js +590 -379
- package/package.json +2 -2
package/lib/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* dsh-context v0.
|
|
2
|
+
* dsh-context v0.68.0
|
|
3
3
|
* A DeepSeek Harness plugin for context insight and management, with context dashboard and context command, for understanding how the context is made of, and how it evolves.
|
|
4
4
|
* @author bowenliang123
|
|
5
5
|
* @license Apache-2.0
|
|
6
6
|
* @homepage https://github.com/bowenliang123/dsh-context
|
|
7
|
-
* @built 2026-10-
|
|
8
|
-
* @commit
|
|
9
|
-
* @commit-date 2026-10-
|
|
7
|
+
* @built 2026-10-11T02:40:54+00:00
|
|
8
|
+
* @commit 425fd2e7b82e
|
|
9
|
+
* @commit-date 2026-10-11T10:37:14+08:00
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { createRequire } from "node:module";
|
|
@@ -18,21 +18,6 @@ import { dirname, isAbsolute, join, normalize, relative } from "node:path";
|
|
|
18
18
|
import { fileURLToPath } from "node:url";
|
|
19
19
|
import { getHeapStatistics } from "node:v8";
|
|
20
20
|
import { randomUUID } from "node:crypto";
|
|
21
|
-
//#region src/shared/providers.ts
|
|
22
|
-
const MODELS_DEV_PROVIDER_IDS = {
|
|
23
|
-
"deepseek-official": "deepseek",
|
|
24
|
-
"deepseek-account": "deepseek",
|
|
25
|
-
"kimi-coding": "moonshotai",
|
|
26
|
-
"minimax-cn": "minimax",
|
|
27
|
-
"zai-coding-cn": "zhipuai"
|
|
28
|
-
};
|
|
29
|
-
function modelsDevProviderOf(dshProviderId) {
|
|
30
|
-
return MODELS_DEV_PROVIDER_IDS[dshProviderId] ?? dshProviderId;
|
|
31
|
-
}
|
|
32
|
-
function isDeepSeekProvider(dshProviderId) {
|
|
33
|
-
return modelsDevProviderOf(dshProviderId) === "deepseek";
|
|
34
|
-
}
|
|
35
|
-
//#endregion
|
|
36
21
|
//#region src/shared/estimate.ts
|
|
37
22
|
const CHARS_PER_TOKEN$1 = 4;
|
|
38
23
|
const ROLE_OVERHEAD$1 = 4;
|
|
@@ -548,7 +533,7 @@ function opsOfCall(input) {
|
|
|
548
533
|
}];
|
|
549
534
|
}
|
|
550
535
|
//#endregion
|
|
551
|
-
//#region src/host/
|
|
536
|
+
//#region src/host/foldState.ts
|
|
552
537
|
function trimToLastTurns(requests, maxTurns) {
|
|
553
538
|
let runs = 0;
|
|
554
539
|
let start = requests.length;
|
|
@@ -624,6 +609,280 @@ function createTimelineState() {
|
|
|
624
609
|
spans: []
|
|
625
610
|
};
|
|
626
611
|
}
|
|
612
|
+
//#endregion
|
|
613
|
+
//#region src/shared/providers.ts
|
|
614
|
+
const MODELS_DEV_PROVIDER_IDS = {
|
|
615
|
+
"deepseek-official": "deepseek",
|
|
616
|
+
"deepseek-account": "deepseek",
|
|
617
|
+
"kimi-coding": "moonshotai",
|
|
618
|
+
"minimax-cn": "minimax",
|
|
619
|
+
"zai-coding-cn": "zhipuai"
|
|
620
|
+
};
|
|
621
|
+
function modelsDevProviderOf(dshProviderId) {
|
|
622
|
+
return MODELS_DEV_PROVIDER_IDS[dshProviderId] ?? dshProviderId;
|
|
623
|
+
}
|
|
624
|
+
function isDeepSeekProvider(dshProviderId) {
|
|
625
|
+
return modelsDevProviderOf(dshProviderId) === "deepseek";
|
|
626
|
+
}
|
|
627
|
+
//#endregion
|
|
628
|
+
//#region src/host/foldMetering.ts
|
|
629
|
+
function tokenCountOf(value) {
|
|
630
|
+
if (typeof value === "number") return Number.isFinite(value) ? Math.max(0, Math.round(value)) : null;
|
|
631
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
632
|
+
const parsed = Number(value);
|
|
633
|
+
return Number.isFinite(parsed) ? Math.max(0, Math.round(parsed)) : null;
|
|
634
|
+
}
|
|
635
|
+
return null;
|
|
636
|
+
}
|
|
637
|
+
function isPeakUtc(time) {
|
|
638
|
+
const at = new Date(time);
|
|
639
|
+
const day = at.getUTCDay();
|
|
640
|
+
if (day === 0 || day === 6) return false;
|
|
641
|
+
const h = at.getUTCHours();
|
|
642
|
+
return h >= 1 && h < 4 || h >= 6 && h < 10;
|
|
643
|
+
}
|
|
644
|
+
function addBilledUsage(prev, provider, model, time, usage) {
|
|
645
|
+
const period = isDeepSeekProvider(provider) && !isPeakUtc(time) ? "off" : "peak";
|
|
646
|
+
const models = prev?.[provider] ?? {};
|
|
647
|
+
const periods = models[model] ?? {};
|
|
648
|
+
const b = periods[period] ?? {
|
|
649
|
+
uncached: 0,
|
|
650
|
+
cacheRead: 0,
|
|
651
|
+
cacheWrite: 0,
|
|
652
|
+
output: 0
|
|
653
|
+
};
|
|
654
|
+
const nextPeriods = { ...periods };
|
|
655
|
+
nextPeriods[period] = {
|
|
656
|
+
uncached: b.uncached + usage.uncached,
|
|
657
|
+
cacheRead: b.cacheRead + usage.cacheRead,
|
|
658
|
+
cacheWrite: b.cacheWrite + usage.cacheWrite,
|
|
659
|
+
output: b.output + usage.output
|
|
660
|
+
};
|
|
661
|
+
const nextModels = {
|
|
662
|
+
...models,
|
|
663
|
+
[model]: nextPeriods
|
|
664
|
+
};
|
|
665
|
+
return {
|
|
666
|
+
...prev ?? {},
|
|
667
|
+
[provider]: nextModels
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
function copyCostUsage(cost) {
|
|
671
|
+
const copy = {};
|
|
672
|
+
for (const provider in cost) {
|
|
673
|
+
const models = {};
|
|
674
|
+
for (const model in cost[provider]) {
|
|
675
|
+
const periods = cost[provider][model];
|
|
676
|
+
const modelCopy = {};
|
|
677
|
+
if (periods.peak !== void 0) modelCopy.peak = { ...periods.peak };
|
|
678
|
+
if (periods.off !== void 0) modelCopy.off = { ...periods.off };
|
|
679
|
+
models[model] = modelCopy;
|
|
680
|
+
}
|
|
681
|
+
copy[provider] = models;
|
|
682
|
+
}
|
|
683
|
+
return copy;
|
|
684
|
+
}
|
|
685
|
+
function accumulateCost(st, time, usage) {
|
|
686
|
+
const model = st.model;
|
|
687
|
+
if (model === void 0) return;
|
|
688
|
+
st.cost = addBilledUsage(st.cost, st.provider ?? "", model, time, usage);
|
|
689
|
+
}
|
|
690
|
+
const TOOL_TIMING_CAP = 16;
|
|
691
|
+
const DECODE_KINDS = [
|
|
692
|
+
"reasoning",
|
|
693
|
+
"text",
|
|
694
|
+
"toolarg"
|
|
695
|
+
];
|
|
696
|
+
function durOf(from, to) {
|
|
697
|
+
if (!Number.isFinite(from) || !Number.isFinite(to)) return 0;
|
|
698
|
+
return Math.max(0, to - from);
|
|
699
|
+
}
|
|
700
|
+
function ensureTiming(st) {
|
|
701
|
+
if (st.timing === void 0) st.timing = {
|
|
702
|
+
wallMs: 0,
|
|
703
|
+
ttftMs: 0,
|
|
704
|
+
genMs: 0,
|
|
705
|
+
calls: 0,
|
|
706
|
+
toolsMs: 0,
|
|
707
|
+
toolCalls: 0,
|
|
708
|
+
tools: {}
|
|
709
|
+
};
|
|
710
|
+
return st.timing;
|
|
711
|
+
}
|
|
712
|
+
const DECODE_FIELDS = {
|
|
713
|
+
reasoning: {
|
|
714
|
+
ms: "reasoningMs",
|
|
715
|
+
n: "reasoningBlocks"
|
|
716
|
+
},
|
|
717
|
+
text: {
|
|
718
|
+
ms: "textMs",
|
|
719
|
+
n: "textBlocks"
|
|
720
|
+
},
|
|
721
|
+
toolarg: {
|
|
722
|
+
ms: "toolArgMs",
|
|
723
|
+
n: "toolArgBlocks"
|
|
724
|
+
}
|
|
725
|
+
};
|
|
726
|
+
function addDecode(timing, kind, ms, blocks) {
|
|
727
|
+
const field = DECODE_FIELDS[kind];
|
|
728
|
+
if (ms > 0) timing[field.ms] = (timing[field.ms] ?? 0) + ms;
|
|
729
|
+
if (blocks > 0) timing[field.n] = (timing[field.n] ?? 0) + blocks;
|
|
730
|
+
}
|
|
731
|
+
function bumpToolTotals(timing, name, ms) {
|
|
732
|
+
if (name === "__proto__") return;
|
|
733
|
+
if (!Object.hasOwn(timing.tools, name)) {
|
|
734
|
+
if (Object.keys(timing.tools).length >= TOOL_TIMING_CAP) {
|
|
735
|
+
let minKey = "";
|
|
736
|
+
let minMs = Infinity;
|
|
737
|
+
for (const k in timing.tools) if (timing.tools[k].ms < minMs) {
|
|
738
|
+
minMs = timing.tools[k].ms;
|
|
739
|
+
minKey = k;
|
|
740
|
+
}
|
|
741
|
+
const kept = {};
|
|
742
|
+
for (const k in timing.tools) if (k !== minKey) kept[k] = timing.tools[k];
|
|
743
|
+
timing.tools = kept;
|
|
744
|
+
}
|
|
745
|
+
timing.tools[name] = {
|
|
746
|
+
calls: 1,
|
|
747
|
+
ms
|
|
748
|
+
};
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
const cur = timing.tools[name];
|
|
752
|
+
timing.tools[name] = {
|
|
753
|
+
calls: cur.calls + 1,
|
|
754
|
+
ms: cur.ms + ms
|
|
755
|
+
};
|
|
756
|
+
}
|
|
757
|
+
//#endregion
|
|
758
|
+
//#region src/host/foldWire.ts
|
|
759
|
+
function headFieldsOf(state) {
|
|
760
|
+
const surfaceTotal = state.sums.user + state.sums.inject + state.sums.skill + state.sums.assistant + state.sums.tool;
|
|
761
|
+
const result = {
|
|
762
|
+
ok: true,
|
|
763
|
+
...state.model !== void 0 ? { model: state.model } : {},
|
|
764
|
+
...state.provider !== void 0 ? { provider: state.provider } : {},
|
|
765
|
+
...state.contextWindow !== void 0 ? { contextWindow: state.contextWindow } : {},
|
|
766
|
+
current: {
|
|
767
|
+
system: state.systemTokens,
|
|
768
|
+
tools: state.toolsTokens,
|
|
769
|
+
user: state.sums.user,
|
|
770
|
+
inject: state.sums.inject,
|
|
771
|
+
skill: state.sums.skill,
|
|
772
|
+
assistant: state.sums.assistant,
|
|
773
|
+
tool: state.sums.tool,
|
|
774
|
+
total: surfaceTotal + state.systemTokens + state.toolsTokens
|
|
775
|
+
},
|
|
776
|
+
images: state.surface.reduce((n, node) => n + (node.imgs ?? 0), 0),
|
|
777
|
+
toolCalls: state.surface.reduce((n, node) => node.cat === "tool" || node.cat === "skill" && node.tool !== void 0 ? n + 1 : n, 0),
|
|
778
|
+
humanInputs: state.humanInputs ?? 0,
|
|
779
|
+
answers: state.answers ?? 0,
|
|
780
|
+
...state.lastUser !== void 0 ? { lastUser: state.lastUser } : {},
|
|
781
|
+
requests: [],
|
|
782
|
+
events: [],
|
|
783
|
+
nodes: [],
|
|
784
|
+
droppedNodes: 0,
|
|
785
|
+
archive: []
|
|
786
|
+
};
|
|
787
|
+
if (state.cost !== void 0) result.cost = copyCostUsage(state.cost);
|
|
788
|
+
if (state.timing !== void 0) {
|
|
789
|
+
const tools = {};
|
|
790
|
+
for (const k in state.timing.tools) tools[k] = { ...state.timing.tools[k] };
|
|
791
|
+
result.timing = {
|
|
792
|
+
...state.timing,
|
|
793
|
+
tools
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
if (state.systems !== void 0 && state.systems.length > 0) result.systems = state.systems.map((n) => ({ ...n }));
|
|
797
|
+
return result;
|
|
798
|
+
}
|
|
799
|
+
function detailCollectionsOf(state, bounds) {
|
|
800
|
+
const result = {
|
|
801
|
+
requests: state.requests.map((r) => ({ ...r })),
|
|
802
|
+
events: state.events.map((e) => ({ ...e })),
|
|
803
|
+
nodes: [],
|
|
804
|
+
droppedNodes: 0,
|
|
805
|
+
archive: state.archived.map((n) => ({ ...n })),
|
|
806
|
+
fileOps: state.fileOps.map((o) => ({ ...o })),
|
|
807
|
+
...state.fileOpsFloor !== void 0 ? { fileOpsFloor: state.fileOpsFloor } : {},
|
|
808
|
+
spans: state.spans.map((s) => ({ ...s }))
|
|
809
|
+
};
|
|
810
|
+
const overflowCount = Math.max(0, state.surface.length - bounds.maxNodes);
|
|
811
|
+
const overflow = state.surface.slice(0, overflowCount);
|
|
812
|
+
const tail = state.surface.slice(overflowCount);
|
|
813
|
+
const pinned = overflow.filter((n) => n.cat === "inject" || n.cat === "skill");
|
|
814
|
+
result.nodes = pinned.length > 0 ? [...pinned, ...tail] : tail;
|
|
815
|
+
result.droppedNodes = overflowCount - pinned.length;
|
|
816
|
+
if (result.droppedNodes > 0) {
|
|
817
|
+
let floor = 0;
|
|
818
|
+
for (const n of overflow) if (n.cat !== "inject" && n.cat !== "skill") floor = Math.max(floor, n.seq);
|
|
819
|
+
result.surfaceFloor = floor;
|
|
820
|
+
}
|
|
821
|
+
if (state.archiveFloor !== void 0) result.archiveFloor = state.archiveFloor;
|
|
822
|
+
const requests = result.requests;
|
|
823
|
+
const events = result.events;
|
|
824
|
+
let ri = 0;
|
|
825
|
+
for (const ev of events) {
|
|
826
|
+
while (ri < requests.length && requests[ri].seq <= ev.seq) ri++;
|
|
827
|
+
const next = requests.at(ri);
|
|
828
|
+
const prev = ri > 0 ? requests.at(ri - 1) : void 0;
|
|
829
|
+
if (next !== void 0 && typeof next.turn === "number" && typeof next.step === "number") {
|
|
830
|
+
ev.turn = next.turn;
|
|
831
|
+
ev.step = next.step;
|
|
832
|
+
}
|
|
833
|
+
if (prev !== void 0 && typeof prev.turn === "number" && typeof prev.step === "number") {
|
|
834
|
+
ev.fromTurn = prev.turn;
|
|
835
|
+
ev.fromStep = prev.step;
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
return result;
|
|
839
|
+
}
|
|
840
|
+
function buildTimelineHead(state) {
|
|
841
|
+
const result = headFieldsOf(state);
|
|
842
|
+
const turns = new Set();
|
|
843
|
+
for (const r of state.requests) turns.add(r.turn ?? 0);
|
|
844
|
+
let injects = 0;
|
|
845
|
+
let compactions = 0;
|
|
846
|
+
let prunes = 0;
|
|
847
|
+
const skills = new Set();
|
|
848
|
+
for (const e of state.events) {
|
|
849
|
+
if (e.kind === "inject") injects++;
|
|
850
|
+
else if (e.kind === "compaction") compactions++;
|
|
851
|
+
else if (e.kind === "prune") prunes++;
|
|
852
|
+
if (e.sub === "skill" && typeof e.name === "string" && e.name !== "") skills.add(e.name);
|
|
853
|
+
}
|
|
854
|
+
result.counts = {
|
|
855
|
+
turns: turns.size,
|
|
856
|
+
steps: state.requests.length,
|
|
857
|
+
injects,
|
|
858
|
+
compactions,
|
|
859
|
+
prunes,
|
|
860
|
+
skills: skills.size
|
|
861
|
+
};
|
|
862
|
+
const last = state.requests.at(-1);
|
|
863
|
+
if (last !== void 0) result.last = {
|
|
864
|
+
seq: last.seq,
|
|
865
|
+
total: last.total,
|
|
866
|
+
...typeof last.prompt === "number" ? { prompt: last.prompt } : {}
|
|
867
|
+
};
|
|
868
|
+
result.detailRev = state.detailRev ?? 0;
|
|
869
|
+
return result;
|
|
870
|
+
}
|
|
871
|
+
function buildTimelineDetail(state, bounds) {
|
|
872
|
+
return {
|
|
873
|
+
rev: state.detailRev ?? 0,
|
|
874
|
+
head: buildTimelineHead(state),
|
|
875
|
+
...detailCollectionsOf(state, bounds)
|
|
876
|
+
};
|
|
877
|
+
}
|
|
878
|
+
function buildTimelineView(state, bounds) {
|
|
879
|
+
return {
|
|
880
|
+
...headFieldsOf(state),
|
|
881
|
+
...detailCollectionsOf(state, bounds)
|
|
882
|
+
};
|
|
883
|
+
}
|
|
884
|
+
//#endregion
|
|
885
|
+
//#region src/host/fold.ts
|
|
627
886
|
function categoryOf(type, message) {
|
|
628
887
|
if (type === "assistant/message") return "assistant";
|
|
629
888
|
if (type === "tool/result") return "tool";
|
|
@@ -687,7 +946,7 @@ function removeSurfaceSeqs(st, claimed, goneSeq) {
|
|
|
687
946
|
st.surface = kept;
|
|
688
947
|
return removed;
|
|
689
948
|
}
|
|
690
|
-
function messageOf$
|
|
949
|
+
function messageOf$2(data) {
|
|
691
950
|
const message = data?.message;
|
|
692
951
|
return message !== null && typeof message === "object" ? message : null;
|
|
693
952
|
}
|
|
@@ -793,125 +1052,13 @@ function applySurface(st, ev, type, message) {
|
|
|
793
1052
|
for (const r of removed) st.sums[r.cat] -= r.tokens;
|
|
794
1053
|
st.sums[cat] += node.tokens;
|
|
795
1054
|
return node;
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
st.surface.push(node);
|
|
799
|
-
st.sums[cat] += node.tokens;
|
|
800
|
-
return node;
|
|
801
|
-
}
|
|
802
|
-
function tokenCountOf(value) {
|
|
803
|
-
if (typeof value === "number") return Number.isFinite(value) ? Math.max(0, Math.round(value)) : null;
|
|
804
|
-
if (typeof value === "string" && value.trim() !== "") {
|
|
805
|
-
const parsed = Number(value);
|
|
806
|
-
return Number.isFinite(parsed) ? Math.max(0, Math.round(parsed)) : null;
|
|
807
|
-
}
|
|
808
|
-
return null;
|
|
809
|
-
}
|
|
810
|
-
function isPeakUtc(time) {
|
|
811
|
-
const at = new Date(time);
|
|
812
|
-
const day = at.getUTCDay();
|
|
813
|
-
if (day === 0 || day === 6) return false;
|
|
814
|
-
const h = at.getUTCHours();
|
|
815
|
-
return h >= 1 && h < 4 || h >= 6 && h < 10;
|
|
816
|
-
}
|
|
817
|
-
function addBilledUsage(prev, provider, model, time, usage) {
|
|
818
|
-
const period = isDeepSeekProvider(provider) && !isPeakUtc(time) ? "off" : "peak";
|
|
819
|
-
const models = prev?.[provider] ?? {};
|
|
820
|
-
const periods = models[model] ?? {};
|
|
821
|
-
const b = periods[period] ?? {
|
|
822
|
-
uncached: 0,
|
|
823
|
-
cacheRead: 0,
|
|
824
|
-
cacheWrite: 0,
|
|
825
|
-
output: 0
|
|
826
|
-
};
|
|
827
|
-
const nextPeriods = { ...periods };
|
|
828
|
-
nextPeriods[period] = {
|
|
829
|
-
uncached: b.uncached + usage.input,
|
|
830
|
-
cacheRead: b.cacheRead + usage.cacheRead,
|
|
831
|
-
cacheWrite: b.cacheWrite + usage.cacheWrite,
|
|
832
|
-
output: b.output + usage.output
|
|
833
|
-
};
|
|
834
|
-
const nextModels = {
|
|
835
|
-
...models,
|
|
836
|
-
[model]: nextPeriods
|
|
837
|
-
};
|
|
838
|
-
return {
|
|
839
|
-
...prev ?? {},
|
|
840
|
-
[provider]: nextModels
|
|
841
|
-
};
|
|
842
|
-
}
|
|
843
|
-
function accumulateCost(st, time, usage) {
|
|
844
|
-
const model = st.model;
|
|
845
|
-
if (model === void 0) return;
|
|
846
|
-
st.cost = addBilledUsage(st.cost, st.provider ?? "", model, time, usage);
|
|
847
|
-
}
|
|
848
|
-
const TOOL_TIMING_CAP = 16;
|
|
849
|
-
const ASK_USER_TOOL = "ask_user_question";
|
|
850
|
-
const DECODE_KINDS = [
|
|
851
|
-
"reasoning",
|
|
852
|
-
"text",
|
|
853
|
-
"toolarg"
|
|
854
|
-
];
|
|
855
|
-
function durOf(from, to) {
|
|
856
|
-
if (!Number.isFinite(from) || !Number.isFinite(to)) return 0;
|
|
857
|
-
return Math.max(0, to - from);
|
|
858
|
-
}
|
|
859
|
-
function ensureTiming(st) {
|
|
860
|
-
if (st.timing === void 0) st.timing = {
|
|
861
|
-
wallMs: 0,
|
|
862
|
-
ttftMs: 0,
|
|
863
|
-
genMs: 0,
|
|
864
|
-
calls: 0,
|
|
865
|
-
toolsMs: 0,
|
|
866
|
-
toolCalls: 0,
|
|
867
|
-
tools: {}
|
|
868
|
-
};
|
|
869
|
-
return st.timing;
|
|
870
|
-
}
|
|
871
|
-
const DECODE_FIELDS = {
|
|
872
|
-
reasoning: {
|
|
873
|
-
ms: "reasoningMs",
|
|
874
|
-
n: "reasoningBlocks"
|
|
875
|
-
},
|
|
876
|
-
text: {
|
|
877
|
-
ms: "textMs",
|
|
878
|
-
n: "textBlocks"
|
|
879
|
-
},
|
|
880
|
-
toolarg: {
|
|
881
|
-
ms: "toolArgMs",
|
|
882
|
-
n: "toolArgBlocks"
|
|
883
|
-
}
|
|
884
|
-
};
|
|
885
|
-
function addDecode(timing, kind, ms, blocks) {
|
|
886
|
-
const field = DECODE_FIELDS[kind];
|
|
887
|
-
if (ms > 0) timing[field.ms] = (timing[field.ms] ?? 0) + ms;
|
|
888
|
-
if (blocks > 0) timing[field.n] = (timing[field.n] ?? 0) + blocks;
|
|
889
|
-
}
|
|
890
|
-
function bumpToolTotals(timing, name, ms) {
|
|
891
|
-
if (!Object.hasOwn(timing.tools, name)) {
|
|
892
|
-
if (Object.keys(timing.tools).length >= TOOL_TIMING_CAP) {
|
|
893
|
-
let minKey = "";
|
|
894
|
-
let minMs = Infinity;
|
|
895
|
-
for (const k in timing.tools) if (timing.tools[k].ms < minMs) {
|
|
896
|
-
minMs = timing.tools[k].ms;
|
|
897
|
-
minKey = k;
|
|
898
|
-
}
|
|
899
|
-
const kept = {};
|
|
900
|
-
for (const k in timing.tools) if (k !== minKey) kept[k] = timing.tools[k];
|
|
901
|
-
timing.tools = kept;
|
|
902
|
-
}
|
|
903
|
-
timing.tools[name] = {
|
|
904
|
-
calls: 1,
|
|
905
|
-
ms
|
|
906
|
-
};
|
|
907
|
-
return;
|
|
908
|
-
}
|
|
909
|
-
const cur = timing.tools[name];
|
|
910
|
-
timing.tools[name] = {
|
|
911
|
-
calls: cur.calls + 1,
|
|
912
|
-
ms: cur.ms + ms
|
|
913
|
-
};
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
st.surface.push(node);
|
|
1058
|
+
st.sums[cat] += node.tokens;
|
|
1059
|
+
return node;
|
|
914
1060
|
}
|
|
1061
|
+
const ASK_USER_TOOL = "ask_user_question";
|
|
915
1062
|
const CLONE_ALL = [
|
|
916
1063
|
"surface",
|
|
917
1064
|
"sums",
|
|
@@ -980,7 +1127,7 @@ function applyTimeline(state, event, bounds) {
|
|
|
980
1127
|
pushSystem(s, {
|
|
981
1128
|
seq: event.seq,
|
|
982
1129
|
time: event.time,
|
|
983
|
-
tokens: estimateSystemContent(messageOf$
|
|
1130
|
+
tokens: estimateSystemContent(messageOf$2(data)?.content)
|
|
984
1131
|
});
|
|
985
1132
|
break;
|
|
986
1133
|
}
|
|
@@ -1137,7 +1284,7 @@ function applyTimeline(state, event, bounds) {
|
|
|
1137
1284
|
case "user/message":
|
|
1138
1285
|
case "developer/message": {
|
|
1139
1286
|
const developer = event.type === "developer/message";
|
|
1140
|
-
const msg = developer ? messageOf$
|
|
1287
|
+
const msg = developer ? messageOf$2(data) : deriveEventMessage(event);
|
|
1141
1288
|
if (developer && (msg === null || !Array.isArray(msg.content))) return state;
|
|
1142
1289
|
const s = ensure([
|
|
1143
1290
|
"surface",
|
|
@@ -1273,7 +1420,7 @@ function applyTimeline(state, event, bounds) {
|
|
|
1273
1420
|
if (cacheRead !== null) record.cacheRead = cacheRead;
|
|
1274
1421
|
if (output !== null) record.output = output;
|
|
1275
1422
|
accumulateCost(s, event.time, {
|
|
1276
|
-
|
|
1423
|
+
uncached: input ?? 0,
|
|
1277
1424
|
cacheRead: cacheRead ?? 0,
|
|
1278
1425
|
cacheWrite: cacheWrite ?? 0,
|
|
1279
1426
|
output: output ?? 0
|
|
@@ -1367,145 +1514,6 @@ function applyTimeline(state, event, bounds) {
|
|
|
1367
1514
|
}
|
|
1368
1515
|
return state;
|
|
1369
1516
|
}
|
|
1370
|
-
function headFieldsOf(state) {
|
|
1371
|
-
const surfaceTotal = state.sums.user + state.sums.inject + state.sums.skill + state.sums.assistant + state.sums.tool;
|
|
1372
|
-
const result = {
|
|
1373
|
-
ok: true,
|
|
1374
|
-
...state.model !== void 0 ? { model: state.model } : {},
|
|
1375
|
-
...state.provider !== void 0 ? { provider: state.provider } : {},
|
|
1376
|
-
...state.contextWindow !== void 0 ? { contextWindow: state.contextWindow } : {},
|
|
1377
|
-
current: {
|
|
1378
|
-
system: state.systemTokens,
|
|
1379
|
-
tools: state.toolsTokens,
|
|
1380
|
-
user: state.sums.user,
|
|
1381
|
-
inject: state.sums.inject,
|
|
1382
|
-
skill: state.sums.skill,
|
|
1383
|
-
assistant: state.sums.assistant,
|
|
1384
|
-
tool: state.sums.tool,
|
|
1385
|
-
total: surfaceTotal + state.systemTokens + state.toolsTokens
|
|
1386
|
-
},
|
|
1387
|
-
images: state.surface.reduce((n, node) => n + (node.imgs ?? 0), 0),
|
|
1388
|
-
toolCalls: state.surface.reduce((n, node) => node.cat === "tool" || node.cat === "skill" && node.tool !== void 0 ? n + 1 : n, 0),
|
|
1389
|
-
humanInputs: state.humanInputs ?? 0,
|
|
1390
|
-
answers: state.answers ?? 0,
|
|
1391
|
-
...state.lastUser !== void 0 ? { lastUser: state.lastUser } : {},
|
|
1392
|
-
requests: [],
|
|
1393
|
-
events: [],
|
|
1394
|
-
nodes: [],
|
|
1395
|
-
droppedNodes: 0,
|
|
1396
|
-
archive: []
|
|
1397
|
-
};
|
|
1398
|
-
if (state.cost !== void 0) {
|
|
1399
|
-
const cost = {};
|
|
1400
|
-
for (const provider in state.cost) {
|
|
1401
|
-
const models = {};
|
|
1402
|
-
for (const model in state.cost[provider]) {
|
|
1403
|
-
const periods = state.cost[provider][model];
|
|
1404
|
-
const copy = {};
|
|
1405
|
-
if (periods.peak !== void 0) copy.peak = { ...periods.peak };
|
|
1406
|
-
if (periods.off !== void 0) copy.off = { ...periods.off };
|
|
1407
|
-
models[model] = copy;
|
|
1408
|
-
}
|
|
1409
|
-
cost[provider] = models;
|
|
1410
|
-
}
|
|
1411
|
-
result.cost = cost;
|
|
1412
|
-
}
|
|
1413
|
-
if (state.timing !== void 0) {
|
|
1414
|
-
const tools = {};
|
|
1415
|
-
for (const k in state.timing.tools) tools[k] = { ...state.timing.tools[k] };
|
|
1416
|
-
result.timing = {
|
|
1417
|
-
...state.timing,
|
|
1418
|
-
tools
|
|
1419
|
-
};
|
|
1420
|
-
}
|
|
1421
|
-
if (state.systems !== void 0 && state.systems.length > 0) result.systems = state.systems.map((n) => ({ ...n }));
|
|
1422
|
-
return result;
|
|
1423
|
-
}
|
|
1424
|
-
function detailCollectionsOf(state, bounds) {
|
|
1425
|
-
const result = {
|
|
1426
|
-
requests: state.requests.map((r) => ({ ...r })),
|
|
1427
|
-
events: state.events.map((e) => ({ ...e })),
|
|
1428
|
-
nodes: [],
|
|
1429
|
-
droppedNodes: 0,
|
|
1430
|
-
archive: state.archived.map((n) => ({ ...n })),
|
|
1431
|
-
fileOps: state.fileOps.map((o) => ({ ...o })),
|
|
1432
|
-
...state.fileOpsFloor !== void 0 ? { fileOpsFloor: state.fileOpsFloor } : {},
|
|
1433
|
-
spans: state.spans.map((s) => ({ ...s }))
|
|
1434
|
-
};
|
|
1435
|
-
const overflowCount = Math.max(0, state.surface.length - bounds.maxNodes);
|
|
1436
|
-
const overflow = state.surface.slice(0, overflowCount);
|
|
1437
|
-
const tail = state.surface.slice(overflowCount);
|
|
1438
|
-
const pinned = overflow.filter((n) => n.cat === "inject" || n.cat === "skill");
|
|
1439
|
-
result.nodes = pinned.length > 0 ? [...pinned, ...tail] : tail;
|
|
1440
|
-
result.droppedNodes = overflowCount - pinned.length;
|
|
1441
|
-
if (result.droppedNodes > 0) {
|
|
1442
|
-
let floor = 0;
|
|
1443
|
-
for (const n of overflow) if (n.cat !== "inject" && n.cat !== "skill") floor = Math.max(floor, n.seq);
|
|
1444
|
-
result.surfaceFloor = floor;
|
|
1445
|
-
}
|
|
1446
|
-
if (state.archiveFloor !== void 0) result.archiveFloor = state.archiveFloor;
|
|
1447
|
-
const requests = result.requests;
|
|
1448
|
-
const events = result.events;
|
|
1449
|
-
let ri = 0;
|
|
1450
|
-
for (const ev of events) {
|
|
1451
|
-
while (ri < requests.length && requests[ri].seq <= ev.seq) ri++;
|
|
1452
|
-
const next = requests.at(ri);
|
|
1453
|
-
const prev = ri > 0 ? requests.at(ri - 1) : void 0;
|
|
1454
|
-
if (next !== void 0 && typeof next.turn === "number" && typeof next.step === "number") {
|
|
1455
|
-
ev.turn = next.turn;
|
|
1456
|
-
ev.step = next.step;
|
|
1457
|
-
}
|
|
1458
|
-
if (prev !== void 0 && typeof prev.turn === "number" && typeof prev.step === "number") {
|
|
1459
|
-
ev.fromTurn = prev.turn;
|
|
1460
|
-
ev.fromStep = prev.step;
|
|
1461
|
-
}
|
|
1462
|
-
}
|
|
1463
|
-
return result;
|
|
1464
|
-
}
|
|
1465
|
-
function buildTimelineHead(state) {
|
|
1466
|
-
const result = headFieldsOf(state);
|
|
1467
|
-
const turns = new Set();
|
|
1468
|
-
for (const r of state.requests) turns.add(r.turn ?? 0);
|
|
1469
|
-
let injects = 0;
|
|
1470
|
-
let compactions = 0;
|
|
1471
|
-
let prunes = 0;
|
|
1472
|
-
const skills = new Set();
|
|
1473
|
-
for (const e of state.events) {
|
|
1474
|
-
if (e.kind === "inject") injects++;
|
|
1475
|
-
else if (e.kind === "compaction") compactions++;
|
|
1476
|
-
else if (e.kind === "prune") prunes++;
|
|
1477
|
-
if (e.sub === "skill" && typeof e.name === "string" && e.name !== "") skills.add(e.name);
|
|
1478
|
-
}
|
|
1479
|
-
result.counts = {
|
|
1480
|
-
turns: turns.size,
|
|
1481
|
-
steps: state.requests.length,
|
|
1482
|
-
injects,
|
|
1483
|
-
compactions,
|
|
1484
|
-
prunes,
|
|
1485
|
-
skills: skills.size
|
|
1486
|
-
};
|
|
1487
|
-
const last = state.requests.at(-1);
|
|
1488
|
-
if (last !== void 0) result.last = {
|
|
1489
|
-
seq: last.seq,
|
|
1490
|
-
total: last.total,
|
|
1491
|
-
...typeof last.prompt === "number" ? { prompt: last.prompt } : {}
|
|
1492
|
-
};
|
|
1493
|
-
result.detailRev = state.detailRev ?? 0;
|
|
1494
|
-
return result;
|
|
1495
|
-
}
|
|
1496
|
-
function buildTimelineDetail(state, bounds) {
|
|
1497
|
-
return {
|
|
1498
|
-
rev: state.detailRev ?? 0,
|
|
1499
|
-
head: buildTimelineHead(state),
|
|
1500
|
-
...detailCollectionsOf(state, bounds)
|
|
1501
|
-
};
|
|
1502
|
-
}
|
|
1503
|
-
function buildTimelineView(state, bounds) {
|
|
1504
|
-
return {
|
|
1505
|
-
...headFieldsOf(state),
|
|
1506
|
-
...detailCollectionsOf(state, bounds)
|
|
1507
|
-
};
|
|
1508
|
-
}
|
|
1509
1517
|
//#endregion
|
|
1510
1518
|
//#region src/host/config.ts
|
|
1511
1519
|
const DEFAULT_BOUNDS = {
|
|
@@ -1549,7 +1557,8 @@ const Config = z$1.object({
|
|
|
1549
1557
|
"path"
|
|
1550
1558
|
]).default("count").loose()),
|
|
1551
1559
|
insightsEntry: volatileField(z$1.union(["show", "hide"]).default("show").loose()),
|
|
1552
|
-
defaultDurationCurve: volatileField(z$1.union(["show", "hide"]).default("show").loose())
|
|
1560
|
+
defaultDurationCurve: volatileField(z$1.union(["show", "hide"]).default("show").loose()),
|
|
1561
|
+
fleetTab: volatileField(z$1.union(["show", "hide"]).default("show").loose())
|
|
1553
1562
|
});
|
|
1554
1563
|
function resolveBounds(config) {
|
|
1555
1564
|
const resolved = Config(config ?? {});
|
|
@@ -1865,7 +1874,7 @@ function billedBucketsOf(value) {
|
|
|
1865
1874
|
const output = tokenCountOf(usage.outputTokens);
|
|
1866
1875
|
if (input === null && cacheRead === null && cacheWrite === null && output === null) return null;
|
|
1867
1876
|
return {
|
|
1868
|
-
|
|
1877
|
+
uncached: input ?? 0,
|
|
1869
1878
|
cacheRead: cacheRead ?? 0,
|
|
1870
1879
|
cacheWrite: cacheWrite ?? 0,
|
|
1871
1880
|
output: output ?? 0
|
|
@@ -1993,7 +2002,7 @@ function applyActivity(state, event) {
|
|
|
1993
2002
|
let cost = prev?.cost;
|
|
1994
2003
|
if (buckets !== null && state.model !== void 0) cost = addBilledUsage(cost, state.provider ?? "", state.model, initiated, buckets);
|
|
1995
2004
|
return withDayEntry(state, key, {
|
|
1996
|
-
tokens: (prev === void 0 ? 0 : prev.tokens) + (buckets === null ? 0 : buckets.
|
|
2005
|
+
tokens: (prev === void 0 ? 0 : prev.tokens) + (buckets === null ? 0 : buckets.uncached + buckets.cacheRead + buckets.cacheWrite + buckets.output),
|
|
1997
2006
|
requests: (prev === void 0 ? 0 : prev.requests) + 1,
|
|
1998
2007
|
...cost !== void 0 ? { cost } : {},
|
|
1999
2008
|
...prev?.skills !== void 0 ? { skills: prev.skills } : {}
|
|
@@ -2007,7 +2016,11 @@ function createContextActivityDefinition() {
|
|
|
2007
2016
|
apply: (state, event) => applyActivity(state, event),
|
|
2008
2017
|
wire: {
|
|
2009
2018
|
viewSchema: contextActivitySchema,
|
|
2010
|
-
view: (state) => ({ days: Object.fromEntries(Object.entries(state.days).map(([k, v]) => [k, {
|
|
2019
|
+
view: (state) => ({ days: Object.fromEntries(Object.entries(state.days).map(([k, v]) => [k, {
|
|
2020
|
+
...v,
|
|
2021
|
+
...v.cost !== void 0 ? { cost: copyCostUsage(v.cost) } : {},
|
|
2022
|
+
...v.skills !== void 0 ? { skills: Object.fromEntries(Object.entries(v.skills).map(([n, t]) => [n, { ...t }])) } : {}
|
|
2023
|
+
}])) })
|
|
2011
2024
|
},
|
|
2012
2025
|
stateVersion: 4
|
|
2013
2026
|
};
|
|
@@ -2172,19 +2185,36 @@ function createToolAttribution(ctx) {
|
|
|
2172
2185
|
return { ownerOf: (name) => mcpSourceOf(name) ?? live.get(name) ?? pinnedSourceOf(name) ?? (boot.has(name) ? "<unknown-plugin>" : void 0) };
|
|
2173
2186
|
}
|
|
2174
2187
|
//#endregion
|
|
2188
|
+
//#region src/host/record.ts
|
|
2189
|
+
function asRecord$1(value) {
|
|
2190
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
2191
|
+
}
|
|
2192
|
+
//#endregion
|
|
2175
2193
|
//#region src/host/connection.ts
|
|
2176
2194
|
function fetchRouteRegistrar(connection) {
|
|
2177
2195
|
return typeof connection?.fetch?.register === "function" ? connection.fetch.register.bind(connection.fetch) : void 0;
|
|
2178
2196
|
}
|
|
2197
|
+
function registerPostRoute(c, connection, path, fetch, label) {
|
|
2198
|
+
const register = fetchRouteRegistrar(connection);
|
|
2199
|
+
if (register === void 0) return false;
|
|
2200
|
+
try {
|
|
2201
|
+
c.effect(() => register({
|
|
2202
|
+
path,
|
|
2203
|
+
methods: ["POST"],
|
|
2204
|
+
requestBody: "buffered",
|
|
2205
|
+
fetch
|
|
2206
|
+
}), label);
|
|
2207
|
+
} catch {
|
|
2208
|
+
return false;
|
|
2209
|
+
}
|
|
2210
|
+
return true;
|
|
2211
|
+
}
|
|
2179
2212
|
//#endregion
|
|
2180
2213
|
//#region src/host/balance.ts
|
|
2181
2214
|
const BALANCE_ROUTE = "/api/dsh-context/balance";
|
|
2182
2215
|
const DEEPSEEK_SETTINGS_NS = "llm-deepseek";
|
|
2183
2216
|
const PUBLIC_BASE_URL = "https://api.deepseek.com";
|
|
2184
2217
|
const FETCH_TIMEOUT_MS = 1e4;
|
|
2185
|
-
function asRecord$2(value) {
|
|
2186
|
-
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
2187
|
-
}
|
|
2188
2218
|
function amountOf(value) {
|
|
2189
2219
|
const n = typeof value === "string" ? Number(value) : value;
|
|
2190
2220
|
return typeof n === "number" && Number.isFinite(n) && n >= 0 ? n : null;
|
|
@@ -2197,9 +2227,9 @@ function deepseekSectionOf(ctx) {
|
|
|
2197
2227
|
if (!Array.isArray(rows)) return null;
|
|
2198
2228
|
let shaped = null;
|
|
2199
2229
|
for (const row of rows) try {
|
|
2200
|
-
const record = asRecord$
|
|
2230
|
+
const record = asRecord$1(row);
|
|
2201
2231
|
if (record === null) continue;
|
|
2202
|
-
const value = asRecord$
|
|
2232
|
+
const value = asRecord$1(record.value);
|
|
2203
2233
|
if (value === null || typeof value.apiKeyEnv !== "string" || value.apiKeyEnv === "") continue;
|
|
2204
2234
|
if (record.ns === DEEPSEEK_SETTINGS_NS || record.ns === "llm-deepseek-api-key") return value;
|
|
2205
2235
|
shaped ??= value;
|
|
@@ -2232,12 +2262,12 @@ async function resolveFacts(ctx) {
|
|
|
2232
2262
|
};
|
|
2233
2263
|
}
|
|
2234
2264
|
function balanceOfPayload(value) {
|
|
2235
|
-
const data = asRecord$
|
|
2265
|
+
const data = asRecord$1(value);
|
|
2236
2266
|
if (data === null) return null;
|
|
2237
2267
|
const infos = Array.isArray(data.balance_infos) ? data.balance_infos : [];
|
|
2238
2268
|
const balances = [];
|
|
2239
2269
|
for (const info of infos) try {
|
|
2240
|
-
const entry = asRecord$
|
|
2270
|
+
const entry = asRecord$1(info);
|
|
2241
2271
|
if (entry === null) continue;
|
|
2242
2272
|
const currency = entry.currency;
|
|
2243
2273
|
const granted = amountOf(entry.granted_balance);
|
|
@@ -2285,8 +2315,6 @@ async function readBalance(facts) {
|
|
|
2285
2315
|
}
|
|
2286
2316
|
function watchBalanceChannel(ctx) {
|
|
2287
2317
|
ctx.inject(["connection"], (c) => {
|
|
2288
|
-
const register = fetchRouteRegistrar(c.get("connection"));
|
|
2289
|
-
if (register === void 0) return;
|
|
2290
2318
|
const handler = async () => {
|
|
2291
2319
|
const facts = await resolveFacts(ctx);
|
|
2292
2320
|
const value = facts !== null ? await readBalance(facts) : null;
|
|
@@ -2295,16 +2323,7 @@ function watchBalanceChannel(ctx) {
|
|
|
2295
2323
|
value
|
|
2296
2324
|
}, { headers: { "cache-control": "no-store" } });
|
|
2297
2325
|
};
|
|
2298
|
-
|
|
2299
|
-
c.effect(() => register({
|
|
2300
|
-
path: BALANCE_ROUTE,
|
|
2301
|
-
methods: ["POST"],
|
|
2302
|
-
requestBody: "buffered",
|
|
2303
|
-
fetch: handler
|
|
2304
|
-
}), "dsh-context: balance route");
|
|
2305
|
-
} catch {
|
|
2306
|
-
return;
|
|
2307
|
-
}
|
|
2326
|
+
registerPostRoute(c, c.get("connection"), BALANCE_ROUTE, handler, "dsh-context: balance route");
|
|
2308
2327
|
});
|
|
2309
2328
|
}
|
|
2310
2329
|
//#endregion
|
|
@@ -2340,9 +2359,6 @@ function makeColdReadGate(reading = v8Reading) {
|
|
|
2340
2359
|
const BACKFILL_ROUTE = "/api/dsh-context/backfill";
|
|
2341
2360
|
const YIELD_MS = 100;
|
|
2342
2361
|
const UNSUPPORTED_FORMAT = "SessionFormatUnsupported";
|
|
2343
|
-
function asRecord$1(value) {
|
|
2344
|
-
return value !== null && typeof value === "object" ? value : null;
|
|
2345
|
-
}
|
|
2346
2362
|
function headerOf(record) {
|
|
2347
2363
|
const header = asRecord$1(asRecord$1(record)?.header);
|
|
2348
2364
|
if (header === null) return null;
|
|
@@ -2392,7 +2408,7 @@ function isUnsupportedFormat(error) {
|
|
|
2392
2408
|
return false;
|
|
2393
2409
|
}
|
|
2394
2410
|
}
|
|
2395
|
-
function messageOf(error) {
|
|
2411
|
+
function messageOf$1(error) {
|
|
2396
2412
|
try {
|
|
2397
2413
|
return String(error);
|
|
2398
2414
|
} catch {
|
|
@@ -2409,22 +2425,12 @@ function watchActivityBackfill(ctx, coldReads = makeColdReadGate()) {
|
|
|
2409
2425
|
launch();
|
|
2410
2426
|
};
|
|
2411
2427
|
const routeFiber = ctx.inject(["connection"], (c) => {
|
|
2412
|
-
const
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
requestBody: "buffered",
|
|
2419
|
-
fetch: () => {
|
|
2420
|
-
requested = true;
|
|
2421
|
-
tryLaunch();
|
|
2422
|
-
return Response.json({ ok: true }, { headers: { "cache-control": "no-store" } });
|
|
2423
|
-
}
|
|
2424
|
-
}), "dsh-context: backfill route");
|
|
2425
|
-
} catch {
|
|
2426
|
-
return;
|
|
2427
|
-
}
|
|
2428
|
+
const handler = () => {
|
|
2429
|
+
requested = true;
|
|
2430
|
+
tryLaunch();
|
|
2431
|
+
return Response.json({ ok: true }, { headers: { "cache-control": "no-store" } });
|
|
2432
|
+
};
|
|
2433
|
+
registerPostRoute(c, c.get("connection"), BACKFILL_ROUTE, handler, "dsh-context: backfill route");
|
|
2428
2434
|
});
|
|
2429
2435
|
const runnerFiber = ctx.inject([
|
|
2430
2436
|
"sessionQuery",
|
|
@@ -2466,8 +2472,8 @@ function watchActivityBackfill(ctx, coldReads = makeColdReadGate()) {
|
|
|
2466
2472
|
} catch (error) {
|
|
2467
2473
|
if (isUnsupportedFormat(error)) {
|
|
2468
2474
|
refused++;
|
|
2469
|
-
ctx.logger.debug(`dsh-context: projection backfill skipped "${header.id}" (${messageOf(error)})`);
|
|
2470
|
-
} else ctx.logger.warn(`dsh-context: projection backfill skipped "${header.id}" (${messageOf(error)})`);
|
|
2475
|
+
ctx.logger.debug(`dsh-context: projection backfill skipped "${header.id}" (${messageOf$1(error)})`);
|
|
2476
|
+
} else ctx.logger.warn(`dsh-context: projection backfill skipped "${header.id}" (${messageOf$1(error)})`);
|
|
2471
2477
|
}
|
|
2472
2478
|
await new Promise((resolve) => setTimeout(resolve, YIELD_MS));
|
|
2473
2479
|
}
|
|
@@ -2477,7 +2483,7 @@ function watchActivityBackfill(ctx, coldReads = makeColdReadGate()) {
|
|
|
2477
2483
|
};
|
|
2478
2484
|
launch = () => {
|
|
2479
2485
|
run().catch((error) => {
|
|
2480
|
-
if (!abort.signal.aborted) ctx.logger.warn(`dsh-context: projection backfill stopped early (${messageOf(error)})`);
|
|
2486
|
+
if (!abort.signal.aborted) ctx.logger.warn(`dsh-context: projection backfill stopped early (${messageOf$1(error)})`);
|
|
2481
2487
|
});
|
|
2482
2488
|
};
|
|
2483
2489
|
tryLaunch();
|
|
@@ -2489,14 +2495,11 @@ function watchActivityBackfill(ctx, coldReads = makeColdReadGate()) {
|
|
|
2489
2495
|
for (const fiber of [routeFiber, runnerFiber]) fiber?.dispose?.();
|
|
2490
2496
|
};
|
|
2491
2497
|
}
|
|
2492
|
-
|
|
2493
|
-
//#region src/host/detail.ts
|
|
2494
|
-
const DETAIL_ROUTE = "/api/dsh-context/detail";
|
|
2495
|
-
function reply(value) {
|
|
2498
|
+
function reply$1(value) {
|
|
2496
2499
|
return Response.json(value, { headers: { "cache-control": "no-store" } });
|
|
2497
2500
|
}
|
|
2498
|
-
function failure(code, message) {
|
|
2499
|
-
return reply({
|
|
2501
|
+
function failure$1(code, message) {
|
|
2502
|
+
return reply$1({
|
|
2500
2503
|
ok: false,
|
|
2501
2504
|
error: {
|
|
2502
2505
|
code,
|
|
@@ -2508,9 +2511,8 @@ function watchDetailChannel(ctx, bounds, coldReads = makeColdReadGate()) {
|
|
|
2508
2511
|
const gate = { live: false };
|
|
2509
2512
|
ctx.inject(["connection", "sessions"], (c) => {
|
|
2510
2513
|
const sessions = c.get("sessions");
|
|
2511
|
-
const register = fetchRouteRegistrar(c.get("connection"));
|
|
2512
2514
|
const getSession = typeof sessions?.get === "function" ? sessions.get.bind(sessions) : void 0;
|
|
2513
|
-
if (
|
|
2515
|
+
if (getSession === void 0) return;
|
|
2514
2516
|
const projections = ctx.sessionProjections;
|
|
2515
2517
|
const handler = async (request) => {
|
|
2516
2518
|
let sessionId;
|
|
@@ -2518,29 +2520,29 @@ function watchDetailChannel(ctx, bounds, coldReads = makeColdReadGate()) {
|
|
|
2518
2520
|
const body = await request.json();
|
|
2519
2521
|
sessionId = body !== null && typeof body === "object" ? body.sessionId : void 0;
|
|
2520
2522
|
} catch {
|
|
2521
|
-
return failure("dsh-context/bad-request", "body is not JSON");
|
|
2523
|
+
return failure$1("dsh-context/bad-request", "body is not JSON");
|
|
2522
2524
|
}
|
|
2523
|
-
if (typeof sessionId !== "string" || sessionId === "") return failure("dsh-context/bad-request", "missing sessionId");
|
|
2525
|
+
if (typeof sessionId !== "string" || sessionId === "") return failure$1("dsh-context/bad-request", "missing sessionId");
|
|
2524
2526
|
try {
|
|
2525
2527
|
const session = getSession(sessionId);
|
|
2526
2528
|
if (session !== void 0 && session !== null) {
|
|
2527
2529
|
const state = projections.stateOf(session, "contextTimeline");
|
|
2528
|
-
if (state === void 0) return reply({
|
|
2530
|
+
if (state === void 0) return reply$1({
|
|
2529
2531
|
ok: true,
|
|
2530
2532
|
value: null
|
|
2531
2533
|
});
|
|
2532
|
-
return reply({
|
|
2534
|
+
return reply$1({
|
|
2533
2535
|
ok: true,
|
|
2534
2536
|
value: buildTimelineDetail(state, bounds)
|
|
2535
2537
|
});
|
|
2536
2538
|
}
|
|
2537
2539
|
const query = ctx.get("sessionQuery");
|
|
2538
2540
|
const observe = typeof query?.observeSession === "function" ? query.observeSession.bind(query) : void 0;
|
|
2539
|
-
if (observe === void 0) return reply({
|
|
2541
|
+
if (observe === void 0) return reply$1({
|
|
2540
2542
|
ok: true,
|
|
2541
2543
|
value: null
|
|
2542
2544
|
});
|
|
2543
|
-
return reply({
|
|
2545
|
+
return reply$1({
|
|
2544
2546
|
ok: true,
|
|
2545
2547
|
value: await coldReads.admit(async () => {
|
|
2546
2548
|
const observation = await observe(sessionId, { projectionMode: "none" });
|
|
@@ -2557,19 +2559,10 @@ function watchDetailChannel(ctx, bounds, coldReads = makeColdReadGate()) {
|
|
|
2557
2559
|
}) ?? null
|
|
2558
2560
|
});
|
|
2559
2561
|
} catch (err) {
|
|
2560
|
-
return failure("gateway/internal", err instanceof Error ? err.message : String(err));
|
|
2562
|
+
return failure$1("gateway/internal", err instanceof Error ? err.message : String(err));
|
|
2561
2563
|
}
|
|
2562
2564
|
};
|
|
2563
|
-
|
|
2564
|
-
c.effect(() => register({
|
|
2565
|
-
path: DETAIL_ROUTE,
|
|
2566
|
-
methods: ["POST"],
|
|
2567
|
-
requestBody: "buffered",
|
|
2568
|
-
fetch: handler
|
|
2569
|
-
}), "dsh-context: detail route");
|
|
2570
|
-
} catch {
|
|
2571
|
-
return;
|
|
2572
|
-
}
|
|
2565
|
+
if (!registerPostRoute(c, c.get("connection"), "/api/dsh-context/detail", handler, "dsh-context: detail route")) return;
|
|
2573
2566
|
gate.live = true;
|
|
2574
2567
|
return () => {
|
|
2575
2568
|
gate.live = false;
|
|
@@ -2746,6 +2739,237 @@ function createFallbackActivityDefinition() {
|
|
|
2746
2739
|
return fallbackDefinition("contextActivity", contextActivitySchema, { days: {} });
|
|
2747
2740
|
}
|
|
2748
2741
|
//#endregion
|
|
2742
|
+
//#region src/host/fleet.ts
|
|
2743
|
+
const FLEET_ROUTE = "/api/dsh-context/fleet";
|
|
2744
|
+
const MESSAGES_MAX = 40;
|
|
2745
|
+
const MESSAGE_TEXT_MAX = 400;
|
|
2746
|
+
const PROMPT_TEXT_MAX = 1600;
|
|
2747
|
+
const REPLY_TEXT_MAX = 300;
|
|
2748
|
+
function reply(value) {
|
|
2749
|
+
return Response.json(value, { headers: { "cache-control": "no-store" } });
|
|
2750
|
+
}
|
|
2751
|
+
function failure(code, message) {
|
|
2752
|
+
return reply({
|
|
2753
|
+
ok: false,
|
|
2754
|
+
error: {
|
|
2755
|
+
code,
|
|
2756
|
+
message
|
|
2757
|
+
}
|
|
2758
|
+
});
|
|
2759
|
+
}
|
|
2760
|
+
function asRecord(value) {
|
|
2761
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
2762
|
+
}
|
|
2763
|
+
function textOfContent(content) {
|
|
2764
|
+
if (!Array.isArray(content)) return "";
|
|
2765
|
+
let out = "";
|
|
2766
|
+
for (const block of content) {
|
|
2767
|
+
const text = asRecord(block)?.text;
|
|
2768
|
+
if (typeof text === "string") out += text;
|
|
2769
|
+
}
|
|
2770
|
+
return out;
|
|
2771
|
+
}
|
|
2772
|
+
const REMINDER_PREFIX = /^\s*<system-reminder>[\s\S]*?<\/system-reminder>\s*/;
|
|
2773
|
+
function clip(text, max) {
|
|
2774
|
+
return text.length > max ? {
|
|
2775
|
+
text: text.slice(0, max) + "…",
|
|
2776
|
+
cut: true
|
|
2777
|
+
} : {
|
|
2778
|
+
text,
|
|
2779
|
+
cut: false
|
|
2780
|
+
};
|
|
2781
|
+
}
|
|
2782
|
+
function descriptorOf(data) {
|
|
2783
|
+
const mode = data.mode;
|
|
2784
|
+
if (mode !== "one-shot" && mode !== "continuable") return null;
|
|
2785
|
+
const out = { mode };
|
|
2786
|
+
for (const key of [
|
|
2787
|
+
"label",
|
|
2788
|
+
"provider",
|
|
2789
|
+
"agentProvider",
|
|
2790
|
+
"agentModel",
|
|
2791
|
+
"persona"
|
|
2792
|
+
]) {
|
|
2793
|
+
const value = data[key];
|
|
2794
|
+
if (typeof value === "string" && value !== "") out[key] = value;
|
|
2795
|
+
}
|
|
2796
|
+
return out;
|
|
2797
|
+
}
|
|
2798
|
+
const MAILBOX_PREFIX = /^Team message \S+ from [^:]{1,64}:\s*/;
|
|
2799
|
+
const RELAY_PREFIX = /^(?:Agent \S+ sent a message: |Team message from [^:\n]{1,64}:\s*)/;
|
|
2800
|
+
function messageOf(seq, time, data) {
|
|
2801
|
+
const source = asRecord(data.source);
|
|
2802
|
+
const kind = source?.kind;
|
|
2803
|
+
let message = null;
|
|
2804
|
+
if (kind === "agent-message" || kind === "team-message") {
|
|
2805
|
+
let text = textOfContent(data.content);
|
|
2806
|
+
text = text.replace(kind === "team-message" ? MAILBOX_PREFIX : RELAY_PREFIX, "");
|
|
2807
|
+
if (text.trim() === "") return null;
|
|
2808
|
+
message = {
|
|
2809
|
+
seq,
|
|
2810
|
+
time,
|
|
2811
|
+
kind: kind === "agent-message" ? "relay" : "mailbox",
|
|
2812
|
+
text
|
|
2813
|
+
};
|
|
2814
|
+
const from = kind === "agent-message" ? source?.senderSessionId : source?.senderId;
|
|
2815
|
+
if (typeof from === "string" && from !== "") message.from = from;
|
|
2816
|
+
const fromName = source?.senderName;
|
|
2817
|
+
if (typeof fromName === "string" && fromName !== "") message.fromName = fromName;
|
|
2818
|
+
} else if (kind === "subagent-settled") {
|
|
2819
|
+
const summary = source?.summary;
|
|
2820
|
+
const text = typeof summary === "string" && summary.trim() !== "" ? summary : textOfContent(data.content);
|
|
2821
|
+
if (text.trim() === "") return null;
|
|
2822
|
+
message = {
|
|
2823
|
+
seq,
|
|
2824
|
+
time,
|
|
2825
|
+
kind: "settled",
|
|
2826
|
+
text
|
|
2827
|
+
};
|
|
2828
|
+
const from = source?.senderSessionId;
|
|
2829
|
+
if (typeof from === "string" && from !== "") message.from = from;
|
|
2830
|
+
}
|
|
2831
|
+
if (message === null) return null;
|
|
2832
|
+
const cut = clip(message.text, MESSAGE_TEXT_MAX);
|
|
2833
|
+
message.text = cut.text;
|
|
2834
|
+
return message;
|
|
2835
|
+
}
|
|
2836
|
+
function isPlainPrompt(source) {
|
|
2837
|
+
if (source === null) return true;
|
|
2838
|
+
return source.kind === "user";
|
|
2839
|
+
}
|
|
2840
|
+
function rosterMemberOf(data) {
|
|
2841
|
+
const member = asRecord(data.member);
|
|
2842
|
+
if (member === null) return null;
|
|
2843
|
+
if (typeof member.name !== "string" || member.name === "") return null;
|
|
2844
|
+
const out = {
|
|
2845
|
+
name: member.name,
|
|
2846
|
+
description: typeof member.description === "string" ? member.description : ""
|
|
2847
|
+
};
|
|
2848
|
+
if (typeof member.provider === "string" && member.provider !== "") out.provider = member.provider;
|
|
2849
|
+
if (member.context === "fresh" || member.context === "fork") out.context = member.context;
|
|
2850
|
+
return out;
|
|
2851
|
+
}
|
|
2852
|
+
function lastReplyOf(events) {
|
|
2853
|
+
for (let i = events.length - 1; i >= 0; i--) {
|
|
2854
|
+
const ev = asRecord(events[i]);
|
|
2855
|
+
if (ev === null || ev.type !== "assistant/message") continue;
|
|
2856
|
+
const content = asRecord(asRecord(ev.data)?.message)?.content;
|
|
2857
|
+
if (!Array.isArray(content)) continue;
|
|
2858
|
+
let text = "";
|
|
2859
|
+
for (const block of content) {
|
|
2860
|
+
const b = asRecord(block);
|
|
2861
|
+
if (b?.type === "text" && typeof b.text === "string") text += b.text;
|
|
2862
|
+
}
|
|
2863
|
+
if (text.trim() === "") continue;
|
|
2864
|
+
const time = typeof ev.time === "number" && Number.isFinite(ev.time) ? ev.time : 0;
|
|
2865
|
+
const cut = clip(text, REPLY_TEXT_MAX);
|
|
2866
|
+
return {
|
|
2867
|
+
time,
|
|
2868
|
+
text: cut.text,
|
|
2869
|
+
cut: cut.cut
|
|
2870
|
+
};
|
|
2871
|
+
}
|
|
2872
|
+
return null;
|
|
2873
|
+
}
|
|
2874
|
+
function fleetDetailOfEvents(events) {
|
|
2875
|
+
let descriptor;
|
|
2876
|
+
let initialPrompt;
|
|
2877
|
+
let truncated = false;
|
|
2878
|
+
const messages = [];
|
|
2879
|
+
const roster = new Map();
|
|
2880
|
+
for (const entry of events) {
|
|
2881
|
+
const ev = asRecord(entry);
|
|
2882
|
+
if (ev === null) continue;
|
|
2883
|
+
const type = ev.type;
|
|
2884
|
+
if (typeof type !== "string") continue;
|
|
2885
|
+
const seq = typeof ev.seq === "number" && Number.isFinite(ev.seq) ? ev.seq : 0;
|
|
2886
|
+
const time = typeof ev.time === "number" && Number.isFinite(ev.time) ? ev.time : 0;
|
|
2887
|
+
const data = asRecord(ev.data);
|
|
2888
|
+
if (data === null) continue;
|
|
2889
|
+
if (type === "subagent/descriptor") {
|
|
2890
|
+
const next = descriptorOf(data);
|
|
2891
|
+
if (next !== null) descriptor = next;
|
|
2892
|
+
continue;
|
|
2893
|
+
}
|
|
2894
|
+
if (type === "team/member") {
|
|
2895
|
+
const member = rosterMemberOf(data);
|
|
2896
|
+
if (member !== null) roster.set(member.name, member);
|
|
2897
|
+
continue;
|
|
2898
|
+
}
|
|
2899
|
+
if (type !== "user/message") continue;
|
|
2900
|
+
const message = messageOf(seq, time, data);
|
|
2901
|
+
if (message !== null) {
|
|
2902
|
+
if (message.text.endsWith("…")) truncated = true;
|
|
2903
|
+
messages.push(message);
|
|
2904
|
+
continue;
|
|
2905
|
+
}
|
|
2906
|
+
if (initialPrompt === void 0 && isPlainPrompt(asRecord(data.source))) {
|
|
2907
|
+
const text = textOfContent(data.content).replace(REMINDER_PREFIX, "");
|
|
2908
|
+
if (text.trim() !== "") {
|
|
2909
|
+
const cut = clip(text, PROMPT_TEXT_MAX);
|
|
2910
|
+
initialPrompt = cut.text;
|
|
2911
|
+
if (cut.cut) truncated = true;
|
|
2912
|
+
}
|
|
2913
|
+
}
|
|
2914
|
+
}
|
|
2915
|
+
messages.sort((a, b) => b.seq - a.seq);
|
|
2916
|
+
if (messages.length > MESSAGES_MAX) {
|
|
2917
|
+
messages.length = MESSAGES_MAX;
|
|
2918
|
+
truncated = true;
|
|
2919
|
+
}
|
|
2920
|
+
const reply = lastReplyOf(events);
|
|
2921
|
+
if (reply !== null && reply.cut) truncated = true;
|
|
2922
|
+
return {
|
|
2923
|
+
...descriptor !== void 0 ? { descriptor } : {},
|
|
2924
|
+
...initialPrompt !== void 0 ? { initialPrompt } : {},
|
|
2925
|
+
...reply !== null ? { lastReply: {
|
|
2926
|
+
time: reply.time,
|
|
2927
|
+
text: reply.text
|
|
2928
|
+
} } : {},
|
|
2929
|
+
...roster.size > 0 ? { roster: [...roster.values()] } : {},
|
|
2930
|
+
messages,
|
|
2931
|
+
truncated
|
|
2932
|
+
};
|
|
2933
|
+
}
|
|
2934
|
+
function watchFleetChannel(ctx, coldReads = makeColdReadGate()) {
|
|
2935
|
+
ctx.inject(["connection"], (c) => {
|
|
2936
|
+
const handler = async (request) => {
|
|
2937
|
+
let sessionId;
|
|
2938
|
+
try {
|
|
2939
|
+
sessionId = asRecord(await request.json())?.sessionId;
|
|
2940
|
+
} catch {
|
|
2941
|
+
return failure("dsh-context/bad-request", "body is not JSON");
|
|
2942
|
+
}
|
|
2943
|
+
if (typeof sessionId !== "string" || sessionId === "") return failure("dsh-context/bad-request", "missing sessionId");
|
|
2944
|
+
try {
|
|
2945
|
+
const query = ctx.get("sessionQuery");
|
|
2946
|
+
const observe = typeof query?.observeSession === "function" ? query.observeSession.bind(query) : void 0;
|
|
2947
|
+
if (observe === void 0) return reply({
|
|
2948
|
+
ok: true,
|
|
2949
|
+
value: null
|
|
2950
|
+
});
|
|
2951
|
+
return reply({
|
|
2952
|
+
ok: true,
|
|
2953
|
+
value: await coldReads.admit(async () => {
|
|
2954
|
+
const observation = await observe(sessionId, { projectionMode: "none" });
|
|
2955
|
+
const events = observation?.events;
|
|
2956
|
+
if (!Array.isArray(events)) return null;
|
|
2957
|
+
try {
|
|
2958
|
+
return fleetDetailOfEvents(events);
|
|
2959
|
+
} finally {
|
|
2960
|
+
const dispose = observation?.[Symbol.dispose];
|
|
2961
|
+
if (typeof dispose === "function") dispose.call(observation);
|
|
2962
|
+
}
|
|
2963
|
+
}) ?? null
|
|
2964
|
+
});
|
|
2965
|
+
} catch (err) {
|
|
2966
|
+
return failure("gateway/internal", err instanceof Error ? err.message : String(err));
|
|
2967
|
+
}
|
|
2968
|
+
};
|
|
2969
|
+
registerPostRoute(c, c.get("connection"), FLEET_ROUTE, handler, "dsh-context: fleet route");
|
|
2970
|
+
});
|
|
2971
|
+
}
|
|
2972
|
+
//#endregion
|
|
2749
2973
|
//#region src/host/stepIdentity.ts
|
|
2750
2974
|
const MINTED_ID_PREFIX = "dshctx-";
|
|
2751
2975
|
function lacksId(message) {
|
|
@@ -2787,9 +3011,6 @@ function watchStepIdentity(ctx) {
|
|
|
2787
3011
|
//#region src/host/skills.ts
|
|
2788
3012
|
const SKILLS_ROUTE = "/api/dsh-context/skills";
|
|
2789
3013
|
const MAX_SKILLS = 500;
|
|
2790
|
-
function asRecord(value) {
|
|
2791
|
-
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
2792
|
-
}
|
|
2793
3014
|
function stringOf(value) {
|
|
2794
3015
|
return typeof value === "string" && value !== "" ? value : void 0;
|
|
2795
3016
|
}
|
|
@@ -2806,7 +3027,7 @@ async function disposeOf(resource) {
|
|
|
2806
3027
|
} catch {}
|
|
2807
3028
|
}
|
|
2808
3029
|
function skillInfoOf(value) {
|
|
2809
|
-
const record = asRecord(value);
|
|
3030
|
+
const record = asRecord$1(value);
|
|
2810
3031
|
if (record === null || typeof record.name !== "string" || record.name === "") return null;
|
|
2811
3032
|
return {
|
|
2812
3033
|
name: record.name,
|
|
@@ -2817,7 +3038,7 @@ function skillInfoOf(value) {
|
|
|
2817
3038
|
}
|
|
2818
3039
|
async function sessionViewOf(ctx, sessionId) {
|
|
2819
3040
|
if (sessionId === void 0) return {};
|
|
2820
|
-
const query = asRecord(ctx.get("sessionQuery"));
|
|
3041
|
+
const query = asRecord$1(ctx.get("sessionQuery"));
|
|
2821
3042
|
if (typeof query?.observeSession !== "function") return {};
|
|
2822
3043
|
let observation;
|
|
2823
3044
|
try {
|
|
@@ -2826,9 +3047,9 @@ async function sessionViewOf(ctx, sessionId) {
|
|
|
2826
3047
|
return {};
|
|
2827
3048
|
}
|
|
2828
3049
|
try {
|
|
2829
|
-
const obs = asRecord(observation);
|
|
2830
|
-
const cwd = stringOf(asRecord(obs?.header)?.cwd);
|
|
2831
|
-
const agentPreset = stringOf(asRecord(asRecord(obs?.projections)?.values)?.agentPreset);
|
|
3050
|
+
const obs = asRecord$1(observation);
|
|
3051
|
+
const cwd = stringOf(asRecord$1(obs?.header)?.cwd);
|
|
3052
|
+
const agentPreset = stringOf(asRecord$1(asRecord$1(obs?.projections)?.values)?.agentPreset);
|
|
2832
3053
|
return {
|
|
2833
3054
|
...cwd === void 0 ? {} : { cwd },
|
|
2834
3055
|
...agentPreset === void 0 ? {} : { agentPreset }
|
|
@@ -2838,10 +3059,10 @@ async function sessionViewOf(ctx, sessionId) {
|
|
|
2838
3059
|
}
|
|
2839
3060
|
}
|
|
2840
3061
|
async function resolveRegistry(ctx, sessionId, agentPreset) {
|
|
2841
|
-
const presets = asRecord(ctx.get("agentPresets"));
|
|
3062
|
+
const presets = asRecord$1(ctx.get("agentPresets"));
|
|
2842
3063
|
let live;
|
|
2843
3064
|
if (sessionId !== void 0) {
|
|
2844
|
-
const agents = asRecord(ctx.get("agents"));
|
|
3065
|
+
const agents = asRecord$1(ctx.get("agents"));
|
|
2845
3066
|
if (typeof agents?.get === "function") try {
|
|
2846
3067
|
live = agents.get.call(agents, sessionId);
|
|
2847
3068
|
} catch {
|
|
@@ -2849,20 +3070,20 @@ async function resolveRegistry(ctx, sessionId, agentPreset) {
|
|
|
2849
3070
|
}
|
|
2850
3071
|
}
|
|
2851
3072
|
if (live !== void 0 && live !== null && typeof presets?.serviceFor === "function") {
|
|
2852
|
-
const scoped = asRecord(presets.serviceFor.call(presets, live, "skills"));
|
|
3073
|
+
const scoped = asRecord$1(presets.serviceFor.call(presets, live, "skills"));
|
|
2853
3074
|
if (scoped !== null && typeof scoped.list === "function") return {
|
|
2854
3075
|
registry: scoped,
|
|
2855
3076
|
scope: live,
|
|
2856
3077
|
lease: void 0
|
|
2857
3078
|
};
|
|
2858
3079
|
}
|
|
2859
|
-
const registry = asRecord(ctx.get("skills"));
|
|
3080
|
+
const registry = asRecord$1(ctx.get("skills"));
|
|
2860
3081
|
if (registry === null || typeof registry.list !== "function") return null;
|
|
2861
3082
|
let scope;
|
|
2862
3083
|
let lease;
|
|
2863
3084
|
if (typeof presets?.acquireScope === "function") try {
|
|
2864
3085
|
lease = await presets.acquireScope.call(presets, agentPreset);
|
|
2865
|
-
scope = asRecord(lease)?.key;
|
|
3086
|
+
scope = asRecord$1(lease)?.key;
|
|
2866
3087
|
} catch {
|
|
2867
3088
|
lease = void 0;
|
|
2868
3089
|
}
|
|
@@ -2874,13 +3095,11 @@ async function resolveRegistry(ctx, sessionId, agentPreset) {
|
|
|
2874
3095
|
}
|
|
2875
3096
|
function watchSkillCatalog(ctx) {
|
|
2876
3097
|
ctx.inject(["connection"], (c) => {
|
|
2877
|
-
const register = fetchRouteRegistrar(c.get("connection"));
|
|
2878
|
-
if (register === void 0) return;
|
|
2879
3098
|
const handler = async (request) => {
|
|
2880
3099
|
let value = null;
|
|
2881
3100
|
let lease;
|
|
2882
3101
|
try {
|
|
2883
|
-
const body = asRecord(await request.json());
|
|
3102
|
+
const body = asRecord$1(await request.json());
|
|
2884
3103
|
const sessionId = stringOf(body?.sessionId);
|
|
2885
3104
|
const view = await sessionViewOf(ctx, sessionId);
|
|
2886
3105
|
const cwd = view.cwd ?? stringOf(body?.cwd);
|
|
@@ -2908,16 +3127,7 @@ function watchSkillCatalog(ctx) {
|
|
|
2908
3127
|
value
|
|
2909
3128
|
}, { headers: { "cache-control": "no-store" } });
|
|
2910
3129
|
};
|
|
2911
|
-
|
|
2912
|
-
c.effect(() => register({
|
|
2913
|
-
path: SKILLS_ROUTE,
|
|
2914
|
-
methods: ["POST"],
|
|
2915
|
-
requestBody: "buffered",
|
|
2916
|
-
fetch: handler
|
|
2917
|
-
}), "dsh-context: skills route");
|
|
2918
|
-
} catch {
|
|
2919
|
-
return;
|
|
2920
|
-
}
|
|
3130
|
+
registerPostRoute(c, c.get("connection"), SKILLS_ROUTE, handler, "dsh-context: skills route");
|
|
2921
3131
|
});
|
|
2922
3132
|
}
|
|
2923
3133
|
//#endregion
|
|
@@ -3013,8 +3223,10 @@ function detectHarnessVersion(ctx, resolveUrl = resolveRunningModule, pluginRoot
|
|
|
3013
3223
|
const name = "dsh-context";
|
|
3014
3224
|
const inject = ["sessionProjections"];
|
|
3015
3225
|
function apply(ctx, config) {
|
|
3226
|
+
const coldReads = makeColdReadGate();
|
|
3016
3227
|
watchBalanceChannel(ctx);
|
|
3017
3228
|
watchSkillCatalog(ctx);
|
|
3229
|
+
watchFleetChannel(ctx, coldReads);
|
|
3018
3230
|
const harnessVersion = detectHarnessVersion(ctx);
|
|
3019
3231
|
if (harnessVersion !== void 0 && !meetsBaseline(harnessVersion)) {
|
|
3020
3232
|
ctx.sessionProjections.register(createFallbackTimelineDefinition(harnessVersion));
|
|
@@ -3024,7 +3236,6 @@ function apply(ctx, config) {
|
|
|
3024
3236
|
}
|
|
3025
3237
|
const attribution = createToolAttribution(ctx);
|
|
3026
3238
|
watchStepIdentity(ctx);
|
|
3027
|
-
const coldReads = makeColdReadGate();
|
|
3028
3239
|
const gate = watchDetailChannel(ctx, resolveBounds(config), coldReads);
|
|
3029
3240
|
ctx.sessionProjections.register(createContextTimelineDefinition(config, () => gate.live));
|
|
3030
3241
|
ctx.sessionProjections.register(createContextHeadersDefinition((name) => attribution.ownerOf(name)));
|