bazilion 0.5.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -12
- package/dist/cli.js +383 -152
- package/dist/cli.js.map +1 -1
- package/dist/daemon.js +238 -14064
- package/dist/daemon.js.map +1 -1
- package/dist/web/client/assets/AgentAvatar-JYijLvZ2.js +1 -0
- package/dist/web/client/assets/AgentTabs-DioGqUVR.js +1 -0
- package/dist/web/client/assets/Button-ByiV6fpd.js +1 -0
- package/dist/web/client/assets/ChatPane-DzEgOEqS.js +74 -0
- package/dist/web/client/assets/ConfigTabs-pY-V0Rie.js +1 -0
- package/dist/web/client/assets/FieldRow-CNKma5LE.js +1 -0
- package/dist/web/client/assets/MembersEditor-C6UpqDdV.js +1 -0
- package/dist/web/client/assets/SpawnTeamModal-BEkNCKXm.js +1 -0
- package/dist/web/client/assets/TemplatesTabs-Da7mg9FI.js +1 -0
- package/dist/web/client/assets/_id-BdKmo0gb.js +1 -0
- package/dist/web/client/assets/_id-LT6Ejjr0.js +1 -0
- package/dist/web/client/assets/_id-MR2XjWh0.js +1 -0
- package/dist/web/client/assets/_id-_6jIt0_-.js +1 -0
- package/dist/web/client/assets/agents-0arKbVYG.js +1 -0
- package/dist/web/client/assets/config-BSAVT-17.js +3 -0
- package/dist/web/client/assets/groups-BqTkhHes.js +1 -0
- package/dist/web/client/assets/inbox-ozoCXzr5.js +1 -0
- package/dist/web/client/assets/index-iayCEuU2.js +12 -0
- package/dist/web/client/assets/jsx-runtime-DGeXAQPT.js +1 -0
- package/dist/web/client/assets/login-D8lNr2SX.js +1 -0
- package/dist/web/client/assets/mcp-BLnngDsj.js +1 -0
- package/dist/web/client/assets/memory-D1GQjEvN.js +1 -0
- package/dist/web/client/assets/preload-helper-CvnapA2_.js +1 -0
- package/dist/web/client/assets/profile-groups-C2yJPTaE.js +1 -0
- package/dist/web/client/assets/profiles-BV7AAZjj.js +1 -0
- package/dist/web/client/assets/routes-DSHQLA7K.js +1 -0
- package/dist/web/client/assets/services-BbCJe1Du.js +1 -0
- package/dist/web/client/assets/skills-C6czKR5I.js +1 -0
- package/dist/web/client/assets/styles-C06axZZk.css +2 -0
- package/dist/web/client/assets/telegram-gE4j8gte.js +1 -0
- package/dist/web/client/assets/tokens-D2_O9ARe.js +1 -0
- package/dist/web/client/assets/triggers-WljnfEfJ.js +1 -0
- package/dist/web/client/assets/welcome-Dn-zvmBE.js +1 -0
- package/dist/web/client/assets/wire-constants-BkT5-597.js +1 -0
- package/dist/web/client/baziu.svg +8 -0
- package/dist/web/server/assets/AgentAvatar-8gTAy_tP.js +37 -0
- package/dist/web/server/assets/AgentTabs-BOjTN7QF.js +34 -0
- package/dist/web/server/assets/Button-Dsnw22OF.js +17 -0
- package/dist/web/server/assets/ChatPane-BvpswYvF.js +1084 -0
- package/dist/web/server/assets/ConfigTabs-CyuxzesF.js +41 -0
- package/dist/web/server/assets/FieldRow-DwyqycWI.js +94 -0
- package/dist/web/server/assets/MembersEditor-BWQztvrX.js +131 -0
- package/dist/web/server/assets/Sidebar-DmEiewRN.js +529 -0
- package/dist/web/server/assets/SpawnTeamModal-dSN421k_.js +107 -0
- package/dist/web/server/assets/TemplatesTabs---7h5GYa.js +30 -0
- package/dist/web/server/assets/_id-81NrHA5d.js +16 -0
- package/dist/web/server/assets/_id-BKev9H1p.js +12 -0
- package/dist/web/server/assets/_id-BNwlbWHP.js +24 -0
- package/dist/web/server/assets/_id-BqnDy_Ca.js +16 -0
- package/dist/web/server/assets/_id-CRqqi8IE.js +161 -0
- package/dist/web/server/assets/_id-CXg-Blec.js +367 -0
- package/dist/web/server/assets/_id-CnQflrRv.js +16 -0
- package/dist/web/server/assets/_id-D0ytyXGY.js +662 -0
- package/dist/web/server/assets/_id-D8duqgd5.js +27 -0
- package/dist/web/server/assets/_id-DDixKEud.js +467 -0
- package/dist/web/server/assets/_id-D_Ew11ED.js +28 -0
- package/dist/web/server/assets/_id-Sjw0zhA6.js +38 -0
- package/dist/web/server/assets/_tanstack-start-manifest_v-DBlFH2gg.js +178 -0
- package/dist/web/server/assets/agents-C7SBPN0M.js +210 -0
- package/dist/web/server/assets/agents-ChcAJUI5.js +14 -0
- package/dist/web/server/assets/agents-k5QURC4I.js +26 -0
- package/dist/web/server/assets/auth-DzRAMwVt.js +26 -0
- package/dist/web/server/assets/config-Bq3o924J.js +12 -0
- package/dist/web/server/assets/config-CHaCv89D.js +19 -0
- package/dist/web/server/assets/config-CdVjqjin.js +391 -0
- package/dist/web/server/assets/createServerRpc-CeKECg65.js +12 -0
- package/dist/web/server/assets/createSsrRpc-ZBGxhl8t.js +16 -0
- package/dist/web/server/assets/daemon-client-2NRMzlTr.js +96 -0
- package/dist/web/server/assets/empty-plugin-adapters-DKUlnwwl.js +5 -0
- package/dist/web/server/assets/groups-CbSwND2r.js +12 -0
- package/dist/web/server/assets/groups-CeRRlZaZ.js +150 -0
- package/dist/web/server/assets/groups-pk4CYSuf.js +21 -0
- package/dist/web/server/assets/inbox-Bxb3W04M.js +27 -0
- package/dist/web/server/assets/inbox-CkiSvD14.js +42 -0
- package/dist/web/server/assets/inbox-DU27iHv_.js +133 -0
- package/dist/web/server/assets/login-CNznncgA.js +58 -0
- package/dist/web/server/assets/login-CQybKk7Y.js +74 -0
- package/dist/web/server/assets/mcp-BU_kKENi.js +268 -0
- package/dist/web/server/assets/mcp-BsFKEoXt.js +12 -0
- package/dist/web/server/assets/mcp-CKqwG4mt.js +12 -0
- package/dist/web/server/assets/memory-BaYnfm7K.js +28 -0
- package/dist/web/server/assets/memory-CQaqWnyM.js +284 -0
- package/dist/web/server/assets/memory-Ns2-Z31p.js +16 -0
- package/dist/web/server/assets/profile-groups-CiU06yN1.js +28 -0
- package/dist/web/server/assets/profile-groups-D21MYoLM.js +208 -0
- package/dist/web/server/assets/profile-groups-aoJleXHP.js +12 -0
- package/dist/web/server/assets/profiles-C6a3RKgu.js +26 -0
- package/dist/web/server/assets/profiles-CZ5NkmVw.js +12 -0
- package/dist/web/server/assets/profiles-LxcC_L6n.js +453 -0
- package/dist/web/server/assets/router-BpBZgRwn.js +460 -0
- package/dist/web/server/assets/routes-C61gBiXa.js +57 -0
- package/dist/web/server/assets/routes-Ce2VWrU9.js +33 -0
- package/dist/web/server/assets/routes-V9URcp1v.js +14 -0
- package/dist/web/server/assets/services-B91w2f-X.js +94 -0
- package/dist/web/server/assets/services-Ccc5s2bS.js +17 -0
- package/dist/web/server/assets/services-DhRiNeq0.js +12 -0
- package/dist/web/server/assets/skills-CFIWVg32.js +12 -0
- package/dist/web/server/assets/skills-CpsyR_WA.js +12 -0
- package/dist/web/server/assets/skills-dLyBZb3B.js +261 -0
- package/dist/web/server/assets/start-CYDpZ6cb.js +4 -0
- package/dist/web/server/assets/telegram-BdaUIjvs.js +12 -0
- package/dist/web/server/assets/telegram-DfAddLdv.js +583 -0
- package/dist/web/server/assets/telegram-T3l9KtiE.js +12 -0
- package/dist/web/server/assets/tokens-BCz3PSoT.js +12 -0
- package/dist/web/server/assets/tokens-CkKqrtk-.js +193 -0
- package/dist/web/server/assets/tokens-DdpnfV_Y.js +14 -0
- package/dist/web/server/assets/triggers-BcH_6PW1.js +26 -0
- package/dist/web/server/assets/triggers-BcTTwMfy.js +16 -0
- package/dist/web/server/assets/triggers-BzJG1nN5.js +191 -0
- package/dist/web/server/assets/welcome-CP4CZ9B6.js +85 -0
- package/dist/web/server/assets/wire-constants-Deb4NxBb.js +16 -0
- package/dist/web/server/server.js +5911 -0
- package/dist/web-server.js +42 -0
- package/dist/web-server.js.map +1 -0
- package/dist/worker.js +65 -2
- package/dist/worker.js.map +1 -1
- package/package.json +18 -12
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
import { t as Route } from "./config-Bq3o924J.js";
|
|
2
|
+
import { t as ConfigTabs } from "./ConfigTabs-CyuxzesF.js";
|
|
3
|
+
import { t as FieldRow } from "./FieldRow-DwyqycWI.js";
|
|
4
|
+
import { useState } from "react";
|
|
5
|
+
import { useRouter } from "@tanstack/react-router";
|
|
6
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
//#region src/routes/config/index.tsx?tsr-split=component
|
|
8
|
+
function ProvidersPage() {
|
|
9
|
+
const { providers, openaiCodex } = Route.useLoaderData();
|
|
10
|
+
const setupComplete = providers.some((p) => p.enabled && p.curated.length > 0);
|
|
11
|
+
return /* @__PURE__ */ jsxs("main", {
|
|
12
|
+
className: "mx-auto max-w-5xl px-6 py-8",
|
|
13
|
+
children: [
|
|
14
|
+
/* @__PURE__ */ jsx("h1", {
|
|
15
|
+
className: "font-serif text-3xl text-foreground mb-2",
|
|
16
|
+
children: "config"
|
|
17
|
+
}),
|
|
18
|
+
/* @__PURE__ */ jsx(ConfigTabs, { active: "providers" }),
|
|
19
|
+
!setupComplete && /* @__PURE__ */ jsx(SetupBlockerBanner, {
|
|
20
|
+
providers,
|
|
21
|
+
openaiCodex
|
|
22
|
+
}),
|
|
23
|
+
/* @__PURE__ */ jsxs("p", {
|
|
24
|
+
className: "text-muted-foreground text-sm mb-6",
|
|
25
|
+
children: [
|
|
26
|
+
"Each card configures one LLM provider end to end: credentials (encrypted in the",
|
|
27
|
+
" ",
|
|
28
|
+
/* @__PURE__ */ jsx("code", {
|
|
29
|
+
className: "font-mono",
|
|
30
|
+
children: "secrets"
|
|
31
|
+
}),
|
|
32
|
+
" table), URLs and IDs (plaintext in the",
|
|
33
|
+
" ",
|
|
34
|
+
/* @__PURE__ */ jsx("code", {
|
|
35
|
+
className: "font-mono",
|
|
36
|
+
children: "config"
|
|
37
|
+
}),
|
|
38
|
+
" table), and the curated model list that powers profile / agent dropdowns."
|
|
39
|
+
]
|
|
40
|
+
}),
|
|
41
|
+
providers.map((p) => /* @__PURE__ */ jsx(ProviderCard, {
|
|
42
|
+
p,
|
|
43
|
+
openaiCodexStatus: p.id === "openai-codex" ? openaiCodex : void 0
|
|
44
|
+
}, p.id))
|
|
45
|
+
]
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function SetupBlockerBanner({ providers, openaiCodex }) {
|
|
49
|
+
const issues = [];
|
|
50
|
+
for (const p of providers) {
|
|
51
|
+
if (!p.enabled) continue;
|
|
52
|
+
if (p.id === "openai-codex" && !openaiCodex.connected) issues.push(`${p.id}: enabled but ChatGPT is not connected — click "Connect ChatGPT" below`);
|
|
53
|
+
if (p.curated.length === 0) issues.push(`${p.id}: enabled but no curated models — add at least one name in the "curated models" box below and save`);
|
|
54
|
+
}
|
|
55
|
+
const enabledCount = providers.filter((p) => p.enabled).length;
|
|
56
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
57
|
+
className: "rounded-md border-2 border-amber-400 bg-amber-50 px-4 py-3 mb-4 text-sm",
|
|
58
|
+
children: [
|
|
59
|
+
/* @__PURE__ */ jsx("div", {
|
|
60
|
+
className: "font-semibold text-amber-900 mb-1",
|
|
61
|
+
children: "First-run setup is not complete"
|
|
62
|
+
}),
|
|
63
|
+
/* @__PURE__ */ jsxs("p", {
|
|
64
|
+
className: "text-amber-900 mb-2",
|
|
65
|
+
children: [
|
|
66
|
+
"The rest of the app stays on the Welcome screen until at least one provider is",
|
|
67
|
+
" ",
|
|
68
|
+
/* @__PURE__ */ jsx("strong", { children: "enabled" }),
|
|
69
|
+
" and has ",
|
|
70
|
+
/* @__PURE__ */ jsx("strong", { children: "at least one curated model" }),
|
|
71
|
+
". Use a catalog chip when one is available, or paste the exact model id from your local/server provider."
|
|
72
|
+
]
|
|
73
|
+
}),
|
|
74
|
+
issues.length > 0 ? /* @__PURE__ */ jsx("ul", {
|
|
75
|
+
className: "list-disc pl-5 text-amber-900 space-y-0.5",
|
|
76
|
+
children: issues.map((i) => /* @__PURE__ */ jsx("li", { children: i }, i))
|
|
77
|
+
}) : enabledCount === 0 ? /* @__PURE__ */ jsx("p", {
|
|
78
|
+
className: "text-amber-900",
|
|
79
|
+
children: "No providers are enabled yet — pick one below, flip the toggle on, set credentials, and save at least one model name."
|
|
80
|
+
}) : null
|
|
81
|
+
]
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
function ProviderCard({ p, openaiCodexStatus }) {
|
|
85
|
+
const router = useRouter();
|
|
86
|
+
const [enabled, setEnabled] = useState(p.enabled);
|
|
87
|
+
const [models, setModels] = useState(p.curated.join("\n"));
|
|
88
|
+
const [savingModels, setSavingModels] = useState(false);
|
|
89
|
+
const [modelStatus, setModelStatus] = useState(null);
|
|
90
|
+
async function toggle(next) {
|
|
91
|
+
setEnabled(next);
|
|
92
|
+
try {
|
|
93
|
+
await fetch(`/api/config/providers/${encodeURIComponent(p.id)}/enabled`, {
|
|
94
|
+
method: "PUT",
|
|
95
|
+
headers: { "content-type": "application/json" },
|
|
96
|
+
body: JSON.stringify({ enabled: next })
|
|
97
|
+
});
|
|
98
|
+
await router.invalidate();
|
|
99
|
+
} catch {
|
|
100
|
+
setEnabled(!next);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
async function saveModels(e) {
|
|
104
|
+
e.preventDefault();
|
|
105
|
+
setSavingModels(true);
|
|
106
|
+
setModelStatus(null);
|
|
107
|
+
try {
|
|
108
|
+
const list = models.split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
|
|
109
|
+
const res = await fetch(`/api/config/providers/${encodeURIComponent(p.id)}/models`, {
|
|
110
|
+
method: "PUT",
|
|
111
|
+
headers: { "content-type": "application/json" },
|
|
112
|
+
body: JSON.stringify({ models: list })
|
|
113
|
+
});
|
|
114
|
+
if (!res.ok) {
|
|
115
|
+
const j = await res.json().catch(() => ({}));
|
|
116
|
+
throw new Error(j.error ?? `${res.status} ${res.statusText}`);
|
|
117
|
+
}
|
|
118
|
+
setModelStatus("saved ✓");
|
|
119
|
+
await router.invalidate();
|
|
120
|
+
} catch (e) {
|
|
121
|
+
setModelStatus(`error: ${e.message}`);
|
|
122
|
+
} finally {
|
|
123
|
+
setSavingModels(false);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
127
|
+
className: "rounded-lg border bg-card mb-3 overflow-hidden",
|
|
128
|
+
children: [/* @__PURE__ */ jsxs("header", {
|
|
129
|
+
className: "flex items-center gap-3 px-4 py-3",
|
|
130
|
+
children: [
|
|
131
|
+
/* @__PURE__ */ jsx("span", {
|
|
132
|
+
className: "font-mono font-semibold",
|
|
133
|
+
children: p.id
|
|
134
|
+
}),
|
|
135
|
+
/* @__PURE__ */ jsxs("span", {
|
|
136
|
+
className: "text-muted-foreground text-sm",
|
|
137
|
+
children: ["· ", p.displayName]
|
|
138
|
+
}),
|
|
139
|
+
/* @__PURE__ */ jsxs("label", {
|
|
140
|
+
className: "flex items-center gap-1.5 text-xs uppercase tracking-wide font-semibold cursor-pointer",
|
|
141
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
142
|
+
type: "checkbox",
|
|
143
|
+
checked: enabled,
|
|
144
|
+
onChange: (e) => toggle(e.target.checked),
|
|
145
|
+
className: "size-4"
|
|
146
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
147
|
+
className: enabled ? "text-emerald-700" : "text-muted-foreground",
|
|
148
|
+
children: enabled ? "enabled" : "disabled"
|
|
149
|
+
})]
|
|
150
|
+
}),
|
|
151
|
+
/* @__PURE__ */ jsxs("span", {
|
|
152
|
+
className: "ml-auto text-xs text-muted-foreground",
|
|
153
|
+
children: [
|
|
154
|
+
p.curated.length > 0 && /* @__PURE__ */ jsxs("span", { children: [p.curated.length, " curated"] }),
|
|
155
|
+
p.catalog.length > 0 && /* @__PURE__ */ jsxs("span", { children: [
|
|
156
|
+
" · ",
|
|
157
|
+
p.catalog.length,
|
|
158
|
+
" catalog"
|
|
159
|
+
] }),
|
|
160
|
+
p.live && !p.live.error && /* @__PURE__ */ jsxs("span", { children: [
|
|
161
|
+
" · ",
|
|
162
|
+
p.live.models.length,
|
|
163
|
+
" live"
|
|
164
|
+
] })
|
|
165
|
+
]
|
|
166
|
+
})
|
|
167
|
+
]
|
|
168
|
+
}), enabled && /* @__PURE__ */ jsxs("div", {
|
|
169
|
+
className: "border-t border-dashed px-4 py-3",
|
|
170
|
+
children: [
|
|
171
|
+
p.hint && /* @__PURE__ */ jsx("p", {
|
|
172
|
+
className: "text-xs text-muted-foreground mb-2",
|
|
173
|
+
children: p.hint
|
|
174
|
+
}),
|
|
175
|
+
p.id === "openai-codex" && openaiCodexStatus && /* @__PURE__ */ jsx(OpenAICodexCard, { status: openaiCodexStatus }),
|
|
176
|
+
p.fields.length === 0 && p.envHint && p.id !== "openai-codex" && /* @__PURE__ */ jsxs("p", {
|
|
177
|
+
className: "text-xs text-muted-foreground",
|
|
178
|
+
children: ["Credentials come from the process env: ", /* @__PURE__ */ jsx("code", {
|
|
179
|
+
className: "font-mono",
|
|
180
|
+
children: p.envHint
|
|
181
|
+
})]
|
|
182
|
+
}),
|
|
183
|
+
p.fields.map((f) => /* @__PURE__ */ jsx(FieldRow, { field: f }, f.envVar)),
|
|
184
|
+
/* @__PURE__ */ jsx("h4", {
|
|
185
|
+
className: "mt-4 mb-1 text-xs uppercase tracking-wide text-muted-foreground",
|
|
186
|
+
children: "curated models (one per line)"
|
|
187
|
+
}),
|
|
188
|
+
p.curated.length === 0 && /* @__PURE__ */ jsxs("p", {
|
|
189
|
+
className: "mb-2 text-xs font-medium text-amber-700",
|
|
190
|
+
children: [
|
|
191
|
+
"First-run setup needs at least one model name here — type one (e.g.",
|
|
192
|
+
" ",
|
|
193
|
+
/* @__PURE__ */ jsx("code", {
|
|
194
|
+
className: "font-mono",
|
|
195
|
+
children: exampleModelFor(p.id)
|
|
196
|
+
}),
|
|
197
|
+
") and click",
|
|
198
|
+
" ",
|
|
199
|
+
/* @__PURE__ */ jsx("em", { children: "save models" }),
|
|
200
|
+
". Catalog chips below are the safest source when available."
|
|
201
|
+
]
|
|
202
|
+
}),
|
|
203
|
+
/* @__PURE__ */ jsxs("form", {
|
|
204
|
+
onSubmit: saveModels,
|
|
205
|
+
children: [/* @__PURE__ */ jsx("textarea", {
|
|
206
|
+
value: models,
|
|
207
|
+
onChange: (e) => setModels(e.target.value),
|
|
208
|
+
rows: Math.max(3, Math.min(8, models.split("\n").length)),
|
|
209
|
+
className: "w-full rounded-md border bg-background px-2 py-1.5 font-mono text-sm outline-none focus:ring-2 focus:ring-ring/30",
|
|
210
|
+
placeholder: p.catalog.length === 0 && !p.live ? "Type model names one per line, e.g. qwen3-coder-30b" : "Click catalog chips below, or type names one per line"
|
|
211
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
212
|
+
className: "flex items-center gap-3 mt-2",
|
|
213
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
214
|
+
type: "submit",
|
|
215
|
+
disabled: savingModels,
|
|
216
|
+
className: "rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground disabled:opacity-50",
|
|
217
|
+
children: "save models"
|
|
218
|
+
}), modelStatus && /* @__PURE__ */ jsx("span", {
|
|
219
|
+
className: "text-xs text-muted-foreground",
|
|
220
|
+
children: modelStatus
|
|
221
|
+
})]
|
|
222
|
+
})]
|
|
223
|
+
}),
|
|
224
|
+
p.catalog.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("h4", {
|
|
225
|
+
className: "mt-4 mb-1 text-xs uppercase tracking-wide text-muted-foreground",
|
|
226
|
+
children: "catalog"
|
|
227
|
+
}), /* @__PURE__ */ jsx(ChipList, {
|
|
228
|
+
items: p.catalog,
|
|
229
|
+
onPick: (name) => setModels((m) => m.includes(name) ? m : `${m}\n${name}`.trim())
|
|
230
|
+
})] }),
|
|
231
|
+
p.live && !p.live.error && p.live.models.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("h4", {
|
|
232
|
+
className: "mt-4 mb-1 text-xs uppercase tracking-wide text-muted-foreground",
|
|
233
|
+
children: "live"
|
|
234
|
+
}), /* @__PURE__ */ jsx(ChipList, {
|
|
235
|
+
items: p.live.models,
|
|
236
|
+
onPick: (name) => setModels((m) => m.includes(name) ? m : `${m}\n${name}`.trim())
|
|
237
|
+
})] }),
|
|
238
|
+
p.live?.error && /* @__PURE__ */ jsxs("p", {
|
|
239
|
+
className: "text-xs text-rose-700 mt-2",
|
|
240
|
+
children: ["could not fetch: ", p.live.error]
|
|
241
|
+
})
|
|
242
|
+
]
|
|
243
|
+
})]
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
function exampleModelFor(providerId) {
|
|
247
|
+
switch (providerId) {
|
|
248
|
+
case "openai-codex": return "gpt-5.3-codex-spark";
|
|
249
|
+
case "openai": return "gpt-5.5";
|
|
250
|
+
case "anthropic": return "claude-opus-4-8";
|
|
251
|
+
case "google": return "gemini-3-pro-preview";
|
|
252
|
+
case "google-vertex": return "gemini-3.1-pro-preview";
|
|
253
|
+
case "xai": return "grok-4.3";
|
|
254
|
+
case "groq": return "llama-3.3-70b-versatile";
|
|
255
|
+
case "cerebras": return "zai-glm-4.7";
|
|
256
|
+
case "mistral": return "mistral-large-latest";
|
|
257
|
+
case "zai": return "glm-5.2";
|
|
258
|
+
case "huggingface": return "Qwen/Qwen3.5-397B-A17B";
|
|
259
|
+
case "openrouter": return "anthropic/claude-opus-4.8";
|
|
260
|
+
case "vercel-ai-gateway": return "anthropic/claude-opus-4.8";
|
|
261
|
+
case "deepseek": return "deepseek-v4-pro";
|
|
262
|
+
case "fireworks": return "accounts/fireworks/models/kimi-k2p7-code";
|
|
263
|
+
case "together": return "Qwen/Qwen3.7-Max";
|
|
264
|
+
case "moonshotai": return "kimi-k2.7-code";
|
|
265
|
+
case "moonshotai-cn": return "kimi-k2.7-code";
|
|
266
|
+
case "kimi-coding": return "kimi-for-coding";
|
|
267
|
+
case "minimax": return "MiniMax-M2.7";
|
|
268
|
+
case "minimax-cn": return "MiniMax-M3";
|
|
269
|
+
case "ant-ling": return "Ling-2.6-1T";
|
|
270
|
+
case "nvidia": return "nvidia/nemotron-3-super-120b-a12b";
|
|
271
|
+
case "cloudflare-workers-ai": return "@cf/moonshotai/kimi-k2.6";
|
|
272
|
+
case "cloudflare-ai-gateway": return "claude-opus-4-7";
|
|
273
|
+
case "github-copilot": return "claude-opus-4.7";
|
|
274
|
+
case "xiaomi": return "mimo-v2.5";
|
|
275
|
+
case "xiaomi-token-plan-ams":
|
|
276
|
+
case "xiaomi-token-plan-cn":
|
|
277
|
+
case "xiaomi-token-plan-sgp": return "mimo-v2.5-pro";
|
|
278
|
+
case "opencode": return "claude-opus-4-8";
|
|
279
|
+
case "opencode-go": return "kimi-k2.7-code";
|
|
280
|
+
case "zai-coding-cn": return "glm-5.2";
|
|
281
|
+
case "azure-openai": return "gpt-5.5";
|
|
282
|
+
case "bedrock": return "anthropic.claude-opus-4-8";
|
|
283
|
+
case "ollama": return "llama3.3";
|
|
284
|
+
case "lmstudio": return "qwen3-coder-30b";
|
|
285
|
+
case "llamacpp": return "unsloth/Qwen3.6-35B-A3B-MTP-GGUF:MXFP4_MOE";
|
|
286
|
+
default: return "model-name";
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
function ChipList({ items, onPick }) {
|
|
290
|
+
return /* @__PURE__ */ jsx("div", {
|
|
291
|
+
className: "flex flex-wrap gap-1.5 max-h-40 overflow-y-auto rounded-md border bg-background p-1.5",
|
|
292
|
+
children: items.map((m) => /* @__PURE__ */ jsx("button", {
|
|
293
|
+
type: "button",
|
|
294
|
+
onClick: () => onPick(m),
|
|
295
|
+
className: "rounded border bg-card px-2 py-0.5 font-mono text-xs hover:border-primary hover:bg-accent",
|
|
296
|
+
children: m
|
|
297
|
+
}, m))
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
function OpenAICodexCard({ status }) {
|
|
301
|
+
const router = useRouter();
|
|
302
|
+
const [busy, setBusy] = useState(false);
|
|
303
|
+
const [err, setErr] = useState(null);
|
|
304
|
+
async function connect() {
|
|
305
|
+
setBusy(true);
|
|
306
|
+
setErr(null);
|
|
307
|
+
try {
|
|
308
|
+
const res = await fetch("/api/auth/openai/login", { method: "POST" });
|
|
309
|
+
if (!res.ok) {
|
|
310
|
+
const j = await res.json().catch(() => ({}));
|
|
311
|
+
throw new Error(j.error ?? `${res.status} ${res.statusText}`);
|
|
312
|
+
}
|
|
313
|
+
await router.invalidate();
|
|
314
|
+
} catch (e) {
|
|
315
|
+
setErr(e.message);
|
|
316
|
+
} finally {
|
|
317
|
+
setBusy(false);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
async function disconnect() {
|
|
321
|
+
setBusy(true);
|
|
322
|
+
setErr(null);
|
|
323
|
+
try {
|
|
324
|
+
await fetch("/api/auth/openai", { method: "DELETE" });
|
|
325
|
+
await router.invalidate();
|
|
326
|
+
} catch (e) {
|
|
327
|
+
setErr(e.message);
|
|
328
|
+
} finally {
|
|
329
|
+
setBusy(false);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
333
|
+
className: "rounded-md border bg-muted/30 p-3 mb-3",
|
|
334
|
+
children: [status.connected ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
335
|
+
className: "flex flex-wrap gap-2 items-center mb-2",
|
|
336
|
+
children: [
|
|
337
|
+
/* @__PURE__ */ jsx("span", {
|
|
338
|
+
className: "rounded-full bg-emerald-100 text-emerald-800 px-2 py-0.5 text-xs font-semibold uppercase",
|
|
339
|
+
children: "connected"
|
|
340
|
+
}),
|
|
341
|
+
status.accountId && /* @__PURE__ */ jsxs("span", {
|
|
342
|
+
className: "text-xs text-muted-foreground",
|
|
343
|
+
children: ["account ", /* @__PURE__ */ jsx("code", {
|
|
344
|
+
className: "font-mono",
|
|
345
|
+
children: status.accountId
|
|
346
|
+
})]
|
|
347
|
+
}),
|
|
348
|
+
status.expiresAt && /* @__PURE__ */ jsxs("span", {
|
|
349
|
+
className: "text-xs text-muted-foreground",
|
|
350
|
+
children: [
|
|
351
|
+
"token expires",
|
|
352
|
+
" ",
|
|
353
|
+
new Date(status.expiresAt).toISOString().replace(/\.\d+Z$/, "Z")
|
|
354
|
+
]
|
|
355
|
+
})
|
|
356
|
+
]
|
|
357
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
358
|
+
type: "button",
|
|
359
|
+
onClick: disconnect,
|
|
360
|
+
disabled: busy,
|
|
361
|
+
className: "rounded-md border px-3 py-1.5 text-sm text-rose-700 hover:bg-rose-50 disabled:opacity-50",
|
|
362
|
+
children: "disconnect"
|
|
363
|
+
})] }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("p", {
|
|
364
|
+
className: "text-xs text-muted-foreground mb-2",
|
|
365
|
+
children: [
|
|
366
|
+
"Sign in with your ChatGPT account — the OAuth flow opens a new browser tab. The loopback callback at ",
|
|
367
|
+
/* @__PURE__ */ jsx("code", {
|
|
368
|
+
className: "font-mono",
|
|
369
|
+
children: "localhost:1455"
|
|
370
|
+
}),
|
|
371
|
+
" only works when you're using the web UI on the same machine as the daemon. For remote setups, run ",
|
|
372
|
+
/* @__PURE__ */ jsx("code", {
|
|
373
|
+
className: "font-mono",
|
|
374
|
+
children: "bazilion auth openai login"
|
|
375
|
+
}),
|
|
376
|
+
" on the client."
|
|
377
|
+
]
|
|
378
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
379
|
+
type: "button",
|
|
380
|
+
onClick: connect,
|
|
381
|
+
disabled: busy,
|
|
382
|
+
className: "rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground disabled:opacity-50",
|
|
383
|
+
children: busy ? "opening browser…" : "Connect ChatGPT →"
|
|
384
|
+
})] }), err && /* @__PURE__ */ jsx("p", {
|
|
385
|
+
className: "text-sm text-rose-700 mt-2",
|
|
386
|
+
children: err
|
|
387
|
+
})]
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
//#endregion
|
|
391
|
+
export { ProvidersPage as component };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { n as TSS_SERVER_FUNCTION } from "../server.js";
|
|
2
|
+
//#region ../../node_modules/.pnpm/@tanstack+start-server-core@1.169.15/node_modules/@tanstack/start-server-core/dist/esm/createServerRpc.js
|
|
3
|
+
var createServerRpc = (serverFnMeta, splitImportFn) => {
|
|
4
|
+
const url = "/_serverFn/" + serverFnMeta.id;
|
|
5
|
+
return Object.assign(splitImportFn, {
|
|
6
|
+
url,
|
|
7
|
+
serverFnMeta,
|
|
8
|
+
[TSS_SERVER_FUNCTION]: true
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
//#endregion
|
|
12
|
+
export { createServerRpc as t };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { n as TSS_SERVER_FUNCTION, r as getServerFnById } from "../server.js";
|
|
2
|
+
//#region ../../node_modules/.pnpm/@tanstack+start-server-core@1.169.15/node_modules/@tanstack/start-server-core/dist/esm/createSsrRpc.js
|
|
3
|
+
var createSsrRpc = (functionId) => {
|
|
4
|
+
const url = "/_serverFn/" + functionId;
|
|
5
|
+
const serverFnMeta = { id: functionId };
|
|
6
|
+
const fn = async (...args) => {
|
|
7
|
+
return (await getServerFnById(functionId, { origin: "server" }))(...args);
|
|
8
|
+
};
|
|
9
|
+
return Object.assign(fn, {
|
|
10
|
+
url,
|
|
11
|
+
serverFnMeta,
|
|
12
|
+
[TSS_SERVER_FUNCTION]: true
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
//#endregion
|
|
16
|
+
export { createSsrRpc as t };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { i as getCookie } from "../server.js";
|
|
2
|
+
//#region ../../packages/client/src/index.ts
|
|
3
|
+
var ApiClientError = class extends Error {
|
|
4
|
+
status;
|
|
5
|
+
body;
|
|
6
|
+
constructor(status, body) {
|
|
7
|
+
super(`${status}: ${body.error}`);
|
|
8
|
+
this.status = status;
|
|
9
|
+
this.body = body;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
async function resolveToken(src) {
|
|
13
|
+
return typeof src === "function" ? await src() : src;
|
|
14
|
+
}
|
|
15
|
+
function createClient(cfg) {
|
|
16
|
+
async function authHeaders() {
|
|
17
|
+
return {
|
|
18
|
+
authorization: `Bearer ${await resolveToken(cfg.token)}`,
|
|
19
|
+
origin: cfg.serverUrl
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
async function request(method, path, body) {
|
|
23
|
+
const headers = { ...await authHeaders() };
|
|
24
|
+
if (body !== void 0) headers["content-type"] = "application/json";
|
|
25
|
+
const res = await fetch(`${cfg.serverUrl}${path}`, {
|
|
26
|
+
method,
|
|
27
|
+
headers,
|
|
28
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
29
|
+
});
|
|
30
|
+
if (!res.ok) {
|
|
31
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
32
|
+
throw new ApiClientError(res.status, err);
|
|
33
|
+
}
|
|
34
|
+
if (res.status === 204) return void 0;
|
|
35
|
+
return await res.json();
|
|
36
|
+
}
|
|
37
|
+
async function postMultipart(path, form) {
|
|
38
|
+
const res = await fetch(`${cfg.serverUrl}${path}`, {
|
|
39
|
+
method: "POST",
|
|
40
|
+
headers: { ...await authHeaders() },
|
|
41
|
+
body: form
|
|
42
|
+
});
|
|
43
|
+
if (!res.ok) {
|
|
44
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
45
|
+
throw new ApiClientError(res.status, err);
|
|
46
|
+
}
|
|
47
|
+
if (res.status === 204) return void 0;
|
|
48
|
+
return await res.json();
|
|
49
|
+
}
|
|
50
|
+
async function* stream(method, path, body) {
|
|
51
|
+
const headers = { ...await authHeaders() };
|
|
52
|
+
if (body !== void 0) headers["content-type"] = "application/json";
|
|
53
|
+
const res = await fetch(`${cfg.serverUrl}${path}`, {
|
|
54
|
+
method,
|
|
55
|
+
headers,
|
|
56
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
57
|
+
});
|
|
58
|
+
if (!res.ok || !res.body) {
|
|
59
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
60
|
+
throw new ApiClientError(res.status, err);
|
|
61
|
+
}
|
|
62
|
+
const reader = res.body.getReader();
|
|
63
|
+
const decoder = new TextDecoder();
|
|
64
|
+
let buffer = "";
|
|
65
|
+
while (true) {
|
|
66
|
+
const { done, value } = await reader.read();
|
|
67
|
+
if (done) break;
|
|
68
|
+
buffer += decoder.decode(value, { stream: true });
|
|
69
|
+
const lines = buffer.split("\n");
|
|
70
|
+
buffer = lines.pop() ?? "";
|
|
71
|
+
for (const line of lines) if (line.trim()) yield JSON.parse(line);
|
|
72
|
+
}
|
|
73
|
+
if (buffer.trim()) yield JSON.parse(buffer);
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
get: (p) => request("GET", p),
|
|
77
|
+
post: (p, b) => request("POST", p, b),
|
|
78
|
+
postMultipart,
|
|
79
|
+
put: (p, b) => request("PUT", p, b),
|
|
80
|
+
patch: (p, b) => request("PATCH", p, b),
|
|
81
|
+
del: (p) => request("DELETE", p),
|
|
82
|
+
stream
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
//#region src/lib/daemon-client.ts
|
|
87
|
+
var DAEMON_URL = process.env.BAZILION_DAEMON ?? "http://127.0.0.1:4321";
|
|
88
|
+
function daemonClient() {
|
|
89
|
+
return createClient({
|
|
90
|
+
serverUrl: DAEMON_URL,
|
|
91
|
+
token: getCookie("bz_token") ?? ""
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
var DAEMON_BASE_URL = DAEMON_URL;
|
|
95
|
+
//#endregion
|
|
96
|
+
export { daemonClient as n, ApiClientError as r, DAEMON_BASE_URL as t };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
//#region ../../node_modules/.pnpm/@tanstack+start-server-core@1.169.15/node_modules/@tanstack/start-server-core/dist/esm/empty-plugin-adapters.js
|
|
2
|
+
var pluginSerializationAdapters = [];
|
|
3
|
+
var hasPluginAdapters = false;
|
|
4
|
+
//#endregion
|
|
5
|
+
export { hasPluginAdapters, pluginSerializationAdapters };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { t as createServerFn } from "../server.js";
|
|
2
|
+
import { t as createSsrRpc } from "./createSsrRpc-ZBGxhl8t.js";
|
|
3
|
+
import { createFileRoute, lazyRouteComponent } from "@tanstack/react-router";
|
|
4
|
+
//#region src/routes/groups/index.tsx
|
|
5
|
+
var $$splitComponentImporter = () => import("./groups-CeRRlZaZ.js");
|
|
6
|
+
var fetchGroupsData = createServerFn({ method: "GET" }).handler(createSsrRpc("3456e4a7ccfe06623459976ccede09e048e75baf27fcc22c5877059c175eb6f8"));
|
|
7
|
+
var Route = createFileRoute("/groups/")({
|
|
8
|
+
loader: () => fetchGroupsData(),
|
|
9
|
+
component: lazyRouteComponent($$splitComponentImporter, "component")
|
|
10
|
+
});
|
|
11
|
+
//#endregion
|
|
12
|
+
export { Route as t };
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { t as Route } from "./groups-CbSwND2r.js";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { useRouter } from "@tanstack/react-router";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
//#region src/routes/groups/index.tsx?tsr-split=component
|
|
6
|
+
function GroupsPage() {
|
|
7
|
+
const { groups, memberCounts } = Route.useLoaderData();
|
|
8
|
+
const router = useRouter();
|
|
9
|
+
async function remove(id) {
|
|
10
|
+
if (!confirm("remove this group registration?")) return;
|
|
11
|
+
const res = await fetch(`/api/groups/${id}`, { method: "DELETE" });
|
|
12
|
+
if (!res.ok && res.status !== 204) {
|
|
13
|
+
alert(res.statusText);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
await router.invalidate();
|
|
17
|
+
}
|
|
18
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
19
|
+
/* @__PURE__ */ jsx("h1", { children: "groups" }),
|
|
20
|
+
/* @__PURE__ */ jsx("p", {
|
|
21
|
+
className: "muted",
|
|
22
|
+
children: "A group is a collaboration context: one filesystem root, one USER.md, one roster. Every agent belongs to exactly one group."
|
|
23
|
+
}),
|
|
24
|
+
/* @__PURE__ */ jsx(RegisterGroupForm, { onRegistered: () => router.invalidate() }),
|
|
25
|
+
/* @__PURE__ */ jsxs("table", { children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
26
|
+
/* @__PURE__ */ jsx("th", { children: "id" }),
|
|
27
|
+
/* @__PURE__ */ jsx("th", { children: "name" }),
|
|
28
|
+
/* @__PURE__ */ jsx("th", { children: "path" }),
|
|
29
|
+
/* @__PURE__ */ jsx("th", { children: "members" }),
|
|
30
|
+
/* @__PURE__ */ jsx("th", { children: "USER.md" }),
|
|
31
|
+
/* @__PURE__ */ jsx("th", {})
|
|
32
|
+
] }) }), /* @__PURE__ */ jsxs("tbody", { children: [groups.length === 0 && /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", {
|
|
33
|
+
colSpan: 6,
|
|
34
|
+
className: "muted",
|
|
35
|
+
children: "no groups registered"
|
|
36
|
+
}) }), groups.map((g) => {
|
|
37
|
+
const count = memberCounts[g.id] ?? 0;
|
|
38
|
+
const userMdBytes = g.userMd.length;
|
|
39
|
+
return /* @__PURE__ */ jsxs("tr", { children: [
|
|
40
|
+
/* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx("code", { children: g.id }) }),
|
|
41
|
+
/* @__PURE__ */ jsx("td", { children: g.name }),
|
|
42
|
+
/* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx("code", { children: g.path }) }),
|
|
43
|
+
/* @__PURE__ */ jsx("td", { children: count }),
|
|
44
|
+
/* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx("a", {
|
|
45
|
+
href: `/groups/${g.id}`,
|
|
46
|
+
children: userMdBytes > 0 ? `${userMdBytes} chars` : "empty"
|
|
47
|
+
}) }),
|
|
48
|
+
/* @__PURE__ */ jsx("td", { children: count === 0 ? /* @__PURE__ */ jsx("button", {
|
|
49
|
+
type: "button",
|
|
50
|
+
className: "ghost-btn",
|
|
51
|
+
onClick: () => remove(g.id),
|
|
52
|
+
children: "remove"
|
|
53
|
+
}) : /* @__PURE__ */ jsx("span", {
|
|
54
|
+
className: "muted",
|
|
55
|
+
title: `${count} agent(s) belong to this group`,
|
|
56
|
+
children: "in use"
|
|
57
|
+
}) })
|
|
58
|
+
] }, g.id);
|
|
59
|
+
})] })] })
|
|
60
|
+
] });
|
|
61
|
+
}
|
|
62
|
+
function RegisterGroupForm({ onRegistered }) {
|
|
63
|
+
const [id, setId] = useState("");
|
|
64
|
+
const [name, setName] = useState("");
|
|
65
|
+
const [link, setLink] = useState("");
|
|
66
|
+
const [err, setErr] = useState(null);
|
|
67
|
+
const [submitting, setSubmitting] = useState(false);
|
|
68
|
+
async function submit(e) {
|
|
69
|
+
e.preventDefault();
|
|
70
|
+
setErr(null);
|
|
71
|
+
if (!id.trim()) {
|
|
72
|
+
setErr("id is required");
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
setSubmitting(true);
|
|
76
|
+
try {
|
|
77
|
+
const res = await fetch("/api/groups", {
|
|
78
|
+
method: "POST",
|
|
79
|
+
headers: { "content-type": "application/json" },
|
|
80
|
+
body: JSON.stringify({
|
|
81
|
+
id: id.trim(),
|
|
82
|
+
name: name.trim() || void 0,
|
|
83
|
+
link: link.trim() || void 0
|
|
84
|
+
})
|
|
85
|
+
});
|
|
86
|
+
if (!res.ok) {
|
|
87
|
+
const e2 = await res.json().catch(() => null);
|
|
88
|
+
throw new Error(e2?.error ?? res.statusText);
|
|
89
|
+
}
|
|
90
|
+
setId("");
|
|
91
|
+
setName("");
|
|
92
|
+
setLink("");
|
|
93
|
+
onRegistered();
|
|
94
|
+
} catch (e2) {
|
|
95
|
+
setErr(e2.message);
|
|
96
|
+
} finally {
|
|
97
|
+
setSubmitting(false);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return /* @__PURE__ */ jsxs("form", {
|
|
101
|
+
className: "card",
|
|
102
|
+
onSubmit: submit,
|
|
103
|
+
children: [
|
|
104
|
+
/* @__PURE__ */ jsx("h3", { children: "register group" }),
|
|
105
|
+
err && /* @__PURE__ */ jsx("div", {
|
|
106
|
+
className: "err",
|
|
107
|
+
children: err
|
|
108
|
+
}),
|
|
109
|
+
/* @__PURE__ */ jsxs("p", {
|
|
110
|
+
className: "muted",
|
|
111
|
+
children: [
|
|
112
|
+
"Groups always live under ",
|
|
113
|
+
/* @__PURE__ */ jsx("code", { children: "~/.bazilion/groups/<slug>/" }),
|
|
114
|
+
". Leave the link target blank to create a fresh directory; supply an absolute path to materialize the slot as a symlink to your existing project tree instead."
|
|
115
|
+
]
|
|
116
|
+
}),
|
|
117
|
+
/* @__PURE__ */ jsxs("div", {
|
|
118
|
+
className: "flex gap-4",
|
|
119
|
+
children: [/* @__PURE__ */ jsxs("label", {
|
|
120
|
+
className: "flex-1",
|
|
121
|
+
children: ["id (slug)", /* @__PURE__ */ jsx("input", {
|
|
122
|
+
value: id,
|
|
123
|
+
onChange: (e) => setId(e.target.value),
|
|
124
|
+
required: true,
|
|
125
|
+
placeholder: "myproject"
|
|
126
|
+
})]
|
|
127
|
+
}), /* @__PURE__ */ jsxs("label", {
|
|
128
|
+
className: "flex-1",
|
|
129
|
+
children: ["name", /* @__PURE__ */ jsx("input", {
|
|
130
|
+
value: name,
|
|
131
|
+
onChange: (e) => setName(e.target.value),
|
|
132
|
+
placeholder: "My Project"
|
|
133
|
+
})]
|
|
134
|
+
})]
|
|
135
|
+
}),
|
|
136
|
+
/* @__PURE__ */ jsxs("label", { children: ["link target (optional, absolute path)", /* @__PURE__ */ jsx("input", {
|
|
137
|
+
value: link,
|
|
138
|
+
onChange: (e) => setLink(e.target.value),
|
|
139
|
+
placeholder: "/home/user/projects/myproject"
|
|
140
|
+
})] }),
|
|
141
|
+
/* @__PURE__ */ jsx("button", {
|
|
142
|
+
type: "submit",
|
|
143
|
+
disabled: submitting,
|
|
144
|
+
children: submitting ? "registering…" : "register"
|
|
145
|
+
})
|
|
146
|
+
]
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
//#endregion
|
|
150
|
+
export { GroupsPage as component };
|