@op-lean/emdash-plugin
v0.2.0
Published
Sandboxed EmDash plugin for scheduled Original Poster AI drafts.
Readme
Original Poster for EmDash
Sandboxed plugin for EmDash 1.0.1 or later. It creates article drafts and separate revision drafts through the paid Original Poster service. It never publishes content.
The plugin is free and MIT licensed. Generation requires a service subscription sold through Stripe. Topics and selected source content leave the site for the private service and its configured AI provider. Disconnecting stops local scheduling and removes credentials. It does not cancel Stripe or undo a provider call already started.
Package installation
Version 0.2.0 uses the sandbox descriptor. For local verification, build and pack the plugin workspace, then install its tarball in a test site.
npm run build --workspace plugin
npm pack --workspace plugin --pack-destination .localnpm install @op-lean/emdash-pluginimport originalPoster from "@op-lean/emdash-plugin";
// In the site's existing emdash(...) configuration:
sandboxed: [originalPoster],Use the site's standard sandbox runner. On Cloudflare it requires Worker Loader, PluginBridge, plugin code storage, an EmDash encryption key and the EmDash scheduler with a Cron Trigger. These belong to the site host. Open Original Poster in the Plugins menu, connect the paid service, then configure topics and a schedule. Credentials are saved in encrypted EmDash settings; no per-plugin Worker secret is needed.
Generation runs in the private service's Cloudflare Workflow. A plugin cron task retrieves its result and saves a draft after the browser closes. A job the service reports as failed, for example over the spend limit, is cleared and shown as an error; the next Create draft starts a new paid job. A job whose result could not be read or saved stops automatic polling. Check access and the service spend ledger, then check the result again or discard the job.
The destination collection must have title: string and content: portableText. The default is posts. Configure the collection in plugin settings. Revision drafts preserve the source entry.
Interrupted draft saves
A retry of the same generation job uses its stored output. CMS creation is a separate operation. completeContentWrite in src/flow.ts creates the draft, stores its ID in plugin KV, sends that ID to /v1/content-complete, and deletes the KV receipt. finishPendingDraft then deletes the pending job.
An interruption can create a second draft in two cases:
- CMS commits the draft, but its bridge reply is lost or execution stops before the KV receipt is stored. Recovery cannot find the first draft's ID and calls CMS create again.
- The service confirms completion and the plugin deletes its KV receipt, but execution stops before pending-job deletion. Recovery still sees the job. This polling path does not check the service's completed-write receipt before calling CMS create again.
While the KV receipt exists, recovery reuses its ID, including after a failed completion request. The first gap predates the sandbox migration. The second is in the asynchronous polling path introduced in 0.2.0. Both remain unresolved. They can duplicate a CMS draft using the existing generation output; they do not themselves request another paid generation or publish either draft. These are code-identified failure windows, not an observed production incident. Successful local retry checks do not prove crash-safe CMS creation.
Build and verification
npm ci
npm run check
npm test
npm run build
npm run bundle --workspace pluginThe pinned official @emdash-cms/[email protected] builds dist/plugin.mjs, dist/manifest.json and the default npm descriptor dist/index.mjs. Only the plugin workspace is distributable. The private service, D1 database and provider secrets are excluded.
emdash-plugin.jsonc pins publisher did:plc:ug6xwhbclf7z3hprhpje4gdh, currently originalposter-ai.bsky.social. The official CLI checks that the authenticated publisher matches this identity before registry publication. Manual registry releases upload the bundle to this publisher's PDS. Delegated repository releases require a public plugin-only source repository. npm publication does not add a catalog listing. Hosting and rollout belong to op-lean.
The service must deploy GenerationWorkflow and its GENERATION binding before client rollout. This migration has not deployed either component.
