bazilion 0.14.2 → 0.16.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.js +1752 -825
- package/dist/cli.js.map +1 -1
- package/dist/daemon.js +16624 -9803
- package/dist/daemon.js.map +1 -1
- package/dist/migrations/0001_init.sql +218 -3
- package/dist/web/client/assets/ChatPane-CQZzxOir.js +76 -0
- package/dist/web/client/assets/{ConfirmDialog-_bmG-wVG.js → ConfirmDialog-MicTTwdy.js} +1 -1
- package/dist/web/client/assets/{FieldRow-Do1cBkRc.js → FieldRow-DJ2Gx4Du.js} +1 -1
- package/dist/web/client/assets/{ProductionTeamPolicyEditor-XP-QJul4.js → ProductionTeamPolicyEditor-DqUnN_ce.js} +1 -1
- package/dist/web/client/assets/{ProfileCommunicationEditor-CwdFPdpk.js → ProfileCommunicationEditor-DArXub0b.js} +1 -1
- package/dist/web/client/assets/ResultCard-Cps_lXVN.js +1 -0
- package/dist/web/client/assets/ResultSourceConversation-CtzJ8QA-.js +1 -0
- package/dist/web/client/assets/TeamTabs-DbIk5vvT.js +1 -0
- package/dist/web/client/assets/{TemplatesTabs-D4WHvs6b.js → TemplatesTabs-CatJIjGi.js} +1 -1
- package/dist/web/client/assets/{UnsavedChangesGuard-B1aLqiK5.js → UnsavedChangesGuard-BCsLw-mU.js} +1 -1
- package/dist/web/client/assets/_id-B5Ov7cdO.js +1 -0
- package/dist/web/client/assets/{_id-BH3v_vI_.js → _id-BEDmIXVf.js} +1 -1
- package/dist/web/client/assets/_id-BFM_tn_s.js +1 -0
- package/dist/web/client/assets/_id-CrnEVcw8.js +1 -0
- package/dist/web/client/assets/{_id-3w4PFfma.js → _id-DxopIW-y.js} +1 -1
- package/dist/web/client/assets/{activity-A_HrG1Tv.js → activity-CrG8Bg60.js} +1 -1
- package/dist/web/client/assets/{agents-C8OVKq3N.js → agents-CMPOFcs-.js} +1 -1
- package/dist/web/client/assets/{agents-BeeFCt2c.js → agents-O4soKZND.js} +1 -1
- package/dist/web/client/assets/{approvals-BIdZ9BSn.js → approvals-CwDu_lrA.js} +1 -1
- package/dist/web/client/assets/{attention-B9bUrxiU.js → attention-BY8MMuM_.js} +1 -1
- package/dist/web/client/assets/chevron-right-Cf6vKeLq.js +1 -0
- package/dist/web/client/assets/{config-By86S7k-.js → config-Cn4iBJFz.js} +1 -1
- package/dist/web/client/assets/{inbox-DlXQCJLe.js → inbox-CWXql0K3.js} +1 -1
- package/dist/web/client/assets/{index-CLdmsmiN.js → index-Bq2zrG2_.js} +2 -2
- package/dist/web/client/assets/{learning-BqZIw2nA.js → learning-DAm4dyyc.js} +1 -1
- package/dist/web/client/assets/login-BsABI8Ux.js +1 -0
- package/dist/web/client/assets/{mcp-DKSY2yVa.js → mcp-loLB0wuh.js} +1 -1
- package/dist/web/client/assets/{members-9GuOiq6J.js → members-BJ0ikkTl.js} +1 -1
- package/dist/web/client/assets/{memory-DiGMI6FC.js → memory-Drn9Gv53.js} +1 -1
- package/dist/web/client/assets/{policy-TBGQffw5.js → policy-pQadZyk0.js} +1 -1
- package/dist/web/client/assets/results-9exU6f7m.js +1 -0
- package/dist/web/client/assets/routes-jw1PuqiR.js +1 -0
- package/dist/web/client/assets/{services-1Z398CES.js → services-BLso1BhA.js} +1 -1
- package/dist/web/client/assets/{skills-BP2gciFt.js → skills-BodqX3OI.js} +1 -1
- package/dist/web/client/assets/styles-d1yjBpud.css +2 -0
- package/dist/web/client/assets/{teams-DBIivGT7.js → teams-ByQedXZi.js} +1 -1
- package/dist/web/client/assets/{teams-tNoMDJ_M.js → teams-SYsF1bOR.js} +1 -1
- package/dist/web/client/assets/telegram-DC9PLFbB.js +1 -0
- package/dist/web/client/assets/{tokens-eDWCGQQ2.js → tokens-DGy8Ijpo.js} +1 -1
- package/dist/web/client/assets/{triggers-DZME3IcK.js → triggers-BXpVmHDG.js} +1 -1
- package/dist/web/client/assets/{welcome-B49sh_uf.js → welcome-BKsnsCxJ.js} +1 -1
- package/dist/web/client/assets/wire-constants-CBD-lTaa.js +1 -0
- package/dist/web/client/assets/{x-CHc7_-TH.js → x-BK4xNCzS.js} +1 -1
- package/dist/web/server/assets/ChatPane-CS5oI7ef.js +2666 -0
- package/dist/web/server/assets/ResultCard-B3zD9N0t.js +143 -0
- package/dist/web/server/assets/ResultSourceConversation-BpVWBRYq.js +64 -0
- package/dist/web/server/assets/{TeamTabs-Co3n2exj.js → TeamTabs-TCKjCvMA.js} +4 -0
- package/dist/web/server/assets/{_id-sNu5aXZt.js → _id-5pgKoid8.js} +2 -1
- package/dist/web/server/assets/_id-BDEpe6k0.js +6 -0
- package/dist/web/server/assets/{_id-DxCnEFpm.js → _id-BG2nkGxa.js} +3 -4
- package/dist/web/server/assets/{_id-BqWTB8Wl.js → _id-B_-CDHOi2.js} +1 -1
- package/dist/web/server/assets/{_id-BeKhPKw3.js → _id-BnqodC1c2.js} +7 -3
- package/dist/web/server/assets/{_id-DvlDkk04.js → _id-CeyHEsCZ.js} +1 -1
- package/dist/web/server/assets/{_id-BYKpT2Tu.js → _id-DFHB9JFQ.js} +1 -1
- package/dist/web/server/assets/{_id-DYU6uIBx.js → _id-DOnInzLb.js} +1 -1
- package/dist/web/server/assets/{_id-HMy7jM3P.js → _id-DrB9uR1b.js} +1 -1
- package/dist/web/server/assets/{_id-BAA9KJBU.js → _id-DtIYuJJX.js} +1 -1
- package/dist/web/server/assets/_id-DwZXhLlL.js +779 -0
- package/dist/web/server/assets/_id-wyjrf0JG.js +17 -0
- package/dist/web/server/assets/{_tanstack-start-manifest_v-Duhf0z7H.js → _tanstack-start-manifest_v-D7gKv6m6.js} +97 -70
- package/dist/web/server/assets/{activity-9VP6QDTH.js → activity-0VUkStOu.js} +1 -1
- package/dist/web/server/assets/{activity-BWv1goK6.js → activity-5fWKPDxj.js} +2 -2
- package/dist/web/server/assets/{activity-LjpblbDL.js → activity-C88qrNqv.js} +1 -1
- package/dist/web/server/assets/{agents-DjyQk94u.js → agents-C86K6HvS.js} +1 -1
- package/dist/web/server/assets/{agents-BJAv919x.js → agents-CSXLaM2W.js} +1 -1
- package/dist/web/server/assets/{approvals-BYi84gwl.js → approvals-C3MysI6l.js} +1 -1
- package/dist/web/server/assets/{approvals-7JOoBchn.js → approvals-DTdrltyk.js} +1 -1
- package/dist/web/server/assets/{approvals-Bz123liE.js → approvals-DXoN-T57.js} +15 -1
- package/dist/web/server/assets/{attention-UhqPK_Ro.js → attention-DLeLCKah.js} +1 -1
- package/dist/web/server/assets/{auth-7BHTH-KS.js → auth-CDZp9aEk.js} +1 -1
- package/dist/web/server/assets/{config-BMiajTZP.js → config-BVTHvljR.js} +1 -1
- package/dist/web/server/assets/{daemon-client-CI5NHwNC.js → daemon-client-xWyYKAcx.js} +59 -0
- package/dist/web/server/assets/{inbox-Dv55rGYq.js → inbox-PQTrjtOw.js} +1 -1
- package/dist/web/server/assets/{learning-C2upa1CE.js → learning-K0cmDsZR.js} +1 -1
- package/dist/web/server/assets/{login-BNj3U6ok.js → login-B_-9L8TU.js} +7 -2
- package/dist/web/server/assets/{login-Be8eP4Jp.js → login-rDox7PRD.js} +5 -2
- package/dist/web/server/assets/{mcp-BvnvlVFd.js → mcp-Rtraochg.js} +1 -1
- package/dist/web/server/assets/{members-DiYtr-zm.js → members-CD3GiTfF.js} +1 -1
- package/dist/web/server/assets/{members-DHYTVgwb.js → members-cc5SeEaW.js} +2 -2
- package/dist/web/server/assets/{members-BP3UTqu1.js → members-grAKFWgv.js} +1 -1
- package/dist/web/server/assets/{memory-CkXUgf5s.js → memory-C5i_GxlY.js} +2 -2
- package/dist/web/server/assets/{memory-DTFEmfF3.js → memory-CVqnyUaM.js} +1 -1
- package/dist/web/server/assets/{memory-BqV-Afy1.js → memory-egFpBD1g.js} +1 -1
- package/dist/web/server/assets/{policy-Bvvav8fh.js → policy-Dgjb0_gK.js} +2 -2
- package/dist/web/server/assets/{policy-BddK4xom.js → policy-bLKwvnja.js} +1 -1
- package/dist/web/server/assets/{policy-18fdTFO4.js → policy-ooSBgiDS.js} +1 -1
- package/dist/web/server/assets/results-CfNsFncJ.js +173 -0
- package/dist/web/server/assets/results-DXdYtHaq.js +12 -0
- package/dist/web/server/assets/results-N-kP4iFT.js +12 -0
- package/dist/web/server/assets/{router-CY_pCgP1.js → router-B6g_s7W3.js} +60 -43
- package/dist/web/server/assets/{routes-COtkyZG1.js → routes-BqSaZvlu.js} +3 -3
- package/dist/web/server/assets/{routes-BgHisAxH.js → routes-Dsh8F_7i.js} +2 -2
- package/dist/web/server/assets/{routes-DAU2g7Uz.js → routes-pcRy_Sf8.js} +1 -1
- package/dist/web/server/assets/{services-DozuJtzX.js → services-DlZA8fRL.js} +1 -1
- package/dist/web/server/assets/{skills-DfGSJTCB.js → skills-i2duvgW-.js} +1 -1
- package/dist/web/server/assets/{teams-be05ci17.js → teams-6RYIj1Xm.js} +1 -1
- package/dist/web/server/assets/{teams-DPnAX4wD.js → teams-B1AI3NfN.js} +1 -1
- package/dist/web/server/assets/{telegram-1AWL6lFw.js → telegram-C4q0YTVn.js} +1 -1
- package/dist/web/server/assets/{telegram-Dj4Wwhd6.js → telegram-CoNeOgqZ.js} +465 -1
- package/dist/web/server/assets/{telegram-DbOFpTFm.js → telegram-Zd1rIZxg.js} +1 -1
- package/dist/web/server/assets/{tokens-DjM8GsgS.js → tokens-RFquA2Bx.js} +1 -1
- package/dist/web/server/assets/{triggers-Nezfw-Bd.js → triggers-DVD-iE-N.js} +1 -1
- package/dist/web/server/server.js +31 -27
- package/dist/worker.js +1765 -710
- package/dist/worker.js.map +1 -1
- package/package.json +3 -3
- package/dist/web/client/assets/TeamTabs-DIRiKcqx.js +0 -1
- package/dist/web/client/assets/_id-Cx7o4Zmf.js +0 -1
- package/dist/web/client/assets/_id-DIiVVxBl.js +0 -1
- package/dist/web/client/assets/chevron-right-VWrk_dTX.js +0 -1
- package/dist/web/client/assets/login-CCMPXiny.js +0 -1
- package/dist/web/client/assets/routes-g3yUOhCb.js +0 -1
- package/dist/web/client/assets/styles-B5vcgXln.css +0 -2
- package/dist/web/client/assets/telegram-CJG_DFdI.js +0 -1
- package/dist/web/client/assets/wire-constants-zZ7Wjb9C.js +0 -74
- package/dist/web/server/assets/ChatPane-CgSe7tsy.js +0 -1429
- package/dist/web/server/assets/_id-ndxFHx0t.js +0 -381
|
@@ -0,0 +1,779 @@
|
|
|
1
|
+
import { t as Route } from "./_id-DtIYuJJX.js";
|
|
2
|
+
import { a as StatusBadge, i as SectionCard, r as PageShell } from "./Page-Bz-ydB8j.js";
|
|
3
|
+
import { t as Button } from "./Button-Dsnw22OF.js";
|
|
4
|
+
import { t as TeamTabs } from "./TeamTabs-TCKjCvMA.js";
|
|
5
|
+
import { t as UnsavedChangesGuard } from "./UnsavedChangesGuard-CiStXyBI.js";
|
|
6
|
+
import { useEffect, useRef, useState } from "react";
|
|
7
|
+
import { useRouter } from "@tanstack/react-router";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
//#region src/components/CodingDefaultsCard.tsx
|
|
10
|
+
function CodingDefaultsCard({ teamId }) {
|
|
11
|
+
const [status, setStatus] = useState(null);
|
|
12
|
+
const [image, setImage] = useState("");
|
|
13
|
+
const [cwd, setCwd] = useState(".");
|
|
14
|
+
const [error, setError] = useState("");
|
|
15
|
+
const [busy, setBusy] = useState(false);
|
|
16
|
+
const url = `/api/teams/${encodeURIComponent(teamId)}/coding-environment`;
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
let active = true;
|
|
19
|
+
fetch(url).then(async (r) => {
|
|
20
|
+
if (!r.ok) throw new Error("Defaults unavailable");
|
|
21
|
+
return r.json();
|
|
22
|
+
}).then((s) => {
|
|
23
|
+
if (active) {
|
|
24
|
+
setStatus(s);
|
|
25
|
+
setImage(s.environment?.config.image ?? s.image);
|
|
26
|
+
setCwd(s.environment?.config.cwd ?? ".");
|
|
27
|
+
}
|
|
28
|
+
}).catch((e) => {
|
|
29
|
+
if (active) setError(e.message);
|
|
30
|
+
});
|
|
31
|
+
return () => {
|
|
32
|
+
active = false;
|
|
33
|
+
};
|
|
34
|
+
}, [url]);
|
|
35
|
+
return /* @__PURE__ */ jsxs("details", {
|
|
36
|
+
className: "border-t mt-4 pt-4",
|
|
37
|
+
children: [
|
|
38
|
+
/* @__PURE__ */ jsx("summary", {
|
|
39
|
+
className: "cursor-pointer text-sm",
|
|
40
|
+
children: "Optional protected runtime defaults"
|
|
41
|
+
}),
|
|
42
|
+
/* @__PURE__ */ jsx("p", {
|
|
43
|
+
className: "text-sm text-muted-foreground my-3",
|
|
44
|
+
children: "Agents discover commands during the task. Override the installation image only if this repository needs a different prepared toolchain. Host turns do not use these Docker defaults."
|
|
45
|
+
}),
|
|
46
|
+
error && /* @__PURE__ */ jsx("p", {
|
|
47
|
+
role: "alert",
|
|
48
|
+
children: error
|
|
49
|
+
}),
|
|
50
|
+
status && /* @__PURE__ */ jsxs("form", {
|
|
51
|
+
className: "space-y-3",
|
|
52
|
+
onSubmit: async (e) => {
|
|
53
|
+
e.preventDefault();
|
|
54
|
+
setBusy(true);
|
|
55
|
+
setError("");
|
|
56
|
+
try {
|
|
57
|
+
const r = await fetch(url, {
|
|
58
|
+
method: "PUT",
|
|
59
|
+
headers: { "Content-Type": "application/json" },
|
|
60
|
+
body: JSON.stringify({
|
|
61
|
+
expectedRevision: status.environment?.revision ?? 0,
|
|
62
|
+
config: {
|
|
63
|
+
image,
|
|
64
|
+
cwd,
|
|
65
|
+
env: status.environment?.config.env ?? {}
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
});
|
|
69
|
+
const value = await r.json();
|
|
70
|
+
if (!r.ok) throw new Error(value.error);
|
|
71
|
+
setStatus({
|
|
72
|
+
...status,
|
|
73
|
+
environment: value,
|
|
74
|
+
image
|
|
75
|
+
});
|
|
76
|
+
} catch (e) {
|
|
77
|
+
setError(e instanceof Error ? e.message : "Save failed");
|
|
78
|
+
} finally {
|
|
79
|
+
setBusy(false);
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
children: [
|
|
83
|
+
/* @__PURE__ */ jsxs("label", {
|
|
84
|
+
className: "block text-sm",
|
|
85
|
+
children: ["Local Docker image", /* @__PURE__ */ jsx("input", {
|
|
86
|
+
required: true,
|
|
87
|
+
value: image,
|
|
88
|
+
onChange: (e) => setImage(e.target.value),
|
|
89
|
+
className: "block w-full rounded border p-2 mt-1"
|
|
90
|
+
})]
|
|
91
|
+
}),
|
|
92
|
+
/* @__PURE__ */ jsxs("label", {
|
|
93
|
+
className: "block text-sm",
|
|
94
|
+
children: ["Default directory", /* @__PURE__ */ jsx("input", {
|
|
95
|
+
required: true,
|
|
96
|
+
value: cwd,
|
|
97
|
+
onChange: (e) => setCwd(e.target.value),
|
|
98
|
+
className: "block w-full rounded border p-2 mt-1"
|
|
99
|
+
})]
|
|
100
|
+
}),
|
|
101
|
+
/* @__PURE__ */ jsx(Button, {
|
|
102
|
+
type: "submit",
|
|
103
|
+
variant: "primary",
|
|
104
|
+
disabled: busy,
|
|
105
|
+
children: busy ? "Saving…" : "Save defaults"
|
|
106
|
+
})
|
|
107
|
+
]
|
|
108
|
+
})
|
|
109
|
+
]
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
//#endregion
|
|
113
|
+
//#region src/components/RepositoryContextCard.tsx
|
|
114
|
+
function RepositoryContextCard({ teamId }) {
|
|
115
|
+
const [target, setTarget] = useState("");
|
|
116
|
+
const [capture, setCapture] = useState(null);
|
|
117
|
+
const [busy, setBusy] = useState(false);
|
|
118
|
+
const [error, setError] = useState(null);
|
|
119
|
+
const request = useRef(0);
|
|
120
|
+
const report = capture?.report;
|
|
121
|
+
const issues = report ? [...new Map([
|
|
122
|
+
...report.instructions.issues,
|
|
123
|
+
...report.commands.issues,
|
|
124
|
+
...report.git.issues
|
|
125
|
+
].map((issue) => [JSON.stringify([issue.path, issue.message]), issue])).values()] : [];
|
|
126
|
+
async function inspect() {
|
|
127
|
+
const current = ++request.current;
|
|
128
|
+
const requestedTarget = target || ".";
|
|
129
|
+
setBusy(true);
|
|
130
|
+
setError(null);
|
|
131
|
+
try {
|
|
132
|
+
const response = await fetch(`/api/teams/${encodeURIComponent(teamId)}/repository-context?target=${encodeURIComponent(requestedTarget)}`, { cache: "no-store" });
|
|
133
|
+
if (!response.ok) throw new Error("Repository context could not be loaded. Refresh to try again.");
|
|
134
|
+
const data = await response.json();
|
|
135
|
+
if (request.current === current) setCapture({
|
|
136
|
+
report: data,
|
|
137
|
+
target: requestedTarget
|
|
138
|
+
});
|
|
139
|
+
} catch (err) {
|
|
140
|
+
if (request.current === current) setError(err instanceof Error ? err.message : "Inspection failed");
|
|
141
|
+
} finally {
|
|
142
|
+
if (request.current === current) setBusy(false);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
useEffect(() => {
|
|
146
|
+
inspect();
|
|
147
|
+
return () => {
|
|
148
|
+
request.current++;
|
|
149
|
+
};
|
|
150
|
+
}, [teamId]);
|
|
151
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
152
|
+
className: "min-w-0",
|
|
153
|
+
"aria-labelledby": "repository-context-heading",
|
|
154
|
+
children: [
|
|
155
|
+
/* @__PURE__ */ jsx("h2", {
|
|
156
|
+
id: "repository-context-heading",
|
|
157
|
+
className: "font-serif text-xl mb-1",
|
|
158
|
+
children: "Explore the repository"
|
|
159
|
+
}),
|
|
160
|
+
/* @__PURE__ */ jsx("p", {
|
|
161
|
+
className: "text-muted-foreground text-sm mb-3",
|
|
162
|
+
children: "See the instructions and commands for the part of the project you’re working on."
|
|
163
|
+
}),
|
|
164
|
+
/* @__PURE__ */ jsxs("form", {
|
|
165
|
+
onSubmit: (event) => {
|
|
166
|
+
event.preventDefault();
|
|
167
|
+
inspect();
|
|
168
|
+
},
|
|
169
|
+
className: "flex flex-wrap gap-2 items-end mb-3",
|
|
170
|
+
children: [/* @__PURE__ */ jsxs("label", {
|
|
171
|
+
className: "flex-1 min-w-[12rem] m-0 text-sm",
|
|
172
|
+
children: ["Project path", /* @__PURE__ */ jsx("input", {
|
|
173
|
+
value: target,
|
|
174
|
+
onChange: (event) => setTarget(event.target.value),
|
|
175
|
+
placeholder: ". (Team root)",
|
|
176
|
+
maxLength: 4096,
|
|
177
|
+
className: "mt-1 block w-full rounded-md border bg-background px-3 py-2 font-mono text-sm"
|
|
178
|
+
})]
|
|
179
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
180
|
+
type: "submit",
|
|
181
|
+
variant: "primary",
|
|
182
|
+
disabled: busy,
|
|
183
|
+
children: busy ? "Inspecting…" : report ? "Refresh context" : "Inspect repository"
|
|
184
|
+
})]
|
|
185
|
+
}),
|
|
186
|
+
error && /* @__PURE__ */ jsxs("p", {
|
|
187
|
+
role: "alert",
|
|
188
|
+
className: "text-sm text-danger mb-3",
|
|
189
|
+
children: [
|
|
190
|
+
error,
|
|
191
|
+
" ",
|
|
192
|
+
report ? "The report below is the previous capture." : ""
|
|
193
|
+
]
|
|
194
|
+
}),
|
|
195
|
+
report && capture && /* @__PURE__ */ jsxs("div", {
|
|
196
|
+
className: "space-y-3 text-sm min-w-0",
|
|
197
|
+
"aria-live": "polite",
|
|
198
|
+
children: [
|
|
199
|
+
/* @__PURE__ */ jsxs("p", {
|
|
200
|
+
className: "text-xs text-muted-foreground break-words",
|
|
201
|
+
children: [
|
|
202
|
+
/* @__PURE__ */ jsx("code", { children: capture.target === "." ? "Team root" : capture.target }),
|
|
203
|
+
" · Inspected",
|
|
204
|
+
" ",
|
|
205
|
+
/* @__PURE__ */ jsx("time", {
|
|
206
|
+
dateTime: new Date(report.capturedAt).toISOString(),
|
|
207
|
+
children: new Date(report.capturedAt).toLocaleString()
|
|
208
|
+
}),
|
|
209
|
+
". Read-only inspection."
|
|
210
|
+
]
|
|
211
|
+
}),
|
|
212
|
+
issues.length > 0 && /* @__PURE__ */ jsxs("div", {
|
|
213
|
+
role: "status",
|
|
214
|
+
className: "border-l-2 border-primary bg-muted/40 px-3 py-2",
|
|
215
|
+
children: [/* @__PURE__ */ jsx("h3", {
|
|
216
|
+
className: "font-sans text-sm font-semibold",
|
|
217
|
+
children: "Some context is unavailable"
|
|
218
|
+
}), /* @__PURE__ */ jsx("ul", {
|
|
219
|
+
className: "mt-1 space-y-1",
|
|
220
|
+
children: issues.map((issue, index) => /* @__PURE__ */ jsxs("li", {
|
|
221
|
+
className: "break-words",
|
|
222
|
+
children: [issue.path ? `${issue.path}: ` : "", issue.message]
|
|
223
|
+
}, index))
|
|
224
|
+
})]
|
|
225
|
+
}),
|
|
226
|
+
/* @__PURE__ */ jsxs("div", {
|
|
227
|
+
className: "rounded-md bg-muted/40 px-3 py-2",
|
|
228
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
229
|
+
className: "flex flex-wrap items-baseline gap-x-3 gap-y-1",
|
|
230
|
+
children: [/* @__PURE__ */ jsx("h3", {
|
|
231
|
+
className: "font-sans text-sm font-semibold",
|
|
232
|
+
children: report.git.state === "available" ? "Working tree" : report.git.state === "not_repository" ? "No Git repository" : "Git unavailable"
|
|
233
|
+
}), report.git.state === "available" && /* @__PURE__ */ jsxs("p", {
|
|
234
|
+
className: "min-w-0 break-all",
|
|
235
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
236
|
+
className: "font-mono",
|
|
237
|
+
children: report.git.branch ?? "Detached HEAD"
|
|
238
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
239
|
+
className: "text-muted-foreground",
|
|
240
|
+
children: [
|
|
241
|
+
" ",
|
|
242
|
+
"· ",
|
|
243
|
+
report.git.head?.slice(0, 8) ?? "No commits yet"
|
|
244
|
+
]
|
|
245
|
+
})]
|
|
246
|
+
})]
|
|
247
|
+
}), report.git.state === "available" && /* @__PURE__ */ jsxs("p", {
|
|
248
|
+
className: "text-xs text-muted-foreground mt-1",
|
|
249
|
+
children: [
|
|
250
|
+
report.git.staged,
|
|
251
|
+
" staged · ",
|
|
252
|
+
report.git.unstaged,
|
|
253
|
+
" unstaged · ",
|
|
254
|
+
report.git.untracked,
|
|
255
|
+
" ",
|
|
256
|
+
"untracked · ",
|
|
257
|
+
report.git.conflicted,
|
|
258
|
+
" conflicted"
|
|
259
|
+
]
|
|
260
|
+
})]
|
|
261
|
+
}),
|
|
262
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
263
|
+
/* @__PURE__ */ jsxs("h3", {
|
|
264
|
+
className: "font-sans text-sm font-semibold",
|
|
265
|
+
children: [
|
|
266
|
+
"Instructions",
|
|
267
|
+
" ",
|
|
268
|
+
/* @__PURE__ */ jsxs("span", {
|
|
269
|
+
className: "font-normal text-muted-foreground",
|
|
270
|
+
children: [
|
|
271
|
+
"· ",
|
|
272
|
+
report.instructions.files.length,
|
|
273
|
+
" files",
|
|
274
|
+
report.instructions.state !== "complete" ? " · incomplete" : ""
|
|
275
|
+
]
|
|
276
|
+
})
|
|
277
|
+
]
|
|
278
|
+
}),
|
|
279
|
+
/* @__PURE__ */ jsx("p", {
|
|
280
|
+
className: "text-xs text-muted-foreground mt-1",
|
|
281
|
+
children: "Listed from broadest to most specific. Operator instructions and runtime policy take priority."
|
|
282
|
+
}),
|
|
283
|
+
report.instructions.files.length === 0 && /* @__PURE__ */ jsx("p", {
|
|
284
|
+
className: "mt-2 text-muted-foreground",
|
|
285
|
+
children: report.instructions.state === "complete" ? "No applicable AGENTS.md files found." : "Instructions for this scope could not be prepared."
|
|
286
|
+
}),
|
|
287
|
+
/* @__PURE__ */ jsx("div", {
|
|
288
|
+
className: "mt-2 divide-y",
|
|
289
|
+
children: report.instructions.files.map((file) => /* @__PURE__ */ jsxs("details", {
|
|
290
|
+
className: "py-2 min-w-0",
|
|
291
|
+
children: [/* @__PURE__ */ jsx("summary", {
|
|
292
|
+
className: "cursor-pointer break-words font-mono text-sm",
|
|
293
|
+
children: file.path
|
|
294
|
+
}), /* @__PURE__ */ jsx("pre", {
|
|
295
|
+
className: "mt-2 rounded-md bg-muted/40 p-3 whitespace-pre-wrap break-words text-xs max-h-80 overflow-auto",
|
|
296
|
+
children: file.content
|
|
297
|
+
})]
|
|
298
|
+
}, file.path))
|
|
299
|
+
})
|
|
300
|
+
] }),
|
|
301
|
+
/* @__PURE__ */ jsxs("div", {
|
|
302
|
+
className: "border-t pt-3",
|
|
303
|
+
children: [
|
|
304
|
+
/* @__PURE__ */ jsx("h3", {
|
|
305
|
+
className: "font-sans text-sm font-semibold",
|
|
306
|
+
children: "Suggested commands"
|
|
307
|
+
}),
|
|
308
|
+
/* @__PURE__ */ jsx("p", {
|
|
309
|
+
className: "text-xs text-muted-foreground mt-1",
|
|
310
|
+
children: "Source suggestions for Agent investigation; inspection never executes commands."
|
|
311
|
+
}),
|
|
312
|
+
report.commands.candidates.length === 0 && /* @__PURE__ */ jsx("p", {
|
|
313
|
+
className: "mt-2 text-muted-foreground",
|
|
314
|
+
children: "No command suggestions available for this scope."
|
|
315
|
+
}),
|
|
316
|
+
/* @__PURE__ */ jsx("ul", {
|
|
317
|
+
className: "mt-1 divide-y",
|
|
318
|
+
children: report.commands.candidates.map((candidate, index) => /* @__PURE__ */ jsxs("li", {
|
|
319
|
+
className: "py-2 min-w-0",
|
|
320
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
321
|
+
className: "flex flex-wrap items-center justify-between gap-2",
|
|
322
|
+
children: /* @__PURE__ */ jsx("code", {
|
|
323
|
+
className: "block bg-transparent p-0 whitespace-pre-wrap break-words min-w-0",
|
|
324
|
+
children: candidate.command
|
|
325
|
+
})
|
|
326
|
+
}), /* @__PURE__ */ jsxs("p", {
|
|
327
|
+
className: "text-xs text-muted-foreground mt-1 break-words",
|
|
328
|
+
children: [
|
|
329
|
+
candidate.source,
|
|
330
|
+
" · ",
|
|
331
|
+
candidate.location,
|
|
332
|
+
" · cwd ",
|
|
333
|
+
candidate.cwd,
|
|
334
|
+
candidate.kind === "script" ? ` · ${candidate.packageManager ?? "package manager unknown"}` : " · documentation excerpt"
|
|
335
|
+
]
|
|
336
|
+
})]
|
|
337
|
+
}, `${candidate.source}:${index}`))
|
|
338
|
+
})
|
|
339
|
+
]
|
|
340
|
+
}),
|
|
341
|
+
/* @__PURE__ */ jsxs("details", {
|
|
342
|
+
className: "border-t pt-3 text-xs text-muted-foreground",
|
|
343
|
+
children: [/* @__PURE__ */ jsx("summary", {
|
|
344
|
+
className: "cursor-pointer",
|
|
345
|
+
children: "Source details and fingerprints"
|
|
346
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
347
|
+
className: "mt-2 space-y-2",
|
|
348
|
+
children: [
|
|
349
|
+
/* @__PURE__ */ jsx("p", { children: "Deeper repository instructions apply within their own subtree. Private Agent instructions are managed on each Agent." }),
|
|
350
|
+
/* @__PURE__ */ jsxs("p", {
|
|
351
|
+
className: "break-all",
|
|
352
|
+
children: ["Snapshot SHA-256: ", report.fingerprint]
|
|
353
|
+
}),
|
|
354
|
+
report.git.head && /* @__PURE__ */ jsxs("p", {
|
|
355
|
+
className: "break-all",
|
|
356
|
+
children: ["Git commit: ", report.git.head]
|
|
357
|
+
}),
|
|
358
|
+
report.instructions.files.map((file) => /* @__PURE__ */ jsxs("p", {
|
|
359
|
+
className: "break-all",
|
|
360
|
+
children: [
|
|
361
|
+
/* @__PURE__ */ jsx("span", {
|
|
362
|
+
className: "font-mono",
|
|
363
|
+
children: file.path
|
|
364
|
+
}),
|
|
365
|
+
" · Scope: ",
|
|
366
|
+
file.scope,
|
|
367
|
+
" · Precedence:",
|
|
368
|
+
" ",
|
|
369
|
+
file.precedence,
|
|
370
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
371
|
+
"SHA-256: ",
|
|
372
|
+
file.sha256
|
|
373
|
+
]
|
|
374
|
+
}, file.path)),
|
|
375
|
+
report.commands.sources.map((source) => /* @__PURE__ */ jsxs("p", {
|
|
376
|
+
className: "break-all",
|
|
377
|
+
children: [
|
|
378
|
+
/* @__PURE__ */ jsx("span", {
|
|
379
|
+
className: "font-mono",
|
|
380
|
+
children: source.path
|
|
381
|
+
}),
|
|
382
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
383
|
+
"SHA-256: ",
|
|
384
|
+
source.sha256
|
|
385
|
+
]
|
|
386
|
+
}, source.path))
|
|
387
|
+
]
|
|
388
|
+
})]
|
|
389
|
+
})
|
|
390
|
+
]
|
|
391
|
+
})
|
|
392
|
+
]
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
//#endregion
|
|
396
|
+
//#region src/routes/teams/$id/index.tsx?tsr-split=component
|
|
397
|
+
function TeamDetailPage() {
|
|
398
|
+
const { team, members, profileGroups } = Route.useLoaderData();
|
|
399
|
+
const router = useRouter();
|
|
400
|
+
const [userMd, setUserMd] = useState(team.userMd);
|
|
401
|
+
const [busy, setBusy] = useState(false);
|
|
402
|
+
const [err, setErr] = useState(null);
|
|
403
|
+
const [savedAt, setSavedAt] = useState(null);
|
|
404
|
+
const [topicDirty, setTopicDirty] = useState(false);
|
|
405
|
+
const contextDirty = userMd !== team.userMd || topicDirty;
|
|
406
|
+
async function save() {
|
|
407
|
+
setBusy(true);
|
|
408
|
+
setErr(null);
|
|
409
|
+
try {
|
|
410
|
+
const res = await fetch(`/api/teams/${encodeURIComponent(team.id)}/user-md`, {
|
|
411
|
+
method: "PUT",
|
|
412
|
+
headers: { "content-type": "application/json" },
|
|
413
|
+
body: JSON.stringify({ userMd })
|
|
414
|
+
});
|
|
415
|
+
if (!res.ok) {
|
|
416
|
+
const e = await res.json().catch(() => ({}));
|
|
417
|
+
throw new Error(e.error ?? `${res.status} ${res.statusText}`);
|
|
418
|
+
}
|
|
419
|
+
setSavedAt(Date.now());
|
|
420
|
+
await router.invalidate();
|
|
421
|
+
} catch (e) {
|
|
422
|
+
setErr(e.message);
|
|
423
|
+
} finally {
|
|
424
|
+
setBusy(false);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
return /* @__PURE__ */ jsxs(PageShell, { children: [
|
|
428
|
+
/* @__PURE__ */ jsx(UnsavedChangesGuard, {
|
|
429
|
+
when: contextDirty,
|
|
430
|
+
subject: "Team context"
|
|
431
|
+
}),
|
|
432
|
+
/* @__PURE__ */ jsxs("h1", {
|
|
433
|
+
className: "font-serif text-3xl text-foreground",
|
|
434
|
+
children: [
|
|
435
|
+
team.name,
|
|
436
|
+
" ",
|
|
437
|
+
/* @__PURE__ */ jsxs("span", {
|
|
438
|
+
className: "text-muted-foreground text-base",
|
|
439
|
+
children: [
|
|
440
|
+
"(",
|
|
441
|
+
team.id,
|
|
442
|
+
")"
|
|
443
|
+
]
|
|
444
|
+
})
|
|
445
|
+
]
|
|
446
|
+
}),
|
|
447
|
+
/* @__PURE__ */ jsxs("p", {
|
|
448
|
+
className: "text-muted-foreground text-sm mb-6 mt-1",
|
|
449
|
+
children: [
|
|
450
|
+
/* @__PURE__ */ jsx("code", {
|
|
451
|
+
className: "font-mono",
|
|
452
|
+
children: team.path
|
|
453
|
+
}),
|
|
454
|
+
" · ",
|
|
455
|
+
members.length,
|
|
456
|
+
" ",
|
|
457
|
+
"member",
|
|
458
|
+
members.length === 1 ? "" : "s",
|
|
459
|
+
" ·",
|
|
460
|
+
" ",
|
|
461
|
+
/* @__PURE__ */ jsx("a", {
|
|
462
|
+
href: `/teams/${encodeURIComponent(team.id)}/memory`,
|
|
463
|
+
className: "text-primary underline",
|
|
464
|
+
children: "shared memory →"
|
|
465
|
+
})
|
|
466
|
+
]
|
|
467
|
+
}),
|
|
468
|
+
/* @__PURE__ */ jsx(TeamTabs, { teamId: team.id }),
|
|
469
|
+
/* @__PURE__ */ jsxs("section", {
|
|
470
|
+
className: "rounded-lg border bg-card p-5 mb-6",
|
|
471
|
+
children: [
|
|
472
|
+
/* @__PURE__ */ jsx("h3", {
|
|
473
|
+
className: "font-serif text-xl mb-1",
|
|
474
|
+
children: "USER.md"
|
|
475
|
+
}),
|
|
476
|
+
/* @__PURE__ */ jsx("p", {
|
|
477
|
+
className: "text-muted-foreground text-sm mb-3",
|
|
478
|
+
children: "Read-only context about the human, injected into every member agent's system prompt. 12 KB cap. Agents cannot edit this file — only you can."
|
|
479
|
+
}),
|
|
480
|
+
/* @__PURE__ */ jsx("label", {
|
|
481
|
+
htmlFor: "team-user-context",
|
|
482
|
+
className: "sr-only",
|
|
483
|
+
children: "USER.md Team context"
|
|
484
|
+
}),
|
|
485
|
+
/* @__PURE__ */ jsx("textarea", {
|
|
486
|
+
id: "team-user-context",
|
|
487
|
+
value: userMd,
|
|
488
|
+
onChange: (e) => setUserMd(e.target.value),
|
|
489
|
+
rows: 16,
|
|
490
|
+
className: "w-full rounded-md border bg-background px-3 py-2 font-mono text-sm outline-none focus:ring-2 focus:ring-ring/30",
|
|
491
|
+
placeholder: "What the agent should know about you in this team context…"
|
|
492
|
+
}),
|
|
493
|
+
/* @__PURE__ */ jsxs("div", {
|
|
494
|
+
className: "flex items-center gap-3 mt-3",
|
|
495
|
+
children: [
|
|
496
|
+
/* @__PURE__ */ jsx(Button, {
|
|
497
|
+
variant: "primary",
|
|
498
|
+
onClick: save,
|
|
499
|
+
disabled: busy || userMd === team.userMd,
|
|
500
|
+
children: busy ? "saving…" : "save"
|
|
501
|
+
}),
|
|
502
|
+
/* @__PURE__ */ jsxs("span", {
|
|
503
|
+
className: "text-xs text-muted-foreground",
|
|
504
|
+
children: [userMd.length, " / 12000 chars"]
|
|
505
|
+
}),
|
|
506
|
+
savedAt && /* @__PURE__ */ jsx("span", {
|
|
507
|
+
role: "status",
|
|
508
|
+
className: "text-xs text-success",
|
|
509
|
+
children: "Saved"
|
|
510
|
+
}),
|
|
511
|
+
err && /* @__PURE__ */ jsx("span", {
|
|
512
|
+
role: "alert",
|
|
513
|
+
className: "text-xs text-danger",
|
|
514
|
+
children: err
|
|
515
|
+
})
|
|
516
|
+
]
|
|
517
|
+
})
|
|
518
|
+
]
|
|
519
|
+
}),
|
|
520
|
+
/* @__PURE__ */ jsxs("details", {
|
|
521
|
+
className: "mb-6 rounded-lg border bg-card p-4",
|
|
522
|
+
children: [
|
|
523
|
+
/* @__PURE__ */ jsx("summary", {
|
|
524
|
+
className: "cursor-pointer text-sm",
|
|
525
|
+
children: "Advanced repository diagnostics"
|
|
526
|
+
}),
|
|
527
|
+
/* @__PURE__ */ jsx(RepositoryContextCard, { teamId: team.id }, team.id),
|
|
528
|
+
/* @__PURE__ */ jsx(CodingDefaultsCard, { teamId: team.id })
|
|
529
|
+
]
|
|
530
|
+
}),
|
|
531
|
+
/* @__PURE__ */ jsx(TopicNameFormatCard, {
|
|
532
|
+
team,
|
|
533
|
+
sampleAgent: members[0]?.name ?? "researcher",
|
|
534
|
+
onSaved: () => router.invalidate(),
|
|
535
|
+
onDirtyChange: setTopicDirty
|
|
536
|
+
}),
|
|
537
|
+
members.length === 0 && /* @__PURE__ */ jsx(SpawnFromTemplateCard, {
|
|
538
|
+
teamId: team.id,
|
|
539
|
+
profileGroups,
|
|
540
|
+
onSpawned: () => router.invalidate()
|
|
541
|
+
}),
|
|
542
|
+
/* @__PURE__ */ jsx(SectionCard, {
|
|
543
|
+
title: "Roster",
|
|
544
|
+
description: "Live Team membership has one canonical management view.",
|
|
545
|
+
actions: /* @__PURE__ */ jsxs(StatusBadge, {
|
|
546
|
+
variant: members.length > 0 ? "success" : "neutral",
|
|
547
|
+
children: [
|
|
548
|
+
members.length,
|
|
549
|
+
" member",
|
|
550
|
+
members.length === 1 ? "" : "s"
|
|
551
|
+
]
|
|
552
|
+
}),
|
|
553
|
+
children: /* @__PURE__ */ jsx("a", {
|
|
554
|
+
href: `/teams/${encodeURIComponent(team.id)}/members`,
|
|
555
|
+
className: "ghost-btn",
|
|
556
|
+
children: "Manage Team members"
|
|
557
|
+
})
|
|
558
|
+
})
|
|
559
|
+
] });
|
|
560
|
+
}
|
|
561
|
+
function TopicNameFormatCard({ team, sampleAgent, onSaved, onDirtyChange }) {
|
|
562
|
+
const [format, setFormat] = useState(team.telegramTopicNameFormat ?? "");
|
|
563
|
+
const [busy, setBusy] = useState(false);
|
|
564
|
+
const [err, setErr] = useState(null);
|
|
565
|
+
const [savedAt, setSavedAt] = useState(null);
|
|
566
|
+
const trimmed = format.trim();
|
|
567
|
+
const preview = trimmed ? trimmed.replaceAll("{agent.name}", sampleAgent).replaceAll("{team.name}", team.name).replaceAll("{team.slug}", team.id) : team.id === "default" ? sampleAgent : `${team.id} › ${sampleAgent}`;
|
|
568
|
+
const dirty = (team.telegramTopicNameFormat ?? "") !== format;
|
|
569
|
+
useEffect(() => {
|
|
570
|
+
onDirtyChange(dirty);
|
|
571
|
+
return () => onDirtyChange(false);
|
|
572
|
+
}, [dirty, onDirtyChange]);
|
|
573
|
+
async function save(clear) {
|
|
574
|
+
setBusy(true);
|
|
575
|
+
setErr(null);
|
|
576
|
+
try {
|
|
577
|
+
const res = await fetch(`/api/teams/${encodeURIComponent(team.id)}/topic-format`, {
|
|
578
|
+
method: "PUT",
|
|
579
|
+
headers: { "content-type": "application/json" },
|
|
580
|
+
body: JSON.stringify({ format: clear ? null : format })
|
|
581
|
+
});
|
|
582
|
+
if (!res.ok) {
|
|
583
|
+
const e = await res.json().catch(() => ({}));
|
|
584
|
+
throw new Error(e.error ?? `${res.status} ${res.statusText}`);
|
|
585
|
+
}
|
|
586
|
+
if (clear) setFormat("");
|
|
587
|
+
setSavedAt(Date.now());
|
|
588
|
+
onSaved();
|
|
589
|
+
} catch (e) {
|
|
590
|
+
setErr(e.message);
|
|
591
|
+
} finally {
|
|
592
|
+
setBusy(false);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
596
|
+
className: "rounded-lg border bg-card p-5 mb-6",
|
|
597
|
+
children: [
|
|
598
|
+
/* @__PURE__ */ jsx("h3", {
|
|
599
|
+
className: "font-serif text-xl mb-1",
|
|
600
|
+
children: "Telegram topic names"
|
|
601
|
+
}),
|
|
602
|
+
/* @__PURE__ */ jsxs("p", {
|
|
603
|
+
className: "text-muted-foreground text-sm mb-3",
|
|
604
|
+
children: [
|
|
605
|
+
"Template for this team's Telegram forum-topic titles. Leave empty for built-in naming. Tokens: ",
|
|
606
|
+
/* @__PURE__ */ jsx("code", {
|
|
607
|
+
className: "font-mono",
|
|
608
|
+
children: "{agent.name}"
|
|
609
|
+
}),
|
|
610
|
+
" ",
|
|
611
|
+
/* @__PURE__ */ jsx("code", {
|
|
612
|
+
className: "font-mono",
|
|
613
|
+
children: "{team.name}"
|
|
614
|
+
}),
|
|
615
|
+
" ",
|
|
616
|
+
/* @__PURE__ */ jsx("code", {
|
|
617
|
+
className: "font-mono",
|
|
618
|
+
children: "{team.slug}"
|
|
619
|
+
}),
|
|
620
|
+
" — must include",
|
|
621
|
+
" ",
|
|
622
|
+
/* @__PURE__ */ jsx("code", {
|
|
623
|
+
className: "font-mono",
|
|
624
|
+
children: "{agent.name}"
|
|
625
|
+
}),
|
|
626
|
+
". Saving renames existing topics that you haven't manually renamed in Telegram."
|
|
627
|
+
]
|
|
628
|
+
}),
|
|
629
|
+
/* @__PURE__ */ jsx("label", {
|
|
630
|
+
htmlFor: "team-telegram-topic-format",
|
|
631
|
+
className: "sr-only",
|
|
632
|
+
children: "Telegram topic name format"
|
|
633
|
+
}),
|
|
634
|
+
/* @__PURE__ */ jsx("input", {
|
|
635
|
+
id: "team-telegram-topic-format",
|
|
636
|
+
value: format,
|
|
637
|
+
onChange: (e) => setFormat(e.target.value),
|
|
638
|
+
placeholder: "{team.name} / {agent.name}",
|
|
639
|
+
className: "w-full rounded-md border bg-background px-3 py-2 font-mono text-sm outline-none focus:ring-2 focus:ring-ring/30"
|
|
640
|
+
}),
|
|
641
|
+
/* @__PURE__ */ jsxs("p", {
|
|
642
|
+
className: "text-xs text-muted-foreground mt-2",
|
|
643
|
+
children: ["preview: ", /* @__PURE__ */ jsx("span", {
|
|
644
|
+
className: "font-mono text-foreground",
|
|
645
|
+
children: preview
|
|
646
|
+
})]
|
|
647
|
+
}),
|
|
648
|
+
/* @__PURE__ */ jsxs("div", {
|
|
649
|
+
className: "flex items-center gap-3 mt-3",
|
|
650
|
+
children: [
|
|
651
|
+
/* @__PURE__ */ jsx(Button, {
|
|
652
|
+
variant: "primary",
|
|
653
|
+
onClick: () => save(false),
|
|
654
|
+
disabled: busy || !dirty || trimmed.length === 0,
|
|
655
|
+
children: busy ? "saving…" : "save"
|
|
656
|
+
}),
|
|
657
|
+
team.telegramTopicNameFormat && /* @__PURE__ */ jsx(Button, {
|
|
658
|
+
variant: "ghost",
|
|
659
|
+
onClick: () => save(true),
|
|
660
|
+
disabled: busy,
|
|
661
|
+
children: "clear"
|
|
662
|
+
}),
|
|
663
|
+
savedAt && /* @__PURE__ */ jsx("span", {
|
|
664
|
+
role: "status",
|
|
665
|
+
className: "text-xs text-success",
|
|
666
|
+
children: "Saved"
|
|
667
|
+
}),
|
|
668
|
+
err && /* @__PURE__ */ jsx("span", {
|
|
669
|
+
role: "alert",
|
|
670
|
+
className: "text-xs text-danger",
|
|
671
|
+
children: err
|
|
672
|
+
})
|
|
673
|
+
]
|
|
674
|
+
})
|
|
675
|
+
]
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
function SpawnFromTemplateCard({ teamId, profileGroups, onSpawned }) {
|
|
679
|
+
const eligible = profileGroups.filter((g) => g.slotCount > 0 && !g.deletedAt);
|
|
680
|
+
const [selected, setSelected] = useState(eligible[0]?.id ?? "");
|
|
681
|
+
const [busy, setBusy] = useState(false);
|
|
682
|
+
const [err, setErr] = useState(null);
|
|
683
|
+
async function spawn() {
|
|
684
|
+
if (!selected) return;
|
|
685
|
+
setBusy(true);
|
|
686
|
+
setErr(null);
|
|
687
|
+
try {
|
|
688
|
+
const template = eligible.find((item) => item.id === selected);
|
|
689
|
+
if (!template) throw new Error("Team template is unavailable.");
|
|
690
|
+
const policyResponse = await fetch(`/api/teams/${encodeURIComponent(teamId)}/policy`);
|
|
691
|
+
if (!policyResponse.ok) throw new Error("The current Team policy is unavailable.");
|
|
692
|
+
const current = await policyResponse.json();
|
|
693
|
+
const res = await fetch(`/api/team-templates/${encodeURIComponent(selected)}/spawn`, {
|
|
694
|
+
method: "POST",
|
|
695
|
+
headers: { "content-type": "application/json" },
|
|
696
|
+
body: JSON.stringify({
|
|
697
|
+
templateExpectedRevision: template.currentRevision,
|
|
698
|
+
teamId,
|
|
699
|
+
teamExpectedRevision: current.teamPolicy.revision,
|
|
700
|
+
mode: "initialize"
|
|
701
|
+
})
|
|
702
|
+
});
|
|
703
|
+
if (!res.ok) {
|
|
704
|
+
const e = await res.json().catch(() => ({}));
|
|
705
|
+
throw new Error(e.error ?? `${res.status} ${res.statusText}`);
|
|
706
|
+
}
|
|
707
|
+
onSpawned();
|
|
708
|
+
} catch (e) {
|
|
709
|
+
setErr(e.message);
|
|
710
|
+
} finally {
|
|
711
|
+
setBusy(false);
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
715
|
+
className: "rounded-lg border bg-card p-5 mb-6",
|
|
716
|
+
children: [
|
|
717
|
+
/* @__PURE__ */ jsx("h3", {
|
|
718
|
+
className: "font-serif text-xl mb-1",
|
|
719
|
+
children: "spawn a team into this team"
|
|
720
|
+
}),
|
|
721
|
+
/* @__PURE__ */ jsx("p", {
|
|
722
|
+
className: "text-muted-foreground text-sm mb-3",
|
|
723
|
+
children: "This Team is empty. Pick a canonical Team template to initialize its roster and policy at the current reviewed Team and Team revisions."
|
|
724
|
+
}),
|
|
725
|
+
eligible.length === 0 ? /* @__PURE__ */ jsxs("p", {
|
|
726
|
+
className: "text-muted-foreground text-sm",
|
|
727
|
+
children: [
|
|
728
|
+
"No Team templates with slots yet. Build one on",
|
|
729
|
+
" ",
|
|
730
|
+
/* @__PURE__ */ jsx("a", {
|
|
731
|
+
href: "/templates/teams",
|
|
732
|
+
className: "text-primary underline",
|
|
733
|
+
children: "Team templates"
|
|
734
|
+
}),
|
|
735
|
+
" ",
|
|
736
|
+
"first."
|
|
737
|
+
]
|
|
738
|
+
}) : /* @__PURE__ */ jsxs("div", {
|
|
739
|
+
className: "flex flex-wrap items-end gap-3",
|
|
740
|
+
children: [
|
|
741
|
+
/* @__PURE__ */ jsxs("label", {
|
|
742
|
+
className: "m-0 flex min-w-0 flex-1 flex-col gap-1 text-sm text-foreground",
|
|
743
|
+
children: ["Team template", /* @__PURE__ */ jsx("select", {
|
|
744
|
+
value: selected,
|
|
745
|
+
onChange: (e) => setSelected(e.target.value),
|
|
746
|
+
className: "min-w-0 rounded-md border bg-background px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-ring/30",
|
|
747
|
+
children: eligible.map((g) => /* @__PURE__ */ jsxs("option", {
|
|
748
|
+
value: g.id,
|
|
749
|
+
children: [
|
|
750
|
+
g.name,
|
|
751
|
+
" (",
|
|
752
|
+
g.slotCount,
|
|
753
|
+
" slot",
|
|
754
|
+
g.slotCount === 1 ? "" : "s",
|
|
755
|
+
", r",
|
|
756
|
+
g.currentRevision,
|
|
757
|
+
")"
|
|
758
|
+
]
|
|
759
|
+
}, g.id))
|
|
760
|
+
})]
|
|
761
|
+
}),
|
|
762
|
+
/* @__PURE__ */ jsx(Button, {
|
|
763
|
+
variant: "primary",
|
|
764
|
+
onClick: spawn,
|
|
765
|
+
disabled: busy || !selected,
|
|
766
|
+
children: busy ? "spawning…" : "spawn team"
|
|
767
|
+
}),
|
|
768
|
+
err && /* @__PURE__ */ jsx("span", {
|
|
769
|
+
role: "alert",
|
|
770
|
+
className: "basis-full text-xs text-danger",
|
|
771
|
+
children: err
|
|
772
|
+
})
|
|
773
|
+
]
|
|
774
|
+
})
|
|
775
|
+
]
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
//#endregion
|
|
779
|
+
export { TeamDetailPage as component };
|