learnharness-plugins
GitHub用于构建、检查和调试 LearnHarness 插件的指南。涵盖 API 参考、架构契约、示例项目选择及安装流程,支持视图、交互、数据读取等扩展功能开发。
触发场景
安装
npx skills add amosblomqvist/learnharness --skill learnharness-plugins -g -y
SKILL.md
Frontmatter
{
"name": "learnharness-plugins",
"description": "Build, inspect, or debug trusted-local LearnHarness plugins using the public API. Covers views\/actions\/settings, host UI, teaching questions, practice problems, whole-session context, submission interception\/images, page-body surfaces, renderers, document conversion, learning-data readers, model calls, managed agents, workers and plugin lifecycle."
}
LearnHarness plugin authoring
Read the matching contract
Start with the authoring guide and documentation map, then use the complete API reference for exact signatures, members and linked data/event types. Read the feature contracts relevant to the task:
| Area | Reference |
|---|---|
| Host boundaries and implementation map | Architecture |
| Teaching questions/editors/grading | Question contract |
| Practice problems/editors/processing | Problem contract |
| Submission interception, images, surfaces | Session extensions |
| Read-only transcript/presentation/unsent drafts | View context |
| Controlled hierarchy presentation | Tree contract |
| Modal/menu/Escape/focus ownership | Interaction contract |
In a checkout, public types are under src/core/: plugins.ts, plugin-ui.ts,
plugin-agents.ts, plugin-workers.ts, plugin-questions.ts, plugin-problems.ts,
plugin-submissions.ts, plugin-view-context.ts, plugin-tree.ts.
These paths are repository-relative. Use type-only imports, never private runtime
modules. Emit portable declarations with node scripts/build-plugin-types.mjs.
Without a checkout, download the complete authoring skill from Settings → Community
plugins → Download authoring skill. Keep its root SKILL.md, docs/, examples/
and types/ together, including the portable tools/; use the included SDK rather than running repository build scripts.
Read bundle.json for the producing app/API/SDK versions. API v1 can gain capabilities:
check actual host compatibility rather than copying a stale minAppVersion. Exported
Hello/recipe distributions conservatively require the producing app version; canonical
official source manifests remain unchanged. Older targets need capability verification.
Choose a starting point
Begin with Hello for the smallest view/settings plugin. The example reading routes lead to the canonical UI Showcase, Drawing Pad, Coding Questions, Flashcards and Rich Code Blocks source projects included in the skill. Use them as real-world public-API references, not private host APIs. Core project IDs are reserved: do not install unchanged Community copies. The example guide distinguishes standalone build prerequisites from checkout-dependent tests. Managed Agent and Teaching Extension are focused recipes, not the primary starting points. Model-using recipes may incur cost when explicitly run.
Build and install
Prefer developing directly in <plugins-directory>/<plugin-id>/: clone/create the
project there, install its build dependencies, and run npm run build. Its output is
already the installed dist/; no copy step is needed. Find the directory in
Settings → Community plugins. The installed folder must match the manifest ID.
For an outside workspace, copy the skill's portable installer into the plugin project
and wire npm run install:local -- "<plugins-directory>" as described in the
authoring guide.
The command builds before replacing only installed dist/, preserving sibling data/.
No destination autodiscovery, saved configuration, automatic enablement or restart.
The included no-build examples can be copied directly; they do not need npm setup.
Guardrails
- Ask the human for product behavior, prompts, defaults, algorithms, source policy, interface and deletion decisions. The platform supplies mechanisms, not product authority.
- Plugins are trusted local code, not a sandbox. Never expose credentials, mutate core learning records, import host components or inject unsanitized model HTML.
- Community runtime layout is
<learning data>/plugins/<id>/dist/manifest.jsonplus bundles/assets. Optional source/build configuration lives besidedist/; persistentdata/is a sibling. Build directly intodist/, notdist/<id>/. Bundle JavaScript; no host-side npm install. - Distribute built contents into the installed
<id>/dist/, preserving sibling data. Cleanup targets only generateddist/, never workspace/data, and must refuse symlinkeddist/or misplaceddist/data/before deletion. - Core code loads directly from app
core-plugins/<id>/; writable core records are in<learning data>/core-plugin-data/<id>/. Always usectx.directory/ctx.dataDirectory, never infer sibling paths. Core updates with the app; both origins start disabled and retain explicit choices. Core IDs are reserved; community copies are skipped with a diagnostic, not replacements. Use Settings → Community plugins for installations and Settings → Core plugins for shipped features.plugins:build-corestages the four catalog-selected packages; it never installs into learner data. - Refresh discovers packages/first builds; admitted code changes need server restart. No hot reload, separate development registration or root-manifest fallback exists.
- Backend activation is per server; frontend activation per window; view/editor mounts have shorter lifetimes. Scope widgets to mount signals, clean up React roots/events/ subscriptions, fence late awaits/publications and avoid top-level side effects.
- Host view shells own top bar/title/gear. Register actions before explicit placements;
registration creates no automatic chrome. Top bars require explicit sessions/own-view
targets. Optional action
shortcutmetadata explicitly scopes app-wide/session/own-view invocation and an optional default chord; the existing Keyboard page handles rebinding. Acceptplacement: "keyboard"when opting in. UserefreshActions()for plugin-owned dynamic predicates; shortcut scope/default are captured at registration. - Use controlled
ctx.uihelpers, not private imports or DOM-dependent styling. Feed accepted values back through shallow handle updates; replace whole nested props. Model/thinking controls do not write core settings. Keep host keyboard/IME/focus, dictation ownership and one-Escape rules. Declarative action shortcuts do not expose raw events, bypass foreground dialogs/editors, or register OS-wide hotkeys. - Session top-bar
context.viewis a fresh detached/frozen whole-session snapshot, including current messages/transcript, presentation and unsent published drafts. Use it instead of a second history parser/shuffle or private DOM inspection. Reads never flush dictation, reveal, save, process or submit. Respect reveal/availability flags for learner-facing output; inspectable history is not sanitized visible prose. - Teaching questions use saved schemas/exact occurrence and validate → optional grade →
save → continue. Grading returns finite JSON observations; the plugin owns display.
Practice problems use validate → optional process → save → continue; only the model's
existing
concludeassesses/closes them. Never invent native envelopes or bypass unavailable implementations. Custom editor values must publish ready before submission. - Interceptors are ordered and fail closed while retaining drafts. Keep
hasPendingInputside-effect-free; callrefreshSubmissions()on external state changes. Consume only captured material through acknowledgedonAccepted, never model retry, dismissal or guessed acceptance after a lost response. Attach explicit native images, not paths/URLs or base64 inside answer JSON. Host thinking/images remain separate renderer channels. - Surfaces capture one page boundary or exact opaque target; never persist/reconstruct targets or retarget after awaits. They cover body only, expire on navigation and stay below Settings/dialogs. Use public content mounts and respect generation cleanup.
ctx.documents.toMarkdownaccepts a browser File (PDF/strict UTF-8), not paths or JSON-bridge uploads. It is bounded/cooperatively canceled, not OCR/storage/inference.- Inference needs explicit available model and truthful user/background purpose. No silent provider/key fallback. Managed conversations and result workers have distinct lifecycle/request-ID semantics; observation/navigation does not cancel execution. Disable/restart interrupts unfinished work; recovery never replays arbitrary tools.
- Notifications are live hints, not durable logs: use
onResyncplus current snapshots, and release observers rather than polling hidden views.
Test without disturbing the installation
Check plugin types/tests/build, runtime layout, disabled discovery, activation/cleanup, restart/data preservation, stale/async generations and native lifecycle paths actually used. Test through public APIs and real host controls, not private component imports in the plugin. Use disposable data and loopback providers where possible. Portable SDK, component/browser fixtures, packaged runtime checks and real-provider/OS tests establish different things; report those boundaries. App builds/installs, release changes, commits, plugin selection and distribution changes require their own human authorization.
版本历史
- cb25c8e 当前 2026-11-13 18:21


