@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.
- package/README.md +7 -4
- package/dist/server/cli.js +35 -233
- package/dist/server/pluginFrontRuntime.js +183 -23
- package/package.json +7 -6
- package/public/assets/DebugDrawer-DB9C3tZz.js +1 -0
- package/public/assets/{_baseUniq-2WvYsyyQ.js → _baseUniq-BHrtLO8W.js} +1 -1
- package/public/assets/{arc-BfQMEcaD.js → arc-BTJHwuiF.js} +1 -1
- package/public/assets/architectureDiagram-Q4EWVU46-CJMeSZx6.js +36 -0
- package/public/assets/{blockDiagram-DXYQGD6D-BwO0KFc4.js → blockDiagram-DXYQGD6D-D_iRmbs0.js} +5 -5
- package/public/assets/{c4Diagram-AHTNJAMY-3ZfOXc8v.js → c4Diagram-AHTNJAMY-DqJK-oCk.js} +1 -1
- package/public/assets/channel-t1oMFJWT.js +1 -0
- package/public/assets/{chunk-4BX2VUAB-CRl1YiJJ.js → chunk-4BX2VUAB-DBqhw0eR.js} +1 -1
- package/public/assets/{chunk-4TB4RGXK-DrpTwphl.js → chunk-4TB4RGXK-BEbQ9ff5.js} +2 -2
- package/public/assets/chunk-55IACEB6-sdAV4otZ.js +1 -0
- package/public/assets/{chunk-EDXVE4YY-BC7-AFdu.js → chunk-EDXVE4YY-BGeNOj7f.js} +1 -1
- package/public/assets/{chunk-FMBD7UC4-DsK26d_T.js → chunk-FMBD7UC4-DwD_gBy0.js} +1 -1
- package/public/assets/{chunk-OYMX7WX6-BeikaWZm.js → chunk-OYMX7WX6-CjMCkDF3.js} +1 -1
- package/public/assets/{chunk-QZHKN3VN-BwxHokKH.js → chunk-QZHKN3VN-Cot2XaAR.js} +1 -1
- package/public/assets/{chunk-YZCP3GAM-BbZ8wRWB.js → chunk-YZCP3GAM-CGX-4Jvn.js} +1 -1
- package/public/assets/classDiagram-6PBFFD2Q-BgSBQBOf.js +1 -0
- package/public/assets/classDiagram-v2-HSJHXN6E-BgSBQBOf.js +1 -0
- package/public/assets/clone-BBHYjbBI.js +1 -0
- package/public/assets/{cose-bilkent-S5V4N54A-C3HWuNVz.js → cose-bilkent-S5V4N54A-CDntEO8X.js} +1 -1
- package/public/assets/{dagre-KV5264BT-DOVky5l9.js → dagre-KV5264BT-ZOVUZI--.js} +2 -2
- package/public/assets/diagram-5BDNPKRD-LdjTY2br.js +10 -0
- package/public/assets/diagram-G4DWMVQ6-BWxGregh.js +24 -0
- package/public/assets/diagram-MMDJMWI5-CxtOYZMd.js +43 -0
- package/public/assets/diagram-TYMM5635-ChD56z2q.js +24 -0
- package/public/assets/{erDiagram-SMLLAGMA-wZ_XblND.js → erDiagram-SMLLAGMA-B8zSJysM.js} +2 -2
- package/public/assets/{flowDiagram-DWJPFMVM-of3iiuJI.js → flowDiagram-DWJPFMVM-Dqqy7UJT.js} +1 -1
- package/public/assets/{ganttDiagram-T4ZO3ILL-CiIxc0v4.js → ganttDiagram-T4ZO3ILL-Dn_EJlMH.js} +1 -1
- package/public/assets/gitGraphDiagram-UUTBAWPF-BVuaJiec.js +106 -0
- package/public/assets/{graph-CandW0gD.js → graph-Dj5mmSf2.js} +1 -1
- package/public/assets/highlighted-body-OFNGDK62-Cn9lWz0x.js +1 -0
- package/public/assets/index-Ciaf_ynY.css +1 -0
- package/public/assets/{index-CtdAhKdF.js → index-CrmEpxcy.js} +423 -398
- package/public/assets/{infoDiagram-42DDH7IO-B4MJKAr8.js → infoDiagram-42DDH7IO-DawFXMLo.js} +1 -1
- package/public/assets/{ishikawaDiagram-UXIWVN3A-Bl2J6bvs.js → ishikawaDiagram-UXIWVN3A-DBxt-riO.js} +4 -4
- package/public/assets/{journeyDiagram-VCZTEJTY-JYysqMwv.js → journeyDiagram-VCZTEJTY-D50mNLlL.js} +4 -4
- package/public/assets/{kanban-definition-6JOO6SKY-B0wB13fQ.js → kanban-definition-6JOO6SKY-CFBUjJCs.js} +6 -6
- package/public/assets/{layout-DYl8UnAo.js → layout-DEdejLi9.js} +1 -1
- package/public/assets/{linear-Dj3asvOm.js → linear-BXKtVmEh.js} +1 -1
- package/public/assets/{min-Cbw7dpzS.js → min-DY1T79Si.js} +1 -1
- package/public/assets/{mindmap-definition-QFDTVHPH-DLl-2gHB.js → mindmap-definition-QFDTVHPH-DbCBDJgc.js} +9 -9
- package/public/assets/pieDiagram-DEJITSTG-DYgefMzu.js +30 -0
- package/public/assets/{quadrantDiagram-34T5L4WZ-CqkG9t9_.js → quadrantDiagram-34T5L4WZ-552sDLt-.js} +2 -2
- package/public/assets/{requirementDiagram-MS252O5E-D_SkRDmv.js → requirementDiagram-MS252O5E-DNzvM72W.js} +1 -1
- package/public/assets/{sankeyDiagram-XADWPNL6-BoQxjHkJ.js → sankeyDiagram-XADWPNL6-DKy6TNHm.js} +6 -6
- package/public/assets/{sequenceDiagram-FGHM5R23-BDGOIizo.js → sequenceDiagram-FGHM5R23-BQCY2Zf9.js} +5 -5
- package/public/assets/{stateDiagram-FHFEXIEX-SYaFpYZC.js → stateDiagram-FHFEXIEX-D7T4Km3f.js} +1 -1
- package/public/assets/stateDiagram-v2-QKLJ7IA2-CYjKpaa0.js +1 -0
- package/public/assets/{timeline-definition-GMOUNBTQ-DKLze3x4.js → timeline-definition-GMOUNBTQ-CqlaVFMe.js} +8 -8
- package/public/assets/{vennDiagram-DHZGUBPP-SSE-F6n3.js → vennDiagram-DHZGUBPP-D4C7VzEp.js} +5 -5
- package/public/assets/{wardley-RL74JXVD-S0ICuT1a.js → wardley-RL74JXVD-BYxilceB.js} +1 -1
- package/public/assets/{wardleyDiagram-NUSXRM2D-DMA7ZjAO.js → wardleyDiagram-NUSXRM2D-B5Zztop3.js} +2 -2
- package/public/assets/{xychartDiagram-5P7HB3ND-CZZ9juBQ.js → xychartDiagram-5P7HB3ND-CAK4X6lJ.js} +4 -4
- package/public/index.html +2 -2
- package/dist/server/scaffoldPlugin.js +0 -72
- package/dist/server/verifyPlugin.js +0 -235
- package/public/assets/DebugDrawer-C-v1B1vW.js +0 -1
- package/public/assets/architectureDiagram-Q4EWVU46-Bj_s6upX.js +0 -36
- package/public/assets/channel-DLeWkql2.js +0 -1
- package/public/assets/chunk-55IACEB6-D5vTVeAc.js +0 -1
- package/public/assets/classDiagram-6PBFFD2Q-CVe-3aSj.js +0 -1
- package/public/assets/classDiagram-v2-HSJHXN6E-CVe-3aSj.js +0 -1
- package/public/assets/clone-Dkncs6zh.js +0 -1
- package/public/assets/diagram-5BDNPKRD-DnAM93VO.js +0 -10
- package/public/assets/diagram-G4DWMVQ6-CcYjwbKm.js +0 -24
- package/public/assets/diagram-MMDJMWI5-B6xlqXbp.js +0 -43
- package/public/assets/diagram-TYMM5635-B9ak5QMP.js +0 -24
- package/public/assets/gitGraphDiagram-UUTBAWPF-IAJs2Nmr.js +0 -106
- package/public/assets/highlighted-body-OFNGDK62-DAnjqfIm.js +0 -1
- package/public/assets/index-iIIavXI3.css +0 -1
- package/public/assets/pieDiagram-DEJITSTG-CMC6SqWn.js +0 -30
- package/public/assets/stateDiagram-v2-QKLJ7IA2-BmucXGxE.js +0 -1
- package/templates/front-canonical.tsx +0 -64
- package/templates/package-canonical.json +0 -19
- package/templates/plugin/README.md +0 -64
- package/templates/plugin/package.json +0 -67
- package/templates/plugin/src/front/__tests__/samplePlugin.test.ts +0 -53
- package/templates/plugin/src/front/index.ts +0 -45
- package/templates/plugin/src/front/panels.tsx +0 -8
- package/templates/plugin/src/front/surfaceResolver.ts +0 -19
- package/templates/plugin/src/server/index.ts +0 -29
- package/templates/plugin/src/shared/constants.ts +0 -2
- package/templates/plugin/src/shared/index.ts +0 -2
- package/templates/plugin/src/shared/types.ts +0 -3
- package/templates/plugin/src/test-setup.ts +0 -43
- package/templates/plugin/tsconfig.json +0 -23
- package/templates/plugin/tsup.config.ts +0 -21
- package/templates/plugin/vitest.config.ts +0 -20
- package/templates/server-canonical.ts +0 -42
package/README.md
CHANGED
|
@@ -92,14 +92,17 @@ pnpm --filter @hachej/boring-ui-cli build
|
|
|
92
92
|
npx ./packages/cli/dist/index.js
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
-
###
|
|
95
|
+
### Plugins
|
|
96
|
+
|
|
97
|
+
Plugin authoring operations live in the dedicated plugin CLI:
|
|
96
98
|
|
|
97
99
|
```bash
|
|
98
|
-
boring-ui
|
|
100
|
+
boring-ui-plugin create my-package-plugin --path plugins
|
|
101
|
+
boring-ui-plugin scaffold my-runtime-plugin "$BORING_AGENT_WORKSPACE_ROOT"
|
|
102
|
+
boring-ui-plugin verify my-runtime-plugin "$BORING_AGENT_WORKSPACE_ROOT"
|
|
103
|
+
boring-ui-plugin test my-runtime-plugin
|
|
99
104
|
```
|
|
100
105
|
|
|
101
|
-
This copies the bundled plugin template from `templates/plugin/`, renames the sample identifiers, and creates `plugins/my-plugin`.
|
|
102
|
-
|
|
103
106
|
---
|
|
104
107
|
|
|
105
108
|
## Authentication
|
package/dist/server/cli.js
CHANGED
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { execSync } from "node:child_process";
|
|
3
3
|
import {
|
|
4
|
-
cpSync,
|
|
5
4
|
existsSync,
|
|
6
|
-
|
|
7
|
-
readdirSync,
|
|
8
|
-
readFileSync,
|
|
9
|
-
renameSync,
|
|
10
|
-
statSync,
|
|
11
|
-
writeFileSync
|
|
5
|
+
readFileSync
|
|
12
6
|
} from "node:fs";
|
|
13
7
|
import { createRequire } from "node:module";
|
|
14
|
-
import { basename, dirname, isAbsolute, join,
|
|
8
|
+
import { basename, dirname, isAbsolute, join, resolve } from "node:path";
|
|
15
9
|
import { fileURLToPath } from "node:url";
|
|
16
10
|
import { parseArgs } from "node:util";
|
|
17
11
|
import { createLocalWorkspaceRegistry } from "./localWorkspaces.js";
|
|
@@ -27,7 +21,7 @@ const MODE_MAP = {
|
|
|
27
21
|
// bwrap isolated, no network (Linux only)
|
|
28
22
|
};
|
|
29
23
|
const require2 = createRequire(import.meta.url);
|
|
30
|
-
const
|
|
24
|
+
const PLUGIN_CLI_PACKAGE_NAME = "@hachej/boring-ui-plugin-cli";
|
|
31
25
|
const CLI_VERSION = (() => {
|
|
32
26
|
try {
|
|
33
27
|
const pkg = require2("../../package.json");
|
|
@@ -81,16 +75,30 @@ function resolveBoringUiCliPackageRoot() {
|
|
|
81
75
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
82
76
|
return resolve(__dirname, "..", "..");
|
|
83
77
|
}
|
|
84
|
-
function
|
|
78
|
+
function isUsableBoringUiPluginCliPackageRoot(candidate) {
|
|
79
|
+
try {
|
|
80
|
+
const pkg = JSON.parse(readFileSync(join(candidate, "package.json"), "utf8"));
|
|
81
|
+
return pkg.name === PLUGIN_CLI_PACKAGE_NAME && existsSync(join(candidate, "dist", "bin.js"));
|
|
82
|
+
} catch {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function resolveBoringUiPluginCliPackageRoot() {
|
|
87
|
+
const cliRoot = resolveBoringUiCliPackageRoot();
|
|
88
|
+
const candidate = resolve(cliRoot, "..", "plugin-cli");
|
|
89
|
+
return isUsableBoringUiPluginCliPackageRoot(candidate) ? candidate : null;
|
|
90
|
+
}
|
|
91
|
+
function createBoringUiCliRuntimePlugin() {
|
|
92
|
+
const useLocal = process.env.BORING_USE_LOCAL_PACKAGES === "1";
|
|
93
|
+
const packageRoot = useLocal ? resolveBoringUiPluginCliPackageRoot() : null;
|
|
85
94
|
return {
|
|
86
|
-
id: "boring-ui-cli-runtime",
|
|
95
|
+
id: "boring-ui-plugin-cli-runtime",
|
|
87
96
|
provisioning: {
|
|
88
97
|
nodePackages: [{
|
|
89
|
-
id: "boring-ui-cli",
|
|
90
|
-
packageName:
|
|
91
|
-
packageRoot,
|
|
92
|
-
|
|
93
|
-
expectedBins: ["boring-ui"]
|
|
98
|
+
id: "boring-ui-plugin-cli",
|
|
99
|
+
packageName: PLUGIN_CLI_PACKAGE_NAME,
|
|
100
|
+
...packageRoot ? { packageRoot } : { version: CLI_VERSION },
|
|
101
|
+
expectedBins: ["boring-ui-plugin"]
|
|
94
102
|
}]
|
|
95
103
|
}
|
|
96
104
|
};
|
|
@@ -124,6 +132,8 @@ function ensureFrontendBuilt(publicDir) {
|
|
|
124
132
|
}
|
|
125
133
|
async function registerStatic(app, publicDir) {
|
|
126
134
|
ensureFrontendBuilt(publicDir);
|
|
135
|
+
const { default: fastifyCompress } = await import("@fastify/compress");
|
|
136
|
+
await app.register(fastifyCompress, { global: true, encodings: ["br", "gzip"], threshold: 1024 });
|
|
127
137
|
const { default: fastifyStatic } = await import("@fastify/static");
|
|
128
138
|
await app.register(fastifyStatic, {
|
|
129
139
|
root: publicDir,
|
|
@@ -142,10 +152,6 @@ const HELP_TEXT = [
|
|
|
142
152
|
"Commands:",
|
|
143
153
|
" boring-ui [workspace] Start the workspace UI for a folder",
|
|
144
154
|
" boring-ui workspaces <subcommand> Manage saved local workspaces",
|
|
145
|
-
" boring-ui scaffold-plugin <name> [workspace]",
|
|
146
|
-
" Scaffold a hot-reloadable plugin",
|
|
147
|
-
" boring-ui verify-plugin [name] [workspace]",
|
|
148
|
-
" Validate plugin manifests/files",
|
|
149
155
|
"",
|
|
150
156
|
"Options:",
|
|
151
157
|
" -p, --port <port> HTTP port (default: 5200)",
|
|
@@ -327,6 +333,7 @@ async function createFolderModeApp(opts) {
|
|
|
327
333
|
});
|
|
328
334
|
});
|
|
329
335
|
app.get("/api/v1/workspace/meta", async () => ({
|
|
336
|
+
workspaceId: "default",
|
|
330
337
|
workspaceRoot,
|
|
331
338
|
projectName,
|
|
332
339
|
version: CLI_VERSION,
|
|
@@ -547,6 +554,7 @@ async function createWorkspacesModeApp(opts) {
|
|
|
547
554
|
]
|
|
548
555
|
});
|
|
549
556
|
await app.register(workspaceServer.uiRoutes, {
|
|
557
|
+
getWorkspaceId: async (request) => (await workspaceFromRequest(request)).id,
|
|
550
558
|
getBridge: async (request) => getBridge((await workspaceFromRequest(request)).id)
|
|
551
559
|
});
|
|
552
560
|
app.get("/api/v1/runtime-plugin-diagnostics", async (request) => {
|
|
@@ -674,109 +682,6 @@ async function startWorkspacesMode(opts) {
|
|
|
674
682
|
if (await checkAuth() === 0) console.log(AUTH_GUIDE);
|
|
675
683
|
openBrowser(initialUrl);
|
|
676
684
|
}
|
|
677
|
-
function findRepoRoot(from) {
|
|
678
|
-
let current = from;
|
|
679
|
-
while (true) {
|
|
680
|
-
if (existsSync(join(current, "pnpm-workspace.yaml"))) return current;
|
|
681
|
-
const parent = dirname(current);
|
|
682
|
-
if (parent === current) return null;
|
|
683
|
-
current = parent;
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
function walkDir(dir, base, out = []) {
|
|
687
|
-
for (const entry of readdirSync(dir)) {
|
|
688
|
-
if (entry === "node_modules" || entry === ".git" || entry === "dist") continue;
|
|
689
|
-
const fullPath = join(dir, entry);
|
|
690
|
-
const stat = statSync(fullPath);
|
|
691
|
-
if (stat.isDirectory()) {
|
|
692
|
-
walkDir(fullPath, base, out);
|
|
693
|
-
continue;
|
|
694
|
-
}
|
|
695
|
-
out.push(relative(base, fullPath));
|
|
696
|
-
}
|
|
697
|
-
return out;
|
|
698
|
-
}
|
|
699
|
-
function replaceInFile(filePath, replacements) {
|
|
700
|
-
let content = readFileSync(filePath, "utf8");
|
|
701
|
-
for (const [from, to] of Object.entries(replacements)) {
|
|
702
|
-
content = content.replaceAll(from, to);
|
|
703
|
-
}
|
|
704
|
-
writeFileSync(filePath, content, "utf8");
|
|
705
|
-
}
|
|
706
|
-
async function handlePluginCommand(opts) {
|
|
707
|
-
const subcommand = opts.positionals[1];
|
|
708
|
-
if (subcommand !== "create") {
|
|
709
|
-
console.log("Usage: boring-ui plugin create <name> [--path <dir>]");
|
|
710
|
-
console.log("");
|
|
711
|
-
console.log("Scaffold a new plugin from the template.");
|
|
712
|
-
console.log("");
|
|
713
|
-
console.log("Arguments:");
|
|
714
|
-
console.log(" <name> Plugin name (e.g. my-plugin)");
|
|
715
|
-
console.log(" --path Parent directory for the new plugin (default: plugins/)");
|
|
716
|
-
return;
|
|
717
|
-
}
|
|
718
|
-
const name = opts.positionals[2];
|
|
719
|
-
if (!name) throw new Error("usage: boring-ui plugin create <name>");
|
|
720
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
721
|
-
const packageRoot = resolve(__dirname, "..", "..");
|
|
722
|
-
const templateDir = join(packageRoot, "templates", "plugin");
|
|
723
|
-
if (!existsSync(templateDir)) {
|
|
724
|
-
throw new Error(
|
|
725
|
-
`Plugin template not found at ${templateDir}.
|
|
726
|
-
This build may not include the plugin template.`
|
|
727
|
-
);
|
|
728
|
-
}
|
|
729
|
-
const repoRoot = findRepoRoot(process.cwd());
|
|
730
|
-
const customPath = opts.args.path;
|
|
731
|
-
const targetParent = customPath ? resolve(customPath) : join(repoRoot ?? process.cwd(), "plugins");
|
|
732
|
-
const targetDir = join(targetParent, name);
|
|
733
|
-
if (existsSync(targetDir)) {
|
|
734
|
-
throw new Error(`Directory already exists: ${targetDir}`);
|
|
735
|
-
}
|
|
736
|
-
const id = name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/^-+|-+$/g, "");
|
|
737
|
-
if (!id) throw new Error(`invalid plugin name: ${name}`);
|
|
738
|
-
const symbolBase = id.replace(/-plugin$/, "") || id;
|
|
739
|
-
const pascalBase = symbolBase.split(/[-_]+/).map((seg) => seg.charAt(0).toUpperCase() + seg.slice(1)).join("");
|
|
740
|
-
const camelBase = pascalBase.charAt(0).toLowerCase() + pascalBase.slice(1);
|
|
741
|
-
const upperBase = symbolBase.replace(/-/g, "_").toUpperCase();
|
|
742
|
-
console.log(`Scaffolding plugin "${id}" at ${targetDir}`);
|
|
743
|
-
mkdirSync(targetParent, { recursive: true });
|
|
744
|
-
cpSync(templateDir, targetDir, { recursive: true });
|
|
745
|
-
const files = walkDir(targetDir, targetDir);
|
|
746
|
-
const pkgName = `@hachej/boring-${id}`;
|
|
747
|
-
for (const file of files) {
|
|
748
|
-
const fullPath = join(targetDir, file);
|
|
749
|
-
replaceInFile(fullPath, {
|
|
750
|
-
"@hachej/boring-plugin-template": pkgName,
|
|
751
|
-
"sample-plugin": id,
|
|
752
|
-
"sample-panel": `${id}-panel`,
|
|
753
|
-
"sample.open": `${id}.open`,
|
|
754
|
-
"sample:": `${id}:`,
|
|
755
|
-
'"sample"': `"${id}"`,
|
|
756
|
-
"SAMPLE": upperBase,
|
|
757
|
-
"Sample": pascalBase,
|
|
758
|
-
"sampleSurfaceResolver": `${camelBase}SurfaceResolver`,
|
|
759
|
-
"samplePanel": `${camelBase}Panel`
|
|
760
|
-
});
|
|
761
|
-
if (file.includes("samplePlugin")) {
|
|
762
|
-
const newFile = file.replace(/samplePlugin/g, `${camelBase}Plugin`);
|
|
763
|
-
const oldPath = join(targetDir, file);
|
|
764
|
-
const newPath = join(targetDir, newFile);
|
|
765
|
-
if (oldPath !== newPath) {
|
|
766
|
-
mkdirSync(dirname(newPath), { recursive: true });
|
|
767
|
-
renameSync(oldPath, newPath);
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
console.log("");
|
|
772
|
-
console.log(`\u2713 Created plugin \`${id}\` at ${relative(process.cwd(), targetDir)}`);
|
|
773
|
-
console.log("");
|
|
774
|
-
console.log("Next steps:");
|
|
775
|
-
console.log(` cd ${relative(process.cwd(), targetDir)}`);
|
|
776
|
-
console.log(" pnpm install");
|
|
777
|
-
console.log(` pnpm --filter ${pkgName} typecheck`);
|
|
778
|
-
console.log(` pnpm --filter ${pkgName} test`);
|
|
779
|
-
}
|
|
780
685
|
async function handleWorkspacesCommand(opts) {
|
|
781
686
|
const registry = createLocalWorkspaceRegistry();
|
|
782
687
|
const subcommand = opts.positionals[1];
|
|
@@ -828,6 +733,10 @@ async function runCli(options) {
|
|
|
828
733
|
name: { type: "string", short: "n" },
|
|
829
734
|
path: { type: "string" },
|
|
830
735
|
json: { type: "boolean" },
|
|
736
|
+
url: { type: "string" },
|
|
737
|
+
workspace: { type: "string" },
|
|
738
|
+
"panel-id": { type: "string" },
|
|
739
|
+
"timeout-ms": { type: "string" },
|
|
831
740
|
help: { type: "boolean", short: "h" }
|
|
832
741
|
},
|
|
833
742
|
allowPositionals: true,
|
|
@@ -849,15 +758,8 @@ async function runCli(options) {
|
|
|
849
758
|
cliMode = rawMode;
|
|
850
759
|
mode = MODE_MAP[cliMode];
|
|
851
760
|
} else {
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
if (detected === "local") {
|
|
855
|
-
cliMode = "local-sandbox";
|
|
856
|
-
mode = "local";
|
|
857
|
-
} else {
|
|
858
|
-
cliMode = "local";
|
|
859
|
-
mode = "direct";
|
|
860
|
-
}
|
|
761
|
+
cliMode = "local";
|
|
762
|
+
mode = "direct";
|
|
861
763
|
}
|
|
862
764
|
const base = {
|
|
863
765
|
publicDir: options.publicDir,
|
|
@@ -866,13 +768,6 @@ async function runCli(options) {
|
|
|
866
768
|
cliMode,
|
|
867
769
|
mode
|
|
868
770
|
};
|
|
869
|
-
if (positionals[0] === "plugin") {
|
|
870
|
-
await handlePluginCommand({
|
|
871
|
-
positionals,
|
|
872
|
-
args: { path: args.path }
|
|
873
|
-
});
|
|
874
|
-
return;
|
|
875
|
-
}
|
|
876
771
|
if (positionals[0] === "workspaces") {
|
|
877
772
|
await handleWorkspacesCommand({
|
|
878
773
|
...base,
|
|
@@ -881,105 +776,11 @@ async function runCli(options) {
|
|
|
881
776
|
});
|
|
882
777
|
return;
|
|
883
778
|
}
|
|
884
|
-
if (positionals[0] === "plugin-status") {
|
|
885
|
-
handlePluginStatusCommand({ json: args.json === true });
|
|
886
|
-
return;
|
|
887
|
-
}
|
|
888
|
-
if (positionals[0] === "scaffold-plugin") {
|
|
889
|
-
await handleScaffoldPluginCommand({ positionals });
|
|
890
|
-
return;
|
|
891
|
-
}
|
|
892
|
-
if (positionals[0] === "verify-plugin") {
|
|
893
|
-
await handleVerifyPluginCommand({ positionals });
|
|
894
|
-
return;
|
|
895
|
-
}
|
|
896
779
|
await startFolderMode({
|
|
897
780
|
...base,
|
|
898
781
|
folderArg: positionals[0]
|
|
899
782
|
});
|
|
900
783
|
}
|
|
901
|
-
function defaultWorkspaceRoot() {
|
|
902
|
-
return process.env.BORING_AGENT_WORKSPACE_ROOT ?? process.cwd();
|
|
903
|
-
}
|
|
904
|
-
function workspaceLocalPluginRootsEnabled() {
|
|
905
|
-
const raw = process.env.BORING_AGENT_WORKSPACE_LOCAL_PLUGIN_ROOTS;
|
|
906
|
-
if (raw == null || raw.trim() === "") return true;
|
|
907
|
-
return !["0", "false", "no", "off"].includes(raw.trim().toLowerCase());
|
|
908
|
-
}
|
|
909
|
-
function buildPluginStatus() {
|
|
910
|
-
const workspaceRoot = resolve(defaultWorkspaceRoot());
|
|
911
|
-
const enabled = workspaceLocalPluginRootsEnabled();
|
|
912
|
-
return {
|
|
913
|
-
workspaceLocalPluginRoots: enabled,
|
|
914
|
-
workspaceRoot,
|
|
915
|
-
extensionsDir: join(workspaceRoot, ".pi", "extensions"),
|
|
916
|
-
reloadSupported: enabled,
|
|
917
|
-
...enabled ? {} : {
|
|
918
|
-
reason: "This runtime writes to a remote sandbox; host-side plugin discovery cannot load .pi/extensions from there."
|
|
919
|
-
}
|
|
920
|
-
};
|
|
921
|
-
}
|
|
922
|
-
function handlePluginStatusCommand(opts) {
|
|
923
|
-
const status = buildPluginStatus();
|
|
924
|
-
if (opts.json) {
|
|
925
|
-
console.log(JSON.stringify(status, null, 2));
|
|
926
|
-
return;
|
|
927
|
-
}
|
|
928
|
-
console.log(status.workspaceLocalPluginRoots ? `workspace-local plugin roots enabled: ${status.extensionsDir}` : `workspace-local plugin roots disabled: ${status.reason}`);
|
|
929
|
-
}
|
|
930
|
-
async function handleVerifyPluginCommand(opts) {
|
|
931
|
-
const maybeName = opts.positionals[1];
|
|
932
|
-
const maybeWorkspace = opts.positionals[2];
|
|
933
|
-
const looksLikePath = maybeName && (maybeName.includes("/") || maybeName.startsWith("."));
|
|
934
|
-
const name = looksLikePath ? void 0 : maybeName;
|
|
935
|
-
const workspaceRoot = resolve(maybeWorkspace ?? (looksLikePath ? maybeName : defaultWorkspaceRoot()));
|
|
936
|
-
const { findHintForError, formatVerifyResult, verifyPlugin } = await import("./verifyPlugin.js");
|
|
937
|
-
const result = verifyPlugin({ workspaceRoot, ...name ? { name } : {} });
|
|
938
|
-
console.log(formatVerifyResult(result));
|
|
939
|
-
if (!result.ok) {
|
|
940
|
-
const hints = [];
|
|
941
|
-
for (const outcome of result.outcomes) {
|
|
942
|
-
for (const err of outcome.errors) {
|
|
943
|
-
const hint = findHintForError(err);
|
|
944
|
-
if (hint) hints.push(` hint (${outcome.id}): ${hint}`);
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
if (hints.length > 0) {
|
|
948
|
-
console.log("");
|
|
949
|
-
console.log("Suggestions:");
|
|
950
|
-
for (const hint of hints) console.log(hint);
|
|
951
|
-
}
|
|
952
|
-
process.exit(1);
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
async function handleScaffoldPluginCommand(opts) {
|
|
956
|
-
const name = opts.positionals[1];
|
|
957
|
-
if (!name) {
|
|
958
|
-
throw new Error("usage: boring-ui scaffold-plugin <name> [workspace]");
|
|
959
|
-
}
|
|
960
|
-
const status = buildPluginStatus();
|
|
961
|
-
if (!status.workspaceLocalPluginRoots) {
|
|
962
|
-
throw new Error(`${status.reason} Do not scaffold into .pi/extensions in this runtime.`);
|
|
963
|
-
}
|
|
964
|
-
const workspaceRoot = resolve(opts.positionals[2] ?? defaultWorkspaceRoot());
|
|
965
|
-
const { scaffoldPlugin } = await import("./scaffoldPlugin.js");
|
|
966
|
-
const result = scaffoldPlugin({ name, workspaceRoot });
|
|
967
|
-
console.log(`scaffolded ${name}`);
|
|
968
|
-
console.log(` dir ${result.pluginDir}`);
|
|
969
|
-
for (const file of result.filesCreated) {
|
|
970
|
-
console.log(` + ${file}`);
|
|
971
|
-
}
|
|
972
|
-
console.log("");
|
|
973
|
-
console.log("Next steps:");
|
|
974
|
-
console.log(` 1. edit front/index.tsx for UI panels/commands/resolvers`);
|
|
975
|
-
console.log(` 2. add pi.extensions / skills for hot-reloadable agent behavior`);
|
|
976
|
-
console.log(` 3. bash \`boring-ui verify-plugin\` \u2014 confirms manifests + files are valid`);
|
|
977
|
-
console.log(` 4. ask the user: /reload`);
|
|
978
|
-
console.log("");
|
|
979
|
-
console.log("Advanced server integration:");
|
|
980
|
-
console.log(" boring.server is boot-time/static composition only. It is NOT hot-registered");
|
|
981
|
-
console.log(" by /reload for .pi/extensions user plugins; use Pi extensions for agent tools.");
|
|
982
|
-
}
|
|
983
784
|
export {
|
|
984
785
|
createBoringUiCliRuntimePlugin,
|
|
985
786
|
createFolderModeApp,
|
|
@@ -987,5 +788,6 @@ export {
|
|
|
987
788
|
provisionCliWorkspaceRuntime,
|
|
988
789
|
registerStatic,
|
|
989
790
|
resolveBoringUiCliPackageRoot,
|
|
791
|
+
resolveBoringUiPluginCliPackageRoot,
|
|
990
792
|
runCli
|
|
991
793
|
};
|