mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-12 14:16:28 +03:00
* Add DeepSeek Harness as a supported skills provider npx impeccable install now detects ~/.dsh (or $DSH_HOME when it sits under home) and installs into ~/.dsh/skills, the user-level skill root DeepSeek Harness scans, with project-level .dsh/skills on the same layout as other providers. Aliases: dsh, deepseek, deepseek-harness. Engine: PROVIDER_DIRS / aliases / display / input order / global hint, $DSH_HOME-aware user skills dir, provider id resolution from the skill dir, pin harness dirs, bundle path normalization for hashing. Build: dsh transformer target emitting the frontmatter DeepSeek Harness reads (user-invocable, license, compatibility, metadata; unknown keys are ignored there) with no emitHooks (DSH hooks are in-process plugins, not on-disk manifests) and no agentFormat (no documented on-disk subagent format); placeholders (AGENTS.md config file, ask_user_question tool, / command prefix), provider block tags, universal README entry. Docs: HARNESSES.md row and frontmatter column, CLI-CONTRACT constants, README/DEVELOP/AGENTS provider lists. Validation: cargo test --workspace; node scripts/run-tests.mjs core (138 pass); bun run build (19 providers, dist/dsh artifact verified); engine smoke against a fake HOME with a local bundle: install --providers=dsh --scope=global, auto-detected install, and update all resolve the .dsh provider. Generated provider output intentionally omitted per repo policy; the sync workflow regenerates tracked .dsh/skills after merge. Prepared with AI assistance (DeepSeek Harness coding agent). * Address review: DSH_HOME-only detection, generated-output pathspecs - Detect DeepSeek Harness through the resolved $DSH_HOME (fallback ~/.dsh) instead of gating on a fixed ~/.dsh path, so a DSH_HOME-only setup is offered by a provider-less install; generalize the two env-relocated config-dir hints (OpenCode, DSH) into one shared probe. - Add .dsh to the sync workflow's GENERATED_PATHS and CI's generated drift check so the tracked .dsh/skills payload is committed and validated. - Cover both behaviors: new install_detection_tests (DSH_HOME-only, default ~/.dsh, refused outside-home override) and a CLI-CONTRACT note on the resolved detection path. Validation: cargo test --workspace; node scripts/run-tests.mjs core (138 pass); engine smoke: DSH_HOME-only fake HOME installs globally into the resolved skills dir. Prepared with AI assistance (DeepSeek Harness coding agent). * Fix DeepSeek Harness home paths on Windows Use native relative-path containment, cover case and drive boundaries, and verify relocated global install/update without changing project skills. Add DSH output coverage and correct the install documentation. AI assistance: Codex, under pbakaus maintainer direction. * Document the CLI limit on external DSH homes Clarify that outside-home manual copies are not detected or updated by the CLI. AI assistance: Codex, under pbakaus maintainer direction. --------- Co-authored-by: Paul Bakaus <paul.bakaus@gmail.com>
207 lines
7.9 KiB
JavaScript
207 lines
7.9 KiB
JavaScript
/**
|
|
* Provider configurations for the transformer factory.
|
|
*
|
|
* Each config specifies:
|
|
* - provider: key into PROVIDER_PLACEHOLDERS (e.g. 'claude-code')
|
|
* - configDir: dot-directory name (e.g. '.claude')
|
|
* - displayName: human-readable name for log output (e.g. 'Claude Code')
|
|
* - providerTags: markdown block tags kept for this target (e.g. <codex>...</codex>)
|
|
* - frontmatterFields: which optional fields to emit beyond name + description
|
|
* - bodyTransform: optional function (body, skill) => transformed body
|
|
*/
|
|
export const PROVIDERS = {
|
|
cursor: {
|
|
provider: 'cursor',
|
|
providerTags: ['cursor'],
|
|
configDir: '.cursor',
|
|
displayName: 'Cursor',
|
|
frontmatterFields: ['license', 'compatibility', 'metadata'],
|
|
// Cursor subagents: `.cursor/agents/<name>.md` at repo level,
|
|
// `~/.cursor/agents/` at user level. Project agents take precedence over
|
|
// user ones, so installs simply overwrite on update.
|
|
agentFormat: 'cursor-md',
|
|
emitHooks: 'cursor',
|
|
// Cursor reads `.cursor/hooks.json`, not `.cursor/hooks/hooks.json`.
|
|
hooksManifestRel: 'hooks.json',
|
|
},
|
|
'claude-code': {
|
|
provider: 'claude-code',
|
|
providerTags: ['claude-code', 'claude'],
|
|
configDir: '.claude',
|
|
displayName: 'Claude Code',
|
|
frontmatterFields: ['user-invocable', 'argument-hint', 'license', 'compatibility', 'metadata'],
|
|
// allowed-tools omitted: Claude Code blocks skill activation in non-interactive
|
|
// sessions when the field is present (issue #736). Other providers keep it.
|
|
agentFormat: 'claude-md',
|
|
emitHooks: 'claude',
|
|
// Project-local Claude Code hooks live in `.claude/settings.json`.
|
|
hooksManifestRel: 'settings.json',
|
|
},
|
|
gemini: {
|
|
provider: 'gemini',
|
|
providerTags: ['gemini'],
|
|
configDir: '.gemini',
|
|
displayName: 'Gemini',
|
|
frontmatterFields: [],
|
|
},
|
|
dsh: {
|
|
provider: 'dsh',
|
|
providerTags: ['dsh'],
|
|
configDir: '.dsh',
|
|
displayName: 'DeepSeek Harness',
|
|
// DeepSeek Harness reads the Agent Skills spec subset (`name`,
|
|
// `description`, `license`, `compatibility`, `metadata`) plus
|
|
// `user-invocable` and `disable-model-invocation`; unknown keys are
|
|
// silently ignored. No hook surface (hooks are in-process plugins, not
|
|
// on-disk manifests) and no native subagent file format, so no
|
|
// emitHooks / agentFormat. Global skills live at ~/.dsh/skills
|
|
// ($DSH_HOME/skills when set), matching the engine's home override.
|
|
frontmatterFields: ['user-invocable', 'license', 'compatibility', 'metadata'],
|
|
},
|
|
codex: {
|
|
provider: 'codex',
|
|
providerTags: ['codex'],
|
|
configDir: '.codex',
|
|
displayName: 'Codex',
|
|
frontmatterFields: [],
|
|
// Codex's validator rejects unknown top-level keys. Version remains
|
|
// available to Impeccable's updater under the spec-defined metadata map.
|
|
versionInMetadata: true,
|
|
writeOpenAIMetadata: true,
|
|
// No agentFormat: the Codex subagent ships nested inside the skill's own
|
|
// agents/ folder (see CODEX_SKILL_PROVIDERS in factory.js), which Codex
|
|
// auto-discovers on install. No top-level .codex/agents/ sidecar is emitted.
|
|
emitHooks: 'codex',
|
|
// Codex discovers project-local hooks at `.codex/hooks.json`.
|
|
hooksManifestRel: 'hooks.json',
|
|
},
|
|
agents: {
|
|
provider: 'agents',
|
|
providerTags: ['agents', 'codex'],
|
|
configDir: '.agents',
|
|
displayName: 'Codex Repo Skills',
|
|
placeholderProvider: 'codex',
|
|
frontmatterFields: [],
|
|
versionInMetadata: true,
|
|
writeOpenAIMetadata: true,
|
|
},
|
|
github: {
|
|
provider: 'github',
|
|
providerTags: ['github'],
|
|
configDir: '.github',
|
|
displayName: 'GitHub Copilot',
|
|
placeholderProvider: 'agents',
|
|
frontmatterFields: ['user-invocable', 'argument-hint', 'license', 'compatibility', 'metadata'],
|
|
// Copilot custom agents: `.github/agents/<name>.agent.md` at repo level,
|
|
// `~/.copilot/agents/` at user level (the CLI installer handles placement).
|
|
// The degraded/ fallbacks still ship for Copilot surfaces where the model
|
|
// fails to delegate; the .agent.md files are the real subagent path.
|
|
agentFormat: 'copilot-agent-md',
|
|
emitHooks: 'github',
|
|
// GitHub Copilot discovers repo-level hooks under `.github/hooks/*.json`.
|
|
hooksManifestRel: 'hooks/impeccable.json',
|
|
},
|
|
kiro: {
|
|
provider: 'kiro',
|
|
providerTags: ['kiro'],
|
|
configDir: '.kiro',
|
|
displayName: 'Kiro',
|
|
frontmatterFields: ['license', 'compatibility', 'metadata'],
|
|
},
|
|
opencode: {
|
|
provider: 'opencode',
|
|
providerTags: ['opencode'],
|
|
configDir: '.opencode',
|
|
displayName: 'OpenCode',
|
|
frontmatterFields: ['user-invocable', 'argument-hint', 'license', 'compatibility', 'metadata', 'allowed-tools'],
|
|
},
|
|
pi: {
|
|
provider: 'pi',
|
|
providerTags: ['pi'],
|
|
configDir: '.pi',
|
|
displayName: 'Pi',
|
|
frontmatterFields: ['license', 'compatibility', 'metadata', 'allowed-tools'],
|
|
},
|
|
qoder: {
|
|
provider: 'qoder',
|
|
providerTags: ['qoder'],
|
|
configDir: '.qoder',
|
|
displayName: 'Qoder',
|
|
frontmatterFields: ['user-invocable', 'argument-hint', 'license', 'compatibility', 'metadata', 'allowed-tools'],
|
|
},
|
|
'trae-cn': {
|
|
provider: 'trae-cn',
|
|
providerTags: ['trae-cn', 'trae'],
|
|
configDir: '.trae-cn',
|
|
displayName: 'Trae China',
|
|
placeholderProvider: 'trae',
|
|
frontmatterFields: ['user-invocable', 'argument-hint', 'license', 'compatibility', 'metadata'],
|
|
},
|
|
trae: {
|
|
provider: 'trae',
|
|
providerTags: ['trae'],
|
|
configDir: '.trae',
|
|
displayName: 'Trae',
|
|
frontmatterFields: ['user-invocable', 'argument-hint', 'license', 'compatibility', 'metadata'],
|
|
},
|
|
'rovo-dev': {
|
|
provider: 'rovo-dev',
|
|
providerTags: ['rovo-dev'],
|
|
configDir: '.rovodev',
|
|
displayName: 'Rovo Dev',
|
|
frontmatterFields: ['user-invocable', 'argument-hint', 'license', 'compatibility', 'metadata', 'allowed-tools'],
|
|
},
|
|
vibe: {
|
|
provider: 'vibe',
|
|
providerTags: ['vibe'],
|
|
configDir: '.vibe',
|
|
displayName: 'Mistral Vibe',
|
|
frontmatterFields: ['user-invocable', 'license', 'compatibility', 'metadata', 'allowed-tools'],
|
|
},
|
|
veto: {
|
|
provider: 'veto',
|
|
providerTags: ['veto'],
|
|
configDir: '.veto',
|
|
displayName: 'Veto',
|
|
frontmatterFields: ['license', 'compatibility', 'metadata'],
|
|
},
|
|
grok: {
|
|
provider: 'grok',
|
|
providerTags: ['grok'],
|
|
configDir: '.grok',
|
|
displayName: 'Grok Build',
|
|
// Grok's skill frontmatter matches the Agent Skills spec plus Claude-style
|
|
// extensions (user-invocable, argument-hint, allowed-tools, model, effort).
|
|
// See https://docs.x.ai/build/features/skills-plugins-marketplaces and
|
|
// ~/.grok/docs/user-guide/08-skills.md.
|
|
frontmatterFields: ['user-invocable', 'argument-hint', 'license', 'compatibility', 'metadata', 'allowed-tools'],
|
|
// Project/user agents are markdown with YAML frontmatter (Claude-compatible).
|
|
agentFormat: 'claude-md',
|
|
emitHooks: 'grok',
|
|
// Grok discovers project hooks from `.grok/hooks/*.json` (not a single
|
|
// settings.json). Claude tool-name matchers alias to Grok tools.
|
|
hooksManifestRel: 'hooks/impeccable.json',
|
|
},
|
|
antigravity: {
|
|
provider: 'antigravity',
|
|
providerTags: ['antigravity'],
|
|
configDir: '.agent',
|
|
displayName: 'Antigravity',
|
|
frontmatterFields: ['license', 'compatibility', 'metadata', 'allowed-tools'],
|
|
},
|
|
hermes: {
|
|
provider: 'hermes',
|
|
providerTags: ['hermes'],
|
|
configDir: '.hermes',
|
|
displayName: 'Hermes Agent',
|
|
// Hermes ships the Agent Skills spec as-is. The optional fields below
|
|
// (license, compatibility, metadata) are spec-defined; harness-specific
|
|
// extensions (user-invocable, argument-hint, allowed-tools) are NOT
|
|
// recognized by the Hermes skill loader and would be silently ignored.
|
|
// Hermes also has no hook surface, no equivalent of Claude's slash
|
|
// commands, and no per-skill tool ACL -- so no emitHooks, no agentFormat,
|
|
// no writeOpenAIMetadata. See hermes-agent/SKILL.md "Skills" section.
|
|
frontmatterFields: ['license', 'compatibility', 'metadata'],
|
|
},
|
|
};
|