@open-agent-toolkit/cli 0.2.31 → 0.2.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/bundle-metadata.json +1 -1
- package/assets/docs/contributing/code.md +13 -1
- package/assets/docs/provider-sync/commands.md +15 -10
- package/assets/docs/provider-sync/manifest-and-drift.md +23 -0
- package/assets/docs/provider-sync/providers.md +8 -2
- package/assets/docs/provider-sync/scope-and-surface.md +3 -1
- package/assets/docs/reference/file-locations.md +5 -0
- package/assets/docs/reference/troubleshooting.md +18 -0
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/create-agnostic-skill/references/docs/skills-guide.md +34 -22
- package/assets/skills/oat-agent-instructions-analyze/references/docs/provider-reference.md +14 -2
- package/assets/skills/oat-agent-instructions-apply/references/docs/provider-reference.md +14 -2
- package/dist/commands/init/index.d.ts +2 -2
- package/dist/commands/init/index.d.ts.map +1 -1
- package/dist/commands/init/index.js +22 -13
- package/dist/commands/remove/skill/remove-skill.d.ts +4 -1
- package/dist/commands/remove/skill/remove-skill.d.ts.map +1 -1
- package/dist/commands/remove/skill/remove-skill.js +44 -5
- package/dist/commands/shared/adopt-stray.d.ts +5 -0
- package/dist/commands/shared/adopt-stray.d.ts.map +1 -1
- package/dist/commands/shared/adopt-stray.js +25 -4
- package/dist/commands/shared/native-skill-disposition.d.ts +22 -0
- package/dist/commands/shared/native-skill-disposition.d.ts.map +1 -0
- package/dist/commands/shared/native-skill-disposition.js +60 -0
- package/dist/commands/status/index.d.ts +2 -2
- package/dist/commands/status/index.d.ts.map +1 -1
- package/dist/commands/status/index.js +22 -13
- package/dist/engine/compute-plan.d.ts +3 -2
- package/dist/engine/compute-plan.d.ts.map +1 -1
- package/dist/engine/compute-plan.js +1 -1
- package/dist/engine/index.d.ts +1 -1
- package/dist/engine/index.d.ts.map +1 -1
- package/dist/engine/index.js +1 -1
- package/dist/providers/copilot/paths.d.ts.map +1 -1
- package/dist/providers/copilot/paths.js +6 -4
- package/package.json +2 -2
- package/dist/commands/shared/cursor-skill-disposition.d.ts +0 -17
- package/dist/commands/shared/cursor-skill-disposition.d.ts.map +0 -1
- package/dist/commands/shared/cursor-skill-disposition.js +0 -41
|
@@ -50,7 +50,7 @@ pnpm type-check
|
|
|
50
50
|
pnpm test
|
|
51
51
|
pnpm build # excludes docs for speed
|
|
52
52
|
pnpm run check:skill-bumps # changed .agents/skills/*/SKILL.md must bump version
|
|
53
|
-
pnpm release:check-versions # lockstep
|
|
53
|
+
pnpm release:check-versions # lockstep bumps; strictly above origin/main
|
|
54
54
|
pnpm release:validate
|
|
55
55
|
pnpm build:docs # builds docs site and its dependencies
|
|
56
56
|
```
|
|
@@ -61,6 +61,18 @@ the named-file `test:release` set. Steps 5 and 6 are the version-lockstep
|
|
|
61
61
|
gates; they are in the local list because they previously ran only in CI and
|
|
62
62
|
version-bump drift twice reached review with no local gate to surface it.
|
|
63
63
|
|
|
64
|
+
`pnpm release:check-versions` compares the five public package versions against
|
|
65
|
+
their merge-base versions (lockstep bump required when any publishable root
|
|
66
|
+
changed). Since 0.2.33, when a publishable root changed, the gate additionally
|
|
67
|
+
requires every lockstep version to be strictly greater than the version on your
|
|
68
|
+
local `origin/main` tracking ref (falling back to a local `main` branch when no
|
|
69
|
+
`origin/main` exists) — so a branch whose bump was overtaken by a later `main`
|
|
70
|
+
release fails locally the same way it fails in CI. Fetch first (`git fetch
|
|
71
|
+
origin`) so that ref is current; a
|
|
72
|
+
checkout with neither `origin/main` nor `main` skips the whole gate (CI uses
|
|
73
|
+
`fetch-depth: 0`). Test files under `packages/cli/src/` count as publishable
|
|
74
|
+
changes for this gate.
|
|
75
|
+
|
|
64
76
|
CI runs neither `pnpm lint` nor `pnpm format` — run both whenever a change
|
|
65
77
|
touches `tools/smoke` or `.agents/skills`, since nothing else covers them.
|
|
66
78
|
For narrower changes, use package-specific checks when possible, but do not
|
|
@@ -33,15 +33,16 @@ Key behavior:
|
|
|
33
33
|
|
|
34
34
|
- Scope support (`project`, `user`, `all`)
|
|
35
35
|
- Optional interactive stray adoption
|
|
36
|
-
- Cursor-local skills are handled individually: Adopt moves
|
|
37
|
-
matching canonical `.agents/skills` directory, while Keep
|
|
38
|
-
preserves it and records its exact path in the applicable sync
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
36
|
+
- Cursor-local and Copilot-local skills are handled individually: Adopt moves
|
|
37
|
+
the skill into the matching canonical `.agents/skills` directory, while Keep
|
|
38
|
+
provider-only preserves it and records its exact path in the applicable sync
|
|
39
|
+
config
|
|
40
|
+
- Aborting a native-read skill migration preserves completed choices and leaves
|
|
41
|
+
the current and remaining skills unresolved
|
|
42
|
+
- Keep provider-only is blocked when a canonical skill has the same name;
|
|
43
|
+
rename one skill before retrying
|
|
44
|
+
- Non-interactive and JSON modes report unresolved native-read skill actions
|
|
45
|
+
without choosing or mutating a disposition
|
|
45
46
|
- JSON output for automation
|
|
46
47
|
|
|
47
48
|
## `oat sync`
|
|
@@ -57,7 +58,11 @@ Key behavior:
|
|
|
57
58
|
- Provider enable/disable honored via sync config
|
|
58
59
|
- Cursor skills are native-read from canonical `.agents/skills`; sync does not
|
|
59
60
|
create `.cursor/skills` mirrors
|
|
60
|
-
-
|
|
61
|
+
- Copilot skills are native-read from canonical `.agents/skills`; sync does not
|
|
62
|
+
create `.github/skills` or `~/.copilot/skills` mirrors. Copilot agents and
|
|
63
|
+
project rules still sync to `.github/agents`, `~/.copilot/agents`, and
|
|
64
|
+
`.github/instructions`.
|
|
65
|
+
- Upgrade cleanup removes only verified clean legacy Cursor or Copilot skill views.
|
|
61
66
|
Changed or unverified views are preserved and detached from obsolete manifest
|
|
62
67
|
ownership.
|
|
63
68
|
|
|
@@ -97,6 +97,29 @@ manifest-owned path before acting:
|
|
|
97
97
|
Use `oat sync --scope <project|user|all> --dry-run` to distinguish planned
|
|
98
98
|
removal from preserve-and-detach operations before running a mutating sync.
|
|
99
99
|
|
|
100
|
+
### Copilot skill migration
|
|
101
|
+
|
|
102
|
+
Copilot reads canonical project and user skills directly from `.agents/skills`
|
|
103
|
+
and `~/.agents/skills`. OAT no longer generates `.github/skills` or
|
|
104
|
+
`~/.copilot/skills` views, but it still scans those legacy directories as
|
|
105
|
+
adoption sources.
|
|
106
|
+
|
|
107
|
+
Interactive `oat init` and `oat status` ask about each unresolved Copilot-local
|
|
108
|
+
skill separately. Adopt moves it into the matching canonical directory without
|
|
109
|
+
recreating a provider view or manifest entry. Keep Copilot-only leaves it in
|
|
110
|
+
place and records its exact path as a known stray. A same-name canonical skill
|
|
111
|
+
blocks Keep Copilot-only until one package is renamed. Non-interactive and JSON
|
|
112
|
+
modes report pending migration actions without choosing a disposition.
|
|
113
|
+
|
|
114
|
+
During upgrade cleanup, OAT removes only verified clean manifest-owned views.
|
|
115
|
+
Changed, replaced, broken, unreadable, or otherwise unverifiable paths are
|
|
116
|
+
preserved and detached from obsolete manifest ownership so they remain
|
|
117
|
+
available for adoption or manual resolution.
|
|
118
|
+
|
|
119
|
+
Copilot agent mappings remain materialized under `.github/agents` and
|
|
120
|
+
`~/.copilot/agents`, and project rules remain rendered under
|
|
121
|
+
`.github/instructions`; this retirement behavior applies only to skill views.
|
|
122
|
+
|
|
100
123
|
For rules, adoption maps provider-native files back into `.agents/rules/*.md`:
|
|
101
124
|
|
|
102
125
|
- Claude: `.claude/rules/*.md`
|
|
@@ -31,8 +31,12 @@ description: 'Provider-specific path mappings for Claude, Cursor, Copilot, Gemin
|
|
|
31
31
|
|
|
32
32
|
=== "Copilot"
|
|
33
33
|
|
|
34
|
-
- Project
|
|
35
|
-
- User
|
|
34
|
+
- Project skills are native-read from `.agents/skills`; agents and rules still sync to `.github/agents` and `.github/instructions`
|
|
35
|
+
- User skills are native-read from `~/.agents/skills`; agents still sync to `~/.copilot/agents`
|
|
36
|
+
- `.github/skills` and `~/.copilot/skills` are legacy adoption sources. OAT does not generate skill views there.
|
|
37
|
+
- Interactive `oat init` and `oat status` ask for an individual disposition for each unresolved Copilot-local skill: adopt it into `.agents/skills` or keep it Copilot-only and remember the exact path in sync config
|
|
38
|
+
- Keep-local is blocked when a canonical skill has the same name
|
|
39
|
+
- During upgrades, OAT removes only verified clean legacy managed skill views. Changed or unverifiable views are preserved, detached from manifest ownership, and offered for adoption.
|
|
36
40
|
- Rule files render as `.github/instructions/*.instructions.md`
|
|
37
41
|
- Canonical always-on rules render with `applyTo: "**"` so Copilot activates them repo-wide; provider rules with exactly `applyTo: "**"` adopt back to `activation: always`
|
|
38
42
|
- Comma-containing globs are not supported for Copilot rule sync because Copilot uses a comma-separated `applyTo` field
|
|
@@ -113,6 +117,8 @@ than falling back to the root target or a base role.
|
|
|
113
117
|
- Adoption reconciles canonical plus the adopted provider first.
|
|
114
118
|
- Native-read Cursor skill adoption moves the provider-local skill into `.agents/skills` without recreating a `.cursor/skills` view or manifest entry.
|
|
115
119
|
- Choosing Keep Cursor-only leaves the skill in place and records its exact normalized path in the project or user sync config.
|
|
120
|
+
- Native-read Copilot skill adoption moves a legacy provider-local skill into the matching canonical `.agents/skills` directory without recreating a `.github/skills` or `~/.copilot/skills` view or manifest entry.
|
|
121
|
+
- Choosing Keep Copilot-only leaves the skill in place and records its exact normalized path in the project or user sync config.
|
|
116
122
|
- Rule adoption normalizes provider filenames back to canonical `.agents/rules/*.md` entries before cross-provider fanout.
|
|
117
123
|
- Cross-provider fanout is explicit via `oat sync --scope all`.
|
|
118
124
|
|
|
@@ -13,8 +13,9 @@ This capability is intentionally independent from OAT workflow artifacts. Teams
|
|
|
13
13
|
|
|
14
14
|
- Canonical directories: `.agents/skills`, `.agents/agents`, `.agents/rules`
|
|
15
15
|
- Managed provider views: `.claude/*`, `.cursor/*`, `.github/*`, `.copilot/*`, `.codex/*` (where applicable)
|
|
16
|
-
- Native-read mappings use canonical `.agents/*` directly without mirrored provider directories. Cursor skills, Gemini skills and agents, and Codex canonical mappings use this model.
|
|
16
|
+
- Native-read mappings use canonical `.agents/*` directly without mirrored provider directories. Cursor and Copilot skills, Gemini skills and agents, and Codex canonical mappings use this model.
|
|
17
17
|
- Cursor's `.cursor/skills` and `~/.cursor/skills` directories are provider-local extension and adoption surfaces, not managed output directories.
|
|
18
|
+
- Copilot's legacy `.github/skills` and `~/.copilot/skills` directories are adoption sources, not managed output directories. Copilot agents and project rules still use `.github/agents`, `~/.copilot/agents`, and `.github/instructions` provider views.
|
|
18
19
|
- Manifest tracking: `.oat/sync/manifest.json` (project) and `~/.oat/sync/manifest.json` (user)
|
|
19
20
|
|
|
20
21
|
Rules are currently project-scoped canonical content. Unlike skills and agents, synced rule files for Claude, Cursor, and Copilot are rendered copies with provider-specific frontmatter and filename extensions.
|
|
@@ -51,6 +52,7 @@ Rules are currently project-scoped canonical content. Unlike skills and agents,
|
|
|
51
52
|
- `oat init --scope project` (interactive) prompts for supported providers and persists explicit true/false values.
|
|
52
53
|
- `oat sync --scope project` uses config-aware provider activation and can prompt to remediate detected mismatches.
|
|
53
54
|
- Cursor provider enablement still controls agents, rules, migration discovery, and legacy cleanup even though Cursor reads canonical skills without a generated skill view.
|
|
55
|
+
- Copilot provider enablement still controls agents, project rules, migration discovery, and legacy cleanup even though Copilot reads canonical skills without a generated skill view.
|
|
54
56
|
- Codex project-scope subagent sync writes `.codex/config.toml` and `.codex/agents/*.toml` at command layer after path-mapping sync. Every generated project Codex variant and registration is repository-owned, version-controlled provider output. OAT provides no automatic ignore mechanism for this project output; collaborators review and commit it like other project configuration.
|
|
55
57
|
- Default Codex execution requires `root (0) → phase implementer (1)`. Sync and direct materialization continue to apply an `agents.max_depth` floor of `2` as optional nested-work capability without lowering a higher target value. A project write may read a higher lower-precedence user value and preserves it in project configuration; it writes only project `.codex/config.toml`. User scope writes only `~/.codex/config.toml` and does not read or change project configuration.
|
|
56
58
|
- Missing depth or depth `1` does not block default phase execution. Invalid values or explicit values below `1` fail managed implementation preflight. `oat doctor` reports whether optional depth-two nesting is available and gives a scope-specific repair when the configured value is unusable.
|
|
@@ -17,6 +17,11 @@ For detailed `.oat/` tree semantics, see:
|
|
|
17
17
|
- Cursor reads project skills directly from `.agents/skills/` and user skills
|
|
18
18
|
directly from `~/.agents/skills/`. `.cursor/skills/` remains a Cursor-only
|
|
19
19
|
extension and adoption surface, not generated output.
|
|
20
|
+
- Copilot reads project skills directly from `.agents/skills/` and user skills
|
|
21
|
+
directly from `~/.agents/skills/`. OAT treats legacy `.github/skills/` and
|
|
22
|
+
`~/.copilot/skills/` as adoption sources, not generated output. Copilot agents
|
|
23
|
+
still sync to `.github/agents/` and `~/.copilot/agents/`, and project rules
|
|
24
|
+
still sync to `.github/instructions/`.
|
|
20
25
|
|
|
21
26
|
## OAT runtime/state
|
|
22
27
|
|
|
@@ -31,6 +31,24 @@ Use `.cursor/skills` only for intentionally Cursor-specific packages. Interactiv
|
|
|
31
31
|
`oat init` and `oat status` offer each unresolved Cursor-local skill for
|
|
32
32
|
canonical adoption or a remembered Keep Cursor-only choice.
|
|
33
33
|
|
|
34
|
+
## Copilot appears detected but no skill sync actions are listed
|
|
35
|
+
|
|
36
|
+
Expected for native-read skill mappings. Verify project skills under
|
|
37
|
+
`.agents/skills` and personal skills under `~/.agents/skills`; Copilot reads
|
|
38
|
+
those canonical directories directly. Sync will not create `.github/skills` or
|
|
39
|
+
`~/.copilot/skills` mirrors.
|
|
40
|
+
|
|
41
|
+
Legacy skills in those provider directories remain adoption candidates. Run
|
|
42
|
+
`oat sync --scope <project|user|all> --dry-run` before upgrading: verified clean
|
|
43
|
+
managed views may be removed, while changed or unverifiable paths are preserved
|
|
44
|
+
and detached from obsolete manifest ownership. Copilot agents and project rules
|
|
45
|
+
continue to sync to `.github/agents`, `~/.copilot/agents`, and
|
|
46
|
+
`.github/instructions`.
|
|
47
|
+
|
|
48
|
+
Interactive `oat init` and `oat status` offer each unresolved legacy skill for
|
|
49
|
+
canonical adoption or a remembered Keep Copilot-only choice. Keep is blocked
|
|
50
|
+
when a same-name canonical skill exists; rename one package before retrying.
|
|
51
|
+
|
|
34
52
|
## `sync` reports provider config mismatch
|
|
35
53
|
|
|
36
54
|
- For interactive runs, select detected providers to enable when prompted.
|
|
@@ -279,13 +279,24 @@ supported home for Cursor-only skills. Cursor also reads `.claude/skills/` and
|
|
|
279
279
|
**Skill locations:**
|
|
280
280
|
|
|
281
281
|
- Project:
|
|
282
|
-
- `.
|
|
282
|
+
- `.agents/skills/<skill-name>/SKILL.md` (**native canonical path**)
|
|
283
|
+
- `.github/skills/<skill-name>/SKILL.md` (**legacy/adoption path**)
|
|
283
284
|
- `.claude/skills/<skill-name>/SKILL.md` (**Claude compatibility**)
|
|
284
285
|
- Personal:
|
|
285
|
-
- `~/.
|
|
286
|
+
- `~/.agents/skills/<skill-name>/SKILL.md` (**native canonical path**)
|
|
287
|
+
- `~/.copilot/skills/<skill-name>/SKILL.md` (**legacy/adoption path**)
|
|
286
288
|
- `~/.claude/skills/<skill-name>/SKILL.md` (**Claude compatibility**; Copilot coding agent and GitHub Copilot CLI only)
|
|
287
289
|
|
|
288
|
-
**Notable:** Like Cursor, Copilot reads
|
|
290
|
+
**Notable:** Like Cursor, Copilot reads canonical `.agents/skills/` at project
|
|
291
|
+
and personal scope. OAT does not generate `.github/skills` or
|
|
292
|
+
`~/.copilot/skills` views; existing packages there remain adoption inputs.
|
|
293
|
+
Copilot agents and project rules still use `.github/agents`,
|
|
294
|
+
`~/.copilot/agents`, and `.github/instructions`.
|
|
295
|
+
|
|
296
|
+
OAT asks whether to adopt each unresolved legacy Copilot skill into canonical
|
|
297
|
+
storage or keep it Copilot-only as an exact known stray. Same-name canonical
|
|
298
|
+
collisions block keep-local. Legacy cleanup removes only verified clean managed
|
|
299
|
+
views and preserves changed or unverifiable content.
|
|
289
300
|
|
|
290
301
|
**Notes:** The `license` field may be required in practice even though the spec marks it optional (see https://github.com/github/copilot-cli/issues/894).
|
|
291
302
|
|
|
@@ -343,16 +354,14 @@ Installs skills from GitHub repos, local paths, or GitLab URLs to any supported
|
|
|
343
354
|
|
|
344
355
|
### Symlink Approach (Recommended)
|
|
345
356
|
|
|
346
|
-
Author skills in `.agents/skills/` (canonical) and distribute to
|
|
357
|
+
Author skills in `.agents/skills/` (canonical) and distribute only to providers
|
|
358
|
+
that require a provider-specific directory:
|
|
347
359
|
|
|
348
360
|
```bash
|
|
349
361
|
# Claude Code
|
|
350
362
|
ln -s ../../.agents/skills/my-skill .claude/skills/my-skill
|
|
351
363
|
|
|
352
|
-
#
|
|
353
|
-
ln -s ../../.agents/skills/my-skill .github/skills/my-skill
|
|
354
|
-
|
|
355
|
-
# Cursor, Codex, and Gemini read .agents/skills/ natively — no symlink needed
|
|
364
|
+
# Cursor, Copilot, Codex, and Gemini read .agents/skills/ natively — no symlink needed
|
|
356
365
|
```
|
|
357
366
|
|
|
358
367
|
For automated distribution, use **OAT sync** (for local/internal skills) or **`npx skills add`** (for remote/community skills):
|
|
@@ -365,11 +374,12 @@ oat sync --scope all
|
|
|
365
374
|
npx skills add github-user/skill-repo -a claude-code -a github-copilot
|
|
366
375
|
```
|
|
367
376
|
|
|
368
|
-
**Result: one canonical source,
|
|
377
|
+
**Result: one canonical source, one symlink, five tools.**
|
|
369
378
|
|
|
370
|
-
**Note:** Cursor, Codex, and Gemini read `.agents/skills/` directly at
|
|
371
|
-
and user scope. Keep `.cursor/skills/` for intentionally Cursor-only
|
|
372
|
-
not as a generated mirror of canonical content.
|
|
379
|
+
**Note:** Cursor, Copilot, Codex, and Gemini read `.agents/skills/` directly at
|
|
380
|
+
project and user scope. Keep `.cursor/skills/` for intentionally Cursor-only
|
|
381
|
+
skills, not as a generated mirror of canonical content. Treat `.github/skills/`
|
|
382
|
+
and `~/.copilot/skills/` as legacy Copilot adoption inputs, not mirrors.
|
|
373
383
|
|
|
374
384
|
---
|
|
375
385
|
|
|
@@ -523,31 +533,33 @@ The proposal has community interest but no official timeline or maintainer respo
|
|
|
523
533
|
|
|
524
534
|
**Source:** https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices, https://github.com/agentskills/agentskills/tree/main/skills-ref
|
|
525
535
|
|
|
526
|
-
### Q:
|
|
536
|
+
### Q: Do native `.agents/skills/` mappings eliminate all provider views?
|
|
527
537
|
|
|
528
|
-
**Answer:** No. Cursor, Codex, and Gemini need no skill mirror, but
|
|
529
|
-
|
|
538
|
+
**Answer:** No. Cursor, Copilot, Codex, and Gemini need no skill mirror, but
|
|
539
|
+
Claude Code still uses a provider-specific path. Provider-specific agent and
|
|
540
|
+
rule views also remain where those runtimes require them:
|
|
530
541
|
|
|
531
542
|
| Tool | Native Path | Reads `.claude/skills/`? | Reads `.agents/skills/`? |
|
|
532
543
|
| -------------- | ----------------- | ------------------------ | ------------------------ |
|
|
533
544
|
| Claude Code | `.claude/skills/` | ✅ (native) | ❌ |
|
|
534
545
|
| Cursor | `.agents/skills/` | ✅ (compatibility) | ✅ (native) |
|
|
535
546
|
| Codex CLI | `.agents/skills/` | ❌ | ✅ (native) |
|
|
536
|
-
| GitHub Copilot | `.
|
|
547
|
+
| GitHub Copilot | `.agents/skills/` | ✅ (compatibility) | ✅ (native) |
|
|
537
548
|
| Gemini CLI | `.agents/skills/` | ❌ | ✅ (native alias) |
|
|
538
549
|
|
|
539
|
-
**Recommended approach:** Author skills in `.agents/skills/` (tool-agnostic
|
|
550
|
+
**Recommended approach:** Author skills in `.agents/skills/` (tool-agnostic
|
|
551
|
+
canonical source), then symlink only where needed:
|
|
540
552
|
|
|
541
553
|
```bash
|
|
542
|
-
#
|
|
554
|
+
# One symlink needed:
|
|
543
555
|
ln -s ../../.agents/skills/my-skill .claude/skills/my-skill # Claude Code + Copilot compatibility
|
|
544
|
-
|
|
545
|
-
# Cursor, Codex, and Gemini read .agents/skills/ natively — no symlink needed
|
|
556
|
+
# Cursor, Copilot, Codex, and Gemini read .agents/skills/ natively — no symlink needed
|
|
546
557
|
```
|
|
547
558
|
|
|
548
|
-
**One canonical source,
|
|
559
|
+
**One canonical source, one symlink, five tools.** Legacy `.github/skills` and
|
|
560
|
+
`~/.copilot/skills` entries are migration candidates, not recommended mirrors.
|
|
549
561
|
|
|
550
|
-
**Note (updated
|
|
562
|
+
**Note (updated August 2026):** Cursor, Copilot, Codex, and Gemini read
|
|
551
563
|
`.agents/skills/` natively at project and user scope. No skill symlinks are
|
|
552
564
|
needed for those providers.
|
|
553
565
|
|
|
@@ -308,11 +308,23 @@ supported as intentional local extensions and migration sources.
|
|
|
308
308
|
|
|
309
309
|
**Skill locations:**
|
|
310
310
|
|
|
311
|
-
- Project: `.
|
|
311
|
+
- Project: `.agents/skills/<skill-name>/SKILL.md` (native-read canonical path)
|
|
312
|
+
- Project legacy/adoption path: `.github/skills/<skill-name>/SKILL.md`
|
|
312
313
|
- Project (cross-compat): `.claude/skills/<skill-name>/SKILL.md`
|
|
313
|
-
- Personal: `~/.
|
|
314
|
+
- Personal: `~/.agents/skills/<skill-name>/SKILL.md` (native-read canonical path)
|
|
315
|
+
- Personal legacy/adoption path: `~/.copilot/skills/<skill-name>/SKILL.md`
|
|
314
316
|
- Personal (cross-compat): `~/.claude/skills/<skill-name>/SKILL.md` (Copilot coding agent and GitHub Copilot CLI only)
|
|
315
317
|
|
|
318
|
+
OAT does not generate Copilot skill views under `.github/skills` or
|
|
319
|
+
`~/.copilot/skills`. Those directories remain migration inputs. Copilot custom
|
|
320
|
+
agents still materialize under `.github/agents` and `~/.copilot/agents`, and
|
|
321
|
+
project rules still render under `.github/instructions`.
|
|
322
|
+
|
|
323
|
+
Interactive migration adopts each legacy skill into canonical storage or keeps
|
|
324
|
+
it Copilot-only by recording the exact path in sync config. Upgrade cleanup
|
|
325
|
+
removes only verified clean managed views; changed or unverifiable paths are
|
|
326
|
+
preserved and detached from obsolete manifest ownership.
|
|
327
|
+
|
|
316
328
|
### Subagents (Custom Agents)
|
|
317
329
|
|
|
318
330
|
| Resource | URL |
|
|
@@ -308,11 +308,23 @@ supported as intentional local extensions and migration sources.
|
|
|
308
308
|
|
|
309
309
|
**Skill locations:**
|
|
310
310
|
|
|
311
|
-
- Project: `.
|
|
311
|
+
- Project: `.agents/skills/<skill-name>/SKILL.md` (native-read canonical path)
|
|
312
|
+
- Project legacy/adoption path: `.github/skills/<skill-name>/SKILL.md`
|
|
312
313
|
- Project (cross-compat): `.claude/skills/<skill-name>/SKILL.md`
|
|
313
|
-
- Personal: `~/.
|
|
314
|
+
- Personal: `~/.agents/skills/<skill-name>/SKILL.md` (native-read canonical path)
|
|
315
|
+
- Personal legacy/adoption path: `~/.copilot/skills/<skill-name>/SKILL.md`
|
|
314
316
|
- Personal (cross-compat): `~/.claude/skills/<skill-name>/SKILL.md` (Copilot coding agent and GitHub Copilot CLI only)
|
|
315
317
|
|
|
318
|
+
OAT does not generate Copilot skill views under `.github/skills` or
|
|
319
|
+
`~/.copilot/skills`. Those directories remain migration inputs. Copilot custom
|
|
320
|
+
agents still materialize under `.github/agents` and `~/.copilot/agents`, and
|
|
321
|
+
project rules still render under `.github/instructions`.
|
|
322
|
+
|
|
323
|
+
Interactive migration adopts each legacy skill into canonical storage or keeps
|
|
324
|
+
it Copilot-only by recording the exact path in sync config. Upgrade cleanup
|
|
325
|
+
removes only verified clean managed views; changed or unverifiable paths are
|
|
326
|
+
preserved and detached from obsolete manifest ownership.
|
|
327
|
+
|
|
316
328
|
### Subagents (Custom Agents)
|
|
317
329
|
|
|
318
330
|
| Resource | URL |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type CommandContext, type GlobalOptions } from '../../app/command-context.js';
|
|
2
2
|
import { type ApplyOatCoreResult } from '../init/gitignore.js';
|
|
3
|
-
import { type
|
|
3
|
+
import { type NativeSkillDisposition } from '../shared/native-skill-disposition.js';
|
|
4
4
|
import { type MultiSelectChoice, type PromptContext, type SelectChoice } from '../shared/shared.prompts.js';
|
|
5
5
|
import { type SyncConfig } from '../../config/index.js';
|
|
6
6
|
import { type OatConfig } from '../../config/oat-config.js';
|
|
@@ -63,7 +63,7 @@ interface InitDependencies {
|
|
|
63
63
|
fileExists: (path: string) => Promise<boolean>;
|
|
64
64
|
inputWithDefault: (message: string, defaultValue: string, ctx: PromptContext) => Promise<string | null>;
|
|
65
65
|
selectWithAbort: <T extends string>(message: string, choices: SelectChoice<T>[], ctx: PromptContext) => Promise<T | null>;
|
|
66
|
-
|
|
66
|
+
applyNativeSkillDisposition: (scopeRoot: string, stray: InitStrayCandidate, manifest: Manifest, disposition: NativeSkillDisposition, syncConfigPath: string, options?: {
|
|
67
67
|
replaceCanonical?: boolean;
|
|
68
68
|
}) => Promise<Manifest>;
|
|
69
69
|
runGuidedSetup: (context: CommandContext, dependencies: InitDependencies) => Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/init/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EAEnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,KAAK,kBAAkB,EAExB,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/init/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,10 +5,10 @@ import { buildCommandContext, } from '../../app/command-context.js';
|
|
|
5
5
|
import { applyOatCoreGitignore, } from '../init/gitignore.js';
|
|
6
6
|
import { applyGitignore } from '../local/apply.js';
|
|
7
7
|
import { addLocalPaths } from '../local/manage.js';
|
|
8
|
-
import { adoptStrayToCanonical, isAdoptionConflictError, } from '../shared/adopt-stray.js';
|
|
8
|
+
import { adoptStrayToCanonical, isAdoptionConflictError, isAdoptionSourceUnavailableError, } from '../shared/adopt-stray.js';
|
|
9
9
|
import { detectCodexRoleStrays, filterMaterializationManagedStrays, regenerateCodexAfterAdoption, } from '../shared/codex-strays.js';
|
|
10
|
-
import { applyCursorSkillDisposition, isCursorSkillCandidate, } from '../shared/cursor-skill-disposition.js';
|
|
11
10
|
import { PROVIDER_CONFIG_REMEDIATION } from '../shared/messages.js';
|
|
11
|
+
import { applyNativeSkillDisposition, getNativeSkillProviderDetails, isNativeSkillCandidate, } from '../shared/native-skill-disposition.js';
|
|
12
12
|
import { withScopeOption } from '../shared/scope-option.js';
|
|
13
13
|
import { confirmAction, inputWithDefault, selectManyWithAbort, selectWithAbort, } from '../shared/shared.prompts.js';
|
|
14
14
|
import { readGlobalOptions, resolveConcreteScopes, } from '../shared/shared.utils.js';
|
|
@@ -176,7 +176,7 @@ function createDependencies() {
|
|
|
176
176
|
fileExists,
|
|
177
177
|
inputWithDefault,
|
|
178
178
|
selectWithAbort,
|
|
179
|
-
|
|
179
|
+
applyNativeSkillDisposition,
|
|
180
180
|
runGuidedSetup: runGuidedSetupImpl,
|
|
181
181
|
runToolPacks: runInitToolsWithDefaults,
|
|
182
182
|
async runProviderSync(projectRoot) {
|
|
@@ -524,23 +524,24 @@ async function runInitCommand(context, dependencies, hookFlag, setupFlag) {
|
|
|
524
524
|
});
|
|
525
525
|
let straysAdopted = 0;
|
|
526
526
|
let codexStrayAdopted = false;
|
|
527
|
-
const
|
|
528
|
-
const ordinaryStrays = strays.filter((stray) => !
|
|
527
|
+
const nativeSkillStrays = strays.filter(isNativeSkillCandidate);
|
|
528
|
+
const ordinaryStrays = strays.filter((stray) => !isNativeSkillCandidate(stray));
|
|
529
529
|
if (!context.interactive && strays.length > 0) {
|
|
530
530
|
context.logger.warn(ADOPT_REMEDIATION);
|
|
531
531
|
}
|
|
532
532
|
if (context.interactive && strays.length > 0 && !migrationAborted) {
|
|
533
|
-
for (const stray of
|
|
534
|
-
const
|
|
533
|
+
for (const stray of nativeSkillStrays) {
|
|
534
|
+
const provider = getNativeSkillProviderDetails(stray);
|
|
535
|
+
const disposition = await dependencies.selectWithAbort(`Migrate ${provider.displayName} skill [${scope}]: ${formatPathForScope(scope, stray.report.providerPath)}`, [
|
|
535
536
|
{
|
|
536
537
|
label: 'Adopt into canonical',
|
|
537
538
|
value: 'adopt',
|
|
538
539
|
description: `Move to ${stray.mapping.canonicalDir}.`,
|
|
539
540
|
},
|
|
540
541
|
{
|
|
541
|
-
label:
|
|
542
|
+
label: `Keep ${provider.displayName}-only`,
|
|
542
543
|
value: 'keep',
|
|
543
|
-
description:
|
|
544
|
+
description: `Leave in ${provider.sourceDir} and remember this choice.`,
|
|
544
545
|
},
|
|
545
546
|
], { interactive: context.interactive });
|
|
546
547
|
if (disposition === null) {
|
|
@@ -548,15 +549,19 @@ async function runInitCommand(context, dependencies, hookFlag, setupFlag) {
|
|
|
548
549
|
break;
|
|
549
550
|
}
|
|
550
551
|
try {
|
|
551
|
-
manifest = await dependencies.
|
|
552
|
+
manifest = await dependencies.applyNativeSkillDisposition(scopeRoot, stray, manifest, disposition, syncConfigPath);
|
|
552
553
|
if (disposition === 'adopt') {
|
|
553
554
|
straysAdopted += 1;
|
|
554
555
|
}
|
|
555
556
|
else {
|
|
556
|
-
context.logger.success(`Kept
|
|
557
|
+
context.logger.success(`Kept ${provider.displayName}-only [${scope}]: ${formatPathForScope(scope, stray.report.providerPath)}.`);
|
|
557
558
|
}
|
|
558
559
|
}
|
|
559
560
|
catch (error) {
|
|
561
|
+
if (isAdoptionSourceUnavailableError(error)) {
|
|
562
|
+
context.logger.warn(error.message);
|
|
563
|
+
continue;
|
|
564
|
+
}
|
|
560
565
|
if (error instanceof Error &&
|
|
561
566
|
error.message.startsWith('Cannot keep ')) {
|
|
562
567
|
context.logger.warn(error.message);
|
|
@@ -567,10 +572,10 @@ async function runInitCommand(context, dependencies, hookFlag, setupFlag) {
|
|
|
567
572
|
}
|
|
568
573
|
const shouldReplace = await dependencies.confirmAction(`Conflict detected for ${formatPathForScope(scope, stray.report.providerPath)}. Replace canonical content with stray content?`, { interactive: context.interactive });
|
|
569
574
|
if (!shouldReplace) {
|
|
570
|
-
context.logger.warn(`Skipped conflicting
|
|
575
|
+
context.logger.warn(`Skipped conflicting ${provider.displayName} skill [${scope}]: ${formatPathForScope(scope, stray.report.providerPath)}`);
|
|
571
576
|
continue;
|
|
572
577
|
}
|
|
573
|
-
manifest = await dependencies.
|
|
578
|
+
manifest = await dependencies.applyNativeSkillDisposition(scopeRoot, stray, manifest, disposition, syncConfigPath, { replaceCanonical: true });
|
|
574
579
|
straysAdopted += 1;
|
|
575
580
|
}
|
|
576
581
|
}
|
|
@@ -596,6 +601,10 @@ async function runInitCommand(context, dependencies, hookFlag, setupFlag) {
|
|
|
596
601
|
codexStrayAdopted || stray.provider === 'codex';
|
|
597
602
|
}
|
|
598
603
|
catch (error) {
|
|
604
|
+
if (isAdoptionSourceUnavailableError(error)) {
|
|
605
|
+
context.logger.warn(error.message);
|
|
606
|
+
continue;
|
|
607
|
+
}
|
|
599
608
|
if (!isAdoptionConflictError(error)) {
|
|
600
609
|
throw error;
|
|
601
610
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { type CommandContext } from '../../../app/command-context.js';
|
|
2
2
|
import { readGlobalOptions } from '../../shared/shared.utils.js';
|
|
3
3
|
import { type SyncConfig } from '../../../config/sync-config.js';
|
|
4
|
-
import { type
|
|
4
|
+
import { type RemovalSyncPlanEntry } from '../../../engine/index.js';
|
|
5
|
+
import { type Manifest, type ManifestEntry } from '../../../manifest/index.js';
|
|
5
6
|
import { type ConfigAwareAdaptersResult, type PathMapping, type ProviderAdapter } from '../../../providers/shared/index.js';
|
|
6
7
|
import type { AdoptionSource } from '../../../providers/shared/adapter.types.js';
|
|
7
8
|
import type { ConcreteScope, Scope } from '../../../shared/types.js';
|
|
@@ -16,7 +17,9 @@ export interface RemoveSkillDependencies {
|
|
|
16
17
|
getConfigAwareAdapters: (adapters: ProviderAdapter[], scopeRoot: string, config: SyncConfig) => Promise<ConfigAwareAdaptersResult>;
|
|
17
18
|
getSyncMappings: (adapter: ProviderAdapter, scope: Scope) => PathMapping[];
|
|
18
19
|
getAdoptionSources: (adapter: ProviderAdapter, scope: Scope) => AdoptionSource[];
|
|
20
|
+
classifyObsoleteMappingRetirement: (manifestEntry: ManifestEntry, scopeRoot: string) => Promise<RemovalSyncPlanEntry>;
|
|
19
21
|
pathExists: (path: string) => Promise<boolean>;
|
|
22
|
+
pathEntryExists: (path: string) => Promise<boolean>;
|
|
20
23
|
removeDirectory: (path: string) => Promise<void>;
|
|
21
24
|
}
|
|
22
25
|
export declare function createDefaultRemoveSkillDependencies(): RemoveSkillDependencies;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remove-skill.d.ts","sourceRoot":"","sources":["../../../../src/commands/remove/skill/remove-skill.ts"],"names":[],"mappings":"AAGA,OAAO,EAAuB,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEhF,OAAO,EACL,iBAAiB,EAElB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAGL,KAAK,UAAU,EAChB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"remove-skill.d.ts","sourceRoot":"","sources":["../../../../src/commands/remove/skill/remove-skill.ts"],"names":[],"mappings":"AAGA,OAAO,EAAuB,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEhF,OAAO,EACL,iBAAiB,EAElB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAGL,KAAK,UAAU,EAChB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,eAAe,CAAC;AAGvB,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,aAAa,EAGnB,MAAM,iBAAiB,CAAC;AAMzB,OAAO,EACL,KAAK,yBAAyB,EAG9B,KAAK,WAAW,EAChB,KAAK,eAAe,EACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEtE,OAAO,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+BpC,MAAM,WAAW,uBAAuB;IACtC,mBAAmB,EAAE,CACnB,OAAO,EAAE,UAAU,CAAC,OAAO,iBAAiB,CAAC,KAC1C,cAAc,CAAC;IACpB,gBAAgB,EAAE,CAChB,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,cAAc,KACpB,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,YAAY,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC1D,YAAY,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E,cAAc,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5D,WAAW,EAAE,MAAM,eAAe,EAAE,CAAC;IACrC,sBAAsB,EAAE,CACtB,QAAQ,EAAE,eAAe,EAAE,EAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,UAAU,KACf,OAAO,CAAC,yBAAyB,CAAC,CAAC;IACxC,eAAe,EAAE,CAAC,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,KAAK,WAAW,EAAE,CAAC;IAC3E,kBAAkB,EAAE,CAClB,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,KAAK,KACT,cAAc,EAAE,CAAC;IACtB,iCAAiC,EAAE,CACjC,aAAa,EAAE,aAAa,EAC5B,SAAS,EAAE,MAAM,KACd,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACnC,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACpD,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAClD;AAED,wBAAgB,oCAAoC,IAAI,uBAAuB,CA0C9E;AAwND,wBAAsB,cAAc,CAClC,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,OAAO,EACf,YAAY,EAAE,uBAAuB,GACpC,OAAO,CAAC,OAAO,CAAC,CAsDlB;AAED,wBAAgB,wBAAwB,CACtC,SAAS,GAAE,OAAO,CAAC,uBAAuB,CAAM,GAC/C,OAAO,CAwCT"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { rm } from 'node:fs/promises';
|
|
1
|
+
import { lstat, rm } from 'node:fs/promises';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { buildCommandContext } from '../../../app/command-context.js';
|
|
4
4
|
import { withScopeOption } from '../../shared/scope-option.js';
|
|
5
5
|
import { readGlobalOptions, resolveConcreteScopes, } from '../../shared/shared.utils.js';
|
|
6
6
|
import { DEFAULT_SYNC_CONFIG, loadSyncConfig, } from '../../../config/sync-config.js';
|
|
7
|
+
import { classifyObsoleteMappingRetirement, } from '../../../engine/index.js';
|
|
7
8
|
import { dirExists, fileExists } from '../../../fs/io.js';
|
|
8
|
-
import { resolveProjectRoot, resolveScopeRoot } from '../../../fs/paths.js';
|
|
9
|
+
import { resolveProjectRoot, resolveScopeRoot, toPosixPath } from '../../../fs/paths.js';
|
|
9
10
|
import { loadManifest, removeEntry, saveManifest, } from '../../../manifest/index.js';
|
|
10
11
|
import { claudeAdapter } from '../../../providers/claude/index.js';
|
|
11
12
|
import { codexAdapter } from '../../../providers/codex/index.js';
|
|
@@ -41,9 +42,19 @@ export function createDefaultRemoveSkillDependencies() {
|
|
|
41
42
|
getConfigAwareAdapters,
|
|
42
43
|
getSyncMappings,
|
|
43
44
|
getAdoptionSources,
|
|
45
|
+
classifyObsoleteMappingRetirement,
|
|
44
46
|
async pathExists(path) {
|
|
45
47
|
return (await fileExists(path)) || (await dirExists(path));
|
|
46
48
|
},
|
|
49
|
+
async pathEntryExists(path) {
|
|
50
|
+
try {
|
|
51
|
+
await lstat(path);
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
},
|
|
47
58
|
async removeDirectory(path) {
|
|
48
59
|
await rm(path, { recursive: true, force: true });
|
|
49
60
|
},
|
|
@@ -77,6 +88,7 @@ async function buildScopePlan(scope, scopeRoot, skillName, dependencies) {
|
|
|
77
88
|
const { activeAdapters } = await dependencies.getConfigAwareAdapters(adapters, scopeRoot, config);
|
|
78
89
|
const managedProviderViews = [];
|
|
79
90
|
const unmanagedProviderViews = [];
|
|
91
|
+
const manifestProvidersToRemove = new Set();
|
|
80
92
|
for (const adapter of activeAdapters) {
|
|
81
93
|
const syncMappings = dependencies
|
|
82
94
|
.getSyncMappings(adapter, scope)
|
|
@@ -88,6 +100,7 @@ async function buildScopePlan(scope, scopeRoot, skillName, dependencies) {
|
|
|
88
100
|
entry.provider === adapter.name);
|
|
89
101
|
const providerPathExists = await dependencies.pathExists(absolutePath);
|
|
90
102
|
if (hasManifestEntry) {
|
|
103
|
+
manifestProvidersToRemove.add(adapter.name);
|
|
91
104
|
managedProviderViews.push({
|
|
92
105
|
provider: adapter.name,
|
|
93
106
|
absolutePath,
|
|
@@ -111,7 +124,32 @@ async function buildScopePlan(scope, scopeRoot, skillName, dependencies) {
|
|
|
111
124
|
for (const source of localAdoptionSources) {
|
|
112
125
|
const relativePath = join(source.directory, skillName);
|
|
113
126
|
const absolutePath = join(scopeRoot, relativePath);
|
|
114
|
-
|
|
127
|
+
const legacyManifestEntry = manifest.entries.find((entry) => adapter.name === 'copilot' &&
|
|
128
|
+
entry.canonicalPath === canonicalRelativePath &&
|
|
129
|
+
entry.provider === adapter.name &&
|
|
130
|
+
entry.providerPath === toPosixPath(relativePath));
|
|
131
|
+
if (legacyManifestEntry) {
|
|
132
|
+
manifestProvidersToRemove.add(adapter.name);
|
|
133
|
+
const [retirement, providerPathExists] = await Promise.all([
|
|
134
|
+
dependencies.classifyObsoleteMappingRetirement(legacyManifestEntry, scopeRoot),
|
|
135
|
+
dependencies.pathEntryExists(absolutePath),
|
|
136
|
+
]);
|
|
137
|
+
if (retirement.operation === 'remove') {
|
|
138
|
+
managedProviderViews.push({
|
|
139
|
+
provider: adapter.name,
|
|
140
|
+
absolutePath,
|
|
141
|
+
relativePath,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
else if (providerPathExists) {
|
|
145
|
+
unmanagedProviderViews.push({
|
|
146
|
+
provider: adapter.name,
|
|
147
|
+
absolutePath,
|
|
148
|
+
relativePath,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
else if (await dependencies.pathExists(absolutePath)) {
|
|
115
153
|
unmanagedProviderViews.push({
|
|
116
154
|
provider: adapter.name,
|
|
117
155
|
absolutePath,
|
|
@@ -129,6 +167,7 @@ async function buildScopePlan(scope, scopeRoot, skillName, dependencies) {
|
|
|
129
167
|
canonicalAbsolutePath,
|
|
130
168
|
managedProviderViews: dedupeViews(managedProviderViews),
|
|
131
169
|
unmanagedProviderViews: dedupeViews(unmanagedProviderViews),
|
|
170
|
+
manifestProvidersToRemove: [...manifestProvidersToRemove],
|
|
132
171
|
};
|
|
133
172
|
}
|
|
134
173
|
function logDryRun(context, plan) {
|
|
@@ -164,8 +203,8 @@ async function applyPlan(context, plan, dependencies) {
|
|
|
164
203
|
await dependencies.removeDirectory(view.absolutePath);
|
|
165
204
|
}
|
|
166
205
|
let nextManifest = plan.manifest;
|
|
167
|
-
for (const
|
|
168
|
-
nextManifest = removeEntry(nextManifest, plan.canonicalRelativePath,
|
|
206
|
+
for (const provider of plan.manifestProvidersToRemove) {
|
|
207
|
+
nextManifest = removeEntry(nextManifest, plan.canonicalRelativePath, provider);
|
|
169
208
|
}
|
|
170
209
|
await dependencies.saveManifest(plan.manifestPath, nextManifest);
|
|
171
210
|
context.logger.info(`[apply][${plan.scope}] removed ${plan.canonicalRelativePath}`);
|
|
@@ -17,6 +17,11 @@ interface AdoptStrayOptions {
|
|
|
17
17
|
replaceCanonical?: boolean;
|
|
18
18
|
}
|
|
19
19
|
export declare function isAdoptionConflictError(error: unknown): error is CliError;
|
|
20
|
+
export declare class AdoptionSourceUnavailableError extends CliError {
|
|
21
|
+
readonly kind: 'adoption-source-unavailable';
|
|
22
|
+
constructor(message: string);
|
|
23
|
+
}
|
|
24
|
+
export declare function isAdoptionSourceUnavailableError(error: unknown): error is AdoptionSourceUnavailableError;
|
|
20
25
|
export declare function adoptStrayToCanonical<TCandidate extends StrayAdoptionCandidate>(scopeRoot: string, stray: TCandidate, manifest: Manifest, options?: AdoptStrayOptions): Promise<Manifest>;
|
|
21
26
|
export {};
|
|
22
27
|
//# sourceMappingURL=adopt-stray.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adopt-stray.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/adopt-stray.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAKzC,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,0BAA0B,CAAC;AAExE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAGnE,UAAU,sBAAsB;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE;QACN,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE;QACT,IAAI,EAAE,YAAY,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED,UAAU,iBAAiB;IACzB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,
|
|
1
|
+
{"version":3,"file":"adopt-stray.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/adopt-stray.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAKzC,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,0BAA0B,CAAC;AAExE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAGnE,UAAU,sBAAsB;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE;QACN,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE;QACT,IAAI,EAAE,YAAY,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED,UAAU,iBAAiB;IACzB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAMzE;AAED,qBAAa,8BAA+B,SAAQ,QAAQ;IAC1D,QAAQ,CAAC,IAAI,EAAG,6BAA6B,CAAU;IAEvD,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAED,wBAAgB,gCAAgC,CAC9C,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,8BAA8B,CAEzC;AAWD,wBAAsB,qBAAqB,CACzC,UAAU,SAAS,sBAAsB,EAEzC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,QAAQ,EAClB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,QAAQ,CAAC,CA0FnB"}
|
|
@@ -9,7 +9,19 @@ import { addEntry } from '../../manifest/manager.js';
|
|
|
9
9
|
import { importCanonicalAgentFromCodexRole } from '../../providers/codex/codec/import-from-codex.js';
|
|
10
10
|
import { canonicalRuleNameForProviderEntry } from '../../rules/canonical/index.js';
|
|
11
11
|
export function isAdoptionConflictError(error) {
|
|
12
|
-
return error instanceof CliError &&
|
|
12
|
+
return (error instanceof CliError &&
|
|
13
|
+
!isAdoptionSourceUnavailableError(error) &&
|
|
14
|
+
error.message.startsWith('Cannot adopt '));
|
|
15
|
+
}
|
|
16
|
+
export class AdoptionSourceUnavailableError extends CliError {
|
|
17
|
+
kind = 'adoption-source-unavailable';
|
|
18
|
+
constructor(message) {
|
|
19
|
+
super(message);
|
|
20
|
+
this.name = 'AdoptionSourceUnavailableError';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export function isAdoptionSourceUnavailableError(error) {
|
|
24
|
+
return error instanceof AdoptionSourceUnavailableError;
|
|
13
25
|
}
|
|
14
26
|
async function pathExists(path) {
|
|
15
27
|
try {
|
|
@@ -21,12 +33,21 @@ async function pathExists(path) {
|
|
|
21
33
|
}
|
|
22
34
|
}
|
|
23
35
|
export async function adoptStrayToCanonical(scopeRoot, stray, manifest, options = {}) {
|
|
36
|
+
const providerAbsolutePath = resolve(scopeRoot, stray.report.providerPath);
|
|
37
|
+
let providerStat;
|
|
38
|
+
try {
|
|
39
|
+
providerStat = await stat(providerAbsolutePath);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
if (error.code !== 'ENOENT') {
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
throw new AdoptionSourceUnavailableError(`Cannot adopt ${toPosixPath(relative(scopeRoot, providerAbsolutePath))}: the path is missing or a broken symlink. Remove it or restore its target, then run the command again.`);
|
|
46
|
+
}
|
|
47
|
+
const isFile = providerStat.isFile();
|
|
24
48
|
if (stray.adoption?.kind === 'codex_role') {
|
|
25
49
|
return adoptCodexRoleStrayToCanonical(scopeRoot, stray, manifest, options);
|
|
26
50
|
}
|
|
27
|
-
const providerAbsolutePath = resolve(scopeRoot, stray.report.providerPath);
|
|
28
|
-
const providerStat = await stat(providerAbsolutePath);
|
|
29
|
-
const isFile = providerStat.isFile();
|
|
30
51
|
if (isFile && stray.mapping.contentType === 'rule') {
|
|
31
52
|
return adoptRuleStrayToCanonical(scopeRoot, stray, manifest, options);
|
|
32
53
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Manifest } from '../../manifest/manifest.types.js';
|
|
2
|
+
import type { PathMapping } from '../../providers/shared/adapter.types.js';
|
|
3
|
+
export type NativeSkillDisposition = 'adopt' | 'keep';
|
|
4
|
+
export interface NativeSkillCandidate {
|
|
5
|
+
provider: string;
|
|
6
|
+
report: {
|
|
7
|
+
providerPath: string;
|
|
8
|
+
};
|
|
9
|
+
mapping: PathMapping;
|
|
10
|
+
}
|
|
11
|
+
export interface NativeSkillProviderDetails {
|
|
12
|
+
displayName: string;
|
|
13
|
+
sourceDir: string;
|
|
14
|
+
}
|
|
15
|
+
interface ApplyNativeSkillDispositionOptions {
|
|
16
|
+
replaceCanonical?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare function getNativeSkillProviderDetails(candidate: NativeSkillCandidate): NativeSkillProviderDetails | null;
|
|
19
|
+
export declare function isNativeSkillCandidate(candidate: NativeSkillCandidate): boolean;
|
|
20
|
+
export declare function applyNativeSkillDisposition(scopeRoot: string, candidate: NativeSkillCandidate, manifest: Manifest, disposition: NativeSkillDisposition, syncConfigPath: string, options?: ApplyNativeSkillDispositionOptions): Promise<Manifest>;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=native-skill-disposition.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-skill-disposition.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/native-skill-disposition.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAInE,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,MAAM,CAAC;AAEtD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE;QACN,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,0BAA0B;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,kCAAkC;IAC1C,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAOD,wBAAgB,6BAA6B,CAC3C,SAAS,EAAE,oBAAoB,GAC9B,0BAA0B,GAAG,IAAI,CAqBnC;AAQD,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,oBAAoB,GAC9B,OAAO,CAET;AAED,wBAAsB,2BAA2B,CAC/C,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,oBAAoB,EAC/B,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,sBAAsB,EACnC,cAAc,EAAE,MAAM,EACtB,OAAO,GAAE,kCAAuC,GAC/C,OAAO,CAAC,QAAQ,CAAC,CAenB"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { access } from 'node:fs/promises';
|
|
2
|
+
import { basename, relative, resolve } from 'node:path';
|
|
3
|
+
import { appendKnownStray } from '../../config/sync-config.js';
|
|
4
|
+
import { CliError } from '../../errors/index.js';
|
|
5
|
+
import { toPosixPath } from '../../fs/paths.js';
|
|
6
|
+
import { adoptStrayToCanonical } from './adopt-stray.js';
|
|
7
|
+
const NATIVE_SKILL_PROVIDER_DISPLAY_NAMES = {
|
|
8
|
+
copilot: 'Copilot',
|
|
9
|
+
cursor: 'Cursor',
|
|
10
|
+
};
|
|
11
|
+
export function getNativeSkillProviderDetails(candidate) {
|
|
12
|
+
if (candidate.mapping.contentType !== 'skill' ||
|
|
13
|
+
!candidate.mapping.nativeRead) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
const providerPath = toPosixPath(candidate.report.providerPath);
|
|
17
|
+
const sourceDir = candidate.mapping.adoptionSourceDirs?.find((directory) => providerPath === directory || providerPath.startsWith(`${directory}/`));
|
|
18
|
+
if (!sourceDir) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
const displayName = NATIVE_SKILL_PROVIDER_DISPLAY_NAMES[candidate.provider] ??
|
|
22
|
+
formatProviderName(candidate.provider);
|
|
23
|
+
return { displayName, sourceDir };
|
|
24
|
+
}
|
|
25
|
+
function formatProviderName(provider) {
|
|
26
|
+
return provider.length === 0
|
|
27
|
+
? 'Provider'
|
|
28
|
+
: `${provider.charAt(0).toUpperCase()}${provider.slice(1)}`;
|
|
29
|
+
}
|
|
30
|
+
export function isNativeSkillCandidate(candidate) {
|
|
31
|
+
return getNativeSkillProviderDetails(candidate) !== null;
|
|
32
|
+
}
|
|
33
|
+
export async function applyNativeSkillDisposition(scopeRoot, candidate, manifest, disposition, syncConfigPath, options = {}) {
|
|
34
|
+
const provider = getNativeSkillProviderDetails(candidate);
|
|
35
|
+
if (!provider) {
|
|
36
|
+
throw new CliError(`Cannot apply a native skill disposition to ${candidate.report.providerPath}.`);
|
|
37
|
+
}
|
|
38
|
+
if (disposition === 'adopt') {
|
|
39
|
+
return adoptStrayToCanonical(scopeRoot, candidate, manifest, options);
|
|
40
|
+
}
|
|
41
|
+
await assertProviderOnlyNameAvailable(scopeRoot, candidate, provider);
|
|
42
|
+
await appendKnownStray(syncConfigPath, candidate.report.providerPath);
|
|
43
|
+
return manifest;
|
|
44
|
+
}
|
|
45
|
+
async function assertProviderOnlyNameAvailable(scopeRoot, candidate, provider) {
|
|
46
|
+
const canonicalPath = resolve(scopeRoot, candidate.mapping.canonicalDir, basename(candidate.report.providerPath));
|
|
47
|
+
if (!(await pathExists(canonicalPath))) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
throw new CliError(`Cannot keep ${candidate.report.providerPath} ${provider.displayName}-only because canonical skill ${toPosixPath(relative(scopeRoot, canonicalPath))} has the same name. Rename one skill, then run the command again.`);
|
|
51
|
+
}
|
|
52
|
+
async function pathExists(path) {
|
|
53
|
+
try {
|
|
54
|
+
await access(path);
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type CommandContext, type GlobalOptions } from '../../app/command-context.js';
|
|
2
2
|
import { type CodexRoleStray } from '../shared/codex-strays.js';
|
|
3
|
-
import { type
|
|
3
|
+
import { type NativeSkillDisposition } from '../shared/native-skill-disposition.js';
|
|
4
4
|
import { type MultiSelectChoice, type PromptContext, type SelectChoice } from '../shared/shared.prompts.js';
|
|
5
5
|
import { type SyncConfig } from '../../config/index.js';
|
|
6
6
|
import { type CopyTransform, type DriftReport } from '../../drift/index.js';
|
|
@@ -44,7 +44,7 @@ interface StatusDependencies {
|
|
|
44
44
|
adoptStray: (scopeRoot: string, stray: StatusStrayCandidate, manifest: Manifest, options?: {
|
|
45
45
|
replaceCanonical?: boolean;
|
|
46
46
|
}) => Promise<Manifest>;
|
|
47
|
-
|
|
47
|
+
applyNativeSkillDisposition: (scopeRoot: string, stray: StatusStrayCandidate, manifest: Manifest, disposition: NativeSkillDisposition, syncConfigPath: string, options?: {
|
|
48
48
|
replaceCanonical?: boolean;
|
|
49
49
|
}) => Promise<Manifest>;
|
|
50
50
|
formatStatusTable: (reports: DriftReport[]) => string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/status/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/status/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAM9B,OAAO,EACL,KAAK,cAAc,EAIpB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAIL,KAAK,sBAAsB,EAC5B,MAAM,2CAA2C,CAAC;AAEnD,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,YAAY,EAGlB,MAAM,iCAAiC,CAAC;AAKzC,OAAO,EAGL,KAAK,UAAU,EAChB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,WAAW,EAIjB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,KAAK,cAAc,EAKpB,MAAM,eAAe,CAAC;AAMvB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAIhD,OAAO,EAEL,KAAK,kBAAkB,EAExB,MAAM,uCAAuC,CAAC;AAG/C,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,wCAAwC,CAAC;AAEhD,OAAO,EAGL,KAAK,WAAW,EAEhB,KAAK,eAAe,EACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEtE,OAAO,EACL,KAAK,aAAa,EAGlB,KAAK,KAAK,EACX,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmBpC,UAAU,kBAAkB;IAC1B,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,gBAAgB,EAAE,CAChB,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,cAAc,KACpB,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,YAAY,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC1D,cAAc,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5D,qBAAqB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IACtE,YAAY,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E,aAAa,EAAE,CACb,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,aAAa,KACjB,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IAC/B,wBAAwB,EAAE,MAAM,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IAC1D,WAAW,EAAE,MAAM,eAAe,EAAE,CAAC;IACrC,iBAAiB,EAAE,CACjB,QAAQ,EAAE,eAAe,EAAE,EAC3B,SAAS,EAAE,MAAM,KACd,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IAChC,eAAe,EAAE,CAAC,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,KAAK,WAAW,EAAE,CAAC;IAC3E,kBAAkB,EAAE,CAClB,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,KAAK,KACT,cAAc,EAAE,CAAC;IACtB,WAAW,EAAE,CACX,KAAK,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,EAClC,SAAS,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,aAAa,KAC1B,OAAO,CAAC,WAAW,CAAC,CAAC;IAC1B,YAAY,EAAE,CACZ,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,QAAQ,EAClB,gBAAgB,EAAE,cAAc,EAAE,EAClC,OAAO,CAAC,EAAE,IAAI,CACZ,WAAW,EACX,aAAa,GAAG,YAAY,GAAG,mBAAmB,CACnD,KACE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5B,qBAAqB,EAAE,CACrB,SAAS,EAAE,MAAM,EACjB,gBAAgB,EAAE,cAAc,EAAE,EAClC,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,KAC3B,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IAC/B,gCAAgC,EAAE,CAChC,SAAS,EAAE,MAAM,EACjB,gBAAgB,EAAE,cAAc,EAAE,EAClC,qBAAqB,CAAC,EAAE,MAAM,EAAE,EAChC,OAAO,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;KAAE,KAC1D,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACjC,8BAA8B,EAAE,CAC9B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,kBAAkB,KACrB,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB,iCAAiC,EAAE,CACjC,SAAS,EAAE,MAAM,EACjB,gBAAgB,EAAE,cAAc,EAAE,EAClC,qBAAqB,CAAC,EAAE,MAAM,EAAE,EAChC,OAAO,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;KAAE,KAC1D,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAClC,+BAA+B,EAAE,CAC/B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,mBAAmB,KACtB,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB,mBAAmB,EAAE,CAAC,CAAC,SAAS,MAAM,EACpC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAAE,EAC/B,GAAG,EAAE,aAAa,KACf,OAAO,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IACzB,eAAe,EAAE,CAAC,CAAC,SAAS,MAAM,EAChC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,EAC1B,GAAG,EAAE,aAAa,KACf,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACvB,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACzE,UAAU,EAAE,CACV,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,oBAAoB,EAC3B,QAAQ,EAAE,QAAQ,EAClB,OAAO,CAAC,EAAE;QAAE,gBAAgB,CAAC,EAAE,OAAO,CAAA;KAAE,KACrC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACvB,2BAA2B,EAAE,CAC3B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,oBAAoB,EAC3B,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,sBAAsB,EACnC,cAAc,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE;QAAE,gBAAgB,CAAC,EAAE,OAAO,CAAA;KAAE,KACrC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACvB,iBAAiB,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,MAAM,CAAC;CACvD;AAED,UAAU,oBAAoB;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,WAAW,CAAC;IACpB,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE;QACT,IAAI,EAAE,YAAY,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AA0rBD,wBAAgB,mBAAmB,CACjC,SAAS,GAAE,OAAO,CAAC,kBAAkB,CAAM,GAC1C,OAAO,CAoBT"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { basename, join, relative } from 'node:path';
|
|
2
2
|
import { buildCommandContext, } from '../../app/command-context.js';
|
|
3
|
-
import { adoptStrayToCanonical, isAdoptionConflictError, } from '../shared/adopt-stray.js';
|
|
3
|
+
import { adoptStrayToCanonical, isAdoptionConflictError, isAdoptionSourceUnavailableError, } from '../shared/adopt-stray.js';
|
|
4
4
|
import { detectCodexRoleStrays, filterMaterializationManagedStrays, regenerateCodexAfterAdoption, } from '../shared/codex-strays.js';
|
|
5
|
-
import {
|
|
5
|
+
import { applyNativeSkillDisposition, getNativeSkillProviderDetails, isNativeSkillCandidate, } from '../shared/native-skill-disposition.js';
|
|
6
6
|
import { withScopeOption } from '../shared/scope-option.js';
|
|
7
7
|
import { confirmAction, selectManyWithAbort, selectWithAbort, } from '../shared/shared.prompts.js';
|
|
8
8
|
import { readGlobalOptions, resolveConcreteScopes, } from '../shared/shared.utils.js';
|
|
@@ -64,7 +64,7 @@ const DEFAULT_DEPENDENCIES = {
|
|
|
64
64
|
selectWithAbort,
|
|
65
65
|
confirmAction,
|
|
66
66
|
adoptStray: adoptStrayDefault,
|
|
67
|
-
|
|
67
|
+
applyNativeSkillDisposition,
|
|
68
68
|
formatStatusTable,
|
|
69
69
|
};
|
|
70
70
|
function entryInsideMapping(entryProviderPath, mappingProviderDir) {
|
|
@@ -355,19 +355,20 @@ async function runStatusCommand(context, dependencies, options = {}) {
|
|
|
355
355
|
let manifestChanged = false;
|
|
356
356
|
let adoptedCount = 0;
|
|
357
357
|
let codexStrayAdopted = false;
|
|
358
|
-
const
|
|
359
|
-
const ordinaryStrays = scopeCollection.strayCandidates.filter((stray) => !
|
|
360
|
-
for (const strayCandidate of
|
|
361
|
-
const
|
|
358
|
+
const nativeSkillStrays = scopeCollection.strayCandidates.filter(isNativeSkillCandidate);
|
|
359
|
+
const ordinaryStrays = scopeCollection.strayCandidates.filter((stray) => !isNativeSkillCandidate(stray));
|
|
360
|
+
for (const strayCandidate of nativeSkillStrays) {
|
|
361
|
+
const provider = getNativeSkillProviderDetails(strayCandidate);
|
|
362
|
+
const disposition = await dependencies.selectWithAbort(`Migrate ${provider.displayName} skill [${scopeCollection.scope}]: ${formatPathForScope(scopeCollection.scope, strayCandidate.report.providerPath)}`, [
|
|
362
363
|
{
|
|
363
364
|
label: 'Adopt into canonical',
|
|
364
365
|
value: 'adopt',
|
|
365
366
|
description: `Move to ${strayCandidate.mapping.canonicalDir}.`,
|
|
366
367
|
},
|
|
367
368
|
{
|
|
368
|
-
label:
|
|
369
|
+
label: `Keep ${provider.displayName}-only`,
|
|
369
370
|
value: 'keep',
|
|
370
|
-
description:
|
|
371
|
+
description: `Leave in ${provider.sourceDir} and remember this choice.`,
|
|
371
372
|
},
|
|
372
373
|
], { interactive: context.interactive });
|
|
373
374
|
if (disposition === null) {
|
|
@@ -376,15 +377,19 @@ async function runStatusCommand(context, dependencies, options = {}) {
|
|
|
376
377
|
}
|
|
377
378
|
try {
|
|
378
379
|
scopeCollection.manifest =
|
|
379
|
-
await dependencies.
|
|
380
|
+
await dependencies.applyNativeSkillDisposition(scopeCollection.scopeRoot, strayCandidate, scopeCollection.manifest, disposition, scopeCollection.syncConfigPath);
|
|
380
381
|
if (disposition === 'adopt') {
|
|
381
382
|
adoptedCount += 1;
|
|
382
383
|
}
|
|
383
384
|
else {
|
|
384
|
-
context.logger.success(`Kept
|
|
385
|
+
context.logger.success(`Kept ${provider.displayName}-only [${scopeCollection.scope}]: ${formatPathForScope(scopeCollection.scope, strayCandidate.report.providerPath)}.`);
|
|
385
386
|
}
|
|
386
387
|
}
|
|
387
388
|
catch (error) {
|
|
389
|
+
if (isAdoptionSourceUnavailableError(error)) {
|
|
390
|
+
context.logger.warn(error.message);
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
388
393
|
if (error instanceof Error &&
|
|
389
394
|
error.message.startsWith('Cannot keep ')) {
|
|
390
395
|
context.logger.warn(error.message);
|
|
@@ -395,11 +400,11 @@ async function runStatusCommand(context, dependencies, options = {}) {
|
|
|
395
400
|
}
|
|
396
401
|
const shouldReplace = await dependencies.confirmAction(`Conflict detected for ${formatPathForScope(scopeCollection.scope, strayCandidate.report.providerPath)}. Replace canonical with stray content?`, { interactive: context.interactive });
|
|
397
402
|
if (!shouldReplace) {
|
|
398
|
-
context.logger.warn(`Skipped adopting conflicting
|
|
403
|
+
context.logger.warn(`Skipped adopting conflicting ${provider.displayName} skill [${scopeCollection.scope}] ${formatPathForScope(scopeCollection.scope, strayCandidate.report.providerPath)}.`);
|
|
399
404
|
continue;
|
|
400
405
|
}
|
|
401
406
|
scopeCollection.manifest =
|
|
402
|
-
await dependencies.
|
|
407
|
+
await dependencies.applyNativeSkillDisposition(scopeCollection.scopeRoot, strayCandidate, scopeCollection.manifest, disposition, scopeCollection.syncConfigPath, { replaceCanonical: true });
|
|
403
408
|
adoptedCount += 1;
|
|
404
409
|
}
|
|
405
410
|
}
|
|
@@ -426,6 +431,10 @@ async function runStatusCommand(context, dependencies, options = {}) {
|
|
|
426
431
|
codexStrayAdopted || strayCandidate.provider === 'codex';
|
|
427
432
|
}
|
|
428
433
|
catch (error) {
|
|
434
|
+
if (isAdoptionSourceUnavailableError(error)) {
|
|
435
|
+
context.logger.warn(error.message);
|
|
436
|
+
continue;
|
|
437
|
+
}
|
|
429
438
|
if (!isAdoptionConflictError(error)) {
|
|
430
439
|
throw error;
|
|
431
440
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { SyncConfig } from '../config/sync-config.js';
|
|
2
|
-
import type { Manifest } from '../manifest/manifest.types.js';
|
|
2
|
+
import type { Manifest, ManifestEntry } from '../manifest/manifest.types.js';
|
|
3
3
|
import type { ProviderAdapter } from '../providers/shared/adapter.types.js';
|
|
4
|
-
import type { EngineScope, SyncPlan } from './engine.types.js';
|
|
4
|
+
import type { EngineScope, RemovalSyncPlanEntry, SyncPlan } from './engine.types.js';
|
|
5
5
|
import type { CanonicalEntry } from './scanner.js';
|
|
6
6
|
interface ComputeSyncPlanArgs {
|
|
7
7
|
canonical: CanonicalEntry[];
|
|
@@ -12,6 +12,7 @@ interface ComputeSyncPlanArgs {
|
|
|
12
12
|
scopeRoot?: string;
|
|
13
13
|
allowedCanonicalPaths?: string[];
|
|
14
14
|
}
|
|
15
|
+
export declare function classifyObsoleteMappingRetirement(manifestEntry: ManifestEntry, scopeRoot: string): Promise<RemovalSyncPlanEntry>;
|
|
15
16
|
export declare function computeSyncPlan({ canonical, adapters, manifest, scope, config, scopeRoot: explicitScopeRoot, allowedCanonicalPaths, }: ComputeSyncPlanArgs): Promise<SyncPlan>;
|
|
16
17
|
export {};
|
|
17
18
|
//# sourceMappingURL=compute-plan.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compute-plan.d.ts","sourceRoot":"","sources":["../../src/engine/compute-plan.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAGtD,OAAO,KAAK,EAAE,QAAQ,
|
|
1
|
+
{"version":3,"file":"compute-plan.d.ts","sourceRoot":"","sources":["../../src/engine/compute-plan.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAGtD,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,KAAK,EAEV,eAAe,EAChB,MAAM,iCAAiC,CAAC;AAIzC,OAAO,KAAK,EACV,WAAW,EACX,oBAAoB,EACpB,QAAQ,EAET,MAAM,gBAAgB,CAAC;AAGxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD,UAAU,mBAAmB;IAC3B,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,WAAW,CAAC;IACnB,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;CAClC;AAiPD,wBAAsB,iCAAiC,CACrD,aAAa,EAAE,aAAa,EAC5B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,oBAAoB,CAAC,CAqG/B;AAiID,wBAAsB,eAAe,CAAC,EACpC,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,KAAK,EACL,MAAM,EACN,SAAS,EAAE,iBAAiB,EAC5B,qBAAqB,GACtB,EAAE,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAyIzC"}
|
|
@@ -176,7 +176,7 @@ async function computeManagedDirectoryCopyHash(providerPath, canonicalPath, cont
|
|
|
176
176
|
return null;
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
|
-
async function classifyObsoleteMappingRetirement(manifestEntry, scopeRoot) {
|
|
179
|
+
export async function classifyObsoleteMappingRetirement(manifestEntry, scopeRoot) {
|
|
180
180
|
const providerPath = resolve(scopeRoot, manifestEntry.providerPath);
|
|
181
181
|
const canonicalPath = resolve(scopeRoot, manifestEntry.canonicalPath);
|
|
182
182
|
let providerStat;
|
package/dist/engine/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { computeSyncPlan } from './compute-plan.js';
|
|
1
|
+
export { classifyObsoleteMappingRetirement, computeSyncPlan, } from './compute-plan.js';
|
|
2
2
|
export { type EngineScope, type RemovalSyncPlanEntry, SYNC_OPERATION_TYPES, type SyncOperationType, type SyncPlan, type SyncPlanEntry, type SyncResult, } from './engine.types.js';
|
|
3
3
|
export { executeSyncPlan } from './execute-plan.js';
|
|
4
4
|
export { configureLocalHooksPath, getHookInstallInfo, HOOK_DRIFT_WARNING, HOOK_MARKER_END, HOOK_MARKER_START, HOOK_STRAY_INFO, installHook, isHookInstalled, REPO_GITHOOKS_PATH, runHookCheck, uninstallHook, } from './hook.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/engine/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/engine/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iCAAiC,EACjC,eAAe,GAChB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,oBAAoB,EACzB,oBAAoB,EACpB,KAAK,iBAAiB,EACtB,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,UAAU,GAChB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EACL,uBAAuB,EACvB,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,eAAe,EACf,kBAAkB,EAClB,YAAY,EACZ,aAAa,GACd,MAAM,QAAQ,CAAC;AAChB,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC1D,OAAO,EACL,SAAS,EACT,YAAY,EACZ,sBAAsB,EACtB,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,8BAA8B,EAAE,MAAM,wBAAwB,CAAC;AACxE,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EACL,wBAAwB,EACxB,6BAA6B,EAC7B,aAAa,GACd,MAAM,WAAW,CAAC"}
|
package/dist/engine/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { computeSyncPlan } from './compute-plan.js';
|
|
1
|
+
export { classifyObsoleteMappingRetirement, computeSyncPlan, } from './compute-plan.js';
|
|
2
2
|
export { SYNC_OPERATION_TYPES, } from './engine.types.js';
|
|
3
3
|
export { executeSyncPlan } from './execute-plan.js';
|
|
4
4
|
export { configureLocalHooksPath, getHookInstallInfo, HOOK_DRIFT_WARNING, HOOK_MARKER_END, HOOK_MARKER_START, HOOK_STRAY_INFO, installHook, isHookInstalled, REPO_GITHOOKS_PATH, runHookCheck, uninstallHook, } from './hook.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../src/providers/copilot/paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAOnE,eAAO,MAAM,wBAAwB,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../src/providers/copilot/paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAOnE,eAAO,MAAM,wBAAwB,EAAE,WAAW,EAuBjD,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,WAAW,EAc9C,CAAC"}
|
|
@@ -3,8 +3,9 @@ export const COPILOT_PROJECT_MAPPINGS = [
|
|
|
3
3
|
{
|
|
4
4
|
contentType: 'skill',
|
|
5
5
|
canonicalDir: '.agents/skills',
|
|
6
|
-
providerDir: '.
|
|
7
|
-
nativeRead:
|
|
6
|
+
providerDir: '.agents/skills',
|
|
7
|
+
nativeRead: true,
|
|
8
|
+
adoptionSourceDirs: ['.github/skills'],
|
|
8
9
|
},
|
|
9
10
|
{
|
|
10
11
|
contentType: 'agent',
|
|
@@ -26,8 +27,9 @@ export const COPILOT_USER_MAPPINGS = [
|
|
|
26
27
|
{
|
|
27
28
|
contentType: 'skill',
|
|
28
29
|
canonicalDir: '.agents/skills',
|
|
29
|
-
providerDir: '.
|
|
30
|
-
nativeRead:
|
|
30
|
+
providerDir: '.agents/skills',
|
|
31
|
+
nativeRead: true,
|
|
32
|
+
adoptionSourceDirs: ['.copilot/skills'],
|
|
31
33
|
},
|
|
32
34
|
{
|
|
33
35
|
contentType: 'agent',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-agent-toolkit/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.33",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Open Agent Toolkit CLI",
|
|
6
6
|
"homepage": "https://github.com/voxmedia/open-agent-toolkit/tree/main/packages/cli",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"ora": "^9.0.0",
|
|
35
35
|
"yaml": "2.8.2",
|
|
36
36
|
"zod": "^3.25.76",
|
|
37
|
-
"@open-agent-toolkit/control-plane": "0.2.
|
|
37
|
+
"@open-agent-toolkit/control-plane": "0.2.33"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/node": "^22.10.0",
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { Manifest } from '../../manifest/manifest.types.js';
|
|
2
|
-
import type { PathMapping } from '../../providers/shared/adapter.types.js';
|
|
3
|
-
export type CursorSkillDisposition = 'adopt' | 'keep';
|
|
4
|
-
export interface CursorSkillCandidate {
|
|
5
|
-
provider: string;
|
|
6
|
-
report: {
|
|
7
|
-
providerPath: string;
|
|
8
|
-
};
|
|
9
|
-
mapping: PathMapping;
|
|
10
|
-
}
|
|
11
|
-
interface ApplyCursorSkillDispositionOptions {
|
|
12
|
-
replaceCanonical?: boolean;
|
|
13
|
-
}
|
|
14
|
-
export declare function isCursorSkillCandidate(candidate: CursorSkillCandidate): boolean;
|
|
15
|
-
export declare function applyCursorSkillDisposition(scopeRoot: string, candidate: CursorSkillCandidate, manifest: Manifest, disposition: CursorSkillDisposition, syncConfigPath: string, options?: ApplyCursorSkillDispositionOptions): Promise<Manifest>;
|
|
16
|
-
export {};
|
|
17
|
-
//# sourceMappingURL=cursor-skill-disposition.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cursor-skill-disposition.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/cursor-skill-disposition.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAInE,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,MAAM,CAAC;AAEtD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE;QACN,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,UAAU,kCAAkC;IAC1C,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,oBAAoB,GAC9B,OAAO,CAST;AAED,wBAAsB,2BAA2B,CAC/C,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,oBAAoB,EAC/B,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,sBAAsB,EACnC,cAAc,EAAE,MAAM,EACtB,OAAO,GAAE,kCAAuC,GAC/C,OAAO,CAAC,QAAQ,CAAC,CAcnB"}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { access } from 'node:fs/promises';
|
|
2
|
-
import { basename, relative, resolve } from 'node:path';
|
|
3
|
-
import { appendKnownStray } from '../../config/sync-config.js';
|
|
4
|
-
import { CliError } from '../../errors/index.js';
|
|
5
|
-
import { toPosixPath } from '../../fs/paths.js';
|
|
6
|
-
import { adoptStrayToCanonical } from './adopt-stray.js';
|
|
7
|
-
export function isCursorSkillCandidate(candidate) {
|
|
8
|
-
const providerPath = toPosixPath(candidate.report.providerPath);
|
|
9
|
-
return (candidate.provider === 'cursor' &&
|
|
10
|
-
candidate.mapping.contentType === 'skill' &&
|
|
11
|
-
candidate.mapping.nativeRead &&
|
|
12
|
-
(providerPath === '.cursor/skills' ||
|
|
13
|
-
providerPath.startsWith('.cursor/skills/')));
|
|
14
|
-
}
|
|
15
|
-
export async function applyCursorSkillDisposition(scopeRoot, candidate, manifest, disposition, syncConfigPath, options = {}) {
|
|
16
|
-
if (!isCursorSkillCandidate(candidate)) {
|
|
17
|
-
throw new CliError(`Cannot apply a Cursor skill disposition to ${candidate.report.providerPath}.`);
|
|
18
|
-
}
|
|
19
|
-
if (disposition === 'adopt') {
|
|
20
|
-
return adoptStrayToCanonical(scopeRoot, candidate, manifest, options);
|
|
21
|
-
}
|
|
22
|
-
await assertCursorOnlyNameAvailable(scopeRoot, candidate);
|
|
23
|
-
await appendKnownStray(syncConfigPath, candidate.report.providerPath);
|
|
24
|
-
return manifest;
|
|
25
|
-
}
|
|
26
|
-
async function assertCursorOnlyNameAvailable(scopeRoot, candidate) {
|
|
27
|
-
const canonicalPath = resolve(scopeRoot, candidate.mapping.canonicalDir, basename(candidate.report.providerPath));
|
|
28
|
-
if (!(await pathExists(canonicalPath))) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
throw new CliError(`Cannot keep ${candidate.report.providerPath} Cursor-only because canonical skill ${toPosixPath(relative(scopeRoot, canonicalPath))} has the same name. Rename one skill, then run the command again.`);
|
|
32
|
-
}
|
|
33
|
-
async function pathExists(path) {
|
|
34
|
-
try {
|
|
35
|
-
await access(path);
|
|
36
|
-
return true;
|
|
37
|
-
}
|
|
38
|
-
catch {
|
|
39
|
-
return false;
|
|
40
|
-
}
|
|
41
|
-
}
|