Download the PHP package spora-ai/spora-plugin-custom-skills-frontend without Composer

On this page you can find all versions of the php package spora-ai/spora-plugin-custom-skills-frontend. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package spora-plugin-custom-skills-frontend

spora-plugin-custom-skills-frontend

Vue 3 IIFE bundle for the Spora Custom Skills admin panel. The host SPA lazy-loads it at /plugins/custom-skills/main.js and mounts it into the /apps/custom-skills slot via the global window.SporaAppCustomSkills.

The PHP half of the panel lives in spora-plugin-custom-skills; this repo ships only the built assets. The REST contract both halves speak is published at https://docs.spora-ai.com/reference/api#custom-skills-spora-plugin-custom-skills — read it before changing anything under src/api/.

What the panel does

One page per destination, each with a subject of its own. The panel used to be a workspace: one route rendering the editor above two lists, a second route pushing a name into the same screen, and a query param for the third case. That holds only while there is exactly one thing to do.

Route Page Source Mutability
/p/{pid} Home — what this principal owns GET /api/v1/custom-skills (this plugin) navigates
/p/{pid}/new Create — a name, then the desk POST /api/v1/custom-skills writes once
/p/{pid}/skill/{name} Desk — write GET/PUT/DELETE /api/v1/custom-skills/{name} full CRUD + restore
/p/{pid}/library Catalogue — every shipped skill GET /api/v1/skills (the host) read-only + Duplicate
/p/{pid}/library/{name} Viewer — read a shipped skill GET /api/v1/skills/{name} + …/files/{path} per sidecar (the host) read-only

Four routing decisions worth defending:

src/lib/paths.ts holds every path the panel navigates to, as pure builders taking the principal. It exists so a link cannot be built without one: roughly fifteen call sites once concatenated /skills/${skill.name} by hand, and each was an independent chance to re-open the wrong-scope bug. src/lib/routes.ts holds the route table, shared with dev-main.ts and the specs — it used to be copied into each, and the copies drifted.

Pre-shipped skills are served by spora-core's SkillController, which has three routes (index, show, file). The frozen contract lists them under "Not endpoints (deliberately)": this plugin must never re-serve them, or the two copies drift. file is how a sidecar's contents are read — the detail route lists a sidecar's path and size but serves only the SKILL.md body, so a viewer cannot open anything else without it.

The four affordances

Each of these exists because its absence produces a support ticket, not because it is a nice-to-have:

  1. The principal is always visible. A sticky bar on every page, carrying a skill count per entry. A row of equal-weight chips reads as filters, and a filter chip does not say "everything below belongs to what I picked". The contract returns one principal's skills per call and has no count endpoint, so each entry is its own GET /custom-skills?principal_id=N, read on open.
  2. Validation feedback — a rejected write answers 422 SKILL_INVALID with a ValidationResult array. SkillDesk.vue renders each entry under the field its path names; warnings, plus any error no field claims, go to a banner. Nothing the validator said is dropped.
  3. Fork from pre-shipped — every shipped row has Duplicate. Without it the only path to a first skill is a blank editor, and the shipped skills are exactly the worked examples people copy from. Forks always get a non-reserved name (forkName()); a shipped slug answers 409 SKILL_NAME_RESERVED.
  4. Allowlist affordance — a row's menu lists the agents that currently resolve it (from GET …/{name}/allowlist, read when the menu opens) and offers Enable on agent…, which writes the agent's skill tool allowed_skills override. The empty state reads "Not enabled for any agent yet — add it to an agent's Skill tool settings before the agent can use it." — the operator otherwise discovers the problem only when the agent replies "Skill 'x' is not in the allowed_skills list for this agent."

Plus: deleting a skill is a multi-agent config change, so the confirmation dialog reads the allowlist before the write and names the agents that will be scrubbed (store.requestDelete()). scrubbed_agents on the delete response is only used to report what actually changed — it arrives too late to warn anyone.

There is no in-panel search

Deliberately. A ⌘K palette already exists one layer up and covers agents, groups and chats. A second search box inside a plugin panel is not a shortcut to the same thing — it is two search boxes that disagree, and this one would be strictly narrower, since the store only ever holds the selected principal's skills, so "search" would quietly mean "search what happens to be in memory". The panel is sorted-and-scrolled instead: every list has a sort control, and "recently used" is not one of the options because nothing records a skill's last invocation.

Layout

Responsive rule

The scope bar wraps and stays sticky. The desk stacks below md and splits above it, and the split says so with an explicit base flex-col plus md:flex-row — a direction variant with no base direction resolves to the CSS initial row and silently disables every md: sizing on the rail beside it. The rail is not hidden at any width: it is capped at 38vh and scrolls inside that, so a skill with a dozen sidecars cannot push the editor off the bottom of the window, and a file <select> in the footer is the second way to name the open file in a narrow one. The desk's preview is not responsive: MdEditor owns it through :preview="true" plus the toolbar's own preview / previewOnly entries, so there is no panel-level mode group to make responsive. The catalogue's per-row file count and licence are always shown; the row wraps its actions onto their own line below sm rather than dropping the meta.

The scope root carries no utility classes

tailwind.config.ts sets important: '#spora-plugin-custom-skills', which compiles to a descendant selector — #spora-plugin-custom-skills .flex. That cannot match the element carrying the id, so a utility class on the panel root is dead CSS that still reads correctly in the source, and the root falls back to a content-sized block. That in turn leaves the desk's h-full resolving against an auto-height parent, which is the whole reason the page once grew to five viewports.

The root's frame (display: flex, min-height: 100vh, the background token) is therefore hand-written in src/style.css, which is emitted verbatim rather than through the prefix. tests/buildAssets.spec.ts asserts both halves of this: the prefix stays a descendant selector, and the root carries no class. If the prefix ever changes to something that matches the scope element, those tests are what should make you notice.

Host globals contract

vite.config.ts externalises four modules and maps them to host globals:

Module Global Published by the host?
vue window.Vue yes (publishPluginGlobals)
pinia window.Pinia yes
vue-router window.VueRouter yes
md-editor-v3 window.MdEditorV3 yes

spora-frontend/src/utils/publishPluginGlobals.ts publishes exactly five globals: Vue, Pinia, VueRouter, VueDraggablePlus and MdEditorV3. Four of them are consumed by this bundle; VueDraggablePlus is published for other plugins.

lucide-vue-next and dompurify are bundled, not externalised, and must stay that way. The host does not publish them, and a bundle that externalises an unpublished global does not degrade — it throws while the IIFE argument list is being resolved, so window.SporaAppCustomSkills is never assigned and the panel is unreachable. spora-plugin-memories-frontend bundles the same two for the same reason; match it.

output.extend must stay off. The host loads this bundle through a dynamic import(), where module scope is undefined, so extend: true emits this.SporaAppCustomSkills = … and throws before the real global is ever assigned. scripts/smoke.js fails the build on that wrapper shape.

Two signals mean the contract drifted:

Commands

npm run build writes frontend/main.js and frontend/style.css. SporaPluginFrontendInstaller copies that directory verbatim into public/plugins/custom-skills/ at install time — do not rename either file.

Tests

md-editor-v3 is stubbed in tests/setup.ts (CodeMirror 6 + highlight.js + katex + mermaid do not run under happy-dom). lucide-vue-next and dompurify are the real modules in tests, so the sanitiser assertion stays meaningful.

Page specs mount through tests/mountPage.ts, which installs the real Pinia and the real route map: the panel is page-per-destination, so a page mounted without a router renders its RouterLinks as bare elements and reads START_LOCATION.

Releasing

See RELEASING.md. In short: bump package.json and composer.json (including dist.url), then tag v<version>. The build-and-release job fails if dist.url does not match the tag.


All versions of spora-plugin-custom-skills-frontend with dependencies

PHP Build Version
Package Version
Requires php Version ^8.4.1
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package spora-ai/spora-plugin-custom-skills-frontend contains the following files

Loading the files please wait ...