priiisk 0.1.19 → 0.1.21
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/dist/{chunk-WRNKCW6X.js → chunk-6KCQ6O4T.js} +26 -36
- package/dist/{chunk-26WAMIP2.js → chunk-DPNPQG2D.js} +5526 -1382
- package/dist/{chunk-UGJ3G52D.js → chunk-GYYNOMA5.js} +21 -21
- package/dist/{chunk-GFEPED7X.js → chunk-IPF3C3B2.js} +23 -23
- package/dist/{chunk-VEYMTNDB.js → chunk-K7LA4DNU.js} +979 -333
- package/dist/{chunk-S4KO3BZU.js → chunk-PCOWK5BR.js} +7 -7
- package/dist/{chunk-X4X2HTNU.js → chunk-PIHJTCPQ.js} +90 -90
- package/dist/{chunk-37ROQVP3.js → chunk-QY7U7U2K.js} +3409 -7728
- package/dist/{chunk-5IO2ETKC.js → chunk-TUCFONJW.js} +1 -1
- package/dist/{chunk-5TXANNSW.js → chunk-U2FODXMR.js} +54 -22
- package/dist/priiisk-host.js +1139 -430
- package/dist/priiisk.js +2 -2
- package/package.json +13 -13
- /package/dist/{chunk-37ROQVP3.js.LEGAL.txt → chunk-DPNPQG2D.js.LEGAL.txt} +0 -0
- /package/dist/{chunk-GFEPED7X.js.LEGAL.txt → chunk-IPF3C3B2.js.LEGAL.txt} +0 -0
|
@@ -2,15 +2,16 @@ import { createRequire as __priiiskCreateRequire } from "node:module";
|
|
|
2
2
|
const require = __priiiskCreateRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
CampAskState,
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
CampWorkerState,
|
|
6
|
+
get2,
|
|
7
|
+
make2 as make4,
|
|
7
8
|
modify,
|
|
8
9
|
modifyEffect,
|
|
9
|
-
set,
|
|
10
|
+
set as set2,
|
|
10
11
|
tagsExhaustive,
|
|
11
12
|
type,
|
|
12
|
-
update
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
update as update2
|
|
14
|
+
} from "./chunk-U2FODXMR.js";
|
|
14
15
|
import {
|
|
15
16
|
Tag,
|
|
16
17
|
TaggedError,
|
|
@@ -18,36 +19,44 @@ import {
|
|
|
18
19
|
_void,
|
|
19
20
|
acquireRelease,
|
|
20
21
|
addFinalizer2 as addFinalizer,
|
|
21
|
-
|
|
22
|
+
as,
|
|
22
23
|
catchAll,
|
|
23
|
-
|
|
24
|
+
catchAllCause,
|
|
24
25
|
currentTimeMillis,
|
|
26
|
+
equipmentDescriptionLines,
|
|
25
27
|
fail4 as fail,
|
|
26
|
-
|
|
28
|
+
flatMap3 as flatMap,
|
|
27
29
|
forEach,
|
|
28
|
-
|
|
30
|
+
forever,
|
|
29
31
|
forkScoped,
|
|
30
32
|
gen,
|
|
33
|
+
get4 as get,
|
|
34
|
+
getAndSet,
|
|
31
35
|
ignore,
|
|
32
36
|
isInterruptedOnly,
|
|
33
37
|
isSuccess,
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
make14 as make3,
|
|
39
|
+
make6 as make,
|
|
40
|
+
make7 as make2,
|
|
36
41
|
makeRuntime,
|
|
42
|
+
millis,
|
|
43
|
+
never,
|
|
37
44
|
pretty,
|
|
38
45
|
run2 as run,
|
|
39
46
|
runForEach,
|
|
40
47
|
runFork,
|
|
41
48
|
scoped,
|
|
49
|
+
set2 as set,
|
|
42
50
|
sleep,
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
succeed2 as succeed,
|
|
52
|
+
succeed3 as succeed2,
|
|
53
|
+
suspend,
|
|
54
|
+
sync,
|
|
47
55
|
taggedEnum,
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
56
|
+
tap,
|
|
57
|
+
update,
|
|
58
|
+
zipRight
|
|
59
|
+
} from "./chunk-DPNPQG2D.js";
|
|
51
60
|
import "./chunk-7UPFIIZD.js";
|
|
52
61
|
|
|
53
62
|
// packages/host-ui/src/backend/campUiBackend.ts
|
|
@@ -76,6 +85,7 @@ var makeInitialCampUiState = (snapshot, presentationNow = 0) => ({
|
|
|
76
85
|
screen: CampUiScreen.camp,
|
|
77
86
|
focusedSlotId: "roster",
|
|
78
87
|
detailVisible: false,
|
|
88
|
+
inventoryVisible: false,
|
|
79
89
|
presentationNow,
|
|
80
90
|
drafts: /* @__PURE__ */ new Map(),
|
|
81
91
|
scrollOffsets: /* @__PURE__ */ new Map(),
|
|
@@ -139,8 +149,8 @@ var updateCampUiStringSet = (current, value, included) => {
|
|
|
139
149
|
var CampUiControllerError = class extends TaggedError("CampUiControllerError") {
|
|
140
150
|
};
|
|
141
151
|
var makeCampUiStore = (initial, presentationNow = 0) => gen(function* () {
|
|
142
|
-
const modelRef = yield*
|
|
143
|
-
const updateState = (mutate) =>
|
|
152
|
+
const modelRef = yield* make4(makeCampUiModel(initial, presentationNow));
|
|
153
|
+
const updateState = (mutate) => update2(modelRef, (model) => ({ ...model, state: mutate(model.state) }));
|
|
144
154
|
const controller = {
|
|
145
155
|
selectWorker: (workerId) => modifyEffect(
|
|
146
156
|
modelRef,
|
|
@@ -201,6 +211,10 @@ var makeCampUiStore = (initial, presentationNow = 0) => gen(function* () {
|
|
|
201
211
|
if (state.detailVisible === detailVisible) return state;
|
|
202
212
|
return { ...state, detailVisible };
|
|
203
213
|
}),
|
|
214
|
+
setInventoryVisible: (inventoryVisible) => updateState((state) => {
|
|
215
|
+
if (state.inventoryVisible === inventoryVisible) return state;
|
|
216
|
+
return { ...state, inventoryVisible };
|
|
217
|
+
}),
|
|
204
218
|
setDetailBlockExpanded: (blockId, expanded) => updateState((state) => ({
|
|
205
219
|
...state,
|
|
206
220
|
expandedDetailBlockIds: updateCampUiStringSet(
|
|
@@ -224,7 +238,7 @@ var makeCampUiStore = (initial, presentationNow = 0) => gen(function* () {
|
|
|
224
238
|
})
|
|
225
239
|
};
|
|
226
240
|
return {
|
|
227
|
-
current:
|
|
241
|
+
current: get2(modelRef),
|
|
228
242
|
changes: modelRef.changes,
|
|
229
243
|
updateSnapshot: (snapshot) => modify(modelRef, (current) => {
|
|
230
244
|
const stale = current.snapshot.generation === snapshot.generation && snapshot.revision <= current.snapshot.revision;
|
|
@@ -238,9 +252,16 @@ var makeCampUiStore = (initial, presentationNow = 0) => gen(function* () {
|
|
|
238
252
|
var makeCampUiComponentGroup = (components) => {
|
|
239
253
|
const inputComponents = components.some((component) => component.handleInput !== void 0);
|
|
240
254
|
const pointerComponents = components.some((component) => component.handlePointer !== void 0);
|
|
255
|
+
const sizingComponents = components.some((component) => component.preferredRows !== void 0);
|
|
241
256
|
const invalidatingComponents = components.some((component) => component.invalidate !== void 0);
|
|
242
257
|
return {
|
|
243
258
|
render: (viewport) => components.flatMap((component) => component.render(viewport)),
|
|
259
|
+
...sizingComponents ? {
|
|
260
|
+
preferredRows: (width) => components.reduce(
|
|
261
|
+
(total, component) => total + (component.preferredRows?.(width) ?? 0),
|
|
262
|
+
0
|
|
263
|
+
)
|
|
264
|
+
} : {},
|
|
244
265
|
...components.some((component) => component.focusable === true) ? { focusable: true } : {},
|
|
245
266
|
...inputComponents ? {
|
|
246
267
|
handleInput: (input) => [...components].reverse().some((component) => component.handleInput?.(input) === true)
|
|
@@ -268,14 +289,14 @@ var emptyCampUiComponent = {
|
|
|
268
289
|
// packages/host-ui/src/composition/campUiSlots.ts
|
|
269
290
|
var CampUiSlot = {
|
|
270
291
|
campHeader: "camp-header",
|
|
271
|
-
|
|
292
|
+
activity: "activity",
|
|
293
|
+
equipment: "equipment",
|
|
272
294
|
resources: "resources",
|
|
273
295
|
roster: "roster",
|
|
274
296
|
sessionHeader: "session-header",
|
|
275
297
|
transcript: "transcript",
|
|
276
298
|
composer: "composer",
|
|
277
|
-
|
|
278
|
-
sessionFooter: "session-footer",
|
|
299
|
+
footer: "footer",
|
|
279
300
|
overlay: "overlay"
|
|
280
301
|
};
|
|
281
302
|
var CampUiContributionStrategy = {
|
|
@@ -440,6 +461,7 @@ var makeCampUiIntentHandler = (options) => type().pipe(
|
|
|
440
461
|
}),
|
|
441
462
|
SelectWorker: ({ workerId }) => options.controller.selectWorker(workerId),
|
|
442
463
|
SetDraft: ({ workerId, draft }) => options.controller.setDraft(workerId, draft),
|
|
464
|
+
SetInventoryVisible: ({ visible }) => options.controller.setInventoryVisible(visible),
|
|
443
465
|
SetScrollOffset: ({ workerId, offset }) => options.controller.setScrollOffset(workerId, offset),
|
|
444
466
|
SetTranscriptVisible: ({ visible }) => options.controller.setDetailVisible(visible),
|
|
445
467
|
Steer: ({ workerId, message }) => message.trim() === "" ? _void : options.backend.steer({ workerId, message }).pipe(
|
|
@@ -502,13 +524,16 @@ var findCampUiSpatialFocusTarget = (frame, currentSlotId, focusableSlotIds, dire
|
|
|
502
524
|
// packages/host-ui/src/layout/campUiLayoutPolicy.ts
|
|
503
525
|
var defaultCampUiLayoutPolicy = {
|
|
504
526
|
leftMinimumWidth: 28,
|
|
505
|
-
|
|
506
|
-
|
|
527
|
+
rightMinimumWidth: 28,
|
|
528
|
+
leftTrackWidthThreshold: 82,
|
|
529
|
+
rightTrackWidthThreshold: 112,
|
|
530
|
+
trackGapWidth: 1,
|
|
507
531
|
wideMinimumHeight: 18,
|
|
508
|
-
|
|
532
|
+
campHeaderHeight: 1,
|
|
509
533
|
footerHeight: 3,
|
|
510
534
|
sessionHeaderHeight: 1,
|
|
511
|
-
|
|
535
|
+
composerMinimumHeight: 1,
|
|
536
|
+
composerMaximumHeight: 4
|
|
512
537
|
};
|
|
513
538
|
|
|
514
539
|
// packages/host-ui/src/layout/campUiSizing.ts
|
|
@@ -516,17 +541,86 @@ var CampUiSectionSizeKind = {
|
|
|
516
541
|
fixed: "fixed",
|
|
517
542
|
grow: "grow"
|
|
518
543
|
};
|
|
519
|
-
var
|
|
544
|
+
var CampUiTrackSizeKind = {
|
|
545
|
+
fixed: "fixed",
|
|
546
|
+
min: "min",
|
|
547
|
+
fill: "fill"
|
|
548
|
+
};
|
|
549
|
+
var units = (value) => Number.isFinite(value) ? Math.max(0, Math.floor(value)) : 0;
|
|
550
|
+
var allocateCampUiTrackColumns = (availableColumns, sizes) => {
|
|
551
|
+
const width = units(availableColumns);
|
|
552
|
+
const allocated = sizes.map(() => 0);
|
|
553
|
+
const visible = sizes.map(
|
|
554
|
+
(size) => size.collapseBelow === void 0 || width >= units(size.collapseBelow)
|
|
555
|
+
);
|
|
556
|
+
const minimumIndexes = [];
|
|
557
|
+
const fillIndexes = [];
|
|
558
|
+
let remaining = width;
|
|
559
|
+
for (const [index, size] of sizes.entries()) {
|
|
560
|
+
if (visible[index] !== true) continue;
|
|
561
|
+
if (size.kind === CampUiTrackSizeKind.min) {
|
|
562
|
+
minimumIndexes.push(index);
|
|
563
|
+
continue;
|
|
564
|
+
}
|
|
565
|
+
if (size.kind === CampUiTrackSizeKind.fill) {
|
|
566
|
+
fillIndexes.push(index);
|
|
567
|
+
continue;
|
|
568
|
+
}
|
|
569
|
+
const trackWidth = Math.min(remaining, units(size.columns));
|
|
570
|
+
allocated[index] = trackWidth;
|
|
571
|
+
remaining -= trackWidth;
|
|
572
|
+
}
|
|
573
|
+
const maximumMinimum = Math.max(
|
|
574
|
+
0,
|
|
575
|
+
...minimumIndexes.map((index) => {
|
|
576
|
+
const size = sizes[index];
|
|
577
|
+
return size?.kind === CampUiTrackSizeKind.min ? units(size.minimumColumns) : 0;
|
|
578
|
+
})
|
|
579
|
+
);
|
|
580
|
+
for (let column = 0; column < maximumMinimum && remaining > 0; column += 1) {
|
|
581
|
+
for (const index of minimumIndexes) {
|
|
582
|
+
const size = sizes[index];
|
|
583
|
+
if (size?.kind !== CampUiTrackSizeKind.min || column >= units(size.minimumColumns)) continue;
|
|
584
|
+
allocated[index] = (allocated[index] ?? 0) + 1;
|
|
585
|
+
remaining -= 1;
|
|
586
|
+
if (remaining === 0) break;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
const weighted = fillIndexes.flatMap((index) => {
|
|
590
|
+
const size = sizes[index];
|
|
591
|
+
const weight = size?.kind === CampUiTrackSizeKind.fill ? Math.max(0, size.weight) : 0;
|
|
592
|
+
return weight > 0 ? [{ index, weight }] : [];
|
|
593
|
+
});
|
|
594
|
+
const totalWeight = weighted.reduce((total, item) => total + item.weight, 0);
|
|
595
|
+
if (remaining > 0 && totalWeight > 0) {
|
|
596
|
+
const distributable = remaining;
|
|
597
|
+
const shares = weighted.map((item) => {
|
|
598
|
+
const exact = distributable * item.weight / totalWeight;
|
|
599
|
+
return { ...item, columns: Math.floor(exact), fraction: exact - Math.floor(exact) };
|
|
600
|
+
});
|
|
601
|
+
for (const share of shares) allocated[share.index] = share.columns;
|
|
602
|
+
let roundingRemainder = distributable - shares.reduce((total, item) => total + item.columns, 0);
|
|
603
|
+
const remainderOrder = [...shares].sort(
|
|
604
|
+
(left, right) => right.fraction - left.fraction || left.index - right.index
|
|
605
|
+
);
|
|
606
|
+
for (const share of remainderOrder) {
|
|
607
|
+
if (roundingRemainder === 0) break;
|
|
608
|
+
allocated[share.index] = (allocated[share.index] ?? 0) + 1;
|
|
609
|
+
roundingRemainder -= 1;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
return allocated;
|
|
613
|
+
};
|
|
520
614
|
var allocateCampUiSectionRows = (availableRows, sizes) => {
|
|
521
615
|
const allocated = sizes.map(() => 0);
|
|
522
|
-
let remaining =
|
|
616
|
+
let remaining = units(availableRows);
|
|
523
617
|
const growIndexes = [];
|
|
524
618
|
for (const [index, size] of sizes.entries()) {
|
|
525
619
|
if (size.kind === CampUiSectionSizeKind.grow) {
|
|
526
620
|
growIndexes.push(index);
|
|
527
621
|
continue;
|
|
528
622
|
}
|
|
529
|
-
const height = Math.min(remaining,
|
|
623
|
+
const height = Math.min(remaining, units(size.rows));
|
|
530
624
|
allocated[index] = height;
|
|
531
625
|
remaining -= height;
|
|
532
626
|
}
|
|
@@ -534,13 +628,13 @@ var allocateCampUiSectionRows = (availableRows, sizes) => {
|
|
|
534
628
|
0,
|
|
535
629
|
...growIndexes.map((index) => {
|
|
536
630
|
const size = sizes[index];
|
|
537
|
-
return size?.kind === CampUiSectionSizeKind.grow ?
|
|
631
|
+
return size?.kind === CampUiSectionSizeKind.grow ? units(size.minimumRows ?? 0) : 0;
|
|
538
632
|
})
|
|
539
633
|
);
|
|
540
634
|
for (let minimumRow = 0; minimumRow < maximumMinimum && remaining > 0; minimumRow += 1) {
|
|
541
635
|
for (const index of growIndexes) {
|
|
542
636
|
const size = sizes[index];
|
|
543
|
-
if (size?.kind !== CampUiSectionSizeKind.grow || minimumRow >=
|
|
637
|
+
if (size?.kind !== CampUiSectionSizeKind.grow || minimumRow >= units(size.minimumRows ?? 0)) {
|
|
544
638
|
continue;
|
|
545
639
|
}
|
|
546
640
|
allocated[index] = (allocated[index] ?? 0) + 1;
|
|
@@ -566,10 +660,14 @@ var allocateCampUiSectionRows = (availableRows, sizes) => {
|
|
|
566
660
|
return allocated;
|
|
567
661
|
};
|
|
568
662
|
var defaultCampUiLeftSectionSizes = {
|
|
569
|
-
camp: { kind: CampUiSectionSizeKind.fixed, rows:
|
|
663
|
+
camp: { kind: CampUiSectionSizeKind.fixed, rows: 3 },
|
|
570
664
|
resources: { kind: CampUiSectionSizeKind.grow, weight: 1, minimumRows: 1 },
|
|
571
665
|
workers: { kind: CampUiSectionSizeKind.grow, weight: 1, minimumRows: 1 }
|
|
572
666
|
};
|
|
667
|
+
var defaultCampUiRightSectionSizes = {
|
|
668
|
+
activity: { kind: CampUiSectionSizeKind.grow, weight: 1, minimumRows: 2 },
|
|
669
|
+
equipment: { kind: CampUiSectionSizeKind.fixed, rows: 7 }
|
|
670
|
+
};
|
|
573
671
|
|
|
574
672
|
// packages/host-ui/src/layout/campUiLayout.ts
|
|
575
673
|
var CampUiLayoutMode = {
|
|
@@ -578,31 +676,47 @@ var CampUiLayoutMode = {
|
|
|
578
676
|
};
|
|
579
677
|
var region = (slotId, x, y, width, height) => width <= 0 || height <= 0 ? void 0 : { slotId, x, y, width, height };
|
|
580
678
|
var compact = (items) => items.filter((item) => item !== void 0);
|
|
581
|
-
var
|
|
679
|
+
var units2 = (value) => Number.isFinite(value) ? Math.max(0, Math.floor(value)) : 0;
|
|
680
|
+
var fixedRows = (available, requested) => Math.min(units2(available), units2(requested));
|
|
582
681
|
var leftSectionHeights = (bodyHeight, slots) => {
|
|
583
682
|
const size = (slotId, fallback) => slots?.get(slotId)?.sectionSize ?? fallback;
|
|
584
683
|
return allocateCampUiSectionRows(bodyHeight, [
|
|
585
684
|
size(CampUiSlot.campHeader, defaultCampUiLeftSectionSizes.camp),
|
|
586
|
-
size(CampUiSlot.resources, defaultCampUiLeftSectionSizes.resources),
|
|
587
685
|
size(CampUiSlot.roster, defaultCampUiLeftSectionSizes.workers)
|
|
588
686
|
]);
|
|
589
687
|
};
|
|
688
|
+
var rightSectionHeights = (bodyHeight, width, slots) => {
|
|
689
|
+
const minimumActivityRows = Math.min(units2(bodyHeight), 2);
|
|
690
|
+
const fallback = defaultCampUiRightSectionSizes.equipment.rows;
|
|
691
|
+
const preferred = units2(
|
|
692
|
+
slots?.get(CampUiSlot.equipment)?.preferredRows?.(units2(width)) ?? fallback
|
|
693
|
+
);
|
|
694
|
+
const equipmentHeight = fixedRows(Math.max(0, bodyHeight - minimumActivityRows), preferred);
|
|
695
|
+
return [Math.max(0, bodyHeight - equipmentHeight), equipmentHeight];
|
|
696
|
+
};
|
|
697
|
+
var composerHeight = (availableHeight, width, policy, slots) => {
|
|
698
|
+
const maximum = units2(policy.composerMaximumHeight);
|
|
699
|
+
const minimum = Math.min(maximum, units2(policy.composerMinimumHeight));
|
|
700
|
+
const preferred = units2(
|
|
701
|
+
slots?.get(CampUiSlot.composer)?.preferredRows?.(units2(width)) ?? minimum
|
|
702
|
+
);
|
|
703
|
+
return fixedRows(availableHeight, Math.max(minimum, Math.min(maximum, preferred)));
|
|
704
|
+
};
|
|
590
705
|
var makeNarrowFrame = (viewport, state, policy, slots) => {
|
|
591
706
|
const footerHeight = fixedRows(viewport.height, policy.footerHeight);
|
|
592
707
|
const bodyHeight = Math.max(0, viewport.height - footerHeight);
|
|
593
708
|
const footerY = bodyHeight;
|
|
594
709
|
const workerScreen = state.screen === CampUiScreen.worker && state.selectedWorkerId !== void 0;
|
|
595
|
-
const [campHeight = 0,
|
|
710
|
+
const [campHeight = 0, rosterHeight = 0] = workerScreen ? [] : leftSectionHeights(bodyHeight, slots);
|
|
596
711
|
const sessionHeaderHeight = workerScreen ? fixedRows(bodyHeight, policy.sessionHeaderHeight) : 0;
|
|
597
|
-
const
|
|
598
|
-
const transcriptHeight = workerScreen ? bodyHeight - sessionHeaderHeight -
|
|
712
|
+
const inputHeight = workerScreen ? composerHeight(bodyHeight - sessionHeaderHeight, viewport.width, policy, slots) : 0;
|
|
713
|
+
const transcriptHeight = workerScreen ? bodyHeight - sessionHeaderHeight - inputHeight : 0;
|
|
599
714
|
return {
|
|
600
715
|
mode: CampUiLayoutMode.narrow,
|
|
601
716
|
dividers: [],
|
|
602
717
|
regions: compact([
|
|
603
718
|
region(CampUiSlot.campHeader, 0, 0, viewport.width, campHeight),
|
|
604
|
-
region(CampUiSlot.
|
|
605
|
-
region(CampUiSlot.roster, 0, campHeight + resourcesHeight, viewport.width, rosterHeight),
|
|
719
|
+
region(CampUiSlot.roster, 0, campHeight, viewport.width, rosterHeight),
|
|
606
720
|
region(CampUiSlot.sessionHeader, 0, 0, viewport.width, sessionHeaderHeight),
|
|
607
721
|
region(CampUiSlot.transcript, 0, sessionHeaderHeight, viewport.width, transcriptHeight),
|
|
608
722
|
region(
|
|
@@ -610,57 +724,79 @@ var makeNarrowFrame = (viewport, state, policy, slots) => {
|
|
|
610
724
|
0,
|
|
611
725
|
sessionHeaderHeight + transcriptHeight,
|
|
612
726
|
viewport.width,
|
|
613
|
-
|
|
727
|
+
inputHeight
|
|
614
728
|
),
|
|
615
|
-
region(
|
|
616
|
-
workerScreen ? CampUiSlot.sessionFooter : CampUiSlot.campFooter,
|
|
617
|
-
0,
|
|
618
|
-
footerY,
|
|
619
|
-
viewport.width,
|
|
620
|
-
footerHeight
|
|
621
|
-
)
|
|
729
|
+
region(CampUiSlot.footer, 0, footerY, viewport.width, footerHeight)
|
|
622
730
|
])
|
|
623
731
|
};
|
|
624
732
|
};
|
|
625
733
|
var makeWideFrame = (viewport, policy, slots) => {
|
|
626
|
-
const
|
|
627
|
-
const
|
|
628
|
-
const
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
734
|
+
const campHeaderHeight = fixedRows(viewport.height, policy.campHeaderHeight);
|
|
735
|
+
const footerHeight = fixedRows(viewport.height - campHeaderHeight, policy.footerHeight);
|
|
736
|
+
const bodyHeight = Math.max(0, viewport.height - campHeaderHeight - footerHeight);
|
|
737
|
+
const footerY = campHeaderHeight + bodyHeight;
|
|
738
|
+
const [leftWidth = 0, leftGap = 0, centerWidth = 0, rightGap = 0, rightWidth = 0] = allocateCampUiTrackColumns(viewport.width, [
|
|
739
|
+
{
|
|
740
|
+
kind: CampUiTrackSizeKind.min,
|
|
741
|
+
minimumColumns: policy.leftMinimumWidth,
|
|
742
|
+
collapseBelow: policy.leftTrackWidthThreshold
|
|
743
|
+
},
|
|
744
|
+
{
|
|
745
|
+
kind: CampUiTrackSizeKind.fixed,
|
|
746
|
+
columns: policy.trackGapWidth,
|
|
747
|
+
collapseBelow: policy.leftTrackWidthThreshold
|
|
748
|
+
},
|
|
749
|
+
{ kind: CampUiTrackSizeKind.fill, weight: 1 },
|
|
750
|
+
{
|
|
751
|
+
kind: CampUiTrackSizeKind.fixed,
|
|
752
|
+
columns: policy.trackGapWidth,
|
|
753
|
+
collapseBelow: policy.rightTrackWidthThreshold
|
|
754
|
+
},
|
|
755
|
+
{
|
|
756
|
+
kind: CampUiTrackSizeKind.min,
|
|
757
|
+
minimumColumns: policy.rightMinimumWidth,
|
|
758
|
+
collapseBelow: policy.rightTrackWidthThreshold
|
|
759
|
+
}
|
|
760
|
+
]);
|
|
761
|
+
const centerX2 = leftWidth + leftGap;
|
|
762
|
+
const rightX = centerX2 + centerWidth + rightGap;
|
|
763
|
+
const [activityHeight = 0, equipmentHeight = 0] = rightSectionHeights(
|
|
639
764
|
bodyHeight,
|
|
765
|
+
rightWidth,
|
|
640
766
|
slots
|
|
641
767
|
);
|
|
642
768
|
const sessionHeaderHeight = fixedRows(bodyHeight, policy.sessionHeaderHeight);
|
|
643
|
-
const
|
|
644
|
-
const transcriptHeight = bodyHeight - sessionHeaderHeight -
|
|
645
|
-
const
|
|
769
|
+
const inputHeight = composerHeight(bodyHeight - sessionHeaderHeight, centerWidth, policy, slots);
|
|
770
|
+
const transcriptHeight = bodyHeight - sessionHeaderHeight - inputHeight;
|
|
771
|
+
const bodyY = campHeaderHeight;
|
|
646
772
|
return {
|
|
647
773
|
mode: CampUiLayoutMode.wide,
|
|
648
|
-
dividers:
|
|
774
|
+
dividers: [],
|
|
649
775
|
regions: compact([
|
|
650
|
-
region(CampUiSlot.campHeader, 0, 0,
|
|
651
|
-
region(CampUiSlot.
|
|
652
|
-
region(CampUiSlot.
|
|
653
|
-
region(
|
|
654
|
-
|
|
776
|
+
region(CampUiSlot.campHeader, 0, 0, viewport.width, campHeaderHeight),
|
|
777
|
+
region(CampUiSlot.roster, 0, bodyY, leftWidth, bodyHeight),
|
|
778
|
+
region(CampUiSlot.sessionHeader, centerX2, bodyY, centerWidth, sessionHeaderHeight),
|
|
779
|
+
region(
|
|
780
|
+
CampUiSlot.transcript,
|
|
781
|
+
centerX2,
|
|
782
|
+
bodyY + sessionHeaderHeight,
|
|
783
|
+
centerWidth,
|
|
784
|
+
transcriptHeight
|
|
785
|
+
),
|
|
655
786
|
region(
|
|
656
787
|
CampUiSlot.composer,
|
|
657
|
-
|
|
658
|
-
sessionHeaderHeight + transcriptHeight,
|
|
659
|
-
|
|
660
|
-
|
|
788
|
+
centerX2,
|
|
789
|
+
bodyY + sessionHeaderHeight + transcriptHeight,
|
|
790
|
+
centerWidth,
|
|
791
|
+
inputHeight
|
|
661
792
|
),
|
|
662
|
-
region(CampUiSlot.
|
|
663
|
-
region(CampUiSlot.
|
|
793
|
+
region(CampUiSlot.activity, rightX, bodyY, rightWidth, activityHeight),
|
|
794
|
+
region(CampUiSlot.equipment, rightX, bodyY + activityHeight, rightWidth, equipmentHeight),
|
|
795
|
+
/*
|
|
796
|
+
* One line across the whole width: two footers pinned to the corners split
|
|
797
|
+
* along the track boundary and repeated what the worker cards already say.
|
|
798
|
+
*/
|
|
799
|
+
region(CampUiSlot.footer, 0, footerY, viewport.width, footerHeight)
|
|
664
800
|
])
|
|
665
801
|
};
|
|
666
802
|
};
|
|
@@ -668,11 +804,10 @@ var makeDefaultCampUiLayout = (policy = defaultCampUiLayoutPolicy) => ({
|
|
|
668
804
|
id: "default",
|
|
669
805
|
resolve: (viewport, state, slots) => {
|
|
670
806
|
const normalized = {
|
|
671
|
-
width:
|
|
672
|
-
height:
|
|
807
|
+
width: units2(viewport.width),
|
|
808
|
+
height: units2(viewport.height)
|
|
673
809
|
};
|
|
674
|
-
|
|
675
|
-
return normalized.width >= wideMinimumWidth && normalized.height >= policy.wideMinimumHeight ? makeWideFrame(normalized, policy, slots) : makeNarrowFrame(normalized, state, policy, slots);
|
|
810
|
+
return normalized.height >= policy.wideMinimumHeight ? makeWideFrame(normalized, policy, slots) : makeNarrowFrame(normalized, state, policy, slots);
|
|
676
811
|
}
|
|
677
812
|
});
|
|
678
813
|
|
|
@@ -850,7 +985,7 @@ var fallbackWorkerPresentation = {
|
|
|
850
985
|
glyph: CampUiGlyph.neutral
|
|
851
986
|
};
|
|
852
987
|
var attentionStates = /* @__PURE__ */ new Set(["waiting_for_orchestrator", "recovering", "retrying"]);
|
|
853
|
-
var
|
|
988
|
+
var resolveCampUiWorkerState = (state, options) => {
|
|
854
989
|
const base = workerStatePresentation.get(state) ?? fallbackWorkerPresentation;
|
|
855
990
|
const terminal = state === "completed" || state === "closed";
|
|
856
991
|
const streamingLifts = !terminal && options.streaming && !attentionStates.has(state);
|
|
@@ -859,7 +994,11 @@ var renderCampUiWorkerState = (state, options) => {
|
|
|
859
994
|
tone: CampUiTone.attention,
|
|
860
995
|
glyph: CampUiGlyph.attention
|
|
861
996
|
} : streamingLifts ? workerStatePresentation.get("running") : base;
|
|
862
|
-
|
|
997
|
+
return presentation ?? fallbackWorkerPresentation;
|
|
998
|
+
};
|
|
999
|
+
var campUiWorkerStateLabel = (state, options) => resolveCampUiWorkerState(state, options).label;
|
|
1000
|
+
var renderCampUiWorkerState = (state, options) => {
|
|
1001
|
+
const resolved = resolveCampUiWorkerState(state, options);
|
|
863
1002
|
return renderCampUiStatus(resolved.label, resolved.tone, resolved.glyph);
|
|
864
1003
|
};
|
|
865
1004
|
var renderSelectedCampUiRow = (line, width) => {
|
|
@@ -927,44 +1066,44 @@ var toneByState = {
|
|
|
927
1066
|
[CampAskState.expired]: CampUiTone.error,
|
|
928
1067
|
[CampAskState.interrupted]: CampUiTone.error
|
|
929
1068
|
};
|
|
1069
|
+
var campUiAskDetailBlock = (ask, model, width) => {
|
|
1070
|
+
const blockId = campUiAskBlockId(ask.askId);
|
|
1071
|
+
const mode = ask.blocking ? "blocking" : "non-blocking";
|
|
1072
|
+
const stateLabel = {
|
|
1073
|
+
[CampAskState.pending]: `pending \xB7 ${formatCampUiDuration(
|
|
1074
|
+
model.state.presentationNow - ask.openedAt
|
|
1075
|
+
)}`,
|
|
1076
|
+
[CampAskState.answered]: "answered",
|
|
1077
|
+
[CampAskState.expired]: "expired",
|
|
1078
|
+
[CampAskState.interrupted]: "interrupted"
|
|
1079
|
+
}[ask.state];
|
|
1080
|
+
const summary = {
|
|
1081
|
+
[CampAskState.pending]: `Awaiting orchestrator reply \xB7 ${ask.askId}`,
|
|
1082
|
+
[CampAskState.answered]: `${ask.answerSummary ?? "Answered"} \xB7 ${ask.askId}`,
|
|
1083
|
+
[CampAskState.expired]: `Expired \xB7 ${ask.askId}`,
|
|
1084
|
+
[CampAskState.interrupted]: `Interrupted by host restart \xB7 ${ask.askId}`
|
|
1085
|
+
}[ask.state];
|
|
1086
|
+
return {
|
|
1087
|
+
id: blockId,
|
|
1088
|
+
lines: renderCampUiDirectedBlock(
|
|
1089
|
+
{
|
|
1090
|
+
label: `Ask \xB7 to ${ask.controllerId} \xB7 ${mode} \xB7 ${stateLabel}`,
|
|
1091
|
+
markdown: ask.question,
|
|
1092
|
+
summary,
|
|
1093
|
+
tone: toneByState[ask.state],
|
|
1094
|
+
expanded: model.state.expandedDetailBlockIds.has(blockId),
|
|
1095
|
+
...ask.state === CampAskState.answered ? { collapsedBodyLines: 0, showToggleHint: false } : {}
|
|
1096
|
+
},
|
|
1097
|
+
width
|
|
1098
|
+
),
|
|
1099
|
+
toggleable: ask.state !== CampAskState.answered
|
|
1100
|
+
};
|
|
1101
|
+
};
|
|
1102
|
+
var isCampUiPendingAsk = (ask) => ask.state === CampAskState.pending;
|
|
930
1103
|
var campUiPendingAskBlockRenderer = {
|
|
931
1104
|
id: "pending-asks",
|
|
932
1105
|
order: 100,
|
|
933
|
-
render: ({ model, worker, width }) =>
|
|
934
|
-
return worker.asks.map((ask) => {
|
|
935
|
-
const blockId = campUiAskBlockId(ask.askId);
|
|
936
|
-
const mode = ask.blocking ? "blocking" : "non-blocking";
|
|
937
|
-
const stateLabel = {
|
|
938
|
-
[CampAskState.pending]: `pending \xB7 ${formatCampUiDuration(
|
|
939
|
-
model.state.presentationNow - ask.openedAt
|
|
940
|
-
)}`,
|
|
941
|
-
[CampAskState.answered]: "answered",
|
|
942
|
-
[CampAskState.expired]: "expired",
|
|
943
|
-
[CampAskState.interrupted]: "interrupted"
|
|
944
|
-
}[ask.state];
|
|
945
|
-
const summary = {
|
|
946
|
-
[CampAskState.pending]: `Awaiting orchestrator reply \xB7 ${ask.askId}`,
|
|
947
|
-
[CampAskState.answered]: `${ask.answerSummary ?? "Answered"} \xB7 ${ask.askId}`,
|
|
948
|
-
[CampAskState.expired]: `Expired \xB7 ${ask.askId}`,
|
|
949
|
-
[CampAskState.interrupted]: `Interrupted by host restart \xB7 ${ask.askId}`
|
|
950
|
-
}[ask.state];
|
|
951
|
-
return {
|
|
952
|
-
id: blockId,
|
|
953
|
-
lines: renderCampUiDirectedBlock(
|
|
954
|
-
{
|
|
955
|
-
label: `Ask \xB7 to ${ask.controllerId} \xB7 ${mode} \xB7 ${stateLabel}`,
|
|
956
|
-
markdown: ask.question,
|
|
957
|
-
summary,
|
|
958
|
-
tone: toneByState[ask.state],
|
|
959
|
-
expanded: model.state.expandedDetailBlockIds.has(blockId),
|
|
960
|
-
...ask.state === CampAskState.answered ? { collapsedBodyLines: 0, showToggleHint: false } : {}
|
|
961
|
-
},
|
|
962
|
-
width
|
|
963
|
-
),
|
|
964
|
-
toggleable: ask.state !== CampAskState.answered
|
|
965
|
-
};
|
|
966
|
-
});
|
|
967
|
-
}
|
|
1106
|
+
render: ({ model, worker, width }) => worker.asks.filter(isCampUiPendingAsk).map((ask) => campUiAskDetailBlock(ask, model, width))
|
|
968
1107
|
};
|
|
969
1108
|
|
|
970
1109
|
// packages/host-ui/src/pi/blocks/campUiAssistantMessage.ts
|
|
@@ -1053,7 +1192,7 @@ var campUiResultSignature = (result) => result === void 0 ? "pending" : campUiMe
|
|
|
1053
1192
|
|
|
1054
1193
|
// packages/host-ui/src/pi/blocks/campUiComposer.ts
|
|
1055
1194
|
import { getMarkdownTheme as getMarkdownTheme3, getSelectListTheme as getSelectListTheme4 } from "@earendil-works/pi-coding-agent";
|
|
1056
|
-
import { Editor, Key, matchesKey } from "@earendil-works/pi-tui";
|
|
1195
|
+
import { CURSOR_MARKER, Editor, Key, matchesKey } from "@earendil-works/pi-tui";
|
|
1057
1196
|
var makeCampUiComposerComponent = (context, tui) => {
|
|
1058
1197
|
const markdownTheme = getMarkdownTheme3();
|
|
1059
1198
|
const selectTheme = getSelectListTheme4();
|
|
@@ -1100,20 +1239,40 @@ var makeCampUiComposerComponent = (context, tui) => {
|
|
|
1100
1239
|
editors.set(workerId, created);
|
|
1101
1240
|
return created;
|
|
1102
1241
|
};
|
|
1242
|
+
const renderSelectedEditor = (width) => {
|
|
1243
|
+
const model = context.readModel();
|
|
1244
|
+
const workerId = model.state.selectedWorkerId;
|
|
1245
|
+
const entry = selectedEditor();
|
|
1246
|
+
if (workerId === void 0 || entry === void 0) return void 0;
|
|
1247
|
+
const { editor } = entry;
|
|
1248
|
+
const focused = model.state.focusedSlotId === CampUiSlot.composer;
|
|
1249
|
+
editor.focused = focused;
|
|
1250
|
+
editor.borderColor = focused ? selectTheme.selectedPrefix : markdownTheme.codeBlockBorder;
|
|
1251
|
+
entry.setDraft(model.state.drafts.get(workerId) ?? "");
|
|
1252
|
+
editor.focused = true;
|
|
1253
|
+
let lines;
|
|
1254
|
+
try {
|
|
1255
|
+
lines = editor.render(width).slice(1, -1);
|
|
1256
|
+
} finally {
|
|
1257
|
+
editor.focused = focused;
|
|
1258
|
+
}
|
|
1259
|
+
const cursorRow = lines.findIndex((line) => line.includes(CURSOR_MARKER));
|
|
1260
|
+
return {
|
|
1261
|
+
cursorRow,
|
|
1262
|
+
lines: lines.map((line) => focused ? line : line.replaceAll(CURSOR_MARKER, ""))
|
|
1263
|
+
};
|
|
1264
|
+
};
|
|
1103
1265
|
return {
|
|
1104
1266
|
focusable: true,
|
|
1267
|
+
preferredRows: (width) => renderSelectedEditor(width)?.lines.length ?? 1,
|
|
1105
1268
|
render: (viewport) => {
|
|
1106
|
-
const
|
|
1107
|
-
|
|
1108
|
-
const
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
editor.focused = model.state.focusedSlotId === CampUiSlot.composer;
|
|
1114
|
-
editor.borderColor = editor.focused ? selectTheme.selectedPrefix : markdownTheme.codeBlockBorder;
|
|
1115
|
-
entry.setDraft(model.state.drafts.get(workerId) ?? "");
|
|
1116
|
-
return editor.render(viewport.width).slice(0, viewport.height);
|
|
1269
|
+
const rendered = renderSelectedEditor(viewport.width);
|
|
1270
|
+
if (rendered === void 0) return [selectTheme.description("worker not selected")];
|
|
1271
|
+
const start = rendered.cursorRow < 0 ? 0 : Math.min(
|
|
1272
|
+
Math.max(0, rendered.lines.length - viewport.height),
|
|
1273
|
+
Math.max(0, rendered.cursorRow - viewport.height + 1)
|
|
1274
|
+
);
|
|
1275
|
+
return rendered.lines.slice(start, start + viewport.height);
|
|
1117
1276
|
},
|
|
1118
1277
|
handleInput: (input) => {
|
|
1119
1278
|
const entry = selectedEditor();
|
|
@@ -1147,50 +1306,12 @@ var makeCampUiComposerComponent = (context, tui) => {
|
|
|
1147
1306
|
import { getSelectListTheme as getSelectListTheme8 } from "@earendil-works/pi-coding-agent";
|
|
1148
1307
|
import { Key as Key2, matchesKey as matchesKey2 } from "@earendil-works/pi-tui";
|
|
1149
1308
|
|
|
1150
|
-
// packages/host-ui/src/pi/blocks/campUiEquipmentBlock.ts
|
|
1151
|
-
import { getMarkdownTheme as getMarkdownTheme4, UserMessageComponent } from "@earendil-works/pi-coding-agent";
|
|
1152
|
-
var escapeMarkdown = (value) => value.replaceAll(/([\\`*_[\]{}()#+.!|>])/gu, "\\$1");
|
|
1153
|
-
var renderNames = (names) => names.length === 0 ? "none" : names.map(escapeMarkdown).join(", ");
|
|
1154
|
-
var renderMcpServers = (equipment) => renderNames(
|
|
1155
|
-
equipment.mcp.serverNames.map((serverName) => {
|
|
1156
|
-
const toolNames = equipment.mcp.toolNamesByServer?.[serverName];
|
|
1157
|
-
return toolNames === void 0 ? serverName : `${serverName} (${toolNames.join(", ")})`;
|
|
1158
|
-
})
|
|
1159
|
-
);
|
|
1160
|
-
var equipmentMarkdown = (equipment) => {
|
|
1161
|
-
const role = equipment.role ?? equipment.preset ?? "unknown";
|
|
1162
|
-
const tools = [.../* @__PURE__ */ new Set([...equipment.builtinTools, ...equipment.customToolNames])].sort();
|
|
1163
|
-
const lines = [
|
|
1164
|
-
`**Equipment \xB7 ${escapeMarkdown(role)}**`,
|
|
1165
|
-
"",
|
|
1166
|
-
`- **Tools:** ${renderNames(tools)}`,
|
|
1167
|
-
`- **MCP:** ${renderMcpServers(equipment)}`,
|
|
1168
|
-
`- **Skills:** ${renderNames(equipment.skillNames)}`,
|
|
1169
|
-
`- **Access:** ${equipment.readOnly ? "read-only" : "read/write"}`
|
|
1170
|
-
];
|
|
1171
|
-
return lines.join("\n");
|
|
1172
|
-
};
|
|
1173
|
-
var campUiEquipmentBlockRenderer = {
|
|
1174
|
-
id: "role-equipment",
|
|
1175
|
-
order: -100,
|
|
1176
|
-
render: ({ worker, width }) => [
|
|
1177
|
-
{
|
|
1178
|
-
id: "role-equipment",
|
|
1179
|
-
lines: new UserMessageComponent(
|
|
1180
|
-
equipmentMarkdown(worker.snapshot.worker.equipment),
|
|
1181
|
-
getMarkdownTheme4(),
|
|
1182
|
-
0
|
|
1183
|
-
).render(width)
|
|
1184
|
-
}
|
|
1185
|
-
]
|
|
1186
|
-
};
|
|
1187
|
-
|
|
1188
1309
|
// packages/host-ui/src/pi/blocks/campUiTranscriptBlocks.ts
|
|
1189
|
-
import { getMarkdownTheme as
|
|
1310
|
+
import { getMarkdownTheme as getMarkdownTheme6, UserMessageComponent } from "@earendil-works/pi-coding-agent";
|
|
1190
1311
|
import { Markdown as Markdown4 } from "@earendil-works/pi-tui";
|
|
1191
1312
|
|
|
1192
1313
|
// packages/host-ui/src/pi/shared/campUiPanel.ts
|
|
1193
|
-
import { getMarkdownTheme as
|
|
1314
|
+
import { getMarkdownTheme as getMarkdownTheme4, getSelectListTheme as getSelectListTheme5 } from "@earendil-works/pi-coding-agent";
|
|
1194
1315
|
import { truncateToWidth as truncateToWidth3, visibleWidth as visibleWidth2 } from "@earendil-works/pi-tui";
|
|
1195
1316
|
var rule = (start, label, width, borderColor, labelColor) => {
|
|
1196
1317
|
const prefix = `${borderColor(`${start}\u2500 `)}${labelColor(label)}${borderColor(" ")}`;
|
|
@@ -1199,7 +1320,7 @@ var rule = (start, label, width, borderColor, labelColor) => {
|
|
|
1199
1320
|
};
|
|
1200
1321
|
var renderCampUiPanel = (label, body, width) => {
|
|
1201
1322
|
if (width <= 0) return [];
|
|
1202
|
-
const borderColor =
|
|
1323
|
+
const borderColor = getMarkdownTheme4().codeBlockBorder;
|
|
1203
1324
|
const labelColor = getSelectListTheme5().selectedText;
|
|
1204
1325
|
if (width === 1) {
|
|
1205
1326
|
return [borderColor("\u2502"), ...body.map(() => borderColor("\u2502")), borderColor("\u2570")];
|
|
@@ -1339,7 +1460,7 @@ var renderCampUiExploredGroup = (reads, width, expanded) => {
|
|
|
1339
1460
|
|
|
1340
1461
|
// packages/host-ui/src/pi/blocks/campUiToolResult.ts
|
|
1341
1462
|
import {
|
|
1342
|
-
getMarkdownTheme as
|
|
1463
|
+
getMarkdownTheme as getMarkdownTheme5,
|
|
1343
1464
|
getSelectListTheme as getSelectListTheme7,
|
|
1344
1465
|
truncateToVisualLines
|
|
1345
1466
|
} from "@earendil-works/pi-coding-agent";
|
|
@@ -1414,13 +1535,13 @@ var renderCampUiToolResult = (result, width, expanded) => {
|
|
|
1414
1535
|
]);
|
|
1415
1536
|
}
|
|
1416
1537
|
const content = toolResultContent(result, true);
|
|
1417
|
-
const lines = content === "" ? [] : new Markdown3(content, 0, 0,
|
|
1538
|
+
const lines = content === "" ? [] : new Markdown3(content, 0, 0, getMarkdownTheme5()).render(boundedWidth);
|
|
1418
1539
|
return keep([
|
|
1419
1540
|
...lines,
|
|
1420
1541
|
...result.errorMessage === void 0 ? [] : [getSelectListTheme7().noMatch(`Error: ${result.errorMessage}`)],
|
|
1421
1542
|
...result.toolResultDetails === void 0 ? [] : [
|
|
1422
1543
|
getSelectListTheme7().description("Details"),
|
|
1423
|
-
...new Markdown3(jsonText(result.toolResultDetails), 0, 0,
|
|
1544
|
+
...new Markdown3(jsonText(result.toolResultDetails), 0, 0, getMarkdownTheme5()).render(
|
|
1424
1545
|
boundedWidth
|
|
1425
1546
|
)
|
|
1426
1547
|
],
|
|
@@ -1467,7 +1588,7 @@ var renderMessage = (message, width) => {
|
|
|
1467
1588
|
] : [];
|
|
1468
1589
|
return [
|
|
1469
1590
|
...attribution,
|
|
1470
|
-
...new
|
|
1591
|
+
...new UserMessageComponent(markdown2, getMarkdownTheme6(), 0).render(width)
|
|
1471
1592
|
];
|
|
1472
1593
|
}
|
|
1473
1594
|
if (message.role === "assistant") {
|
|
@@ -1481,9 +1602,9 @@ var renderMessage = (message, width) => {
|
|
|
1481
1602
|
const suffix = message.errorMessage === void 0 ? "" : `
|
|
1482
1603
|
|
|
1483
1604
|
Error: ${message.errorMessage}`;
|
|
1484
|
-
return new Markdown4(`${prefix}${markdown}${suffix}`, 0, 0,
|
|
1605
|
+
return new Markdown4(`${prefix}${markdown}${suffix}`, 0, 0, getMarkdownTheme6()).render(width);
|
|
1485
1606
|
};
|
|
1486
|
-
var renderMarkdown = (markdown, width) => new Markdown4(markdown, 0, 0,
|
|
1607
|
+
var renderMarkdown = (markdown, width) => new Markdown4(markdown, 0, 0, getMarkdownTheme6()).render(Math.max(1, width));
|
|
1487
1608
|
var firstStringArgument = (parameters, names) => {
|
|
1488
1609
|
for (const name of names) {
|
|
1489
1610
|
const value = parameters[name];
|
|
@@ -1532,7 +1653,7 @@ var exploredRead = (toolCall, path, result) => {
|
|
|
1532
1653
|
...errorMessage === void 0 ? {} : { errorMessage }
|
|
1533
1654
|
};
|
|
1534
1655
|
};
|
|
1535
|
-
var renderTranscript = (transcript, width, expandedDetailBlockIds) => {
|
|
1656
|
+
var renderTranscript = (transcript, width, expandedDetailBlockIds, settledAsks) => {
|
|
1536
1657
|
const results = /* @__PURE__ */ new Map();
|
|
1537
1658
|
const callIds = /* @__PURE__ */ new Set();
|
|
1538
1659
|
for (const message of transcript) {
|
|
@@ -1559,7 +1680,19 @@ var renderTranscript = (transcript, width, expandedDetailBlockIds) => {
|
|
|
1559
1680
|
});
|
|
1560
1681
|
group = [];
|
|
1561
1682
|
};
|
|
1683
|
+
let nextAsk = 0;
|
|
1684
|
+
const flushAsksUntil = (timestamp) => {
|
|
1685
|
+
if (timestamp === void 0) return;
|
|
1686
|
+
while (nextAsk < settledAsks.length) {
|
|
1687
|
+
const pending = settledAsks[nextAsk];
|
|
1688
|
+
if (pending === void 0 || pending.at > timestamp) return;
|
|
1689
|
+
closeGroup();
|
|
1690
|
+
blocks.push(pending.block);
|
|
1691
|
+
nextAsk += 1;
|
|
1692
|
+
}
|
|
1693
|
+
};
|
|
1562
1694
|
transcript.forEach((message, index) => {
|
|
1695
|
+
flushAsksUntil(message.timestamp);
|
|
1563
1696
|
const messageId = message.id ?? String(index);
|
|
1564
1697
|
if (message.role === "toolResult") {
|
|
1565
1698
|
if (message.toolCallId !== void 0 && callIds.has(message.toolCallId)) return;
|
|
@@ -1606,21 +1739,26 @@ var renderTranscript = (transcript, width, expandedDetailBlockIds) => {
|
|
|
1606
1739
|
}
|
|
1607
1740
|
});
|
|
1608
1741
|
closeGroup();
|
|
1742
|
+
for (const remaining of settledAsks.slice(nextAsk)) blocks.push(remaining.block);
|
|
1609
1743
|
return blocks;
|
|
1610
1744
|
};
|
|
1611
1745
|
var campUiTranscriptBlockRenderer = {
|
|
1612
1746
|
id: "transcript",
|
|
1613
1747
|
order: 0,
|
|
1614
|
-
render: (
|
|
1615
|
-
worker
|
|
1616
|
-
width,
|
|
1617
|
-
|
|
1618
|
-
|
|
1748
|
+
render: (context) => {
|
|
1749
|
+
const { model, worker, width } = context;
|
|
1750
|
+
const settledAsks = worker.asks.filter((ask) => !isCampUiPendingAsk(ask)).map((ask) => ({ at: ask.openedAt, block: campUiAskDetailBlock(ask, model, width) })).sort((left, right) => left.at - right.at);
|
|
1751
|
+
return renderTranscript(
|
|
1752
|
+
worker.snapshot.session?.transcript ?? [],
|
|
1753
|
+
width,
|
|
1754
|
+
model.state.expandedDetailBlockIds,
|
|
1755
|
+
settledAsks
|
|
1756
|
+
);
|
|
1757
|
+
}
|
|
1619
1758
|
};
|
|
1620
1759
|
|
|
1621
1760
|
// packages/host-ui/src/pi/blocks/campUiDetail.ts
|
|
1622
1761
|
var defaultCampUiDetailBlockRenderers = [
|
|
1623
|
-
campUiEquipmentBlockRenderer,
|
|
1624
1762
|
campUiTranscriptBlockRenderer,
|
|
1625
1763
|
campUiPendingAskBlockRenderer
|
|
1626
1764
|
];
|
|
@@ -1759,12 +1897,261 @@ var makeCampUiDetailComponent = (context, registry = defaultCampUiDetailBlockRen
|
|
|
1759
1897
|
};
|
|
1760
1898
|
};
|
|
1761
1899
|
|
|
1762
|
-
// packages/host-ui/src/pi/layout/
|
|
1900
|
+
// packages/host-ui/src/pi/layout/campUiActivity.ts
|
|
1763
1901
|
import { getSelectListTheme as getSelectListTheme9 } from "@earendil-works/pi-coding-agent";
|
|
1902
|
+
import { sliceByColumn, visibleWidth as visibleWidth3 } from "@earendil-works/pi-tui";
|
|
1903
|
+
var CampUiActivityAccess = {
|
|
1904
|
+
read: "read",
|
|
1905
|
+
edit: "edit",
|
|
1906
|
+
write: "write"
|
|
1907
|
+
};
|
|
1908
|
+
var accessByTool = /* @__PURE__ */ new Map([
|
|
1909
|
+
["read", CampUiActivityAccess.read],
|
|
1910
|
+
["edit", CampUiActivityAccess.edit],
|
|
1911
|
+
["write", CampUiActivityAccess.write]
|
|
1912
|
+
]);
|
|
1913
|
+
var accessRank = {
|
|
1914
|
+
read: 0,
|
|
1915
|
+
edit: 1,
|
|
1916
|
+
write: 2
|
|
1917
|
+
};
|
|
1918
|
+
var filePathArgument = (parameters) => {
|
|
1919
|
+
for (const name of ["path", "file_path"]) {
|
|
1920
|
+
const value = parameters[name];
|
|
1921
|
+
if (typeof value === "string" && value.trim() !== "") return value.trim();
|
|
1922
|
+
}
|
|
1923
|
+
return void 0;
|
|
1924
|
+
};
|
|
1925
|
+
var splitPath2 = (path) => {
|
|
1926
|
+
const separator = path.lastIndexOf("/");
|
|
1927
|
+
if (separator < 0) return { directory: ".", name: path };
|
|
1928
|
+
if (separator === 0) return { directory: "/", name: path.slice(1) || path };
|
|
1929
|
+
return { directory: path.slice(0, separator), name: path.slice(separator + 1) || path };
|
|
1930
|
+
};
|
|
1931
|
+
var collectCampUiActivityTree = (transcript) => {
|
|
1932
|
+
const directories = /* @__PURE__ */ new Map();
|
|
1933
|
+
const nodes = /* @__PURE__ */ new Map();
|
|
1934
|
+
for (const message of transcript) {
|
|
1935
|
+
for (const content of message.content) {
|
|
1936
|
+
if (content.kind !== "tool-call") continue;
|
|
1937
|
+
const access = accessByTool.get(content.toolName);
|
|
1938
|
+
if (access === void 0) continue;
|
|
1939
|
+
const path = filePathArgument(content.arguments);
|
|
1940
|
+
if (path === void 0) continue;
|
|
1941
|
+
const existing = nodes.get(path);
|
|
1942
|
+
if (existing !== void 0) {
|
|
1943
|
+
existing.count += 1;
|
|
1944
|
+
if (accessRank[access] > accessRank[existing.access]) existing.access = access;
|
|
1945
|
+
continue;
|
|
1946
|
+
}
|
|
1947
|
+
const { directory, name } = splitPath2(path);
|
|
1948
|
+
const node = { path, directory, name, access, count: 1 };
|
|
1949
|
+
nodes.set(path, node);
|
|
1950
|
+
const group = directories.get(directory) ?? { path: directory, nodes: [] };
|
|
1951
|
+
if (!directories.has(directory)) directories.set(directory, group);
|
|
1952
|
+
group.nodes.push(node);
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
return [...directories.values()].map((directory) => ({
|
|
1956
|
+
path: directory.path,
|
|
1957
|
+
nodes: directory.nodes.map((node) => ({ ...node }))
|
|
1958
|
+
}));
|
|
1959
|
+
};
|
|
1960
|
+
var CAMP_UI_ACTIVITY_MAX_VISIBLE_PATHS = 12;
|
|
1961
|
+
var ACTIVITY_COLUMNS_PER_VISIBLE_PATH = 4;
|
|
1962
|
+
var flattenedNodes = (tree) => tree.flatMap((directory) => directory.nodes);
|
|
1963
|
+
var renderedRowCount = (tree, selected, hidden) => {
|
|
1964
|
+
const directories = tree.filter(
|
|
1965
|
+
(directory) => directory.nodes.some((node) => selected.has(node))
|
|
1966
|
+
).length;
|
|
1967
|
+
return selected.size + directories + (hidden > 0 ? 1 : 0);
|
|
1968
|
+
};
|
|
1969
|
+
var selectVisibleNodes2 = (tree, width, height) => {
|
|
1970
|
+
const nodes = flattenedNodes(tree);
|
|
1971
|
+
const selected = /* @__PURE__ */ new Set();
|
|
1972
|
+
const widthBudget = Math.max(
|
|
1973
|
+
1,
|
|
1974
|
+
Math.floor(Math.max(0, width) / ACTIVITY_COLUMNS_PER_VISIBLE_PATH)
|
|
1975
|
+
);
|
|
1976
|
+
const nodeBudget = Math.min(CAMP_UI_ACTIVITY_MAX_VISIBLE_PATHS, widthBudget);
|
|
1977
|
+
const mutations = nodes.filter((node) => node.access !== CampUiActivityAccess.read);
|
|
1978
|
+
const reads = nodes.filter((node) => node.access === CampUiActivityAccess.read);
|
|
1979
|
+
const addVisible = (node) => {
|
|
1980
|
+
if (selected.size >= nodeBudget) return;
|
|
1981
|
+
const candidate = new Set(selected).add(node);
|
|
1982
|
+
const hidden = nodes.length - candidate.size;
|
|
1983
|
+
if (renderedRowCount(tree, candidate, hidden) <= Math.max(0, height)) selected.add(node);
|
|
1984
|
+
};
|
|
1985
|
+
for (const node of mutations) addVisible(node);
|
|
1986
|
+
if (mutations.some((node) => !selected.has(node))) return selected;
|
|
1987
|
+
for (const node of reads) addVisible(node);
|
|
1988
|
+
return selected;
|
|
1989
|
+
};
|
|
1990
|
+
var shortenTail = (value, width) => {
|
|
1991
|
+
const available = Math.max(0, Math.floor(width));
|
|
1992
|
+
const valueWidth = visibleWidth3(value);
|
|
1993
|
+
if (valueWidth <= available) return value;
|
|
1994
|
+
if (available <= 0) return "";
|
|
1995
|
+
if (available === 1) return "\u2026";
|
|
1996
|
+
return `\u2026${sliceByColumn(value, valueWidth - available + 1, available - 1, true)}`;
|
|
1997
|
+
};
|
|
1998
|
+
var accessPresentation = {
|
|
1999
|
+
read: { label: "read", glyph: "r", tone: CampUiTone.neutral },
|
|
2000
|
+
edit: { label: "edited", glyph: "~", tone: CampUiTone.attention },
|
|
2001
|
+
write: { label: "created", glyph: "+", tone: CampUiTone.success }
|
|
2002
|
+
};
|
|
2003
|
+
var nodeLine2 = (node, last, width) => {
|
|
2004
|
+
const theme = getSelectListTheme9();
|
|
2005
|
+
const presentation = accessPresentation[node.access];
|
|
2006
|
+
const count = node.count > 1 ? ` \xD7${String(node.count)}` : "";
|
|
2007
|
+
const suffix = ` \xB7 ${presentation.label}${count}`;
|
|
2008
|
+
const branch = last ? "\u2514\u2500" : "\u251C\u2500";
|
|
2009
|
+
const nameWidth = Math.max(1, width - visibleWidth3(`${branch} ${presentation.glyph} ${suffix}`));
|
|
2010
|
+
const name = shortenTail(node.name, nameWidth);
|
|
2011
|
+
return fitCampUiLine(
|
|
2012
|
+
`${theme.description(branch)} ${renderCampUiStatus(name, presentation.tone, presentation.glyph)}${theme.description(suffix)}`,
|
|
2013
|
+
width
|
|
2014
|
+
);
|
|
2015
|
+
};
|
|
2016
|
+
var hiddenSummary = (nodes) => {
|
|
2017
|
+
const parts = Object.values(CampUiActivityAccess).flatMap((access) => {
|
|
2018
|
+
const count = nodes.filter((node) => node.access === access).length;
|
|
2019
|
+
if (count === 0) return [];
|
|
2020
|
+
const label = accessPresentation[access].label;
|
|
2021
|
+
return [`${String(count)} ${label} ${count === 1 ? "path" : "paths"}`];
|
|
2022
|
+
});
|
|
2023
|
+
return `... ${parts.join(" \xB7 ")} hidden`;
|
|
2024
|
+
};
|
|
2025
|
+
var renderCampUiActivityTree = (transcript, width, height) => {
|
|
2026
|
+
const theme = getSelectListTheme9();
|
|
2027
|
+
const tree = collectCampUiActivityTree(transcript);
|
|
2028
|
+
const nodes = flattenedNodes(tree);
|
|
2029
|
+
if (height <= 0) return [];
|
|
2030
|
+
if (nodes.length === 0) return [fitCampUiLine(theme.description("no file activity"), width)];
|
|
2031
|
+
const selected = selectVisibleNodes2(tree, width, height);
|
|
2032
|
+
const lines = [];
|
|
2033
|
+
for (const directory of tree) {
|
|
2034
|
+
const visible = directory.nodes.filter((node) => selected.has(node));
|
|
2035
|
+
if (visible.length === 0) continue;
|
|
2036
|
+
lines.push(fitCampUiLine(theme.description(shortenTail(directory.path, width)), width));
|
|
2037
|
+
visible.forEach((node, index) => {
|
|
2038
|
+
lines.push(nodeLine2(node, index === visible.length - 1, width));
|
|
2039
|
+
});
|
|
2040
|
+
}
|
|
2041
|
+
const hidden = nodes.filter((node) => !selected.has(node));
|
|
2042
|
+
if (hidden.length > 0) {
|
|
2043
|
+
lines.push(fitCampUiLine(theme.description(hiddenSummary(hidden)), width));
|
|
2044
|
+
}
|
|
2045
|
+
return lines;
|
|
2046
|
+
};
|
|
2047
|
+
var makeCampUiActivity = (context) => ({
|
|
2048
|
+
render: (viewport) => {
|
|
2049
|
+
const model = context.readModel();
|
|
2050
|
+
const workerId = model.state.selectedWorkerId;
|
|
2051
|
+
const worker = workerId === void 0 ? void 0 : findCampUiWorker(model.snapshot, workerId);
|
|
2052
|
+
return renderCampUiActivityTree(
|
|
2053
|
+
worker?.snapshot.session?.transcript ?? [],
|
|
2054
|
+
viewport.width,
|
|
2055
|
+
viewport.height
|
|
2056
|
+
);
|
|
2057
|
+
}
|
|
2058
|
+
});
|
|
2059
|
+
|
|
2060
|
+
// packages/host-ui/src/pi/layout/campUiChrome.ts
|
|
2061
|
+
import { getSelectListTheme as getSelectListTheme10 } from "@earendil-works/pi-coding-agent";
|
|
2062
|
+
import { truncateToWidth as truncateToWidth4, visibleWidth as visibleWidth4 } from "@earendil-works/pi-tui";
|
|
2063
|
+
|
|
2064
|
+
// packages/host-ui/src/pi/shared/campUiPulse.ts
|
|
2065
|
+
var BRAILLE_BASE = 10240;
|
|
2066
|
+
var DOT_BITS = [
|
|
2067
|
+
[1, 2, 4, 64],
|
|
2068
|
+
[8, 16, 32, 128]
|
|
2069
|
+
];
|
|
2070
|
+
var ROWS_PER_CELL = 4;
|
|
2071
|
+
var LINES = 2;
|
|
2072
|
+
var LEVELS = ROWS_PER_CELL * LINES;
|
|
2073
|
+
var SAMPLES_PER_COLUMN = 2;
|
|
2074
|
+
var EMPTY_CELL = String.fromCharCode(BRAILLE_BASE);
|
|
2075
|
+
var emptyPulse = (columns) => {
|
|
2076
|
+
const blank = EMPTY_CELL.repeat(Math.max(0, columns));
|
|
2077
|
+
return [blank, blank];
|
|
2078
|
+
};
|
|
2079
|
+
var renderCampUiPulse = (samples, options) => {
|
|
2080
|
+
const columns = Math.max(0, Math.floor(options.columns));
|
|
2081
|
+
if (columns === 0 || samples.length === 0) return emptyPulse(columns);
|
|
2082
|
+
const window = samples.slice(-columns * SAMPLES_PER_COLUMN);
|
|
2083
|
+
const peak = options.ceiling ?? Math.max(...window);
|
|
2084
|
+
const scale = peak > 0 ? peak : 1;
|
|
2085
|
+
const cells = [new Array(columns).fill(0), new Array(columns).fill(0)];
|
|
2086
|
+
const offset = columns * SAMPLES_PER_COLUMN - window.length;
|
|
2087
|
+
window.forEach((value, index) => {
|
|
2088
|
+
const position = offset + index;
|
|
2089
|
+
const column = Math.floor(position / SAMPLES_PER_COLUMN);
|
|
2090
|
+
const half = position % SAMPLES_PER_COLUMN;
|
|
2091
|
+
const height = Math.max(0, Math.min(LEVELS - 1, Math.round(value / scale * (LEVELS - 1))));
|
|
2092
|
+
const row = LEVELS - 1 - height;
|
|
2093
|
+
const line = Math.floor(row / ROWS_PER_CELL);
|
|
2094
|
+
const bits = DOT_BITS[half]?.[row % ROWS_PER_CELL];
|
|
2095
|
+
const target = cells[line];
|
|
2096
|
+
if (bits === void 0 || target === void 0) return;
|
|
2097
|
+
target[column] = (target[column] ?? 0) | bits;
|
|
2098
|
+
});
|
|
2099
|
+
const [upper, lower] = cells.map(
|
|
2100
|
+
(row) => row.map((bits) => String.fromCharCode(BRAILLE_BASE + bits)).join("")
|
|
2101
|
+
);
|
|
2102
|
+
return [upper ?? "", lower ?? ""];
|
|
2103
|
+
};
|
|
2104
|
+
|
|
2105
|
+
// packages/host-ui/src/pi/shared/campUiTone.ts
|
|
2106
|
+
var CampUiLevel = {
|
|
2107
|
+
/** An ordinary card: present, but not asking to be read. */
|
|
2108
|
+
resting: "resting",
|
|
2109
|
+
/** The cursor is on this card; its session is not open. */
|
|
2110
|
+
focused: "focused",
|
|
2111
|
+
/** The open card, whose session fills the centre. */
|
|
2112
|
+
selected: "selected"
|
|
2113
|
+
};
|
|
2114
|
+
var roleColors = {
|
|
2115
|
+
foreman: { r: 122, g: 192, b: 140 },
|
|
2116
|
+
wright: { r: 196, g: 96, b: 108 },
|
|
2117
|
+
assayer: { r: 214, g: 168, b: 96 },
|
|
2118
|
+
prospector: { r: 120, g: 178, b: 214 }
|
|
2119
|
+
};
|
|
2120
|
+
var UNKNOWN_ROLE = { r: 178, g: 178, b: 190 };
|
|
2121
|
+
var CampUiInk = {
|
|
2122
|
+
primary: { r: 216, g: 216, b: 228 },
|
|
2123
|
+
secondary: { r: 182, g: 182, b: 196 },
|
|
2124
|
+
muted: { r: 154, g: 154, b: 168 }
|
|
2125
|
+
};
|
|
2126
|
+
var levelSteps = {
|
|
2127
|
+
[CampUiLevel.selected]: { saturation: 1, brightness: 1 },
|
|
2128
|
+
[CampUiLevel.focused]: { saturation: 0.72, brightness: 0.96 },
|
|
2129
|
+
[CampUiLevel.resting]: { saturation: 0.45, brightness: 0.9 }
|
|
2130
|
+
};
|
|
2131
|
+
var luminance = ({ r, g, b }) => 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
2132
|
+
var FOREGROUND_RESET = "\x1B[39m";
|
|
2133
|
+
var step = (color, level) => {
|
|
2134
|
+
const { saturation, brightness } = levelSteps[level];
|
|
2135
|
+
const grey = luminance(color);
|
|
2136
|
+
const blend = (channel) => Math.max(0, Math.min(255, Math.round((grey + (channel - grey) * saturation) * brightness)));
|
|
2137
|
+
return { r: blend(color.r), g: blend(color.g), b: blend(color.b) };
|
|
2138
|
+
};
|
|
2139
|
+
var foreground = (color) => `\x1B[38;2;${String(color.r)};${String(color.g)};${String(color.b)}m`;
|
|
2140
|
+
var campUiRoleColor = (role) => role === void 0 ? UNKNOWN_ROLE : roleColors[role] ?? UNKNOWN_ROLE;
|
|
2141
|
+
var campUiText = (text, color, level) => `${foreground(step(color, level))}${text}${FOREGROUND_RESET}`;
|
|
2142
|
+
var campUiPulseText = (pulse, level, roleColor) => campUiText(pulse, level === CampUiLevel.selected ? roleColor : CampUiInk.secondary, level);
|
|
2143
|
+
var levelMarkers = {
|
|
2144
|
+
[CampUiLevel.selected]: "\u25CF",
|
|
2145
|
+
[CampUiLevel.focused]: "\u25CB",
|
|
2146
|
+
[CampUiLevel.resting]: " "
|
|
2147
|
+
};
|
|
2148
|
+
var campUiLevelMarkerText = (level, color) => level === CampUiLevel.resting ? levelMarkers[level] : campUiText(levelMarkers[level], color, level);
|
|
2149
|
+
|
|
2150
|
+
// packages/host-ui/src/pi/layout/campUiChrome.ts
|
|
1764
2151
|
var makeCampUiCampHeader = (context) => ({
|
|
1765
2152
|
render: (viewport) => {
|
|
1766
2153
|
const snapshot = context.readModel().snapshot;
|
|
1767
|
-
const theme =
|
|
2154
|
+
const theme = getSelectListTheme10();
|
|
1768
2155
|
const mode = snapshot.placement === "external" ? "agentless" : "foreman";
|
|
1769
2156
|
return [
|
|
1770
2157
|
fitCampUiLine(theme.description(snapshot.displayName), viewport.width),
|
|
@@ -1775,55 +2162,158 @@ var makeCampUiCampHeader = (context) => ({
|
|
|
1775
2162
|
];
|
|
1776
2163
|
}
|
|
1777
2164
|
});
|
|
1778
|
-
var
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
2165
|
+
var PULSE_WINDOW_MS = 12e4;
|
|
2166
|
+
var PULSE_CEILING = 4;
|
|
2167
|
+
var PULSE_SAMPLES_PER_COLUMN = 2;
|
|
2168
|
+
var rosterWidths = (width) => {
|
|
2169
|
+
const right = Math.min(17, Math.max(0, width - 17));
|
|
2170
|
+
const left = Math.min(11, Math.max(0, width - right - 6));
|
|
2171
|
+
return { left, pulse: Math.max(0, width - left - right - 4), right };
|
|
2172
|
+
};
|
|
2173
|
+
var rightColumn = (text, width) => {
|
|
2174
|
+
const fitted = truncateToWidth4(text, width);
|
|
2175
|
+
return `${" ".repeat(Math.max(0, width - visibleWidth4(fitted)))}${fitted}`;
|
|
2176
|
+
};
|
|
2177
|
+
var pulseSamples = (timestamps, sampleCount, now) => {
|
|
2178
|
+
if (sampleCount <= 0) return [];
|
|
2179
|
+
const samples = new Array(sampleCount).fill(0);
|
|
2180
|
+
const windowStart = now - PULSE_WINDOW_MS;
|
|
2181
|
+
const interval = PULSE_WINDOW_MS / sampleCount;
|
|
2182
|
+
for (const timestamp of timestamps) {
|
|
2183
|
+
if (timestamp < windowStart || timestamp > now) continue;
|
|
2184
|
+
const index = Math.min(sampleCount - 1, Math.floor((timestamp - windowStart) / interval));
|
|
2185
|
+
samples[index] = (samples[index] ?? 0) + 1;
|
|
1790
2186
|
}
|
|
1791
|
-
|
|
2187
|
+
return samples;
|
|
2188
|
+
};
|
|
2189
|
+
var elapsedText = (updatedAt, now) => {
|
|
2190
|
+
const seconds = Math.floor(Math.max(0, now - updatedAt) / 1e3);
|
|
2191
|
+
if (seconds < 60) return `${String(seconds)}s`;
|
|
2192
|
+
const minutes = Math.floor(seconds / 60);
|
|
2193
|
+
if (minutes < 60) return `${String(minutes)}m`;
|
|
2194
|
+
const hours = Math.floor(minutes / 60);
|
|
2195
|
+
if (hours < 24) return `${String(hours)}h`;
|
|
2196
|
+
return `${String(Math.floor(hours / 24))}d`;
|
|
2197
|
+
};
|
|
2198
|
+
var percentText = (percent) => percent === null || percent === void 0 ? "\u2014" : `${percent.toFixed(0)}%`;
|
|
2199
|
+
var usageText = (entry, width) => {
|
|
2200
|
+
const usage = entry.snapshot.session?.usage;
|
|
2201
|
+
const context = percentText(usage?.context?.percent);
|
|
2202
|
+
const cache = usage?.latestCacheHitRate === void 0 ? usage === void 0 || usage.tokens.total === 0 ? "n/a" : "n/r" : percentText(usage.latestCacheHitRate);
|
|
2203
|
+
const cost = usage === void 0 ? "\u2014" : `$${usage.cost.toFixed(3)}`;
|
|
2204
|
+
const full = `${context} ${cache} ${cost}`;
|
|
2205
|
+
if (visibleWidth4(full) <= width || usage === void 0) return full;
|
|
2206
|
+
const compactCost = `$${usage.cost.toFixed(2).replace(/^0/u, "")}`;
|
|
2207
|
+
return `${context}${cache}${compactCost}`;
|
|
2208
|
+
};
|
|
2209
|
+
var stateText = (state, duration, width) => {
|
|
2210
|
+
const full = `${state} ${duration}`;
|
|
2211
|
+
return visibleWidth4(full) <= width ? full : state;
|
|
2212
|
+
};
|
|
2213
|
+
var modelText = (entry) => {
|
|
2214
|
+
const model = entry.snapshot.session?.usage?.model ?? entry.snapshot.worker.equipment.model;
|
|
2215
|
+
if (model === void 0) return "model unknown";
|
|
2216
|
+
return model.split("/").at(-1) ?? model;
|
|
2217
|
+
};
|
|
2218
|
+
var cardLine = (marker, left, pulse, right, widths, width) => fitCampUiLine(
|
|
2219
|
+
`${marker} ${fitCampUiLine(left, widths.left)} ${fitCampUiLine(pulse, widths.pulse)} ${rightColumn(right, widths.right)}`,
|
|
2220
|
+
width
|
|
2221
|
+
);
|
|
2222
|
+
var renderExternalControllerCard = (controllerConnected, width) => {
|
|
2223
|
+
const level = CampUiLevel.resting;
|
|
2224
|
+
const color = campUiRoleColor("foreman");
|
|
2225
|
+
const widths = rosterWidths(width);
|
|
2226
|
+
const neutral = (text) => campUiText(text, CampUiInk.secondary, level);
|
|
2227
|
+
return [
|
|
2228
|
+
cardLine(
|
|
2229
|
+
campUiLevelMarkerText(level, color),
|
|
2230
|
+
campUiText("controller", color, level),
|
|
2231
|
+
"",
|
|
2232
|
+
neutral("ext"),
|
|
2233
|
+
widths,
|
|
2234
|
+
width
|
|
2235
|
+
),
|
|
2236
|
+
cardLine(
|
|
2237
|
+
" ",
|
|
2238
|
+
"",
|
|
2239
|
+
"",
|
|
2240
|
+
neutral(controllerConnected ? "lease live" : "lease lost"),
|
|
2241
|
+
widths,
|
|
2242
|
+
width
|
|
2243
|
+
)
|
|
2244
|
+
];
|
|
2245
|
+
};
|
|
2246
|
+
var renderWorkerCard = (entry, selectedWorkerId, detailVisible, now, width) => {
|
|
2247
|
+
const worker = entry.snapshot.worker;
|
|
2248
|
+
const session = entry.snapshot.session;
|
|
2249
|
+
const level = worker.id !== selectedWorkerId ? CampUiLevel.resting : detailVisible ? CampUiLevel.selected : CampUiLevel.focused;
|
|
2250
|
+
const roleColor = campUiRoleColor(worker.equipment.role);
|
|
2251
|
+
const widths = rosterWidths(width);
|
|
2252
|
+
const timestamps = (session?.transcript ?? []).flatMap(
|
|
2253
|
+
(message) => message.timestamp === void 0 ? [] : [message.timestamp]
|
|
2254
|
+
);
|
|
2255
|
+
const pulse = renderCampUiPulse(
|
|
2256
|
+
pulseSamples(timestamps, widths.pulse * PULSE_SAMPLES_PER_COLUMN, now),
|
|
2257
|
+
{ columns: widths.pulse, ceiling: PULSE_CEILING }
|
|
2258
|
+
);
|
|
2259
|
+
const pendingAsks = entry.asks.filter((ask) => ask.state === "pending").length;
|
|
2260
|
+
const state = campUiWorkerStateLabel(worker.state, {
|
|
2261
|
+
failed: entry.error !== void 0,
|
|
2262
|
+
pendingAsks,
|
|
2263
|
+
streaming: session?.isStreaming === true
|
|
2264
|
+
});
|
|
2265
|
+
const neutral = (text) => campUiText(text, CampUiInk.secondary, level);
|
|
2266
|
+
const name = worker.alias ?? worker.id.slice(0, 8);
|
|
2267
|
+
return [
|
|
2268
|
+
cardLine(
|
|
2269
|
+
campUiLevelMarkerText(level, roleColor),
|
|
2270
|
+
campUiText(name, roleColor, level),
|
|
2271
|
+
campUiPulseText(pulse[0], level, roleColor),
|
|
2272
|
+
neutral(modelText(entry)),
|
|
2273
|
+
widths,
|
|
2274
|
+
width
|
|
2275
|
+
),
|
|
2276
|
+
cardLine(
|
|
2277
|
+
" ",
|
|
2278
|
+
neutral(stateText(state, elapsedText(worker.updatedAt, now), widths.left)),
|
|
2279
|
+
campUiPulseText(pulse[1], level, roleColor),
|
|
2280
|
+
neutral(usageText(entry, widths.right)),
|
|
2281
|
+
widths,
|
|
2282
|
+
width
|
|
2283
|
+
)
|
|
2284
|
+
];
|
|
2285
|
+
};
|
|
1792
2286
|
var makeCampUiRoster = (context) => ({
|
|
1793
2287
|
focusable: true,
|
|
1794
2288
|
render: (viewport) => {
|
|
1795
2289
|
const model = context.readModel();
|
|
1796
|
-
const
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
return [theme.description("No workers")];
|
|
2290
|
+
const external = model.snapshot.placement === CampUiPlacement.external;
|
|
2291
|
+
if (model.snapshot.workers.length === 0 && !external) {
|
|
2292
|
+
return [getSelectListTheme10().description("No workers")];
|
|
1800
2293
|
}
|
|
1801
|
-
const
|
|
1802
|
-
|
|
1803
|
-
const
|
|
1804
|
-
const
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
const label = selected ? theme.selectedText(name) : name;
|
|
1813
|
-
const role = theme.description(`(${worker.equipment.role ?? "unknown"})`);
|
|
1814
|
-
const status = renderCampUiWorkerState(worker.state, {
|
|
1815
|
-
failed: entry.error !== void 0,
|
|
1816
|
-
pendingAsks,
|
|
1817
|
-
streaming: session?.isStreaming === true
|
|
1818
|
-
});
|
|
1819
|
-
const line = `${status} ${label} ${role}${tool}`;
|
|
1820
|
-
return selected && focused ? renderSelectedCampUiRow(line, viewport.width) : fitCampUiLine(line, viewport.width);
|
|
2294
|
+
const controller = external ? renderExternalControllerCard(model.snapshot.controllerConnected, viewport.width) : [];
|
|
2295
|
+
const workers = model.snapshot.workers.flatMap((entry) => {
|
|
2296
|
+
const candidateNow = model.state.presentationNow;
|
|
2297
|
+
const now = Number.isFinite(candidateNow) ? candidateNow : entry.snapshot.worker.updatedAt;
|
|
2298
|
+
return renderWorkerCard(
|
|
2299
|
+
entry,
|
|
2300
|
+
model.state.selectedWorkerId,
|
|
2301
|
+
model.state.detailVisible,
|
|
2302
|
+
now,
|
|
2303
|
+
viewport.width
|
|
2304
|
+
);
|
|
1821
2305
|
});
|
|
1822
|
-
return workers;
|
|
2306
|
+
return [...controller, ...workers];
|
|
1823
2307
|
},
|
|
1824
2308
|
handlePointer: (pointer) => {
|
|
1825
2309
|
if (pointer.action !== "press" || pointer.button !== "left") return [];
|
|
1826
|
-
const
|
|
2310
|
+
const model = context.readModel();
|
|
2311
|
+
const controllerRows = model.snapshot.placement === CampUiPlacement.external ? 2 : 0;
|
|
2312
|
+
if (pointer.y < controllerRows) {
|
|
2313
|
+
return [CampUiIntents.FocusSlot({ slotId: CampUiSlot.roster })];
|
|
2314
|
+
}
|
|
2315
|
+
const workerIndex = Math.floor((pointer.y - controllerRows) / 2);
|
|
2316
|
+
const workerId = model.snapshot.workers[workerIndex]?.snapshot.worker.id;
|
|
1827
2317
|
if (workerId === void 0) return [];
|
|
1828
2318
|
return [
|
|
1829
2319
|
CampUiIntents.FocusSlot({ slotId: CampUiSlot.roster }),
|
|
@@ -1834,7 +2324,7 @@ var makeCampUiRoster = (context) => ({
|
|
|
1834
2324
|
var makeCampUiSessionHeader = (context) => ({
|
|
1835
2325
|
render: (viewport) => {
|
|
1836
2326
|
const model = context.readModel();
|
|
1837
|
-
const theme =
|
|
2327
|
+
const theme = getSelectListTheme10();
|
|
1838
2328
|
const workerId = model.state.selectedWorkerId;
|
|
1839
2329
|
if (workerId === void 0) {
|
|
1840
2330
|
return [fitCampUiLine(theme.description("Select a worker"), viewport.width)];
|
|
@@ -1855,29 +2345,63 @@ var makeCampUiSessionHeader = (context) => ({
|
|
|
1855
2345
|
] : []
|
|
1856
2346
|
});
|
|
1857
2347
|
|
|
1858
|
-
// packages/host-ui/src/pi/layout/
|
|
1859
|
-
import {
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
2348
|
+
// packages/host-ui/src/pi/layout/campUiEquipment.ts
|
|
2349
|
+
import { getSelectListTheme as getSelectListTheme11 } from "@earendil-works/pi-coding-agent";
|
|
2350
|
+
import { wrapTextWithAnsi } from "@earendil-works/pi-tui";
|
|
2351
|
+
var fullEquipmentLines = (equipment, revision, width) => {
|
|
2352
|
+
if (width <= 0) return [];
|
|
2353
|
+
const theme = getSelectListTheme11();
|
|
2354
|
+
return equipmentDescriptionLines(equipment, revision).flatMap(
|
|
2355
|
+
(line) => wrapTextWithAnsi(theme.description(line), width).map(
|
|
2356
|
+
(wrapped) => fitCampUiLine(wrapped, width)
|
|
2357
|
+
)
|
|
2358
|
+
);
|
|
2359
|
+
};
|
|
2360
|
+
var renderCampUiEquipment = (equipment, revision, width, height) => {
|
|
2361
|
+
const lines = fullEquipmentLines(equipment, revision, width);
|
|
2362
|
+
const available = Math.max(0, Math.floor(height));
|
|
2363
|
+
if (available === 0 || lines.length === 0) return [];
|
|
2364
|
+
if (lines.length <= available) return lines;
|
|
2365
|
+
const shown = lines.slice(0, Math.max(0, available - 1));
|
|
2366
|
+
const hidden = lines.length - shown.length;
|
|
2367
|
+
const summary = getSelectListTheme11().description(
|
|
2368
|
+
`... ${String(hidden)} equipment ${hidden === 1 ? "line" : "lines"} hidden`
|
|
1863
2369
|
);
|
|
2370
|
+
return [...shown, fitCampUiLine(summary, width)];
|
|
2371
|
+
};
|
|
2372
|
+
var makeCampUiEquipment = (context) => {
|
|
2373
|
+
const selectedWorker = () => {
|
|
2374
|
+
const model = context.readModel();
|
|
2375
|
+
const workerId = model.state.selectedWorkerId;
|
|
2376
|
+
return workerId === void 0 ? void 0 : findCampUiWorker(model.snapshot, workerId);
|
|
2377
|
+
};
|
|
2378
|
+
const fullLines = (width) => {
|
|
2379
|
+
const worker = selectedWorker();
|
|
2380
|
+
return worker === void 0 ? [fitCampUiLine(getSelectListTheme11().description("no worker selected"), width)] : fullEquipmentLines(
|
|
2381
|
+
worker.snapshot.worker.equipment,
|
|
2382
|
+
worker.snapshot.worker.equipmentVersion,
|
|
2383
|
+
width
|
|
2384
|
+
);
|
|
2385
|
+
};
|
|
1864
2386
|
return {
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
2387
|
+
preferredRows: (width) => fullLines(width).length,
|
|
2388
|
+
render: (viewport) => {
|
|
2389
|
+
const worker = selectedWorker();
|
|
2390
|
+
if (worker === void 0) return fullLines(viewport.width).slice(0, viewport.height);
|
|
2391
|
+
return renderCampUiEquipment(
|
|
2392
|
+
worker.snapshot.worker.equipment,
|
|
2393
|
+
worker.snapshot.worker.equipmentVersion,
|
|
2394
|
+
viewport.width,
|
|
2395
|
+
viewport.height
|
|
2396
|
+
);
|
|
2397
|
+
}
|
|
1869
2398
|
};
|
|
1870
2399
|
};
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
}
|
|
1877
|
-
const lowerBound = partial ? "\u2265" : "";
|
|
1878
|
-
return `\u2193 ${lowerBound}${compactNumber(usage.tokens)} tokens \xB7 ${lowerBound}$${usage.cost.toFixed(3)}${coverage}`;
|
|
1879
|
-
};
|
|
1880
|
-
var footerDivider = (width) => fitCampUiLine(getMarkdownTheme8().codeBlockBorder("\u2500".repeat(width)), width);
|
|
2400
|
+
|
|
2401
|
+
// packages/host-ui/src/pi/layout/campUiFooter.ts
|
|
2402
|
+
import { getMarkdownTheme as getMarkdownTheme7, getSelectListTheme as getSelectListTheme12 } from "@earendil-works/pi-coding-agent";
|
|
2403
|
+
import { sliceByColumn as sliceByColumn2, visibleWidth as visibleWidth5 } from "@earendil-works/pi-tui";
|
|
2404
|
+
var footerDivider = (width) => fitCampUiLine(getMarkdownTheme7().codeBlockBorder("\u2500".repeat(width)), width);
|
|
1881
2405
|
var retryText = (retryAt, attempt, now) => {
|
|
1882
2406
|
if (retryAt === void 0) return attempt === void 0 ? "" : `attempt ${String(attempt)}`;
|
|
1883
2407
|
const seconds = Math.max(0, Math.ceil((retryAt - now) / 1e3));
|
|
@@ -1888,56 +2412,73 @@ var diagnosticText = (value) => {
|
|
|
1888
2412
|
const normalized = value?.replaceAll(/\s+/gu, " ").trim();
|
|
1889
2413
|
return normalized === "" ? void 0 : normalized;
|
|
1890
2414
|
};
|
|
1891
|
-
var
|
|
2415
|
+
var workerCountText = (workers) => {
|
|
2416
|
+
if (workers.length === 0) return "no workers";
|
|
2417
|
+
const working = workers.filter(
|
|
2418
|
+
(worker) => worker.snapshot.worker.state === CampWorkerState.running
|
|
2419
|
+
).length;
|
|
2420
|
+
const waiting = workers.filter((worker) => worker.asks.some(isPendingAsk)).length;
|
|
2421
|
+
const parts = [
|
|
2422
|
+
`${String(workers.length)} ${workers.length === 1 ? "worker" : "workers"}`,
|
|
2423
|
+
...working === 0 ? [] : [`${String(working)} working`],
|
|
2424
|
+
...waiting === 0 ? [] : [`${String(waiting)} waiting`]
|
|
2425
|
+
];
|
|
2426
|
+
return parts.join(" \xB7 ");
|
|
2427
|
+
};
|
|
2428
|
+
var isPendingAsk = (ask) => ask.state === "pending";
|
|
2429
|
+
var shortenPath = (value, width) => {
|
|
2430
|
+
const available = Math.max(0, Math.floor(width));
|
|
2431
|
+
if (available <= 0) return "";
|
|
2432
|
+
if (visibleWidth5(value) <= available) return value;
|
|
2433
|
+
if (available === 1) return "\u2026";
|
|
2434
|
+
const kept = available - 1;
|
|
2435
|
+
return `\u2026${sliceByColumn2(value, visibleWidth5(value) - kept, kept, true)}`;
|
|
2436
|
+
};
|
|
2437
|
+
var makeCampUiFooter = (context) => ({
|
|
1892
2438
|
render: (viewport) => {
|
|
1893
2439
|
const model = context.readModel();
|
|
1894
|
-
const theme =
|
|
1895
|
-
const
|
|
1896
|
-
const
|
|
2440
|
+
const theme = getSelectListTheme12();
|
|
2441
|
+
const snapshot = model.snapshot;
|
|
2442
|
+
const health = snapshot.health;
|
|
1897
2443
|
const actionError = diagnosticText(model.state.lastActionError);
|
|
1898
2444
|
const healthSummary = diagnosticText(health.message);
|
|
1899
2445
|
const healthMessage = health.code === void 0 ? healthSummary : healthSummary === void 0 ? health.code : `${health.code} \xB7 ${healthSummary}`;
|
|
1900
2446
|
const healthTone = health.status === CampUiHealthStatus.failed ? CampUiTone.error : CampUiTone.attention;
|
|
1901
|
-
const diagnostic = actionError !== void 0 ? `${renderCampUiStatus("action error", CampUiTone.error)} ${theme.description(`\xB7 ${actionError}`)}` : healthMessage !== void 0 ? styleCampUiTone(healthTone, healthMessage) : health.status === CampUiHealthStatus.ready ? "" : renderCampUiStatus(health.status, healthTone);
|
|
1902
2447
|
const retry = retryText(health.retryAt, health.attempt, model.state.presentationNow);
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
2448
|
+
const diagnostic = actionError !== void 0 ? `${renderCampUiStatus("action error", CampUiTone.error)} ${theme.description(`\xB7 ${actionError}`)}` : healthMessage !== void 0 ? styleCampUiTone(healthTone, healthMessage) : health.status === CampUiHealthStatus.ready ? "" : renderCampUiStatus(health.status, healthTone);
|
|
2449
|
+
const branch = snapshot.projectBranch === null ? "" : ` \xB7 ${snapshot.projectBranch}`;
|
|
2450
|
+
const version = `v${snapshot.hostVersion}`;
|
|
2451
|
+
const candidates = [
|
|
2452
|
+
{ right: [workerCountText(snapshot.workers), version, retry], branch },
|
|
2453
|
+
{ right: [workerCountText(snapshot.workers), version], branch },
|
|
2454
|
+
{ right: [version], branch },
|
|
2455
|
+
{ right: [version], branch: "" }
|
|
1907
2456
|
];
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
const
|
|
1915
|
-
const
|
|
1916
|
-
const
|
|
1917
|
-
const
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
const
|
|
1922
|
-
const thinking = worker?.snapshot.session?.thinkingLevel ?? worker?.snapshot.worker.equipment.thinkingLevel ?? "unknown";
|
|
1923
|
-
const identity = worker === void 0 ? theme.description("worker not selected") : `${theme.selectedText(worker.snapshot.worker.alias ?? worker.snapshot.worker.id.slice(0, 8))} ${theme.description(`\xB7 ${worker.snapshot.worker.cwd}`)}`;
|
|
1924
|
-
const branch = worker === void 0 || model.snapshot.projectBranch === null ? "" : theme.description(`branch ${model.snapshot.projectBranch}`);
|
|
2457
|
+
const MINIMUM_PATH_COLUMNS = 8;
|
|
2458
|
+
const chosen = candidates.find((candidate) => {
|
|
2459
|
+
const rightWidth = visibleWidth5(candidate.right.filter((part) => part !== "").join(" \xB7 "));
|
|
2460
|
+
const room = viewport.width - rightWidth - 3 - visibleWidth5(candidate.branch);
|
|
2461
|
+
return room >= MINIMUM_PATH_COLUMNS;
|
|
2462
|
+
}) ?? candidates[candidates.length - 1];
|
|
2463
|
+
const right = (chosen ?? candidates[0])?.right.filter((part) => part !== "").join(" \xB7 ") ?? "";
|
|
2464
|
+
const chosenBranch = chosen?.branch ?? "";
|
|
2465
|
+
const leftBudget = Math.max(0, viewport.width - visibleWidth5(right) - 3);
|
|
2466
|
+
const path = shortenPath(
|
|
2467
|
+
snapshot.projectScope,
|
|
2468
|
+
Math.max(0, leftBudget - visibleWidth5(chosenBranch))
|
|
2469
|
+
);
|
|
2470
|
+
const left = diagnostic === "" ? theme.description(`${path}${chosenBranch}`) : `${diagnostic} ${theme.description(`\xB7 ${path}${chosenBranch}`)}`;
|
|
1925
2471
|
return [
|
|
1926
2472
|
footerDivider(viewport.width),
|
|
1927
|
-
|
|
1928
|
-
joinCampUiColumns(
|
|
1929
|
-
theme.description(`${tokenText} \xB7 ${costText} \xB7 ${cacheText} \xB7 ${contextText}`),
|
|
1930
|
-
theme.description(`${modelText} \xB7 effort ${thinking}`),
|
|
1931
|
-
viewport.width
|
|
1932
|
-
)
|
|
2473
|
+
joinCampUiColumns(left, theme.description(right), viewport.width)
|
|
1933
2474
|
];
|
|
1934
2475
|
}
|
|
1935
2476
|
});
|
|
1936
2477
|
|
|
1937
2478
|
// packages/host-ui/src/pi/layout/campUiResources.ts
|
|
1938
|
-
import { getSelectListTheme as
|
|
2479
|
+
import { getSelectListTheme as getSelectListTheme13 } from "@earendil-works/pi-coding-agent";
|
|
1939
2480
|
var renderResourceTree = (label, value, tone, width) => {
|
|
1940
|
-
const theme =
|
|
2481
|
+
const theme = getSelectListTheme13();
|
|
1941
2482
|
const lines = [
|
|
1942
2483
|
theme.description(label),
|
|
1943
2484
|
`${theme.description("\u2514\u2500")} ${renderCampUiStatus(value, tone)}`
|
|
@@ -1945,6 +2486,7 @@ var renderResourceTree = (label, value, tone, width) => {
|
|
|
1945
2486
|
return lines.map((line) => fitCampUiLine(line, width));
|
|
1946
2487
|
};
|
|
1947
2488
|
var makeCampUiResources = (context) => ({
|
|
2489
|
+
preferredRows: () => 10,
|
|
1948
2490
|
render: (viewport) => {
|
|
1949
2491
|
const model = context.readModel();
|
|
1950
2492
|
const snapshot = model.snapshot;
|
|
@@ -1978,27 +2520,29 @@ var makeCampUiResources = (context) => ({
|
|
|
1978
2520
|
...missingMcpHealth ? ["health not reported"] : []
|
|
1979
2521
|
];
|
|
1980
2522
|
const mcpText = !equipmentReported ? "not reported" : mcpNames.length === 0 ? "none configured" : `${mcpNames.join(", ")}${mcpNotes.length === 0 ? "" : ` \xB7 ${mcpNotes.join(", ")}`}`;
|
|
1981
|
-
|
|
2523
|
+
const contentWidth = Math.max(1, viewport.width - 2);
|
|
2524
|
+
const body = [
|
|
1982
2525
|
...renderResourceTree(
|
|
1983
2526
|
"Context",
|
|
1984
2527
|
resourceText(inventory.contextFiles),
|
|
1985
2528
|
inventory.contextFiles.length > 0 ? CampUiTone.success : CampUiTone.neutral,
|
|
1986
|
-
|
|
2529
|
+
contentWidth
|
|
1987
2530
|
),
|
|
1988
2531
|
...renderResourceTree(
|
|
1989
2532
|
"Extensions",
|
|
1990
2533
|
resourceText(inventory.extensions),
|
|
1991
2534
|
inventory.extensions.length > 0 ? CampUiTone.success : CampUiTone.neutral,
|
|
1992
|
-
|
|
2535
|
+
contentWidth
|
|
1993
2536
|
),
|
|
1994
2537
|
...renderResourceTree(
|
|
1995
2538
|
"Skills",
|
|
1996
2539
|
resourceText(inventory.skills),
|
|
1997
2540
|
inventory.skills.length > 0 ? CampUiTone.success : CampUiTone.neutral,
|
|
1998
|
-
|
|
2541
|
+
contentWidth
|
|
1999
2542
|
),
|
|
2000
|
-
...renderResourceTree("MCP", mcpText, mcpTone,
|
|
2543
|
+
...renderResourceTree("MCP", mcpText, mcpTone, contentWidth)
|
|
2001
2544
|
];
|
|
2545
|
+
return renderCampUiPanel("Camp inventory \xB7 Esc to close", body, viewport.width);
|
|
2002
2546
|
}
|
|
2003
2547
|
});
|
|
2004
2548
|
|
|
@@ -2010,14 +2554,14 @@ var makeDefaultCampUiContributions = (tui, detailBlocks) => [
|
|
|
2010
2554
|
mount: (context) => succeed2(makeCampUiCampHeader(context))
|
|
2011
2555
|
},
|
|
2012
2556
|
{
|
|
2013
|
-
id: "default-
|
|
2014
|
-
slotId: CampUiSlot.
|
|
2015
|
-
mount: (context) => succeed2(
|
|
2557
|
+
id: "default-activity",
|
|
2558
|
+
slotId: CampUiSlot.activity,
|
|
2559
|
+
mount: (context) => succeed2(makeCampUiActivity(context))
|
|
2016
2560
|
},
|
|
2017
2561
|
{
|
|
2018
|
-
id: "default-
|
|
2019
|
-
slotId: CampUiSlot.
|
|
2020
|
-
mount: (context) => succeed2(
|
|
2562
|
+
id: "default-equipment",
|
|
2563
|
+
slotId: CampUiSlot.equipment,
|
|
2564
|
+
mount: (context) => succeed2(makeCampUiEquipment(context))
|
|
2021
2565
|
},
|
|
2022
2566
|
{
|
|
2023
2567
|
id: "default-roster",
|
|
@@ -2040,29 +2584,29 @@ var makeDefaultCampUiContributions = (tui, detailBlocks) => [
|
|
|
2040
2584
|
mount: (context) => succeed2(makeCampUiComposerComponent(context, tui))
|
|
2041
2585
|
},
|
|
2042
2586
|
{
|
|
2043
|
-
id: "default-
|
|
2044
|
-
slotId: CampUiSlot.
|
|
2045
|
-
mount: (context) => succeed2(
|
|
2587
|
+
id: "default-footer",
|
|
2588
|
+
slotId: CampUiSlot.footer,
|
|
2589
|
+
mount: (context) => succeed2(makeCampUiFooter(context))
|
|
2046
2590
|
},
|
|
2047
2591
|
{
|
|
2048
|
-
id: "default-
|
|
2049
|
-
slotId: CampUiSlot.
|
|
2050
|
-
mount: (context) => succeed2(
|
|
2592
|
+
id: "default-inventory-overlay",
|
|
2593
|
+
slotId: CampUiSlot.overlay,
|
|
2594
|
+
mount: (context) => succeed2(makeCampUiResources(context))
|
|
2051
2595
|
}
|
|
2052
2596
|
];
|
|
2053
2597
|
|
|
2054
2598
|
// packages/host-ui/src/pi/layout/campUiSection.ts
|
|
2055
|
-
import { getMarkdownTheme as
|
|
2056
|
-
import { visibleWidth as
|
|
2599
|
+
import { getMarkdownTheme as getMarkdownTheme8, getSelectListTheme as getSelectListTheme14 } from "@earendil-works/pi-coding-agent";
|
|
2600
|
+
import { visibleWidth as visibleWidth6 } from "@earendil-works/pi-tui";
|
|
2057
2601
|
var renderHeader = (header, width) => {
|
|
2058
|
-
const theme =
|
|
2059
|
-
const selectTheme =
|
|
2602
|
+
const theme = getMarkdownTheme8();
|
|
2603
|
+
const selectTheme = getSelectListTheme14();
|
|
2060
2604
|
const rule2 = header.focused === true ? selectTheme.selectedPrefix : theme.codeBlockBorder;
|
|
2061
2605
|
const title = header.focused === true ? selectTheme.selectedText : theme.heading;
|
|
2062
2606
|
const ruleCharacter = header.focused === true ? "\u2501" : "\u2500";
|
|
2063
2607
|
const detail = header.detail === void 0 ? "" : ` ${selectTheme.description(header.detail)}`;
|
|
2064
2608
|
const label = `${rule2(ruleCharacter.repeat(2))} ${title(header.title)}${detail} `;
|
|
2065
|
-
const ruleWidth = Math.max(0, width -
|
|
2609
|
+
const ruleWidth = Math.max(0, width - visibleWidth6(label));
|
|
2066
2610
|
return fitCampUiLine(`${label}${rule2(ruleCharacter.repeat(ruleWidth))}`, width);
|
|
2067
2611
|
};
|
|
2068
2612
|
var makeCampUiSection = (options) => {
|
|
@@ -2074,6 +2618,7 @@ var makeCampUiSection = (options) => {
|
|
|
2074
2618
|
const disposableComponents = components.some((component) => component.dispose !== void 0);
|
|
2075
2619
|
return {
|
|
2076
2620
|
sectionSize: options.size,
|
|
2621
|
+
...options.preferredRows === void 0 ? {} : { preferredRows: options.preferredRows },
|
|
2077
2622
|
...components.some((component) => component.focusable === true) ? { focusable: true } : {},
|
|
2078
2623
|
render: (viewport) => {
|
|
2079
2624
|
if (viewport.height <= 0) {
|
|
@@ -2139,28 +2684,38 @@ var decorateDefaultCampUiSections = (context, slots) => {
|
|
|
2139
2684
|
{
|
|
2140
2685
|
component: component(CampUiSlot.campHeader),
|
|
2141
2686
|
size: { kind: CampUiSectionSizeKind.fixed, rows: 2 }
|
|
2142
|
-
},
|
|
2143
|
-
{
|
|
2144
|
-
component: component(CampUiSlot.seat),
|
|
2145
|
-
size: { kind: CampUiSectionSizeKind.grow, weight: 1, minimumRows: 1 }
|
|
2146
2687
|
}
|
|
2147
2688
|
]
|
|
2148
2689
|
})
|
|
2149
2690
|
);
|
|
2150
|
-
decorated.delete(CampUiSlot.seat);
|
|
2151
2691
|
decorated.set(
|
|
2152
|
-
CampUiSlot.
|
|
2692
|
+
CampUiSlot.activity,
|
|
2153
2693
|
makeCampUiSection({
|
|
2154
|
-
header: () => ({ title: "
|
|
2155
|
-
size:
|
|
2694
|
+
header: () => ({ title: "Activity" }),
|
|
2695
|
+
size: defaultCampUiRightSectionSizes.activity,
|
|
2156
2696
|
children: [
|
|
2157
2697
|
{
|
|
2158
|
-
component: component(CampUiSlot.
|
|
2698
|
+
component: component(CampUiSlot.activity),
|
|
2159
2699
|
size: { kind: CampUiSectionSizeKind.grow, weight: 1 }
|
|
2160
2700
|
}
|
|
2161
2701
|
]
|
|
2162
2702
|
})
|
|
2163
2703
|
);
|
|
2704
|
+
const equipment = component(CampUiSlot.equipment);
|
|
2705
|
+
decorated.set(
|
|
2706
|
+
CampUiSlot.equipment,
|
|
2707
|
+
makeCampUiSection({
|
|
2708
|
+
header: () => ({ title: "Equipment" }),
|
|
2709
|
+
size: defaultCampUiRightSectionSizes.equipment,
|
|
2710
|
+
children: [
|
|
2711
|
+
{
|
|
2712
|
+
component: equipment,
|
|
2713
|
+
size: { kind: CampUiSectionSizeKind.grow, weight: 1 }
|
|
2714
|
+
}
|
|
2715
|
+
],
|
|
2716
|
+
preferredRows: (width) => 1 + (equipment.preferredRows?.(width) ?? defaultCampUiRightSectionSizes.equipment.rows - 1)
|
|
2717
|
+
})
|
|
2718
|
+
);
|
|
2164
2719
|
decorated.set(
|
|
2165
2720
|
CampUiSlot.roster,
|
|
2166
2721
|
makeCampUiSection({
|
|
@@ -2186,7 +2741,7 @@ import { initTheme } from "@earendil-works/pi-coding-agent";
|
|
|
2186
2741
|
import { ProcessTerminal, TUI } from "@earendil-works/pi-tui";
|
|
2187
2742
|
|
|
2188
2743
|
// packages/host-ui/src/pi/piCampUiRoot.ts
|
|
2189
|
-
import { getMarkdownTheme as
|
|
2744
|
+
import { getMarkdownTheme as getMarkdownTheme9 } from "@earendil-works/pi-coding-agent";
|
|
2190
2745
|
import { Key as Key3, matchesKey as matchesKey3 } from "@earendil-works/pi-tui";
|
|
2191
2746
|
|
|
2192
2747
|
// packages/host-ui/src/pi/runtime/campUiPointerInput.ts
|
|
@@ -2315,7 +2870,7 @@ var PiCampUiRoot = class {
|
|
|
2315
2870
|
segments.push({
|
|
2316
2871
|
x: divider.x,
|
|
2317
2872
|
width: 1,
|
|
2318
|
-
text:
|
|
2873
|
+
text: getMarkdownTheme9().codeBlockBorder("\u2502")
|
|
2319
2874
|
});
|
|
2320
2875
|
}
|
|
2321
2876
|
}
|
|
@@ -2362,6 +2917,14 @@ var PiCampUiRoot = class {
|
|
|
2362
2917
|
if (focusedSlotId !== model.state.focusedSlotId) {
|
|
2363
2918
|
this.context.emit(CampUiIntents.FocusSlot({ slotId: focusedSlotId }));
|
|
2364
2919
|
}
|
|
2920
|
+
if (model.state.inventoryVisible && matchesKey3(input, Key3.escape)) {
|
|
2921
|
+
this.context.emit(CampUiIntents.SetInventoryVisible({ visible: false }));
|
|
2922
|
+
return;
|
|
2923
|
+
}
|
|
2924
|
+
if (focusedSlotId !== CampUiSlot.composer && input === "i") {
|
|
2925
|
+
this.context.emit(CampUiIntents.SetInventoryVisible({ visible: true }));
|
|
2926
|
+
return;
|
|
2927
|
+
}
|
|
2365
2928
|
if (this.slots.get(focusedSlotId)?.handleInput?.(input) === true) return;
|
|
2366
2929
|
if (matchesKey3(input, Key3.escape)) {
|
|
2367
2930
|
if (focusedSlotId === CampUiSlot.composer) {
|
|
@@ -2447,19 +3010,67 @@ var PiCampUiRoot = class {
|
|
|
2447
3010
|
}
|
|
2448
3011
|
};
|
|
2449
3012
|
|
|
3013
|
+
// packages/host-ui/src/pi/runtime/campUiFrameScheduler.ts
|
|
3014
|
+
var DEFAULT_MINIMUM_INTERVAL_MS = 1e3;
|
|
3015
|
+
var DEFAULT_MAXIMUM_INTERVAL_MS = 8e3;
|
|
3016
|
+
var DEFAULT_EXPENSIVE_FRAME_MS = 120;
|
|
3017
|
+
var CAMP_UI_REDUCED_MOTION_ENV = "PRIIISK_REDUCED_MOTION";
|
|
3018
|
+
var campUiReducedMotionFromEnv = (environment) => {
|
|
3019
|
+
const value = environment[CAMP_UI_REDUCED_MOTION_ENV]?.trim().toLowerCase();
|
|
3020
|
+
return value !== void 0 && value !== "" && value !== "0" && value !== "false";
|
|
3021
|
+
};
|
|
3022
|
+
var makeCampUiFrameScheduler = (options = {}) => gen(function* () {
|
|
3023
|
+
const minimum = Math.max(
|
|
3024
|
+
1,
|
|
3025
|
+
Math.floor(options.minimumIntervalMs ?? DEFAULT_MINIMUM_INTERVAL_MS)
|
|
3026
|
+
);
|
|
3027
|
+
const maximum = Math.max(
|
|
3028
|
+
minimum,
|
|
3029
|
+
Math.floor(options.maximumIntervalMs ?? DEFAULT_MAXIMUM_INTERVAL_MS)
|
|
3030
|
+
);
|
|
3031
|
+
const expensive = Math.max(
|
|
3032
|
+
1,
|
|
3033
|
+
Math.floor(options.expensiveFrameMs ?? DEFAULT_EXPENSIVE_FRAME_MS)
|
|
3034
|
+
);
|
|
3035
|
+
const reducedMotion = options.reducedMotion === true;
|
|
3036
|
+
const pending = yield* make(false);
|
|
3037
|
+
const interval = yield* make(minimum);
|
|
3038
|
+
return {
|
|
3039
|
+
request: reducedMotion ? _void : set(pending, true),
|
|
3040
|
+
intervalMs: get(interval),
|
|
3041
|
+
run: (frame) => reducedMotion ? never : forever(
|
|
3042
|
+
gen(function* () {
|
|
3043
|
+
yield* sleep(millis(yield* get(interval)));
|
|
3044
|
+
const requested = yield* getAndSet(pending, false);
|
|
3045
|
+
if (!requested) return;
|
|
3046
|
+
const startedAt = yield* currentTimeMillis;
|
|
3047
|
+
yield* frame;
|
|
3048
|
+
const cost = (yield* currentTimeMillis) - startedAt;
|
|
3049
|
+
yield* update(
|
|
3050
|
+
interval,
|
|
3051
|
+
(current) => cost > expensive ? Math.min(maximum, current * 2) : Math.max(minimum, Math.floor(current / 2))
|
|
3052
|
+
);
|
|
3053
|
+
})
|
|
3054
|
+
)
|
|
3055
|
+
};
|
|
3056
|
+
});
|
|
3057
|
+
|
|
2450
3058
|
// packages/host-ui/src/pi/runtime/campUiPresentationClock.ts
|
|
2451
3059
|
var hasPendingCampUiAsk = (model) => model.snapshot.workers.some(
|
|
2452
3060
|
(worker) => worker.asks.some((ask) => ask.state === CampAskState.pending)
|
|
2453
3061
|
);
|
|
2454
|
-
var runCampUiPresentationClock = (readModel, controller) =>
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
3062
|
+
var runCampUiPresentationClock = (readModel, controller, scheduler) => gen(function* () {
|
|
3063
|
+
const frames = scheduler ?? (yield* makeCampUiFrameScheduler({
|
|
3064
|
+
reducedMotion: campUiReducedMotionFromEnv(process.env)
|
|
3065
|
+
}));
|
|
3066
|
+
const advance = suspend(
|
|
3067
|
+
() => hasPendingCampUiAsk(readModel()) ? currentTimeMillis.pipe(flatMap(controller.setPresentationNow)) : _void
|
|
3068
|
+
);
|
|
3069
|
+
return yield* zipRight(
|
|
3070
|
+
frames.request,
|
|
3071
|
+
frames.run(zipRight(advance, frames.request))
|
|
3072
|
+
);
|
|
3073
|
+
});
|
|
2463
3074
|
|
|
2464
3075
|
// packages/host-ui/src/pi/runtime/campUiSubscriptionRetry.ts
|
|
2465
3076
|
var CAMP_UI_SUBSCRIPTION_MAX_RETRIES = 4;
|
|
@@ -2515,16 +3126,16 @@ var makeCampUiTerminalModes = (terminal) => {
|
|
|
2515
3126
|
var closedOnPurpose = (exit) => isSuccess(exit) || isInterruptedOnly(exit.cause);
|
|
2516
3127
|
var mountPiCampUi = (options) => gen(function* () {
|
|
2517
3128
|
const startedAt = yield* currentTimeMillis;
|
|
2518
|
-
const healthRef = yield*
|
|
3129
|
+
const healthRef = yield* make4({
|
|
2519
3130
|
status: CampUiRuntimeStatus.starting,
|
|
2520
3131
|
operation: "ui.mount",
|
|
2521
3132
|
updatedAt: startedAt
|
|
2522
3133
|
});
|
|
2523
|
-
const setHealth = (health) =>
|
|
3134
|
+
const setHealth = (health) => get2(healthRef).pipe(
|
|
2524
3135
|
flatMap(
|
|
2525
3136
|
(current2) => sameCampUiRuntimeHealth(current2, { ...health, updatedAt: current2.updatedAt }) ? _void : currentTimeMillis.pipe(
|
|
2526
3137
|
flatMap(
|
|
2527
|
-
(updatedAt) =>
|
|
3138
|
+
(updatedAt) => set2(healthRef, { ...health, updatedAt })
|
|
2528
3139
|
)
|
|
2529
3140
|
)
|
|
2530
3141
|
)
|
|
@@ -2577,6 +3188,22 @@ var mountPiCampUi = (options) => gen(function* () {
|
|
|
2577
3188
|
);
|
|
2578
3189
|
tui.addChild(root);
|
|
2579
3190
|
tui.setFocus(root);
|
|
3191
|
+
const inventory = slots.get(CampUiSlot.overlay);
|
|
3192
|
+
const inventoryOverlay = inventory === void 0 ? void 0 : tui.showOverlay(
|
|
3193
|
+
{
|
|
3194
|
+
render: (width) => [
|
|
3195
|
+
...inventory.render({ width, height: Math.max(0, terminal.rows) })
|
|
3196
|
+
],
|
|
3197
|
+
invalidate: () => inventory.invalidate?.()
|
|
3198
|
+
},
|
|
3199
|
+
{
|
|
3200
|
+
width: "60%",
|
|
3201
|
+
minWidth: 36,
|
|
3202
|
+
margin: 1,
|
|
3203
|
+
visible: () => current.state.inventoryVisible,
|
|
3204
|
+
nonCapturing: true
|
|
3205
|
+
}
|
|
3206
|
+
);
|
|
2580
3207
|
yield* sync(() => {
|
|
2581
3208
|
terminal.setTitle(initial.displayName);
|
|
2582
3209
|
terminal.clearScreen();
|
|
@@ -2593,6 +3220,9 @@ var mountPiCampUi = (options) => gen(function* () {
|
|
|
2593
3220
|
)
|
|
2594
3221
|
)
|
|
2595
3222
|
);
|
|
3223
|
+
if (inventoryOverlay !== void 0) {
|
|
3224
|
+
yield* addFinalizer(() => sync(() => inventoryOverlay.hide()));
|
|
3225
|
+
}
|
|
2596
3226
|
yield* forkScoped(
|
|
2597
3227
|
gen(function* () {
|
|
2598
3228
|
for (let attempt = 0; attempt < 25; attempt += 1) {
|
|
@@ -2601,7 +3231,7 @@ var mountPiCampUi = (options) => gen(function* () {
|
|
|
2601
3231
|
}
|
|
2602
3232
|
})
|
|
2603
3233
|
);
|
|
2604
|
-
const fibers = yield*
|
|
3234
|
+
const fibers = yield* make3();
|
|
2605
3235
|
yield* run(
|
|
2606
3236
|
fibers,
|
|
2607
3237
|
store.changes.pipe(
|
|
@@ -2665,12 +3295,12 @@ var mountPiCampUi = (options) => gen(function* () {
|
|
|
2665
3295
|
return {
|
|
2666
3296
|
controller: store.controller,
|
|
2667
3297
|
tui,
|
|
2668
|
-
health: { current:
|
|
3298
|
+
health: { current: get2(healthRef), changes: healthRef.changes }
|
|
2669
3299
|
};
|
|
2670
3300
|
});
|
|
2671
3301
|
|
|
2672
3302
|
// packages/host-ui/src/pi/run-selector/campRunSelector.ts
|
|
2673
|
-
import { getMarkdownTheme as
|
|
3303
|
+
import { getMarkdownTheme as getMarkdownTheme10, getSelectListTheme as getSelectListTheme15, initTheme as initTheme2 } from "@earendil-works/pi-coding-agent";
|
|
2674
3304
|
import {
|
|
2675
3305
|
Key as Key4,
|
|
2676
3306
|
matchesKey as matchesKey4,
|
|
@@ -2692,8 +3322,8 @@ var PiCampRunSelectorRoot = class {
|
|
|
2692
3322
|
render(width) {
|
|
2693
3323
|
const height = Math.max(0, this.getHeight());
|
|
2694
3324
|
const viewportWidth = Math.max(0, width - 1);
|
|
2695
|
-
const markdown =
|
|
2696
|
-
const selection =
|
|
3325
|
+
const markdown = getMarkdownTheme10();
|
|
3326
|
+
const selection = getSelectListTheme15();
|
|
2697
3327
|
const header = `${markdown.codeBlockBorder("\u2500\u2500")} ${markdown.heading("Resume camp")} ${markdown.codeBlockBorder("\u2500".repeat(Math.max(0, viewportWidth - 16)))}`;
|
|
2698
3328
|
const available = Math.max(0, height - 2);
|
|
2699
3329
|
const capacity = Math.max(1, Math.floor(available / 2));
|
|
@@ -2702,7 +3332,7 @@ var PiCampRunSelectorRoot = class {
|
|
|
2702
3332
|
Math.max(0, this.items.length - capacity)
|
|
2703
3333
|
);
|
|
2704
3334
|
const visibleItems = this.items.slice(start, start + capacity);
|
|
2705
|
-
const
|
|
3335
|
+
const rows = visibleItems.flatMap((item, index) => {
|
|
2706
3336
|
const selected = start + index === this.selectedIndex;
|
|
2707
3337
|
const prefix = selected ? selection.selectedPrefix("\u25CF ") : " ";
|
|
2708
3338
|
const title = selected ? selection.selectedText(item.runId) : item.runId;
|
|
@@ -2714,7 +3344,7 @@ var PiCampRunSelectorRoot = class {
|
|
|
2714
3344
|
fitCampUiLine(` ${details}`, viewportWidth)
|
|
2715
3345
|
];
|
|
2716
3346
|
});
|
|
2717
|
-
const content = [fitCampUiLine(header, viewportWidth), "", ...
|
|
3347
|
+
const content = [fitCampUiLine(header, viewportWidth), "", ...rows].slice(0, height);
|
|
2718
3348
|
return [...content, ...Array.from({ length: Math.max(0, height - content.length) }, () => "")];
|
|
2719
3349
|
}
|
|
2720
3350
|
handleInput(input) {
|
|
@@ -2737,7 +3367,7 @@ var PiCampRunSelectorRoot = class {
|
|
|
2737
3367
|
var selectCampRun = (options) => scoped(
|
|
2738
3368
|
gen(function* () {
|
|
2739
3369
|
yield* sync(() => initTheme2(void 0, false));
|
|
2740
|
-
const selected = yield*
|
|
3370
|
+
const selected = yield* make2();
|
|
2741
3371
|
const terminal = options.terminal ?? new ProcessTerminal2();
|
|
2742
3372
|
const modes = makeCampUiTerminalModes(terminal);
|
|
2743
3373
|
yield* acquireRelease(
|
|
@@ -2771,12 +3401,15 @@ var selectCampRun = (options) => scoped(
|
|
|
2771
3401
|
// packages/host-ui/src/index.ts
|
|
2772
3402
|
var PACKAGE = "@priiisk/host-ui";
|
|
2773
3403
|
export {
|
|
3404
|
+
CAMP_UI_ACTIVITY_MAX_VISIBLE_PATHS,
|
|
2774
3405
|
CAMP_UI_BASH_PREVIEW_LINES,
|
|
2775
3406
|
CAMP_UI_DEFAULT_TOOL_PREVIEW_LINES,
|
|
2776
3407
|
CAMP_UI_EXPLORED_COLLAPSED_PATHS,
|
|
2777
3408
|
CAMP_UI_EXPLORED_TOOL_NAMES,
|
|
3409
|
+
CAMP_UI_REDUCED_MOTION_ENV,
|
|
2778
3410
|
CAMP_UI_SUBSCRIPTION_BASE_DELAY_MS,
|
|
2779
3411
|
CAMP_UI_SUBSCRIPTION_MAX_RETRIES,
|
|
3412
|
+
CampUiActivityAccess,
|
|
2780
3413
|
CampUiAssistantMessage,
|
|
2781
3414
|
CampUiBackend,
|
|
2782
3415
|
CampUiBackendError,
|
|
@@ -2795,24 +3428,29 @@ export {
|
|
|
2795
3428
|
CampUiSectionSizeKind,
|
|
2796
3429
|
CampUiSlot,
|
|
2797
3430
|
CampUiTone,
|
|
3431
|
+
CampUiTrackSizeKind,
|
|
2798
3432
|
DEFAULT_DIRECTED_BLOCK_BODY_LINES,
|
|
2799
3433
|
PACKAGE,
|
|
2800
3434
|
PiCampRunSelectorRoot,
|
|
2801
3435
|
PiCampUiRoot,
|
|
2802
3436
|
allocateCampUiSectionRows,
|
|
3437
|
+
allocateCampUiTrackColumns,
|
|
2803
3438
|
cachedCampUiBlock,
|
|
2804
3439
|
campUiAskBlockId,
|
|
3440
|
+
campUiAskDetailBlock,
|
|
2805
3441
|
campUiBlockCacheSize,
|
|
2806
|
-
campUiEquipmentBlockRenderer,
|
|
2807
3442
|
campUiExploredReadPath,
|
|
2808
3443
|
campUiExploredReadRange,
|
|
2809
3444
|
campUiMessageSignature,
|
|
2810
3445
|
campUiPendingAskBlockRenderer,
|
|
2811
3446
|
campUiPendingAskTargets,
|
|
3447
|
+
campUiReducedMotionFromEnv,
|
|
2812
3448
|
campUiResultSignature,
|
|
2813
3449
|
campUiSubscriptionRetryDelay,
|
|
2814
3450
|
campUiToolResultCacheSize,
|
|
2815
3451
|
campUiTranscriptBlockRenderer,
|
|
3452
|
+
campUiWorkerStateLabel,
|
|
3453
|
+
collectCampUiActivityTree,
|
|
2816
3454
|
compactNumber,
|
|
2817
3455
|
composeCampUiDetailBlocks,
|
|
2818
3456
|
composeCampUiSlots,
|
|
@@ -2820,6 +3458,7 @@ export {
|
|
|
2820
3458
|
defaultCampUiDetailBlockRenderers,
|
|
2821
3459
|
defaultCampUiLayoutPolicy,
|
|
2822
3460
|
defaultCampUiLeftSectionSizes,
|
|
3461
|
+
defaultCampUiRightSectionSizes,
|
|
2823
3462
|
emptyCampUiComponent,
|
|
2824
3463
|
findCampUiSpatialFocusTarget,
|
|
2825
3464
|
findCampUiWorker,
|
|
@@ -2829,14 +3468,19 @@ export {
|
|
|
2829
3468
|
hasCampUiTextContent,
|
|
2830
3469
|
hasPendingCampUiAsk,
|
|
2831
3470
|
isCampUiExploredTool,
|
|
3471
|
+
isCampUiPendingAsk,
|
|
2832
3472
|
joinCampUiColumns,
|
|
2833
3473
|
jsonText,
|
|
3474
|
+
makeCampUiActivity,
|
|
2834
3475
|
makeCampUiComponentGroup,
|
|
2835
3476
|
makeCampUiComposerComponent,
|
|
2836
3477
|
makeCampUiDetailComponent,
|
|
3478
|
+
makeCampUiEquipment,
|
|
3479
|
+
makeCampUiFrameScheduler,
|
|
2837
3480
|
makeCampUiIntentHandler,
|
|
2838
3481
|
makeCampUiIntentRouter,
|
|
2839
3482
|
makeCampUiModel,
|
|
3483
|
+
makeCampUiResources,
|
|
2840
3484
|
makeCampUiSection,
|
|
2841
3485
|
makeCampUiStore,
|
|
2842
3486
|
makeDefaultCampUiContributions,
|
|
@@ -2844,9 +3488,11 @@ export {
|
|
|
2844
3488
|
makeInitialCampUiState,
|
|
2845
3489
|
mountPiCampUi,
|
|
2846
3490
|
nextCampUiPendingAskTarget,
|
|
3491
|
+
renderCampUiActivityTree,
|
|
2847
3492
|
renderCampUiDetailBlockLayout,
|
|
2848
3493
|
renderCampUiDetailBlocks,
|
|
2849
3494
|
renderCampUiDirectedBlock,
|
|
3495
|
+
renderCampUiEquipment,
|
|
2850
3496
|
renderCampUiExploredGroup,
|
|
2851
3497
|
renderCampUiPanel,
|
|
2852
3498
|
renderCampUiState,
|