Official

market

The plugin marketplace: browse, install through an agent's scan, update and publish plugins, and the marketplace tools of agents in the Plugins workspace.

The app opens the listing; nothing installs until an agent in your Plugins workspace has read the files and you enable the plugin. In a terminal: cvg install convergence/market@0.1.0

Permissions in 0.1.0

  • Marketplace marketOfficial onlyUses the marketplace APIs. Only official plugins can have it.Search, read, install, update and publish marketplace plugins, and sign in to the marketplace
  • Manage plugins plugins.manageOfficial onlyReloads and enables plugins. Only official plugins can have it.Ask for the enable card of a plugin an agent installed
  • Control chats chats.controlHighCreates chats, sends prompts and cancels runs.Open the chat in the Plugins workspace where an agent scans, installs or updates a plugin
  • Provide agent tools tools.provideMediumGives tools to agents.Give agents in the Plugins workspace the marketplace tools
  • Read chats chats.readMediumReads your transcripts and chat lists.Find the agent, model and effort last used in the Plugins workspace
  • Show panels ui.slotsLowShows views in the listed parts of the window.Show the marketplace button, with its update count, and the marketplace pageSlots: railcenter

Files

state.ts3.7 KB
// The marketplace page's state belongs to one activation; the controller
// mutates it and the views read it. The view handles let asynchronous host
// answers request a render.
import * as Context from "effect/Context";
import * as Layer from "effect/Layer";
import type { AgentInfo, ViewHandle } from "convergence";
import type { AgentChoice, AgentOption } from "./logic.ts";
import { CATEGORIES } from "./logic.ts";
import type {
  BugDraft,
  BugPreview,
  Listing,
  MarketAccount,
  MarketComments,
  MarketRelease,
  MarketReleaseFile,
  MarketUpdateItem,
  SentReport,
} from "./remote.ts";

export const ROUTE = "market";

export type Page = "browse" | "listing" | "updates" | "bugs";

export interface Menus {
  readonly agents: readonly AgentInfo[];
  readonly options: readonly AgentOption[];
  readonly choice: AgentChoice;
  readonly error?: string;
}

export interface AccountState {
  readonly signedIn: boolean;
  readonly registry?: string;
  readonly error?: string;
  readonly expired?: boolean;
}

export interface SignIn {
  readonly code: string;
  readonly url: string;
}

export interface OpenFile {
  readonly path: string;
  readonly loading: boolean;
  readonly text?: string;
  readonly size?: number;
  readonly truncated?: boolean;
  readonly binary?: boolean;
  readonly error?: string;
}

export type CommentsState = MarketComments | "loading" | { readonly error: string };

export interface ReportDraft {
  reason: string;
  files: string;
}

// The bug report form (§14.1) and the request waiting on its send card.
export interface BugState {
  loading: boolean;
  error: string | null;
  draft: BugDraft | null;
  chosen: Set<string>;
  fullSource: Set<string>;
  screenshots: string[];
  text: string;
  email: string;
  preview: BugPreview | null;
  previewing: boolean;
  previewError: string | null;
  unchecked: Set<string>;
  open: Set<string>;
  previewKey?: string;
  seen?: Set<string>;
  requestId: string | null;
  fixAfter: boolean;
  sent: SentReport | null;
}

export interface State {
  loaded: boolean;
  page: Page;
  query: string;
  category: string | null;
  sort: string;
  results: readonly Listing[] | null;
  total: number;
  pageNo: number;
  searching: boolean;
  searchError: string | null;
  categories: readonly { readonly id: string | null; readonly title: string }[];
  listing: Listing | null;
  listingId: string | null;
  listingError: string | null;
  version: string | null;
  tab: string;
  tree: MarketRelease | "loading" | null;
  treeError: string | null;
  file: OpenFile | null;
  comments: CommentsState | null;
  report: ReportDraft | null;
  updates: readonly MarketUpdateItem[];
  updatesGeneration: number;
  busy: Record<string, boolean>;
  menus: Menus | null;
  direct: boolean;
  account: MarketAccount | AccountState | null;
  signIn: SignIn | null;
  linkNonce: unknown;
  bug: BugState | null;
  reports: readonly SentReport[];
  settingsSchema: { key: string; settings: unknown } | null;
  views: ViewHandle[];
}

export const initialState = (): State => ({
  loaded: false,
  page: "browse",
  query: "",
  category: null,
  sort: "",
  results: null,
  total: 0,
  pageNo: 1,
  searching: false,
  searchError: null,
  categories: CATEGORIES,
  listing: null,
  listingId: null,
  listingError: null,
  version: null,
  tab: "permissions",
  tree: null,
  treeError: null,
  file: null,
  comments: null,
  report: null,
  updates: [],
  updatesGeneration: 0,
  busy: {},
  menus: null,
  direct: false,
  account: null,
  signIn: null,
  linkNonce: null,
  bug: null,
  reports: [],
  settingsSchema: null,
  views: [],
});

export class MarketState extends Context.Service<MarketState, State>()("market/State") {
  static readonly layer = Layer.sync(MarketState, initialState);
}

Versions

VersionPublishedPlugin APISizePermissionsStatus
0.1.0latestOct 5, 2026>=2 <344.9 KB6 permissionsListed

Reviews and comments

0 threads · 0 reviews

No comments yet.