diff --git a/apps/commandboard-api/package.json b/apps/commandboard-api/package.json index ef70c40..9769f12 100644 --- a/apps/commandboard-api/package.json +++ b/apps/commandboard-api/package.json @@ -13,6 +13,7 @@ }, "dependencies": { "@logicsrc/plugin-core": "file:../../packages/plugin-core", + "@logicsrc/plugin-agentbbs": "file:../../plugins/agentbbs", "@logicsrc/plugin-c0mpute": "file:../../plugins/c0mpute", "@logicsrc/plugin-coinpay": "file:../../plugins/coinpay", "@logicsrc/plugin-email-accounts": "file:../../plugins/email-accounts", diff --git a/apps/commandboard-api/src/contract.test.ts b/apps/commandboard-api/src/contract.test.ts index 2b9629d..843df66 100644 --- a/apps/commandboard-api/src/contract.test.ts +++ b/apps/commandboard-api/src/contract.test.ts @@ -47,7 +47,7 @@ describe("CommandBoard API contracts", () => { }; expect(response.status).toBe(200); - expect(body.plugins.map((plugin) => plugin.id)).toEqual(["coinpay", "ugig", "sh1pt", "c0mpute", "feed-discovery", "social-accounts", "email-accounts"]); + expect(body.plugins.map((plugin) => plugin.id)).toEqual(["coinpay", "ugig", "sh1pt", "c0mpute", "feed-discovery", "social-accounts", "email-accounts", "agentbbs"]); expect(body.plugins.find((plugin) => plugin.id === "sh1pt")).toMatchObject({ enabled: true, capabilities: expect.arrayContaining(["projects.sync", "actions.publish", "deployments.status"]) @@ -61,6 +61,7 @@ describe("CommandBoard API contracts", () => { expect(body.capabilities["feeds.discover"]).toEqual(["feed-discovery"]); expect(body.capabilities["social.post.publish"]).toEqual(["social-accounts"]); expect(body.capabilities["email.send"]).toEqual(["email-accounts"]); + expect(body.capabilities["pods.provision"]).toEqual(["agentbbs"]); }); it("exposes communication account provider contracts", async () => { diff --git a/apps/commandboard-api/src/index.ts b/apps/commandboard-api/src/index.ts index 58b6166..6f29f71 100644 --- a/apps/commandboard-api/src/index.ts +++ b/apps/commandboard-api/src/index.ts @@ -1,6 +1,7 @@ import { createServer, type IncomingMessage, type ServerResponse } from "node:http"; import { pathToFileURL } from "node:url"; import { createPluginRegistry } from "@logicsrc/plugin-core"; +import { agentBbsPlugin } from "@logicsrc/plugin-agentbbs"; import { c0mputePlugin } from "@logicsrc/plugin-c0mpute"; import { coinPayPlugin } from "@logicsrc/plugin-coinpay"; import { emailAccountsPlugin, listEmailAccountProviders } from "@logicsrc/plugin-email-accounts"; @@ -10,7 +11,7 @@ import { listSocialAccountProviders, socialAccountsPlugin } from "@logicsrc/plug import { uGigPlugin } from "@logicsrc/plugin-ugig"; import { schemas, validate } from "@logicsrc/validators"; -const registry = createPluginRegistry([coinPayPlugin, uGigPlugin, sh1ptPlugin, c0mputePlugin, feedDiscoveryPlugin, socialAccountsPlugin, emailAccountsPlugin]); +const registry = createPluginRegistry([coinPayPlugin, uGigPlugin, sh1ptPlugin, c0mputePlugin, feedDiscoveryPlugin, socialAccountsPlugin, emailAccountsPlugin, agentBbsPlugin]); const boards = [ { path: "/general", title: "General", description: "CommandBoard.run general discussion." }, diff --git a/package-lock.json b/package-lock.json index 6d2c8af..14f0942 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "name": "@logicsrc/commandboard-api", "version": "0.1.0", "dependencies": { + "@logicsrc/plugin-agentbbs": "file:../../plugins/agentbbs", "@logicsrc/plugin-c0mpute": "file:../../plugins/c0mpute", "@logicsrc/plugin-coinpay": "file:../../plugins/coinpay", "@logicsrc/plugin-core": "file:../../packages/plugin-core", @@ -1442,6 +1443,10 @@ "resolved": "apps/commandboard-web", "link": true }, + "node_modules/@logicsrc/plugin-agentbbs": { + "resolved": "plugins/agentbbs", + "link": true + }, "node_modules/@logicsrc/plugin-c0mpute": { "resolved": "plugins/c0mpute", "link": true @@ -6068,6 +6073,7 @@ "version": "0.1.0", "dependencies": { "@logicsrc/account-core": "file:../account-core", + "@logicsrc/plugin-agentbbs": "file:../../plugins/agentbbs", "@logicsrc/plugin-coinpay": "file:../../plugins/coinpay", "@logicsrc/plugin-core": "file:../plugin-core", "@logicsrc/plugin-email-accounts": "file:../../plugins/email-accounts", @@ -6148,6 +6154,16 @@ "vitest": "^4.0.8" } }, + "plugins/agentbbs": { + "name": "@logicsrc/plugin-agentbbs", + "version": "0.1.0", + "dependencies": { + "@logicsrc/plugin-core": "file:../../packages/plugin-core" + }, + "devDependencies": { + "vitest": "^4.0.8" + } + }, "plugins/c0mpute": { "name": "@logicsrc/plugin-c0mpute", "version": "0.1.0", diff --git a/package.json b/package.json index c0deda1..5a00f70 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "apps/*" ], "scripts": { - "build": "npm --workspace @logicsrc/schemas run build && npm --workspace @logicsrc/validators run build && npm --workspace @logicsrc/sdk run build && npm --workspace @logicsrc/plugin-core run build && npm --workspace @logicsrc/account-core run build && npm --workspace @logicsrc/plugin-coinpay run build && npm --workspace @logicsrc/plugin-ugig run build && npm --workspace @logicsrc/plugin-sh1pt run build && npm --workspace @logicsrc/plugin-c0mpute run build && npm --workspace @logicsrc/plugin-feed-discovery run build && npm --workspace @logicsrc/plugin-social-accounts run build && npm --workspace @logicsrc/plugin-email-accounts run build && npm --workspace @logicsrc/tui run build && npm --workspace @logicsrc/cli run build && npm --workspace @profullstack/logicsrc-mcp run build && npm --workspace @logicsrc/commandboard-api run build && npm --workspace @logicsrc/commandboard-web run build && npm --workspace @logicsrc/web run build", + "build": "npm --workspace @logicsrc/schemas run build && npm --workspace @logicsrc/validators run build && npm --workspace @logicsrc/sdk run build && npm --workspace @logicsrc/plugin-core run build && npm --workspace @logicsrc/account-core run build && npm --workspace @logicsrc/plugin-coinpay run build && npm --workspace @logicsrc/plugin-ugig run build && npm --workspace @logicsrc/plugin-sh1pt run build && npm --workspace @logicsrc/plugin-c0mpute run build && npm --workspace @logicsrc/plugin-feed-discovery run build && npm --workspace @logicsrc/plugin-social-accounts run build && npm --workspace @logicsrc/plugin-email-accounts run build && npm --workspace @logicsrc/plugin-agentbbs run build && npm --workspace @logicsrc/tui run build && npm --workspace @logicsrc/cli run build && npm --workspace @profullstack/logicsrc-mcp run build && npm --workspace @logicsrc/commandboard-api run build && npm --workspace @logicsrc/commandboard-web run build && npm --workspace @logicsrc/web run build", "start": "npm --workspace @logicsrc/web run start", "test": "npm run test --workspaces --if-present", "check": "npm run build && npm run test", diff --git a/packages/cli/package.json b/packages/cli/package.json index eaddef5..a96e122 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -16,6 +16,7 @@ "dependencies": { "@logicsrc/account-core": "file:../account-core", "@logicsrc/plugin-core": "file:../plugin-core", + "@logicsrc/plugin-agentbbs": "file:../../plugins/agentbbs", "@logicsrc/plugin-coinpay": "file:../../plugins/coinpay", "@logicsrc/plugin-email-accounts": "file:../../plugins/email-accounts", "@logicsrc/plugin-feed-discovery": "file:../../plugins/feed-discovery", diff --git a/packages/cli/src/registry.ts b/packages/cli/src/registry.ts index 090a5f0..a542497 100644 --- a/packages/cli/src/registry.ts +++ b/packages/cli/src/registry.ts @@ -1,4 +1,5 @@ import { createPluginRegistry } from "@logicsrc/plugin-core"; +import { agentBbsPlugin } from "@logicsrc/plugin-agentbbs"; import { coinPayPlugin } from "@logicsrc/plugin-coinpay"; import { emailAccountsPlugin } from "@logicsrc/plugin-email-accounts"; import { feedDiscoveryPlugin } from "@logicsrc/plugin-feed-discovery"; @@ -6,5 +7,5 @@ import { socialAccountsPlugin } from "@logicsrc/plugin-social-accounts"; import { uGigPlugin } from "@logicsrc/plugin-ugig"; export function defaultPluginRegistry() { - return createPluginRegistry([coinPayPlugin, uGigPlugin, feedDiscoveryPlugin, socialAccountsPlugin, emailAccountsPlugin]); + return createPluginRegistry([coinPayPlugin, uGigPlugin, feedDiscoveryPlugin, socialAccountsPlugin, emailAccountsPlugin, agentBbsPlugin]); } diff --git a/plugins/agentbbs/README.md b/plugins/agentbbs/README.md new file mode 100644 index 0000000..9c110bb --- /dev/null +++ b/plugins/agentbbs/README.md @@ -0,0 +1,22 @@ +# @logicsrc/plugin-agentbbs + +Connector plugin for [AgentBBS](https://github.com/profullstack/agentbbs), the BBS-over-SSH platform for humans and agents (chat, pods, arcade, finger presence, ASCII video). + +The plugin declares the AgentBBS capability surface for the LogicSRC registry. It targets a running AgentBBS instance over SSH — it does not embed the Go server. + +## Capabilities + +- `bbs.status` — instance reachability and motd +- `chat.read` / `chat.send` — agent@ shared chat rooms +- `pods.list` / `pods.provision` / `pods.membership` — pod@ hosting, CoinPay $1/mo membership +- `arcade.list` — arcade games (DOOM et al.) +- `ascii.stream` — ascii-live video streams +- `finger.lookup` — finger@ user presence + +## Configuration + +| Env var | Purpose | +| --- | --- | +| `AGENTBBS_SSH_HOST` | AgentBBS host (e.g. `bbs.profullstack.com`) | +| `AGENTBBS_SSH_PORT` | SSH port (default `22`) | +| `AGENTBBS_SSH_KEY_PATH` | Identity key used to authenticate as the agent | diff --git a/plugins/agentbbs/package.json b/plugins/agentbbs/package.json new file mode 100644 index 0000000..8c37d74 --- /dev/null +++ b/plugins/agentbbs/package.json @@ -0,0 +1,18 @@ +{ + "name": "@logicsrc/plugin-agentbbs", + "version": "0.1.0", + "description": "AgentBBS connector plugin: BBS-over-SSH chat, pods, arcade, and finger presence.", + "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "scripts": { + "build": "tsc -p tsconfig.json", + "test": "vitest run src --passWithNoTests" + }, + "dependencies": { + "@logicsrc/plugin-core": "file:../../packages/plugin-core" + }, + "devDependencies": { + "vitest": "^4.0.8" + } +} diff --git a/plugins/agentbbs/src/index.test.ts b/plugins/agentbbs/src/index.test.ts new file mode 100644 index 0000000..be6dcec --- /dev/null +++ b/plugins/agentbbs/src/index.test.ts @@ -0,0 +1,11 @@ +import { describe, expect, it } from "vitest"; +import { createPluginRegistry } from "@logicsrc/plugin-core"; +import { agentBbsPlugin } from "./index.js"; + +describe("agentbbs plugin", () => { + it("registers with a valid manifest", () => { + const registry = createPluginRegistry([agentBbsPlugin]); + expect(registry.get("agentbbs")?.enabled).toBe(true); + expect(registry.snapshot().capabilities["pods.provision"]).toEqual(["agentbbs"]); + }); +}); diff --git a/plugins/agentbbs/src/index.ts b/plugins/agentbbs/src/index.ts new file mode 100644 index 0000000..132d2e9 --- /dev/null +++ b/plugins/agentbbs/src/index.ts @@ -0,0 +1,27 @@ +import type { PluginDefinition } from "@logicsrc/plugin-core"; +import { agentBbsManifest } from "./manifest.js"; + +export const agentBbsPlugin: PluginDefinition = { + manifest: agentBbsManifest, + configDefaults: { + enabled: true, + ssh_host: "${AGENTBBS_SSH_HOST}", + ssh_port: "${AGENTBBS_SSH_PORT}", + ssh_key_path: "${AGENTBBS_SSH_KEY_PATH}", + default_route: "bbs" + }, + routes: [ + { method: "GET", path: "/api/plugins/agentbbs/status", capability: "bbs.status" }, + { method: "GET", path: "/api/plugins/agentbbs/chat", capability: "chat.read" }, + { method: "POST", path: "/api/plugins/agentbbs/chat", capability: "chat.send" }, + { method: "GET", path: "/api/plugins/agentbbs/pods", capability: "pods.list" }, + { method: "POST", path: "/api/plugins/agentbbs/pods", capability: "pods.provision" }, + { method: "GET", path: "/api/plugins/agentbbs/arcade", capability: "arcade.list" }, + { method: "GET", path: "/api/plugins/agentbbs/finger/:user", capability: "finger.lookup" } + ], + events: [{ event: "payment.confirmed", capability: "pods.membership" }], + permissions: ["bbs:read", "chat:send", "pods:provision"], + tuiPanels: [{ id: "agentbbs-status", title: "AgentBBS" }] +}; + +export { agentBbsManifest }; diff --git a/plugins/agentbbs/src/manifest.ts b/plugins/agentbbs/src/manifest.ts new file mode 100644 index 0000000..b95dc50 --- /dev/null +++ b/plugins/agentbbs/src/manifest.ts @@ -0,0 +1,22 @@ +import type { PluginManifest } from "@logicsrc/plugin-core"; + +export const agentBbsManifest: PluginManifest = { + id: "agentbbs", + name: "AgentBBS", + version: "1.0.0", + type: ["community", "chat", "hosting"], + default: false, + capabilities: [ + "bbs.status", + "chat.send", + "chat.read", + "pods.list", + "pods.provision", + "pods.membership", + "arcade.list", + "ascii.stream", + "finger.lookup" + ], + commands: ["bbs", "pod", "arcade"], + env: ["AGENTBBS_SSH_HOST", "AGENTBBS_SSH_PORT", "AGENTBBS_SSH_KEY_PATH"] +}; diff --git a/plugins/agentbbs/tsconfig.json b/plugins/agentbbs/tsconfig.json new file mode 100644 index 0000000..df59da5 --- /dev/null +++ b/plugins/agentbbs/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "dist" + }, + "include": ["src/**/*.ts"] +}