@paradow/ledge 0.33.0 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/{action-QW2ZQQBN.js → action-K42H5BDA.js} +5 -5
- package/dist/cli/{attach-ULTYWCJ7.js → attach-KEE4A5YP.js} +28 -15
- package/dist/cli/{bridge-CSLF7EW6.js → bridge-X327AZY4.js} +2 -2
- package/dist/cli/{chunk-3DB3VOMM.js → chunk-25RVT5MR.js} +3 -103
- package/dist/cli/{chunk-GXL3X7M7.js → chunk-3OJCWJAA.js} +2 -2
- package/dist/cli/chunk-4OYVM4MT.js +49 -0
- package/dist/cli/{chunk-JEGPTNWV.js → chunk-4TCSADFR.js} +5 -23
- package/dist/cli/{chunk-HOOHS3MX.js → chunk-53ISXX2R.js} +1 -1
- package/dist/cli/{chunk-6IYPRUQG.js → chunk-54KF5RBY.js} +1 -1
- package/dist/cli/{chunk-ASYAWVFW.js → chunk-7NHQGP6J.js} +1 -1
- package/dist/cli/{chunk-4HXJQEUN.js → chunk-G7XPEVCG.js} +5 -5
- package/dist/cli/{chunk-WXE2NOE5.js → chunk-IWY7DSSO.js} +835 -1033
- package/dist/cli/{chunk-CSLVBADC.js → chunk-KPDTYX7F.js} +3 -3
- package/dist/cli/chunk-RPH773TY.js +6 -0
- package/dist/cli/{chunk-CCSUP5ZI.js → chunk-RX5CJ7YH.js} +3 -5
- package/dist/cli/{chunk-NLL2EQJ2.js → chunk-T547FLQN.js} +38 -4
- package/dist/cli/{chunk-K7UEKSB2.js → chunk-UJ2WBGLW.js} +2 -2
- package/dist/cli/{chunk-XOZD4BP5.js → chunk-ULOMKEB6.js} +4 -4
- package/dist/cli/{chunk-CPERVAPQ.js → chunk-V4XKKL6K.js} +13 -40
- package/dist/cli/{chunk-PZ3F4QH3.js → daemon-RO43S3S5.js} +4655 -2964
- package/dist/cli/{decide-PFHHOCFZ.js → decide-KZFYL3HY.js} +5 -5
- package/dist/cli/{handover-EMO6JT7O.js → handover-BWNMI2RA.js} +5 -5
- package/dist/cli/{hook-W2BU74H5.js → hook-ZLWXI5EQ.js} +21 -71
- package/dist/cli/index.js +18 -25
- package/dist/cli/launch-GCX7TXOH.js +28 -0
- package/dist/cli/{send-NEI4X33R.js → send-SXZAPVRH.js} +5 -5
- package/dist/cli/{setup-K42IVMHS.js → setup-TJ32FMVJ.js} +4 -4
- package/dist/cli/{status-U2HGGKHF.js → status-YDVRES4E.js} +3 -3
- package/dist/cli/{task-PDDCE23D.js → task-TUSOVJK7.js} +5 -5
- package/dist/cli/{tui-UPMRMCPC.js → tui-TCVIRZCQ.js} +1401 -1269
- package/dist/cli/{uninstall-4IMMR55T.js → uninstall-QO7YMSLA.js} +4 -4
- package/dist/cli/{version-LUMK3Z3T.js → version-BAYSYWFP.js} +1 -1
- package/dist/cli/who-6AZYSP7T.js +12 -0
- package/dist/ledge-guide.md +26 -49
- package/package.json +2 -1
- package/dist/cli/chunk-4VNKZOC2.js +0 -160
- package/dist/cli/chunk-E3LXONBI.js +0 -6
- package/dist/cli/chunk-NWIICISV.js +0 -290
- package/dist/cli/daemon-5GT545BB.js +0 -2322
- package/dist/cli/launch-LP7YJR5N.js +0 -36
- package/dist/cli/team-S3ASP22H.js +0 -205
- package/dist/cli/who-NM3GPAPJ.js +0 -12
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
attachEnv
|
|
3
|
-
} from "./chunk-CPERVAPQ.js";
|
|
4
1
|
import {
|
|
5
2
|
imageInfo
|
|
6
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-4OYVM4MT.js";
|
|
4
|
+
import {
|
|
5
|
+
attachEnv
|
|
6
|
+
} from "./chunk-V4XKKL6K.js";
|
|
7
7
|
import {
|
|
8
8
|
MAX_FRAME
|
|
9
9
|
} from "./chunk-OLLQBK6N.js";
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-4VNKZOC2.js";
|
|
13
|
-
import "./chunk-JEGPTNWV.js";
|
|
14
|
-
import "./chunk-ASYAWVFW.js";
|
|
10
|
+
import "./chunk-4TCSADFR.js";
|
|
11
|
+
import "./chunk-7NHQGP6J.js";
|
|
15
12
|
import {
|
|
16
13
|
ACTION_ERROR_CODES,
|
|
17
14
|
ATTACHMENTS_MAX,
|
|
@@ -22,6 +19,7 @@ import {
|
|
|
22
19
|
ChatTurnSchema,
|
|
23
20
|
ContextPrefsSchema,
|
|
24
21
|
IslandPrefsSchema,
|
|
22
|
+
KERNEL_RIG,
|
|
25
23
|
LEDGE_GIVER,
|
|
26
24
|
MachinesSchema,
|
|
27
25
|
NOTE_MAX,
|
|
@@ -30,7 +28,7 @@ import {
|
|
|
30
28
|
PROJECT_COLORS,
|
|
31
29
|
PROTOCOL_PORT,
|
|
32
30
|
ProjectsSchema,
|
|
33
|
-
|
|
31
|
+
RIG_POLICIES,
|
|
34
32
|
backendOf,
|
|
35
33
|
contextNear,
|
|
36
34
|
isArchived,
|
|
@@ -42,15 +40,18 @@ import {
|
|
|
42
40
|
projectOf,
|
|
43
41
|
proposalRows,
|
|
44
42
|
readDaemonToken,
|
|
43
|
+
rigCommands,
|
|
44
|
+
seatPlan,
|
|
45
|
+
seatsByRole,
|
|
46
|
+
showRigCommand,
|
|
45
47
|
taskClosed,
|
|
46
48
|
transmissions
|
|
47
|
-
} from "./chunk-
|
|
48
|
-
import "./chunk-
|
|
49
|
-
import "./chunk-
|
|
50
|
-
import "./chunk-6IYPRUQG.js";
|
|
49
|
+
} from "./chunk-IWY7DSSO.js";
|
|
50
|
+
import "./chunk-T547FLQN.js";
|
|
51
|
+
import "./chunk-54KF5RBY.js";
|
|
51
52
|
import {
|
|
52
53
|
ledgeDir
|
|
53
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-53ISXX2R.js";
|
|
54
55
|
import {
|
|
55
56
|
__commonJS,
|
|
56
57
|
__export,
|
|
@@ -346,7 +347,7 @@ var daemonStore = {
|
|
|
346
347
|
return;
|
|
347
348
|
}
|
|
348
349
|
if (m.type === "chat.step" || m.type === "chat.delta" || m.type === "chat.done" || m.type === "chat.error") {
|
|
349
|
-
const chat = state.chat.map((t) => t.qid !== m.qid ? t : m.type === "chat.step" ? { ...t, steps: [...t.steps, m.step] } : m.type === "chat.done" ? { ...t, answer: m.text, answeredAt: m.at, ...m.proposal ? { proposal: m.proposal } : {}, ...m.proposals ? { proposals: m.proposals } : {}, ...m.relay ? { relay: m.relay } : {}, ...m.closes ? { closes: m.closes } : {}, ...m.projectProposal ? { projectProposal: m.projectProposal } : {}, ...m.
|
|
350
|
+
const chat = state.chat.map((t) => t.qid !== m.qid ? t : m.type === "chat.step" ? { ...t, steps: [...t.steps, m.step] } : m.type === "chat.done" ? { ...t, answer: m.text, answeredAt: m.at, ...m.proposal ? { proposal: m.proposal } : {}, ...m.proposals ? { proposals: m.proposals } : {}, ...m.relay ? { relay: m.relay } : {}, ...m.closes ? { closes: m.closes } : {}, ...m.projectProposal ? { projectProposal: m.projectProposal } : {}, ...m.tasks ? { tasks: m.tasks } : {}, ...m.actions ? { actions: m.actions } : {} } : m.type === "chat.error" ? { ...t, error: m.message } : t);
|
|
350
351
|
const chatLive = m.type === "chat.delta" ? { qid: m.qid, text: (state.chatLive?.qid === m.qid ? state.chatLive.text : "") + m.text } : m.type === "chat.step" ? state.chatLive : null;
|
|
351
352
|
state = { ...state, chat, chatLive };
|
|
352
353
|
emit();
|
|
@@ -542,9 +543,6 @@ function useMachines(client) {
|
|
|
542
543
|
var nullSnapshot = () => null;
|
|
543
544
|
var noTasks = [];
|
|
544
545
|
var emptyTasks = () => noTasks;
|
|
545
|
-
function useTeams(client) {
|
|
546
|
-
return useSyncExternalStore3(client.fleet?.subscribe ?? noopSubscribe, client.fleet?.teams ?? nullSnapshot, nullSnapshot);
|
|
547
|
-
}
|
|
548
546
|
var defaultNear = () => CONTEXT_NEAR;
|
|
549
547
|
function useContextNear(client) {
|
|
550
548
|
return useSyncExternalStore3(client.fleet?.subscribe ?? noopSubscribe, () => client.fleet?.contextNear() ?? CONTEXT_NEAR, defaultNear);
|
|
@@ -591,7 +589,14 @@ function createFleetClient(config, makeClient = createDaemonClient, opts = {}) {
|
|
|
591
589
|
const scans = /* @__PURE__ */ new Map();
|
|
592
590
|
const attachmentAsks = /* @__PURE__ */ new Map();
|
|
593
591
|
const modelLists = /* @__PURE__ */ new Map();
|
|
594
|
-
const
|
|
592
|
+
const rigFailure = (kind, requestId, machineId, error) => kind === "act" ? { type: "openrig.done", requestId, machineId, ok: false, commands: [], error } : kind === "specs" ? { type: "openrig.specList", requestId, machineId, specs: [], error } : kind === "launch" ? { type: "openrig.launched", requestId, machineId, ok: false, plan: false, commands: [], error } : kind === "seats" ? { type: "openrig.reseated", requestId, machineId, ok: false, commands: [], added: [], removed: [], error } : { type: "openrig.state", requestId, machineId, error };
|
|
593
|
+
const rigAsks = /* @__PURE__ */ new Map();
|
|
594
|
+
const answerFailedRigs = (machine, error) => {
|
|
595
|
+
for (const [requestId, a] of rigAsks) if (a.machine === machine) {
|
|
596
|
+
rigAsks.delete(requestId);
|
|
597
|
+
emit2(rigFailure(a.kind, requestId, machine, error));
|
|
598
|
+
}
|
|
599
|
+
};
|
|
595
600
|
const operations = /* @__PURE__ */ new Map();
|
|
596
601
|
const closeRows = /* @__PURE__ */ new Map();
|
|
597
602
|
const endOperation = (machine) => {
|
|
@@ -625,25 +630,17 @@ function createFleetClient(config, makeClient = createDaemonClient, opts = {}) {
|
|
|
625
630
|
emit2({ type: "models.listing", requestId, tool: l.tool, models: [], error });
|
|
626
631
|
}
|
|
627
632
|
};
|
|
628
|
-
const answerFailedRoles = (machine, error) => {
|
|
629
|
-
for (const [requestId, owner] of roleLists) if (owner === machine) {
|
|
630
|
-
roleLists.delete(requestId);
|
|
631
|
-
emit2({ type: "roles.listing", requestId, roles: [], templates: [], problems: [], error });
|
|
632
|
-
}
|
|
633
|
-
};
|
|
634
633
|
let source2 = "local";
|
|
635
634
|
let projects = null;
|
|
636
635
|
let island;
|
|
637
636
|
let contextNear2;
|
|
638
637
|
let mobile;
|
|
639
638
|
let mobileError;
|
|
640
|
-
let teams = null;
|
|
641
639
|
let tasks = /* @__PURE__ */ new Map();
|
|
642
640
|
let taskList = [];
|
|
643
641
|
const taskLists = /* @__PURE__ */ new Set();
|
|
644
642
|
let listSeq = 0;
|
|
645
643
|
const local = (id) => id === LEDGE_GIVER ? id : qualify("local", id);
|
|
646
|
-
const teamOut = (t) => ({ ...t, seats: t.seats.map((s) => ({ ...s, sessionId: s.sessionId === null ? null : qualify("local", s.sessionId) })) });
|
|
647
644
|
const taskOut = (t) => ({
|
|
648
645
|
...t,
|
|
649
646
|
giver: local(t.giver),
|
|
@@ -655,14 +652,15 @@ function createFleetClient(config, makeClient = createDaemonClient, opts = {}) {
|
|
|
655
652
|
taskList = [...tasks.values()].sort((a, b2) => a.at.localeCompare(b2.at));
|
|
656
653
|
listeners2.forEach((fn) => fn());
|
|
657
654
|
};
|
|
655
|
+
const knowsTasks = (version) => {
|
|
656
|
+
const [major = 0, minor = 0] = (version ?? "").split(".").map(Number);
|
|
657
|
+
return major > 0 || minor >= 17;
|
|
658
|
+
};
|
|
658
659
|
const askTasks = (p) => {
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
};
|
|
664
|
-
ask2({});
|
|
665
|
-
for (const t of teams ?? []) if (t.state !== "dissolved") ask2({ team: t.id });
|
|
660
|
+
if (!knowsTasks(p.snapshot?.daemon?.version)) return;
|
|
661
|
+
const rid = `fleet-tasks-${++listSeq}`;
|
|
662
|
+
taskLists.add(rid);
|
|
663
|
+
p.client.send({ type: "task.cmd", rid, by: LEDGE_GIVER, op: "list", all: true });
|
|
666
664
|
};
|
|
667
665
|
let routing = null, resetAt = "", lastStatus = "connecting";
|
|
668
666
|
const emit2 = (m) => messages.forEach((fn) => fn(m));
|
|
@@ -715,10 +713,10 @@ function createFleetClient(config, makeClient = createDaemonClient, opts = {}) {
|
|
|
715
713
|
const p = peers.get(c.id);
|
|
716
714
|
return { ...c, status: p.status, ready: available(p), recents: p.snapshot?.recents ?? [], sessions: stateSessions(p), launcher: p.snapshot?.launcher ?? null, version: p.snapshot?.daemon?.version, daemon: p.snapshot?.daemon, error: p.error };
|
|
717
715
|
});
|
|
718
|
-
const
|
|
719
|
-
if (
|
|
720
|
-
lastStatus =
|
|
721
|
-
statuses.forEach((fn) => fn(
|
|
716
|
+
const next3 = status();
|
|
717
|
+
if (next3 !== lastStatus) {
|
|
718
|
+
lastStatus = next3;
|
|
719
|
+
statuses.forEach((fn) => fn(next3));
|
|
722
720
|
}
|
|
723
721
|
listeners2.forEach((fn) => fn());
|
|
724
722
|
}
|
|
@@ -731,10 +729,10 @@ function createFleetClient(config, makeClient = createDaemonClient, opts = {}) {
|
|
|
731
729
|
const primary = peers.get("local")?.snapshot;
|
|
732
730
|
emit2({ type: "snapshot", sessions: [...peers.values()].filter((p) => available(p) || stale(p)).flatMap((p) => p.snapshot.sessions.map((s) => session(p, s))), recents: available(peers.get(selected)) ? peers.get(selected).snapshot.recents : [], launcher: primary?.launcher, daemon: primary?.daemon });
|
|
733
731
|
for (const p of peers.values()) if (available(p) || stale(p)) for (const [id, lines] of p.previews) emit2({ type: "session.preview", id: qualify(p.config.id, id), lines });
|
|
734
|
-
const
|
|
735
|
-
if (
|
|
736
|
-
lastStatus =
|
|
737
|
-
statuses.forEach((fn) => fn(
|
|
732
|
+
const next3 = status();
|
|
733
|
+
if (next3 !== lastStatus) {
|
|
734
|
+
lastStatus = next3;
|
|
735
|
+
statuses.forEach((fn) => fn(next3));
|
|
738
736
|
}
|
|
739
737
|
listeners2.forEach((fn) => fn());
|
|
740
738
|
}
|
|
@@ -765,14 +763,14 @@ function createFleetClient(config, makeClient = createDaemonClient, opts = {}) {
|
|
|
765
763
|
...raw.actions ? { actions: raw.actions.map((a) => ({ ...a, ...a.session ? { session: qualify(p.config.id, a.session) } : {} })) } : {}
|
|
766
764
|
};
|
|
767
765
|
}
|
|
768
|
-
function apply(
|
|
766
|
+
function apply(next3) {
|
|
769
767
|
configuring = true;
|
|
770
|
-
for (const [id, p] of peers) if (!
|
|
768
|
+
for (const [id, p] of peers) if (!next3.some((c) => !c.disabled && c.id === id && c.url === p.config.url && c.ssh === p.config.ssh)) {
|
|
771
769
|
p.client.close();
|
|
772
770
|
p.off.forEach((off) => off());
|
|
773
771
|
peers.delete(id);
|
|
774
772
|
}
|
|
775
|
-
configs =
|
|
773
|
+
configs = next3;
|
|
776
774
|
for (const c of active()) {
|
|
777
775
|
const p = peers.get(c.id);
|
|
778
776
|
if (p) p.config = c;
|
|
@@ -789,15 +787,15 @@ function createFleetClient(config, makeClient = createDaemonClient, opts = {}) {
|
|
|
789
787
|
const machine = p.config.id;
|
|
790
788
|
if (m.type === "machines") {
|
|
791
789
|
if (machine !== "local" || !opts.machinesFromDaemon) return;
|
|
792
|
-
let
|
|
790
|
+
let next3;
|
|
793
791
|
try {
|
|
794
|
-
|
|
792
|
+
next3 = parseMachines(m.machines);
|
|
795
793
|
} catch {
|
|
796
794
|
return;
|
|
797
795
|
}
|
|
798
|
-
const mine =
|
|
796
|
+
const mine = next3.length === 1 ? loadMachines(prefix) : [];
|
|
799
797
|
source2 = "daemon";
|
|
800
|
-
if (
|
|
798
|
+
if (next3.length === 1 && mine.length > 1) {
|
|
801
799
|
p.client.send({ type: "machines.set", machines: toWire(mine) });
|
|
802
800
|
return;
|
|
803
801
|
}
|
|
@@ -805,7 +803,7 @@ function createFleetClient(config, makeClient = createDaemonClient, opts = {}) {
|
|
|
805
803
|
localStorage.removeItem(MACHINES_KEY);
|
|
806
804
|
} catch {
|
|
807
805
|
}
|
|
808
|
-
apply(
|
|
806
|
+
apply(next3);
|
|
809
807
|
return;
|
|
810
808
|
}
|
|
811
809
|
if (m.type === "projects") {
|
|
@@ -826,19 +824,6 @@ function createFleetClient(config, makeClient = createDaemonClient, opts = {}) {
|
|
|
826
824
|
listeners2.forEach((fn) => fn());
|
|
827
825
|
return;
|
|
828
826
|
}
|
|
829
|
-
if (m.type === "teams" || m.type === "team.updated") {
|
|
830
|
-
if (machine !== "local") return;
|
|
831
|
-
const known2 = new Set((teams ?? []).map((t) => t.id));
|
|
832
|
-
teams = m.type === "teams" ? m.teams.map(teamOut) : [...(teams ?? []).filter((t) => t.id !== m.team.id), teamOut(m.team)].sort((a, b2) => a.createdAt.localeCompare(b2.createdAt));
|
|
833
|
-
listeners2.forEach((fn) => fn());
|
|
834
|
-
if (m.type === "team.updated" && !known2.has(m.team.id) && m.team.state !== "dissolved") {
|
|
835
|
-
const rid = `fleet-tasks-${++listSeq}`;
|
|
836
|
-
taskLists.add(rid);
|
|
837
|
-
p.client.send({ type: "task.cmd", rid, by: LEDGE_GIVER, op: "list", all: true, team: m.team.id });
|
|
838
|
-
}
|
|
839
|
-
if (m.type === "teams" && p.snapshot?.daemon?.teams) askTasks(p);
|
|
840
|
-
return;
|
|
841
|
-
}
|
|
842
827
|
if (m.type === "task.updated") {
|
|
843
828
|
if (machine === "local") putTasks([m.task]);
|
|
844
829
|
return;
|
|
@@ -871,6 +856,7 @@ function createFleetClient(config, makeClient = createDaemonClient, opts = {}) {
|
|
|
871
856
|
p.restarting = false;
|
|
872
857
|
p.previews.clear();
|
|
873
858
|
publish();
|
|
859
|
+
if (machine === "local") askTasks(p);
|
|
874
860
|
return;
|
|
875
861
|
}
|
|
876
862
|
if (m.type === "session.updated") {
|
|
@@ -960,16 +946,17 @@ function createFleetClient(config, makeClient = createDaemonClient, opts = {}) {
|
|
|
960
946
|
}
|
|
961
947
|
return;
|
|
962
948
|
}
|
|
963
|
-
if (m.type === "
|
|
964
|
-
if (
|
|
965
|
-
|
|
966
|
-
|
|
949
|
+
if (m.type === "openrig.state" || m.type === "openrig.done" || m.type === "openrig.specList" || m.type === "openrig.launched" || m.type === "openrig.reseated") {
|
|
950
|
+
if (m.requestId !== void 0) {
|
|
951
|
+
if (rigAsks.get(m.requestId)?.machine !== machine) return;
|
|
952
|
+
rigAsks.delete(m.requestId);
|
|
967
953
|
}
|
|
954
|
+
emit2({ ...m, machineId: machine });
|
|
968
955
|
return;
|
|
969
956
|
}
|
|
970
|
-
if (m.type === "
|
|
971
|
-
if (
|
|
972
|
-
|
|
957
|
+
if (m.type === "models.listing") {
|
|
958
|
+
if (modelLists.get(m.requestId)?.machine === machine) {
|
|
959
|
+
modelLists.delete(m.requestId);
|
|
973
960
|
emit2(m);
|
|
974
961
|
}
|
|
975
962
|
return;
|
|
@@ -1016,15 +1003,15 @@ function createFleetClient(config, makeClient = createDaemonClient, opts = {}) {
|
|
|
1016
1003
|
const qid = globalQid(machine, m.qid), old = turns2.get(qid);
|
|
1017
1004
|
if (!old) return;
|
|
1018
1005
|
if (m.type === "chat.done") {
|
|
1019
|
-
const raw = { ...old, qid: m.qid, answer: m.text, answeredAt: m.at, proposal: m.proposal, proposals: m.proposals, relay: m.relay, closes: m.closes, projectProposal: m.projectProposal,
|
|
1006
|
+
const raw = { ...old, qid: m.qid, answer: m.text, answeredAt: m.at, proposal: m.proposal, proposals: m.proposals, relay: m.relay, closes: m.closes, projectProposal: m.projectProposal, tasks: m.tasks, actions: m.actions };
|
|
1020
1007
|
const t = mappedTurn(p, { ...raw, steps: [] });
|
|
1021
1008
|
turns2.set(qid, { ...t, steps: old.steps });
|
|
1022
1009
|
history();
|
|
1023
1010
|
} else if (m.type === "chat.error") fail(qid, m.message);
|
|
1024
1011
|
else if (m.type === "chat.step") {
|
|
1025
|
-
const
|
|
1026
|
-
turns2.set(qid, { ...old, steps: [...old.steps,
|
|
1027
|
-
emit2({ ...m, qid, step:
|
|
1012
|
+
const step3 = { ...m.step, ...m.step.id ? { id: qualify(machine, m.step.id) } : {} };
|
|
1013
|
+
turns2.set(qid, { ...old, steps: [...old.steps, step3] });
|
|
1014
|
+
emit2({ ...m, qid, step: step3 });
|
|
1028
1015
|
} else emit2({ ...m, qid });
|
|
1029
1016
|
return;
|
|
1030
1017
|
}
|
|
@@ -1054,8 +1041,8 @@ function createFleetClient(config, makeClient = createDaemonClient, opts = {}) {
|
|
|
1054
1041
|
answerFailedModels(machine, "outdated");
|
|
1055
1042
|
return;
|
|
1056
1043
|
}
|
|
1057
|
-
if (m.request
|
|
1058
|
-
|
|
1044
|
+
if (m.request?.startsWith("openrig.")) {
|
|
1045
|
+
answerFailedRigs(machine, "outdated");
|
|
1059
1046
|
return;
|
|
1060
1047
|
}
|
|
1061
1048
|
if ((m.request === "folder.list" || m.request === "folder.create") && [...listings.values()].some((l) => l.machine === machine)) {
|
|
@@ -1091,7 +1078,7 @@ function createFleetClient(config, makeClient = createDaemonClient, opts = {}) {
|
|
|
1091
1078
|
answerUnfoundListings(c.id, "offline");
|
|
1092
1079
|
answerFailedScans(c.id, "offline");
|
|
1093
1080
|
answerFailedModels(c.id, "offline");
|
|
1094
|
-
|
|
1081
|
+
answerFailedRigs(c.id, "offline");
|
|
1095
1082
|
for (const [requestId, owner] of documents) if (owner === c.id) {
|
|
1096
1083
|
documents.delete(requestId);
|
|
1097
1084
|
emit2({ type: "document.error", requestId, path: "", code: "read_failed" });
|
|
@@ -1266,6 +1253,17 @@ function createFleetClient(config, makeClient = createDaemonClient, opts = {}) {
|
|
|
1266
1253
|
}
|
|
1267
1254
|
modelLists.set(msg.requestId, { machine, tool: msg.tool });
|
|
1268
1255
|
}
|
|
1256
|
+
if (msg.type === "openrig.status" || msg.type === "openrig.act" || msg.type === "openrig.specs" || msg.type === "openrig.launch" || msg.type === "openrig.seats") {
|
|
1257
|
+
machine = msg.machineId ?? "local";
|
|
1258
|
+
const { machineId: _m, ...rest } = msg;
|
|
1259
|
+
outgoing = rest;
|
|
1260
|
+
const kind = msg.type === "openrig.status" ? "status" : msg.type === "openrig.act" ? "act" : msg.type === "openrig.specs" ? "specs" : msg.type === "openrig.seats" ? "seats" : "launch";
|
|
1261
|
+
if (!available(peers.get(machine))) {
|
|
1262
|
+
emit2(rigFailure(kind, msg.requestId, machine, "offline"));
|
|
1263
|
+
return;
|
|
1264
|
+
}
|
|
1265
|
+
rigAsks.set(msg.requestId, { machine, kind });
|
|
1266
|
+
}
|
|
1269
1267
|
if (msg.type === "folder.list") {
|
|
1270
1268
|
if (msg.machineId) machine = msg.machineId;
|
|
1271
1269
|
else if (msg.requestId !== void 0) machine = "local";
|
|
@@ -1293,30 +1291,10 @@ function createFleetClient(config, makeClient = createDaemonClient, opts = {}) {
|
|
|
1293
1291
|
}
|
|
1294
1292
|
}
|
|
1295
1293
|
if (msg.type === "update.daemon") machine = "local";
|
|
1296
|
-
if (msg.type === "
|
|
1297
|
-
machine = msg.machineId ?? "local";
|
|
1298
|
-
if (!available(peers.get(machine))) {
|
|
1299
|
-
emit2({ type: "roles.listing", requestId: msg.requestId, roles: [], templates: [], problems: [], error: "offline" });
|
|
1300
|
-
return;
|
|
1301
|
-
}
|
|
1302
|
-
roleLists.set(msg.requestId, machine);
|
|
1303
|
-
}
|
|
1304
|
-
if (msg.type === "roles.list" || msg.type === "team.launch") {
|
|
1305
|
-
if (!("qid" in msg && msg.qid)) machine = msg.machineId ?? "local";
|
|
1306
|
-
const { machineId: _m, ...rest } = outgoing;
|
|
1307
|
-
outgoing = rest;
|
|
1308
|
-
}
|
|
1309
|
-
if (msg.type === "team.join" || msg.type === "team.leave" || msg.type === "team.resume" || msg.type === "team.dissolve" || msg.type === "team.save" || msg.type === "task.cmd" && !msg.qid || msg.type === "action.run") machine = "local";
|
|
1310
|
-
if (outgoing.type === "team.join" || outgoing.type === "team.leave") {
|
|
1311
|
-
const o = splitId(outgoing.session);
|
|
1312
|
-
if (o) {
|
|
1313
|
-
machine = o.machine;
|
|
1314
|
-
outgoing = { ...outgoing, session: o.id };
|
|
1315
|
-
}
|
|
1316
|
-
}
|
|
1294
|
+
if (msg.type === "task.cmd" && !msg.qid || msg.type === "action.run") machine = "local";
|
|
1317
1295
|
if (outgoing.type === "task.cmd") {
|
|
1318
1296
|
const o = outgoing.to ? splitId(outgoing.to) : null;
|
|
1319
|
-
if (o
|
|
1297
|
+
if (o) outgoing = { ...outgoing, to: o.id };
|
|
1320
1298
|
const b2 = splitId(outgoing.by);
|
|
1321
1299
|
if (b2 && outgoing.by !== LEDGE_GIVER) outgoing = { ...outgoing, by: b2.id };
|
|
1322
1300
|
}
|
|
@@ -1362,15 +1340,15 @@ function createFleetClient(config, makeClient = createDaemonClient, opts = {}) {
|
|
|
1362
1340
|
publish();
|
|
1363
1341
|
},
|
|
1364
1342
|
configure(raw) {
|
|
1365
|
-
const
|
|
1343
|
+
const next3 = parseMachines(raw);
|
|
1366
1344
|
if (source2 === "daemon") {
|
|
1367
1345
|
const local2 = peers.get("local").client;
|
|
1368
1346
|
if (local2.status() !== "open") throw Object.assign(new Error("The local daemon is not connected"), { name: "DaemonOffline" });
|
|
1369
|
-
local2.send({ type: "machines.set", machines: toWire(
|
|
1347
|
+
local2.send({ type: "machines.set", machines: toWire(next3) });
|
|
1370
1348
|
return;
|
|
1371
1349
|
}
|
|
1372
|
-
localStorage.setItem(MACHINES_KEY, JSON.stringify(
|
|
1373
|
-
apply(
|
|
1350
|
+
localStorage.setItem(MACHINES_KEY, JSON.stringify(next3));
|
|
1351
|
+
apply(next3);
|
|
1374
1352
|
},
|
|
1375
1353
|
configured: () => configs,
|
|
1376
1354
|
machinesSource: () => source2,
|
|
@@ -1414,16 +1392,16 @@ function createFleetClient(config, makeClient = createDaemonClient, opts = {}) {
|
|
|
1414
1392
|
};
|
|
1415
1393
|
},
|
|
1416
1394
|
projects: () => projects,
|
|
1417
|
-
setProjects(
|
|
1418
|
-
const valid = ProjectsSchema.parse(
|
|
1395
|
+
setProjects(next3) {
|
|
1396
|
+
const valid = ProjectsSchema.parse(next3);
|
|
1419
1397
|
const local2 = peers.get("local").client;
|
|
1420
1398
|
if (local2.status() !== "open") throw Object.assign(new Error("The local daemon is not connected"), { name: "DaemonOffline" });
|
|
1421
1399
|
if (projects === null) throw Object.assign(new Error("Update the local Ledge daemon: it does not know projects"), { name: "DaemonOutdated" });
|
|
1422
1400
|
local2.send({ type: "projects.set", projects: valid });
|
|
1423
1401
|
},
|
|
1424
1402
|
island: () => island,
|
|
1425
|
-
setIsland(
|
|
1426
|
-
const valid = IslandPrefsSchema.parse(
|
|
1403
|
+
setIsland(next3) {
|
|
1404
|
+
const valid = IslandPrefsSchema.parse(next3);
|
|
1427
1405
|
const local2 = peers.get("local").client;
|
|
1428
1406
|
if (local2.status() !== "open") throw Object.assign(new Error("The local daemon is not connected"), { name: "DaemonOffline" });
|
|
1429
1407
|
if (island === void 0) throw Object.assign(new Error("Update the local Ledge daemon: it does not know the island settings"), { name: "DaemonOutdated" });
|
|
@@ -1431,7 +1409,6 @@ function createFleetClient(config, makeClient = createDaemonClient, opts = {}) {
|
|
|
1431
1409
|
},
|
|
1432
1410
|
mobile: () => mobile,
|
|
1433
1411
|
mobileError: () => mobileError,
|
|
1434
|
-
teams: () => teams,
|
|
1435
1412
|
tasks: () => taskList,
|
|
1436
1413
|
contextNear: () => contextNear2,
|
|
1437
1414
|
setContextNear(near) {
|
|
@@ -1514,8 +1491,8 @@ function getImage(client, attachment, route = {}, preview = false, timeoutMs = T
|
|
|
1514
1491
|
}
|
|
1515
1492
|
|
|
1516
1493
|
// src/tui/App.tsx
|
|
1517
|
-
import { useCallback, useEffect as
|
|
1518
|
-
import { useApp, useInput as
|
|
1494
|
+
import { useCallback as useCallback2, useEffect as useEffect15, useMemo as useMemo7, useRef as useRef14, useState as useState16 } from "react";
|
|
1495
|
+
import { useApp, useInput as useInput8, useStdout, useWindowSize as useWindowSize2 } from "ink";
|
|
1519
1496
|
|
|
1520
1497
|
// src/tui/actions.ts
|
|
1521
1498
|
import { useEffect as useEffect3, useMemo, useRef as useRef2 } from "react";
|
|
@@ -1876,7 +1853,7 @@ async function openImage(file, env = process.env, spawnImpl = spawn2, platform =
|
|
|
1876
1853
|
// src/tui/context.tsx
|
|
1877
1854
|
import { createContext, useContext, useEffect as useEffect4, useRef as useRef3 } from "react";
|
|
1878
1855
|
import { useWindowSize } from "ink";
|
|
1879
|
-
var SCREENS = ["overview", "session", "ask", "launch", "settings", "
|
|
1856
|
+
var SCREENS = ["overview", "session", "ask", "launch", "settings", "openrig"];
|
|
1880
1857
|
var TuiContext = createContext(null);
|
|
1881
1858
|
var useTui = () => {
|
|
1882
1859
|
const tui = useContext(TuiContext);
|
|
@@ -1923,7 +1900,7 @@ function formatBytes(n, lang) {
|
|
|
1923
1900
|
var b = (name) => `**${name}**`;
|
|
1924
1901
|
var short = (text5) => text5.length <= 100 ? text5 : `${text5.slice(0, 99)}\u2026`;
|
|
1925
1902
|
var need = (v, keys, say) => keys.every((k) => v[k]) ? say(v) : void 0;
|
|
1926
|
-
var about = (action, v) => action?.startsWith("
|
|
1903
|
+
var about = (action, v) => action?.startsWith("task.") && v.task ? "task" : v.session ? "session" : v.task ? "task" : null;
|
|
1927
1904
|
var fr = {
|
|
1928
1905
|
line: {
|
|
1929
1906
|
"session.model": (v) => need(v, ["session"], (w) => `Passer ${b(w.session)} sur ${v.model ? `${v.model}${v.effort ? `, effort ${v.effort}` : ""}` : v.effort ? `son mod\xE8le par d\xE9faut, effort ${v.effort}` : "son mod\xE8le et son effort par d\xE9faut"}`),
|
|
@@ -1933,26 +1910,21 @@ var fr = {
|
|
|
1933
1910
|
"session.resume": (v) => need(v, ["session"], (w) => `Reprendre ${b(w.session)} sur sa conversation`),
|
|
1934
1911
|
"session.close": (v) => need(v, ["session"], (w) => `Fermer ${b(w.session)}`),
|
|
1935
1912
|
"session.decide": (v) => need(v, ["session", "decision", "kind"], (w) => `${w.decision === "deny" ? "Refuser" : "Accepter"} la demande de ${w.kind} de ${b(w.session)}${v.note ? ", avec une note" : ""}`),
|
|
1936
|
-
"team.join": (v) => need(v, ["session", "team", "role"], (w) => `Faire entrer ${b(w.session)} dans ${b(w.team)} comme @${w.role}`),
|
|
1937
|
-
"team.leave": (v) => need(v, ["session", "team"], (w) => `Retirer ${b(w.session)} de ${b(w.team)}`),
|
|
1938
|
-
"team.resume": (v) => need(v, ["team"], (w) => `Reprendre l\u2019\xE9quipe ${b(w.team)}`),
|
|
1939
|
-
"team.dissolve": (v) => need(v, ["team"], (w) => `Dissoudre l\u2019\xE9quipe ${b(w.team)}`),
|
|
1940
|
-
"team.save": (v) => need(v, ["team", "name"], (w) => v.replaces ? `Remplacer le mod\xE8le \xAB ${w.name} \xBB par ${b(w.team)}` : `Enregistrer ${b(w.team)} comme mod\xE8le \xAB ${w.name} \xBB`),
|
|
1941
1913
|
"task.cancel": (v) => need(v, ["task", "owner"], (w) => `Annuler la t\xE2che \xAB ${short(w.task)} \xBB de ${b(w.owner)}`),
|
|
1942
1914
|
"task.pass": (v) => need(v, ["task", "owner", "session"], (w) => `Passer la t\xE2che \xAB ${short(w.task)} \xBB de ${b(w.owner)} \xE0 ${b(w.session)}`),
|
|
1943
1915
|
"task.answer": (v) => need(v, ["task", "session"], (w) => `R\xE9pondre \xE0 la d\xE9cision \xAB ${short(w.task)} \xBB de ${b(w.session)}`)
|
|
1944
1916
|
},
|
|
1945
1917
|
why: (code3, action, v) => {
|
|
1946
|
-
const s = v.session ? b(v.session) : void 0,
|
|
1918
|
+
const s = v.session ? b(v.session) : void 0, k = v.task ? `\xAB ${short(v.task)} \xBB` : void 0;
|
|
1947
1919
|
const gone = "cette action n\u2019est plus possible.";
|
|
1948
1920
|
switch (code3) {
|
|
1949
1921
|
case "unknown": {
|
|
1950
1922
|
const on = about(action, v);
|
|
1951
|
-
return on === "
|
|
1923
|
+
return on === "task" ? `Ledge ne trouve plus la t\xE2che ${k}.` : on === "session" ? `Ledge ne trouve plus ${s}.` : gone;
|
|
1952
1924
|
}
|
|
1953
1925
|
case "ambiguous": {
|
|
1954
1926
|
const on = about(action, v);
|
|
1955
|
-
return on === "
|
|
1927
|
+
return on === "session" ? `plusieurs sessions s\u2019appellent ${s} : redemande \xE0 Ledge en pr\xE9cisant laquelle.` : gone;
|
|
1956
1928
|
}
|
|
1957
1929
|
case "read_only":
|
|
1958
1930
|
return s ? `${s} est en lecture seule : Ledge ne peut pas lui \xE9crire.` : gone;
|
|
@@ -1974,18 +1946,6 @@ var fr = {
|
|
|
1974
1946
|
return s ? `les demandes de ${s} se r\xE8glent dans sa session.` : gone;
|
|
1975
1947
|
case "no_note":
|
|
1976
1948
|
return s ? `${s} ne peut pas recevoir de note avec cette r\xE9ponse.` : gone;
|
|
1977
|
-
case "member":
|
|
1978
|
-
return s && t ? `${s} est d\xE9j\xE0 dans l\u2019\xE9quipe ${t}.` : gone;
|
|
1979
|
-
case "not_member":
|
|
1980
|
-
return s && t ? `${s} n\u2019est pas dans l\u2019\xE9quipe ${t}.` : gone;
|
|
1981
|
-
case "unknown_role":
|
|
1982
|
-
return v.role ? `le r\xF4le @${v.role} n\u2019existe pas pour ce projet.` : gone;
|
|
1983
|
-
case "not_resting":
|
|
1984
|
-
return t ? `l\u2019\xE9quipe ${t} n\u2019est pas au repos : rien \xE0 reprendre.` : gone;
|
|
1985
|
-
case "dissolved":
|
|
1986
|
-
return t ? `l\u2019\xE9quipe ${t} a \xE9t\xE9 dissoute entre-temps.` : gone;
|
|
1987
|
-
case "no_seat":
|
|
1988
|
-
return t ? `l\u2019\xE9quipe ${t} n\u2019a aucun poste : rien \xE0 enregistrer comme mod\xE8le.` : gone;
|
|
1989
1949
|
case "closed":
|
|
1990
1950
|
return k ? `la t\xE2che ${k} est d\xE9j\xE0 close.` : gone;
|
|
1991
1951
|
case "holder":
|
|
@@ -2012,26 +1972,21 @@ var en = {
|
|
|
2012
1972
|
"session.resume": (v) => need(v, ["session"], (w) => `Resume ${b(w.session)} on its conversation`),
|
|
2013
1973
|
"session.close": (v) => need(v, ["session"], (w) => `Close ${b(w.session)}`),
|
|
2014
1974
|
"session.decide": (v) => need(v, ["session", "decision", "kind"], (w) => `${w.decision === "deny" ? "Deny" : "Accept"} ${b(w.session)}\u2019s ${w.kind} request${v.note ? ", with a note" : ""}`),
|
|
2015
|
-
"team.join": (v) => need(v, ["session", "team", "role"], (w) => `Add ${b(w.session)} to ${b(w.team)} as @${w.role}`),
|
|
2016
|
-
"team.leave": (v) => need(v, ["session", "team"], (w) => `Remove ${b(w.session)} from ${b(w.team)}`),
|
|
2017
|
-
"team.resume": (v) => need(v, ["team"], (w) => `Resume the team ${b(w.team)}`),
|
|
2018
|
-
"team.dissolve": (v) => need(v, ["team"], (w) => `Dissolve the team ${b(w.team)}`),
|
|
2019
|
-
"team.save": (v) => need(v, ["team", "name"], (w) => v.replaces ? `Replace the template \u201C${w.name}\u201D with ${b(w.team)}` : `Save ${b(w.team)} as the template \u201C${w.name}\u201D`),
|
|
2020
1975
|
"task.cancel": (v) => need(v, ["task", "owner"], (w) => `Cancel ${b(w.owner)}\u2019s task \u201C${short(w.task)}\u201D`),
|
|
2021
1976
|
"task.pass": (v) => need(v, ["task", "owner", "session"], (w) => `Pass ${b(w.owner)}\u2019s task \u201C${short(w.task)}\u201D to ${b(w.session)}`),
|
|
2022
1977
|
"task.answer": (v) => need(v, ["task", "session"], (w) => `Answer ${b(w.session)}\u2019s decision \u201C${short(w.task)}\u201D`)
|
|
2023
1978
|
},
|
|
2024
1979
|
why: (code3, action, v) => {
|
|
2025
|
-
const s = v.session ? b(v.session) : void 0,
|
|
1980
|
+
const s = v.session ? b(v.session) : void 0, k = v.task ? `\u201C${short(v.task)}\u201D` : void 0;
|
|
2026
1981
|
const gone = "this action is no longer possible.";
|
|
2027
1982
|
switch (code3) {
|
|
2028
1983
|
case "unknown": {
|
|
2029
1984
|
const on = about(action, v);
|
|
2030
|
-
return on === "
|
|
1985
|
+
return on === "task" ? `Ledge can no longer find the task ${k}.` : on === "session" ? `Ledge can no longer find ${s}.` : gone;
|
|
2031
1986
|
}
|
|
2032
1987
|
case "ambiguous": {
|
|
2033
1988
|
const on = about(action, v);
|
|
2034
|
-
return on === "
|
|
1989
|
+
return on === "session" ? `several sessions are called ${s}: ask Ledge again and say which one.` : gone;
|
|
2035
1990
|
}
|
|
2036
1991
|
case "read_only":
|
|
2037
1992
|
return s ? `${s} is read-only: Ledge cannot write to it.` : gone;
|
|
@@ -2053,18 +2008,6 @@ var en = {
|
|
|
2053
2008
|
return s ? `${s}\u2019s requests are answered in its session.` : gone;
|
|
2054
2009
|
case "no_note":
|
|
2055
2010
|
return s ? `${s} cannot take a note with this answer.` : gone;
|
|
2056
|
-
case "member":
|
|
2057
|
-
return s && t ? `${s} is already in the team ${t}.` : gone;
|
|
2058
|
-
case "not_member":
|
|
2059
|
-
return s && t ? `${s} is not in the team ${t}.` : gone;
|
|
2060
|
-
case "unknown_role":
|
|
2061
|
-
return v.role ? `there is no @${v.role} role for this project.` : gone;
|
|
2062
|
-
case "not_resting":
|
|
2063
|
-
return t ? `the team ${t} is not resting: nothing to resume.` : gone;
|
|
2064
|
-
case "dissolved":
|
|
2065
|
-
return t ? `the team ${t} was dissolved in the meantime.` : gone;
|
|
2066
|
-
case "no_seat":
|
|
2067
|
-
return t ? `the team ${t} has no seat: nothing to save as a template.` : gone;
|
|
2068
2011
|
case "closed":
|
|
2069
2012
|
return k ? `the task ${k} is already closed.` : gone;
|
|
2070
2013
|
case "holder":
|
|
@@ -2099,11 +2042,6 @@ var fr2 = {
|
|
|
2099
2042
|
"session.restore": "Restaurer",
|
|
2100
2043
|
"session.resume": "Reprendre",
|
|
2101
2044
|
"session.decide": "Accepter",
|
|
2102
|
-
"team.join": "Ajouter",
|
|
2103
|
-
"team.leave": "Retirer",
|
|
2104
|
-
"team.resume": "Reprendre",
|
|
2105
|
-
"team.dissolve": "Dissoudre",
|
|
2106
|
-
"team.save": "Enregistrer",
|
|
2107
2045
|
"task.cancel": "Abandonner",
|
|
2108
2046
|
"task.pass": "Passer le relais",
|
|
2109
2047
|
"task.answer": "R\xE9pondre"
|
|
@@ -2166,11 +2104,6 @@ var en2 = {
|
|
|
2166
2104
|
"session.restore": "Restore",
|
|
2167
2105
|
"session.resume": "Resume",
|
|
2168
2106
|
"session.decide": "Accept",
|
|
2169
|
-
"team.join": "Add",
|
|
2170
|
-
"team.leave": "Remove",
|
|
2171
|
-
"team.resume": "Resume",
|
|
2172
|
-
"team.dissolve": "Dissolve",
|
|
2173
|
-
"team.save": "Save",
|
|
2174
2107
|
"task.cancel": "Drop",
|
|
2175
2108
|
"task.pass": "Hand over",
|
|
2176
2109
|
"task.answer": "Answer"
|
|
@@ -2234,7 +2167,7 @@ var fr3 = {
|
|
|
2234
2167
|
h: (n) => `${n} h`,
|
|
2235
2168
|
d: (n) => `${n} j`
|
|
2236
2169
|
},
|
|
2237
|
-
tabs: { overview: "Vue d\u2019ensemble", session: "Session", ask: "Demander \xE0 Ledge", launch: "Nouvelle session", settings: "R\xE9glages",
|
|
2170
|
+
tabs: { overview: "Vue d\u2019ensemble", session: "Session", ask: "Demander \xE0 Ledge", launch: "Nouvelle session", settings: "R\xE9glages", openrig: "OpenRig" },
|
|
2238
2171
|
bar: {
|
|
2239
2172
|
sessions: (n) => `${n} ${plural(n, "session", "sessions")}`,
|
|
2240
2173
|
machines: (n) => `${n} ${plural(n, "machine", "machines")}`,
|
|
@@ -2276,11 +2209,6 @@ var fr3 = {
|
|
|
2276
2209
|
scroll: "d\xE9filer",
|
|
2277
2210
|
space: "espace",
|
|
2278
2211
|
redraw: "autre nom",
|
|
2279
|
-
save: "enregistrer l\u2019\xE9quipe",
|
|
2280
|
-
tasks: "t\xE2ches de l\u2019\xE9quipe",
|
|
2281
|
-
join: "rejoindre une \xE9quipe",
|
|
2282
|
-
resume: "reprendre l\u2019\xE9quipe",
|
|
2283
|
-
teamMode: "session ou \xE9quipe",
|
|
2284
2212
|
handover: "passer le relais",
|
|
2285
2213
|
decide: "r\xE9pondre \xE0 la d\xE9cision",
|
|
2286
2214
|
sendAnswer: "envoyer la r\xE9ponse",
|
|
@@ -2308,16 +2236,12 @@ var fr3 = {
|
|
|
2308
2236
|
deny: "refuser",
|
|
2309
2237
|
ignore: "ignorer",
|
|
2310
2238
|
review: "revoir",
|
|
2311
|
-
openSession: (name) => `ouvrir ${name}
|
|
2312
|
-
rolesTemplates: "r\xF4les / mod\xE8les",
|
|
2313
|
-
folder: "dossier",
|
|
2314
|
-
launchRole: "lancer avec ce r\xF4le",
|
|
2315
|
-
launchTeam: "lancer cette \xE9quipe",
|
|
2316
|
-
openFile: "ouvrir le fichier",
|
|
2317
|
-
ignored: "ignor\xE9s",
|
|
2318
|
-
reread: "relire"
|
|
2239
|
+
openSession: (name) => `ouvrir ${name}`
|
|
2319
2240
|
},
|
|
2320
2241
|
overview: {
|
|
2242
|
+
rigsGroup: "RIGS",
|
|
2243
|
+
kernelGroup: "KERNEL",
|
|
2244
|
+
rigSeat: (rig, role) => `rig ${rig} \xB7 ${role}`,
|
|
2321
2245
|
yours: (n) => `\xC0 toi \xB7 ${n}`,
|
|
2322
2246
|
projects: "Projets",
|
|
2323
2247
|
exchanges: "\xC9changes",
|
|
@@ -2338,11 +2262,6 @@ var fr3 = {
|
|
|
2338
2262
|
deny: "Refuser",
|
|
2339
2263
|
always: "Toujours",
|
|
2340
2264
|
denyWithNote: "Refuser en expliquant",
|
|
2341
|
-
common: "table commune",
|
|
2342
|
-
teamLine: (done, given) => `\xE9quipe \xB7 ${done}/${given}`,
|
|
2343
|
-
resting: "au repos \xB7 R pour reprendre",
|
|
2344
|
-
tasks: (team) => `T\xE2ches \xB7 ${team}`,
|
|
2345
|
-
noTask: "Aucune t\xE2che.",
|
|
2346
2265
|
ledge: "Ledge",
|
|
2347
2266
|
near: (name, pct) => `${name} \xB7 ctx ${pct} % \xB7 H rel\xE8ve`,
|
|
2348
2267
|
reliefFailed: (name, why) => `La rel\xE8ve de ${name} a \xE9chou\xE9 : ${why}`,
|
|
@@ -2354,10 +2273,7 @@ var fr3 = {
|
|
|
2354
2273
|
decision: (giver, title2) => `${giver} te demande : ${title2}`,
|
|
2355
2274
|
decisionTitle: (giver, title2) => `R\xE9pondre \xE0 ${giver} \xB7 ${title2}`,
|
|
2356
2275
|
decisionHint: "Ta r\xE9ponse, telle que la session la lira\u2026",
|
|
2357
|
-
confirmAnswer: (giver) => `Envoyer \xE0 ${giver} ? Une r\xE9ponse ne se reprend pas
|
|
2358
|
-
joinWhich: (name) => `${name} rejoint quelle \xE9quipe ? (\u2191\u2193 \u21B5, esc)`,
|
|
2359
|
-
noTeamHere: "Aucune \xE9quipe dans ce projet.",
|
|
2360
|
-
notInTeam: "Cette session n\u2019est dans aucune \xE9quipe."
|
|
2276
|
+
confirmAnswer: (giver) => `Envoyer \xE0 ${giver} ? Une r\xE9ponse ne se reprend pas`
|
|
2361
2277
|
},
|
|
2362
2278
|
session: {
|
|
2363
2279
|
you: "Vous",
|
|
@@ -2415,19 +2331,8 @@ var fr3 = {
|
|
|
2415
2331
|
offline: "Le daemon local est hors ligne : la question attendra.",
|
|
2416
2332
|
steps: { sessions: "les sessions", pane: (n) => `le terminal de ${n}`, reply: (n) => `la r\xE9ponse de ${n}`, git: (n) => `l\u2019\xE9tat git de ${n}`, repo: (p) => p },
|
|
2417
2333
|
operator: (s, m) => `Ledge \xB7 Op\xE9rateur \xB7 voit ${s} ${plural(s, "session", "sessions")}, ${m} ${plural(m, "machine", "machines")}`,
|
|
2418
|
-
teamCard: (name) => `\xC9quipe \xB7 ${name}`,
|
|
2419
2334
|
taskCard: "T\xE2ches \xE0 confier",
|
|
2420
|
-
launchTeam: "Lancer l\u2019\xE9quipe",
|
|
2421
|
-
save: "Enregistrer",
|
|
2422
|
-
saved: "enregistr\xE9e",
|
|
2423
|
-
seats: "Si\xE8ges",
|
|
2424
|
-
table: "Table",
|
|
2425
|
-
newTable: (project) => `nouvelle table dans la pi\xE8ce ${project}`,
|
|
2426
|
-
autonomy: { ask: "demande", edits: "modifie sans demander", auto: "autonome" },
|
|
2427
|
-
autoWarning: (roles) => `${roles} travaillera sans demander.`,
|
|
2428
|
-
teamLaunched: (at) => `\u2713 \xC9quipe lanc\xE9e \xE0 ${at}`,
|
|
2429
2335
|
give: "Confier",
|
|
2430
|
-
waitTeam: "active une fois l\u2019\xE9quipe lanc\xE9e",
|
|
2431
2336
|
given: (owner, id, state2) => `\u2713 Confi\xE9e \xE0 ${owner} \xB7 ${id} \xB7 ${state2}`,
|
|
2432
2337
|
taskState: { open: "\xE0 prendre", taken: "prise", done: "finie", refused: "refus\xE9e", dropped: "abandonn\xE9e" },
|
|
2433
2338
|
placeholder: "Une question pour Ledge\u2026",
|
|
@@ -2478,66 +2383,7 @@ var fr3 = {
|
|
|
2478
2383
|
thenAttach: "puis a pour s\u2019attacher \xE0 son terminal",
|
|
2479
2384
|
missing: { prompt: "\xC9crivez une instruction.", machine: "Aucune machine en ligne.", repos: "Choisissez un d\xE9p\xF4t ou un dossier." },
|
|
2480
2385
|
launching: "Lancement\u2026",
|
|
2481
|
-
launched: (name) => `\u2713 ${name} est lanc\xE9e
|
|
2482
|
-
teamTitle: "Nouvelle \xE9quipe",
|
|
2483
|
-
mode: "Mode",
|
|
2484
|
-
session: "session",
|
|
2485
|
-
team: "\xE9quipe",
|
|
2486
|
-
template: "Mod\xE8le",
|
|
2487
|
-
custom: "si\xE8ges choisis un par un",
|
|
2488
|
-
seats: "Si\xE8ges",
|
|
2489
|
-
teamName: "Nom",
|
|
2490
|
-
noRole: "aucun r\xF4le : \xE9cris ~/.ledge/roles/<id>.md",
|
|
2491
|
-
loadingRoles: "lecture des r\xF4les\u2026",
|
|
2492
|
-
teamPreview: (team, project) => `L\u2019\xE9quipe ${team} s\u2019installera \xE0 une nouvelle table de la pi\xE8ce ${project}.`,
|
|
2493
|
-
teamLaunched: (name) => `\u2713 \xC9quipe ${name} lanc\xE9e`,
|
|
2494
|
-
teamFailed: (why) => `\xC9quipe non lanc\xE9e : ${why}`,
|
|
2495
|
-
noSeat: "Choisissez au moins un si\xE8ge."
|
|
2496
|
-
},
|
|
2497
|
-
catalog: {
|
|
2498
|
-
roles: "r\xF4les",
|
|
2499
|
-
templates: "mod\xE8les",
|
|
2500
|
-
homeOnly: "Perso seulement",
|
|
2501
|
-
repoRoles: "d\xE9p\xF4t \xB7 .ledge/roles",
|
|
2502
|
-
homeRoles: "perso \xB7 ~/.ledge/roles",
|
|
2503
|
-
repoTeams: "d\xE9p\xF4t \xB7 .ledge/teams",
|
|
2504
|
-
homeTeams: "perso \xB7 ~/.ledge/teams",
|
|
2505
|
-
repo: "d\xE9p\xF4t",
|
|
2506
|
-
home: "perso",
|
|
2507
|
-
tool: "outil",
|
|
2508
|
-
model: "mod\xE8le",
|
|
2509
|
-
effort: "effort",
|
|
2510
|
-
autonomy: "autonomie",
|
|
2511
|
-
file: "fichier",
|
|
2512
|
-
usedIn: "dans",
|
|
2513
|
-
heldBy: "tenu par",
|
|
2514
|
-
teams: "\xE9quipes",
|
|
2515
|
-
replaces: (path2) => `remplace ${path2}`,
|
|
2516
|
-
toolDefault: "d\xE9faut de l\u2019outil",
|
|
2517
|
-
noTemplate: "aucun mod\xE8le",
|
|
2518
|
-
nobody: "personne",
|
|
2519
|
-
noTeam: "aucune",
|
|
2520
|
-
active: "active",
|
|
2521
|
-
resting: "au repos",
|
|
2522
|
-
instruction: (n, max) => `Consigne \xB7 ${n}/${max}`,
|
|
2523
|
-
noInstruction: "Pas de consigne.",
|
|
2524
|
-
seats: (n) => `${n} ${plural(n, "poste", "postes")}`,
|
|
2525
|
-
autonomyShort: { ask: "demande", edits: "\xE9ditions", auto: "auto" },
|
|
2526
|
-
ignored: (n) => `\u26A0 ${n} ${plural(n, "fichier ignor\xE9", "fichiers ignor\xE9s")}`,
|
|
2527
|
-
see: "voir",
|
|
2528
|
-
problems: "Fichiers ignor\xE9s",
|
|
2529
|
-
noProblem: "Aucun fichier ignor\xE9.",
|
|
2530
|
-
loading: "lecture des r\xF4les\u2026",
|
|
2531
|
-
noAnswer: "Le daemon n\u2019a pas r\xE9pondu.",
|
|
2532
|
-
offline: (m) => `${m} est hors ligne.`,
|
|
2533
|
-
outdated: (m) => `Le daemon de ${m} est trop ancien pour le catalogue.`,
|
|
2534
|
-
onMachine: (m) => `sur ${m}`,
|
|
2535
|
-
roleChecking: (id) => `@${id} : lecture du r\xF4le dans ce dossier\u2026`,
|
|
2536
|
-
roleReadIn: (cwd) => `celui de ${cwd}`,
|
|
2537
|
-
roleElsewhere: (id, cwd) => `@${id} n\u2019est lu que dans ${cwd} : lanc\xE9 sans r\xF4le`,
|
|
2538
|
-
noRole: "Aucun r\xF4le ici : \xE9cris .ledge/roles/<id>.md",
|
|
2539
|
-
noTemplateHere: "Aucun mod\xE8le ici : \xE9cris .ledge/teams/<id>.yaml",
|
|
2540
|
-
role: "R\xF4le"
|
|
2386
|
+
launched: (name) => `\u2713 ${name} est lanc\xE9e`
|
|
2541
2387
|
},
|
|
2542
2388
|
settings: { title: "R\xE9glages", language: "Langue", theme: "Th\xE8me", themes: { auto: "Auto", dark: "Sombre", light: "Clair" }, themeAuto: (tone2) => `Auto (fond ${tone2 === "light" ? "clair" : "sombre"})`, context: "Contexte max", contextHint: "au-del\xE0 : passer le relais", contextUnknown: "mettez \xE0 jour le daemon", contextSaved: (pct) => `Contexte max : ${pct} %`, saved: "R\xE9glage enregistr\xE9.", saveFailed: (m) => `R\xE9glage appliqu\xE9, mais non enregistr\xE9 : ${m}` },
|
|
2543
2389
|
help: {
|
|
@@ -2548,8 +2394,9 @@ var fr3 = {
|
|
|
2548
2394
|
ask: "Demander \xE0 Ledge",
|
|
2549
2395
|
launch: "Nouvelle session",
|
|
2550
2396
|
settings: "R\xE9glages",
|
|
2397
|
+
openrig: "OpenRig",
|
|
2398
|
+
rigLaunch: "Lancer un rig",
|
|
2551
2399
|
screens: "changer d\u2019\xE9cran",
|
|
2552
|
-
teams: "\xC9quipes",
|
|
2553
2400
|
field: "Saisie",
|
|
2554
2401
|
wordBefore: "effacer le mot avant",
|
|
2555
2402
|
more: (above, below) => [above ? `\u2191 ${above} plus haut` : "", below ? `\u2193 ${below} plus bas` : ""].filter(Boolean).join(" \xB7 ")
|
|
@@ -2595,9 +2442,6 @@ var fr3 = {
|
|
|
2595
2442
|
noTerminal: (n) => `Pas de terminal pour ${n}.`,
|
|
2596
2443
|
attachFailed: (code3) => `tmux s\u2019est arr\xEAt\xE9 avec le code ${code3}.`,
|
|
2597
2444
|
modelSwitch: "Ce daemon ne change pas le mod\xE8le d\u2019une session en cours.",
|
|
2598
|
-
joined: (n, team) => `${n} rejoint ${team}.`,
|
|
2599
|
-
resumed: (team) => `Reprise de l\u2019\xE9quipe ${team} demand\xE9e.`,
|
|
2600
|
-
saved: (path2) => `\xC9quipe enregistr\xE9e : ${path2}`,
|
|
2601
2445
|
draftKept: "Brouillon gard\xE9 : r pour reprendre.",
|
|
2602
2446
|
draftQuit: "Brouillon en cours : ctrl+c encore pour quitter quand m\xEAme (il sera perdu).",
|
|
2603
2447
|
exited: (cmd, code3) => `${cmd} s\u2019est arr\xEAt\xE9 avec le code ${code3}.`
|
|
@@ -2614,10 +2458,154 @@ var fr3 = {
|
|
|
2614
2458
|
question: (n, text5) => `${n} a une question : ${text5}`,
|
|
2615
2459
|
title: (n) => n > 0 ? `ledge \xB7 ${n} t\u2019${plural(n, "attend", "attendent")}` : "ledge"
|
|
2616
2460
|
},
|
|
2461
|
+
openrig: {
|
|
2462
|
+
operatorKey: "op\xE9rateur",
|
|
2463
|
+
operatorHint: "O : lui parler",
|
|
2464
|
+
operatorNotYet: "Ledge ne suit pas encore la session de l\u2019op\xE9rateur : r\xE9essayez dans quelques secondes.",
|
|
2465
|
+
activity: (a) => ({ running: "au travail", idle: "disponible", unknown: "\u2014" })[a] ?? a,
|
|
2466
|
+
title: "OpenRig",
|
|
2467
|
+
daemon: "Daemon",
|
|
2468
|
+
kernel: "Kernel",
|
|
2469
|
+
rigs: "Rigs",
|
|
2470
|
+
machine: "machine",
|
|
2471
|
+
toggle: "d\xE9marrer/arr\xEAter",
|
|
2472
|
+
restart: "red\xE9marrer",
|
|
2473
|
+
unfold: "d\xE9plier",
|
|
2474
|
+
daemonKey: "daemon",
|
|
2475
|
+
kernelKey: "kernel",
|
|
2476
|
+
daemonState: { running: "actif", stopped: "arr\xEAt\xE9", stale: "arr\xEAt\xE9 sans arr\xEAt propre", unknown: "inconnu" },
|
|
2477
|
+
kernelState: { ready: "pr\xEAt", starting: "d\xE9marrage", stopped: "arr\xEAt\xE9", skipped: "sans kernel", absent: "absent", unknown: "inconnu" },
|
|
2478
|
+
look: { running: "en marche", starting: "d\xE9marrage", attention: "\xE0 surveiller", stopped: "arr\xEAt\xE9" },
|
|
2479
|
+
daemonMeta: (port, pid) => [port ? `127.0.0.1:${port}` : "", pid ? `pid ${pid}` : ""].filter(Boolean).join(" \xB7 "),
|
|
2480
|
+
restoreHint: "\u21BB au d\xE9marrage : rigs relanc\xE9s",
|
|
2481
|
+
kernelHint: "l\u2019op\xE9rateur qui aide \xE0 lancer un rig",
|
|
2482
|
+
seats: (running, total) => `${running}/${total}`,
|
|
2483
|
+
attention: (n) => `${n} ${plural(n, "si\xE8ge demande", "si\xE8ges demandent")} attention`,
|
|
2484
|
+
since: (uptime) => `depuis ${uptime}`,
|
|
2485
|
+
snapshot: (s) => `snapshot ${s}`,
|
|
2486
|
+
work: (n) => n ? `${n} ${plural(n, "t\xE2che", "t\xE2ches")}` : "",
|
|
2487
|
+
stoppedOnPurpose: "arr\xEAt\xE9 volontairement",
|
|
2488
|
+
noRigs: "Aucun rig sur cette machine.",
|
|
2489
|
+
notInstalled: "OpenRig n\u2019est pas install\xE9 sur cette machine (la commande rig est introuvable).",
|
|
2490
|
+
stoppedDaemon: "Le daemon OpenRig est arr\xEAt\xE9 : D le d\xE9marre.",
|
|
2491
|
+
offline: "Machine hors ligne.",
|
|
2492
|
+
outdated: "Le daemon Ledge de cette machine ne conna\xEEt pas OpenRig : mettez-le \xE0 jour.",
|
|
2493
|
+
loading: "Lecture d\u2019OpenRig\u2026",
|
|
2494
|
+
version: (v) => `OpenRig ${v}`,
|
|
2495
|
+
confirmTitle: "Confirmer",
|
|
2496
|
+
confirm: (what) => `${what} ?`,
|
|
2497
|
+
what: {
|
|
2498
|
+
"daemon.stop": "Arr\xEAter le daemon OpenRig",
|
|
2499
|
+
"daemon.restart": "Red\xE9marrer le daemon OpenRig",
|
|
2500
|
+
"kernel.stop": "Arr\xEAter le kernel",
|
|
2501
|
+
"kernel.restart": "Red\xE9marrer le kernel",
|
|
2502
|
+
"rig.stop": (rig) => `Arr\xEAter le rig \xAB ${rig} \xBB`,
|
|
2503
|
+
"rig.restart": (rig) => `Red\xE9marrer le rig \xAB ${rig} \xBB`
|
|
2504
|
+
},
|
|
2505
|
+
busy: (names, n) => n ? `${n} ${plural(n, "agent au travail s\u2019arr\xEAte", "agents au travail s\u2019arr\xEAtent")} : ${names}.` : "Aucun agent au travail.",
|
|
2506
|
+
yes: "confirmer",
|
|
2507
|
+
no: "annuler",
|
|
2508
|
+
running: (cmd) => `en cours : ${cmd}`,
|
|
2509
|
+
done: (cmd) => `fait : ${cmd}`,
|
|
2510
|
+
failed: (why) => `\xE9chec : ${why}`,
|
|
2511
|
+
why: { busy: "une autre action OpenRig est en cours sur cette machine", not_installed: "OpenRig n\u2019est pas install\xE9", offline: "machine hors ligne", outdated: "daemon Ledge trop ancien" }
|
|
2512
|
+
},
|
|
2513
|
+
rigLaunch: {
|
|
2514
|
+
title: "Lancer un rig",
|
|
2515
|
+
launchKey: "lancer un rig",
|
|
2516
|
+
count: "nombre de si\xE8ges",
|
|
2517
|
+
permissions: "4 \xB7 Permissions",
|
|
2518
|
+
policyKey: "permissions",
|
|
2519
|
+
policyOf: { auto: "Auto", standard: "Standard", open: "Ouvert", yolo: "YOLO", locked: "Verrouill\xE9" },
|
|
2520
|
+
specPolicy: (p) => `celle de la spec (${p})`,
|
|
2521
|
+
noSpecPolicy: "aucune",
|
|
2522
|
+
asRig: "comme le rig",
|
|
2523
|
+
policyHint: {
|
|
2524
|
+
none: "sans politique : Claude en acceptEdits, Codex en workspace-write",
|
|
2525
|
+
auto: "Claude d\xE9cide seul (mode auto) ; Codex garde la posture par d\xE9faut",
|
|
2526
|
+
standard: "tout passe sauf PR, publication, fusion, force push et destructif (demande une personne) ; r\xE8gles appliqu\xE9es une fois traduites dans les r\xE9glages du harnais",
|
|
2527
|
+
open: "tout passe sauf le destructif ; r\xE8gles appliqu\xE9es une fois traduites dans les r\xE9glages du harnais",
|
|
2528
|
+
yolo: "aucune demande : Claude --dangerously-skip-permissions, Codex danger-full-access",
|
|
2529
|
+
locked: "seuls la cha\xEEne d\u2019outils et rig up/down passent ; r\xE8gles appliqu\xE9es une fois traduites dans les r\xE9glages du harnais"
|
|
2530
|
+
},
|
|
2531
|
+
nonInterruptive: "accepter les avertissements de premier lancement (--non-interruptive)",
|
|
2532
|
+
spec: "1 \xB7 Spec de d\xE9part",
|
|
2533
|
+
where: "2 \xB7 O\xF9",
|
|
2534
|
+
roles: "3 \xB7 Si\xE8ges par r\xF4le",
|
|
2535
|
+
delegation: "5 \xB7 Qui d\xE9l\xE8gue \xE0 qui",
|
|
2536
|
+
preview: "Aper\xE7u \xB7 rig.yaml",
|
|
2537
|
+
specHint: "Le mod\xE8le de rig : ses pods, ses r\xF4les, les liens entre eux.",
|
|
2538
|
+
source: { user: "mes specs", builtin: "OpenRig" },
|
|
2539
|
+
seatsOf: (n) => `${n} ${plural(n, "si\xE8ge", "si\xE8ges")}`,
|
|
2540
|
+
folder: "Dossier",
|
|
2541
|
+
name: "Nom",
|
|
2542
|
+
folderHint: "un dossier de cette machine, ~ accept\xE9",
|
|
2543
|
+
projectFolder: (p) => `projet ${p}`,
|
|
2544
|
+
model: "mod\xE8le",
|
|
2545
|
+
defaultModel: "par d\xE9faut",
|
|
2546
|
+
modelKey: "mod\xE8le",
|
|
2547
|
+
rolesHint: "Un compteur \xE0 3 donne build, build-2, build-3, identiques au premier.",
|
|
2548
|
+
pairs: "par paires",
|
|
2549
|
+
all: "chaque si\xE8ge \u2192 tous",
|
|
2550
|
+
pairsHint: "build-2 \u2192 review-2",
|
|
2551
|
+
allHint: "chaque build \u2192 tous les review",
|
|
2552
|
+
save: "enregistrer dans mes specs",
|
|
2553
|
+
notScaled: "un si\xE8ge par r\xF4le : rien \xE0 d\xE9l\xE9guer de plus",
|
|
2554
|
+
loading: "Lecture des specs\u2026",
|
|
2555
|
+
noSpecs: "Aucune spec sur cette machine.",
|
|
2556
|
+
daemonStopped: "D\xE9marrez le daemon OpenRig d\u2019abord (D sur l\u2019\xE9cran OpenRig).",
|
|
2557
|
+
noCheck: "p v\xE9rifie le lancement (rig up --plan), sans rien d\xE9marrer.",
|
|
2558
|
+
checking: "V\xE9rification\u2026",
|
|
2559
|
+
launching: "Lancement\u2026",
|
|
2560
|
+
passes: (seats) => `\u2713 le plan passe \xB7 ${seats} ${plural(seats, "si\xE8ge", "si\xE8ges")}`,
|
|
2561
|
+
planStatus: (s) => `plan : ${s}`,
|
|
2562
|
+
warning: (text5, seats) => seats ? `${text5} (${seats})` : text5,
|
|
2563
|
+
launched: (name, n) => `Rig \xAB ${name} \xBB lanc\xE9 \xB7 ${n} ${plural(n, "si\xE8ge", "si\xE8ges")}.`,
|
|
2564
|
+
check: "v\xE9rifier (--plan)",
|
|
2565
|
+
launch: (n) => `lancer ${n} ${plural(n, "si\xE8ge", "si\xE8ges")}`,
|
|
2566
|
+
missing: { spec: "Choisissez une spec.", cwd: "Indiquez le dossier de travail.", name: "Le nom du rig : lettres, chiffres, . _ - (pas de - au d\xE9but).", seats: "Au moins un si\xE8ge." },
|
|
2567
|
+
why: {
|
|
2568
|
+
busy: "Une autre action OpenRig est en cours sur cette machine.",
|
|
2569
|
+
cwd_missing: "Ce dossier n\u2019existe pas sur la machine.",
|
|
2570
|
+
spec_not_found: "Cette spec n\u2019est plus dans la biblioth\xE8que.",
|
|
2571
|
+
daemon_stopped: "D\xE9marrez le daemon OpenRig d\u2019abord (D sur l\u2019\xE9cran OpenRig).",
|
|
2572
|
+
not_installed: "OpenRig n\u2019est pas install\xE9 sur cette machine.",
|
|
2573
|
+
offline: "Machine hors ligne.",
|
|
2574
|
+
outdated: "Le daemon Ledge de cette machine ne sait pas lancer de rig : mettez-le \xE0 jour."
|
|
2575
|
+
}
|
|
2576
|
+
},
|
|
2577
|
+
rigSeats: {
|
|
2578
|
+
title: (rig, machine) => `Si\xE8ges \xB7 ${rig} \xB7 ${machine}`,
|
|
2579
|
+
key: "si\xE8ges",
|
|
2580
|
+
stays: (now2) => `Le rig reste en marche. Aujourd\u2019hui : ${now2}.`,
|
|
2581
|
+
role: "r\xF4le",
|
|
2582
|
+
count: "nombre",
|
|
2583
|
+
delegationKey: "d\xE9l\xE9gation",
|
|
2584
|
+
apply: "appliquer",
|
|
2585
|
+
cancel: "annuler",
|
|
2586
|
+
pairs: "d\xE9l\xE9gation par paires",
|
|
2587
|
+
all: "chaque ajout \u2192 tous",
|
|
2588
|
+
linksPairs: "liens ajout\xE9s par paires",
|
|
2589
|
+
linksAll: "liens ajout\xE9s \xE0 tous",
|
|
2590
|
+
nothing: "Changez un nombre : - +",
|
|
2591
|
+
notRunning: "Seul un rig en marche change de si\xE8ges.",
|
|
2592
|
+
busy: (seat) => `${seat} travaille : son travail en cours s\u2019arr\xEAte.`,
|
|
2593
|
+
applying: "en cours\u2026",
|
|
2594
|
+
done: (added, removed, links) => `+${added} \u2212${removed} si\xE8ges${links !== void 0 ? `, ${links} ${plural(links, "lien", "liens")}` : ""}`,
|
|
2595
|
+
linksUnsupported: "cet OpenRig ne sait pas lier des si\xE8ges ajout\xE9s \xE0 un rig en marche (avant 0.7)",
|
|
2596
|
+
why: {
|
|
2597
|
+
rig_not_running: "Le rig n\u2019est plus en marche.",
|
|
2598
|
+
rig_root_unknown: "Impossible de copier un si\xE8ge : les agents du rig sont introuvables.",
|
|
2599
|
+
busy: "Une autre action OpenRig est en cours sur cette machine.",
|
|
2600
|
+
not_installed: "OpenRig n\u2019est pas install\xE9 sur cette machine.",
|
|
2601
|
+
offline: "Machine hors ligne.",
|
|
2602
|
+
outdated: "Le daemon Ledge de cette machine ne sait pas changer les si\xE8ges d\u2019un rig : mettez-le \xE0 jour."
|
|
2603
|
+
}
|
|
2604
|
+
},
|
|
2617
2605
|
small: {
|
|
2618
2606
|
tooSmall: (w, h) => `Fen\xEAtre trop petite : ${w}\xD7${h}`,
|
|
2619
2607
|
atLeast: (w, h) => `il faut au moins ${w}\xD7${h}`,
|
|
2620
|
-
waits: (name,
|
|
2608
|
+
waits: (name, question2) => question2 ? `${name} a une question` : `${name} attend ton accord`,
|
|
2621
2609
|
kept: "brouillon gard\xE9"
|
|
2622
2610
|
},
|
|
2623
2611
|
cli: { notTty: "ledge tui: needs a terminal (stdin and stdout must be a TTY)", movedToTab: "ledge tui s\u2019ouvre dans l\u2019onglet Ledge.", loadingProfile: "Windows Terminal charge le profil Ledge\u2026" }
|
|
@@ -2629,7 +2617,7 @@ var en3 = {
|
|
|
2629
2617
|
lang: { fr: "Fran\xE7ais", en: "English" },
|
|
2630
2618
|
state: { approval: "Needs you", question: "A question", starting: "Starting", idle: "Available", working: "Working", done: "Finished", error: "Error", readonly: "Read-only" },
|
|
2631
2619
|
time: { now: "just now", decimal: ".", s: (n) => `${n}s`, min: (n) => `${n} min`, h: (n) => `${n} h`, d: (n) => `${n} d` },
|
|
2632
|
-
tabs: { overview: "Overview", session: "Session", ask: "Ask Ledge", launch: "New session", settings: "Settings",
|
|
2620
|
+
tabs: { overview: "Overview", session: "Session", ask: "Ask Ledge", launch: "New session", settings: "Settings", openrig: "OpenRig" },
|
|
2633
2621
|
bar: {
|
|
2634
2622
|
sessions: (n) => `${n} ${plural2(n, "session", "sessions")}`,
|
|
2635
2623
|
machines: (n) => `${n} ${plural2(n, "machine", "machines")}`,
|
|
@@ -2671,11 +2659,6 @@ var en3 = {
|
|
|
2671
2659
|
scroll: "scroll",
|
|
2672
2660
|
space: "space",
|
|
2673
2661
|
redraw: "another name",
|
|
2674
|
-
save: "save the team",
|
|
2675
|
-
tasks: "team tasks",
|
|
2676
|
-
join: "join a team",
|
|
2677
|
-
resume: "resume the team",
|
|
2678
|
-
teamMode: "session or team",
|
|
2679
2662
|
handover: "hand over",
|
|
2680
2663
|
decide: "answer the decision",
|
|
2681
2664
|
sendAnswer: "send the answer",
|
|
@@ -2703,16 +2686,12 @@ var en3 = {
|
|
|
2703
2686
|
deny: "deny",
|
|
2704
2687
|
ignore: "ignore",
|
|
2705
2688
|
review: "review",
|
|
2706
|
-
openSession: (name) => `open ${name}
|
|
2707
|
-
rolesTemplates: "roles / templates",
|
|
2708
|
-
folder: "folder",
|
|
2709
|
-
launchRole: "launch with this role",
|
|
2710
|
-
launchTeam: "launch this team",
|
|
2711
|
-
openFile: "open the file",
|
|
2712
|
-
ignored: "ignored",
|
|
2713
|
-
reread: "read again"
|
|
2689
|
+
openSession: (name) => `open ${name}`
|
|
2714
2690
|
},
|
|
2715
2691
|
overview: {
|
|
2692
|
+
rigsGroup: "RIGS",
|
|
2693
|
+
kernelGroup: "KERNEL",
|
|
2694
|
+
rigSeat: (rig, role) => `rig ${rig} \xB7 ${role}`,
|
|
2716
2695
|
yours: (n) => `Yours \xB7 ${n}`,
|
|
2717
2696
|
projects: "Projects",
|
|
2718
2697
|
exchanges: "Messages",
|
|
@@ -2733,11 +2712,6 @@ var en3 = {
|
|
|
2733
2712
|
deny: "Deny",
|
|
2734
2713
|
always: "Always",
|
|
2735
2714
|
denyWithNote: "Deny with a note",
|
|
2736
|
-
common: "common table",
|
|
2737
|
-
teamLine: (done, given) => `team \xB7 ${done}/${given}`,
|
|
2738
|
-
resting: "resting \xB7 R to resume",
|
|
2739
|
-
tasks: (team) => `Tasks \xB7 ${team}`,
|
|
2740
|
-
noTask: "No task.",
|
|
2741
2715
|
ledge: "Ledge",
|
|
2742
2716
|
near: (name, pct) => `${name} \xB7 ctx ${pct} % \xB7 H hand over`,
|
|
2743
2717
|
reliefFailed: (name, why) => `The relief of ${name} failed: ${why}`,
|
|
@@ -2749,10 +2723,7 @@ var en3 = {
|
|
|
2749
2723
|
decision: (giver, title2) => `${giver} asks you: ${title2}`,
|
|
2750
2724
|
decisionTitle: (giver, title2) => `Answer ${giver} \xB7 ${title2}`,
|
|
2751
2725
|
decisionHint: "Your answer, as the session will read it\u2026",
|
|
2752
|
-
confirmAnswer: (giver) => `Send to ${giver}? An answer cannot be taken back
|
|
2753
|
-
joinWhich: (name) => `${name} joins which team? (\u2191\u2193 \u21B5, esc)`,
|
|
2754
|
-
noTeamHere: "No team in this project.",
|
|
2755
|
-
notInTeam: "This session is in no team."
|
|
2726
|
+
confirmAnswer: (giver) => `Send to ${giver}? An answer cannot be taken back`
|
|
2756
2727
|
},
|
|
2757
2728
|
session: {
|
|
2758
2729
|
you: "You",
|
|
@@ -2810,19 +2781,8 @@ var en3 = {
|
|
|
2810
2781
|
offline: "The local daemon is offline: the question will wait.",
|
|
2811
2782
|
steps: { sessions: "the sessions", pane: (n) => `${n}'s terminal`, reply: (n) => `${n}'s reply`, git: (n) => `${n}'s git state`, repo: (p) => p },
|
|
2812
2783
|
operator: (s, m) => `Ledge \xB7 Operator \xB7 sees ${s} ${plural2(s, "session", "sessions")}, ${m} ${plural2(m, "machine", "machines")}`,
|
|
2813
|
-
teamCard: (name) => `Team \xB7 ${name}`,
|
|
2814
2784
|
taskCard: "Tasks to give",
|
|
2815
|
-
launchTeam: "Launch the team",
|
|
2816
|
-
save: "Save",
|
|
2817
|
-
saved: "saved",
|
|
2818
|
-
seats: "Seats",
|
|
2819
|
-
table: "Table",
|
|
2820
|
-
newTable: (project) => `new table in the ${project} room`,
|
|
2821
|
-
autonomy: { ask: "asks", edits: "edits without asking", auto: "autonomous" },
|
|
2822
|
-
autoWarning: (roles) => `${roles} will work without asking.`,
|
|
2823
|
-
teamLaunched: (at) => `\u2713 Team launched at ${at}`,
|
|
2824
2785
|
give: "Give",
|
|
2825
|
-
waitTeam: "active once the team is launched",
|
|
2826
2786
|
given: (owner, id, state2) => `\u2713 Given to ${owner} \xB7 ${id} \xB7 ${state2}`,
|
|
2827
2787
|
taskState: { open: "to take", taken: "taken", done: "done", refused: "refused", dropped: "dropped" },
|
|
2828
2788
|
placeholder: "A question for Ledge\u2026",
|
|
@@ -2878,66 +2838,7 @@ var en3 = {
|
|
|
2878
2838
|
thenAttach: "then a to attach to its terminal",
|
|
2879
2839
|
missing: { prompt: "Write an instruction.", machine: "No machine online.", repos: "Pick a repository or a folder." },
|
|
2880
2840
|
launching: "Launching\u2026",
|
|
2881
|
-
launched: (name) => `\u2713 ${name} is started
|
|
2882
|
-
teamTitle: "New team",
|
|
2883
|
-
mode: "Mode",
|
|
2884
|
-
session: "session",
|
|
2885
|
-
team: "team",
|
|
2886
|
-
template: "Template",
|
|
2887
|
-
custom: "seats chosen one by one",
|
|
2888
|
-
seats: "Seats",
|
|
2889
|
-
teamName: "Name",
|
|
2890
|
-
noRole: "no role: write ~/.ledge/roles/<id>.md",
|
|
2891
|
-
loadingRoles: "reading the roles\u2026",
|
|
2892
|
-
teamPreview: (team, project) => `Team ${team} will sit at a new table in the ${project} room.`,
|
|
2893
|
-
teamLaunched: (name) => `\u2713 Team ${name} launched`,
|
|
2894
|
-
teamFailed: (why) => `Team not launched: ${why}`,
|
|
2895
|
-
noSeat: "Choose at least one seat."
|
|
2896
|
-
},
|
|
2897
|
-
catalog: {
|
|
2898
|
-
roles: "roles",
|
|
2899
|
-
templates: "templates",
|
|
2900
|
-
homeOnly: "Personal only",
|
|
2901
|
-
repoRoles: "repository \xB7 .ledge/roles",
|
|
2902
|
-
homeRoles: "personal \xB7 ~/.ledge/roles",
|
|
2903
|
-
repoTeams: "repository \xB7 .ledge/teams",
|
|
2904
|
-
homeTeams: "personal \xB7 ~/.ledge/teams",
|
|
2905
|
-
repo: "repository",
|
|
2906
|
-
home: "personal",
|
|
2907
|
-
tool: "agent",
|
|
2908
|
-
model: "model",
|
|
2909
|
-
effort: "effort",
|
|
2910
|
-
autonomy: "autonomy",
|
|
2911
|
-
file: "file",
|
|
2912
|
-
usedIn: "in",
|
|
2913
|
-
heldBy: "held by",
|
|
2914
|
-
teams: "teams",
|
|
2915
|
-
replaces: (path2) => `replaces ${path2}`,
|
|
2916
|
-
toolDefault: "the agent\u2019s default",
|
|
2917
|
-
noTemplate: "no template",
|
|
2918
|
-
nobody: "nobody",
|
|
2919
|
-
noTeam: "none",
|
|
2920
|
-
active: "active",
|
|
2921
|
-
resting: "resting",
|
|
2922
|
-
instruction: (n, max) => `Instruction \xB7 ${n}/${max}`,
|
|
2923
|
-
noInstruction: "No instruction.",
|
|
2924
|
-
seats: (n) => `${n} ${plural2(n, "seat", "seats")}`,
|
|
2925
|
-
autonomyShort: { ask: "asks", edits: "edits", auto: "auto" },
|
|
2926
|
-
ignored: (n) => `\u26A0 ${n} ${plural2(n, "file", "files")} ignored`,
|
|
2927
|
-
see: "see",
|
|
2928
|
-
problems: "Ignored files",
|
|
2929
|
-
noProblem: "No ignored file.",
|
|
2930
|
-
loading: "reading the roles\u2026",
|
|
2931
|
-
noAnswer: "The daemon did not answer.",
|
|
2932
|
-
offline: (m) => `${m} is offline.`,
|
|
2933
|
-
outdated: (m) => `${m}\u2019s daemon is too old for the catalog.`,
|
|
2934
|
-
onMachine: (m) => `on ${m}`,
|
|
2935
|
-
roleChecking: (id) => `@${id}: reading the role in this folder\u2026`,
|
|
2936
|
-
roleReadIn: (cwd) => `the one in ${cwd}`,
|
|
2937
|
-
roleElsewhere: (id, cwd) => `@${id} is only read in ${cwd}: launched without a role`,
|
|
2938
|
-
noRole: "No role here: write .ledge/roles/<id>.md",
|
|
2939
|
-
noTemplateHere: "No template here: write .ledge/teams/<id>.yaml",
|
|
2940
|
-
role: "Role"
|
|
2841
|
+
launched: (name) => `\u2713 ${name} is started`
|
|
2941
2842
|
},
|
|
2942
2843
|
settings: { title: "Settings", language: "Language", theme: "Theme", themes: { auto: "Auto", dark: "Dark", light: "Light" }, themeAuto: (tone2) => `Auto (${tone2} background)`, context: "Max context", contextHint: "past it: hand over", contextUnknown: "update the daemon", contextSaved: (pct) => `Max context: ${pct} %`, saved: "Setting saved.", saveFailed: (m) => `Setting applied, but not saved: ${m}` },
|
|
2943
2844
|
help: {
|
|
@@ -2948,8 +2849,9 @@ var en3 = {
|
|
|
2948
2849
|
ask: "Ask Ledge",
|
|
2949
2850
|
launch: "New session",
|
|
2950
2851
|
settings: "Settings",
|
|
2852
|
+
openrig: "OpenRig",
|
|
2853
|
+
rigLaunch: "Launch a rig",
|
|
2951
2854
|
screens: "switch screen",
|
|
2952
|
-
teams: "Teams",
|
|
2953
2855
|
field: "Typing",
|
|
2954
2856
|
wordBefore: "delete the word before",
|
|
2955
2857
|
more: (above, below) => [above ? `\u2191 ${above} above` : "", below ? `\u2193 ${below} below` : ""].filter(Boolean).join(" \xB7 ")
|
|
@@ -2988,9 +2890,6 @@ var en3 = {
|
|
|
2988
2890
|
noTerminal: (n) => `No terminal for ${n}.`,
|
|
2989
2891
|
attachFailed: (code3) => `tmux stopped with code ${code3}.`,
|
|
2990
2892
|
modelSwitch: "This daemon cannot change a running session\u2019s model.",
|
|
2991
|
-
joined: (n, team) => `${n} joins ${team}.`,
|
|
2992
|
-
resumed: (team) => `Asked to resume team ${team}.`,
|
|
2993
|
-
saved: (path2) => `Team saved: ${path2}`,
|
|
2994
2893
|
draftKept: "Draft kept: r to pick it up.",
|
|
2995
2894
|
draftQuit: "Draft in progress: ctrl+c again to quit anyway (it will be lost).",
|
|
2996
2895
|
exited: (cmd, code3) => `${cmd} exited with code ${code3}.`
|
|
@@ -3007,10 +2906,154 @@ var en3 = {
|
|
|
3007
2906
|
question: (n, text5) => `${n} has a question: ${text5}`,
|
|
3008
2907
|
title: (n) => n > 0 ? `ledge \xB7 ${n} waiting` : "ledge"
|
|
3009
2908
|
},
|
|
2909
|
+
openrig: {
|
|
2910
|
+
operatorKey: "operator",
|
|
2911
|
+
operatorHint: "O: talk to it",
|
|
2912
|
+
operatorNotYet: "Ledge does not follow the operator\u2019s session yet: try again in a few seconds.",
|
|
2913
|
+
activity: (a) => ({ running: "working", idle: "available", unknown: "\u2014" })[a] ?? a,
|
|
2914
|
+
title: "OpenRig",
|
|
2915
|
+
daemon: "Daemon",
|
|
2916
|
+
kernel: "Kernel",
|
|
2917
|
+
rigs: "Rigs",
|
|
2918
|
+
machine: "machine",
|
|
2919
|
+
toggle: "start/stop",
|
|
2920
|
+
restart: "restart",
|
|
2921
|
+
unfold: "unfold",
|
|
2922
|
+
daemonKey: "daemon",
|
|
2923
|
+
kernelKey: "kernel",
|
|
2924
|
+
daemonState: { running: "running", stopped: "stopped", stale: "stopped uncleanly", unknown: "unknown" },
|
|
2925
|
+
kernelState: { ready: "ready", starting: "starting", stopped: "stopped", skipped: "no kernel", absent: "absent", unknown: "unknown" },
|
|
2926
|
+
look: { running: "running", starting: "starting", attention: "needs a look", stopped: "stopped" },
|
|
2927
|
+
daemonMeta: (port, pid) => [port ? `127.0.0.1:${port}` : "", pid ? `pid ${pid}` : ""].filter(Boolean).join(" \xB7 "),
|
|
2928
|
+
restoreHint: "\u21BB on start: rigs brought back",
|
|
2929
|
+
kernelHint: "the operator that helps start a rig",
|
|
2930
|
+
seats: (running, total) => `${running}/${total}`,
|
|
2931
|
+
attention: (n) => `${n} ${plural2(n, "seat needs", "seats need")} attention`,
|
|
2932
|
+
since: (uptime) => `up ${uptime}`,
|
|
2933
|
+
snapshot: (s) => `snapshot ${s}`,
|
|
2934
|
+
work: (n) => n ? `${n} ${plural2(n, "task", "tasks")}` : "",
|
|
2935
|
+
stoppedOnPurpose: "stopped on purpose",
|
|
2936
|
+
noRigs: "No rig on this machine.",
|
|
2937
|
+
notInstalled: "OpenRig is not installed on this machine (no rig command).",
|
|
2938
|
+
stoppedDaemon: "The OpenRig daemon is stopped: D starts it.",
|
|
2939
|
+
offline: "Machine offline.",
|
|
2940
|
+
outdated: "This machine\u2019s Ledge daemon does not know OpenRig: update it.",
|
|
2941
|
+
loading: "Reading OpenRig\u2026",
|
|
2942
|
+
version: (v) => `OpenRig ${v}`,
|
|
2943
|
+
confirmTitle: "Confirm",
|
|
2944
|
+
confirm: (what) => `${what}?`,
|
|
2945
|
+
what: {
|
|
2946
|
+
"daemon.stop": "Stop the OpenRig daemon",
|
|
2947
|
+
"daemon.restart": "Restart the OpenRig daemon",
|
|
2948
|
+
"kernel.stop": "Stop the kernel",
|
|
2949
|
+
"kernel.restart": "Restart the kernel",
|
|
2950
|
+
"rig.stop": (rig) => `Stop the rig \u201C${rig}\u201D`,
|
|
2951
|
+
"rig.restart": (rig) => `Restart the rig \u201C${rig}\u201D`
|
|
2952
|
+
},
|
|
2953
|
+
busy: (names, n) => n ? `${n} working ${plural2(n, "agent stops", "agents stop")}: ${names}.` : "No agent at work.",
|
|
2954
|
+
yes: "confirm",
|
|
2955
|
+
no: "cancel",
|
|
2956
|
+
running: (cmd) => `running: ${cmd}`,
|
|
2957
|
+
done: (cmd) => `done: ${cmd}`,
|
|
2958
|
+
failed: (why) => `failed: ${why}`,
|
|
2959
|
+
why: { busy: "another OpenRig action runs on this machine", not_installed: "OpenRig is not installed", offline: "machine offline", outdated: "Ledge daemon too old" }
|
|
2960
|
+
},
|
|
2961
|
+
rigLaunch: {
|
|
2962
|
+
title: "Launch a rig",
|
|
2963
|
+
launchKey: "launch a rig",
|
|
2964
|
+
count: "number of seats",
|
|
2965
|
+
permissions: "4 \xB7 Permissions",
|
|
2966
|
+
policyKey: "permissions",
|
|
2967
|
+
policyOf: { auto: "Auto", standard: "Standard", open: "Open", yolo: "YOLO", locked: "Locked" },
|
|
2968
|
+
specPolicy: (p) => `the spec\u2019s (${p})`,
|
|
2969
|
+
noSpecPolicy: "none",
|
|
2970
|
+
asRig: "as the rig",
|
|
2971
|
+
policyHint: {
|
|
2972
|
+
none: "no policy: Claude in acceptEdits, Codex in workspace-write",
|
|
2973
|
+
auto: "Claude decides on its own (auto mode); Codex keeps the default posture",
|
|
2974
|
+
standard: "everything passes but PRs, publishing, merging, force push and destructive (asks a person); rules applied once translated into the harness settings",
|
|
2975
|
+
open: "everything passes but destructive; rules applied once translated into the harness settings",
|
|
2976
|
+
yolo: "no prompt: Claude --dangerously-skip-permissions, Codex danger-full-access",
|
|
2977
|
+
locked: "only the toolchain and rig up/down pass; rules applied once translated into the harness settings"
|
|
2978
|
+
},
|
|
2979
|
+
nonInterruptive: "accept the first-launch warnings (--non-interruptive)",
|
|
2980
|
+
spec: "1 \xB7 Starting spec",
|
|
2981
|
+
where: "2 \xB7 Where",
|
|
2982
|
+
roles: "3 \xB7 Seats per role",
|
|
2983
|
+
delegation: "5 \xB7 Who delegates to whom",
|
|
2984
|
+
preview: "Preview \xB7 rig.yaml",
|
|
2985
|
+
specHint: "The rig\u2019s model: its pods, its roles, the links between them.",
|
|
2986
|
+
source: { user: "my specs", builtin: "OpenRig" },
|
|
2987
|
+
seatsOf: (n) => `${n} ${plural2(n, "seat", "seats")}`,
|
|
2988
|
+
folder: "Folder",
|
|
2989
|
+
name: "Name",
|
|
2990
|
+
folderHint: "a folder of this machine, ~ accepted",
|
|
2991
|
+
projectFolder: (p) => `project ${p}`,
|
|
2992
|
+
model: "model",
|
|
2993
|
+
defaultModel: "default",
|
|
2994
|
+
modelKey: "model",
|
|
2995
|
+
rolesHint: "A counter at 3 gives build, build-2, build-3, the same as the first.",
|
|
2996
|
+
pairs: "in pairs",
|
|
2997
|
+
all: "each seat \u2192 all",
|
|
2998
|
+
pairsHint: "build-2 \u2192 review-2",
|
|
2999
|
+
allHint: "each build \u2192 every review",
|
|
3000
|
+
save: "save in my specs",
|
|
3001
|
+
notScaled: "one seat per role: nothing more to delegate",
|
|
3002
|
+
loading: "Reading the specs\u2026",
|
|
3003
|
+
noSpecs: "No spec on this machine.",
|
|
3004
|
+
daemonStopped: "Start the OpenRig daemon first (D on the OpenRig screen).",
|
|
3005
|
+
noCheck: "p checks the launch (rig up --plan) without starting anything.",
|
|
3006
|
+
checking: "Checking\u2026",
|
|
3007
|
+
launching: "Launching\u2026",
|
|
3008
|
+
passes: (seats) => `\u2713 the plan passes \xB7 ${seats} ${plural2(seats, "seat", "seats")}`,
|
|
3009
|
+
planStatus: (s) => `plan: ${s}`,
|
|
3010
|
+
warning: (text5, seats) => seats ? `${text5} (${seats})` : text5,
|
|
3011
|
+
launched: (name, n) => `Rig \u201C${name}\u201D launched \xB7 ${n} ${plural2(n, "seat", "seats")}.`,
|
|
3012
|
+
check: "check (--plan)",
|
|
3013
|
+
launch: (n) => `launch ${n} ${plural2(n, "seat", "seats")}`,
|
|
3014
|
+
missing: { spec: "Pick a spec.", cwd: "Give the working folder.", name: "The rig\u2019s name: letters, digits, . _ - (no leading -).", seats: "At least one seat." },
|
|
3015
|
+
why: {
|
|
3016
|
+
busy: "Another OpenRig action runs on this machine.",
|
|
3017
|
+
cwd_missing: "This folder does not exist on the machine.",
|
|
3018
|
+
spec_not_found: "This spec is no longer in the library.",
|
|
3019
|
+
daemon_stopped: "Start the OpenRig daemon first (D on the OpenRig screen).",
|
|
3020
|
+
not_installed: "OpenRig is not installed on this machine.",
|
|
3021
|
+
offline: "Machine offline.",
|
|
3022
|
+
outdated: "This machine\u2019s Ledge daemon cannot launch a rig: update it."
|
|
3023
|
+
}
|
|
3024
|
+
},
|
|
3025
|
+
rigSeats: {
|
|
3026
|
+
title: (rig, machine) => `Seats \xB7 ${rig} \xB7 ${machine}`,
|
|
3027
|
+
key: "seats",
|
|
3028
|
+
stays: (now2) => `The rig keeps running. Now: ${now2}.`,
|
|
3029
|
+
role: "role",
|
|
3030
|
+
count: "number",
|
|
3031
|
+
delegationKey: "delegation",
|
|
3032
|
+
apply: "apply",
|
|
3033
|
+
cancel: "cancel",
|
|
3034
|
+
pairs: "delegation in pairs",
|
|
3035
|
+
all: "each added \u2192 all",
|
|
3036
|
+
linksPairs: "links added in pairs",
|
|
3037
|
+
linksAll: "links added to all",
|
|
3038
|
+
nothing: "Change a number: - +",
|
|
3039
|
+
notRunning: "Only a running rig changes seats.",
|
|
3040
|
+
busy: (seat) => `${seat} is working: its work in progress stops.`,
|
|
3041
|
+
applying: "applying\u2026",
|
|
3042
|
+
done: (added, removed, links) => `+${added} \u2212${removed} seats${links !== void 0 ? `, ${links} ${plural2(links, "link", "links")}` : ""}`,
|
|
3043
|
+
linksUnsupported: "this OpenRig cannot link seats added to a running rig (before 0.7)",
|
|
3044
|
+
why: {
|
|
3045
|
+
rig_not_running: "The rig is no longer running.",
|
|
3046
|
+
rig_root_unknown: "Cannot copy a seat: the rig\u2019s agents cannot be found.",
|
|
3047
|
+
busy: "Another OpenRig action runs on this machine.",
|
|
3048
|
+
not_installed: "OpenRig is not installed on this machine.",
|
|
3049
|
+
offline: "Machine offline.",
|
|
3050
|
+
outdated: "This machine\u2019s Ledge daemon cannot change a rig\u2019s seats: update it."
|
|
3051
|
+
}
|
|
3052
|
+
},
|
|
3010
3053
|
small: {
|
|
3011
3054
|
tooSmall: (w, h) => `Window too small: ${w}\xD7${h}`,
|
|
3012
3055
|
atLeast: (w, h) => `needs at least ${w}\xD7${h}`,
|
|
3013
|
-
waits: (name,
|
|
3056
|
+
waits: (name, question2) => question2 ? `${name} has a question` : `${name} waits for your approval`,
|
|
3014
3057
|
kept: "draft kept"
|
|
3015
3058
|
},
|
|
3016
3059
|
cli: { notTty: "ledge tui: needs a terminal (stdin and stdout must be a TTY)", movedToTab: "ledge tui opens in the Ledge tab.", loadingProfile: "Windows Terminal is loading the Ledge profile\u2026" }
|
|
@@ -3029,37 +3072,33 @@ var useI18n = () => useContext2(I18nContext);
|
|
|
3029
3072
|
// src/tui/model/overview.ts
|
|
3030
3073
|
var listed = (sessions) => sessions.filter((s) => s.state !== "exited");
|
|
3031
3074
|
var machineOf = (s) => s.machineId ?? splitId(s.id)?.machine ?? "local";
|
|
3032
|
-
function overview(sessions, projects
|
|
3075
|
+
function overview(sessions, projects) {
|
|
3033
3076
|
const live = listed(sessions);
|
|
3034
3077
|
const yours = live.filter(isPending).sort((a, b2) => a.lastActivityAt.localeCompare(b2.lastActivityAt) || a.id.localeCompare(b2.id));
|
|
3035
3078
|
const nodes = /* @__PURE__ */ new Map();
|
|
3036
3079
|
const known2 = new Map((projects?.projects ?? []).map((p) => [p.id, p]));
|
|
3037
|
-
for (const p of projects?.projects ?? []) nodes.set(`p:${p.id}`, { key: `p:${p.id}`, label: p.name, color: p.color, branches: [], count: 0
|
|
3038
|
-
const
|
|
3039
|
-
for (const team of teams) {
|
|
3040
|
-
if (team.state === "dissolved") continue;
|
|
3041
|
-
const pid = projects ? projectOf({ machineId: team.machine, cwd: team.cwd }, projects) ?? team.project : team.project;
|
|
3042
|
-
const node2 = pid ? nodes.get(`p:${pid}`) : void 0;
|
|
3043
|
-
if (!node2) continue;
|
|
3044
|
-
const mine = tasks.filter((x) => x.team === team.id && x.giver === LEDGE_GIVER);
|
|
3045
|
-
const row2 = { key: `${node2.key}|team:${team.id}`, team, sessions: [], done: mine.filter((x) => x.state === "done").length, given: mine.length };
|
|
3046
|
-
node2.teams.push(row2);
|
|
3047
|
-
rooms.set(team.id, row2);
|
|
3048
|
-
}
|
|
3080
|
+
for (const p of projects?.projects ?? []) nodes.set(`p:${p.id}`, { key: `p:${p.id}`, label: p.name, color: p.color, branches: [], count: 0 });
|
|
3081
|
+
const rigNodes = /* @__PURE__ */ new Map();
|
|
3049
3082
|
for (const s of live) {
|
|
3083
|
+
if (s.rig) {
|
|
3084
|
+
const kind = s.rig.name === "kernel" ? "kernel" : "rig";
|
|
3085
|
+
const key2 = kind === "kernel" ? "g:kernel" : `g:rig:${s.rig.name}`;
|
|
3086
|
+
let node3 = rigNodes.get(key2);
|
|
3087
|
+
if (!node3) {
|
|
3088
|
+
node3 = { key: key2, label: kind === "kernel" ? "Kernel" : s.rig.name, kind, branches: [{ branch: "", sessions: [] }], count: 0 };
|
|
3089
|
+
rigNodes.set(key2, node3);
|
|
3090
|
+
}
|
|
3091
|
+
node3.branches[0].sessions.push(s);
|
|
3092
|
+
node3.count += 1;
|
|
3093
|
+
continue;
|
|
3094
|
+
}
|
|
3050
3095
|
const pid = projects ? projectOf({ machineId: machineOf(s), cwd: s.cwd }, projects) : null;
|
|
3051
3096
|
const key = pid && known2.has(pid) ? `p:${pid}` : `r:${machineOf(s)}:${s.repoPath ?? s.cwd}`;
|
|
3052
3097
|
let node2 = nodes.get(key);
|
|
3053
3098
|
if (!node2) {
|
|
3054
|
-
node2 = { key, label: s.repo ?? s.project, branches: [], count: 0
|
|
3099
|
+
node2 = { key, label: s.repo ?? s.project, branches: [], count: 0 };
|
|
3055
3100
|
nodes.set(key, node2);
|
|
3056
3101
|
}
|
|
3057
|
-
const seat = s.team ? rooms.get(s.team) : void 0;
|
|
3058
|
-
if (seat && node2.teams.includes(seat)) {
|
|
3059
|
-
seat.sessions.push(s);
|
|
3060
|
-
node2.count += 1;
|
|
3061
|
-
continue;
|
|
3062
|
-
}
|
|
3063
3102
|
const branch = s.branch ?? "-";
|
|
3064
3103
|
let row2 = node2.branches.find((b2) => b2.branch === branch);
|
|
3065
3104
|
if (!row2) {
|
|
@@ -3069,8 +3108,9 @@ function overview(sessions, projects, teams = [], tasks = []) {
|
|
|
3069
3108
|
row2.sessions.push(s);
|
|
3070
3109
|
node2.count += 1;
|
|
3071
3110
|
}
|
|
3072
|
-
const
|
|
3073
|
-
const
|
|
3111
|
+
const groups = [...rigNodes.values()].sort((a, b2) => a.kind === b2.kind ? a.label.localeCompare(b2.label) : a.kind === "kernel" ? 1 : -1);
|
|
3112
|
+
const tree2 = [...[...nodes.values()].filter((n) => n.count > 0), ...groups];
|
|
3113
|
+
const order2 = tree2.flatMap((n) => n.branches.flatMap((b2) => b2.sessions.map((s) => s.id)));
|
|
3074
3114
|
return { yours, tree: tree2, order: order2, machines: new Set(live.map(machineOf)).size };
|
|
3075
3115
|
}
|
|
3076
3116
|
var helperCount = (s) => liveHelpers(s).length;
|
|
@@ -3096,13 +3136,13 @@ function exchanges(sessions, max, tasks = [], ledge = "Ledge") {
|
|
|
3096
3136
|
const byId = new Map(sessions.map((s) => [s.id, s]));
|
|
3097
3137
|
const bare = (id) => splitId(id)?.id ?? id;
|
|
3098
3138
|
const find2 = (id) => byId.get(id) ?? sessions.find((x) => bare(x.id) === bare(id));
|
|
3099
|
-
const
|
|
3139
|
+
const nameOf2 = (id, then) => id === LEDGE_GIVER ? ledge : find2(id)?.name ?? then;
|
|
3100
3140
|
return [...sessions.flatMap((s) => {
|
|
3101
3141
|
const m = s.lastMessage;
|
|
3102
3142
|
if (!m) return [];
|
|
3103
3143
|
const peer = m.peer ? find2(m.peer) : void 0;
|
|
3104
3144
|
return [{ at: m.at, from: s.name, to: peer?.name ?? m.to, summary: m.summary, kind: "message" }];
|
|
3105
|
-
}), ...tasks.flatMap((x) => transmissions(x).map((tr) => ({ at: tr.at, from:
|
|
3145
|
+
}), ...tasks.flatMap((x) => transmissions(x).map((tr) => ({ at: tr.at, from: nameOf2(tr.from, tr.fromName), to: nameOf2(tr.to, tr.toName), summary: x.title, kind: "task" })))].sort((a, b2) => b2.at.localeCompare(a.at)).slice(0, max);
|
|
3106
3146
|
}
|
|
3107
3147
|
var nearContext = (sessions, near) => sessions.filter((s) => s.state !== "exited" && !s.archivedAt && (s.handover ? s.handover.state === "failed" : contextNear(s.context, near)));
|
|
3108
3148
|
var closedLedgeTasks = (tasks) => tasks.filter((x) => x.giver === LEDGE_GIVER && taskClosed(x) && !x.seen);
|
|
@@ -3274,9 +3314,9 @@ var stateColors = (p) => ({
|
|
|
3274
3314
|
var STATE_COLOR = stateColors(C);
|
|
3275
3315
|
var current = "dark";
|
|
3276
3316
|
var tone = () => current;
|
|
3277
|
-
function setTone(
|
|
3278
|
-
current =
|
|
3279
|
-
Object.assign(C, PALETTES[
|
|
3317
|
+
function setTone(next3) {
|
|
3318
|
+
current = next3;
|
|
3319
|
+
Object.assign(C, PALETTES[next3]);
|
|
3280
3320
|
Object.assign(STATE_COLOR, stateColors(C));
|
|
3281
3321
|
}
|
|
3282
3322
|
var projectColor = (color2) => color2 ? PROJECT_COLORS[color2] : C.dim;
|
|
@@ -3534,7 +3574,7 @@ function visitParents(tree2, test, visitor, reverse) {
|
|
|
3534
3574
|
check = test;
|
|
3535
3575
|
}
|
|
3536
3576
|
const is2 = convert(check);
|
|
3537
|
-
const
|
|
3577
|
+
const step3 = reverse ? -1 : 1;
|
|
3538
3578
|
factory(tree2, void 0, [])();
|
|
3539
3579
|
function factory(node2, index2, parents) {
|
|
3540
3580
|
const value = (
|
|
@@ -3571,7 +3611,7 @@ function visitParents(tree2, test, visitor, reverse) {
|
|
|
3571
3611
|
node2
|
|
3572
3612
|
);
|
|
3573
3613
|
if (nodeAsParent.children && result[0] !== SKIP) {
|
|
3574
|
-
offset = (reverse ? nodeAsParent.children.length : -1) +
|
|
3614
|
+
offset = (reverse ? nodeAsParent.children.length : -1) + step3;
|
|
3575
3615
|
grandparents = parents.concat(nodeAsParent);
|
|
3576
3616
|
while (offset > -1 && offset < nodeAsParent.children.length) {
|
|
3577
3617
|
const child = nodeAsParent.children[offset];
|
|
@@ -3579,7 +3619,7 @@ function visitParents(tree2, test, visitor, reverse) {
|
|
|
3579
3619
|
if (subresult[0] === EXIT) {
|
|
3580
3620
|
return subresult;
|
|
3581
3621
|
}
|
|
3582
|
-
offset = typeof subresult[1] === "number" ? subresult[1] : offset +
|
|
3622
|
+
offset = typeof subresult[1] === "number" ? subresult[1] : offset + step3;
|
|
3583
3623
|
}
|
|
3584
3624
|
}
|
|
3585
3625
|
}
|
|
@@ -8222,9 +8262,9 @@ function tokenizeAutolink(effects, ok3, nok) {
|
|
|
8222
8262
|
}
|
|
8223
8263
|
function emailValue(code3) {
|
|
8224
8264
|
if ((code3 === 45 || asciiAlphanumeric(code3)) && size++ < 63) {
|
|
8225
|
-
const
|
|
8265
|
+
const next3 = code3 === 45 ? emailValue : emailLabel;
|
|
8226
8266
|
effects.consume(code3);
|
|
8227
|
-
return
|
|
8267
|
+
return next3;
|
|
8228
8268
|
}
|
|
8229
8269
|
return nok(code3);
|
|
8230
8270
|
}
|
|
@@ -11490,11 +11530,11 @@ function tokenizeTable(effects, ok3, nok) {
|
|
|
11490
11530
|
}
|
|
11491
11531
|
}
|
|
11492
11532
|
const tail = index2 > -1 ? self.events[index2][1].type : null;
|
|
11493
|
-
const
|
|
11494
|
-
if (
|
|
11533
|
+
const next3 = tail === "tableHead" || tail === "tableRow" ? bodyRowStart : headRowBefore;
|
|
11534
|
+
if (next3 === bodyRowStart && self.parser.lazy[self.now().line]) {
|
|
11495
11535
|
return nok(code3);
|
|
11496
11536
|
}
|
|
11497
|
-
return
|
|
11537
|
+
return next3(code3);
|
|
11498
11538
|
}
|
|
11499
11539
|
function headRowBefore(code3) {
|
|
11500
11540
|
effects.enter("tableHead");
|
|
@@ -12856,9 +12896,9 @@ function preprocess() {
|
|
|
12856
12896
|
break;
|
|
12857
12897
|
}
|
|
12858
12898
|
case 9: {
|
|
12859
|
-
const
|
|
12899
|
+
const next3 = Math.ceil(column / 4) * 4;
|
|
12860
12900
|
chunks.push(-2);
|
|
12861
|
-
while (column++ <
|
|
12901
|
+
while (column++ < next3) {
|
|
12862
12902
|
chunks.push(-1);
|
|
12863
12903
|
}
|
|
12864
12904
|
break;
|
|
@@ -13732,8 +13772,8 @@ function trough() {
|
|
|
13732
13772
|
if (typeof callback !== "function") {
|
|
13733
13773
|
throw new TypeError("Expected function as last argument, not " + callback);
|
|
13734
13774
|
}
|
|
13735
|
-
|
|
13736
|
-
function
|
|
13775
|
+
next3(null, ...values);
|
|
13776
|
+
function next3(error, ...output) {
|
|
13737
13777
|
const fn = fns[++middlewareIndex];
|
|
13738
13778
|
let index2 = -1;
|
|
13739
13779
|
if (error) {
|
|
@@ -13747,7 +13787,7 @@ function trough() {
|
|
|
13747
13787
|
}
|
|
13748
13788
|
values = output;
|
|
13749
13789
|
if (fn) {
|
|
13750
|
-
wrap(fn,
|
|
13790
|
+
wrap(fn, next3)(...output);
|
|
13751
13791
|
} else {
|
|
13752
13792
|
callback(null, ...output);
|
|
13753
13793
|
}
|
|
@@ -15401,6 +15441,11 @@ function fit(s, n) {
|
|
|
15401
15441
|
return cps.length > n ? `${cps.slice(0, Math.max(0, n - 1)).join("")}\u2026` : s + " ".repeat(n - cps.length);
|
|
15402
15442
|
}
|
|
15403
15443
|
|
|
15444
|
+
// src/tui/model/rigSeat.ts
|
|
15445
|
+
var rigTag = (s) => s.rig ? `[${s.rig.name}] ` : "";
|
|
15446
|
+
var rigRole = (s) => s.rig ? s.rig.role ?? s.rig.seat : "";
|
|
15447
|
+
var seatSecond = (s, rest) => s.rig ? [rigRole(s), rest].filter(Boolean).join(" \xB7 ") : rest;
|
|
15448
|
+
|
|
15404
15449
|
// src/tui/ui/now.ts
|
|
15405
15450
|
import { useSyncExternalStore as useSyncExternalStore4 } from "react";
|
|
15406
15451
|
var listeners = /* @__PURE__ */ new Set();
|
|
@@ -15534,10 +15579,10 @@ function fieldLines(text5, cursor, width, o) {
|
|
|
15534
15579
|
const at = cursor !== null && cursor >= r.a && cursor < r.b ? cursor : -1;
|
|
15535
15580
|
if (at < 0) line.push({ text: text5.slice(r.a, r.b), color: o.color });
|
|
15536
15581
|
else {
|
|
15537
|
-
const
|
|
15582
|
+
const next3 = after({ text: text5, cursor: at });
|
|
15538
15583
|
if (at > r.a) line.push({ text: text5.slice(r.a, at), color: o.color });
|
|
15539
|
-
line.push(inv(text5.slice(at, Math.min(
|
|
15540
|
-
if (
|
|
15584
|
+
line.push(inv(text5.slice(at, Math.min(next3, r.b))));
|
|
15585
|
+
if (next3 < r.b) line.push({ text: text5.slice(next3, r.b), color: o.color });
|
|
15541
15586
|
}
|
|
15542
15587
|
if (cursor === r.b && r.last) line.push(inv(" "));
|
|
15543
15588
|
return line.filter((s) => s.text !== "" || s === line[0]);
|
|
@@ -15655,11 +15700,11 @@ function Field({ value, onChange, onSubmit, onEscape, onBrowse, history = [], ac
|
|
|
15655
15700
|
}
|
|
15656
15701
|
};
|
|
15657
15702
|
const show = (b2, i) => {
|
|
15658
|
-
const
|
|
15659
|
-
const text5 =
|
|
15660
|
-
st.current = { f: { text: text5, cursor: text5.length }, browse:
|
|
15703
|
+
const next3 = b2 && i !== void 0 ? { ...b2, i } : b2;
|
|
15704
|
+
const text5 = next3 ? next3.items[next3.i] : st.current.f.text;
|
|
15705
|
+
st.current = { f: { text: text5, cursor: text5.length }, browse: next3, pasted: 0 };
|
|
15661
15706
|
render2();
|
|
15662
|
-
onBrowse?.(inHistory(
|
|
15707
|
+
onBrowse?.(inHistory(next3));
|
|
15663
15708
|
};
|
|
15664
15709
|
useInput((input, key) => {
|
|
15665
15710
|
const { f: f2, browse: browse2 } = st.current;
|
|
@@ -15877,6 +15922,10 @@ function SessionCard({ s, note }) {
|
|
|
15877
15922
|
" ",
|
|
15878
15923
|
t.state[state2]
|
|
15879
15924
|
] }),
|
|
15925
|
+
s.rig ? /* @__PURE__ */ jsxs5(Text5, { color: C.blue, children: [
|
|
15926
|
+
" ",
|
|
15927
|
+
t.overview.rigSeat(s.rig.name, s.rig.role ?? s.rig.seat)
|
|
15928
|
+
] }) : null,
|
|
15880
15929
|
/* @__PURE__ */ jsxs5(Text5, { color: C.dim, children: [
|
|
15881
15930
|
" ",
|
|
15882
15931
|
TOOL_NAME[s.tool],
|
|
@@ -15954,6 +16003,7 @@ function Tail({ lines, color: color2, empty: empty3, emptyColor }) {
|
|
|
15954
16003
|
// src/tui/screens/Overview.tsx
|
|
15955
16004
|
import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
15956
16005
|
var WIDE = 100;
|
|
16006
|
+
var folderOf = (cwd) => (cwd ?? "").split("/").filter(Boolean).at(-1) ?? "";
|
|
15957
16007
|
function windowed(rows, selectedKey, height) {
|
|
15958
16008
|
if (rows.length <= height) return [...rows];
|
|
15959
16009
|
const at = Math.max(0, rows.findIndex((r) => r.key === selectedKey));
|
|
@@ -15966,9 +16016,8 @@ function Overview() {
|
|
|
15966
16016
|
const { columns, rows: height } = useScreenSize();
|
|
15967
16017
|
const wide = columns >= WIDE;
|
|
15968
16018
|
const left2 = wide ? Math.min(64, Math.max(44, Math.floor(columns * 0.42))) : columns;
|
|
15969
|
-
const teams = useTeams(tui.client);
|
|
15970
16019
|
const tasks = useTasks(tui.client);
|
|
15971
|
-
const view = useMemo2(() => overview(d.sessions, projects
|
|
16020
|
+
const view = useMemo2(() => overview(d.sessions, projects), [d.sessions, projects]);
|
|
15972
16021
|
const sel = selected?.id ?? null;
|
|
15973
16022
|
const closed = closedLedgeTasks(tasks);
|
|
15974
16023
|
const decisions = useMemo2(() => openDecisions(tasks), [tasks]);
|
|
@@ -15990,11 +16039,6 @@ function Overview() {
|
|
|
15990
16039
|
};
|
|
15991
16040
|
const threshold = useContextNear(tui.client);
|
|
15992
16041
|
const near = useMemo2(() => nearContext(d.sessions, threshold), [d.sessions, threshold]);
|
|
15993
|
-
const [tasksShown, setTasksShown] = useState3(true);
|
|
15994
|
-
const [joining, setJoining] = useState3(null);
|
|
15995
|
-
const node2 = selected ? view.tree.find((n) => n.branches.some((b2) => b2.sessions.includes(selected)) || n.teams.some((x) => x.sessions.includes(selected))) : void 0;
|
|
15996
|
-
const seatTeam = selected?.team ? teams?.find((x) => x.id === selected.team && x.state !== "dissolved") : void 0;
|
|
15997
|
-
const choices2 = node2?.teams.map((x) => x.team).filter((x) => x.state !== "dissolved" && x.id !== selected?.team) ?? [];
|
|
15998
16042
|
useScreenKeys((input, key) => {
|
|
15999
16043
|
if (deciding) {
|
|
16000
16044
|
if (!deciding.confirm) {
|
|
@@ -16016,50 +16060,6 @@ function Overview() {
|
|
|
16016
16060
|
if (decisions[0]) setDeciding({ id: decisions[0].id, draft: "", confirm: false });
|
|
16017
16061
|
return true;
|
|
16018
16062
|
}
|
|
16019
|
-
if (joining) {
|
|
16020
|
-
if (key.escape) {
|
|
16021
|
-
setJoining(null);
|
|
16022
|
-
return true;
|
|
16023
|
-
}
|
|
16024
|
-
if (input === "j" || key.downArrow) {
|
|
16025
|
-
setJoining({ index: (joining.index + 1) % Math.max(1, choices2.length) });
|
|
16026
|
-
return true;
|
|
16027
|
-
}
|
|
16028
|
-
if (input === "k" || key.upArrow) {
|
|
16029
|
-
setJoining({ index: (joining.index + choices2.length - 1) % Math.max(1, choices2.length) });
|
|
16030
|
-
return true;
|
|
16031
|
-
}
|
|
16032
|
-
if (key.return && selected && choices2[joining.index]) {
|
|
16033
|
-
const team = choices2[joining.index];
|
|
16034
|
-
const role = selected.role ?? team.seats.find((x) => x.sessionId === null)?.role;
|
|
16035
|
-
setJoining(null);
|
|
16036
|
-
if (!role) {
|
|
16037
|
-
tui.toast({ text: t.overview.noTeamHere, tone: "info" });
|
|
16038
|
-
return true;
|
|
16039
|
-
}
|
|
16040
|
-
tui.client.send({ type: "team.join", team: team.id, session: selected.id, role });
|
|
16041
|
-
tui.toast({ text: t.toast.joined(selected.name, team.name), tone: "ok" });
|
|
16042
|
-
return true;
|
|
16043
|
-
}
|
|
16044
|
-
return true;
|
|
16045
|
-
}
|
|
16046
|
-
if (input === "J" && selected) {
|
|
16047
|
-
if (choices2.length) setJoining({ index: 0 });
|
|
16048
|
-
else tui.toast({ text: t.overview.noTeamHere, tone: "info" });
|
|
16049
|
-
return true;
|
|
16050
|
-
}
|
|
16051
|
-
if (input === "R") {
|
|
16052
|
-
const resting = (seatTeam?.state === "resting" ? seatTeam : void 0) ?? node2?.teams.find((x) => x.team.state === "resting")?.team ?? view.tree.flatMap((n) => n.teams).find((x) => x.team.state === "resting")?.team;
|
|
16053
|
-
if (resting) {
|
|
16054
|
-
tui.client.send({ type: "team.resume", team: resting.id });
|
|
16055
|
-
tui.toast({ text: t.toast.resumed(resting.name), tone: "ok" });
|
|
16056
|
-
}
|
|
16057
|
-
return true;
|
|
16058
|
-
}
|
|
16059
|
-
if (input === "T") {
|
|
16060
|
-
setTasksShown((v) => !v);
|
|
16061
|
-
return true;
|
|
16062
|
-
}
|
|
16063
16063
|
if (input === "H") {
|
|
16064
16064
|
const s = (selected && selected.source === "launcher" && selected.state !== "exited" && selected.tool !== "omp" && (!selected.handover || selected.handover.state === "failed") ? selected : void 0) ?? near.find((x) => x.handover?.state !== "failed") ?? near[0];
|
|
16065
16065
|
if (!s) return true;
|
|
@@ -16087,8 +16087,8 @@ function Overview() {
|
|
|
16087
16087
|
return true;
|
|
16088
16088
|
}
|
|
16089
16089
|
if (key.tab) {
|
|
16090
|
-
const
|
|
16091
|
-
if (
|
|
16090
|
+
const next3 = nextWaiting(view.yours, sel);
|
|
16091
|
+
if (next3) select(next3);
|
|
16092
16092
|
return true;
|
|
16093
16093
|
}
|
|
16094
16094
|
if (key.return) {
|
|
@@ -16112,22 +16112,25 @@ function Overview() {
|
|
|
16112
16112
|
}
|
|
16113
16113
|
return false;
|
|
16114
16114
|
});
|
|
16115
|
-
const
|
|
16116
|
-
|
|
16117
|
-
|
|
16115
|
+
const groupRows = (kind) => view.tree.filter((n) => n.kind === kind).flatMap((n) => [
|
|
16116
|
+
...kind === "rig" ? [{ kind: "project", key: n.key, label: n.label, color: C.blue, count: n.count, rig: true, folder: folderOf(n.branches[0]?.sessions[0]?.cwd) }] : [],
|
|
16117
|
+
...n.branches.flatMap((b2) => b2.sessions.map((s) => ({ kind: "session", key: s.id, s, indent: kind === "rig" ? 2 : 0, group: kind })))
|
|
16118
|
+
]);
|
|
16119
|
+
const rigRows = groupRows("rig"), kernelRows = groupRows("kernel");
|
|
16120
|
+
const tree2 = view.tree.filter((n) => !n.kind).flatMap((n) => {
|
|
16118
16121
|
return [
|
|
16119
16122
|
{ kind: "project", key: n.key, label: n.label, color: projectColor(n.color), count: n.count },
|
|
16120
|
-
...
|
|
16121
|
-
...n.branches.flatMap((b2) => [{ kind: "branch", key: `${n.key}|${b2.branch}`, branch: b2.branch, indent: teamed ? 4 : 2 }, ...b2.sessions.map((s) => ({ kind: "session", key: s.id, s, indent: teamed ? 2 : 0 }))]),
|
|
16122
|
-
...n.teams.flatMap((x) => [{ kind: "team", key: x.key, team: x.team, done: x.done, given: x.given }, ...x.sessions.map((s) => ({ kind: "session", key: s.id, s, indent: 2 }))])
|
|
16123
|
+
...n.branches.flatMap((b2) => [{ kind: "branch", key: `${n.key}|${b2.branch}`, branch: b2.branch, indent: 2 }, ...b2.sessions.map((s) => ({ kind: "session", key: s.id, s, indent: 0 }))])
|
|
16123
16124
|
];
|
|
16124
16125
|
});
|
|
16125
16126
|
const yoursCount = view.yours.length + decisions.length + closed.length + near.length;
|
|
16126
16127
|
const yoursHeight = Math.max(1, Math.min(yoursCount, 6));
|
|
16127
|
-
const joinHeight = joining && selected ? Math.max(1, choices2.length) + 2 : 0;
|
|
16128
16128
|
const answerLines = deciding?.confirm ? wrap2(deciding.draft.trim(), Math.max(10, columns - 4)) : [];
|
|
16129
16129
|
const decideHeight = !deciding ? 0 : deciding.confirm ? Math.min(answerLines.length, Math.max(1, height - 12)) + 2 : fieldRows(columns, height) + 2;
|
|
16130
|
-
const
|
|
16130
|
+
const allHeight = Math.max(3, height - 3 - (yoursHeight + 2) - decideHeight - 3);
|
|
16131
|
+
const kernelHeight = kernelRows.length ? Math.min(kernelRows.length, 5) : 0;
|
|
16132
|
+
const rigsHeight = rigRows.length ? Math.min(rigRows.length, Math.max(3, Math.floor(allHeight / 3))) : 0;
|
|
16133
|
+
const treeHeight = Math.max(3, allHeight - (rigsHeight ? rigsHeight + 2 : 0) - (kernelHeight ? kernelHeight + 2 : 0));
|
|
16131
16134
|
const inner = left2 - 4, nameW = 7;
|
|
16132
16135
|
const stateW = Math.max(...Object.values(t.state).map((x) => x.length)) + 1;
|
|
16133
16136
|
const topicW = Math.max(6, inner - 6 - nameW - stateW - 3);
|
|
@@ -16140,8 +16143,13 @@ function Overview() {
|
|
|
16140
16143
|
" "
|
|
16141
16144
|
] }),
|
|
16142
16145
|
/* @__PURE__ */ jsx10(Text7, { color: C.fg, bold: true, children: fit(s.name, nameW) }),
|
|
16143
|
-
/* @__PURE__ */
|
|
16144
|
-
|
|
16146
|
+
s.rig ? /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
16147
|
+
/* @__PURE__ */ jsx10(Text7, { children: " " }),
|
|
16148
|
+
/* @__PURE__ */ jsx10(Text7, { color: C.blue, children: rigTag(s) }),
|
|
16149
|
+
/* @__PURE__ */ jsx10(Text7, { color: C.dim, children: seatSecond(s, "") }),
|
|
16150
|
+
/* @__PURE__ */ jsx10(Text7, { children: " " })
|
|
16151
|
+
] }) : /* @__PURE__ */ jsx10(Text7, { color: C.dim, children: fit(s.repo ?? s.project, 9) }),
|
|
16152
|
+
/* @__PURE__ */ jsx10(Text7, { color: STATE_COLOR[st], children: fit(oneLine(s.pending?.text ?? ""), s.rig ? Math.max(6, askW + 9 - rigTag(s).length - seatSecond(s, "").length - 4) : askW) }),
|
|
16145
16153
|
/* @__PURE__ */ jsxs6(Text7, { color: C.faint, children: [
|
|
16146
16154
|
" ",
|
|
16147
16155
|
/* @__PURE__ */ jsx10(Ago, { iso: s.lastActivityAt })
|
|
@@ -16168,7 +16176,7 @@ function Overview() {
|
|
|
16168
16176
|
s.handover?.state === "failed" ? g.fail : "\u25D4",
|
|
16169
16177
|
" "
|
|
16170
16178
|
] }),
|
|
16171
|
-
/* @__PURE__ */ jsx10(Text7, { color: C.fg, children: s.handover?.state === "failed" ? t.overview.reliefFailed(s.name, s.handover.reason ?? "?") : t.overview.near(
|
|
16179
|
+
/* @__PURE__ */ jsx10(Text7, { color: C.fg, children: s.handover?.state === "failed" ? t.overview.reliefFailed(s.name, s.handover.reason ?? "?") : t.overview.near(s.name, Math.round((s.context?.used ?? 0) / (s.context?.window ?? 1) * 100)) })
|
|
16172
16180
|
] }, `near:${s.id}`))] });
|
|
16173
16181
|
const treeBox = /* @__PURE__ */ jsx10(TitledBox, { title: t.overview.projects, flexGrow: 1, children: tree2.length === 0 ? /* @__PURE__ */ jsx10(Text7, { color: C.faint, children: t.overview.noSession }) : windowed(tree2, sel, treeHeight).map((r) => r.kind === "project" ? /* @__PURE__ */ jsxs6(Text7, { wrap: "truncate", children: [
|
|
16174
16182
|
/* @__PURE__ */ jsx10(Text7, { color: r.color, children: g.project }),
|
|
@@ -16176,32 +16184,32 @@ function Overview() {
|
|
|
16176
16184
|
/* @__PURE__ */ jsx10(Text7, { color: C.fg, bold: true, children: r.label }),
|
|
16177
16185
|
" ",
|
|
16178
16186
|
/* @__PURE__ */ jsx10(Text7, { color: C.faint, children: t.overview.sessions(r.count) })
|
|
16179
|
-
] }, r.key) : r.kind === "common" ? /* @__PURE__ */ jsxs6(Text7, { wrap: "truncate", color: C.faint, children: [
|
|
16180
|
-
" ",
|
|
16181
|
-
g.common,
|
|
16182
|
-
" ",
|
|
16183
|
-
t.overview.common
|
|
16184
|
-
] }, r.key) : r.kind === "team" ? /* @__PURE__ */ jsxs6(Text7, { wrap: "truncate", children: [
|
|
16185
|
-
/* @__PURE__ */ jsx10(Text7, { children: " " }),
|
|
16186
|
-
/* @__PURE__ */ jsx10(Text7, { color: C.coral, children: g.team }),
|
|
16187
|
-
" ",
|
|
16188
|
-
/* @__PURE__ */ jsx10(Text7, { color: r.team.state === "resting" ? C.dim : C.fg, bold: true, children: r.team.name }),
|
|
16189
|
-
" ",
|
|
16190
|
-
/* @__PURE__ */ jsx10(Text7, { color: C.faint, children: r.team.state === "resting" ? t.overview.resting : t.overview.teamLine(r.done, r.given) })
|
|
16191
16187
|
] }, r.key) : r.kind === "branch" ? /* @__PURE__ */ jsxs6(Text7, { wrap: "truncate", color: C.faint, children: [
|
|
16192
16188
|
" ".repeat(r.indent),
|
|
16193
16189
|
g.branch,
|
|
16194
16190
|
" ",
|
|
16195
16191
|
r.branch
|
|
16196
|
-
] }, r.key) : /* @__PURE__ */ jsx10(SessionRow, { s: r.s, on: r.s.id === sel, nameW, topicW: Math.max(6, topicW - r.indent
|
|
16192
|
+
] }, r.key) : /* @__PURE__ */ jsx10(SessionRow, { s: r.s, on: r.s.id === sel, nameW, topicW: Math.max(6, topicW - r.indent), stateW, indent: r.indent }, r.key)) });
|
|
16193
|
+
const groupBox = (title2, rows, rowsHeight) => rows.length === 0 ? null : /* @__PURE__ */ jsx10(TitledBox, { title: title2, height: rowsHeight + 2, children: windowed(rows, sel, rowsHeight).map((r) => r.kind === "project" ? /* @__PURE__ */ jsxs6(Text7, { wrap: "truncate", children: [
|
|
16194
|
+
/* @__PURE__ */ jsx10(Text7, { color: r.color, children: "\u2B21" }),
|
|
16195
|
+
" ",
|
|
16196
|
+
/* @__PURE__ */ jsx10(Text7, { color: C.fg, bold: true, children: r.label }),
|
|
16197
|
+
r.folder ? /* @__PURE__ */ jsxs6(Text7, { color: C.faint, children: [
|
|
16198
|
+
" ",
|
|
16199
|
+
r.folder
|
|
16200
|
+
] }) : null,
|
|
16201
|
+
/* @__PURE__ */ jsxs6(Text7, { color: C.faint, children: [
|
|
16202
|
+
" ",
|
|
16203
|
+
t.overview.sessions(r.count)
|
|
16204
|
+
] })
|
|
16205
|
+
] }, r.key) : r.kind === "session" ? /* @__PURE__ */ jsx10(SessionRow, { s: r.s, on: r.s.id === sel, nameW, topicW: Math.max(6, topicW - r.indent), stateW, indent: r.indent, group: r.group }, r.key) : null) });
|
|
16206
|
+
const rigsBox = groupBox(t.overview.rigsGroup, rigRows, rigsHeight);
|
|
16207
|
+
const kernelBox = groupBox(t.overview.kernelGroup, kernelRows, kernelHeight);
|
|
16197
16208
|
const keys = deciding?.confirm ? [["y", t.keys.sendAnswer], ["n esc", t.keys.edit]] : deciding ? [["\u21B5", t.keys.review], ["alt+\u21B5", t.keys.newLine], ["esc", t.keys.cancel]] : [
|
|
16198
16209
|
["j k", t.keys.navigate],
|
|
16199
16210
|
["\u21B5", t.keys.open],
|
|
16200
16211
|
...view.yours.length ? [["tab", t.keys.next], ["y n", t.keys.answer]] : [],
|
|
16201
16212
|
["a", t.keys.attach],
|
|
16202
|
-
...seatTeam ? [["T", t.keys.tasks]] : [],
|
|
16203
|
-
...choices2.length ? [["J", t.keys.join]] : [],
|
|
16204
|
-
...view.tree.some((n) => n.teams.some((x) => x.team.state === "resting")) ? [["R", t.keys.resume]] : [],
|
|
16205
16213
|
...decisions.length ? [["D", t.keys.decide]] : [],
|
|
16206
16214
|
...near.length ? [["H", t.keys.handover]] : [],
|
|
16207
16215
|
["/", t.keys.ask],
|
|
@@ -16210,36 +16218,17 @@ function Overview() {
|
|
|
16210
16218
|
["?", t.keys.help],
|
|
16211
16219
|
["q", t.keys.quit]
|
|
16212
16220
|
];
|
|
16213
|
-
const teamTasks = seatTeam ? tasks.filter((x) => x.team === seatTeam.id && (!taskClosed(x) || x.updatedAt.slice(0, 10) === (/* @__PURE__ */ new Date()).toISOString().slice(0, 10))).slice(-4) : [];
|
|
16214
16221
|
return /* @__PURE__ */ jsxs6(Frame, { crumb: tui.machines.map((m) => `${m.label} ${m.ready ? g.machine : "\u25CB"}`).join(" "), keys, children: [
|
|
16215
16222
|
/* @__PURE__ */ jsxs6(Box8, { flexGrow: 1, children: [
|
|
16216
16223
|
/* @__PURE__ */ jsxs6(Box8, { flexDirection: "column", width: left2, flexShrink: 0, children: [
|
|
16217
16224
|
yoursBox,
|
|
16218
|
-
|
|
16219
|
-
|
|
16220
|
-
|
|
16221
|
-
x.name
|
|
16222
|
-
] }, x.id)) }) : null,
|
|
16223
|
-
treeBox
|
|
16225
|
+
treeBox,
|
|
16226
|
+
rigsBox,
|
|
16227
|
+
kernelBox
|
|
16224
16228
|
] }),
|
|
16225
16229
|
wide ? /* @__PURE__ */ jsxs6(Box8, { flexDirection: "column", flexGrow: 1, children: [
|
|
16226
16230
|
selected ? /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
16227
|
-
/* @__PURE__ */ jsx10(TitledBox, { title: `${selected.name} \xB7 ${oneLine(selected.topic ?? selected.title)}`, color: isPending(selected) ? C.red : C.line, titleColor: isPending(selected) ? C.red : C.dim, children: /* @__PURE__ */ jsx10(SessionCard, { s: selected, note: true }) }),
|
|
16228
|
-
seatTeam && tasksShown ? /* @__PURE__ */ jsx10(TitledBox, { title: t.overview.tasks(`${g.team} ${seatTeam.name}`), height: Math.max(3, teamTasks.length + 2), children: teamTasks.length === 0 ? /* @__PURE__ */ jsx10(Text7, { color: C.faint, children: t.overview.noTask }) : teamTasks.map((x) => /* @__PURE__ */ jsxs6(Text7, { wrap: "truncate", children: [
|
|
16229
|
-
/* @__PURE__ */ jsx10(Text7, { color: C.faint, children: x.id }),
|
|
16230
|
-
" ",
|
|
16231
|
-
/* @__PURE__ */ jsx10(Text7, { color: C.fg, children: x.title }),
|
|
16232
|
-
" ",
|
|
16233
|
-
/* @__PURE__ */ jsxs6(Text7, { color: C.dim, children: [
|
|
16234
|
-
x.giverName,
|
|
16235
|
-
" ",
|
|
16236
|
-
g.arrow,
|
|
16237
|
-
" ",
|
|
16238
|
-
x.ownerName
|
|
16239
|
-
] }),
|
|
16240
|
-
" ",
|
|
16241
|
-
/* @__PURE__ */ jsx10(Text7, { color: x.state === "done" ? C.green : x.state === "taken" ? C.blue : C.faint, children: t.ask.taskState[x.state] })
|
|
16242
|
-
] }, x.id)) }) : null,
|
|
16231
|
+
/* @__PURE__ */ jsx10(TitledBox, { title: `${selected.name}${selected.rig ? ` \xB7 ${t.overview.rigSeat(selected.rig.name, selected.rig.role ?? selected.rig.seat)}` : ""} \xB7 ${oneLine(selected.topic ?? selected.title)}`, color: isPending(selected) ? C.red : C.line, titleColor: isPending(selected) ? C.red : C.dim, children: /* @__PURE__ */ jsx10(SessionCard, { s: selected, note: true }) }),
|
|
16243
16232
|
/* @__PURE__ */ jsx10(TitledBox, { title: t.overview.terminal(paneName(selected)), flexGrow: 1, children: /* @__PURE__ */ jsx10(Tail, { lines: d.previews.get(selected.id) ?? [], color: C.dim, empty: t.overview.noPreview, emptyColor: C.faint }) })
|
|
16244
16233
|
] }) : /* @__PURE__ */ jsx10(TitledBox, { title: t.tabs.session, flexGrow: 1, children: /* @__PURE__ */ jsx10(Text7, { color: C.faint, children: t.session.noSession }) }),
|
|
16245
16234
|
/* @__PURE__ */ jsx10(TitledBox, { title: t.overview.exchanges, height: 5, children: (() => {
|
|
@@ -16279,7 +16268,7 @@ function Overview() {
|
|
|
16279
16268
|
) : null
|
|
16280
16269
|
] });
|
|
16281
16270
|
}
|
|
16282
|
-
function SessionRow({ s, on, nameW, topicW, stateW, indent: indent2 = 0 }) {
|
|
16271
|
+
function SessionRow({ s, on, nameW, topicW, stateW, indent: indent2 = 0, group }) {
|
|
16283
16272
|
const { t, g } = useTui();
|
|
16284
16273
|
const st = botState(s);
|
|
16285
16274
|
const n = helperCount(s);
|
|
@@ -16291,14 +16280,19 @@ function SessionRow({ s, on, nameW, topicW, stateW, indent: indent2 = 0 }) {
|
|
|
16291
16280
|
" "
|
|
16292
16281
|
] }),
|
|
16293
16282
|
/* @__PURE__ */ jsx10(Text7, { color: s.offline ? C.dim : C.fg, bold: true, children: fit(s.name, nameW) }),
|
|
16294
|
-
|
|
16295
|
-
"
|
|
16296
|
-
s.role,
|
|
16297
|
-
" "
|
|
16298
|
-
] }) : null,
|
|
16299
|
-
/* @__PURE__ */ jsxs6(Text7, { color: C.dim, children: [
|
|
16300
|
-
fit(oneLine(s.topic ?? s.title), topicW),
|
|
16283
|
+
group ? /* @__PURE__ */ jsxs6(Text7, { color: C.dim, children: [
|
|
16284
|
+
" ",
|
|
16285
|
+
fit(group === "kernel" ? `${(s.rig?.role ?? "").replace(/\.(agent|lead|worker)$/, "").padEnd(11)}${s.tool}` : s.rig?.role ?? "", topicW - 1),
|
|
16301
16286
|
" "
|
|
16287
|
+
] }) : /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
16288
|
+
s.rig ? /* @__PURE__ */ jsxs6(Text7, { color: C.blue, children: [
|
|
16289
|
+
" ",
|
|
16290
|
+
rigTag(s)
|
|
16291
|
+
] }) : null,
|
|
16292
|
+
/* @__PURE__ */ jsxs6(Text7, { color: C.dim, children: [
|
|
16293
|
+
fit(seatSecond(s, oneLine(s.topic ?? s.title)), s.rig ? Math.max(0, topicW - rigTag(s).length - 1) : topicW),
|
|
16294
|
+
" "
|
|
16295
|
+
] })
|
|
16302
16296
|
] }),
|
|
16303
16297
|
/* @__PURE__ */ jsx10(Text7, { color: s.offline ? C.faint : STATE_COLOR[st], children: fit(s.offline ? t.overview.offline : t.state[st], stateW).trimEnd() }),
|
|
16304
16298
|
n > 0 ? /* @__PURE__ */ jsxs6(Text7, { color: C.violet, children: [
|
|
@@ -16329,9 +16323,9 @@ function useChips(put) {
|
|
|
16329
16323
|
const { t, toast } = useTui();
|
|
16330
16324
|
const [items, setItems] = useState4([]);
|
|
16331
16325
|
const held = useRef8([]);
|
|
16332
|
-
const commit = (
|
|
16333
|
-
held.current =
|
|
16334
|
-
setItems(
|
|
16326
|
+
const commit = (next3) => {
|
|
16327
|
+
held.current = next3;
|
|
16328
|
+
setItems(next3);
|
|
16335
16329
|
};
|
|
16336
16330
|
const patch = (key, over) => commit(held.current.map((c) => c.key === key ? { ...c, ...over } : c));
|
|
16337
16331
|
const reasonOf = (e) => {
|
|
@@ -16374,10 +16368,10 @@ function useChips(put) {
|
|
|
16374
16368
|
}
|
|
16375
16369
|
};
|
|
16376
16370
|
}
|
|
16377
|
-
function ChipsLine({ chips }) {
|
|
16371
|
+
function ChipsLine({ chips: chips2 }) {
|
|
16378
16372
|
const { t } = useTui();
|
|
16379
|
-
if (
|
|
16380
|
-
return /* @__PURE__ */ jsx11(Text8, { wrap: "truncate", children:
|
|
16373
|
+
if (chips2.length === 0) return null;
|
|
16374
|
+
return /* @__PURE__ */ jsx11(Text8, { wrap: "truncate", children: chips2.map((c, i) => /* @__PURE__ */ jsxs7(Text8, { children: [
|
|
16381
16375
|
i ? " " : "",
|
|
16382
16376
|
/* @__PURE__ */ jsxs7(Text8, { color: c.state === "refused" ? C.red : C.dim, children: [
|
|
16383
16377
|
"\u25A3 ",
|
|
@@ -16396,14 +16390,14 @@ function ChipsLine({ chips }) {
|
|
|
16396
16390
|
] }, c.key)) });
|
|
16397
16391
|
}
|
|
16398
16392
|
var EXT = { "image/png": "png", "image/jpeg": "jpg", "image/gif": "gif", "image/webp": "webp" };
|
|
16399
|
-
function usePaste2(
|
|
16393
|
+
function usePaste2(chips2) {
|
|
16400
16394
|
const { readImage, toast, t } = useTui();
|
|
16401
16395
|
const reading = useRef8(false);
|
|
16402
16396
|
return () => {
|
|
16403
16397
|
if (reading.current) return;
|
|
16404
16398
|
reading.current = true;
|
|
16405
16399
|
void readImage().then((got) => {
|
|
16406
|
-
if (got)
|
|
16400
|
+
if (got) chips2.add(got);
|
|
16407
16401
|
else toast({ text: t.images.none, tone: "info" });
|
|
16408
16402
|
}, () => toast({ text: t.images.none, tone: "info" })).finally(() => {
|
|
16409
16403
|
reading.current = false;
|
|
@@ -16558,30 +16552,30 @@ function SessionView({ s }) {
|
|
|
16558
16552
|
setAnchor({ key, offset: top - lineKeys.indexOf(key) });
|
|
16559
16553
|
};
|
|
16560
16554
|
const images = useMemo3(() => (items ? threadImages(items, unfolded) : []).map((ref) => ({ ref, route: { id: s.id } })), [items, unfolded, s.id]);
|
|
16561
|
-
const
|
|
16562
|
-
const paste = usePaste2(
|
|
16555
|
+
const chips2 = useChips((image2) => putImage(client, image2, { id: s.id }));
|
|
16556
|
+
const paste = usePaste2(chips2);
|
|
16563
16557
|
const openImage2 = useOpenImage();
|
|
16564
16558
|
const machine = splitId(s.id)?.machine ?? "local";
|
|
16565
16559
|
const canSwitch = machines.find((m) => m.id === machine)?.daemon?.modelSwitch === true;
|
|
16566
16560
|
const send = (text5, { fromHistory }) => {
|
|
16567
|
-
const withImages = mode === "reply" && !fromHistory &&
|
|
16561
|
+
const withImages = mode === "reply" && !fromHistory && chips2.items.length > 0;
|
|
16568
16562
|
if (!text5.trim() && !withImages) {
|
|
16569
16563
|
setMode("read");
|
|
16570
16564
|
return true;
|
|
16571
16565
|
}
|
|
16572
|
-
if (withImages && !
|
|
16566
|
+
if (withImages && !chips2.ready) return false;
|
|
16573
16567
|
if (withImages && p?.kind === "question") {
|
|
16574
16568
|
toast({ text: t.images.dialog, tone: "info" });
|
|
16575
16569
|
return false;
|
|
16576
16570
|
}
|
|
16577
|
-
const taken = withImages ?
|
|
16571
|
+
const taken = withImages ? chips2.clear() : [];
|
|
16578
16572
|
const back2 = (x) => {
|
|
16579
16573
|
if (!kept.drafts.get(s.id)) setDraft(x);
|
|
16580
|
-
if (taken.length)
|
|
16574
|
+
if (taken.length) chips2.putBack(taken);
|
|
16581
16575
|
};
|
|
16582
16576
|
const how = taken.length ? { attachments: taken.flatMap((c) => c.id ? [c.id] : []) } : void 0;
|
|
16583
16577
|
if (!(mode === "note" ? actions.denyWithNote(s, text5.trim(), back2) : actions.reply(s, text5, back2, how))) {
|
|
16584
|
-
if (taken.length)
|
|
16578
|
+
if (taken.length) chips2.putBack(taken);
|
|
16585
16579
|
return false;
|
|
16586
16580
|
}
|
|
16587
16581
|
if (text5.trim()) kept.sent.set(s.id, [...kept.sent.get(s.id) ?? [], text5]);
|
|
@@ -16596,7 +16590,7 @@ function SessionView({ s }) {
|
|
|
16596
16590
|
};
|
|
16597
16591
|
useInput3((input, key) => {
|
|
16598
16592
|
if (key.meta && input === "v") paste();
|
|
16599
|
-
else if ((key.backspace || key.delete) && draft === "")
|
|
16593
|
+
else if ((key.backspace || key.delete) && draft === "") chips2.removeLast();
|
|
16600
16594
|
}, { isActive: mode === "reply" });
|
|
16601
16595
|
useScreenKeys((input, key) => {
|
|
16602
16596
|
if (mode === "model") return true;
|
|
@@ -16682,7 +16676,7 @@ function SessionView({ s }) {
|
|
|
16682
16676
|
if (input === "y" || input === "n" || input === "A" || /^[1-9]$/.test(input)) return actions.key(s, input);
|
|
16683
16677
|
return false;
|
|
16684
16678
|
});
|
|
16685
|
-
const title2 = `${s.name} \xB7 ${oneLine(s.topic ?? s.title)} \xB7 ${TOOL_NAME[s.tool]} \xB7 ${modelLabel(s, t.session.defaultModel)}`;
|
|
16679
|
+
const title2 = `${s.name}${s.rig ? ` \xB7 ${t.overview.rigSeat(s.rig.name, s.rig.role ?? s.rig.seat)}` : ""} \xB7 ${oneLine(s.topic ?? s.title)} \xB7 ${TOOL_NAME[s.tool]} \xB7 ${modelLabel(s, t.session.defaultModel)}`;
|
|
16686
16680
|
const showsThread = mode !== "model" && !terminal && !!items && lines.length > 0;
|
|
16687
16681
|
const above = lines.length - view - up;
|
|
16688
16682
|
const foot = up > 0 ? t.session.scrolled(above, up) : lines.length > view ? t.session.above(lines.length - view) : void 0;
|
|
@@ -16690,7 +16684,7 @@ function SessionView({ s }) {
|
|
|
16690
16684
|
const editing = mode === "reply" || mode === "note";
|
|
16691
16685
|
const body = rows - 2 - (lastToast ? 1 : 0);
|
|
16692
16686
|
const inner = Math.max(20, columns - 4);
|
|
16693
|
-
const below = (editing ? Math.min(fieldRows(columns, rows), layout(draft, Math.max(10, columns - 4) - 2).length) + 2 : 3) + (
|
|
16687
|
+
const below = (editing ? Math.min(fieldRows(columns, rows), layout(draft, Math.max(10, columns - 4) - 2).length) + 2 : 3) + (chips2.items.length ? 1 : 0);
|
|
16694
16688
|
let request2 = p ? ask(s, p, t, inner, 4, !editing) : null;
|
|
16695
16689
|
const over = request2 ? askRows(request2, inner) + below - body : 0;
|
|
16696
16690
|
if (p && request2 && over > 0) request2 = ask(s, p, t, inner, Math.max(1, 4 - over), !editing);
|
|
@@ -16712,7 +16706,7 @@ function SessionView({ s }) {
|
|
|
16712
16706
|
}
|
|
16713
16707
|
) : terminal ? /* @__PURE__ */ jsx13(Tail, { lines: d.previews.get(s.id) ?? [], color: C.dim, empty: t.overview.noPreview, emptyColor: C.faint }) : !items ? /* @__PURE__ */ jsx13(Text10, { color: C.faint, children: t.session.loading }) : lines.length === 0 ? /* @__PURE__ */ jsx13(Text10, { color: C.faint, children: t.session.empty }) : /* @__PURE__ */ jsx13(Lines, { lines, up, onHeight: setView }) }) : null,
|
|
16714
16708
|
p && request2 ? /* @__PURE__ */ jsx13(PendingBox, { s, a: request2 }) : null,
|
|
16715
|
-
/* @__PURE__ */ jsx13(ChipsLine, { chips:
|
|
16709
|
+
/* @__PURE__ */ jsx13(ChipsLine, { chips: chips2.items }),
|
|
16716
16710
|
mode === "reply" || mode === "note" ? /* @__PURE__ */ jsx13(
|
|
16717
16711
|
Field,
|
|
16718
16712
|
{
|
|
@@ -16782,7 +16776,7 @@ function actionRowOf(a) {
|
|
|
16782
16776
|
if (a.vars !== void 0) row2.vars = a.vars;
|
|
16783
16777
|
if (a.detail !== void 0 && a.action === "session.decide" && a.vars?.kind) row2.request = { kind: a.vars.kind, text: a.detail };
|
|
16784
16778
|
else if (a.detail !== void 0) row2.detail = a.detail;
|
|
16785
|
-
const target = a.vars?.session ?? a.vars?.owner
|
|
16779
|
+
const target = a.vars?.session ?? a.vars?.owner;
|
|
16786
16780
|
if (target !== void 0) row2.target = target;
|
|
16787
16781
|
if (a.vars?.decision === "accept" || a.vars?.decision === "deny") row2.decision = a.vars.decision;
|
|
16788
16782
|
if (a.action === "session.decide" && row2.decision !== "deny") row2.deny = { summary: a.summary };
|
|
@@ -16875,7 +16869,6 @@ function chatView(turns2, live, o) {
|
|
|
16875
16869
|
out.push([{ text: "" }], ...markdownLines(text5, { width: width - 2, g, color: C.fg }).map((l) => [pad(2), ...l]));
|
|
16876
16870
|
if (streaming !== void 0) out.push([pad(2), { text: g.caret, color: C.coral }]);
|
|
16877
16871
|
} else out.push([{ text: ` ${t.ask.reading}`, color: C.faint }]);
|
|
16878
|
-
if (turn.team?.teamId && turn.team.launchedAt) out.push([{ text: ` ${g.team} ${turn.team.name} \xB7 ${t.ask.teamLaunched(clock(turn.team.launchedAt))}`, color: C.green }]);
|
|
16879
16872
|
for (const c of turn.tasks ?? []) if (c.taskId) out.push([{ text: ` ${c.title} \xB7 ${t.ask.given(c.ownerName ?? c.toName ?? c.to, c.taskId, t.ask.taskState[c.state ?? "open"])}`, color: C.green }]);
|
|
16880
16873
|
out.push(...actionTrace(turn, t, g, width));
|
|
16881
16874
|
for (const l of out) {
|
|
@@ -16887,7 +16880,7 @@ function chatView(turns2, live, o) {
|
|
|
16887
16880
|
}
|
|
16888
16881
|
function actionTrace(turn, t, g, width) {
|
|
16889
16882
|
const a = t.ask.action, c = a.copy;
|
|
16890
|
-
const cards = !!(turn.actions || turn.proposal || turn.relay || turn.closes || turn.
|
|
16883
|
+
const cards = !!(turn.actions || turn.proposal || turn.relay || turn.closes || turn.tasks || turn.projectProposal);
|
|
16891
16884
|
if (turn.ignoredAt) {
|
|
16892
16885
|
const shown = turn.actions ? cardPlan(turn.actions).shown : [];
|
|
16893
16886
|
const sent = { done: shown.filter((s) => s === "done").length, denied: shown.filter((s) => s === "denied").length, failed: shown.filter((s) => s === "failed").length };
|
|
@@ -16916,7 +16909,6 @@ function openCards(turns2) {
|
|
|
16916
16909
|
for (const turn of [...turns2].reverse()) {
|
|
16917
16910
|
if (!turn.answeredAt || turn.ignoredAt) continue;
|
|
16918
16911
|
if (turn.actions && !cardClosed(turn.actions)) out.push({ kind: "action", qid: turn.qid });
|
|
16919
|
-
if (turn.team && !turn.team.teamId) out.push({ kind: "team", qid: turn.qid });
|
|
16920
16912
|
const tasks = (turn.tasks ?? []).map((c, i) => c.taskId ? -1 : i).filter((i) => i >= 0);
|
|
16921
16913
|
if (tasks.length) out.push({ kind: "task", qid: turn.qid, rows: tasks });
|
|
16922
16914
|
const launch2 = proposalRows(turn).map((p, i) => p.launchedId ? -1 : i).filter((i) => i >= 0);
|
|
@@ -17111,8 +17103,8 @@ function Ask() {
|
|
|
17111
17103
|
const [focus, setFocus] = useState9(-1);
|
|
17112
17104
|
const [anchor, setAnchor] = useState9(null);
|
|
17113
17105
|
const [view, setView] = useState9(10);
|
|
17114
|
-
const
|
|
17115
|
-
const paste = usePaste2(
|
|
17106
|
+
const chips2 = useChips(null);
|
|
17107
|
+
const paste = usePaste2(chips2);
|
|
17116
17108
|
const openImage2 = useOpenImage();
|
|
17117
17109
|
const [busy, setBusy] = useState9(null);
|
|
17118
17110
|
const [rowOf2, setRowOf] = useState9({});
|
|
@@ -17126,7 +17118,7 @@ function Ask() {
|
|
|
17126
17118
|
if (!s || !turn) return;
|
|
17127
17119
|
if (turn.error) {
|
|
17128
17120
|
sentAsk.current = null;
|
|
17129
|
-
|
|
17121
|
+
chips2.putBack(s.taken);
|
|
17130
17122
|
setDraft(kept.drafts.get("ask") || s.text);
|
|
17131
17123
|
} else if (turn.answeredAt) sentAsk.current = null;
|
|
17132
17124
|
}, [d.chat]);
|
|
@@ -17135,7 +17127,7 @@ function Ask() {
|
|
|
17135
17127
|
lines: Math.floor((height - 6) / Math.max(1, cards.length)),
|
|
17136
17128
|
height: (text5, indent2) => text5.split("\n").reduce((n, l) => n + Math.max(1, wrapSegs([{ text: l, color: C.fg }], Math.max(10, columns - 8 - indent2)).length), 0)
|
|
17137
17129
|
};
|
|
17138
|
-
const
|
|
17130
|
+
const planOf2 = (turn) => cardPlan(turn.actions ?? [], room);
|
|
17139
17131
|
useEffect10(() => {
|
|
17140
17132
|
if (focus >= cards.length) setFocus(cards.length ? cards.length - 1 : -1);
|
|
17141
17133
|
}, [cards.length, focus]);
|
|
@@ -17152,7 +17144,7 @@ function Ask() {
|
|
|
17152
17144
|
}, [confirming, cards]);
|
|
17153
17145
|
useEffect10(() => {
|
|
17154
17146
|
const turn = confirming && d.chat.find((x) => x.qid === confirming.qid);
|
|
17155
|
-
if (turn && !confirming.rows.every((i) => appliable(
|
|
17147
|
+
if (turn && !confirming.rows.every((i) => appliable(planOf2(turn).shown[i]))) setConfirming(null);
|
|
17156
17148
|
});
|
|
17157
17149
|
const ignored = [...d.chat].filter((x) => x.ignoredAt).sort((a, b2) => b2.ignoredAt.localeCompare(a.ignoredAt))[0];
|
|
17158
17150
|
useEffect10(() => {
|
|
@@ -17174,7 +17166,7 @@ function Ask() {
|
|
|
17174
17166
|
const local = machines.find((m) => m.id === "local");
|
|
17175
17167
|
const asking = d.chat.find((x) => !x.answeredAt && !x.error);
|
|
17176
17168
|
const ask2 = (text5, { fromHistory }) => {
|
|
17177
|
-
const images = fromHistory ? [] :
|
|
17169
|
+
const images = fromHistory ? [] : chips2.uploads();
|
|
17178
17170
|
if (!text5.trim() && images.length === 0) return true;
|
|
17179
17171
|
if (!local?.ready) {
|
|
17180
17172
|
toast({ text: t.ask.offline, tone: "info" });
|
|
@@ -17185,7 +17177,7 @@ function Ask() {
|
|
|
17185
17177
|
daemonStore.beginTurn({ qid, ...asked2, steps: [] });
|
|
17186
17178
|
client.send({ type: "chat.ask", qid, text: asked2.question, ...images.length ? { images } : {} });
|
|
17187
17179
|
kept.asked.push(asked2);
|
|
17188
|
-
if (images.length) sentAsk.current = { qid, taken:
|
|
17180
|
+
if (images.length) sentAsk.current = { qid, taken: chips2.clear(), text: asked2.question };
|
|
17189
17181
|
if (!fromHistory) setDraft("");
|
|
17190
17182
|
return true;
|
|
17191
17183
|
};
|
|
@@ -17194,21 +17186,13 @@ function Ask() {
|
|
|
17194
17186
|
const turn = d.chat.find((x) => x.qid === card2.qid);
|
|
17195
17187
|
if (!turn) return;
|
|
17196
17188
|
if (card2.kind === "task") {
|
|
17197
|
-
const row2 = card2.rows
|
|
17198
|
-
const c = turn.tasks[r];
|
|
17199
|
-
return !c.to.startsWith("@") || c.team || turn.team?.teamId;
|
|
17200
|
-
});
|
|
17201
|
-
if (row2 === void 0) {
|
|
17202
|
-
toast({ text: t.ask.waitTeam, tone: "info" });
|
|
17203
|
-
return;
|
|
17204
|
-
}
|
|
17189
|
+
const row2 = card2.rows[0];
|
|
17205
17190
|
setBusy({ qid: card2.qid, turn, errorSeq: d.errors.at(-1)?.seq ?? 0, at: Date.now() });
|
|
17206
17191
|
client.send({ type: "task.cmd", rid: randomUUID2(), by: LEDGE_GIVER, op: "give", qid: card2.qid, row: row2 });
|
|
17207
17192
|
return;
|
|
17208
17193
|
}
|
|
17209
17194
|
setBusy({ qid: card2.qid, turn, errorSeq: d.errors.at(-1)?.seq ?? 0, at: Date.now() });
|
|
17210
|
-
if (card2.kind === "
|
|
17211
|
-
else if (card2.kind === "launch") {
|
|
17195
|
+
if (card2.kind === "launch") {
|
|
17212
17196
|
const first = proposalRows(turn)[card2.rows[0]];
|
|
17213
17197
|
client.send({ type: "session.launch", tool: first.tool, cwd: first.cwd, ...first.prompt ? { prompt: first.prompt } : {}, qid: card2.qid, rows: card2.rows });
|
|
17214
17198
|
} else if (card2.kind === "relay") client.send({ type: turn.relay?.status === "queued" ? "session.relay.cancel" : "session.relay", qid: card2.qid });
|
|
@@ -17223,7 +17207,7 @@ function Ask() {
|
|
|
17223
17207
|
const actionKey = (qid, input, key) => {
|
|
17224
17208
|
const turn = d.chat.find((x) => x.qid === qid);
|
|
17225
17209
|
if (!turn?.actions) return false;
|
|
17226
|
-
const p =
|
|
17210
|
+
const p = planOf2(turn);
|
|
17227
17211
|
const sel = selectedRow(p, rowOf2[qid]);
|
|
17228
17212
|
const ask3 = (rows) => {
|
|
17229
17213
|
if (rows.some((i) => p.rows[i].risk === "destructive")) setConfirming({ qid, rows });
|
|
@@ -17315,7 +17299,7 @@ function Ask() {
|
|
|
17315
17299
|
return;
|
|
17316
17300
|
}
|
|
17317
17301
|
if ((key.backspace || key.delete) && l.focus === -1 && l.draft === "") {
|
|
17318
|
-
|
|
17302
|
+
chips2.removeLast();
|
|
17319
17303
|
return;
|
|
17320
17304
|
}
|
|
17321
17305
|
if (key.meta && input === "o" && l.turnImages.length) {
|
|
@@ -17375,11 +17359,6 @@ function Ask() {
|
|
|
17375
17359
|
act(cards[focus]);
|
|
17376
17360
|
return true;
|
|
17377
17361
|
}
|
|
17378
|
-
if (input === "s" && cards[focus].kind === "team") {
|
|
17379
|
-
const team = d.chat.find((x) => x.qid === cards[focus].qid)?.team;
|
|
17380
|
-
if (team && !team.template && !team.savedPath) client.send({ type: "team.save", rid: randomUUID2(), qid: cards[focus].qid, name: team.name, seats: team.seats.map((x) => ({ role: x.role, tool: x.tool, ...x.model ? { model: x.model } : {}, ...x.effort ? { effort: x.effort } : {}, ...x.name ? { name: x.name } : {} })) });
|
|
17381
|
-
return true;
|
|
17382
|
-
}
|
|
17383
17362
|
if (key.escape) {
|
|
17384
17363
|
setFocus(-1);
|
|
17385
17364
|
return true;
|
|
@@ -17393,23 +17372,23 @@ function Ask() {
|
|
|
17393
17372
|
const turn = d.chat.find((x) => x.qid === qid);
|
|
17394
17373
|
if (!turn?.actions) return [];
|
|
17395
17374
|
if (confirming?.qid === qid) return [["y", t.keys.apply], ["esc", t.keys.cancel]];
|
|
17396
|
-
const p =
|
|
17375
|
+
const p = planOf2(turn);
|
|
17397
17376
|
const sel = selectedRow(p, rowOf2[qid]);
|
|
17398
17377
|
const r = p.rows[sel], s = p.shown[sel], many = p.rows.length > 1;
|
|
17399
|
-
const
|
|
17400
|
-
if (s === "cut") return [["n", t.keys.deny], ["o", t.keys.openSession(r.target ?? "")], ["esc", t.keys.ignore],
|
|
17401
|
-
if (!p.open.length) return [
|
|
17378
|
+
const next3 = ["tab", focus + 1 < cards.length ? t.keys.nextCard : t.keys.conversation];
|
|
17379
|
+
if (s === "cut") return [["n", t.keys.deny], ["o", t.keys.openSession(r.target ?? "")], ["esc", t.keys.ignore], next3, ["ctrl+n", t.keys.newChat]];
|
|
17380
|
+
if (!p.open.length) return [next3, ["ctrl+n", t.keys.newChat], ["esc", t.keys.back]];
|
|
17402
17381
|
return [
|
|
17403
17382
|
["\u21B5", many ? t.keys.applyRow : t.keys.apply],
|
|
17404
17383
|
...many ? [["a", t.keys.applyAll], ["\u2191 \u2193", t.keys.line]] : [],
|
|
17405
17384
|
...deniable(r, s) ? [["n", t.keys.deny]] : [],
|
|
17406
17385
|
["esc", t.keys.ignore],
|
|
17407
|
-
|
|
17386
|
+
next3,
|
|
17408
17387
|
["ctrl+n", t.keys.newChat]
|
|
17409
17388
|
];
|
|
17410
17389
|
};
|
|
17411
17390
|
const history = askHistory(d.chat, kept.asked);
|
|
17412
|
-
const keys = confirm ? [["n esc", t.keys.keep], ["y", t.keys.wipe]] : focus === -1 && browsing ? [["\u21B5", t.keys.resend], ["\u2191 \u2193", t.keys.history], ["esc", t.keys.backToDraft]] : focus === -1 ? [["\u21B5", t.keys.sendOnly], ...review$, ["alt+\u21B5", t.keys.newLine], ["esc", t.keys.back], ["PgUp PgDn", t.keys.scroll], ["\u2191 \u2193", t.keys.history], ["tab", cards.length ? t.keys.nextCard : t.keys.conversation], ["alt+v", t.keys.image], ...turnImages.length ? [["alt+o", t.keys.openImage]] : [], ["ctrl+n", t.keys.newChat], ...stop] : focus === CONVO ? [["j k", t.keys.line], ["PgUp PgDn", t.keys.page], ["G", t.keys.end], ...stop, ["tab", t.keys.question], ["esc", t.keys.question]] : card?.kind === "action" ? [...actionKeys(card.qid), ...stop, ...review$] : [["\u21B5", t.keys.send], ["tab", focus + 1 < cards.length ? t.keys.nextCard : t.keys.conversation],
|
|
17391
|
+
const keys = confirm ? [["n esc", t.keys.keep], ["y", t.keys.wipe]] : focus === -1 && browsing ? [["\u21B5", t.keys.resend], ["\u2191 \u2193", t.keys.history], ["esc", t.keys.backToDraft]] : focus === -1 ? [["\u21B5", t.keys.sendOnly], ...review$, ["alt+\u21B5", t.keys.newLine], ["esc", t.keys.back], ["PgUp PgDn", t.keys.scroll], ["\u2191 \u2193", t.keys.history], ["tab", cards.length ? t.keys.nextCard : t.keys.conversation], ["alt+v", t.keys.image], ...turnImages.length ? [["alt+o", t.keys.openImage]] : [], ["ctrl+n", t.keys.newChat], ...stop] : focus === CONVO ? [["j k", t.keys.line], ["PgUp PgDn", t.keys.page], ["G", t.keys.end], ...stop, ["tab", t.keys.question], ["esc", t.keys.question]] : card?.kind === "action" ? [...actionKeys(card.qid), ...stop, ...review$] : [["\u21B5", t.keys.send], ["tab", focus + 1 < cards.length ? t.keys.nextCard : t.keys.conversation], ["ctrl+n", t.keys.newChat], ...stop, ["esc", t.keys.back]];
|
|
17413
17392
|
const foot = up > 0 ? asking && live?.qid === asking.qid ? t.ask.answering : t.session.scrolled(lines.length - view - up, up) : lines.length > view ? focus === CONVO ? t.session.above(lines.length - view) : t.ask.above(lines.length - view) : void 0;
|
|
17414
17393
|
const reading = focus === CONVO;
|
|
17415
17394
|
return /* @__PURE__ */ jsxs11(Frame, { crumb: `${t.tabs.ask}`, keys, kept: draft !== "", children: [
|
|
@@ -17428,7 +17407,7 @@ function Ask() {
|
|
|
17428
17407
|
cards.map((c, i) => {
|
|
17429
17408
|
const turn = d.chat.find((x) => x.qid === c.qid);
|
|
17430
17409
|
if (c.kind !== "action") return /* @__PURE__ */ jsx15(CardBox, { card: c, turn, focused: i === focus, busy: busy?.qid === c.qid }, `${c.kind}:${c.qid}`);
|
|
17431
|
-
const p =
|
|
17410
|
+
const p = planOf2(turn);
|
|
17432
17411
|
const sel = selectedRow(p, rowOf2[c.qid]);
|
|
17433
17412
|
return /* @__PURE__ */ jsx15(ActionBox, { turn, plan: p, focused: i === focus, busy: busy?.qid === c.qid, sel, confirming: confirming?.qid === c.qid ? confirming.rows : null }, `action:${c.qid}`);
|
|
17434
17413
|
}),
|
|
@@ -17442,7 +17421,7 @@ function Ask() {
|
|
|
17442
17421
|
/* @__PURE__ */ jsx15(Button, { label: t.ask.wipe, k: "y" })
|
|
17443
17422
|
] })
|
|
17444
17423
|
] }) : /* @__PURE__ */ jsxs11(Fragment4, { children: [
|
|
17445
|
-
/* @__PURE__ */ jsx15(ChipsLine, { chips:
|
|
17424
|
+
/* @__PURE__ */ jsx15(ChipsLine, { chips: chips2.items }),
|
|
17446
17425
|
/* @__PURE__ */ jsx15(
|
|
17447
17426
|
Field,
|
|
17448
17427
|
{
|
|
@@ -17465,46 +17444,8 @@ function Ask() {
|
|
|
17465
17444
|
function CardBox({ card, turn, focused, busy }) {
|
|
17466
17445
|
const { t, g } = useTui();
|
|
17467
17446
|
const color2 = focused ? C.coral : C.line;
|
|
17468
|
-
if (card.kind === "team") {
|
|
17469
|
-
const team = turn.team;
|
|
17470
|
-
const auto = team.seats.filter((x) => x.autonomy === "auto").map((x) => `@${x.role}`);
|
|
17471
|
-
return /* @__PURE__ */ jsxs11(TitledBox, { title: t.ask.teamCard(team.name), flexShrink: 0, color: color2, titleColor: C.coral, children: [
|
|
17472
|
-
/* @__PURE__ */ jsxs11(Text12, { wrap: "truncate", children: [
|
|
17473
|
-
/* @__PURE__ */ jsx15(Text12, { color: C.dim, children: t.ask.folder.padEnd(13) }),
|
|
17474
|
-
/* @__PURE__ */ jsx15(Text12, { color: C.faint, children: team.cwd })
|
|
17475
|
-
] }),
|
|
17476
|
-
/* @__PURE__ */ jsxs11(Text12, { wrap: "truncate", children: [
|
|
17477
|
-
/* @__PURE__ */ jsx15(Text12, { color: C.dim, children: t.ask.table.padEnd(13) }),
|
|
17478
|
-
g.team,
|
|
17479
|
-
" ",
|
|
17480
|
-
t.ask.newTable(team.projectName ?? team.project)
|
|
17481
|
-
] }),
|
|
17482
|
-
team.seats.map((x) => /* @__PURE__ */ jsxs11(Text12, { wrap: "truncate", children: [
|
|
17483
|
-
/* @__PURE__ */ jsx15(Text12, { color: C.dim, children: "".padEnd(13) }),
|
|
17484
|
-
/* @__PURE__ */ jsxs11(Text12, { color: C.violet, children: [
|
|
17485
|
-
"@",
|
|
17486
|
-
x.role
|
|
17487
|
-
] }),
|
|
17488
|
-
" ",
|
|
17489
|
-
x.label,
|
|
17490
|
-
" ",
|
|
17491
|
-
/* @__PURE__ */ jsx15(Text12, { color: C.faint, children: [TOOL_NAME[x.tool], x.model, x.effort].filter(Boolean).join(" \xB7 ") }),
|
|
17492
|
-
" ",
|
|
17493
|
-
/* @__PURE__ */ jsx15(Text12, { color: x.autonomy === "auto" ? C.yellow : C.faint, children: t.ask.autonomy[x.autonomy ?? "ask"] })
|
|
17494
|
-
] }, x.role)),
|
|
17495
|
-
auto.length ? /* @__PURE__ */ jsx15(Text12, { color: C.yellow, wrap: "truncate", children: t.ask.autoWarning(auto.join(", ")) }) : null,
|
|
17496
|
-
team.error ? /* @__PURE__ */ jsx15(Text12, { color: C.red, wrap: "truncate", children: team.error }) : null,
|
|
17497
|
-
team.saveError && !team.savedPath ? /* @__PURE__ */ jsx15(Text12, { color: C.red, wrap: "truncate", children: team.saveError }) : null,
|
|
17498
|
-
/* @__PURE__ */ jsxs11(Box12, { columnGap: 2, children: [
|
|
17499
|
-
/* @__PURE__ */ jsx15(Button, { label: busy ? `${g.live} ${t.ask.launchTeam}` : t.ask.launchTeam, k: "\u21B5", primary: focused }),
|
|
17500
|
-
!team.template ? team.savedPath ? /* @__PURE__ */ jsx15(Text12, { color: C.faint, children: t.ask.saved }) : /* @__PURE__ */ jsx15(Button, { label: t.ask.save, k: "s" }) : null,
|
|
17501
|
-
/* @__PURE__ */ jsx15(Text12, { color: C.faint, children: t.ask.nothingWithoutYou })
|
|
17502
|
-
] })
|
|
17503
|
-
] });
|
|
17504
|
-
}
|
|
17505
17447
|
if (card.kind === "task") {
|
|
17506
17448
|
const tasks = turn.tasks;
|
|
17507
|
-
const waits = !!turn.team && !turn.team.teamId;
|
|
17508
17449
|
return /* @__PURE__ */ jsxs11(TitledBox, { title: t.ask.taskCard, flexShrink: 0, color: color2, titleColor: C.violet, children: [
|
|
17509
17450
|
card.rows.map((r) => {
|
|
17510
17451
|
const c = tasks[r];
|
|
@@ -17518,10 +17459,7 @@ function CardBox({ card, turn, focused, busy }) {
|
|
|
17518
17459
|
] }) : null
|
|
17519
17460
|
] }, r);
|
|
17520
17461
|
}),
|
|
17521
|
-
/* @__PURE__ */
|
|
17522
|
-
/* @__PURE__ */ jsx15(Button, { label: busy ? `${g.live} ${t.ask.give}` : t.ask.give, k: "\u21B5", primary: focused && !waits }),
|
|
17523
|
-
waits ? /* @__PURE__ */ jsx15(Text12, { color: C.faint, children: t.ask.waitTeam }) : null
|
|
17524
|
-
] })
|
|
17462
|
+
/* @__PURE__ */ jsx15(Box12, { columnGap: 2, children: /* @__PURE__ */ jsx15(Button, { label: busy ? `${g.live} ${t.ask.give}` : t.ask.give, k: "\u21B5", primary: focused }) })
|
|
17525
17463
|
] });
|
|
17526
17464
|
}
|
|
17527
17465
|
if (card.kind === "launch") {
|
|
@@ -17581,7 +17519,7 @@ function CardBox({ card, turn, focused, busy }) {
|
|
|
17581
17519
|
}
|
|
17582
17520
|
|
|
17583
17521
|
// src/tui/screens/Launch.tsx
|
|
17584
|
-
import { useEffect as useEffect11, useMemo as useMemo5,
|
|
17522
|
+
import { useEffect as useEffect11, useMemo as useMemo5, useState as useState10 } from "react";
|
|
17585
17523
|
import { Box as Box13, Text as Text14, useInput as useInput6 } from "ink";
|
|
17586
17524
|
|
|
17587
17525
|
// ../fleet/src/launch.ts
|
|
@@ -17626,8 +17564,8 @@ function missingOf(f, machines) {
|
|
|
17626
17564
|
return null;
|
|
17627
17565
|
}
|
|
17628
17566
|
function previewOf(f, sessions, projectIdOf) {
|
|
17629
|
-
const
|
|
17630
|
-
const taken = sessions.filter((s) => s.state !== "exited" &&
|
|
17567
|
+
const machineOf2 = (s) => splitId(s.id)?.machine ?? s.machineId ?? "local";
|
|
17568
|
+
const taken = sessions.filter((s) => s.state !== "exited" && machineOf2(s) === f.machine).map((s) => s.name);
|
|
17631
17569
|
const seated = f.project === null ? 0 : sessions.filter((s) => projectIdOf(s) === f.project).length;
|
|
17632
17570
|
return { name: pickName(taken), seat: seated + 1 };
|
|
17633
17571
|
}
|
|
@@ -17648,9 +17586,6 @@ function launchMessage(f, name) {
|
|
|
17648
17586
|
};
|
|
17649
17587
|
}
|
|
17650
17588
|
|
|
17651
|
-
// src/tui/screens/Launch.tsx
|
|
17652
|
-
import { randomUUID as randomUUID3 } from "crypto";
|
|
17653
|
-
|
|
17654
17589
|
// src/tui/ui/TextInput.tsx
|
|
17655
17590
|
import { Text as Text13, useInput as useInput5 } from "ink";
|
|
17656
17591
|
import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
@@ -17709,25 +17644,9 @@ function ProjectChoice({ project, on }) {
|
|
|
17709
17644
|
] });
|
|
17710
17645
|
}
|
|
17711
17646
|
function Launch() {
|
|
17712
|
-
const { catalog } = useTui();
|
|
17713
|
-
const [prefill] = useState10(() => {
|
|
17714
|
-
const p = catalog.current.launch;
|
|
17715
|
-
catalog.current.launch = void 0;
|
|
17716
|
-
return p;
|
|
17717
|
-
});
|
|
17718
|
-
const [team, setTeam] = useState10(prefill?.template !== void 0);
|
|
17719
|
-
return team ? /* @__PURE__ */ jsx17(TeamLaunch, { onSession: () => setTeam(false), prefill: prefill?.template !== void 0 ? prefill : void 0 }) : /* @__PURE__ */ jsx17(SessionLaunch, { onTeam: () => setTeam(true), prefill: prefill?.template === void 0 ? prefill : void 0 });
|
|
17720
|
-
}
|
|
17721
|
-
function SessionLaunch({ onTeam, prefill }) {
|
|
17722
17647
|
const { client, d, machines, projects, t, g, toast, go, select, small } = useTui();
|
|
17723
17648
|
const list3 = projects?.projects ?? [];
|
|
17724
|
-
const
|
|
17725
|
-
const [form, setForm] = useState10(() => {
|
|
17726
|
-
const tool = prefill?.role?.tool ?? "claude";
|
|
17727
|
-
const base = withPick(launchDefaults(list3, machines, prefill?.project ? { project: prefill.project } : {}, tool), rolePick(prefill?.role, tool));
|
|
17728
|
-
const f = prefill ? withMachine(base, list3, prefill.machine) : base;
|
|
17729
|
-
return prefill?.cwd ? { ...f, repos: [prefill.cwd] } : f;
|
|
17730
|
-
});
|
|
17649
|
+
const [form, setForm] = useState10(() => launchDefaults(list3, machines, {}, "claude"));
|
|
17731
17650
|
const [field, setField] = useState10("prompt");
|
|
17732
17651
|
const [folder, setFolder] = useState10("");
|
|
17733
17652
|
const [repoAt, setRepoAt] = useState10(0);
|
|
@@ -17751,33 +17670,6 @@ function SessionLaunch({ onTeam, prefill }) {
|
|
|
17751
17670
|
return own4.length ? own4 : (machine?.recents ?? []).slice(0, 6).map((r) => r.cwd);
|
|
17752
17671
|
}, [project, form.machine, machine?.recents]);
|
|
17753
17672
|
const withFolder = folder.trim() ? { ...form, repos: MULTI_REPO_TOOLS.has(form.tool) ? [folder.trim(), ...form.repos.filter((r) => r !== folder.trim())] : [folder.trim()] } : form;
|
|
17754
|
-
const target = withFolder.repos[0] ?? null;
|
|
17755
|
-
const sameMachine = !!prefill?.role && withFolder.machine === prefill.machine;
|
|
17756
|
-
const readHere = sameMachine && target !== null && target === prefill.cwd;
|
|
17757
|
-
const asked2 = sameMachine && !readHere && target !== null ? `${withFolder.machine}\0${target}` : null;
|
|
17758
|
-
const [seen, setSeen] = useState10(null);
|
|
17759
|
-
useEffect11(() => {
|
|
17760
|
-
if (!asked2) return;
|
|
17761
|
-
const [machineId, cwd] = asked2.split("\0");
|
|
17762
|
-
const requestId = `tui-role-${randomUUID3()}`;
|
|
17763
|
-
const off = client.onMessage((m) => {
|
|
17764
|
-
if (m.type !== "roles.listing" || m.requestId !== requestId) return;
|
|
17765
|
-
off();
|
|
17766
|
-
const found = m.error ? null : m.roles.find((r) => r.id === prefill.role.id) ?? null;
|
|
17767
|
-
setSeen({ key: asked2, role: found });
|
|
17768
|
-
const was = prefill.role;
|
|
17769
|
-
if (found && (found.tool !== was.tool || found.model !== was.model || found.effort !== was.effort))
|
|
17770
|
-
setForm((f) => found.tool && found.tool !== f.tool ? withTool(f, found.tool, rolePick(found, found.tool)) : withPick(f, rolePick(found, f.tool)));
|
|
17771
|
-
});
|
|
17772
|
-
const timer2 = setTimeout(() => client.send({ type: "roles.list", cwd, requestId, ...machineId !== "local" ? { machineId } : {} }), 250);
|
|
17773
|
-
return () => {
|
|
17774
|
-
clearTimeout(timer2);
|
|
17775
|
-
off();
|
|
17776
|
-
};
|
|
17777
|
-
}, [asked2]);
|
|
17778
|
-
const checking = asked2 !== null && seen?.key !== asked2;
|
|
17779
|
-
const role = readHere ? prefill.role : asked2 !== null && seen?.key === asked2 ? seen.role ?? void 0 : void 0;
|
|
17780
|
-
const other = !!role && role.path !== prefill?.role?.path;
|
|
17781
17673
|
const projectIdOf = (s) => projects ? projectOf(s, projects) : null;
|
|
17782
17674
|
const drawn = useMemo5(() => previewOf(withFolder, d.sessions, projectIdOf), [form.machine, form.project, d.sessions.length]);
|
|
17783
17675
|
const [name, setName] = useState10(null);
|
|
@@ -17803,17 +17695,13 @@ function SessionLaunch({ onTeam, prefill }) {
|
|
|
17803
17695
|
}, [launching, d.lastLaunched, d.errors]);
|
|
17804
17696
|
const launch2 = () => {
|
|
17805
17697
|
if (launching) return;
|
|
17806
|
-
if (checking && !missing) {
|
|
17807
|
-
toast({ text: t.catalog.roleChecking(prefill.role.id), tone: "info" });
|
|
17808
|
-
return;
|
|
17809
|
-
}
|
|
17810
17698
|
if (missing) {
|
|
17811
17699
|
toast({ text: t.launch.missing[missing], tone: "info" });
|
|
17812
17700
|
setField(missing === "prompt" ? "prompt" : missing === "machine" ? "machine" : "repos");
|
|
17813
17701
|
return;
|
|
17814
17702
|
}
|
|
17815
17703
|
setLaunching({ seq: d.lastLaunched?.seq ?? 0, errorSeq: d.errors.at(-1)?.seq ?? 0, at: Date.now(), name: shownName });
|
|
17816
|
-
client.send(
|
|
17704
|
+
client.send(launchMessage(withFolder, shownName));
|
|
17817
17705
|
};
|
|
17818
17706
|
useInput6((input, key) => {
|
|
17819
17707
|
if (small && !key.escape) return;
|
|
@@ -17825,10 +17713,6 @@ function SessionLaunch({ onTeam, prefill }) {
|
|
|
17825
17713
|
launch2();
|
|
17826
17714
|
return;
|
|
17827
17715
|
}
|
|
17828
|
-
if (key.ctrl && input === "t") {
|
|
17829
|
-
onTeam();
|
|
17830
|
-
return;
|
|
17831
|
-
}
|
|
17832
17716
|
if (key.ctrl && input === "r") {
|
|
17833
17717
|
setName(pickName([...d.sessions.map((s) => s.name), shownName]));
|
|
17834
17718
|
return;
|
|
@@ -17854,16 +17738,16 @@ function SessionLaunch({ onTeam, prefill }) {
|
|
|
17854
17738
|
}
|
|
17855
17739
|
if (!by) return;
|
|
17856
17740
|
if (field === "tool") setForm((f) => {
|
|
17857
|
-
const
|
|
17858
|
-
return withTool(f,
|
|
17741
|
+
const next3 = cycle(tools, f.tool, by);
|
|
17742
|
+
return withTool(f, next3);
|
|
17859
17743
|
});
|
|
17860
17744
|
else if (field === "model") setForm((f) => withPick(f, { model: cycle(modelIds, f.model, by), effort: null }));
|
|
17861
17745
|
else if (field === "effort") setForm((f) => withPick(f, { model: f.model, effort: cycle(efforts, f.effort, by) }));
|
|
17862
17746
|
else if (field === "project") {
|
|
17863
17747
|
const ids = [...list3.map((p) => p.id), null];
|
|
17864
17748
|
setForm((f) => {
|
|
17865
|
-
const
|
|
17866
|
-
return
|
|
17749
|
+
const next3 = cycle(ids, f.project, by);
|
|
17750
|
+
return next3 === null ? { ...f, project: null, repos: [] } : withProject(f, list3, next3);
|
|
17867
17751
|
});
|
|
17868
17752
|
setRepoAt(0);
|
|
17869
17753
|
} else if (field === "machine") {
|
|
@@ -17881,43 +17765,8 @@ function SessionLaunch({ onTeam, prefill }) {
|
|
|
17881
17765
|
x === cur ? /* @__PURE__ */ jsx17(Text14, { color: C.fg, bold: true, children: `${g.prev} ${label(x)} ${g.next}` }) : /* @__PURE__ */ jsx17(Text14, { color: C.dim, children: label(x) }),
|
|
17882
17766
|
" "
|
|
17883
17767
|
] }, i)) });
|
|
17884
|
-
return /* @__PURE__ */ jsxs13(Frame, { crumb: t.launch.title, keys: [["tab", t.keys.nextField], ["\u2190 \u2192", t.keys.choose], [t.keys.space, t.keys.tick], ["ctrl+s", t.keys.start], ["ctrl+
|
|
17768
|
+
return /* @__PURE__ */ jsxs13(Frame, { crumb: t.launch.title, keys: [["tab", t.keys.nextField], ["\u2190 \u2192", t.keys.choose], [t.keys.space, t.keys.tick], ["ctrl+s", t.keys.start], ["ctrl+r", t.keys.redraw], ["esc", t.keys.cancel]], children: [
|
|
17885
17769
|
/* @__PURE__ */ jsxs13(TitledBox, { title: t.launch.title, flexGrow: 1, children: [
|
|
17886
|
-
/* @__PURE__ */ jsxs13(Box13, { children: [
|
|
17887
|
-
/* @__PURE__ */ jsx17(Text14, { color: C.faint, children: " " }),
|
|
17888
|
-
/* @__PURE__ */ jsx17(Box13, { width: 14, flexShrink: 0, children: /* @__PURE__ */ jsx17(Text14, { color: C.dim, children: t.launch.mode }) }),
|
|
17889
|
-
/* @__PURE__ */ jsxs13(Text14, { children: [
|
|
17890
|
-
/* @__PURE__ */ jsxs13(Text14, { color: C.coral, children: [
|
|
17891
|
-
g.radioOn,
|
|
17892
|
-
" ",
|
|
17893
|
-
t.launch.session
|
|
17894
|
-
] }),
|
|
17895
|
-
" ",
|
|
17896
|
-
/* @__PURE__ */ jsxs13(Text14, { color: C.dim, children: [
|
|
17897
|
-
g.radioOff,
|
|
17898
|
-
" ",
|
|
17899
|
-
t.launch.team
|
|
17900
|
-
] }),
|
|
17901
|
-
" ",
|
|
17902
|
-
/* @__PURE__ */ jsx17(Text14, { color: C.faint, children: "ctrl+t" })
|
|
17903
|
-
] })
|
|
17904
|
-
] }),
|
|
17905
|
-
prefill?.role ? /* @__PURE__ */ jsxs13(Box13, { children: [
|
|
17906
|
-
/* @__PURE__ */ jsx17(Text14, { color: C.faint, children: " " }),
|
|
17907
|
-
/* @__PURE__ */ jsx17(Box13, { width: 14, flexShrink: 0, children: /* @__PURE__ */ jsx17(Text14, { color: C.dim, children: t.catalog.role }) }),
|
|
17908
|
-
role ? /* @__PURE__ */ jsxs13(Text14, { wrap: "truncate", children: [
|
|
17909
|
-
/* @__PURE__ */ jsxs13(Text14, { color: C.violet, children: [
|
|
17910
|
-
"@",
|
|
17911
|
-
role.id
|
|
17912
|
-
] }),
|
|
17913
|
-
" ",
|
|
17914
|
-
/* @__PURE__ */ jsx17(Text14, { color: C.fg, children: role.label }),
|
|
17915
|
-
other ? /* @__PURE__ */ jsxs13(Text14, { color: C.faint, children: [
|
|
17916
|
-
" \xB7 ",
|
|
17917
|
-
t.catalog.roleReadIn(target)
|
|
17918
|
-
] }) : null
|
|
17919
|
-
] }) : /* @__PURE__ */ jsx17(Text14, { wrap: "truncate", color: C.faint, children: checking ? t.catalog.roleChecking(prefill.role.id) : t.catalog.roleElsewhere(prefill.role.id, prefill.cwd ?? "~/.ledge") })
|
|
17920
|
-
] }) : null,
|
|
17921
17770
|
row2("prompt", t.launch.instruction, /* @__PURE__ */ jsx17(TextInput, { value: form.prompt, onChange: (v) => setForm((f) => ({ ...f, prompt: v })), active: field === "prompt" })),
|
|
17922
17771
|
/* @__PURE__ */ jsx17(Text14, { children: " " }),
|
|
17923
17772
|
row2("tool", t.launch.agent, /* @__PURE__ */ jsx17(Text14, { wrap: "truncate", children: tools.map((x) => /* @__PURE__ */ jsxs13(Text14, { color: x === form.tool ? C.coral : C.dim, children: [
|
|
@@ -17971,216 +17820,6 @@ function SessionLaunch({ onTeam, prefill }) {
|
|
|
17971
17820
|
] })
|
|
17972
17821
|
] });
|
|
17973
17822
|
}
|
|
17974
|
-
var TEAM_FIELDS = ["project", "folder", "template", "seats", "name"];
|
|
17975
|
-
var autonomyColor = (a) => ({ ask: C.faint, edits: C.dim, auto: C.yellow })[a];
|
|
17976
|
-
function TeamLaunch({ onSession, prefill }) {
|
|
17977
|
-
const { client, machines, projects, t, g, toast, go, small } = useTui();
|
|
17978
|
-
const list3 = projects?.projects ?? [];
|
|
17979
|
-
const [projectId, setProjectId] = useState10(prefill ? prefill.project : list3[0]?.id ?? null);
|
|
17980
|
-
const project = list3.find((p) => p.id === projectId);
|
|
17981
|
-
const folders = useMemo5(() => {
|
|
17982
|
-
const own4 = (project?.repos ?? []).filter((r) => r.machine === "local").map((r) => r.path);
|
|
17983
|
-
const base = own4.length ? own4 : (machines.find((m) => m.id === "local")?.recents ?? []).slice(0, 6).map((r) => r.cwd);
|
|
17984
|
-
return prefill?.cwd && projectId === prefill.project && !base.includes(prefill.cwd) ? [prefill.cwd, ...base] : base;
|
|
17985
|
-
}, [project, machines]);
|
|
17986
|
-
const [folderAt, setFolderAt] = useState10(() => Math.max(0, prefill?.cwd ? folders.indexOf(prefill.cwd) : 0));
|
|
17987
|
-
const wanted = useRef11(prefill?.template);
|
|
17988
|
-
const cwd = folders[folderAt] ?? folders[0] ?? null;
|
|
17989
|
-
const [field, setField] = useState10("template");
|
|
17990
|
-
const [defs, setDefs] = useState10(null);
|
|
17991
|
-
const [template, setTemplate] = useState10(null);
|
|
17992
|
-
const [seats, setSeats] = useState10([]);
|
|
17993
|
-
const [seatAt, setSeatAt] = useState10(0);
|
|
17994
|
-
const [name, setName] = useState10("");
|
|
17995
|
-
const [launching, setLaunching] = useState10(false);
|
|
17996
|
-
useEditing(true);
|
|
17997
|
-
useEffect11(() => {
|
|
17998
|
-
if (!cwd) {
|
|
17999
|
-
setDefs({ roles: [], templates: [] });
|
|
18000
|
-
return;
|
|
18001
|
-
}
|
|
18002
|
-
setDefs(null);
|
|
18003
|
-
const requestId = `tui-roles-${randomUUID3()}`;
|
|
18004
|
-
const off = client.onMessage((m) => {
|
|
18005
|
-
if (m.type !== "roles.listing" || m.requestId !== requestId) return;
|
|
18006
|
-
off();
|
|
18007
|
-
setDefs({ roles: m.roles, templates: m.templates });
|
|
18008
|
-
setSeats(m.roles.map((role) => ({ role, tool: role.tool ?? "claude", on: false })));
|
|
18009
|
-
const first = m.templates.find((x) => x.id === wanted.current) ?? m.templates[0];
|
|
18010
|
-
wanted.current = void 0;
|
|
18011
|
-
setTemplate(first?.id ?? null);
|
|
18012
|
-
setName((n) => n || first?.name || project?.name || "");
|
|
18013
|
-
});
|
|
18014
|
-
client.send({ type: "roles.list", cwd, requestId });
|
|
18015
|
-
return off;
|
|
18016
|
-
}, [cwd]);
|
|
18017
|
-
const tpl = defs?.templates.find((x) => x.id === template);
|
|
18018
|
-
const chosen = tpl ? tpl.seats.map((x) => {
|
|
18019
|
-
const role = defs.roles.find((r) => r.id === x.role);
|
|
18020
|
-
return { id: x.role, tool: x.tool ?? role?.tool ?? "claude", autonomy: role?.autonomy ?? "ask" };
|
|
18021
|
-
}) : seats.filter((x) => x.on).map((x) => ({ id: x.role.id, tool: x.tool, autonomy: x.role.autonomy ?? "ask" }));
|
|
18022
|
-
const auto = chosen.filter((x) => x.autonomy === "auto").map((x) => `@${x.id}`);
|
|
18023
|
-
const teamName = name.trim() || tpl?.name || project?.name || "team";
|
|
18024
|
-
const launch2 = () => {
|
|
18025
|
-
if (launching || !cwd) return;
|
|
18026
|
-
if (!chosen.length) {
|
|
18027
|
-
toast({ text: t.launch.noSeat, tone: "info" });
|
|
18028
|
-
return;
|
|
18029
|
-
}
|
|
18030
|
-
const rid = randomUUID3();
|
|
18031
|
-
setLaunching(true);
|
|
18032
|
-
const off = client.onMessage((m) => {
|
|
18033
|
-
if (m.type !== "team.launched" && m.type !== "team.failed" || m.rid !== rid) return;
|
|
18034
|
-
off();
|
|
18035
|
-
setLaunching(false);
|
|
18036
|
-
if (m.type === "team.launched") {
|
|
18037
|
-
toast({ text: t.launch.teamLaunched(m.team.name), tone: "ok" });
|
|
18038
|
-
go("overview");
|
|
18039
|
-
} else toast({ text: t.launch.teamFailed(m.reason), tone: "error" });
|
|
18040
|
-
});
|
|
18041
|
-
client.send({ type: "team.launch", rid, cwd, name: teamName, ...tpl ? { template: tpl.id } : { seats: chosen.map((x) => ({ role: x.id, tool: x.tool })) } });
|
|
18042
|
-
};
|
|
18043
|
-
const tools = ["claude", "codex", "cursor", "omp"];
|
|
18044
|
-
const templates = [...(defs?.templates ?? []).map((x) => x.id), null];
|
|
18045
|
-
useInput6((input, key) => {
|
|
18046
|
-
if (small && !key.escape) return;
|
|
18047
|
-
if (key.escape) {
|
|
18048
|
-
go("overview");
|
|
18049
|
-
return;
|
|
18050
|
-
}
|
|
18051
|
-
if (key.ctrl && input === "s") {
|
|
18052
|
-
launch2();
|
|
18053
|
-
return;
|
|
18054
|
-
}
|
|
18055
|
-
if (key.ctrl && input === "t") {
|
|
18056
|
-
onSession();
|
|
18057
|
-
return;
|
|
18058
|
-
}
|
|
18059
|
-
if (key.tab || key.downArrow || key.return) {
|
|
18060
|
-
setField((f) => cycle(TEAM_FIELDS, f, key.shift ? -1 : 1));
|
|
18061
|
-
return;
|
|
18062
|
-
}
|
|
18063
|
-
if (key.upArrow) {
|
|
18064
|
-
setField((f) => cycle(TEAM_FIELDS, f, -1));
|
|
18065
|
-
return;
|
|
18066
|
-
}
|
|
18067
|
-
if (field === "name") return;
|
|
18068
|
-
const by = key.rightArrow || input === "l" ? 1 : key.leftArrow || input === "h" ? -1 : 0;
|
|
18069
|
-
if (field === "project" && by) {
|
|
18070
|
-
const ids = list3.map((p) => p.id);
|
|
18071
|
-
if (ids.length) {
|
|
18072
|
-
setProjectId((cur) => cycle(ids, cur ?? ids[0], by));
|
|
18073
|
-
setFolderAt(0);
|
|
18074
|
-
}
|
|
18075
|
-
} else if (field === "folder" && by && folders.length) setFolderAt((i) => (i + by + folders.length) % folders.length);
|
|
18076
|
-
else if (field === "template" && by) {
|
|
18077
|
-
const next2 = cycle(templates, template, by);
|
|
18078
|
-
setTemplate(next2);
|
|
18079
|
-
const x = defs?.templates.find((y) => y.id === next2);
|
|
18080
|
-
if (x) setName(x.name);
|
|
18081
|
-
} else if (field === "seats" && !tpl) {
|
|
18082
|
-
if (input === "j") setSeatAt((i) => seats.length ? (i + 1) % seats.length : 0);
|
|
18083
|
-
else if (input === "k") setSeatAt((i) => seats.length ? (i + seats.length - 1) % seats.length : 0);
|
|
18084
|
-
else if (input === " ") setSeats((xs) => xs.map((x, i) => i === seatAt ? { ...x, on: !x.on } : x));
|
|
18085
|
-
else if (by) setSeats((xs) => xs.map((x, i) => i === seatAt ? { ...x, tool: cycle(tools, x.tool, by) } : x));
|
|
18086
|
-
}
|
|
18087
|
-
});
|
|
18088
|
-
const row2 = (f, label, value) => /* @__PURE__ */ jsxs13(Box13, { backgroundColor: field === f ? C.sel : void 0, children: [
|
|
18089
|
-
/* @__PURE__ */ jsx17(Text14, { color: field === f ? C.coral : C.faint, children: field === f ? "\u258C" : " " }),
|
|
18090
|
-
/* @__PURE__ */ jsx17(Box13, { width: 14, flexShrink: 0, children: /* @__PURE__ */ jsx17(Text14, { color: C.dim, children: label }) }),
|
|
18091
|
-
/* @__PURE__ */ jsx17(Box13, { flexGrow: 1, overflow: "hidden", flexDirection: "column", children: value })
|
|
18092
|
-
] }, f);
|
|
18093
|
-
return /* @__PURE__ */ jsxs13(Frame, { crumb: t.launch.teamTitle, keys: [["tab", t.keys.nextField], ["\u2190 \u2192", t.keys.choose], [t.keys.space, t.keys.tick], ["ctrl+s", t.keys.start], ["ctrl+t", t.keys.teamMode], ["esc", t.keys.cancel]], children: [
|
|
18094
|
-
/* @__PURE__ */ jsxs13(TitledBox, { title: t.launch.teamTitle, flexGrow: 1, children: [
|
|
18095
|
-
/* @__PURE__ */ jsxs13(Box13, { children: [
|
|
18096
|
-
/* @__PURE__ */ jsx17(Text14, { color: C.faint, children: " " }),
|
|
18097
|
-
/* @__PURE__ */ jsx17(Box13, { width: 14, flexShrink: 0, children: /* @__PURE__ */ jsx17(Text14, { color: C.dim, children: t.launch.mode }) }),
|
|
18098
|
-
/* @__PURE__ */ jsxs13(Text14, { children: [
|
|
18099
|
-
/* @__PURE__ */ jsxs13(Text14, { color: C.dim, children: [
|
|
18100
|
-
g.radioOff,
|
|
18101
|
-
" ",
|
|
18102
|
-
t.launch.session
|
|
18103
|
-
] }),
|
|
18104
|
-
" ",
|
|
18105
|
-
/* @__PURE__ */ jsxs13(Text14, { color: C.coral, children: [
|
|
18106
|
-
g.radioOn,
|
|
18107
|
-
" ",
|
|
18108
|
-
t.launch.team
|
|
18109
|
-
] }),
|
|
18110
|
-
" ",
|
|
18111
|
-
/* @__PURE__ */ jsx17(Text14, { color: C.faint, children: "ctrl+t" })
|
|
18112
|
-
] })
|
|
18113
|
-
] }),
|
|
18114
|
-
row2("project", t.launch.project, /* @__PURE__ */ jsx17(Text14, { wrap: "truncate", children: list3.length === 0 ? /* @__PURE__ */ jsx17(Text14, { color: C.faint, children: t.launch.none }) : list3.map((p) => /* @__PURE__ */ jsx17(ProjectChoice, { project: p, on: p.id === projectId }, p.id)) })),
|
|
18115
|
-
row2("folder", t.launch.folder, /* @__PURE__ */ jsx17(Text14, { wrap: "truncate", children: cwd ? /* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
18116
|
-
/* @__PURE__ */ jsx17(Text14, { color: C.fg, children: cwd }),
|
|
18117
|
-
folders.length > 1 ? /* @__PURE__ */ jsxs13(Text14, { color: C.faint, children: [
|
|
18118
|
-
" (",
|
|
18119
|
-
folderAt + 1,
|
|
18120
|
-
"/",
|
|
18121
|
-
folders.length,
|
|
18122
|
-
")"
|
|
18123
|
-
] }) : null
|
|
18124
|
-
] }) : /* @__PURE__ */ jsx17(Text14, { color: C.faint, children: t.launch.none }) })),
|
|
18125
|
-
row2("template", t.launch.template, defs === null ? /* @__PURE__ */ jsx17(Text14, { color: C.faint, children: t.launch.loadingRoles }) : /* @__PURE__ */ jsx17(Text14, { wrap: "truncate", children: templates.map((x) => /* @__PURE__ */ jsxs13(Text14, { color: x === template ? C.fg : C.dim, bold: x === template, children: [
|
|
18126
|
-
x === template ? `${g.prev} ${x ?? t.launch.custom} ${g.next}` : x ?? t.launch.custom,
|
|
18127
|
-
" "
|
|
18128
|
-
] }, x ?? "-")) })),
|
|
18129
|
-
row2("seats", t.launch.seats, tpl ? /* @__PURE__ */ jsx17(Text14, { wrap: "truncate", children: chosen.map((x) => /* @__PURE__ */ jsxs13(Text14, { children: [
|
|
18130
|
-
/* @__PURE__ */ jsxs13(Text14, { color: C.violet, children: [
|
|
18131
|
-
"@",
|
|
18132
|
-
x.id
|
|
18133
|
-
] }),
|
|
18134
|
-
" ",
|
|
18135
|
-
/* @__PURE__ */ jsx17(Text14, { color: C.dim, children: TOOL_NAME[x.tool] }),
|
|
18136
|
-
" "
|
|
18137
|
-
] }, x.id)) }) : seats.length === 0 ? /* @__PURE__ */ jsx17(Text14, { color: C.faint, children: t.launch.noRole }) : /* @__PURE__ */ jsx17(Fragment5, { children: seats.map((x, i) => /* @__PURE__ */ jsxs13(Text14, { wrap: "truncate", backgroundColor: field === "seats" && i === seatAt ? C.line : void 0, children: [
|
|
18138
|
-
/* @__PURE__ */ jsx17(Text14, { color: x.on ? C.green : C.faint, children: x.on ? g.boxOn : g.boxOff }),
|
|
18139
|
-
" ",
|
|
18140
|
-
/* @__PURE__ */ jsxs13(Text14, { color: C.violet, children: [
|
|
18141
|
-
"@",
|
|
18142
|
-
x.role.id
|
|
18143
|
-
] }),
|
|
18144
|
-
" ",
|
|
18145
|
-
x.role.label,
|
|
18146
|
-
" ",
|
|
18147
|
-
/* @__PURE__ */ jsxs13(Text14, { color: C.dim, children: [
|
|
18148
|
-
g.prev,
|
|
18149
|
-
" ",
|
|
18150
|
-
TOOL_NAME[x.tool],
|
|
18151
|
-
" ",
|
|
18152
|
-
g.next
|
|
18153
|
-
] }),
|
|
18154
|
-
" ",
|
|
18155
|
-
/* @__PURE__ */ jsx17(Text14, { color: autonomyColor(x.role.autonomy ?? "ask"), children: t.ask.autonomy[x.role.autonomy ?? "ask"] })
|
|
18156
|
-
] }, x.role.id)) })),
|
|
18157
|
-
row2("name", t.launch.teamName, /* @__PURE__ */ jsx17(TextInput, { value: name, onChange: setName, active: field === "name", placeholder: teamName }))
|
|
18158
|
-
] }),
|
|
18159
|
-
/* @__PURE__ */ jsxs13(TitledBox, { title: t.launch.preview, color: C.coral, titleColor: C.coral, children: [
|
|
18160
|
-
/* @__PURE__ */ jsxs13(Text14, { wrap: "truncate", children: [
|
|
18161
|
-
/* @__PURE__ */ jsx17(Text14, { color: C.coral, children: g.team }),
|
|
18162
|
-
" ",
|
|
18163
|
-
/* @__PURE__ */ jsx17(Text14, { color: C.fg, bold: true, children: t.launch.teamPreview(teamName, project?.name ?? cwd ?? "-") })
|
|
18164
|
-
] }),
|
|
18165
|
-
/* @__PURE__ */ jsx17(Text14, { wrap: "truncate", children: chosen.map((x) => /* @__PURE__ */ jsxs13(Text14, { children: [
|
|
18166
|
-
/* @__PURE__ */ jsxs13(Text14, { color: C.violet, children: [
|
|
18167
|
-
"@",
|
|
18168
|
-
x.id
|
|
18169
|
-
] }),
|
|
18170
|
-
" ",
|
|
18171
|
-
/* @__PURE__ */ jsx17(Text14, { color: C.dim, children: TOOL_NAME[x.tool] }),
|
|
18172
|
-
" ",
|
|
18173
|
-
/* @__PURE__ */ jsx17(Text14, { color: autonomyColor(x.autonomy), children: t.ask.autonomy[x.autonomy] }),
|
|
18174
|
-
" "
|
|
18175
|
-
] }, x.id)) }),
|
|
18176
|
-
auto.length ? /* @__PURE__ */ jsx17(Text14, { color: C.yellow, wrap: "truncate", children: t.ask.autoWarning(auto.join(", ")) }) : null,
|
|
18177
|
-
/* @__PURE__ */ jsxs13(Box13, { marginTop: 1, columnGap: 2, children: [
|
|
18178
|
-
/* @__PURE__ */ jsx17(Button, { label: launching ? t.launch.launching : t.ask.launchTeam, k: "ctrl+s", primary: true }),
|
|
18179
|
-
/* @__PURE__ */ jsx17(Button, { label: t.launch.cancel, k: "esc" })
|
|
18180
|
-
] })
|
|
18181
|
-
] })
|
|
18182
|
-
] });
|
|
18183
|
-
}
|
|
18184
17823
|
|
|
18185
17824
|
// src/tui/screens/Settings.tsx
|
|
18186
17825
|
import { useState as useState11 } from "react";
|
|
@@ -18286,7 +17925,8 @@ function Help() {
|
|
|
18286
17925
|
[t.help.field, [["\u21B5", k.sendOnly], ["alt+\u21B5 ctrl+j", k.newLine], ["\u2191 \u2193", k.lineHistory], ["ctrl \u2190 \u2192", k.word], ["ctrl+w", t.help.wordBefore], ["ctrl+u", k.clear], ["esc", k.keepAndLeave]]],
|
|
18287
17926
|
[t.help.launch, [["tab \u2191 \u2193", k.nextField], ["\u2190 \u2192", k.choose], [t.keys.space, k.tick], ["ctrl+r", t.keys.redraw], ["ctrl+s", k.start], ["esc", k.cancel]]],
|
|
18288
17927
|
[t.help.settings, [["\u2191 \u2193", k.navigate], ["\u2190 \u2192", k.change]]],
|
|
18289
|
-
[t.help.
|
|
17928
|
+
[t.help.rigLaunch, [["tab \u2191 \u2193", k.nextField], ["\u2190 \u2192", k.choose], ["- +", t.rigLaunch.count], ["m", t.rigLaunch.modelKey], ["o", t.rigLaunch.policyKey], [t.keys.space, k.tick], ["p ctrl+p", t.rigLaunch.check], ["ctrl+s", k.start], ["esc", k.cancel]]],
|
|
17929
|
+
[t.help.openrig, [["tab", t.openrig.machine], ["j k \u2191 \u2193", k.navigate], ["\u21B5", t.openrig.unfold], ["s", t.openrig.toggle], ["R", t.openrig.restart], ["\xB1 =", t.rigSeats.key], ["+", t.rigLaunch.launchKey], ["D", `${t.openrig.daemonKey} \xB7 ${t.openrig.toggle}`], ["K", `${t.openrig.kernelKey} \xB7 ${t.openrig.toggle}`], ["y n", `${t.openrig.yes} \xB7 ${t.openrig.no}`]]]
|
|
18290
17930
|
];
|
|
18291
17931
|
const lines = helpLines(groups, Math.max(20, columns - 4));
|
|
18292
17932
|
const [view, setView] = useState12(10);
|
|
@@ -18317,419 +17957,917 @@ function Help() {
|
|
|
18317
17957
|
return /* @__PURE__ */ jsx19(Frame, { crumb: t.help.title, keys: [["esc", k.back], ...maxTop ? [["j k PgUp PgDn", k.scroll]] : []], children: /* @__PURE__ */ jsx19(TitledBox, { title: t.help.title, flexGrow: 1, foot: foot || void 0, children: /* @__PURE__ */ jsx19(Lines, { lines, up: Math.max(0, below), onHeight: setView }) }) });
|
|
18318
17958
|
}
|
|
18319
17959
|
|
|
18320
|
-
// src/tui/screens/
|
|
18321
|
-
import { useEffect as
|
|
17960
|
+
// src/tui/screens/OpenRig.tsx
|
|
17961
|
+
import { useEffect as useEffect13, useRef as useRef12, useState as useState14 } from "react";
|
|
18322
17962
|
import { Box as Box16, Text as Text17 } from "ink";
|
|
18323
|
-
import { randomUUID as randomUUID4 } from "crypto";
|
|
18324
17963
|
|
|
18325
|
-
// src/
|
|
18326
|
-
|
|
18327
|
-
|
|
18328
|
-
|
|
18329
|
-
|
|
18330
|
-
|
|
18331
|
-
|
|
18332
|
-
|
|
18333
|
-
const
|
|
18334
|
-
const
|
|
18335
|
-
const
|
|
18336
|
-
|
|
18337
|
-
const
|
|
18338
|
-
|
|
17964
|
+
// ../fleet/src/openrig.ts
|
|
17965
|
+
import { useCallback, useEffect as useEffect12, useRef as useRef11, useState as useState13 } from "react";
|
|
17966
|
+
var OPENRIG_POLL_MS = 5e3;
|
|
17967
|
+
var next2 = 0;
|
|
17968
|
+
function useOpenRig(client, machine, pollMs = OPENRIG_POLL_MS) {
|
|
17969
|
+
const [view, setView] = useState13({ machine, state: null });
|
|
17970
|
+
const [pending, setPending] = useState13(null);
|
|
17971
|
+
const [last, setLast] = useState13(null);
|
|
17972
|
+
const waiting = useRef11(/* @__PURE__ */ new Map());
|
|
17973
|
+
const asked2 = useRef11(null);
|
|
17974
|
+
const ask2 = useCallback(() => {
|
|
17975
|
+
if (machine === null) return;
|
|
17976
|
+
const requestId = `openrig-${++next2}`;
|
|
17977
|
+
asked2.current = requestId;
|
|
17978
|
+
client.send({ type: "openrig.status", requestId, machineId: machine });
|
|
17979
|
+
}, [client, machine]);
|
|
17980
|
+
useEffect12(() => {
|
|
17981
|
+
setView({ machine, state: null });
|
|
17982
|
+
setPending(null);
|
|
17983
|
+
setLast(null);
|
|
17984
|
+
if (machine === null) return;
|
|
17985
|
+
const off = client.onMessage((m) => {
|
|
17986
|
+
if (m.type === "openrig.state") {
|
|
17987
|
+
if ((m.machineId ?? "local") !== machine) return;
|
|
17988
|
+
if (m.requestId !== void 0 && m.requestId !== asked2.current) return;
|
|
17989
|
+
setView((v) => ({ machine, state: m.state ?? (m.error ? null : v.state), ...m.error ? { error: m.error } : {} }));
|
|
17990
|
+
} else if (m.type === "openrig.done") {
|
|
17991
|
+
const resolve = waiting.current.get(m.requestId);
|
|
17992
|
+
if (!resolve) return;
|
|
17993
|
+
waiting.current.delete(m.requestId);
|
|
17994
|
+
resolve(m);
|
|
17995
|
+
}
|
|
17996
|
+
});
|
|
17997
|
+
ask2();
|
|
17998
|
+
const timer2 = setInterval(ask2, pollMs);
|
|
17999
|
+
return () => {
|
|
18000
|
+
off();
|
|
18001
|
+
clearInterval(timer2);
|
|
18002
|
+
for (const [, r] of waiting.current) r({ type: "openrig.done", requestId: "", ok: false, commands: [], error: "cancelled" });
|
|
18003
|
+
waiting.current.clear();
|
|
18004
|
+
};
|
|
18005
|
+
}, [client, machine, ask2, pollMs]);
|
|
18006
|
+
const act = useCallback((action) => {
|
|
18007
|
+
if (machine === null) return Promise.resolve({ type: "openrig.done", requestId: "", ok: false, commands: [], error: "offline" });
|
|
18008
|
+
const requestId = `openrig-act-${++next2}`;
|
|
18009
|
+
setPending(action);
|
|
18010
|
+
setLast(null);
|
|
18011
|
+
return new Promise((resolve) => {
|
|
18012
|
+
waiting.current.set(requestId, (d) => {
|
|
18013
|
+
setPending((p) => p === action ? null : p);
|
|
18014
|
+
setLast(d);
|
|
18015
|
+
resolve(d);
|
|
18016
|
+
});
|
|
18017
|
+
client.send({ type: "openrig.act", requestId, action, machineId: machine });
|
|
18018
|
+
});
|
|
18019
|
+
}, [client, machine]);
|
|
18020
|
+
const shown = view.machine === machine ? view : { state: null };
|
|
18021
|
+
return { state: shown.state, ..."error" in shown && shown.error ? { error: shown.error } : {}, pending, last, act, refresh: ask2 };
|
|
18022
|
+
}
|
|
18023
|
+
function useRigSpecs(client, machine) {
|
|
18024
|
+
const [answer, setAnswer] = useState13(null);
|
|
18025
|
+
const [round, setRound] = useState13(0);
|
|
18026
|
+
useEffect12(() => {
|
|
18027
|
+
if (machine === null) return;
|
|
18028
|
+
const requestId = `openrig-specs-${++next2}`;
|
|
18029
|
+
setAnswer((a) => a?.machine === machine ? a : null);
|
|
18030
|
+
const off = client.onMessage((m) => {
|
|
18031
|
+
if (m.type !== "openrig.specList" || m.requestId !== requestId) return;
|
|
18032
|
+
setAnswer({ machine, specs: m.specs, ...m.error ? { error: m.error } : {} });
|
|
18033
|
+
});
|
|
18034
|
+
client.send({ type: "openrig.specs", requestId, machineId: machine });
|
|
18035
|
+
return off;
|
|
18036
|
+
}, [client, machine, round]);
|
|
18037
|
+
const reload = useCallback(() => setRound((r) => r + 1), []);
|
|
18038
|
+
if (machine === null) return { status: "idle", specs: [], reload };
|
|
18039
|
+
if (!answer || answer.machine !== machine) return { status: "loading", specs: [], reload };
|
|
18040
|
+
return { status: "ready", specs: answer.specs, ...answer.error ? { error: answer.error } : {}, reload };
|
|
18041
|
+
}
|
|
18042
|
+
function launchRig(client, machine, launch2) {
|
|
18043
|
+
const requestId = `openrig-launch-${++next2}`;
|
|
18044
|
+
return new Promise((resolve) => {
|
|
18045
|
+
const off = client.onMessage((m) => {
|
|
18046
|
+
if (m.type !== "openrig.launched" || m.requestId !== requestId) return;
|
|
18047
|
+
off();
|
|
18048
|
+
resolve(m);
|
|
18049
|
+
});
|
|
18050
|
+
client.send({ type: "openrig.launch", requestId, launch: launch2, machineId: machine });
|
|
18339
18051
|
});
|
|
18340
|
-
|
|
18341
|
-
|
|
18342
|
-
const
|
|
18343
|
-
|
|
18344
|
-
|
|
18345
|
-
|
|
18052
|
+
}
|
|
18053
|
+
function reseatRig(client, machine, rig, seats, delegation) {
|
|
18054
|
+
const requestId = `openrig-seats-${++next2}`;
|
|
18055
|
+
return new Promise((resolve) => {
|
|
18056
|
+
const off = client.onMessage((m) => {
|
|
18057
|
+
if (m.type !== "openrig.reseated" || m.requestId !== requestId) return;
|
|
18058
|
+
off();
|
|
18059
|
+
resolve(m);
|
|
18060
|
+
});
|
|
18061
|
+
client.send({ type: "openrig.seats", requestId, machineId: machine, rig, seats, ...delegation ? { delegation } : {} });
|
|
18062
|
+
});
|
|
18063
|
+
}
|
|
18064
|
+
|
|
18065
|
+
// src/tui/model/openrig.ts
|
|
18066
|
+
var listedRigs = (s) => (s?.rigs ?? []).filter((r) => r.name !== KERNEL_RIG);
|
|
18067
|
+
var daemonUp = (s) => !!s?.installed && s.daemon.state === "running";
|
|
18068
|
+
var rigRunning = (r) => r.status === "running" || r.running > 0;
|
|
18069
|
+
function rigLook(r) {
|
|
18070
|
+
if (r.attention > 0) return "attention";
|
|
18071
|
+
if (r.status === "running") return "running";
|
|
18072
|
+
return r.running > 0 ? "starting" : "stopped";
|
|
18073
|
+
}
|
|
18074
|
+
var seatBusy = (s) => s.activity === "running" || s.work > 0;
|
|
18075
|
+
var rigToggle = (r) => rigRunning(r) ? { kind: "rig.stop", rig: r.name, snapshot: true } : { kind: "rig.start", rig: r.name };
|
|
18076
|
+
var daemonToggle = (s) => s.daemon.state === "running" ? { kind: "daemon.stop" } : { kind: "daemon.start", restore: "last" };
|
|
18077
|
+
var kernelToggle = (s) => s.kernel.state === "ready" || s.kernel.state === "starting" ? { kind: "kernel.stop" } : { kind: "kernel.start" };
|
|
18078
|
+
var asksFirst = (a) => a.kind.endsWith(".stop") || a.kind.endsWith(".restart");
|
|
18079
|
+
function busySeats(s, a) {
|
|
18080
|
+
const of = (r) => (r?.nodes ?? []).filter(seatBusy);
|
|
18081
|
+
if (a.kind === "rig.stop" || a.kind === "rig.restart") return of(s.rigs.find((r) => r.name === a.rig)).map((n) => n.logicalId);
|
|
18082
|
+
if (a.kind === "kernel.stop" || a.kind === "kernel.restart") return of(s.rigs.find((r) => r.name === KERNEL_RIG)).map((n) => n.logicalId);
|
|
18083
|
+
if (a.kind === "daemon.stop" || a.kind === "daemon.restart") return s.rigs.flatMap((r) => of(r).map((n) => `${r.name} \xB7 ${n.logicalId}`));
|
|
18084
|
+
return [];
|
|
18085
|
+
}
|
|
18086
|
+
var commandsOf = (a) => rigCommands(a).map(showRigCommand);
|
|
18087
|
+
var confirmOf = (s, a) => ({ action: a, busy: busySeats(s, a), commands: commandsOf(a) });
|
|
18088
|
+
var step2 = (at, by, n) => n ? (at + by + n) % n : 0;
|
|
18089
|
+
function keepRig(rigs, at, id) {
|
|
18090
|
+
const found = id ? rigs.findIndex((r) => r.id === id) : -1;
|
|
18091
|
+
return found >= 0 ? found : Math.max(0, Math.min(at, rigs.length - 1));
|
|
18092
|
+
}
|
|
18093
|
+
|
|
18094
|
+
// src/tui/model/rigSeats.ts
|
|
18095
|
+
var canReseat = (r) => !!r && rigRunning(r) && r.nodes.length > 0;
|
|
18096
|
+
function seatRows(r) {
|
|
18097
|
+
const byId = new Map(r.nodes.map((n) => [n.logicalId, n]));
|
|
18098
|
+
return [...seatsByRole(r.nodes)].map(([role, seats]) => ({ role, seats, first: byId.get(seats[0]) }));
|
|
18099
|
+
}
|
|
18100
|
+
var countsOf = (rows) => Object.fromEntries(rows.map((r) => [r.role, r.seats.length]));
|
|
18101
|
+
var withCount = (counts, role, by) => ({ ...counts, [role]: Math.max(0, Math.min(9, (counts[role] ?? 0) + by)) });
|
|
18102
|
+
var changedCounts = (rows, counts) => Object.fromEntries(rows.filter((r) => (counts[r.role] ?? r.seats.length) !== r.seats.length).map((r) => [r.role, counts[r.role]]));
|
|
18103
|
+
var planOf = (r, rows, counts) => seatPlan(r.nodes, changedCounts(rows, counts));
|
|
18104
|
+
function chips(row2, plan) {
|
|
18105
|
+
const removed = new Set(plan.remove);
|
|
18346
18106
|
return [
|
|
18347
|
-
...
|
|
18348
|
-
|
|
18349
|
-
if (seen.has(k)) return false;
|
|
18350
|
-
seen.add(k);
|
|
18351
|
-
return true;
|
|
18352
|
-
}).map((x) => ({ cwd: x.cwd, machine: x.machine, label: label(x) })),
|
|
18353
|
-
{ cwd: null, machine: "local", label: o.homeOnly }
|
|
18107
|
+
...row2.seats.map((id) => ({ id, kind: removed.has(id) ? "removed" : "kept" })),
|
|
18108
|
+
...plan.add.filter((a) => a.role === row2.role).map((a) => ({ id: a.id, kind: "added" }))
|
|
18354
18109
|
];
|
|
18355
18110
|
}
|
|
18356
|
-
|
|
18357
|
-
const
|
|
18358
|
-
|
|
18359
|
-
|
|
18360
|
-
|
|
18361
|
-
|
|
18362
|
-
|
|
18363
|
-
|
|
18364
|
-
|
|
18111
|
+
var busyRemovals = (r, plan) => plan.remove.filter((id) => {
|
|
18112
|
+
const n = r.nodes.find((x) => x.logicalId === id);
|
|
18113
|
+
return !!n && seatBusy(n);
|
|
18114
|
+
});
|
|
18115
|
+
function previewCommands(rig, plan, links) {
|
|
18116
|
+
if (!plan.add.length && !plan.remove.length) return [];
|
|
18117
|
+
return [
|
|
18118
|
+
...plan.add.map((a) => `rig add ${rig} ${a.pod} ${a.id}`),
|
|
18119
|
+
...plan.remove.map((id) => `rig remove ${rig} ${id}`),
|
|
18120
|
+
...plan.add.length ? [`rig edge add \u2026 (${links})`] : [],
|
|
18121
|
+
`rig snapshot ${rig}`
|
|
18122
|
+
];
|
|
18365
18123
|
}
|
|
18366
|
-
var stepIndex = (length, i, by) => length ? ((i + by) % length + length) % length : 0;
|
|
18367
18124
|
|
|
18368
|
-
// src/tui/ui/
|
|
18369
|
-
import {
|
|
18370
|
-
import {
|
|
18371
|
-
|
|
18372
|
-
|
|
18373
|
-
const
|
|
18374
|
-
const
|
|
18375
|
-
const
|
|
18376
|
-
const
|
|
18377
|
-
return /* @__PURE__ */
|
|
18125
|
+
// src/tui/ui/RigSeats.tsx
|
|
18126
|
+
import { Box as Box15, Text as Text16 } from "ink";
|
|
18127
|
+
import { jsx as jsx20, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
18128
|
+
function RigSeats({ rig, machine, rows, counts, at, delegation, plan, applying }) {
|
|
18129
|
+
const { t, g } = useTui();
|
|
18130
|
+
const s = t.rigSeats;
|
|
18131
|
+
const now2 = rows.map((r) => `${r.seats.length} ${r.role}`).join(", ");
|
|
18132
|
+
const commands = previewCommands(rig.name, plan, delegation === "pairs" ? s.linksPairs : s.linksAll);
|
|
18133
|
+
const busy = busyRemovals(rig, plan);
|
|
18134
|
+
return /* @__PURE__ */ jsxs15(TitledBox, { title: s.title(rig.name, machine), color: C.coral, titleColor: C.coral, titleBold: true, flexGrow: 1, children: [
|
|
18135
|
+
/* @__PURE__ */ jsx20(Text16, { wrap: "truncate", color: C.dim, children: s.stays(now2) }),
|
|
18136
|
+
/* @__PURE__ */ jsx20(Text16, { children: " " }),
|
|
18137
|
+
rows.map((r, i) => {
|
|
18138
|
+
const on = i === at, n = counts[r.role] ?? r.seats.length;
|
|
18139
|
+
return /* @__PURE__ */ jsxs15(Box15, { flexShrink: 0, backgroundColor: on ? C.sel : void 0, children: [
|
|
18140
|
+
/* @__PURE__ */ jsx20(Text16, { color: on ? C.coral : C.faint, children: on ? "\u258C" : " " }),
|
|
18141
|
+
/* @__PURE__ */ jsx20(Box15, { width: 16, flexShrink: 0, children: /* @__PURE__ */ jsx20(Text16, { wrap: "truncate", color: C.fg, bold: true, children: r.role }) }),
|
|
18142
|
+
/* @__PURE__ */ jsx20(Box15, { width: 26, flexShrink: 0, children: /* @__PURE__ */ jsx20(Text16, { wrap: "truncate", color: C.dim, children: [r.first.runtime, r.first.model].filter(Boolean).join(" \xB7 ") }) }),
|
|
18143
|
+
/* @__PURE__ */ jsx20(Box15, { width: 8, flexShrink: 0, children: /* @__PURE__ */ jsxs15(Text16, { children: [
|
|
18144
|
+
/* @__PURE__ */ jsx20(Text16, { color: C.dim, children: "\u2212 " }),
|
|
18145
|
+
/* @__PURE__ */ jsx20(Text16, { color: n === r.seats.length ? C.fg : C.green, bold: true, children: n }),
|
|
18146
|
+
/* @__PURE__ */ jsx20(Text16, { color: C.dim, children: " +" })
|
|
18147
|
+
] }) }),
|
|
18148
|
+
/* @__PURE__ */ jsx20(Box15, { flexGrow: 1, overflow: "hidden", children: /* @__PURE__ */ jsx20(Text16, { wrap: "truncate", children: chips(r, plan).map((c) => /* @__PURE__ */ jsxs15(Text16, { color: c.kind === "added" ? C.green : c.kind === "removed" ? C.red : C.dim, strikethrough: c.kind === "removed", children: [
|
|
18149
|
+
c.kind === "added" ? `+${c.id}` : c.id,
|
|
18150
|
+
" "
|
|
18151
|
+
] }, c.id)) }) })
|
|
18152
|
+
] }, r.role);
|
|
18153
|
+
}),
|
|
18154
|
+
/* @__PURE__ */ jsx20(Text16, { children: " " }),
|
|
18155
|
+
plan.add.length ? /* @__PURE__ */ jsxs15(Text16, { wrap: "truncate", children: [
|
|
18156
|
+
delegation === "pairs" ? /* @__PURE__ */ jsx20(Text16, { color: C.fg, bold: true, children: `${g.prev} ${s.pairs} ${g.next}` }) : /* @__PURE__ */ jsx20(Text16, { color: C.dim, children: s.pairs }),
|
|
18157
|
+
" ",
|
|
18158
|
+
delegation === "all" ? /* @__PURE__ */ jsx20(Text16, { color: C.fg, bold: true, children: `${g.prev} ${s.all} ${g.next}` }) : /* @__PURE__ */ jsx20(Text16, { color: C.dim, children: s.all })
|
|
18159
|
+
] }) : null,
|
|
18160
|
+
busy.map((id) => /* @__PURE__ */ jsx20(Text16, { wrap: "truncate", color: C.red, children: s.busy(id) }, id)),
|
|
18161
|
+
commands.length ? /* @__PURE__ */ jsx20(Box15, { marginTop: 1, flexDirection: "column", children: commands.map((c) => /* @__PURE__ */ jsx20(Text16, { wrap: "truncate", color: C.faint, children: c }, c)) }) : /* @__PURE__ */ jsx20(Text16, { color: C.faint, children: s.nothing }),
|
|
18162
|
+
applying ? /* @__PURE__ */ jsx20(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx20(Text16, { color: C.blue, children: s.applying }) }) : null
|
|
18163
|
+
] });
|
|
18378
18164
|
}
|
|
18379
18165
|
|
|
18380
|
-
// src/tui/screens/
|
|
18381
|
-
import {
|
|
18382
|
-
var
|
|
18383
|
-
|
|
18384
|
-
|
|
18166
|
+
// src/tui/screens/OpenRig.tsx
|
|
18167
|
+
import { jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
18168
|
+
var LOOK = {
|
|
18169
|
+
running: { glyph: "\u25CF", color: () => C.green },
|
|
18170
|
+
starting: { glyph: "\u25CC", color: () => C.blue },
|
|
18171
|
+
attention: { glyph: "\u25B2", color: () => C.yellow },
|
|
18172
|
+
stopped: { glyph: "\u25CB", color: () => C.faint }
|
|
18173
|
+
};
|
|
18174
|
+
function question(t, a) {
|
|
18175
|
+
const w = t.openrig.what;
|
|
18176
|
+
if (a.kind === "rig.stop") return t.openrig.confirm(w["rig.stop"](a.rig));
|
|
18177
|
+
if (a.kind === "rig.restart") return t.openrig.confirm(w["rig.restart"](a.rig));
|
|
18178
|
+
if (a.kind === "daemon.stop" || a.kind === "daemon.restart" || a.kind === "kernel.stop" || a.kind === "kernel.restart") return t.openrig.confirm(w[a.kind]);
|
|
18179
|
+
return "";
|
|
18180
|
+
}
|
|
18181
|
+
function OpenRigScreen() {
|
|
18385
18182
|
const tui = useTui();
|
|
18386
|
-
const {
|
|
18387
|
-
const
|
|
18388
|
-
const
|
|
18389
|
-
const
|
|
18390
|
-
|
|
18391
|
-
const
|
|
18392
|
-
const
|
|
18393
|
-
const
|
|
18394
|
-
const [
|
|
18395
|
-
const
|
|
18396
|
-
const [
|
|
18397
|
-
const [
|
|
18398
|
-
const [
|
|
18399
|
-
const
|
|
18400
|
-
|
|
18401
|
-
|
|
18402
|
-
|
|
18403
|
-
|
|
18404
|
-
|
|
18405
|
-
|
|
18406
|
-
|
|
18407
|
-
|
|
18408
|
-
|
|
18409
|
-
setDefs({ roles: m.roles, templates: m.templates, problems: m.problems, ...m.error ? { error: m.error } : {} });
|
|
18183
|
+
const { t, machines } = tui;
|
|
18184
|
+
const o = t.openrig;
|
|
18185
|
+
const [machineId, setMachineId] = useState14(tui.kept.rigMachine ?? null);
|
|
18186
|
+
const machine = machines.find((m) => m.id === machineId) ?? machines[0] ?? null;
|
|
18187
|
+
tui.kept.rigMachine = machine?.id ?? null;
|
|
18188
|
+
const rig = useOpenRig(tui.client, machine?.id ?? null);
|
|
18189
|
+
const state2 = rig.state;
|
|
18190
|
+
const rigs = listedRigs(state2);
|
|
18191
|
+
const [at, setAt] = useState14(0);
|
|
18192
|
+
const selectedId = useRef12(null);
|
|
18193
|
+
const [open, setOpen] = useState14(/* @__PURE__ */ new Set());
|
|
18194
|
+
const [confirm, setConfirm] = useState14(null);
|
|
18195
|
+
const [seats, setSeats] = useState14(null);
|
|
18196
|
+
const ids = rigs.map((r) => r.id).join(",");
|
|
18197
|
+
useEffect13(() => {
|
|
18198
|
+
setAt((a) => keepRig(rigs, a, selectedId.current));
|
|
18199
|
+
}, [ids]);
|
|
18200
|
+
const current2 = rigs[Math.min(at, rigs.length - 1)];
|
|
18201
|
+
selectedId.current = current2?.id ?? null;
|
|
18202
|
+
const run2 = (a) => {
|
|
18203
|
+
void rig.act(a).then((d) => {
|
|
18204
|
+
if (d.error === "cancelled") return;
|
|
18205
|
+
tui.toast(d.ok ? { text: o.done(d.commands.join(" && ")), tone: "ok" } : { text: o.failed(o.why[d.error ?? ""] ?? d.error ?? ""), tone: "error" });
|
|
18410
18206
|
});
|
|
18411
|
-
|
|
18412
|
-
|
|
18413
|
-
|
|
18414
|
-
|
|
18415
|
-
|
|
18416
|
-
|
|
18417
|
-
|
|
18418
|
-
|
|
18419
|
-
|
|
18420
|
-
|
|
18421
|
-
|
|
18422
|
-
const
|
|
18423
|
-
|
|
18424
|
-
|
|
18425
|
-
|
|
18426
|
-
|
|
18427
|
-
|
|
18428
|
-
|
|
18429
|
-
|
|
18430
|
-
|
|
18431
|
-
|
|
18432
|
-
|
|
18433
|
-
|
|
18434
|
-
|
|
18207
|
+
};
|
|
18208
|
+
const ask2 = (a) => {
|
|
18209
|
+
if (!state2) return;
|
|
18210
|
+
if (asksFirst(a)) setConfirm(confirmOf(state2, a));
|
|
18211
|
+
else run2(a);
|
|
18212
|
+
};
|
|
18213
|
+
const seatRig = seats ? rigs.find((r) => r.name === seats.rig) : void 0;
|
|
18214
|
+
const rows = seatRig ? seatRows(seatRig) : [];
|
|
18215
|
+
useEffect13(() => {
|
|
18216
|
+
if (seats && !seats.applying && !canReseat(seatRig)) setSeats(null);
|
|
18217
|
+
}, [seats, seatRig]);
|
|
18218
|
+
const apply = () => {
|
|
18219
|
+
if (!seats || !seatRig || !machine || seats.applying) return;
|
|
18220
|
+
const changed = changedCounts(rows, seats.counts);
|
|
18221
|
+
if (!Object.keys(changed).length) return;
|
|
18222
|
+
const adds = planOf(seatRig, rows, seats.counts).add.length > 0;
|
|
18223
|
+
setSeats((x) => x ? { ...x, applying: true } : x);
|
|
18224
|
+
void reseatRig(tui.client, machine.id, seatRig.name, changed, adds ? seats.delegation : void 0).then((r) => {
|
|
18225
|
+
if (!r.ok) {
|
|
18226
|
+
setSeats((x) => x ? { ...x, applying: false } : x);
|
|
18227
|
+
tui.toast({ text: t.rigSeats.why[r.error ?? ""] ?? r.error ?? "", tone: "error" });
|
|
18228
|
+
return;
|
|
18229
|
+
}
|
|
18230
|
+
setSeats(null);
|
|
18231
|
+
rig.refresh();
|
|
18232
|
+
const done = t.rigSeats.done(r.added.length, r.removed.length, r.links);
|
|
18233
|
+
tui.toast({ text: r.linksUnsupported ? `${done} \xB7 ${t.rigSeats.linksUnsupported}` : done, tone: r.linksUnsupported ? "info" : "ok" });
|
|
18234
|
+
});
|
|
18235
|
+
};
|
|
18435
18236
|
useScreenKeys((input, key) => {
|
|
18436
|
-
if (
|
|
18437
|
-
|
|
18237
|
+
if (seats) {
|
|
18238
|
+
if (seats.applying) return true;
|
|
18239
|
+
if (key.escape) {
|
|
18240
|
+
setSeats(null);
|
|
18241
|
+
return true;
|
|
18242
|
+
}
|
|
18243
|
+
if (key.return) {
|
|
18244
|
+
apply();
|
|
18245
|
+
return true;
|
|
18246
|
+
}
|
|
18247
|
+
if (key.upArrow || input === "k") {
|
|
18248
|
+
setSeats((x) => x ? { ...x, at: step2(x.at, -1, rows.length) } : x);
|
|
18249
|
+
return true;
|
|
18250
|
+
}
|
|
18251
|
+
if (key.downArrow || input === "j") {
|
|
18252
|
+
setSeats((x) => x ? { ...x, at: step2(x.at, 1, rows.length) } : x);
|
|
18253
|
+
return true;
|
|
18254
|
+
}
|
|
18255
|
+
const role = rows[seats.at]?.role;
|
|
18256
|
+
if (role && (input === "+" || input === "=")) {
|
|
18257
|
+
setSeats((x) => x ? { ...x, counts: withCount(x.counts, role, 1) } : x);
|
|
18258
|
+
return true;
|
|
18259
|
+
}
|
|
18260
|
+
if (role && input === "-") {
|
|
18261
|
+
setSeats((x) => x ? { ...x, counts: withCount(x.counts, role, -1) } : x);
|
|
18262
|
+
return true;
|
|
18263
|
+
}
|
|
18264
|
+
if (key.leftArrow || key.rightArrow) {
|
|
18265
|
+
setSeats((x) => x ? { ...x, delegation: x.delegation === "pairs" ? "all" : "pairs" } : x);
|
|
18266
|
+
return true;
|
|
18267
|
+
}
|
|
18438
18268
|
return true;
|
|
18439
18269
|
}
|
|
18440
|
-
if (
|
|
18441
|
-
if (
|
|
18270
|
+
if (confirm) {
|
|
18271
|
+
if (input === "y") {
|
|
18272
|
+
run2(confirm.action);
|
|
18273
|
+
setConfirm(null);
|
|
18274
|
+
return true;
|
|
18275
|
+
}
|
|
18276
|
+
if (input === "n" || key.escape) {
|
|
18277
|
+
setConfirm(null);
|
|
18278
|
+
return true;
|
|
18279
|
+
}
|
|
18442
18280
|
return true;
|
|
18443
18281
|
}
|
|
18444
|
-
if (
|
|
18445
|
-
|
|
18282
|
+
if (key.tab) {
|
|
18283
|
+
const i = Math.max(0, machines.findIndex((m) => m.id === machine?.id));
|
|
18284
|
+
setMachineId(machines[step2(i, key.shift ? -1 : 1, machines.length)]?.id ?? null);
|
|
18285
|
+
setOpen(/* @__PURE__ */ new Set());
|
|
18446
18286
|
return true;
|
|
18447
18287
|
}
|
|
18448
|
-
if (
|
|
18449
|
-
|
|
18450
|
-
setProblems(false);
|
|
18288
|
+
if (input === "+") {
|
|
18289
|
+
if (machine) tui.go("rigLaunch");
|
|
18451
18290
|
return true;
|
|
18452
18291
|
}
|
|
18453
|
-
if (
|
|
18454
|
-
|
|
18455
|
-
const next2 = order2[stepIndex(order2.length, i, input === "j" || key.downArrow ? 1 : -1)];
|
|
18456
|
-
if (next2) setAt((x) => ({ ...x, [view]: next2.key }));
|
|
18292
|
+
if (key.upArrow || input === "k") {
|
|
18293
|
+
setAt((i) => step2(i, -1, rigs.length));
|
|
18457
18294
|
return true;
|
|
18458
18295
|
}
|
|
18459
|
-
if (input === "
|
|
18460
|
-
|
|
18461
|
-
catalog.current.folder = next2.cwd;
|
|
18462
|
-
catalog.current.machine = next2.machine;
|
|
18463
|
-
setScope(next2);
|
|
18464
|
-
setProblems(false);
|
|
18296
|
+
if (key.downArrow || input === "j") {
|
|
18297
|
+
setAt((i) => step2(i, 1, rigs.length));
|
|
18465
18298
|
return true;
|
|
18466
18299
|
}
|
|
18467
|
-
if (key.return
|
|
18468
|
-
|
|
18469
|
-
|
|
18300
|
+
if (key.return) {
|
|
18301
|
+
if (current2) setOpen((s) => {
|
|
18302
|
+
const n = new Set(s);
|
|
18303
|
+
if (n.has(current2.id)) n.delete(current2.id);
|
|
18304
|
+
else n.add(current2.id);
|
|
18305
|
+
return n;
|
|
18306
|
+
});
|
|
18307
|
+
return true;
|
|
18308
|
+
}
|
|
18309
|
+
const busy = rig.pending !== null;
|
|
18310
|
+
if (input === "D") {
|
|
18311
|
+
if (state2?.installed && !busy) ask2(daemonToggle(state2));
|
|
18312
|
+
return true;
|
|
18313
|
+
}
|
|
18314
|
+
if (input === "K") {
|
|
18315
|
+
if (daemonUp(state2) && !busy) ask2(kernelToggle(state2));
|
|
18316
|
+
return true;
|
|
18317
|
+
}
|
|
18318
|
+
if (input === "O") {
|
|
18319
|
+
const op = operatorSession(state2, tui.d.sessions, machine?.id ?? "local");
|
|
18320
|
+
if (op) {
|
|
18321
|
+
tui.select(op.id);
|
|
18322
|
+
tui.go("session");
|
|
18323
|
+
} else if (daemonUp(state2)) tui.toast({ text: o.operatorNotYet, tone: "info" });
|
|
18324
|
+
return true;
|
|
18325
|
+
}
|
|
18326
|
+
if (input === "s") {
|
|
18327
|
+
if (daemonUp(state2) && current2 && !busy) ask2(rigToggle(current2));
|
|
18328
|
+
return true;
|
|
18329
|
+
}
|
|
18330
|
+
if (input === "R") {
|
|
18331
|
+
if (daemonUp(state2) && current2 && !busy) ask2({ kind: "rig.restart", rig: current2.name });
|
|
18470
18332
|
return true;
|
|
18471
18333
|
}
|
|
18472
|
-
if (input === "
|
|
18473
|
-
|
|
18474
|
-
tui.
|
|
18334
|
+
if (input === "\xB1" || input === "=") {
|
|
18335
|
+
if (!busy && canReseat(current2)) setSeats({ rig: current2.name, counts: countsOf(seatRows(current2)), at: 0, delegation: "pairs", applying: false });
|
|
18336
|
+
else if (current2) tui.toast({ text: t.rigSeats.notRunning, tone: "info" });
|
|
18475
18337
|
return true;
|
|
18476
18338
|
}
|
|
18477
18339
|
return false;
|
|
18478
18340
|
});
|
|
18479
|
-
const
|
|
18480
|
-
const
|
|
18481
|
-
|
|
18482
|
-
|
|
18483
|
-
|
|
18484
|
-
|
|
18485
|
-
|
|
18486
|
-
|
|
18487
|
-
|
|
18488
|
-
|
|
18489
|
-
const
|
|
18490
|
-
const
|
|
18491
|
-
const
|
|
18492
|
-
const
|
|
18493
|
-
|
|
18494
|
-
/* @__PURE__ */
|
|
18495
|
-
|
|
18496
|
-
|
|
18497
|
-
|
|
18498
|
-
|
|
18499
|
-
|
|
18500
|
-
" ",
|
|
18501
|
-
r.text
|
|
18502
|
-
] }, r.key);
|
|
18503
|
-
const on = r.key === current2?.key;
|
|
18504
|
-
return /* @__PURE__ */ jsxs15(Text17, { wrap: "truncate", backgroundColor: on ? C.sel : void 0, children: [
|
|
18505
|
-
/* @__PURE__ */ jsx21(Text17, { color: on ? C.coral : C.faint, children: on ? "\u258C" : " " }),
|
|
18506
|
-
r.kind === "role" ? /* @__PURE__ */ jsxs15(Fragment6, { children: [
|
|
18507
|
-
/* @__PURE__ */ jsxs15(Text17, { color: C.violet, children: [
|
|
18508
|
-
"@",
|
|
18509
|
-
fit(r.role.id, 8)
|
|
18341
|
+
const keys = seats ? [["\u2191 \u2193", t.rigSeats.role], ["- +", t.rigSeats.count], ["\u2190 \u2192", t.rigSeats.delegationKey], ["\u21B5", t.rigSeats.apply], ["esc", t.rigSeats.cancel]] : confirm ? [["y", o.yes], ["n", o.no]] : [["tab", o.machine], ["j k", t.keys.navigate], ["\u21B5", o.unfold], ["s", o.toggle], ["R", o.restart], ["\xB1 =", t.rigSeats.key], ["+", t.rigLaunch.launchKey], ["D", o.daemonKey], ["K", o.kernelKey], ["O", o.operatorKey], ["esc", t.keys.back]];
|
|
18342
|
+
const crumb = [state2?.version ? o.version(state2.version) : o.title, machine?.label].filter(Boolean).join(" \xB7 ");
|
|
18343
|
+
return /* @__PURE__ */ jsxs16(Frame, { crumb, crumbShort: o.title, keys, children: [
|
|
18344
|
+
!machine ? null : rig.error ? /* @__PURE__ */ jsx21(TitledBox, { title: o.title, mark: { text: machine.label, color: C.dim }, flexGrow: 1, children: /* @__PURE__ */ jsx21(Text17, { color: C.yellow, children: rig.error === "offline" ? o.offline : o.outdated }) }) : !state2 ? /* @__PURE__ */ jsx21(TitledBox, { title: o.title, mark: { text: machine.label, color: C.dim }, flexGrow: 1, children: /* @__PURE__ */ jsx21(Text17, { color: C.faint, children: o.loading }) }) : !state2.installed ? /* @__PURE__ */ jsx21(TitledBox, { title: o.title, mark: { text: machine.label, color: C.dim }, flexGrow: 1, children: /* @__PURE__ */ jsx21(Text17, { color: C.dim, children: o.notInstalled }) }) : seats && seatRig ? /* @__PURE__ */ jsx21(RigSeats, { rig: seatRig, machine: machine.label, rows, counts: seats.counts, at: seats.at, delegation: seats.delegation, plan: planOf(seatRig, rows, seats.counts), applying: seats.applying }) : /* @__PURE__ */ jsx21(Body, { state: state2, rigs, at, open, machineLabel: machine.label }),
|
|
18345
|
+
confirm ? /* @__PURE__ */ jsx21(ConfirmBox, { confirm }) : null,
|
|
18346
|
+
rig.pending ? /* @__PURE__ */ jsx21(Box16, { paddingX: 1, height: 1, children: /* @__PURE__ */ jsx21(Text17, { wrap: "truncate", color: C.blue, children: o.running(confirmOf(state2 ?? EMPTY2, rig.pending).commands.join(" && ")) }) }) : null
|
|
18347
|
+
] });
|
|
18348
|
+
}
|
|
18349
|
+
var EMPTY2 = { installed: true, daemon: { state: "unknown" }, kernel: { state: "unknown" }, rigs: [], at: "" };
|
|
18350
|
+
function Body({ state: state2, rigs, at, open, machineLabel: machineLabel2 }) {
|
|
18351
|
+
const { t } = useTui();
|
|
18352
|
+
const o = t.openrig;
|
|
18353
|
+
const up = daemonUp(state2);
|
|
18354
|
+
const kernelColor = state2.kernel.state === "ready" ? C.green : state2.kernel.state === "starting" ? C.blue : C.faint;
|
|
18355
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", flexGrow: 1, children: [
|
|
18356
|
+
/* @__PURE__ */ jsxs16(Box16, { children: [
|
|
18357
|
+
/* @__PURE__ */ jsxs16(TitledBox, { title: `${o.daemon} \xB7 ${machineLabel2}`, flexGrow: 1, width: "50%", children: [
|
|
18358
|
+
/* @__PURE__ */ jsxs16(Text17, { wrap: "truncate", children: [
|
|
18359
|
+
/* @__PURE__ */ jsxs16(Text17, { color: up ? C.green : C.faint, children: [
|
|
18360
|
+
up ? "\u25CF " : "\u25CB ",
|
|
18361
|
+
o.daemonState[state2.daemon.state] ?? state2.daemon.state
|
|
18510
18362
|
] }),
|
|
18511
|
-
|
|
18512
|
-
|
|
18513
|
-
|
|
18514
|
-
|
|
18515
|
-
|
|
18516
|
-
|
|
18517
|
-
|
|
18518
|
-
|
|
18519
|
-
|
|
18520
|
-
|
|
18521
|
-
|
|
18522
|
-
|
|
18523
|
-
|
|
18524
|
-
|
|
18525
|
-
|
|
18526
|
-
|
|
18527
|
-
|
|
18528
|
-
|
|
18529
|
-
|
|
18530
|
-
|
|
18531
|
-
|
|
18532
|
-
|
|
18533
|
-
|
|
18534
|
-
] })
|
|
18363
|
+
/* @__PURE__ */ jsxs16(Text17, { color: C.dim, children: [
|
|
18364
|
+
" ",
|
|
18365
|
+
up ? o.daemonMeta(state2.daemon.port, state2.daemon.pid) : state2.daemon.message ?? ""
|
|
18366
|
+
] })
|
|
18367
|
+
] }),
|
|
18368
|
+
/* @__PURE__ */ jsx21(Text17, { wrap: "truncate", color: C.faint, children: up ? o.restoreHint : o.stoppedDaemon })
|
|
18369
|
+
] }),
|
|
18370
|
+
/* @__PURE__ */ jsxs16(TitledBox, { title: o.kernel, flexGrow: 1, width: "50%", children: [
|
|
18371
|
+
/* @__PURE__ */ jsxs16(Text17, { wrap: "truncate", color: up ? kernelColor : C.faint, children: [
|
|
18372
|
+
state2.kernel.state === "ready" ? "\u25CF " : "\u25CB ",
|
|
18373
|
+
o.kernelState[state2.kernel.state] ?? state2.kernel.state
|
|
18374
|
+
] }),
|
|
18375
|
+
/* @__PURE__ */ jsx21(Text17, { wrap: "truncate", color: C.faint, children: o.kernelHint }),
|
|
18376
|
+
up && (state2.rigs.find((r) => r.name === "kernel")?.nodes ?? []).map((n) => /* @__PURE__ */ jsxs16(Text17, { wrap: "truncate", children: [
|
|
18377
|
+
/* @__PURE__ */ jsx21(Text17, { color: n.sessionStatus !== "running" ? C.faint : n.activity === "running" ? C.blue : C.green, children: "\u25C6 " }),
|
|
18378
|
+
/* @__PURE__ */ jsx21(Text17, { color: C.fg, children: n.logicalId.padEnd(16) }),
|
|
18379
|
+
/* @__PURE__ */ jsx21(Text17, { color: C.dim, children: n.runtime.padEnd(13) }),
|
|
18380
|
+
/* @__PURE__ */ jsx21(Text17, { color: C.dim, children: n.sessionStatus === "running" ? o.activity(n.activity) : n.sessionStatus }),
|
|
18381
|
+
n.logicalId === "operator.agent" && /* @__PURE__ */ jsxs16(Text17, { color: C.faint, children: [
|
|
18382
|
+
" ",
|
|
18383
|
+
o.operatorHint
|
|
18384
|
+
] })
|
|
18385
|
+
] }, n.session))
|
|
18535
18386
|
] })
|
|
18536
|
-
] })
|
|
18387
|
+
] }),
|
|
18388
|
+
/* @__PURE__ */ jsx21(TitledBox, { title: `${o.rigs} \xB7 ${rigs.length}`, flexGrow: 1, children: !up ? /* @__PURE__ */ jsx21(Text17, { color: C.faint, children: o.stoppedDaemon }) : !rigs.length ? /* @__PURE__ */ jsx21(Text17, { color: C.faint, children: o.noRigs }) : rigs.map((r, i) => /* @__PURE__ */ jsx21(RigRow, { rig: r, selected: i === at, open: open.has(r.id) }, r.id)) })
|
|
18537
18389
|
] });
|
|
18538
|
-
|
|
18539
|
-
|
|
18540
|
-
|
|
18390
|
+
}
|
|
18391
|
+
function RigRow({ rig, selected, open }) {
|
|
18392
|
+
const { t } = useTui();
|
|
18393
|
+
const o = t.openrig;
|
|
18394
|
+
const look = rigLook(rig), l = LOOK[look];
|
|
18395
|
+
const onPurpose = look === "stopped" && rig.nodes.length > 0 && rig.nodes.every((n) => n.stopped);
|
|
18396
|
+
const note = rig.attention > 0 ? { text: o.attention(rig.attention), color: C.yellow } : onPurpose ? { text: o.stoppedOnPurpose, color: C.dim } : null;
|
|
18397
|
+
const when = [rig.uptime ? o.since(rig.uptime) : "", rig.snapshot ? o.snapshot(rig.snapshot) : ""].filter(Boolean).join(" \xB7 ");
|
|
18398
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
|
|
18399
|
+
/* @__PURE__ */ jsx21(Box16, { backgroundColor: selected ? C.sel : void 0, children: /* @__PURE__ */ jsxs16(Text17, { wrap: "truncate", children: [
|
|
18400
|
+
/* @__PURE__ */ jsx21(Text17, { color: selected ? C.coral : C.faint, children: selected ? "\u258C" : " " }),
|
|
18401
|
+
/* @__PURE__ */ jsx21(Text17, { color: C.dim, children: open ? "\u25BE " : "\u25B8 " }),
|
|
18402
|
+
/* @__PURE__ */ jsx21(Text17, { color: C.fg, bold: true, children: rig.name.padEnd(16) }),
|
|
18403
|
+
/* @__PURE__ */ jsx21(Text17, { color: l.color(), children: ` ${l.glyph} ${o.look[look]}`.padEnd(18) }),
|
|
18404
|
+
/* @__PURE__ */ jsx21(Text17, { color: C.fg, children: o.seats(rig.running, rig.seats).padEnd(7) }),
|
|
18405
|
+
note ? /* @__PURE__ */ jsx21(Text17, { color: note.color, children: note.text.padEnd(34) }) : /* @__PURE__ */ jsx21(Text17, { children: "".padEnd(34) }),
|
|
18406
|
+
/* @__PURE__ */ jsx21(Text17, { color: C.dim, children: when })
|
|
18407
|
+
] }) }),
|
|
18408
|
+
open ? rig.nodes.map((n) => /* @__PURE__ */ jsxs16(Text17, { wrap: "truncate", children: [
|
|
18409
|
+
/* @__PURE__ */ jsx21(Text17, { color: seatBusy(n) ? C.blue : C.faint, children: " \u25C6 " }),
|
|
18410
|
+
/* @__PURE__ */ jsx21(Text17, { color: C.fg, children: n.logicalId.padEnd(18) }),
|
|
18411
|
+
/* @__PURE__ */ jsx21(Text17, { color: C.dim, children: [n.runtime, n.model].filter(Boolean).join(" \xB7 ").padEnd(26) }),
|
|
18412
|
+
/* @__PURE__ */ jsx21(Text17, { color: n.activity === "running" ? C.blue : C.dim, children: o.activity(n.activity).padEnd(12) }),
|
|
18413
|
+
/* @__PURE__ */ jsx21(Text17, { color: C.dim, children: o.work(n.work) })
|
|
18414
|
+
] }, n.logicalId)) : null
|
|
18541
18415
|
] });
|
|
18542
|
-
|
|
18543
|
-
|
|
18544
|
-
|
|
18545
|
-
|
|
18546
|
-
|
|
18547
|
-
|
|
18548
|
-
|
|
18549
|
-
|
|
18550
|
-
|
|
18551
|
-
|
|
18552
|
-
|
|
18553
|
-
|
|
18554
|
-
|
|
18555
|
-
|
|
18556
|
-
|
|
18557
|
-
|
|
18558
|
-
|
|
18559
|
-
|
|
18560
|
-
|
|
18561
|
-
|
|
18562
|
-
|
|
18563
|
-
|
|
18564
|
-
|
|
18416
|
+
}
|
|
18417
|
+
function ConfirmBox({ confirm }) {
|
|
18418
|
+
const { t } = useTui();
|
|
18419
|
+
const o = t.openrig;
|
|
18420
|
+
return /* @__PURE__ */ jsxs16(TitledBox, { title: o.confirmTitle, color: C.coral, titleColor: C.coral, titleBold: true, double: true, children: [
|
|
18421
|
+
/* @__PURE__ */ jsx21(Text17, { wrap: "truncate", color: C.fg, bold: true, children: question(t, confirm.action) }),
|
|
18422
|
+
/* @__PURE__ */ jsx21(Text17, { wrap: "wrap", color: confirm.busy.length ? C.yellow : C.dim, children: o.busy(confirm.busy.join(", "), confirm.busy.length) }),
|
|
18423
|
+
confirm.commands.map((c) => /* @__PURE__ */ jsx21(Text17, { wrap: "truncate", color: C.faint, children: c }, c)),
|
|
18424
|
+
/* @__PURE__ */ jsxs16(Text17, { children: [
|
|
18425
|
+
/* @__PURE__ */ jsx21(Text17, { color: C.fg, bold: true, children: " y " }),
|
|
18426
|
+
/* @__PURE__ */ jsxs16(Text17, { color: C.dim, children: [
|
|
18427
|
+
o.yes,
|
|
18428
|
+
" "
|
|
18429
|
+
] }),
|
|
18430
|
+
/* @__PURE__ */ jsx21(Text17, { color: C.fg, bold: true, children: " n " }),
|
|
18431
|
+
/* @__PURE__ */ jsx21(Text17, { color: C.dim, children: o.no })
|
|
18432
|
+
] })
|
|
18433
|
+
] });
|
|
18434
|
+
}
|
|
18435
|
+
function operatorSession(state2, sessions, machine) {
|
|
18436
|
+
const seat = state2?.rigs.find((r) => r.name === "kernel")?.nodes.find((n) => n.logicalId === "operator.agent")?.session;
|
|
18437
|
+
return seat ? sessions.find((x) => x.rig?.seat === seat && x.state !== "exited" && (x.machineId ?? "local") === machine) : void 0;
|
|
18438
|
+
}
|
|
18439
|
+
|
|
18440
|
+
// src/tui/screens/RigLaunch.tsx
|
|
18441
|
+
import { useEffect as useEffect14, useMemo as useMemo6, useRef as useRef13, useState as useState15 } from "react";
|
|
18442
|
+
import { Box as Box17, Text as Text18, useInput as useInput7 } from "ink";
|
|
18443
|
+
|
|
18444
|
+
// src/tui/model/rigLaunch.ts
|
|
18445
|
+
var RUNTIMES = ["claude-code", "codex"];
|
|
18446
|
+
var orderSpecs = (specs) => [...specs].sort((a, b2) => a.source === b2.source ? a.name.localeCompare(b2.name) : a.source === "user" ? -1 : b2.source === "user" ? 1 : a.source.localeCompare(b2.source));
|
|
18447
|
+
var rolesOf = (spec) => (spec?.pods ?? []).flatMap((p) => p.members.map((m) => ({ role: `${p.id}.${m.id}`, pod: p.id, member: m.id, agent: m.agent, runtime: m.runtime, ...m.model ? { model: m.model } : {}, ...m.policy ? { policy: m.policy } : {} })));
|
|
18448
|
+
var emptyForm = (spec, cwd = "") => ({ spec, cwd, name: null, seats: {}, runtimes: {}, models: {}, delegation: "pairs", save: false, policy: null, policies: {}, nonInterruptive: false });
|
|
18449
|
+
var withSpec = (f, spec) => ({ ...f, spec, seats: {}, runtimes: {}, models: {}, policies: {} });
|
|
18450
|
+
function withPolicy(f, by) {
|
|
18451
|
+
const all2 = [null, ...RIG_POLICIES];
|
|
18452
|
+
return { ...f, policy: all2[(all2.indexOf(f.policy) + by + all2.length) % all2.length] };
|
|
18453
|
+
}
|
|
18454
|
+
function withRolePolicy(f, role) {
|
|
18455
|
+
const all2 = [void 0, ...RIG_POLICIES];
|
|
18456
|
+
const next3 = all2[(all2.indexOf(f.policies[role]) + 1) % all2.length];
|
|
18457
|
+
const { [role]: _gone, ...rest } = f.policies;
|
|
18458
|
+
return { ...f, policies: next3 ? { ...rest, [role]: next3 } : rest };
|
|
18459
|
+
}
|
|
18460
|
+
var yoloChosen = (f, roles) => f.policy === "yolo" || roles.some((r) => f.policies[r.role] === "yolo");
|
|
18461
|
+
var seatsOf = (f, role) => f.seats[role] ?? 1;
|
|
18462
|
+
var withSeats = (f, role, by) => ({ ...f, seats: { ...f.seats, [role]: Math.max(0, Math.min(9, seatsOf(f, role) + by)) } });
|
|
18463
|
+
var runtimeOf = (f, r) => f.runtimes[r.role] ?? r.runtime;
|
|
18464
|
+
function withRuntime(f, r, by) {
|
|
18465
|
+
const cur = runtimeOf(f, r), i = RUNTIMES.indexOf(cur);
|
|
18466
|
+
const next3 = RUNTIMES[((i < 0 ? by > 0 ? -1 : 0 : i) + by + RUNTIMES.length) % RUNTIMES.length];
|
|
18467
|
+
const { [r.role]: _gone, ...rest } = f.runtimes;
|
|
18468
|
+
return { ...f, runtimes: next3 === r.runtime ? rest : { ...rest, [r.role]: next3 } };
|
|
18469
|
+
}
|
|
18470
|
+
var modelOf = (f, r) => f.models[r.role] ?? r.model;
|
|
18471
|
+
function withModel(f, r, model) {
|
|
18472
|
+
const { [r.role]: _gone, ...rest } = f.models;
|
|
18473
|
+
const m = model.trim();
|
|
18474
|
+
return { ...f, models: m && m !== r.model ? { ...rest, [r.role]: m } : rest };
|
|
18475
|
+
}
|
|
18476
|
+
var totalSeats = (f, roles) => roles.reduce((n, r) => n + seatsOf(f, r.role), 0);
|
|
18477
|
+
var scaled = (f, roles) => roles.some((r) => seatsOf(f, r.role) > 1);
|
|
18478
|
+
var nameOf = (f) => f.name?.trim() || f.spec || "";
|
|
18479
|
+
function missingOf2(f, roles) {
|
|
18480
|
+
if (!f.spec) return "spec";
|
|
18481
|
+
if (!f.cwd.trim()) return "cwd";
|
|
18482
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(nameOf(f))) return "name";
|
|
18483
|
+
if (totalSeats(f, roles) === 0) return "seats";
|
|
18484
|
+
return null;
|
|
18485
|
+
}
|
|
18486
|
+
function launchOf(f, roles, plan) {
|
|
18487
|
+
const seats = Object.fromEntries(roles.filter((r) => seatsOf(f, r.role) !== 1).map((r) => [r.role, seatsOf(f, r.role)]));
|
|
18488
|
+
const runtimes = Object.fromEntries(roles.filter((r) => f.runtimes[r.role]).map((r) => [r.role, f.runtimes[r.role]]));
|
|
18489
|
+
const models = Object.fromEntries(roles.filter((r) => f.models[r.role]).map((r) => [r.role, f.models[r.role]]));
|
|
18490
|
+
const policies = Object.fromEntries(roles.filter((r) => f.policies[r.role]).map((r) => [r.role, f.policies[r.role]]));
|
|
18491
|
+
return {
|
|
18492
|
+
spec: f.spec,
|
|
18493
|
+
cwd: f.cwd.trim(),
|
|
18494
|
+
name: nameOf(f),
|
|
18495
|
+
...Object.keys(seats).length ? { seats } : {},
|
|
18496
|
+
...Object.keys(runtimes).length ? { runtimes } : {},
|
|
18497
|
+
...Object.keys(models).length ? { models } : {},
|
|
18498
|
+
...f.policy ? { policy: f.policy } : {},
|
|
18499
|
+
...Object.keys(policies).length ? { policies } : {},
|
|
18500
|
+
...f.nonInterruptive && yoloChosen(f, roles) ? { nonInterruptive: true } : {},
|
|
18501
|
+
...scaled(f, roles) ? { delegation: f.delegation } : {},
|
|
18502
|
+
...f.save ? { save: true } : {},
|
|
18503
|
+
...plan ? { plan: true } : {}
|
|
18504
|
+
};
|
|
18505
|
+
}
|
|
18506
|
+
var folderChoices = (projects, machine) => (projects?.projects ?? []).flatMap((p) => p.repos.filter((r) => r.machine === machine).map((r) => ({ project: p.name, path: r.path })));
|
|
18507
|
+
function nextFolder(choices2, cwd, by) {
|
|
18508
|
+
if (!choices2.length) return cwd;
|
|
18509
|
+
const i = choices2.findIndex((c) => c.path === cwd);
|
|
18510
|
+
return choices2[i < 0 ? by > 0 ? 0 : choices2.length - 1 : (i + by + choices2.length) % choices2.length].path;
|
|
18511
|
+
}
|
|
18512
|
+
function warningLines(warnings) {
|
|
18513
|
+
const groups = /* @__PURE__ */ new Map();
|
|
18514
|
+
for (const w of warnings) {
|
|
18515
|
+
const m = /^([A-Za-z0-9_-]+\.[A-Za-z0-9_-]+):\s*(.+)$/.exec(w.trim());
|
|
18516
|
+
const key = m ? m[2] : w.trim(), who = m ? [m[1]] : [];
|
|
18517
|
+
groups.set(key, [...groups.get(key) ?? [], ...who]);
|
|
18518
|
+
}
|
|
18519
|
+
return [...groups].map(([text5, seats]) => ({ text: text5, seats }));
|
|
18520
|
+
}
|
|
18521
|
+
var fieldsOf = (roles, yolo = false) => ["spec", "cwd", "name", ...roles.map((_, i) => `role:${i}`), "policy", ...yolo ? ["nonInterruptive"] : [], "delegation", "save"];
|
|
18522
|
+
var roleAt = (field) => field.startsWith("role:") ? Number(field.slice(5)) : null;
|
|
18523
|
+
function moveField(fields, cur, by) {
|
|
18524
|
+
const i = fields.indexOf(cur);
|
|
18525
|
+
return fields[i < 0 ? 0 : (i + by + fields.length) % fields.length];
|
|
18526
|
+
}
|
|
18527
|
+
var isText = (field) => field === "cwd" || field === "name";
|
|
18528
|
+
|
|
18529
|
+
// src/tui/screens/RigLaunch.tsx
|
|
18530
|
+
import { Fragment as Fragment6, jsx as jsx22, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
18531
|
+
var SPEC_ROWS = 7;
|
|
18532
|
+
var specLine = (s) => {
|
|
18533
|
+
const members = s.pods.flatMap((p) => p.members.map((m) => m.id));
|
|
18534
|
+
return `${members.slice(0, 4).join(" + ")}${members.length > 4 ? "\u2026" : ""} \xB7 ${members.length}`;
|
|
18535
|
+
};
|
|
18536
|
+
function RigLaunchScreen() {
|
|
18537
|
+
const tui = useTui();
|
|
18538
|
+
const { t, g, machines, projects, client, toast, go, small } = tui;
|
|
18539
|
+
const l = t.rigLaunch;
|
|
18540
|
+
const machine = machines.find((m) => m.id === tui.kept.rigMachine) ?? machines[0] ?? null;
|
|
18541
|
+
const machineId = machine?.id ?? null;
|
|
18542
|
+
const specsView = useRigSpecs(client, machineId);
|
|
18543
|
+
const specs = useMemo6(() => orderSpecs(specsView.specs), [specsView.specs]);
|
|
18544
|
+
const folders = useMemo6(() => folderChoices(projects, machineId), [projects, machineId]);
|
|
18545
|
+
const [form, setFormState] = useState15(() => emptyForm(null, folders[0]?.path ?? ""));
|
|
18546
|
+
const [field, setField] = useState15("spec");
|
|
18547
|
+
const [modelAt, setModelAt] = useState15(null);
|
|
18548
|
+
const [modelDraft, setModelDraft] = useState15("");
|
|
18549
|
+
const [busy, setBusy] = useState15(null);
|
|
18550
|
+
const [result, setResult] = useState15(null);
|
|
18551
|
+
const alive = useRef13(true);
|
|
18552
|
+
useEffect14(() => () => {
|
|
18553
|
+
alive.current = false;
|
|
18554
|
+
}, []);
|
|
18555
|
+
useEditing(true);
|
|
18556
|
+
const spec = specs.find((s) => s.name === form.spec);
|
|
18557
|
+
const roles = rolesOf(spec);
|
|
18558
|
+
const yolo = yoloChosen(form, roles);
|
|
18559
|
+
const fields = fieldsOf(roles, yolo);
|
|
18560
|
+
useEffect14(() => {
|
|
18561
|
+
if (!form.spec && specs[0]) setFormState((f) => withSpec(f, specs[0].name));
|
|
18562
|
+
}, [specs]);
|
|
18563
|
+
useEffect14(() => {
|
|
18564
|
+
if (!form.cwd && folders[0]) setFormState((f) => ({ ...f, cwd: folders[0].path }));
|
|
18565
|
+
}, [folders]);
|
|
18566
|
+
const setForm = (fn) => {
|
|
18567
|
+
setFormState(fn);
|
|
18568
|
+
setResult(null);
|
|
18569
|
+
};
|
|
18570
|
+
const submit = (plan) => {
|
|
18571
|
+
if (busy || !machineId) return;
|
|
18572
|
+
const missing = missingOf2(form, roles);
|
|
18573
|
+
if (missing) {
|
|
18574
|
+
toast({ text: l.missing[missing], tone: "info" });
|
|
18575
|
+
return;
|
|
18576
|
+
}
|
|
18577
|
+
setBusy(plan ? "check" : "launch");
|
|
18578
|
+
setResult(null);
|
|
18579
|
+
const launch2 = launchOf(form, roles, plan);
|
|
18580
|
+
void launchRig(client, machineId, launch2).then((r) => {
|
|
18581
|
+
if (!alive.current) return;
|
|
18582
|
+
setBusy(null);
|
|
18583
|
+
setResult(r);
|
|
18584
|
+
if (!r.ok) {
|
|
18585
|
+
toast({ text: l.why[r.error ?? ""] ?? r.error ?? "", tone: "error" });
|
|
18586
|
+
return;
|
|
18587
|
+
}
|
|
18588
|
+
if (!plan) {
|
|
18589
|
+
toast({ text: l.launched(launch2.name, r.seats ?? totalSeats(form, roles)), tone: "ok" });
|
|
18590
|
+
go("openrig");
|
|
18591
|
+
}
|
|
18592
|
+
});
|
|
18593
|
+
};
|
|
18594
|
+
const role = roleAt(field) !== null ? roles[roleAt(field)] : void 0;
|
|
18595
|
+
useInput7((input, key) => {
|
|
18596
|
+
if (small && !key.escape) return;
|
|
18597
|
+
if (busy === "launch") return;
|
|
18598
|
+
if (modelAt !== null) {
|
|
18599
|
+
if (key.tab) {
|
|
18600
|
+
const r = roles[modelAt];
|
|
18601
|
+
if (r) setForm((f) => withModel(f, r, modelDraft));
|
|
18602
|
+
setModelAt(null);
|
|
18603
|
+
}
|
|
18604
|
+
return;
|
|
18605
|
+
}
|
|
18606
|
+
if (key.escape) {
|
|
18607
|
+
go("openrig");
|
|
18608
|
+
return;
|
|
18609
|
+
}
|
|
18610
|
+
if (key.ctrl && input === "s") {
|
|
18611
|
+
submit(false);
|
|
18612
|
+
return;
|
|
18613
|
+
}
|
|
18614
|
+
if (key.ctrl && input === "p") {
|
|
18615
|
+
submit(true);
|
|
18616
|
+
return;
|
|
18617
|
+
}
|
|
18618
|
+
if (key.tab || key.downArrow) {
|
|
18619
|
+
setField((f) => moveField(fields, f, key.shift ? -1 : 1));
|
|
18620
|
+
return;
|
|
18621
|
+
}
|
|
18622
|
+
if (key.upArrow) {
|
|
18623
|
+
setField((f) => moveField(fields, f, -1));
|
|
18624
|
+
return;
|
|
18625
|
+
}
|
|
18626
|
+
const by = key.rightArrow ? 1 : key.leftArrow ? -1 : 0;
|
|
18627
|
+
if (field === "cwd" && by) {
|
|
18628
|
+
setForm((f) => ({ ...f, cwd: nextFolder(folders, f.cwd, by) }));
|
|
18629
|
+
return;
|
|
18630
|
+
}
|
|
18631
|
+
if (isText(field)) return;
|
|
18632
|
+
if (input === "p") {
|
|
18633
|
+
submit(true);
|
|
18634
|
+
return;
|
|
18635
|
+
}
|
|
18636
|
+
if (field === "spec" && by && specs.length) {
|
|
18637
|
+
const i = Math.max(0, specs.findIndex((s) => s.name === form.spec));
|
|
18638
|
+
setForm((f) => withSpec(f, specs[(i + by + specs.length) % specs.length].name));
|
|
18639
|
+
return;
|
|
18640
|
+
}
|
|
18641
|
+
if (role) {
|
|
18642
|
+
if (by) setForm((f) => withRuntime(f, role, by));
|
|
18643
|
+
else if (input === "+" || input === "=") setForm((f) => withSeats(f, role.role, 1));
|
|
18644
|
+
else if (input === "-") setForm((f) => withSeats(f, role.role, -1));
|
|
18645
|
+
else if (input === "m") {
|
|
18646
|
+
setModelAt(roleAt(field));
|
|
18647
|
+
setModelDraft(modelOf(form, role) ?? "");
|
|
18648
|
+
} else if (input === "o") setForm((f) => withRolePolicy(f, role.role));
|
|
18649
|
+
return;
|
|
18650
|
+
}
|
|
18651
|
+
if (field === "policy" && by) {
|
|
18652
|
+
setForm((f) => withPolicy(f, by));
|
|
18653
|
+
return;
|
|
18654
|
+
}
|
|
18655
|
+
if (field === "nonInterruptive" && (by || input === " " || key.return)) {
|
|
18656
|
+
setForm((f) => ({ ...f, nonInterruptive: !f.nonInterruptive }));
|
|
18657
|
+
return;
|
|
18658
|
+
}
|
|
18659
|
+
if (field === "delegation" && (by || input === " ")) {
|
|
18660
|
+
setForm((f) => ({ ...f, delegation: f.delegation === "pairs" ? "all" : "pairs" }));
|
|
18661
|
+
return;
|
|
18662
|
+
}
|
|
18663
|
+
if (field === "save" && (by || input === " " || key.return)) {
|
|
18664
|
+
setForm((f) => ({ ...f, save: !f.save }));
|
|
18665
|
+
return;
|
|
18666
|
+
}
|
|
18667
|
+
});
|
|
18668
|
+
const row2 = (f, label, value, width = 9) => /* @__PURE__ */ jsxs17(Box17, { flexShrink: 0, backgroundColor: field === f ? C.sel : void 0, children: [
|
|
18669
|
+
/* @__PURE__ */ jsx22(Text18, { color: field === f ? C.coral : C.faint, children: field === f ? "\u258C" : " " }),
|
|
18670
|
+
/* @__PURE__ */ jsx22(Box17, { width, flexShrink: 0, children: /* @__PURE__ */ jsx22(Text18, { color: C.dim, children: label }) }),
|
|
18671
|
+
/* @__PURE__ */ jsx22(Box17, { flexGrow: 1, overflow: "hidden", children: value })
|
|
18672
|
+
] }, f);
|
|
18673
|
+
const chosen = (on, text5) => on ? /* @__PURE__ */ jsx22(Text18, { color: C.fg, bold: true, children: `${g.prev} ${text5} ${g.next}` }) : /* @__PURE__ */ jsx22(Text18, { color: C.dim, children: text5 });
|
|
18674
|
+
const at = Math.max(0, specs.findIndex((s) => s.name === form.spec));
|
|
18675
|
+
const from = Math.max(0, Math.min(at - Math.floor(SPEC_ROWS / 2), specs.length - SPEC_ROWS));
|
|
18676
|
+
const folderOf2 = folders.find((f) => f.path === form.cwd);
|
|
18677
|
+
const seats = totalSeats(form, roles);
|
|
18678
|
+
const stopped = specsView.error === "daemon_stopped";
|
|
18679
|
+
const keys = modelAt !== null ? [["\u21B5", t.keys.apply], ["esc", t.keys.cancel]] : [["tab \u2191 \u2193", t.keys.nextField], ["\u2190 \u2192", t.keys.choose], ["- +", l.count], ["m", l.modelKey], ["o", l.policyKey], ["p", l.check], ["ctrl+s", l.launch(seats)], ["esc", t.keys.cancel]];
|
|
18680
|
+
return /* @__PURE__ */ jsx22(Frame, { crumb: `${l.title} \xB7 ${machine?.label ?? "-"}`, crumbShort: l.title, keys, children: /* @__PURE__ */ jsxs17(Box17, { flexGrow: 1, children: [
|
|
18681
|
+
/* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", width: "55%", flexShrink: 0, children: [
|
|
18682
|
+
/* @__PURE__ */ jsx22(TitledBox, { title: l.spec, color: field === "spec" ? C.coral : C.line, titleColor: field === "spec" ? C.coral : C.dim, flexShrink: 0, height: (specs.length ? Math.min(SPEC_ROWS, specs.length) : 2) + 2, children: specsView.status === "loading" ? /* @__PURE__ */ jsx22(Text18, { color: C.faint, children: l.loading }) : stopped ? /* @__PURE__ */ jsx22(Text18, { color: C.yellow, children: l.daemonStopped }) : specsView.error ? /* @__PURE__ */ jsx22(Text18, { color: C.yellow, children: l.why[specsView.error] ?? specsView.error }) : !specs.length ? /* @__PURE__ */ jsx22(Text18, { color: C.faint, children: l.noSpecs }) : specs.slice(from, from + SPEC_ROWS).map((s) => {
|
|
18683
|
+
const on = s.name === form.spec;
|
|
18684
|
+
return /* @__PURE__ */ jsx22(Box17, { flexShrink: 0, backgroundColor: on && field === "spec" ? C.sel : void 0, children: /* @__PURE__ */ jsxs17(Text18, { wrap: "truncate", children: [
|
|
18685
|
+
/* @__PURE__ */ jsxs17(Text18, { color: on ? C.coral : C.dim, children: [
|
|
18686
|
+
on ? g.radioOn : g.radioOff,
|
|
18687
|
+
" "
|
|
18688
|
+
] }),
|
|
18689
|
+
/* @__PURE__ */ jsx22(Text18, { color: on ? C.fg : C.dim, bold: on, children: s.name.padEnd(16) }),
|
|
18690
|
+
/* @__PURE__ */ jsx22(Text18, { color: C.dim, children: specLine(s).padEnd(24) }),
|
|
18691
|
+
/* @__PURE__ */ jsx22(Text18, { color: C.faint, children: l.source[s.source] ?? s.source })
|
|
18692
|
+
] }) }, `${s.source}:${s.name}`);
|
|
18693
|
+
}) }),
|
|
18694
|
+
/* @__PURE__ */ jsxs17(TitledBox, { title: l.where, flexShrink: 0, height: folderOf2 ? 5 : 4, children: [
|
|
18695
|
+
row2("cwd", l.folder, /* @__PURE__ */ jsx22(Box17, { children: /* @__PURE__ */ jsx22(TextInput, { value: form.cwd, onChange: (v) => setForm((f) => ({ ...f, cwd: v })), active: field === "cwd" && modelAt === null, placeholder: l.folderHint }) })),
|
|
18696
|
+
folderOf2 ? /* @__PURE__ */ jsx22(Box17, { flexShrink: 0, children: /* @__PURE__ */ jsxs17(Text18, { wrap: "truncate", color: C.faint, children: [
|
|
18697
|
+
" ",
|
|
18698
|
+
g.prev,
|
|
18565
18699
|
" ",
|
|
18566
|
-
|
|
18567
|
-
"
|
|
18568
|
-
|
|
18569
|
-
|
|
18570
|
-
|
|
18571
|
-
|
|
18572
|
-
|
|
18573
|
-
|
|
18574
|
-
|
|
18700
|
+
l.projectFolder(folderOf2.project),
|
|
18701
|
+
" ",
|
|
18702
|
+
g.next
|
|
18703
|
+
] }) }) : null,
|
|
18704
|
+
row2("name", l.name, /* @__PURE__ */ jsx22(Box17, { children: /* @__PURE__ */ jsx22(TextInput, { value: form.name ?? "", onChange: (v) => setForm((f) => ({ ...f, name: v })), active: field === "name" && modelAt === null, placeholder: form.spec ?? "" }) }))
|
|
18705
|
+
] }),
|
|
18706
|
+
/* @__PURE__ */ jsxs17(TitledBox, { title: l.roles, flexGrow: 1, flexShrink: 1, children: [
|
|
18707
|
+
roles.length ? /* @__PURE__ */ jsx22(Box17, { flexShrink: 0, children: /* @__PURE__ */ jsx22(Text18, { wrap: "truncate", color: C.faint, children: l.rolesHint }) }) : null,
|
|
18708
|
+
roles.map((r, i) => {
|
|
18709
|
+
const f = `role:${i}`, on = field === f, n = seatsOf(form, r.role);
|
|
18710
|
+
const runtime = runtimeOf(form, r), model = modelOf(form, r);
|
|
18711
|
+
return /* @__PURE__ */ jsxs17(Box17, { flexShrink: 0, backgroundColor: on ? C.sel : void 0, children: [
|
|
18712
|
+
/* @__PURE__ */ jsx22(Text18, { color: on ? C.coral : C.faint, children: on ? "\u258C" : " " }),
|
|
18713
|
+
/* @__PURE__ */ jsx22(Box17, { width: 14, flexShrink: 0, children: /* @__PURE__ */ jsx22(Text18, { wrap: "truncate", color: C.fg, bold: true, children: r.role }) }),
|
|
18714
|
+
/* @__PURE__ */ jsx22(Box17, { width: 16, flexShrink: 0, children: /* @__PURE__ */ jsx22(Text18, { wrap: "truncate", children: chosen(on, runtime) }) }),
|
|
18715
|
+
/* @__PURE__ */ jsx22(Box17, { width: 7, flexShrink: 0, children: /* @__PURE__ */ jsxs17(Text18, { children: [
|
|
18716
|
+
/* @__PURE__ */ jsx22(Text18, { color: C.dim, children: "\u2212 " }),
|
|
18717
|
+
/* @__PURE__ */ jsx22(Text18, { color: n === 1 ? C.fg : C.green, bold: true, children: n }),
|
|
18718
|
+
/* @__PURE__ */ jsx22(Text18, { color: C.dim, children: " +" })
|
|
18719
|
+
] }) }),
|
|
18720
|
+
/* @__PURE__ */ jsx22(Box17, { width: 13, flexShrink: 0, children: /* @__PURE__ */ jsx22(Text18, { wrap: "truncate", color: form.policies[r.role] === "yolo" ? C.red : form.policies[r.role] ? C.fg : C.faint, children: form.policies[r.role] ? l.policyOf[form.policies[r.role]] : l.asRig }) }),
|
|
18721
|
+
/* @__PURE__ */ jsx22(Box17, { flexGrow: 1, overflow: "hidden", children: modelAt === i ? /* @__PURE__ */ jsx22(TextInput, { value: modelDraft, onChange: setModelDraft, active: true, onSubmit: (v) => {
|
|
18722
|
+
setForm((x) => withModel(x, r, v));
|
|
18723
|
+
setModelAt(null);
|
|
18724
|
+
}, onEscape: () => setModelAt(null), placeholder: l.defaultModel }) : /* @__PURE__ */ jsx22(Text18, { wrap: "truncate", color: model ? C.fg : C.faint, children: model ?? l.defaultModel }) })
|
|
18725
|
+
] }, r.role);
|
|
18726
|
+
})
|
|
18727
|
+
] }),
|
|
18728
|
+
/* @__PURE__ */ jsxs17(TitledBox, { title: l.permissions, flexShrink: 0, children: [
|
|
18729
|
+
row2("policy", "", /* @__PURE__ */ jsxs17(Text18, { wrap: "truncate", children: [
|
|
18730
|
+
chosen(field === "policy" || form.policy !== null, form.policy === null ? l.specPolicy(spec?.policy ?? l.noSpecPolicy) : l.policyOf[form.policy]),
|
|
18731
|
+
/* @__PURE__ */ jsx22(Text18, { color: C.faint, children: ` ${[null, ...RIG_POLICIES].indexOf(form.policy) + 1}/${RIG_POLICIES.length + 1}` })
|
|
18732
|
+
] }), 1),
|
|
18733
|
+
/* @__PURE__ */ jsx22(Box17, { flexShrink: 0, paddingLeft: 3, children: /* @__PURE__ */ jsx22(Text18, { wrap: "wrap", color: (form.policy ?? spec?.policy?.replace(/^builtin:/, "")) === "yolo" ? C.red : C.faint, children: l.policyHint[form.policy ?? spec?.policy?.replace(/^builtin:/, "") ?? "none"] ?? l.policyHint.none }) }),
|
|
18734
|
+
yolo ? row2("nonInterruptive", "", /* @__PURE__ */ jsxs17(Text18, { wrap: "truncate", children: [
|
|
18735
|
+
/* @__PURE__ */ jsx22(Text18, { color: form.nonInterruptive ? C.red : C.faint, children: form.nonInterruptive ? g.boxOn : g.boxOff }),
|
|
18736
|
+
/* @__PURE__ */ jsxs17(Text18, { color: C.dim, children: [
|
|
18575
18737
|
" ",
|
|
18576
|
-
|
|
18577
|
-
] })
|
|
18578
|
-
|
|
18579
|
-
|
|
18580
|
-
|
|
18738
|
+
l.nonInterruptive
|
|
18739
|
+
] })
|
|
18740
|
+
] }), 1) : null
|
|
18741
|
+
] }),
|
|
18742
|
+
/* @__PURE__ */ jsxs17(TitledBox, { title: l.delegation, flexShrink: 0, height: 4, children: [
|
|
18743
|
+
row2("delegation", "", /* @__PURE__ */ jsx22(Text18, { wrap: "truncate", children: scaled(form, roles) ? /* @__PURE__ */ jsxs17(Fragment6, { children: [
|
|
18744
|
+
chosen(form.delegation === "pairs", l.pairs),
|
|
18745
|
+
/* @__PURE__ */ jsxs17(Text18, { color: C.faint, children: [
|
|
18746
|
+
" ",
|
|
18747
|
+
l.pairsHint,
|
|
18748
|
+
" "
|
|
18749
|
+
] }),
|
|
18750
|
+
chosen(form.delegation === "all", l.all)
|
|
18751
|
+
] }) : /* @__PURE__ */ jsx22(Text18, { color: C.faint, children: l.notScaled }) }), 1),
|
|
18752
|
+
row2("save", "", /* @__PURE__ */ jsxs17(Text18, { wrap: "truncate", children: [
|
|
18753
|
+
/* @__PURE__ */ jsx22(Text18, { color: form.save ? C.green : C.faint, children: form.save ? g.boxOn : g.boxOff }),
|
|
18754
|
+
/* @__PURE__ */ jsxs17(Text18, { color: C.dim, children: [
|
|
18755
|
+
" ",
|
|
18756
|
+
l.save,
|
|
18757
|
+
form.save ? ` : ${nameOf(form)}` : ""
|
|
18758
|
+
] })
|
|
18759
|
+
] }), 1)
|
|
18760
|
+
] })
|
|
18581
18761
|
] }),
|
|
18582
|
-
/* @__PURE__ */
|
|
18583
|
-
] }) : template ? /* @__PURE__ */ jsxs15(TitledBox, { title: `${g.team} ${template.name} \xB7 ${t.catalog.seats(template.seats.length)} \xB7 ${template.source === "repo" ? t.catalog.repo : t.catalog.home}`, color: C.coral, titleColor: C.coral, flexGrow: 1, children: [
|
|
18584
|
-
template.seats.map((s) => {
|
|
18585
|
-
const r = roleById(s.role);
|
|
18586
|
-
const tool = s.tool ?? r?.tool;
|
|
18587
|
-
return /* @__PURE__ */ jsxs15(Text17, { wrap: "truncate", children: [
|
|
18588
|
-
/* @__PURE__ */ jsxs15(Text17, { color: C.violet, children: [
|
|
18589
|
-
"@",
|
|
18590
|
-
fit(s.role, 8)
|
|
18591
|
-
] }),
|
|
18592
|
-
" ",
|
|
18593
|
-
/* @__PURE__ */ jsx21(Text17, { color: C.fg, children: fit(r?.label ?? "?", 12) }),
|
|
18594
|
-
" ",
|
|
18595
|
-
/* @__PURE__ */ jsx21(Text17, { color: s.tool ? C.blue : C.dim, children: tool ? TOOL_NAME[tool] : t.catalog.toolDefault }),
|
|
18596
|
-
s.model ? /* @__PURE__ */ jsxs15(Text17, { color: C.blue, children: [
|
|
18597
|
-
" \xB7 ",
|
|
18598
|
-
s.model
|
|
18599
|
-
] }) : r?.model ? /* @__PURE__ */ jsxs15(Text17, { color: C.dim, children: [
|
|
18600
|
-
" \xB7 ",
|
|
18601
|
-
r.model
|
|
18602
|
-
] }) : null,
|
|
18603
|
-
" ",
|
|
18604
|
-
/* @__PURE__ */ jsx21(Text17, { color: autonomyColor2(autonomy(r)), children: t.catalog.autonomyShort[autonomy(r)] })
|
|
18605
|
-
] }, s.role);
|
|
18606
|
-
}),
|
|
18607
|
-
/* @__PURE__ */ jsx21(Text17, { children: " " }),
|
|
18608
|
-
(() => {
|
|
18609
|
-
const auto = template.seats.filter((s) => roleById(s.role)?.autonomy === "auto").map((s) => `@${s.role}`);
|
|
18610
|
-
return auto.length ? /* @__PURE__ */ jsxs15(Text17, { color: C.yellow, wrap: "truncate", children: [
|
|
18611
|
-
"\u26A0 ",
|
|
18612
|
-
t.ask.autoWarning(auto.join(", "))
|
|
18613
|
-
] }) : null;
|
|
18614
|
-
})(),
|
|
18615
|
-
field(t.catalog.file, /* @__PURE__ */ jsxs15(Text17, { color: C.dim, children: [
|
|
18616
|
-
remote ? `${t.catalog.onMachine(machineLabel2)} ` : "",
|
|
18617
|
-
template.path
|
|
18618
|
-
] })),
|
|
18619
|
-
field(t.catalog.teams, (() => {
|
|
18620
|
-
const xs = teams.filter((x) => x.template === template.id && x.state !== "dissolved");
|
|
18621
|
-
return xs.length ? /* @__PURE__ */ jsx21(Text17, { children: xs.map((x) => /* @__PURE__ */ jsxs15(Text17, { children: [
|
|
18622
|
-
/* @__PURE__ */ jsxs15(Text17, { color: C.violet, children: [
|
|
18623
|
-
g.team,
|
|
18624
|
-
" ",
|
|
18625
|
-
x.name
|
|
18626
|
-
] }),
|
|
18627
|
-
" ",
|
|
18628
|
-
/* @__PURE__ */ jsx21(Text17, { color: C.dim, children: x.state === "active" ? t.catalog.active : t.catalog.resting }),
|
|
18629
|
-
" "
|
|
18630
|
-
] }, x.id)) }) : /* @__PURE__ */ jsx21(Text17, { color: C.faint, children: t.catalog.noTeam });
|
|
18631
|
-
})())
|
|
18632
|
-
] }) : /* @__PURE__ */ jsx21(TitledBox, { title: t.tabs.teams, flexGrow: 1, children: /* @__PURE__ */ jsx21(Text17, { color: C.faint, children: defs === null ? silent ? "" : t.catalog.loading : defs.error ? "" : view === "roles" ? t.catalog.noRole : t.catalog.noTemplateHere }) });
|
|
18633
|
-
const keys = [
|
|
18634
|
-
["j k", t.keys.navigate],
|
|
18635
|
-
["\u2190 \u2192", t.keys.rolesTemplates],
|
|
18636
|
-
["c", t.keys.folder],
|
|
18637
|
-
...reread ? [["r", t.keys.reread]] : [],
|
|
18638
|
-
...launchable ? [["\u21B5", view === "roles" ? t.keys.launchRole : t.keys.launchTeam]] : [],
|
|
18639
|
-
...current2 && !remote ? [["o", t.keys.openFile]] : [],
|
|
18640
|
-
...issues.length ? [["!", t.keys.ignored]] : [],
|
|
18641
|
-
["esc", t.keys.back]
|
|
18642
|
-
];
|
|
18643
|
-
return /* @__PURE__ */ jsx21(Frame, { crumb: t.tabs.teams, keys, children: /* @__PURE__ */ jsxs15(Box16, { flexGrow: 1, flexDirection: wide ? "row" : "column", children: [
|
|
18644
|
-
/* @__PURE__ */ jsx21(Box16, { flexDirection: "column", width: wide ? left2 : void 0, flexShrink: 0, flexGrow: wide ? 0 : 1, children: listBox }),
|
|
18645
|
-
/* @__PURE__ */ jsx21(Box16, { flexDirection: "column", flexGrow: 1, children: detail })
|
|
18762
|
+
/* @__PURE__ */ jsx22(Preview, { busy, result, seats })
|
|
18646
18763
|
] }) });
|
|
18647
18764
|
}
|
|
18765
|
+
function Preview({ busy, result, seats }) {
|
|
18766
|
+
const { t } = useTui();
|
|
18767
|
+
const l = t.rigLaunch;
|
|
18768
|
+
const check = result?.check;
|
|
18769
|
+
return /* @__PURE__ */ jsx22(TitledBox, { title: l.preview, flexGrow: 1, color: C.coral, titleColor: C.coral, children: busy ? /* @__PURE__ */ jsx22(Text18, { color: C.blue, children: busy === "check" ? l.checking : l.launching }) : !result ? /* @__PURE__ */ jsx22(Text18, { wrap: "wrap", color: C.faint, children: l.noCheck }) : /* @__PURE__ */ jsxs17(Fragment6, { children: [
|
|
18770
|
+
check ? check.status === "planned" && !check.errors.length ? /* @__PURE__ */ jsx22(Text18, { color: C.green, bold: true, children: l.passes(result.seats ?? seats) }) : /* @__PURE__ */ jsx22(Text18, { color: check.errors.length ? C.red : C.yellow, bold: true, children: l.planStatus(check.status) }) : null,
|
|
18771
|
+
!result.ok ? /* @__PURE__ */ jsx22(Text18, { wrap: "wrap", color: C.red, children: l.why[result.error ?? ""] ?? result.error }) : null,
|
|
18772
|
+
check?.errors.map((e, i) => /* @__PURE__ */ jsx22(Text18, { wrap: "wrap", color: C.red, children: e }, `e${i}`)),
|
|
18773
|
+
warningLines(check?.warnings ?? []).map((w, i) => /* @__PURE__ */ jsx22(Text18, { wrap: "wrap", color: C.yellow, children: l.warning(w.text, w.seats.join(", ")) }, `w${i}`)),
|
|
18774
|
+
result.commands.map((c) => /* @__PURE__ */ jsx22(Text18, { wrap: "truncate", color: C.faint, children: c }, c)),
|
|
18775
|
+
result.yaml ? /* @__PURE__ */ jsx22(Box17, { marginTop: 1, flexDirection: "column", children: result.yaml.split("\n").map((line, i) => /* @__PURE__ */ jsx22(YamlLine, { line }, i)) }) : null
|
|
18776
|
+
] }) });
|
|
18777
|
+
}
|
|
18778
|
+
function YamlLine({ line }) {
|
|
18779
|
+
const m = /^(\s*-?\s*)([A-Za-z0-9_.-]+:)(.*)$/.exec(line);
|
|
18780
|
+
if (line.trim().startsWith("#")) return /* @__PURE__ */ jsx22(Text18, { wrap: "truncate", color: C.faint, children: line || " " });
|
|
18781
|
+
if (!m) return /* @__PURE__ */ jsx22(Text18, { wrap: "truncate", color: C.dim, children: line || " " });
|
|
18782
|
+
return /* @__PURE__ */ jsxs17(Text18, { wrap: "truncate", children: [
|
|
18783
|
+
/* @__PURE__ */ jsx22(Text18, { color: C.dim, children: m[1] }),
|
|
18784
|
+
/* @__PURE__ */ jsx22(Text18, { color: C.blue, children: m[2] }),
|
|
18785
|
+
/* @__PURE__ */ jsx22(Text18, { color: C.green, children: m[3] })
|
|
18786
|
+
] });
|
|
18787
|
+
}
|
|
18648
18788
|
|
|
18649
18789
|
// src/tui/App.tsx
|
|
18650
|
-
import { jsx as
|
|
18790
|
+
import { jsx as jsx23 } from "react/jsx-runtime";
|
|
18651
18791
|
var TOAST_MS = 5e3;
|
|
18652
18792
|
var QUIT_MS = 2e3;
|
|
18653
18793
|
function App(props) {
|
|
18654
|
-
const [lang, setLangState] =
|
|
18655
|
-
const [theme, setThemeState] =
|
|
18794
|
+
const [lang, setLangState] = useState16(props.lang);
|
|
18795
|
+
const [theme, setThemeState] = useState16(props.theme ?? "auto");
|
|
18656
18796
|
const tone2 = toneFor(theme, props.background ?? tone());
|
|
18657
18797
|
if (tone2 !== tone()) setTone(tone2);
|
|
18658
|
-
return /* @__PURE__ */
|
|
18798
|
+
return /* @__PURE__ */ jsx23(I18nProvider, { lang, children: /* @__PURE__ */ jsx23(Shell, { ...props, lang, setLang: setLangState, theme, setThemeState, tone: tone2 }) });
|
|
18659
18799
|
}
|
|
18660
18800
|
function Shell({ client, lang, setLang: setLangState, saveLang, theme, setThemeState, tone: tone2, background, saveTheme, notify, glyphs, env, run: run2, readImage, openFile }) {
|
|
18661
18801
|
const { exit: exit3, suspendTerminal } = useApp();
|
|
18662
18802
|
const { stdout } = useStdout();
|
|
18663
|
-
const write =
|
|
18803
|
+
const write = useCallback2((seq) => {
|
|
18664
18804
|
if (seq) stdout.write(seq);
|
|
18665
18805
|
}, [stdout]);
|
|
18666
18806
|
const d = useDaemon();
|
|
18667
18807
|
const machines = useMachines(client);
|
|
18668
18808
|
const projects = useProjects(client);
|
|
18669
|
-
const teams = useTeams(client);
|
|
18670
18809
|
const tasks = useTasks(client);
|
|
18671
18810
|
const fleet = client.fleet;
|
|
18672
18811
|
const t = MESSAGES[lang];
|
|
18673
|
-
const [screen, setScreen] =
|
|
18674
|
-
const [back2, setBack] =
|
|
18675
|
-
const [selectedId, setSelectedId] =
|
|
18676
|
-
const [lastToast, setToast] =
|
|
18677
|
-
const [editing, setEditingState] =
|
|
18678
|
-
const keys =
|
|
18679
|
-
const kept =
|
|
18680
|
-
const armed =
|
|
18681
|
-
|
|
18682
|
-
useEffect13(() => {
|
|
18812
|
+
const [screen, setScreen] = useState16("overview");
|
|
18813
|
+
const [back2, setBack] = useState16("overview");
|
|
18814
|
+
const [selectedId, setSelectedId] = useState16(null);
|
|
18815
|
+
const [lastToast, setToast] = useState16(null);
|
|
18816
|
+
const [editing, setEditingState] = useState16(false);
|
|
18817
|
+
const keys = useRef14(null);
|
|
18818
|
+
const kept = useRef14({ drafts: /* @__PURE__ */ new Map(), sent: /* @__PURE__ */ new Map(), asked: [] }).current;
|
|
18819
|
+
const armed = useRef14(0);
|
|
18820
|
+
useEffect15(() => {
|
|
18683
18821
|
if (!lastToast) return;
|
|
18684
18822
|
const timer2 = setTimeout(() => setToast(null), lastToast.ms ?? TOAST_MS);
|
|
18685
18823
|
return () => clearTimeout(timer2);
|
|
18686
18824
|
}, [lastToast]);
|
|
18687
|
-
const toast =
|
|
18688
|
-
const setEditing =
|
|
18689
|
-
const view =
|
|
18690
|
-
const order2 =
|
|
18691
|
-
|
|
18825
|
+
const toast = useCallback2((x) => setToast(x), []);
|
|
18826
|
+
const setEditing = useCallback2((on) => setEditingState(on), []);
|
|
18827
|
+
const view = useMemo7(() => overview(d.sessions, projects), [d.sessions, projects]);
|
|
18828
|
+
const order2 = useRef14([]);
|
|
18829
|
+
useEffect15(() => {
|
|
18692
18830
|
setSelectedId((cur) => cur === null && view.yours[0] ? view.yours[0].id : keepSelection(view.order, cur, order2.current));
|
|
18693
18831
|
order2.current = view.order;
|
|
18694
18832
|
}, [view]);
|
|
18695
18833
|
const selected = (selectedId ? d.byId.get(selectedId) : void 0) ?? null;
|
|
18696
|
-
const seen =
|
|
18697
|
-
const titled =
|
|
18698
|
-
|
|
18834
|
+
const seen = useRef14(null);
|
|
18835
|
+
const titled = useRef14("");
|
|
18836
|
+
useEffect15(() => {
|
|
18699
18837
|
if (seen.current) for (const text5 of asked(seen.current, d.sessions, t.notify)) write(notification(text5, notify, env));
|
|
18700
18838
|
seen.current = d.byId;
|
|
18701
|
-
const
|
|
18702
|
-
if (
|
|
18703
|
-
titled.current =
|
|
18704
|
-
write(
|
|
18839
|
+
const next3 = title(t.notify.title(listed(d.sessions).filter(isPending).length + openDecisions(tasks).length));
|
|
18840
|
+
if (next3 !== titled.current) {
|
|
18841
|
+
titled.current = next3;
|
|
18842
|
+
write(next3);
|
|
18705
18843
|
}
|
|
18706
18844
|
}, [d.byId, tasks]);
|
|
18707
18845
|
const actions = useActions({ client, sessions: d.sessions, errors: d.errors, t, toast });
|
|
18708
|
-
const go =
|
|
18846
|
+
const go = useCallback2((next3) => {
|
|
18709
18847
|
setScreen((cur) => {
|
|
18710
|
-
if (
|
|
18711
|
-
return
|
|
18848
|
+
if (next3 === "help" || next3 === "settings") setBack(cur === "help" || cur === "settings" ? "overview" : cur);
|
|
18849
|
+
return next3;
|
|
18712
18850
|
});
|
|
18713
18851
|
}, []);
|
|
18714
|
-
const setLang =
|
|
18715
|
-
setLangState(
|
|
18852
|
+
const setLang = useCallback2((next3) => {
|
|
18853
|
+
setLangState(next3);
|
|
18716
18854
|
try {
|
|
18717
|
-
saveLang(
|
|
18718
|
-
toast({ text: MESSAGES[
|
|
18855
|
+
saveLang(next3);
|
|
18856
|
+
toast({ text: MESSAGES[next3].settings.saved, tone: "ok" });
|
|
18719
18857
|
} catch (e) {
|
|
18720
|
-
toast({ text: MESSAGES[
|
|
18858
|
+
toast({ text: MESSAGES[next3].settings.saveFailed(e.message), tone: "error" });
|
|
18721
18859
|
}
|
|
18722
18860
|
}, [saveLang, setLangState, toast]);
|
|
18723
|
-
const setTheme =
|
|
18724
|
-
setThemeState(
|
|
18861
|
+
const setTheme = useCallback2((next3) => {
|
|
18862
|
+
setThemeState(next3);
|
|
18725
18863
|
try {
|
|
18726
|
-
saveTheme?.(
|
|
18864
|
+
saveTheme?.(next3);
|
|
18727
18865
|
toast({ text: t.settings.saved, tone: "ok" });
|
|
18728
18866
|
} catch (e) {
|
|
18729
18867
|
toast({ text: t.settings.saveFailed(e.message), tone: "error" });
|
|
18730
18868
|
}
|
|
18731
18869
|
}, [saveTheme, setThemeState, toast, t]);
|
|
18732
|
-
const attach =
|
|
18870
|
+
const attach = useCallback2((s) => {
|
|
18733
18871
|
const cmd = attachCommand(fleet, s);
|
|
18734
18872
|
if ("why" in cmd) {
|
|
18735
18873
|
toast({ text: cmd.why === "offline" ? t.toast.offline(s.name) : cmd.why === "omp" ? t.toast.noTerminalOmp(s.name) : t.toast.noTerminal(s.name), tone: "info" });
|
|
@@ -18741,7 +18879,7 @@ function Shell({ client, lang, setLang: setLangState, saveLang, theme, setThemeS
|
|
|
18741
18879
|
if (code3 !== 0) toast({ text: t.toast.attachFailed(code3), tone: "error" });
|
|
18742
18880
|
});
|
|
18743
18881
|
}, [fleet, suspendTerminal, run2, t, toast, write]);
|
|
18744
|
-
const runInTerminal =
|
|
18882
|
+
const runInTerminal = useCallback2((argv) => {
|
|
18745
18883
|
void suspendTerminal(async () => {
|
|
18746
18884
|
const code3 = await (run2 ?? runAttached)(argv);
|
|
18747
18885
|
if (code3 !== 0) toast({ text: t.toast.exited(argv[0], code3), tone: "error" });
|
|
@@ -18776,13 +18914,12 @@ function Shell({ client, lang, setLang: setLangState, saveLang, theme, setThemeS
|
|
|
18776
18914
|
attach,
|
|
18777
18915
|
runInTerminal,
|
|
18778
18916
|
env,
|
|
18779
|
-
catalog,
|
|
18780
18917
|
keys,
|
|
18781
18918
|
kept,
|
|
18782
18919
|
readImage: readImage ?? (() => readClipboardImage(env)),
|
|
18783
18920
|
openFile: openFile ?? ((file) => openImage(file, env))
|
|
18784
18921
|
};
|
|
18785
|
-
|
|
18922
|
+
useInput8((input, key) => {
|
|
18786
18923
|
if (key.ctrl && input === "c") {
|
|
18787
18924
|
if (keys.current?.(input, key)) return;
|
|
18788
18925
|
const drafts = [...kept.drafts].some(([id, x]) => x.trim() && (id === "ask" || d.byId.has(id)));
|
|
@@ -18829,8 +18966,8 @@ function Shell({ client, lang, setLang: setLangState, saveLang, theme, setThemeS
|
|
|
18829
18966
|
return;
|
|
18830
18967
|
}
|
|
18831
18968
|
});
|
|
18832
|
-
const
|
|
18833
|
-
return /* @__PURE__ */
|
|
18969
|
+
const Body2 = { overview: Overview, session: SessionScreen, ask: Ask, launch: Launch, settings: Settings, openrig: OpenRigScreen, rigLaunch: RigLaunchScreen, help: Help }[screen];
|
|
18970
|
+
return /* @__PURE__ */ jsx23(TuiContext.Provider, { value: tui, children: /* @__PURE__ */ jsx23(Body2, {}) });
|
|
18834
18971
|
}
|
|
18835
18972
|
|
|
18836
18973
|
// src/tui/fleet.ts
|
|
@@ -18885,9 +19022,6 @@ var UNICODE = {
|
|
|
18885
19022
|
next: "\u25B8",
|
|
18886
19023
|
ellipsis: "\u2026",
|
|
18887
19024
|
bar: "\u2502",
|
|
18888
|
-
/** A team's table and the common table (roles spec §3.9). */
|
|
18889
|
-
team: "\u25A3",
|
|
18890
|
-
common: "\u25AD",
|
|
18891
19025
|
/** Markdown: a list's marks, a quote's bar, a rule, a code block's corners, a link's arrow, the end of a streamed answer. */
|
|
18892
19026
|
bullet: "\u2022",
|
|
18893
19027
|
subBullet: "\u25E6",
|
|
@@ -18905,7 +19039,7 @@ var UNICODE = {
|
|
|
18905
19039
|
stale: "!",
|
|
18906
19040
|
/** Links are clickable (OSC 8); without, their address follows them. */
|
|
18907
19041
|
links: true,
|
|
18908
|
-
/** A task handed between
|
|
19042
|
+
/** A task handed between sessions in « Échanges » (#92). */
|
|
18909
19043
|
task: "\u25A4"
|
|
18910
19044
|
};
|
|
18911
19045
|
var ASCII = {
|
|
@@ -18939,8 +19073,6 @@ var ASCII = {
|
|
|
18939
19073
|
next: ">",
|
|
18940
19074
|
ellipsis: "...",
|
|
18941
19075
|
bar: "|",
|
|
18942
|
-
team: "[T]",
|
|
18943
|
-
common: "[ ]",
|
|
18944
19076
|
bullet: "-",
|
|
18945
19077
|
subBullet: "o",
|
|
18946
19078
|
quote: "|",
|
|
@@ -19138,7 +19270,7 @@ async function backgroundAtStart(theme, env, io) {
|
|
|
19138
19270
|
}
|
|
19139
19271
|
|
|
19140
19272
|
// src/tui/index.tsx
|
|
19141
|
-
import { jsx as
|
|
19273
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
19142
19274
|
var TUI_USAGE = "ledge tui [--notify bell|osc9|off] [--here]";
|
|
19143
19275
|
function tuiArgs(args) {
|
|
19144
19276
|
let notify = "bell";
|
|
@@ -19177,15 +19309,15 @@ async function runTui(args) {
|
|
|
19177
19309
|
const detach = attachClient(client);
|
|
19178
19310
|
client.connect();
|
|
19179
19311
|
const app = render(
|
|
19180
|
-
/* @__PURE__ */
|
|
19312
|
+
/* @__PURE__ */ jsx24(
|
|
19181
19313
|
App,
|
|
19182
19314
|
{
|
|
19183
19315
|
client,
|
|
19184
19316
|
lang,
|
|
19185
|
-
saveLang: (
|
|
19317
|
+
saveLang: (next3) => saveSettings({ ...loadSettings(), lang: next3 }),
|
|
19186
19318
|
theme,
|
|
19187
19319
|
background,
|
|
19188
|
-
saveTheme: (
|
|
19320
|
+
saveTheme: (next3) => saveSettings({ ...loadSettings(), theme: next3 }),
|
|
19189
19321
|
notify: parsed.notify,
|
|
19190
19322
|
glyphs: glyphsFor(process.env),
|
|
19191
19323
|
env: process.env
|