Repository navigation
feat: explicit skill invocation in TUI and desktop, aligned on a shared runtime contract #1148
Copy link
Copy link
Closed
Labels
enhancementNew feature or requestNew feature or request
Description
Problem
Skill support today is model-driven only: the agent may call the Skill tool when a request looks relevant, but users have no reliable way to explicitly invoke a skill. Three verified gaps:
- TUI has no manual trigger at all. The prompt fragment advertises the skill catalog and the
Skilltool is wired with host gating (packages/cli/src/runtime-bootstrap.ts), but a user who wants a specific skill can only ask for it in prose and hope. - Desktop
/popup lists only workspace-installed skills. It is fed byskills:list→scanWorkspaceSkills(single-root,{workspaceRoot}/skills/), while the runtime injects from five discovery paths (resolveSkillDiscoveryPaths:{cwd}/.maka/skills,{cwd}/.agents/skills,{workspaceRoot}/skills,~/.maka/skills,~/.agents/skills). Agent-visible skills are invisible to users. - Desktop skill injection never applies the host-capability gate. Both call sites pass
host === undefined(system-prompt-main.ts→buildSkillsPromptFragment,main.ts→buildSkillAgentTool), which the runtime explicitly treats as legacy no-gating.required-tools/required-capabilitiesmetadata is inert on desktop, and the prompt can advertise skills the session cannot load (the desktop tool set is conditionally assembled, so this is not theoretical). The CLI already does this correctly.
Design (agreed)
One shared contract in @maka/runtime (skill-invocation module), consumed by both clients:
listInvocableSkills(source, host)— five-path scan + host gate + enablement → slim entries; the single source for TUI autocomplete/highlight validation and the desktop discoverable IPC.resolveSkillInvocations+composeSkillInvocationMessage— load via the existingloadSkillInstructionssemantics (truncation, cleaning, gating) and compose the final user message (instruction blocks carry the existing user-provided trust framing; no permission escalation).
TUI (packages/cli)
/skill:<name>tokens inline in the input, anywhere in the text, multiple allowed (deduped, order-preserving)./skill:triggers dynamic autocomplete fromlistInvocableSkills; bare/skillopens a picker (the/modelpattern) that only inserts the token.- Valid tokens are highlighted in the editor in the CLI brand accent color; invalid tokens are simply not highlighted — absence of the affordance is the inactive state (no separate inactive styling).
- Tokens are parsed at submit time; the CLI (not the model) deterministically loads and injects instructions. Failed tokens stay as literal text and the send proceeds with at most a non-blocking notice — sending is the high-frequency path and must never be blocked by skill resolution.
Desktop (apps/desktop + packages/ui)
- The
/popup and its inserted text (使用 X 技能:) stay as-is; selecting a skill additionally creates an invocation chip{id, name}. - Chips render inline at the head of the input flow (flex-wrap container, textarea keeps all native behavior; no contenteditable, no attachment-lane elevation), using the existing
Chipprimitive (accent) + Blocks icon + name, multiple allowed, hover-to-remove. Chips that are no longer invocable are silently dropped on skills-list refresh — a chip is the active-invocation indicator, so an invalid one must not exist. sessions:sendgains an optionalskillIdsfield; main resolves and injects via the shared module beforeruntime.sendMessage. Races resolve silently in favor of sending.- The discoverable IPC (popup data source) switches to
listInvocableSkills, closing gap 2; desktop passes a realHostCapabilitiesbuilt from the assembled tool list to both injection call sites, closing gap 3.
Delivery plan
| PR | Scope | Depends on |
|---|---|---|
| 1 | runtime skill-invocation module + TUI end-to-end (TUI as first consumer proves the contract) |
— |
| 2 | desktop host-capability gating for skill injection (standalone bug fix) | — |
| 3 | desktop discoverable IPC + inline chips + main-side injection | 1, 2 |
Non-goals
- contenteditable rewrite or overlay-highlight tricks in the desktop composer
- forking/patching
pi-tui's Editor (highlighting is a render post-process in our subclass) - registering each skill as a top-level slash command
- any special "inactive" visual state on either client
- desktop skill management (panel stays workspace-scoped)
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request
Activity
feat: explicit skill invocation via /skill:<name> tokens in the TUI (#…
Nyvo-io commentedon Jul 18, 2026
I would like to claim Part 2 of #1148: Desktop host-capability gating for skill discovery and injection.
The TUI/runtime contract work in #1150 is already merged, so I will focus on the standalone Desktop slice described in the issue:
I will add focused regression coverage for unavailable required tools/capabilities and verify that eligible skills continue to load with the existing instruction semantics. The Desktop discovery IPC and inline invocation chips remain Part 3 and are out of scope for this PR. I will wait for maintainer confirmation before creating the implementation branch.
Astro-Han commentedon Jul 18, 2026
Assigned!
Astro-Han commentedon Jul 25, 2026
Closing as completed/superseded.
The shared runtime and TUI invocation path landed in #1150. Desktop capability gating and invocation correctness landed through #1224, #1240, #1282, and #1386. The remaining TUI
/skillsproduct decision is isolated in #1279, while Desktop Skills visual simplification is tracked by #1452.There is no remaining implementation unique to this issue.