@vibecontrols/plugin-sdk 2026.509.1

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 (40) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +206 -0
  3. package/boilerplate/.github/workflows/release.template.yml +57 -0
  4. package/boilerplate/README.md +41 -0
  5. package/boilerplate/bunfig.toml +13 -0
  6. package/boilerplate/eslint.config.base.js +36 -0
  7. package/boilerplate/lefthook.base.yml +10 -0
  8. package/boilerplate/package.template.json +52 -0
  9. package/boilerplate/tsconfig.base.json +20 -0
  10. package/dist/audit/index.d.ts +17 -0
  11. package/dist/audit/index.js +19 -0
  12. package/dist/broadcast/index.d.ts +15 -0
  13. package/dist/broadcast/index.js +14 -0
  14. package/dist/cli/index.d.ts +75 -0
  15. package/dist/cli/index.js +104 -0
  16. package/dist/config/index.d.ts +34 -0
  17. package/dist/config/index.js +66 -0
  18. package/dist/contract/index.d.ts +118 -0
  19. package/dist/contract/index.js +16 -0
  20. package/dist/http/index.d.ts +35 -0
  21. package/dist/http/index.js +70 -0
  22. package/dist/index.d.ts +15 -0
  23. package/dist/index.js +595 -0
  24. package/dist/lifecycle/index.d.ts +31 -0
  25. package/dist/lifecycle/index.js +30 -0
  26. package/dist/log/index.d.ts +22 -0
  27. package/dist/log/index.js +25 -0
  28. package/dist/providers/index.d.ts +29 -0
  29. package/dist/providers/index.js +38 -0
  30. package/dist/routes/index.d.ts +37 -0
  31. package/dist/routes/index.js +77 -0
  32. package/dist/storage/index.d.ts +36 -0
  33. package/dist/storage/index.js +67 -0
  34. package/dist/subprocess/index.d.ts +37 -0
  35. package/dist/subprocess/index.js +69 -0
  36. package/dist/telemetry/index.d.ts +27 -0
  37. package/dist/telemetry/index.js +41 -0
  38. package/dist/testing/index.d.ts +31 -0
  39. package/dist/testing/index.js +97 -0
  40. package/package.json +159 -0
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Proprietary License
2
+
3
+ Copyright (c) 2025-2026 Burdenoff Consultancy Services Pvt. Ltd. All rights reserved.
4
+
5
+ This software and associated documentation files (the "Software") are the proprietary
6
+ property of Burdenoff Consultancy Services Pvt. Ltd. and its affiliates.
7
+
8
+ UNAUTHORIZED COPYING, MODIFICATION, DISTRIBUTION, OR USE OF THIS SOFTWARE, VIA ANY
9
+ MEDIUM, IS STRICTLY PROHIBITED.
10
+
11
+ The Software is provided under a proprietary license. You may use the Software only in
12
+ accordance with the terms of your license agreement with Burdenoff Consultancy Services
13
+ Pvt. Ltd.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16
+ INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
17
+ PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
19
+ OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20
+ OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ For licensing inquiries, contact: contact@vibecontrols.com
package/README.md ADDED
@@ -0,0 +1,206 @@
1
+ # @vibecontrols/plugin-sdk
2
+
3
+ Shared contract, lifecycle, CLI, telemetry, storage, and HTTP helpers consumed by every `@vibecontrols/vibe-plugin-*` package and by the agent itself.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ bun add @vibecontrols/plugin-sdk
9
+ # or
10
+ npm install @vibecontrols/plugin-sdk
11
+ ```
12
+
13
+ ## Modules
14
+
15
+ Granular subpath imports so plugins tree-shake aggressively. The most-used helpers are also re-exported from the root barrel `@vibecontrols/plugin-sdk`.
16
+
17
+ ### `contract` — types
18
+
19
+ The plugin contract v2 surface. `VibePlugin`, `HostServices`, `PluginCapabilities`, `Prerequisite`, `StorageProvider`, `ServiceRegistry`, plus `FULL_TRUST_CAPS`. Every host-side field is optional so plugins keep working against partial hosts.
20
+
21
+ ```ts
22
+ import type { VibePluginFactory, VibePlugin } from "@vibecontrols/plugin-sdk/contract";
23
+
24
+ export const createPlugin: VibePluginFactory = (ctx) => ({
25
+ name: "demo",
26
+ version: "1.0.0",
27
+ capabilities: { storage: "rw", telemetry: true },
28
+ tags: ["backend"],
29
+ });
30
+ ```
31
+
32
+ ### `lifecycle` — boilerplate-free init / shutdown
33
+
34
+ `createLifecycleHooks` collapses `onServerStart` / `onServerStop` boilerplate, emits a one-shot `<plugin>.ready` telemetry event, and skips on unsupported platforms.
35
+
36
+ ```ts
37
+ import { createLifecycleHooks } from "@vibecontrols/plugin-sdk/lifecycle";
38
+
39
+ const { onServerStart, onServerStop } = createLifecycleHooks({
40
+ name: "demo",
41
+ telemetryEventName: "demo.ready",
42
+ onInit: async (hostServices) => {
43
+ /* ... */
44
+ },
45
+ });
46
+ ```
47
+
48
+ ### `cli` — multimode + redaction + command builder
49
+
50
+ `runMultimode<T>` selects between JSON / plain / interactive renderers from a single `fetchData` call. `redact(value)` strips secrets recursively. `CliCommandBuilder` registers status sub-commands with `--json` / `--plain` baked in.
51
+
52
+ ```ts
53
+ import { CliCommandBuilder, redact } from "@vibecontrols/plugin-sdk/cli";
54
+
55
+ new CliCommandBuilder(program).addStatusCommand("status", {
56
+ description: "Show plugin status",
57
+ fetchData: () => fetchStatus(),
58
+ redact: true,
59
+ });
60
+ ```
61
+
62
+ ### `routes` — Elysia fluent builder
63
+
64
+ ```ts
65
+ import { RoutesBuilder } from "@vibecontrols/plugin-sdk/routes";
66
+
67
+ const app = new RoutesBuilder("demo", hostServices)
68
+ .withPrefix("/api/demo")
69
+ .withAuth(() => process.env.AGENT_API_KEY ?? "")
70
+ .withErrorHandler()
71
+ .withLogging()
72
+ .build();
73
+
74
+ app.get("/ping", () => ({ ok: true }));
75
+ ```
76
+
77
+ ### `telemetry` — auto-tagged emitter
78
+
79
+ ```ts
80
+ import { TelemetryEmitter } from "@vibecontrols/plugin-sdk/telemetry";
81
+
82
+ const tel = new TelemetryEmitter("demo", "1.0.0", hostServices);
83
+ tel.emitReady({ port: 3005 });
84
+ tel.emitError(new Error("boom"));
85
+ ```
86
+
87
+ ### `log` — source-bound logger
88
+
89
+ ```ts
90
+ import { BoundLogger } from "@vibecontrols/plugin-sdk/log";
91
+
92
+ const log = new BoundLogger(hostServices.logger, "demo");
93
+ log.info("started", { port: 3005 });
94
+ ```
95
+
96
+ ### `storage` — typed JSON-encoded helpers
97
+
98
+ ```ts
99
+ import { TypedStore, NamespaceStore } from "@vibecontrols/plugin-sdk/storage";
100
+
101
+ const ns = new NamespaceStore(hostServices.storage!, "demo");
102
+ const settings = ns.typed<{ enabled: boolean }>("settings");
103
+ await settings.set({ enabled: true });
104
+ const current = await settings.get();
105
+ ```
106
+
107
+ ### `config` — env + host config + defaults
108
+
109
+ ```ts
110
+ import { ConfigManager } from "@vibecontrols/plugin-sdk/config";
111
+
112
+ const cfg = new ConfigManager("demo", hostServices, hostServices.logger);
113
+ const port = (await cfg.getInt("port", 3005))!;
114
+ const apiKey = await cfg.getRequired("api_key"); // throws if missing
115
+ ```
116
+
117
+ ### `subprocess` — cross-platform process helpers
118
+
119
+ ```ts
120
+ import {
121
+ gracefulKill,
122
+ isProcessAlive,
123
+ findAvailablePort,
124
+ sleep,
125
+ } from "@vibecontrols/plugin-sdk/subprocess";
126
+
127
+ const port = await findAvailablePort(7000);
128
+ await gracefulKill(child.pid, 3000);
129
+ ```
130
+
131
+ ### `http` — HttpClient with retries + timeout
132
+
133
+ ```ts
134
+ import { HttpClient } from "@vibecontrols/plugin-sdk/http";
135
+
136
+ const client = new HttpClient("https://api.example.com", { timeoutMs: 5000 });
137
+ const data = await client.get<{ ok: boolean }>("/v1/status");
138
+ ```
139
+
140
+ ### `providers` — ProviderRegistry façade
141
+
142
+ ```ts
143
+ import { ProviderRegistry } from "@vibecontrols/plugin-sdk/providers";
144
+
145
+ const reg = new ProviderRegistry(hostServices);
146
+ reg.registerProvider("tunnel", "cloudflare", myCloudflareProvider);
147
+ const all = reg.listProviders("tunnel");
148
+ ```
149
+
150
+ ### `audit` — bound source emitter
151
+
152
+ ```ts
153
+ import { AuditLogger } from "@vibecontrols/plugin-sdk/audit";
154
+
155
+ const audit = new AuditLogger("demo", hostServices);
156
+ audit.emit("started", { port: 3005 });
157
+ ```
158
+
159
+ ### `broadcast` — typed WebSocket emitter
160
+
161
+ ```ts
162
+ import { BroadcastEmitter } from "@vibecontrols/plugin-sdk/broadcast";
163
+
164
+ new BroadcastEmitter(hostServices).broadcast("demo.event", { count: 1 });
165
+ ```
166
+
167
+ ### `testing` — Bun-mock factories
168
+
169
+ Run with `bun test` (depends on the runtime `bun:test` import).
170
+
171
+ ```ts
172
+ import { createMockHostServices, createMockProfileContext } from "@vibecontrols/plugin-sdk/testing";
173
+
174
+ const hs = createMockHostServices({ getAgentVersion: () => "test" });
175
+ const ctx = createMockProfileContext();
176
+ ```
177
+
178
+ ## Compatibility Matrix
179
+
180
+ | SDK version | Agent version | Plugin contract |
181
+ | ------------ | -------------- | --------------------------- |
182
+ | `2026.509.x` | `>=2026.509.1` | v2 (`createPlugin` factory) |
183
+
184
+ ## Boilerplate
185
+
186
+ Downstream plugins can extend the shared configs in `boilerplate/`:
187
+
188
+ - `tsconfig.base.json` — strict TS + ESM
189
+ - `eslint.config.base.js` — no-any, no-eslint-disable, max-warnings 0
190
+ - `lefthook.base.yml` — pre-push sanity gate
191
+ - `bunfig.toml` — Verdaccio scope wiring
192
+ - `.github/workflows/release.template.yml` — CalVer publish pipeline
193
+ - `package.template.json` — minimal starter package.json
194
+
195
+ See `templates/plugin-scaffold.md` for the recommended layout.
196
+
197
+ ## Contributing
198
+
199
+ 1. `bun install`
200
+ 2. `bun run sanity` must be green (0 errors, 0 warnings)
201
+ 3. Trunk-based: `main` only. CalVer release via `gh workflow run release.yml -f version=YYYY.MDD.PATCH`.
202
+ 4. Spec: `~/products/vibecontrols/vibecontrols-specs/architecture/PLUGIN_SDK_EXTRACTION.md`
203
+
204
+ ## License
205
+
206
+ Proprietary — Burdenoff Consultancy Services Pvt. Ltd. See `LICENSE`.
@@ -0,0 +1,57 @@
1
+ # Release — publish a vibe-plugin-* package to npmjs (public) + Verdaccio.
2
+ #
3
+ # Trigger: workflow_dispatch (manual version) or CalVer git-tag push.
4
+ # Replace `@vibecontrols/vibe-plugin-EXAMPLE` with the real package name.
5
+
6
+ name: Release
7
+
8
+ on:
9
+ push:
10
+ tags:
11
+ - "[0-9][0-9][0-9][0-9].[0-9]*.[0-9]*"
12
+ workflow_dispatch:
13
+ inputs:
14
+ version:
15
+ description: "CalVer version (YYYY.MDD.PATCH). Leave empty to auto-compute."
16
+ required: false
17
+ type: string
18
+
19
+ concurrency:
20
+ group: release
21
+ cancel-in-progress: false
22
+
23
+ jobs:
24
+ release:
25
+ name: Release to npmjs + Verdaccio
26
+ runs-on: org-runners
27
+ timeout-minutes: 15
28
+ permissions:
29
+ contents: write
30
+ steps:
31
+ - uses: actions/checkout@v5
32
+ with:
33
+ fetch-depth: 0
34
+ - uses: oven-sh/setup-bun@v2
35
+ with:
36
+ bun-version-file: .bun-version
37
+ - name: Configure Verdaccio scoped registry
38
+ run: |
39
+ AUTH=$(echo -n "ci-publisher:${{ secrets.VERDACCIO_CI_PASSWORD }}" | base64)
40
+ cat > bunfig.toml << EOF
41
+ [install]
42
+ exact = true
43
+ [install.scopes]
44
+ vibecontrols = { token = "${AUTH}", url = "https://verdaccio.tooling.internal.burdenoff.com/" }
45
+ burdenoff = { token = "${AUTH}", url = "https://verdaccio.tooling.internal.burdenoff.com/" }
46
+ EOF
47
+ - run: bun install --frozen-lockfile
48
+ - run: bun run sanity
49
+ - run: bun run build
50
+ - name: Publish to npmjs
51
+ run: |
52
+ echo "//registry.npmjs.org/:_authToken=${{ secrets.NPMJS_VIBECONTROLS_TOKEN }}" > ~/.npmrc
53
+ bunx npm publish --access public
54
+ - name: Publish to Verdaccio
55
+ run: |
56
+ echo "//verdaccio.tooling.internal.burdenoff.com/:_authToken=$(echo -n 'ci-publisher:${{ secrets.VERDACCIO_CI_PASSWORD }}' | base64)" > ~/.npmrc
57
+ bunx npm publish --registry https://verdaccio.tooling.internal.burdenoff.com/
@@ -0,0 +1,41 @@
1
+ # Plugin Boilerplate
2
+
3
+ Extends-able starters for `@vibecontrols/vibe-plugin-*` packages. Copy or extend from a downstream plugin's config files:
4
+
5
+ | File | Purpose |
6
+ | ---------------------------------------- | ------------------------------------------------------------------------ |
7
+ | `tsconfig.base.json` | Strict TS + ESM, ES2022, declaration emit. `extends` from your tsconfig. |
8
+ | `eslint.config.base.js` | No `any`, no `@ts-ignore`, no `eslint-disable`. Spread into your config. |
9
+ | `lefthook.base.yml` | Pre-push sanity gate. |
10
+ | `bunfig.toml` | Verdaccio scope wiring for `@burdenoff` + `@vibecontrols`. |
11
+ | `package.template.json` | Minimal `package.json` starter. |
12
+ | `.github/workflows/release.template.yml` | CalVer release pipeline (npmjs + Verdaccio). |
13
+
14
+ ## Quick start
15
+
16
+ ```bash
17
+ mkdir vibe-plugin-myplugin && cd vibe-plugin-myplugin
18
+ cp ../vibecontrols-plugin-sdk/boilerplate/package.template.json package.json
19
+ cp ../vibecontrols-plugin-sdk/boilerplate/bunfig.toml ./
20
+ cp ../vibecontrols-plugin-sdk/boilerplate/lefthook.base.yml lefthook.yml
21
+ mkdir -p .github/workflows
22
+ cp ../vibecontrols-plugin-sdk/boilerplate/.github/workflows/release.template.yml .github/workflows/release.yml
23
+ bun install
24
+ ```
25
+
26
+ Then point your `tsconfig.json` and `eslint.config.js` at the bases:
27
+
28
+ ```jsonc
29
+ // tsconfig.json
30
+ {
31
+ "extends": "@vibecontrols/plugin-sdk/boilerplate/tsconfig.base.json",
32
+ "compilerOptions": { "outDir": "./dist", "noEmit": true },
33
+ "include": ["src/**/*", "tests/**/*"],
34
+ }
35
+ ```
36
+
37
+ ```js
38
+ // eslint.config.js
39
+ import base from "@vibecontrols/plugin-sdk/boilerplate/eslint.config.base.js";
40
+ export default [...base];
41
+ ```
@@ -0,0 +1,13 @@
1
+ # Shared bunfig.toml for vibe-plugin-* packages.
2
+ # Resolves @burdenoff/* and @vibecontrols/* from Verdaccio while public
3
+ # releases also flow through npmjs. CI may overwrite per-environment.
4
+
5
+ [install]
6
+ exact = true
7
+
8
+ [run]
9
+ shell = "bun"
10
+
11
+ [install.scopes]
12
+ burdenoff = { username = "ci-publisher", password = "$VERDACCIO_PASSWORD", url = "https://verdaccio.tooling.internal.burdenoff.com/" }
13
+ vibecontrols = { username = "ci-publisher", password = "$VERDACCIO_PASSWORD", url = "https://verdaccio.tooling.internal.burdenoff.com/" }
@@ -0,0 +1,36 @@
1
+ // Base ESLint config for vibe-plugin-* packages.
2
+ //
3
+ // Usage (downstream eslint.config.js):
4
+ // import base from "@vibecontrols/plugin-sdk/boilerplate/eslint.config.base.js";
5
+ // export default [...base, { /* per-package overrides */ }];
6
+
7
+ import js from "@eslint/js";
8
+ import tseslint from "typescript-eslint";
9
+ import globals from "globals";
10
+
11
+ export default tseslint.config(
12
+ {
13
+ ignores: ["dist/", "node_modules/", "coverage/", ".eslintcache"],
14
+ },
15
+ js.configs.recommended,
16
+ ...tseslint.configs.recommended,
17
+ {
18
+ languageOptions: {
19
+ globals: {
20
+ ...globals.node,
21
+ Bun: "readonly",
22
+ },
23
+ },
24
+ rules: {
25
+ "@typescript-eslint/no-explicit-any": "error",
26
+ "@typescript-eslint/no-unused-vars": [
27
+ "error",
28
+ {
29
+ argsIgnorePattern: "^_",
30
+ varsIgnorePattern: "^_",
31
+ destructuredArrayIgnorePattern: "^_",
32
+ },
33
+ ],
34
+ },
35
+ },
36
+ );
@@ -0,0 +1,10 @@
1
+ # Shared pre-push sanity gate for vibe-plugin-* packages.
2
+ # Install:
3
+ # bun add -d lefthook && bunx lefthook install
4
+ # Then either copy this file to lefthook.yml or extend via include.
5
+
6
+ pre-push:
7
+ parallel: false
8
+ commands:
9
+ sanity:
10
+ run: bun run sanity
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@vibecontrols/vibe-plugin-EXAMPLE",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "description": "Replace with the plugin description",
6
+ "engines": { "bun": ">=1.3.10" },
7
+ "license": "SEE LICENSE IN LICENSE",
8
+ "main": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "import": "./dist/index.js",
13
+ "types": "./dist/index.d.ts"
14
+ }
15
+ },
16
+ "files": ["dist/**/*", "!dist/**/*.map", "README.md", "LICENSE"],
17
+ "scripts": {
18
+ "build": "tsup",
19
+ "dev": "tsup --watch",
20
+ "lint": "eslint ./src ./tests",
21
+ "lint:sanity": "bun run lint -- --max-warnings 0",
22
+ "format": "prettier . --write",
23
+ "format:check": "prettier . --check",
24
+ "type:check": "tsc --noEmit",
25
+ "test": "bun test tests/**/*.test.ts",
26
+ "clean": "rimraf dist .eslintcache",
27
+ "prebuild": "bun run clean",
28
+ "sanity": "bun run format:check && bun run lint:sanity && bun run type:check && bun run test && bun run build"
29
+ },
30
+ "dependencies": {
31
+ "@vibecontrols/plugin-sdk": "^2026.509.1"
32
+ },
33
+ "devDependencies": {
34
+ "@eslint/js": "^10.0.1",
35
+ "@types/bun": "^1.3.9",
36
+ "eslint": "^10.0.1",
37
+ "globals": "^17.3.0",
38
+ "prettier": "^3.8.1",
39
+ "rimraf": "^6.1.3",
40
+ "tsup": "^8.5.0",
41
+ "typescript": "^5.9.3",
42
+ "typescript-eslint": "^8.56.0"
43
+ },
44
+ "peerDependencies": {
45
+ "elysia": ">=1.3.0",
46
+ "commander": ">=14.0.0"
47
+ },
48
+ "peerDependenciesMeta": {
49
+ "elysia": { "optional": true },
50
+ "commander": { "optional": true }
51
+ }
52
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Bundler",
6
+ "lib": ["ES2022"],
7
+ "types": ["bun"],
8
+ "esModuleInterop": true,
9
+ "allowSyntheticDefaultImports": true,
10
+ "strict": true,
11
+ "noUncheckedIndexedAccess": true,
12
+ "skipLibCheck": true,
13
+ "forceConsistentCasingInFileNames": true,
14
+ "resolveJsonModule": true,
15
+ "declaration": true,
16
+ "declarationMap": false,
17
+ "sourceMap": true,
18
+ "removeComments": false
19
+ }
20
+ }
@@ -0,0 +1,17 @@
1
+ import { HostServices } from '../contract/index.js';
2
+
3
+ /**
4
+ * @vibecontrols/plugin-sdk/audit
5
+ *
6
+ * `AuditLogger` binds `source` to the plugin name and forwards events to
7
+ * `hostServices.audit?.emit`. No-op when the host doesn't expose audit.
8
+ */
9
+
10
+ declare class AuditLogger {
11
+ private readonly source;
12
+ private readonly hostServices?;
13
+ constructor(source: string, hostServices?: HostServices | undefined);
14
+ emit(event: string, payload?: Record<string, unknown>): void;
15
+ }
16
+
17
+ export { AuditLogger };
@@ -0,0 +1,19 @@
1
+ // src/audit/index.ts
2
+ var AuditLogger = class {
3
+ constructor(source, hostServices) {
4
+ this.source = source;
5
+ this.hostServices = hostServices;
6
+ }
7
+ source;
8
+ hostServices;
9
+ emit(event, payload) {
10
+ this.hostServices?.audit?.emit(event, {
11
+ source: this.source,
12
+ ...payload ?? {}
13
+ });
14
+ }
15
+ };
16
+
17
+ export { AuditLogger };
18
+ //# sourceMappingURL=index.js.map
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,15 @@
1
+ import { HostServices } from '../contract/index.js';
2
+
3
+ /**
4
+ * @vibecontrols/plugin-sdk/broadcast
5
+ *
6
+ * Type-safe wrapper over `hostServices.broadcast` — no-op when absent.
7
+ */
8
+
9
+ declare class BroadcastEmitter {
10
+ private readonly hostServices?;
11
+ constructor(hostServices?: HostServices | undefined);
12
+ broadcast<T>(type: string, payload: T): void;
13
+ }
14
+
15
+ export { BroadcastEmitter };
@@ -0,0 +1,14 @@
1
+ // src/broadcast/index.ts
2
+ var BroadcastEmitter = class {
3
+ constructor(hostServices) {
4
+ this.hostServices = hostServices;
5
+ }
6
+ hostServices;
7
+ broadcast(type, payload) {
8
+ this.hostServices?.broadcast?.(type, payload);
9
+ }
10
+ };
11
+
12
+ export { BroadcastEmitter };
13
+ //# sourceMappingURL=index.js.map
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,75 @@
1
+ import { Command } from 'commander';
2
+
3
+ /**
4
+ * Multi-mode output dispatcher.
5
+ *
6
+ * Lifted from vibecontrols-agent/src/cli/utils/multimode.ts but trimmed:
7
+ * the SDK doesn't ship the agent's `isInteractive()` helper since plugins
8
+ * can't depend on opentui from the SDK. Instead we use a stdout-isTTY +
9
+ * env CI/NO_COLOR check inline.
10
+ */
11
+ type OutputMode = "auto" | "interactive" | "plain" | "json";
12
+ interface OutputFlags {
13
+ json?: boolean;
14
+ plain?: boolean;
15
+ interactive?: boolean;
16
+ }
17
+ interface MultimodeOptions<T> {
18
+ fetchData: () => Promise<T> | T;
19
+ plain: (data: T) => void | Promise<void>;
20
+ interactive?: (data: T) => Promise<void>;
21
+ json?: (data: T) => unknown;
22
+ mode?: OutputMode;
23
+ }
24
+ /** Resolve user-supplied CLI flags into an OutputMode. */
25
+ declare function pickOutputMode(flags: OutputFlags): OutputMode;
26
+ declare function runMultimode<T>(opts: MultimodeOptions<T>): Promise<void>;
27
+ /**
28
+ * Convenience: emit `data` as JSON if `--json` is set; return `true` when
29
+ * something was printed. Mutating commands (start/stop/install/...) reach
30
+ * for this when they want a scriptable JSON opt-in.
31
+ */
32
+ declare function maybePrintJson(flags: OutputFlags, data: unknown): boolean;
33
+
34
+ /**
35
+ * Recursive sensitive-field stripper. Replaces values for keys matching the
36
+ * sensitive regex with the literal string "[redacted]". Walks arrays, plain
37
+ * objects, and leaves primitives / null / undefined untouched.
38
+ */
39
+ declare function redact<T>(value: T): T;
40
+
41
+ /**
42
+ * CliCommandBuilder — fluent helper that wires the standard `--json` /
43
+ * `--plain` flags onto a Commander command and routes the action through
44
+ * `runMultimode`. Removes the ~30-line boilerplate every plugin author
45
+ * pastes for status/list commands.
46
+ *
47
+ * commander is a peerDep — this module imports `Command` as a *type* from
48
+ * "commander" so the SDK builds without commander present, and runs only
49
+ * when the consumer installed it.
50
+ */
51
+
52
+ interface StatusCommandSpec<T> {
53
+ description: string;
54
+ fetchData: () => Promise<T> | T;
55
+ /** Plain renderer override. Defaults to `JSON.stringify` if absent. */
56
+ format?: (data: T) => void | Promise<void>;
57
+ /**
58
+ * Apply redaction before any renderer. Strips sensitive keys recursively
59
+ * (see ./redaction.ts).
60
+ */
61
+ redact?: boolean;
62
+ }
63
+ declare class CliCommandBuilder {
64
+ private readonly program;
65
+ constructor(program: Command);
66
+ /**
67
+ * Register a `<name>` sub-command that fetches once and renders via
68
+ * `--json` / `--plain` / interactive (when stdout is a TTY).
69
+ */
70
+ addStatusCommand<T>(name: string, spec: StatusCommandSpec<T>): this;
71
+ /** Escape hatch: hand back the underlying commander Command. */
72
+ command(): Command;
73
+ }
74
+
75
+ export { CliCommandBuilder, type MultimodeOptions, type OutputFlags, type OutputMode, type StatusCommandSpec, maybePrintJson, pickOutputMode, redact, runMultimode };