@hachej/boring-ui-plugin-cli 0.1.40 → 0.1.42

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 ADDED
@@ -0,0 +1,79 @@
1
+ # @hachej/boring-ui-plugin-cli
2
+
3
+ Plugin authoring CLI for the boring-ui workspace runtime. The binary is
4
+ `boring-ui-plugin`; it is also bundled into `@hachej/boring-ui-cli` and reached
5
+ as `boring-ui plugin <subcommand>`.
6
+
7
+ It scaffolds, verifies, tests, and manages boring-ui plugins, and exports the
8
+ plugin-source resolution helpers the CLI uses to discover plugins.
9
+
10
+ ## Two kinds of plugin
11
+
12
+ | | `create` | `scaffold` |
13
+ |--|----------|------------|
14
+ | Output | npm-package plugin under `plugins/<name>/` (copied from `templates/plugin/`) | workspace runtime plugin under `<workspace>/.pi/extensions/<name>/` |
15
+ | Build | has a build step (`tsup`), `workspace:*` deps | no build step, hot-reloadable via `/reload` |
16
+ | Use for | app/internal publishable plugins | per-workspace plugins authored from inside the running UI |
17
+
18
+ ## Commands
19
+
20
+ ```
21
+ boring-ui-plugin status [--json]
22
+ boring-ui-plugin create <name> [--path <dir>]
23
+ boring-ui-plugin scaffold <name> [workspace]
24
+ boring-ui-plugin verify [name] [workspace]
25
+ boring-ui-plugin test <name> [--url <url>] [--workspace <id>] [--panel-id <id>] [--timeout-ms <ms>] [--json]
26
+ boring-ui-plugin install [-l|--local|--global] [--workspace <dir>] <source>
27
+ boring-ui-plugin list [--local|--global|--all] [--workspace <dir>] [--json]
28
+ boring-ui-plugin remove [-l|--local|--global] [--workspace <dir>] <id-or-source>
29
+ ```
30
+
31
+ - **status** — reports whether workspace-local plugin roots are enabled (driven
32
+ by `BORING_AGENT_WORKSPACE_LOCAL_PLUGIN_ROOTS`) and the resolved
33
+ `.pi/extensions` dir.
34
+ - **verify** — validates plugin manifests on disk *without* a running server
35
+ (manifest validity + `boring.front` / `boring.server` / `pi.extensions` file
36
+ existence). It does not execute plugin code, so syntax errors only surface on
37
+ a real `/reload`. Prints hints for known errors and exits non-zero on failure.
38
+ - **test** — drives a self-test against a running workspace server (default URL
39
+ inferred, override with `--url`) to catch panel render / front-import
40
+ failures that don't appear in the `/reload` banner.
41
+ - **install / list / remove** — manage plugin *sources* in two scopes: `local`
42
+ (`<workspace>/.pi`, default) and `global` (`~/.pi/agent`). Sources can be a
43
+ local path, a git URL, or an npm spec. Dependencies are **not** installed for
44
+ you — run your package manager in the plugin folder, then `/reload` in the UI.
45
+
46
+ Run `boring-ui-plugin` with no command for usage.
47
+
48
+ ## Plugin manifest
49
+
50
+ Plugins are declared in `package.json` via two fields (`src/manifest.ts`):
51
+
52
+ - `boring` — workspace/UI discovery: `front` (browser entry default-exporting a
53
+ `BoringFrontFactory`), `server` (backend entry), labels.
54
+ - `pi` — agent/Pi runtime contributions: `extensions`, `skills`, prompt
55
+ fragments, Pi packages, and slash commands.
56
+
57
+ ## Programmatic API
58
+
59
+ The package exports its building blocks for embedding hosts (e.g. the CLI):
60
+ `runBoringUiPluginCli`, `createPlugin`, `scaffoldPlugin`, `verifyPlugin`,
61
+ `runPluginSelfTest`, `installPluginSource` / `listPluginSources` /
62
+ `removePluginSource`, and source-scope helpers
63
+ (`resolvePluginSourceScopePaths`, `readPluginSourceRecords`) via the
64
+ `./plugin-sources` subpath. See `src/index.ts` for the full surface.
65
+
66
+ ## Templates
67
+
68
+ `templates/plugin/` is the canonical npm-package plugin shape copied by
69
+ `create`; its [README](./templates/plugin/README.md) documents the front /
70
+ server / shared layout and invariants. `templates/*-canonical.*` are the
71
+ single-file canonical sources used by `scaffold`.
72
+
73
+ ## Docs
74
+
75
+ - [`docs/README.md`](./docs/README.md) — architecture and internals.
76
+
77
+ ## License
78
+
79
+ MIT
package/dist/bin.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runBoringUiPluginCli
4
- } from "./chunk-PYNOFBR6.js";
5
- import "./chunk-3WN35EV3.js";
4
+ } from "./chunk-4ZXW5O2M.js";
5
+ import "./chunk-KTILPA2U.js";
6
6
 
7
7
  // src/bin.ts
8
8
  runBoringUiPluginCli().catch((error) => {
@@ -5,7 +5,7 @@ import {
5
5
  listPluginSources,
6
6
  removePluginSource,
7
7
  validateBoringPluginManifest
8
- } from "./chunk-3WN35EV3.js";
8
+ } from "./chunk-KTILPA2U.js";
9
9
 
10
10
  // src/server/index.ts
11
11
  import { join as join4, resolve as resolve4 } from "path";
@@ -679,6 +679,11 @@ function collectRuntimeDiagnostics(pluginId, body) {
679
679
  if (!plugin) return { events };
680
680
  if (typeof plugin.serverLoadedRevision === "number") revision = plugin.serverLoadedRevision;
681
681
  if (typeof plugin.serverError === "string") events.push(event("PLUGIN_SERVER_ERROR", plugin.serverError));
682
+ if (isObject2(plugin.frontError)) {
683
+ if (typeof plugin.frontError.revision === "number") revision = plugin.frontError.revision;
684
+ const message = typeof plugin.frontError.message === "string" ? plugin.frontError.message : "front module failed to load";
685
+ events.push(event("PLUGIN_FRONT_ERROR", message));
686
+ }
682
687
  if (isObject2(plugin.host)) {
683
688
  if (typeof plugin.host.revision === "number") revision = plugin.host.revision;
684
689
  const code = typeof plugin.host.lastErrorCode === "string" ? plugin.host.lastErrorCode : "PLUGIN_RUNTIME_HOST_ERROR";
@@ -896,7 +901,8 @@ function handleScaffold(positionals) {
896
901
  console.log(" 3. bash `boring-ui-plugin verify` \u2014 confirms manifests + files are valid");
897
902
  console.log(" 4. if the UI is open, bash `boring-ui-plugin test <name>` \u2014 catches panel render failures");
898
903
  console.log(" 5. ask the user: /reload");
899
- console.log(" 6. after /reload, call the plugin_diagnostics tool to confirm no load errors \u2014 /reload reports plugin/skill errors there");
904
+ console.log(" 6. after /reload, ALWAYS call the plugin_diagnostics tool AND re-run `boring-ui-plugin test <name>` \u2014 front import failures only show up there (source plugin-front / PLUGIN_FRONT_ERROR), not in the /reload banner");
905
+ console.log(" 7. iterate (fix -> /reload -> plugin_diagnostics + test) until both are clean before reporting success");
900
906
  }
901
907
  function handleVerify(positionals) {
902
908
  const result = verifyPlugin(parseVerifyArgs(positionals));
@@ -503,6 +503,14 @@ function readPluginSourceRecordsForRoots(opts) {
503
503
  const global = resolvePluginSourceScopePaths("global", opts);
504
504
  return [...readPluginSourceRecords(global), ...readPluginSourceRecords(local)];
505
505
  }
506
+ function resolveRegisteredPluginSourceDirs(paths) {
507
+ return packageEntries(readPiSettings(paths.settingsPath)).flatMap((entry) => {
508
+ const source = packageEntrySource(entry);
509
+ if (!source) return [];
510
+ const rootDir = resolvePackageSourcePath(paths.baseDir, source);
511
+ return rootDir ? [{ source, rootDir }] : [];
512
+ });
513
+ }
506
514
  function upsertPackageSource(paths, record) {
507
515
  const settings = readPiSettings(paths.settingsPath);
508
516
  const entries = packageEntries(settings);
@@ -621,6 +629,7 @@ export {
621
629
  resolvePluginSourceScopePaths,
622
630
  readPluginSourceRecords,
623
631
  readPluginSourceRecordsForRoots,
632
+ resolveRegisteredPluginSourceDirs,
624
633
  installPluginSource,
625
634
  listPluginSources,
626
635
  removePluginSource,
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { InstallPluginSourceOptions, ListPluginSourcesOptions, PluginInstallResult, PluginInstallScope, PluginListResult, PluginRemoveResult, PluginSourceKind, PluginSourceRecord, PluginSourceScopePaths, RemovePluginSourceOptions, formatPluginSourceList, installPluginSource, listPluginSources, readPluginSourceRecords, readPluginSourceRecordsForRoots, removePluginSource, resolvePluginSourceScopePaths } from './plugin-sources.js';
1
+ export { InstallPluginSourceOptions, ListPluginSourcesOptions, PluginInstallResult, PluginInstallScope, PluginListResult, PluginRemoveResult, PluginSourceKind, PluginSourceRecord, PluginSourceScopePaths, RegisteredPluginSourceDir, RemovePluginSourceOptions, formatPluginSourceList, installPluginSource, listPluginSources, readPluginSourceRecords, readPluginSourceRecordsForRoots, removePluginSource, resolvePluginSourceScopePaths, resolveRegisteredPluginSourceDirs } from './plugin-sources.js';
2
2
 
3
3
  interface CreatePluginOptions {
4
4
  name: string;
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  runPluginSelfTest,
9
9
  scaffoldPlugin,
10
10
  verifyPlugin
11
- } from "./chunk-PYNOFBR6.js";
11
+ } from "./chunk-4ZXW5O2M.js";
12
12
  import {
13
13
  formatPluginSourceList,
14
14
  installPluginSource,
@@ -16,8 +16,9 @@ import {
16
16
  readPluginSourceRecords,
17
17
  readPluginSourceRecordsForRoots,
18
18
  removePluginSource,
19
- resolvePluginSourceScopePaths
20
- } from "./chunk-3WN35EV3.js";
19
+ resolvePluginSourceScopePaths,
20
+ resolveRegisteredPluginSourceDirs
21
+ } from "./chunk-KTILPA2U.js";
21
22
  export {
22
23
  createPlugin,
23
24
  findHintForError,
@@ -31,6 +32,7 @@ export {
31
32
  readPluginSourceRecordsForRoots,
32
33
  removePluginSource,
33
34
  resolvePluginSourceScopePaths,
35
+ resolveRegisteredPluginSourceDirs,
34
36
  runBoringUiPluginCli,
35
37
  runPluginSelfTest,
36
38
  scaffoldPlugin,
@@ -63,9 +63,28 @@ declare function readPluginSourceRecordsForRoots(opts: {
63
63
  workspaceRoot: string;
64
64
  globalRoot?: string;
65
65
  }): PluginSourceRecord[];
66
+ interface RegisteredPluginSourceDir {
67
+ /** Raw package source string as written in settings.json. */
68
+ source: string;
69
+ /** Absolute directory the source resolves to (may not exist). */
70
+ rootDir: string;
71
+ }
72
+ /**
73
+ * Resolve every local-path `packages` entry in the scope's settings.json
74
+ * to its directory WITHOUT validating the plugin root. Remote specs
75
+ * (npm:, git:, URLs) are skipped — their installed copies live under the
76
+ * scope's npm/git dirs, which hosts already scan directly.
77
+ *
78
+ * Unlike `readPluginSourceRecords`, broken entries are returned rather
79
+ * than dropped: hosts pass these dirs to the Boring plugin scanner with
80
+ * `registered: true`, so a deleted dir or stripped package.json surfaces
81
+ * as a preflight error in the plugin UI instead of the plugin silently
82
+ * vanishing.
83
+ */
84
+ declare function resolveRegisteredPluginSourceDirs(paths: PluginSourceScopePaths): RegisteredPluginSourceDir[];
66
85
  declare function installPluginSource(opts: InstallPluginSourceOptions): PluginInstallResult;
67
86
  declare function listPluginSources(opts?: ListPluginSourcesOptions): PluginListResult;
68
87
  declare function removePluginSource(opts: RemovePluginSourceOptions): PluginRemoveResult;
69
88
  declare function formatPluginSourceList(result: PluginListResult): string;
70
89
 
71
- export { type InstallPluginSourceOptions, type ListPluginSourcesOptions, type PluginInstallResult, type PluginInstallScope, type PluginListResult, type PluginRemoveResult, type PluginSourceKind, type PluginSourceRecord, type PluginSourceScopePaths, type RemovePluginSourceOptions, formatPluginSourceList, installPluginSource, listPluginSources, readPluginSourceRecords, readPluginSourceRecordsForRoots, removePluginSource, resolvePluginSourceScopePaths };
90
+ export { type InstallPluginSourceOptions, type ListPluginSourcesOptions, type PluginInstallResult, type PluginInstallScope, type PluginListResult, type PluginRemoveResult, type PluginSourceKind, type PluginSourceRecord, type PluginSourceScopePaths, type RegisteredPluginSourceDir, type RemovePluginSourceOptions, formatPluginSourceList, installPluginSource, listPluginSources, readPluginSourceRecords, readPluginSourceRecordsForRoots, removePluginSource, resolvePluginSourceScopePaths, resolveRegisteredPluginSourceDirs };
@@ -5,8 +5,9 @@ import {
5
5
  readPluginSourceRecords,
6
6
  readPluginSourceRecordsForRoots,
7
7
  removePluginSource,
8
- resolvePluginSourceScopePaths
9
- } from "./chunk-3WN35EV3.js";
8
+ resolvePluginSourceScopePaths,
9
+ resolveRegisteredPluginSourceDirs
10
+ } from "./chunk-KTILPA2U.js";
10
11
  export {
11
12
  formatPluginSourceList,
12
13
  installPluginSource,
@@ -14,5 +15,6 @@ export {
14
15
  readPluginSourceRecords,
15
16
  readPluginSourceRecordsForRoots,
16
17
  removePluginSource,
17
- resolvePluginSourceScopePaths
18
+ resolvePluginSourceScopePaths,
19
+ resolveRegisteredPluginSourceDirs
18
20
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hachej/boring-ui-plugin-cli",
3
- "version": "0.1.40",
3
+ "version": "0.1.42",
4
4
  "description": "Slim boring-ui plugin authoring CLI for workspace runtimes.",
5
5
  "license": "MIT",
6
6
  "type": "module",