@hachej/boring-ui-cli 0.1.31 → 0.1.32

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.
Files changed (92) hide show
  1. package/README.md +7 -4
  2. package/dist/server/cli.js +35 -233
  3. package/dist/server/pluginFrontRuntime.js +183 -23
  4. package/package.json +7 -6
  5. package/public/assets/DebugDrawer-DB9C3tZz.js +1 -0
  6. package/public/assets/{_baseUniq-2WvYsyyQ.js → _baseUniq-BHrtLO8W.js} +1 -1
  7. package/public/assets/{arc-BfQMEcaD.js → arc-BTJHwuiF.js} +1 -1
  8. package/public/assets/architectureDiagram-Q4EWVU46-CJMeSZx6.js +36 -0
  9. package/public/assets/{blockDiagram-DXYQGD6D-BwO0KFc4.js → blockDiagram-DXYQGD6D-D_iRmbs0.js} +5 -5
  10. package/public/assets/{c4Diagram-AHTNJAMY-3ZfOXc8v.js → c4Diagram-AHTNJAMY-DqJK-oCk.js} +1 -1
  11. package/public/assets/channel-t1oMFJWT.js +1 -0
  12. package/public/assets/{chunk-4BX2VUAB-CRl1YiJJ.js → chunk-4BX2VUAB-DBqhw0eR.js} +1 -1
  13. package/public/assets/{chunk-4TB4RGXK-DrpTwphl.js → chunk-4TB4RGXK-BEbQ9ff5.js} +2 -2
  14. package/public/assets/chunk-55IACEB6-sdAV4otZ.js +1 -0
  15. package/public/assets/{chunk-EDXVE4YY-BC7-AFdu.js → chunk-EDXVE4YY-BGeNOj7f.js} +1 -1
  16. package/public/assets/{chunk-FMBD7UC4-DsK26d_T.js → chunk-FMBD7UC4-DwD_gBy0.js} +1 -1
  17. package/public/assets/{chunk-OYMX7WX6-BeikaWZm.js → chunk-OYMX7WX6-CjMCkDF3.js} +1 -1
  18. package/public/assets/{chunk-QZHKN3VN-BwxHokKH.js → chunk-QZHKN3VN-Cot2XaAR.js} +1 -1
  19. package/public/assets/{chunk-YZCP3GAM-BbZ8wRWB.js → chunk-YZCP3GAM-CGX-4Jvn.js} +1 -1
  20. package/public/assets/classDiagram-6PBFFD2Q-BgSBQBOf.js +1 -0
  21. package/public/assets/classDiagram-v2-HSJHXN6E-BgSBQBOf.js +1 -0
  22. package/public/assets/clone-BBHYjbBI.js +1 -0
  23. package/public/assets/{cose-bilkent-S5V4N54A-C3HWuNVz.js → cose-bilkent-S5V4N54A-CDntEO8X.js} +1 -1
  24. package/public/assets/{dagre-KV5264BT-DOVky5l9.js → dagre-KV5264BT-ZOVUZI--.js} +2 -2
  25. package/public/assets/diagram-5BDNPKRD-LdjTY2br.js +10 -0
  26. package/public/assets/diagram-G4DWMVQ6-BWxGregh.js +24 -0
  27. package/public/assets/diagram-MMDJMWI5-CxtOYZMd.js +43 -0
  28. package/public/assets/diagram-TYMM5635-ChD56z2q.js +24 -0
  29. package/public/assets/{erDiagram-SMLLAGMA-wZ_XblND.js → erDiagram-SMLLAGMA-B8zSJysM.js} +2 -2
  30. package/public/assets/{flowDiagram-DWJPFMVM-of3iiuJI.js → flowDiagram-DWJPFMVM-Dqqy7UJT.js} +1 -1
  31. package/public/assets/{ganttDiagram-T4ZO3ILL-CiIxc0v4.js → ganttDiagram-T4ZO3ILL-Dn_EJlMH.js} +1 -1
  32. package/public/assets/gitGraphDiagram-UUTBAWPF-BVuaJiec.js +106 -0
  33. package/public/assets/{graph-CandW0gD.js → graph-Dj5mmSf2.js} +1 -1
  34. package/public/assets/highlighted-body-OFNGDK62-Cn9lWz0x.js +1 -0
  35. package/public/assets/index-Ciaf_ynY.css +1 -0
  36. package/public/assets/{index-CtdAhKdF.js → index-CrmEpxcy.js} +423 -398
  37. package/public/assets/{infoDiagram-42DDH7IO-B4MJKAr8.js → infoDiagram-42DDH7IO-DawFXMLo.js} +1 -1
  38. package/public/assets/{ishikawaDiagram-UXIWVN3A-Bl2J6bvs.js → ishikawaDiagram-UXIWVN3A-DBxt-riO.js} +4 -4
  39. package/public/assets/{journeyDiagram-VCZTEJTY-JYysqMwv.js → journeyDiagram-VCZTEJTY-D50mNLlL.js} +4 -4
  40. package/public/assets/{kanban-definition-6JOO6SKY-B0wB13fQ.js → kanban-definition-6JOO6SKY-CFBUjJCs.js} +6 -6
  41. package/public/assets/{layout-DYl8UnAo.js → layout-DEdejLi9.js} +1 -1
  42. package/public/assets/{linear-Dj3asvOm.js → linear-BXKtVmEh.js} +1 -1
  43. package/public/assets/{min-Cbw7dpzS.js → min-DY1T79Si.js} +1 -1
  44. package/public/assets/{mindmap-definition-QFDTVHPH-DLl-2gHB.js → mindmap-definition-QFDTVHPH-DbCBDJgc.js} +9 -9
  45. package/public/assets/pieDiagram-DEJITSTG-DYgefMzu.js +30 -0
  46. package/public/assets/{quadrantDiagram-34T5L4WZ-CqkG9t9_.js → quadrantDiagram-34T5L4WZ-552sDLt-.js} +2 -2
  47. package/public/assets/{requirementDiagram-MS252O5E-D_SkRDmv.js → requirementDiagram-MS252O5E-DNzvM72W.js} +1 -1
  48. package/public/assets/{sankeyDiagram-XADWPNL6-BoQxjHkJ.js → sankeyDiagram-XADWPNL6-DKy6TNHm.js} +6 -6
  49. package/public/assets/{sequenceDiagram-FGHM5R23-BDGOIizo.js → sequenceDiagram-FGHM5R23-BQCY2Zf9.js} +5 -5
  50. package/public/assets/{stateDiagram-FHFEXIEX-SYaFpYZC.js → stateDiagram-FHFEXIEX-D7T4Km3f.js} +1 -1
  51. package/public/assets/stateDiagram-v2-QKLJ7IA2-CYjKpaa0.js +1 -0
  52. package/public/assets/{timeline-definition-GMOUNBTQ-DKLze3x4.js → timeline-definition-GMOUNBTQ-CqlaVFMe.js} +8 -8
  53. package/public/assets/{vennDiagram-DHZGUBPP-SSE-F6n3.js → vennDiagram-DHZGUBPP-D4C7VzEp.js} +5 -5
  54. package/public/assets/{wardley-RL74JXVD-S0ICuT1a.js → wardley-RL74JXVD-BYxilceB.js} +1 -1
  55. package/public/assets/{wardleyDiagram-NUSXRM2D-DMA7ZjAO.js → wardleyDiagram-NUSXRM2D-B5Zztop3.js} +2 -2
  56. package/public/assets/{xychartDiagram-5P7HB3ND-CZZ9juBQ.js → xychartDiagram-5P7HB3ND-CAK4X6lJ.js} +4 -4
  57. package/public/index.html +2 -2
  58. package/dist/server/scaffoldPlugin.js +0 -72
  59. package/dist/server/verifyPlugin.js +0 -235
  60. package/public/assets/DebugDrawer-C-v1B1vW.js +0 -1
  61. package/public/assets/architectureDiagram-Q4EWVU46-Bj_s6upX.js +0 -36
  62. package/public/assets/channel-DLeWkql2.js +0 -1
  63. package/public/assets/chunk-55IACEB6-D5vTVeAc.js +0 -1
  64. package/public/assets/classDiagram-6PBFFD2Q-CVe-3aSj.js +0 -1
  65. package/public/assets/classDiagram-v2-HSJHXN6E-CVe-3aSj.js +0 -1
  66. package/public/assets/clone-Dkncs6zh.js +0 -1
  67. package/public/assets/diagram-5BDNPKRD-DnAM93VO.js +0 -10
  68. package/public/assets/diagram-G4DWMVQ6-CcYjwbKm.js +0 -24
  69. package/public/assets/diagram-MMDJMWI5-B6xlqXbp.js +0 -43
  70. package/public/assets/diagram-TYMM5635-B9ak5QMP.js +0 -24
  71. package/public/assets/gitGraphDiagram-UUTBAWPF-IAJs2Nmr.js +0 -106
  72. package/public/assets/highlighted-body-OFNGDK62-DAnjqfIm.js +0 -1
  73. package/public/assets/index-iIIavXI3.css +0 -1
  74. package/public/assets/pieDiagram-DEJITSTG-CMC6SqWn.js +0 -30
  75. package/public/assets/stateDiagram-v2-QKLJ7IA2-BmucXGxE.js +0 -1
  76. package/templates/front-canonical.tsx +0 -64
  77. package/templates/package-canonical.json +0 -19
  78. package/templates/plugin/README.md +0 -64
  79. package/templates/plugin/package.json +0 -67
  80. package/templates/plugin/src/front/__tests__/samplePlugin.test.ts +0 -53
  81. package/templates/plugin/src/front/index.ts +0 -45
  82. package/templates/plugin/src/front/panels.tsx +0 -8
  83. package/templates/plugin/src/front/surfaceResolver.ts +0 -19
  84. package/templates/plugin/src/server/index.ts +0 -29
  85. package/templates/plugin/src/shared/constants.ts +0 -2
  86. package/templates/plugin/src/shared/index.ts +0 -2
  87. package/templates/plugin/src/shared/types.ts +0 -3
  88. package/templates/plugin/src/test-setup.ts +0 -43
  89. package/templates/plugin/tsconfig.json +0 -23
  90. package/templates/plugin/tsup.config.ts +0 -21
  91. package/templates/plugin/vitest.config.ts +0 -20
  92. package/templates/server-canonical.ts +0 -42
@@ -1,235 +0,0 @@
1
- #!/usr/bin/env node
2
- import { existsSync, readdirSync, readFileSync, realpathSync, statSync } from "node:fs";
3
- import { isAbsolute, join, relative, resolve } from "node:path";
4
- import {
5
- isSafePluginRelativePath,
6
- validateBoringPluginManifest
7
- } from "@hachej/boring-workspace/plugin";
8
- function pluginFileSignature(path) {
9
- if (!path || !existsSync(path)) return "missing";
10
- const stat = statSync(path);
11
- return `${stat.mtimeMs}:${stat.size}`;
12
- }
13
- function readPluginSignatureCache(pluginRootDir) {
14
- const path = join(pluginRootDir, ".boring-signature.json");
15
- if (!existsSync(path)) return null;
16
- let parsed;
17
- try {
18
- parsed = JSON.parse(readFileSync(path, "utf8"));
19
- } catch {
20
- return null;
21
- }
22
- if (!parsed || typeof parsed !== "object") return null;
23
- const obj = parsed;
24
- if (obj.version !== 1) return null;
25
- const sig = obj.serverSignature;
26
- if (sig !== null && typeof sig !== "string") return null;
27
- const loadedAt = typeof obj.loadedAt === "number" ? obj.loadedAt : 0;
28
- return { version: 1, serverSignature: sig, loadedAt };
29
- }
30
- function verifyPlugin(opts) {
31
- const workspaceRoot = resolve(opts.workspaceRoot);
32
- const extensionsDir = join(workspaceRoot, ".pi", "extensions");
33
- if (!existsSync(extensionsDir)) {
34
- return {
35
- outcomes: [],
36
- ok: true,
37
- extensionsDir,
38
- extensionsDirMissing: true
39
- };
40
- }
41
- const targets = [];
42
- if (opts.name) {
43
- const dir = join(extensionsDir, opts.name);
44
- if (!existsSync(dir)) {
45
- return {
46
- outcomes: [
47
- { id: opts.name, dir, ok: false, errors: [`plugin directory not found: ${dir}`], warnings: [] }
48
- ],
49
- ok: false,
50
- extensionsDir,
51
- extensionsDirMissing: false
52
- };
53
- }
54
- targets.push(dir);
55
- } else {
56
- for (const entry of readdirSync(extensionsDir, { withFileTypes: true })) {
57
- if (!entry.isDirectory()) continue;
58
- if (entry.name.startsWith(".") || entry.name.startsWith("preflight-")) continue;
59
- targets.push(join(extensionsDir, entry.name));
60
- }
61
- }
62
- const outcomes = targets.map((dir) => verifySinglePlugin(dir));
63
- return {
64
- outcomes,
65
- ok: outcomes.every((o) => o.ok),
66
- extensionsDir,
67
- extensionsDirMissing: false
68
- };
69
- }
70
- function isInsideRoot(rootReal, targetReal) {
71
- const rel = relative(rootReal, targetReal);
72
- return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
73
- }
74
- function resolveExistingContainedPath(pluginDir, value, field) {
75
- if (!isSafePluginRelativePath(value)) {
76
- return { path: null, error: `${field} must be a safe relative path inside the plugin root: ${JSON.stringify(value)}` };
77
- }
78
- const abs = resolve(pluginDir, value);
79
- if (!existsSync(abs)) return { path: null, error: `${field} points at "${value}" but that file does not exist (looked at ${abs})` };
80
- const rootReal = realpathSync(pluginDir);
81
- const targetReal = realpathSync(abs);
82
- if (!isInsideRoot(rootReal, targetReal)) {
83
- return { path: null, error: `${field} points at "${value}" but resolves outside the plugin root (looked at ${abs})` };
84
- }
85
- return { path: targetReal };
86
- }
87
- function verifySinglePlugin(pluginDir) {
88
- const id = pluginDir.split(/[\\/]/).pop() ?? "<unknown>";
89
- const errors = [];
90
- const warnings = [];
91
- const pkgPath = join(pluginDir, "package.json");
92
- if (!existsSync(pkgPath)) {
93
- return { id, dir: pluginDir, ok: false, errors: ["package.json missing"], warnings };
94
- }
95
- let parsed;
96
- try {
97
- parsed = JSON.parse(readFileSync(pkgPath, "utf8"));
98
- } catch (error) {
99
- const message = error instanceof Error ? error.message : String(error);
100
- return { id, dir: pluginDir, ok: false, errors: [`package.json is not valid JSON: ${message}`], warnings };
101
- }
102
- const result = validateBoringPluginManifest(parsed);
103
- if (!result.valid) {
104
- for (const issue of result.issues) errors.push(formatIssue(issue));
105
- return { id, dir: pluginDir, ok: false, errors, warnings };
106
- }
107
- const manifest = result.packageJson;
108
- const boring = manifest.boring;
109
- if (boring?.front) {
110
- const resolved = resolveExistingContainedPath(pluginDir, boring.front, "boring.front");
111
- if (resolved.error) errors.push(resolved.error);
112
- }
113
- let serverPathAbs = null;
114
- if (typeof boring?.server === "string") {
115
- const resolved = resolveExistingContainedPath(pluginDir, boring.server, "boring.server");
116
- if (resolved.error) {
117
- errors.push(resolved.error);
118
- } else {
119
- serverPathAbs = resolved.path;
120
- warnings.push(
121
- "boring.server file is valid, but workspace server entries are boot-time/static composition only. /reload does not import or register .pi/extensions server routes/agentTools; restart the workspace with this package passed via defaultPluginPackages or explicit plugins to activate server code."
122
- );
123
- }
124
- }
125
- const cache = readPluginSignatureCache(pluginDir);
126
- if (cache) {
127
- const currentServerSig = serverPathAbs ? pluginFileSignature(serverPathAbs) : null;
128
- const cachedSig = cache.serverSignature;
129
- if (cachedSig !== currentServerSig) {
130
- warnings.push(
131
- "server file changed since the workspace last loaded this plugin \u2014 /reload will hot-swap the front, but routes and agent tools stay on the previously loaded code. Stop and restart the workspace process (Ctrl-C, then re-run your dev command) to pick up the new code."
132
- );
133
- }
134
- }
135
- const piExt = manifest.pi?.extensions;
136
- if (Array.isArray(piExt)) {
137
- for (const ext of piExt) {
138
- if (typeof ext !== "string") continue;
139
- const resolved = resolveExistingContainedPath(pluginDir, ext, "pi.extensions entry");
140
- if (resolved.error) errors.push(resolved.error);
141
- }
142
- }
143
- const piSkills = manifest.pi?.skills;
144
- if (Array.isArray(piSkills)) {
145
- for (const skill of piSkills) {
146
- if (typeof skill !== "string") continue;
147
- const resolved = resolveExistingContainedPath(pluginDir, skill, "pi.skills entry");
148
- if (resolved.error) errors.push(resolved.error);
149
- }
150
- }
151
- return { id, dir: pluginDir, ok: errors.length === 0, errors, warnings };
152
- }
153
- function formatIssue(issue) {
154
- return `${issue.code}: ${issue.field}: ${issue.message}`;
155
- }
156
- function formatVerifyResult(result) {
157
- if (result.extensionsDirMissing) {
158
- return [
159
- `WARNING \u2014 no plugins to verify. Scanned: ${result.extensionsDir} (directory does not exist).`,
160
- "",
161
- "If you just wrote a plugin: check that you put it under THIS workspace's `.pi/extensions/` and not a different cwd. The scanned path above is `<cwd>/.pi/extensions/`."
162
- ].join("\n");
163
- }
164
- if (result.outcomes.length === 0) {
165
- return [
166
- `WARNING \u2014 scanned ${result.extensionsDir} but found NO plugin directories.`,
167
- "",
168
- "If you just wrote a plugin: it is NOT in this dir. Either you wrote to a different `.pi/extensions/` (check your cwd), or the dir name starts with `.` / `preflight-` (skipped)."
169
- ].join("\n");
170
- }
171
- const lines = [];
172
- const failures = result.outcomes.filter((o) => !o.ok);
173
- const withWarnings = result.outcomes.filter((o) => o.warnings.length > 0);
174
- if (failures.length === 0) {
175
- lines.push(`OK \u2014 ${result.outcomes.length} plugin(s) have valid manifests + present files. (scanned ${result.extensionsDir})`);
176
- for (const outcome of result.outcomes) {
177
- const tag = outcome.warnings.length > 0 ? "\u26A0" : "\u2713";
178
- lines.push(` ${tag} ${outcome.id}`);
179
- for (const w of outcome.warnings) {
180
- lines.push(` WARN: ${w}`);
181
- }
182
- }
183
- lines.push("");
184
- if (withWarnings.length > 0) {
185
- const n = withWarnings.length;
186
- lines.push(`Manifests are valid, but ${n} plugin${n === 1 ? "" : "s"} need a workspace restart (NOT just /reload) to pick up server-side changes \u2014 see WARN lines above.`);
187
- lines.push("");
188
- }
189
- lines.push("Note: this validator does NOT execute plugin code. Front/Pi syntax / type / runtime errors surface on /reload; boring.server files require static composition plus a process restart.");
190
- } else {
191
- lines.push(`FAILED \u2014 ${failures.length} of ${result.outcomes.length} plugin(s) have errors. (scanned ${result.extensionsDir})`);
192
- lines.push("");
193
- for (const outcome of result.outcomes) {
194
- if (outcome.ok) {
195
- const tag = outcome.warnings.length > 0 ? "\u26A0" : "\u2713";
196
- lines.push(` ${tag} ${outcome.id}`);
197
- for (const w of outcome.warnings) {
198
- lines.push(` WARN: ${w}`);
199
- }
200
- } else {
201
- lines.push(` \u2717 ${outcome.id} (${outcome.dir})`);
202
- for (const err of outcome.errors) {
203
- lines.push(` ${err}`);
204
- }
205
- for (const w of outcome.warnings) {
206
- lines.push(` WARN: ${w}`);
207
- }
208
- }
209
- }
210
- lines.push("");
211
- lines.push("Fix the errors above and run `boring-ui verify-plugin` again. Once it reports OK, ask the user to run /reload for front/Pi assets; boring.server changes require static composition plus restart.");
212
- }
213
- return lines.join("\n");
214
- }
215
- const COMMON_MISTAKE_HINTS = [
216
- {
217
- pattern: /boring\.server must be a safe relative path or false/i,
218
- hint: 'Set `boring.server` to a string path like "server/index.ts", or to `false` (or omit the field). It is NOT a boolean true. For hot-reloadable agent behavior in .pi/extensions, prefer pi.extensions instead.'
219
- },
220
- {
221
- pattern: /package\.json manifest must be an object/i,
222
- hint: "package.json must parse as a JSON object \u2014 check for trailing commas or unquoted keys."
223
- }
224
- ];
225
- function findHintForError(message) {
226
- for (const m of COMMON_MISTAKE_HINTS) {
227
- if (m.pattern.test(message)) return m.hint;
228
- }
229
- return void 0;
230
- }
231
- export {
232
- findHintForError,
233
- formatVerifyResult,
234
- verifyPlugin
235
- };
@@ -1 +0,0 @@
1
- import{r as d,j as e,T as N,a as y,b as T,c as b,d as k,I as w,R as S,B as C,C as R,e as E,f as M,g as I}from"./index-CtdAhKdF.js";function D({value:o,label:s}){const[n,t]=d.useState(!1),l=d.useCallback(()=>{var r,i;const x=(i=(r=navigator.clipboard)==null?void 0:r.writeText)==null?void 0:i.bind(navigator.clipboard);x&&x(o).then(()=>{t(!0),window.setTimeout(()=>t(!1),1200)})},[o]);return e.jsx(w,{type:"button",variant:"ghost",size:"icon-xs",onClick:l,className:"text-muted-foreground/60","aria-label":s,title:s,children:n?e.jsx(M,{className:"h-3 w-3"}):e.jsx(I,{className:"h-3 w-3"})})}function j({label:o,value:s}){return e.jsxs("div",{className:"rounded-md border border-border/40 bg-muted/20 p-2",children:[e.jsxs("div",{className:"mb-1 flex items-center justify-between gap-2",children:[e.jsx("span",{className:"text-[10px] font-medium uppercase tracking-[0.16em] text-muted-foreground/80",children:o}),e.jsx(D,{value:s,label:`Copy ${o}`})]}),e.jsx("code",{className:"block break-all font-mono text-[11px] leading-relaxed text-foreground dark:text-zinc-100",children:s})]})}function $({sessionId:o}){const s=`pi --session ${o}`;return e.jsxs("div",{className:"flex flex-col gap-3 overflow-auto p-3 text-[11px] text-muted-foreground dark:text-zinc-300",children:[e.jsx("p",{className:"text-muted-foreground dark:text-zinc-300",children:"This web chat is backed by a pi session. Use the id below from the workspace root to resume the same conversation in a terminal."}),e.jsx(j,{label:"Pi session id",value:o}),e.jsx(j,{label:"Resume command",value:s}),e.jsxs("p",{className:"rounded-md border border-border/30 bg-muted/10 p-2 text-[10px] leading-relaxed text-muted-foreground/75 dark:text-zinc-300",children:["Tip: ",e.jsx("code",{className:"font-mono text-foreground/80",children:"pi --continue"})," ","opens the most recent session for the current working directory. The explicit command above targets this session directly."]})]})}const _=2500,v=20;function L({sessionId:o,requestHeaders:s}){const[n,t]=d.useState({kind:"loading"}),[l,x]=d.useState(0),r=d.useRef(0),i=d.useCallback(()=>{r.current=0,x(a=>a+1)},[]);return d.useEffect(()=>{let a=!1,m=null;t({kind:"loading"});const g=s?{headers:s}:void 0;return fetch(`/api/v1/agent/sessions/${encodeURIComponent(o)}/system-prompt`,g).then(async c=>{var f;if(a)return;if(c.ok){const h=await c.json();if(typeof h.systemPrompt=="string"){r.current=0,t({kind:"ok",text:h.systemPrompt});return}}const u=await c.json().catch(()=>null),p=((f=u==null?void 0:u.error)==null?void 0:f.message)??`HTTP ${c.status}`;c.status===404&&r.current<v?(t({kind:"empty",reason:p}),m=setTimeout(()=>{a||(r.current++,x(h=>h+1))},_)):t(c.status===404?{kind:"empty",reason:p}:{kind:"error",reason:p})}).catch(c=>{a||t({kind:"error",reason:c instanceof Error?c.message:String(c)})}),()=>{a=!0,m&&clearTimeout(m)}},[o,s,l]),e.jsxs("div",{className:"flex flex-col h-full min-h-0",children:[e.jsxs("div",{className:"shrink-0 flex items-center justify-between px-3 pt-2 pb-1 border-b border-border/40",children:[e.jsx("span",{className:"text-[10px] text-muted-foreground/80 font-mono",children:n.kind==="ok"?`${n.text.length.toLocaleString()} chars`:n.kind==="loading"?"loading…":n.kind==="empty"?`waiting for session · retry ${r.current}/${v}`:"error"}),n.kind!=="loading"&&e.jsx(w,{type:"button",variant:"ghost",size:"icon-xs",onClick:i,className:"text-muted-foreground/60","aria-label":"Refresh system prompt",children:e.jsx(S,{className:"h-3 w-3"})})]}),(n.kind==="loading"||n.kind==="empty")&&e.jsx("p",{className:"text-[11px] text-muted-foreground p-3",children:n.kind==="loading"?"Loading…":n.reason}),n.kind==="error"&&e.jsx("p",{className:"text-[11px] text-destructive p-3",children:n.reason}),n.kind==="ok"&&e.jsx("pre",{className:"flex-1 overflow-auto px-3 py-2 font-mono text-[11px] leading-relaxed text-foreground whitespace-pre-wrap break-words",children:n.text})]})}function z(o){const s=o,n=(s==null?void 0:s.type)??"?";if(n==="text"){const t=String(s.text??"");return t.slice(0,80)+(t.length>80?"…":"")}if(n==="tool-invocation"){const t=s.toolInvocation,l=String((t==null?void 0:t.state)??"");return`${(t==null?void 0:t.toolName)??"?"}() · ${l}`}if(n==="reasoning"){const t=String(s.text??s.reasoning??"");return t.slice(0,80)+(t.length>80?"…":"")}return n}function A(o){const s=[];for(let n=0;n<o.length;n++){const t=o[n],l=t,x=l.createdAt?new Date(l.createdAt).toISOString().slice(11,23):null;for(let r=0;r<t.parts.length;r++){const i=t.parts[r];s.push({msgId:t.id,msgIndex:n,role:t.role,time:x,partIndex:r,partType:(i==null?void 0:i.type)??"unknown",part:i})}}return s}function B({messages:o}){const s=A(o),[n,t]=d.useState(null),l=d.useRef(null),x=d.useRef(s.length);return d.useEffect(()=>{var r;s.length!==x.current&&((r=l.current)==null||r.scrollIntoView({behavior:"smooth"}),x.current=s.length)},[s.length]),s.length===0?e.jsx("p",{className:"text-[11px] text-muted-foreground p-3",children:"No messages yet."}):e.jsxs("div",{className:"flex flex-col h-full min-h-0",children:[e.jsxs("div",{className:"shrink-0 px-3 pt-2 pb-1 text-[10px] text-muted-foreground/80 font-mono border-b border-border/40",children:[o.length," msg · ",s.length," parts"]}),e.jsxs("div",{className:"flex-1 overflow-auto",children:[s.map(r=>{const i=`${r.msgId}:${r.partIndex}`,a=n===i;return e.jsxs("div",{className:"border-b border-border/30 last:border-0",children:[e.jsxs(C,{type:"button",variant:"ghost",onClick:()=>t(a?null:i),className:"h-auto w-full justify-start gap-1.5 rounded-none px-2 py-1.5 text-left",children:[e.jsx("span",{className:"mt-0.5 shrink-0 text-muted-foreground/40",children:a?e.jsx(R,{className:"h-3 w-3"}):e.jsx(E,{className:"h-3 w-3"})}),e.jsx("span",{className:"font-mono text-[10px] shrink-0 w-20",children:r.time?e.jsx("span",{className:"text-muted-foreground/60",children:r.time}):e.jsxs("span",{className:"text-muted-foreground/30",children:["m",r.msgIndex]})}),e.jsx("span",{className:k("shrink-0 font-mono text-[10px] w-14",r.role==="user"?"text-accent":"text-muted-foreground"),children:r.role}),e.jsx("span",{className:"shrink-0 font-mono text-[10px] text-muted-foreground/60 w-24",children:r.partType}),e.jsx("span",{className:"flex-1 min-w-0 font-mono text-[11px] text-foreground truncate",children:z(r.part)})]}),a&&e.jsx("pre",{className:"px-3 pb-2 font-mono text-[10px] leading-relaxed text-foreground/80 whitespace-pre-wrap break-words bg-muted/20",children:JSON.stringify(r.part,null,2)})]},i)}),e.jsx("div",{ref:l})]})]})}const P=[{id:"session",label:"Session"},{id:"prompt",label:"System prompt"},{id:"messages",label:"Messages"}],X=280,U=800;function K({sessionId:o,messages:s,requestHeaders:n,width:t,onWidthChange:l}){const[x,r]=d.useState("session"),i=d.useCallback(a=>{a.preventDefault();const m=a.clientX,g=t,c=p=>{const f=m-p.clientX;l(Math.min(U,Math.max(X,g+f)))},u=()=>{window.removeEventListener("mousemove",c),window.removeEventListener("mouseup",u)};window.addEventListener("mousemove",c),window.addEventListener("mouseup",u)},[t,l]);return e.jsxs(e.Fragment,{children:[e.jsx("div",{onMouseDown:i,className:"w-1 shrink-0 cursor-col-resize hover:bg-accent/40 active:bg-accent/60 transition-colors","aria-hidden":!0}),e.jsx("aside",{style:{width:t},className:k("flex h-full shrink-0 flex-col border-l border-border/60","bg-[oklch(from_var(--background)_calc(l-0.01)_c_h)]"),children:e.jsxs(N,{value:x,onValueChange:a=>r(a),className:"flex flex-col flex-1 min-h-0 overflow-hidden",children:[e.jsx("header",{className:"flex shrink-0 items-center gap-0 border-b border-border/60 px-1",children:e.jsx(y,{variant:"line",className:"h-auto gap-0 p-0 w-full",children:P.map(({id:a,label:m})=>e.jsx(T,{value:a,className:"h-8 flex-none px-3 py-2 text-[11px] font-medium data-[state=active]:after:bg-[color:var(--accent)]",children:m},a))})}),e.jsx(b,{value:"session",forceMount:!0,className:"flex flex-col flex-1 min-h-0 overflow-hidden data-[state=inactive]:hidden",children:e.jsx($,{sessionId:o})}),e.jsx(b,{value:"prompt",forceMount:!0,className:"flex flex-col flex-1 min-h-0 overflow-hidden data-[state=inactive]:hidden",children:e.jsx(L,{sessionId:o,requestHeaders:n})}),e.jsx(b,{value:"messages",forceMount:!0,className:"flex flex-col flex-1 min-h-0 overflow-hidden data-[state=inactive]:hidden",children:e.jsx(B,{messages:s})})]})})]})}export{K as DebugDrawer};