@open-agent-toolkit/cli 0.1.73 → 0.1.76
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/config/dispatch-matrix-recommendation.json +13 -17
- package/assets/docs/cli-utilities/configuration.md +53 -72
- package/assets/docs/cli-utilities/workflow-gates.md +38 -2
- package/assets/docs/provider-sync/commands.md +26 -0
- package/assets/docs/provider-sync/config.md +17 -6
- package/assets/docs/provider-sync/index.md +17 -5
- package/assets/docs/provider-sync/manifest-and-drift.md +39 -1
- package/assets/docs/provider-sync/providers.md +23 -19
- package/assets/docs/provider-sync/scope-and-surface.md +5 -1
- package/assets/docs/reference/file-locations.md +9 -3
- package/assets/docs/reference/oat-directory-structure.md +11 -3
- package/assets/docs/reference/troubleshooting.md +11 -0
- package/assets/docs/workflows/projects/artifacts.md +1 -1
- package/assets/docs/workflows/projects/dispatch-ceiling.md +29 -33
- package/assets/docs/workflows/projects/implementation-execution.md +7 -4
- package/assets/docs/workflows/projects/lifecycle.md +4 -3
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/create-agnostic-skill/SKILL.md +1 -1
- package/assets/skills/create-agnostic-skill/references/docs/skills-guide.md +24 -15
- package/assets/skills/oat-agent-instructions-analyze/references/docs/provider-reference.md +9 -3
- package/assets/skills/oat-agent-instructions-apply/references/docs/provider-reference.md +9 -3
- package/assets/skills/oat-dispatch-subagents/SKILL.md +1 -1
- package/assets/skills/oat-dispatch-subagents/references/provider-cursor.md +27 -15
- package/assets/skills/oat-project-autonomous/SKILL.md +1 -1
- package/assets/skills/oat-project-autonomous/references/gate-inventory.md +1 -1
- package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +1 -1
- package/assets/skills/oat-project-implement/references/completion-and-closeout.md +17 -15
- package/assets/skills/oat-project-implement/references/dispatch-and-dry-run.md +15 -9
- package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +1 -1
- package/assets/skills/oat-project-implement/references/phase-execution.md +11 -5
- package/assets/skills/oat-project-import-plan/SKILL.md +30 -8
- package/assets/skills/oat-project-plan/SKILL.md +30 -8
- package/assets/skills/oat-project-plan-writing/SKILL.md +12 -9
- package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +1 -1
- package/assets/skills/oat-project-quick-start/SKILL.md +30 -8
- package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +1 -1
- package/assets/skills/oat-project-review-provide/SKILL.md +19 -11
- package/assets/skills/oat-project-review-provide-remote/SKILL.md +27 -4
- package/dist/commands/config/index.d.ts.map +1 -1
- package/dist/commands/config/index.js +55 -0
- package/dist/commands/doctor/index.d.ts +2 -1
- package/dist/commands/doctor/index.d.ts.map +1 -1
- package/dist/commands/doctor/index.js +37 -1
- package/dist/commands/gate/index.d.ts +1 -1
- package/dist/commands/gate/index.d.ts.map +1 -1
- package/dist/commands/gate/index.js +35 -3
- package/dist/commands/init/index.d.ts +7 -3
- package/dist/commands/init/index.d.ts.map +1 -1
- package/dist/commands/init/index.js +129 -38
- package/dist/commands/project/dispatch-ceiling/index.d.ts.map +1 -1
- package/dist/commands/project/dispatch-ceiling/index.js +17 -9
- package/dist/commands/remove/skill/remove-skill.d.ts +2 -0
- package/dist/commands/remove/skill/remove-skill.d.ts.map +1 -1
- package/dist/commands/remove/skill/remove-skill.js +20 -2
- package/dist/commands/shared/adopt-stray.d.ts.map +1 -1
- package/dist/commands/shared/adopt-stray.js +3 -0
- package/dist/commands/shared/codex-strays.d.ts +9 -0
- package/dist/commands/shared/codex-strays.d.ts.map +1 -1
- package/dist/commands/shared/codex-strays.js +4 -0
- package/dist/commands/shared/cursor-skill-disposition.d.ts +17 -0
- package/dist/commands/shared/cursor-skill-disposition.d.ts.map +1 -0
- package/dist/commands/shared/cursor-skill-disposition.js +41 -0
- package/dist/commands/status/index.d.ts +17 -5
- package/dist/commands/status/index.d.ts.map +1 -1
- package/dist/commands/status/index.js +151 -47
- package/dist/commands/sync/apply.d.ts.map +1 -1
- package/dist/commands/sync/apply.js +50 -24
- package/dist/commands/sync/dry-run.d.ts.map +1 -1
- package/dist/commands/sync/dry-run.js +31 -18
- package/dist/commands/sync/index.d.ts.map +1 -1
- package/dist/commands/sync/index.js +34 -25
- package/dist/commands/sync/sync.types.d.ts +26 -11
- package/dist/commands/sync/sync.types.d.ts.map +1 -1
- package/dist/commands/sync/sync.utils.d.ts.map +1 -1
- package/dist/commands/sync/sync.utils.js +3 -2
- package/dist/config/oat-config.d.ts +0 -1
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +26 -23
- package/dist/config/sync-config.d.ts +6 -2
- package/dist/config/sync-config.d.ts.map +1 -1
- package/dist/config/sync-config.js +18 -6
- package/dist/config/user-sync-config.d.ts +11 -0
- package/dist/config/user-sync-config.d.ts.map +1 -0
- package/dist/config/user-sync-config.js +61 -0
- package/dist/drift/strays.d.ts +1 -1
- package/dist/drift/strays.d.ts.map +1 -1
- package/dist/drift/strays.js +2 -1
- package/dist/engine/compute-plan.d.ts.map +1 -1
- package/dist/engine/compute-plan.js +154 -4
- package/dist/engine/engine.types.d.ts +2 -2
- package/dist/engine/engine.types.d.ts.map +1 -1
- package/dist/engine/engine.types.js +1 -0
- package/dist/engine/execute-plan.d.ts.map +1 -1
- package/dist/engine/execute-plan.js +4 -0
- 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/engine/scanner.d.ts +3 -1
- package/dist/engine/scanner.d.ts.map +1 -1
- package/dist/engine/scanner.js +4 -2
- package/dist/manifest/manifest.types.d.ts +12 -12
- package/dist/providers/ceiling/registry.d.ts +2 -0
- package/dist/providers/ceiling/registry.d.ts.map +1 -1
- package/dist/providers/ceiling/registry.js +20 -4
- package/dist/providers/codex/codec/sync-extension.d.ts +11 -10
- package/dist/providers/codex/codec/sync-extension.d.ts.map +1 -1
- package/dist/providers/codex/codec/sync-extension.js +42 -14
- package/dist/providers/cursor/codec/catalog.d.ts +18 -0
- package/dist/providers/cursor/codec/catalog.d.ts.map +1 -0
- package/dist/providers/cursor/codec/catalog.js +39 -0
- package/dist/providers/cursor/codec/materialize.d.ts +24 -0
- package/dist/providers/cursor/codec/materialize.d.ts.map +1 -0
- package/dist/providers/cursor/codec/materialize.js +166 -0
- package/dist/providers/cursor/codec/shared.d.ts +14 -0
- package/dist/providers/cursor/codec/shared.d.ts.map +1 -0
- package/dist/providers/cursor/codec/shared.js +76 -0
- package/dist/providers/cursor/codec/sync-extension.d.ts +37 -0
- package/dist/providers/cursor/codec/sync-extension.d.ts.map +1 -0
- package/dist/providers/cursor/codec/sync-extension.js +393 -0
- package/dist/providers/cursor/index.d.ts +3 -0
- package/dist/providers/cursor/index.d.ts.map +1 -1
- package/dist/providers/cursor/index.js +3 -0
- package/dist/providers/cursor/paths.d.ts.map +1 -1
- package/dist/providers/cursor/paths.js +6 -4
- package/dist/providers/identity/availability.d.ts +7 -0
- package/dist/providers/identity/availability.d.ts.map +1 -1
- package/dist/providers/identity/availability.js +23 -0
- package/dist/providers/shared/adapter.types.d.ts +6 -0
- package/dist/providers/shared/adapter.types.d.ts.map +1 -1
- package/dist/providers/shared/adapter.utils.d.ts +2 -1
- package/dist/providers/shared/adapter.utils.d.ts.map +1 -1
- package/dist/providers/shared/adapter.utils.js +29 -6
- package/dist/providers/shared/index.d.ts +2 -0
- package/dist/providers/shared/index.d.ts.map +1 -1
- package/dist/providers/shared/index.js +1 -0
- package/dist/providers/shared/materialization-extension.d.ts +44 -0
- package/dist/providers/shared/materialization-extension.d.ts.map +1 -0
- package/dist/providers/shared/materialization-extension.js +26 -0
- package/package.json +2 -2
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { lstat, readdir, readFile, rm, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { basename, dirname, isAbsolute, join, relative, resolve, sep, } from 'node:path';
|
|
4
|
+
import { parseCanonicalAgentFile } from '../../../agents/canonical/index.js';
|
|
5
|
+
import { normalizeDispatchMatrix, walkDispatchMatrix, } from '../../../config/dispatch-matrix.js';
|
|
6
|
+
import { normalizeProjectPath, resolveActiveProject } from '../../../config/oat-config.js';
|
|
7
|
+
import { resolveEffectiveConfig } from '../../../config/resolve.js';
|
|
8
|
+
import { CliError } from '../../../errors/index.js';
|
|
9
|
+
import { ensureDir, fileExists } from '../../../fs/io.js';
|
|
10
|
+
import { validateRealPathWithinScope } from '../../../fs/paths.js';
|
|
11
|
+
import { hasMaterializationChanges, summarizeMaterializationPlan, toMaterializationOperations, } from '../../shared/index.js';
|
|
12
|
+
import YAML from 'yaml';
|
|
13
|
+
import { CURSOR_MODEL_PIN_MAPPINGS, SUPPORTED_CURSOR_BASE_ROLES, SUPPORTED_CURSOR_ROLE_TARGETS, } from './catalog.js';
|
|
14
|
+
import { assertNoUnmanagedCursorAgentCollisions, materializeCursorAgent, } from './materialize.js';
|
|
15
|
+
import { isOatManagedCursorRoleFile, readOatManagedCursorRoleOwner, readOatManagedCursorRoleName, } from './shared.js';
|
|
16
|
+
const OWNER_PRECEDENCE = {
|
|
17
|
+
'supported-catalogue': 0,
|
|
18
|
+
'user-config': 1,
|
|
19
|
+
'project-config': 2,
|
|
20
|
+
};
|
|
21
|
+
function hashContent(content) {
|
|
22
|
+
return createHash('sha256').update(content).digest('hex');
|
|
23
|
+
}
|
|
24
|
+
function toRelativePath(scopeRoot, absolutePath) {
|
|
25
|
+
return relative(scopeRoot, absolutePath).replaceAll('\\', '/');
|
|
26
|
+
}
|
|
27
|
+
function isUserCursorScope(scopeRoot, options) {
|
|
28
|
+
return Boolean(options.userConfigDir &&
|
|
29
|
+
resolve(scopeRoot) === resolve(options.userConfigDir, '..'));
|
|
30
|
+
}
|
|
31
|
+
function assertApprovedMapping(mapping) {
|
|
32
|
+
if (mapping.gateEvidence.gate !== 'g01' ||
|
|
33
|
+
mapping.gateEvidence.disposition !== 'approved' ||
|
|
34
|
+
!mapping.gateEvidence.probeName.trim()) {
|
|
35
|
+
throw new CliError(`Cannot materialize Cursor model ${mapping.ladderModelId}: mapping-specific gate g01 approval is required.`);
|
|
36
|
+
}
|
|
37
|
+
if (!/\[[^\]]+\]$/.test(mapping.frontmatterModel)) {
|
|
38
|
+
throw new CliError(`Cannot materialize Cursor model ${mapping.ladderModelId}: approved mapping must include a non-empty bracket segment.`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function addCursorTarget(ladderModelId, owner, source, targets, mappings) {
|
|
42
|
+
const mapping = mappings.find((candidate) => candidate.ladderModelId === ladderModelId);
|
|
43
|
+
if (!mapping) {
|
|
44
|
+
throw new CliError(`Cannot materialize unknown Cursor model mapping "${ladderModelId}" from ${source}. Add mapping-specific gate g01 evidence before using this target.`);
|
|
45
|
+
}
|
|
46
|
+
assertApprovedMapping(mapping);
|
|
47
|
+
const existing = targets.get(ladderModelId);
|
|
48
|
+
if (!existing ||
|
|
49
|
+
OWNER_PRECEDENCE[owner] >= OWNER_PRECEDENCE[existing.owner]) {
|
|
50
|
+
targets.set(ladderModelId, { mapping, owner, source });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function collectCursorTargetsFromProvider(providerValue, source, pathPrefix, owner, targets, mappings) {
|
|
54
|
+
if (providerValue === undefined) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const refs = walkDispatchMatrix({ cursor: providerValue }, { source, pathPrefix });
|
|
58
|
+
for (const ref of refs) {
|
|
59
|
+
if (ref.value) {
|
|
60
|
+
addCursorTarget(ref.value, owner, `${ref.source}:${ref.path}`, targets, mappings);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (ref.target &&
|
|
64
|
+
(ref.target.harness ?? 'cursor') === 'cursor' &&
|
|
65
|
+
ref.target.model) {
|
|
66
|
+
addCursorTarget(ref.target.model, owner, `${ref.source}:${ref.path}`, targets, mappings);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function frontmatterBlock(content) {
|
|
71
|
+
const normalized = content.startsWith('\uFEFF') ? content.slice(1) : content;
|
|
72
|
+
const match = /^---\n([\s\S]*?)\n---(?:\n|$)/.exec(normalized);
|
|
73
|
+
return match?.[1] ?? null;
|
|
74
|
+
}
|
|
75
|
+
async function readOptionalFile(path) {
|
|
76
|
+
return (await fileExists(path)) ? readFile(path, 'utf8') : null;
|
|
77
|
+
}
|
|
78
|
+
async function collectProjectStateCursorTargets(scopeRoot, options, targets, mappings) {
|
|
79
|
+
const projectPathCandidate = options.projectPath === undefined
|
|
80
|
+
? (await resolveActiveProject(scopeRoot)).path
|
|
81
|
+
: options.projectPath;
|
|
82
|
+
if (!projectPathCandidate) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const projectPath = normalizeProjectPath(scopeRoot, projectPathCandidate);
|
|
86
|
+
if (!projectPath) {
|
|
87
|
+
if (options.projectPath !== undefined) {
|
|
88
|
+
throw new CliError(`Project-scoped Cursor materialization path must be repo-relative or inside repo root: ${projectPathCandidate}`);
|
|
89
|
+
}
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
let realProjectPath;
|
|
93
|
+
try {
|
|
94
|
+
realProjectPath = (await validateRealPathWithinScope(join(scopeRoot, projectPath), scopeRoot)).realPath;
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
if (options.projectPath !== undefined) {
|
|
98
|
+
throw new CliError(`Project-scoped Cursor materialization path must be repo-relative or inside repo root: ${projectPathCandidate}`);
|
|
99
|
+
}
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const stateContent = await readOptionalFile(join(realProjectPath, 'state.md'));
|
|
103
|
+
const rawFrontmatter = stateContent ? frontmatterBlock(stateContent) : null;
|
|
104
|
+
if (!rawFrontmatter) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const parsed = YAML.parse(rawFrontmatter);
|
|
108
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const policy = parsed['oat_dispatch_policy'];
|
|
112
|
+
if (!policy || typeof policy !== 'object' || Array.isArray(policy)) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const matrix = policy['matrix'];
|
|
116
|
+
const normalized = normalizeDispatchMatrix(matrix, {
|
|
117
|
+
pathPrefix: 'oat_dispatch_policy.matrix',
|
|
118
|
+
compatibilityMode: 'project-state',
|
|
119
|
+
});
|
|
120
|
+
collectCursorTargetsFromProvider(normalized.providers.cursor, 'project-state', 'oat_dispatch_policy.matrix', 'project-config', targets, mappings);
|
|
121
|
+
}
|
|
122
|
+
async function readCursorMaterializationTargets(scopeRoot, options) {
|
|
123
|
+
const mappings = options.modelMappings ?? CURSOR_MODEL_PIN_MAPPINGS;
|
|
124
|
+
const supportedTargets = options.supportedTargets ?? SUPPORTED_CURSOR_ROLE_TARGETS;
|
|
125
|
+
const targets = new Map();
|
|
126
|
+
const effectiveConfig = await resolveEffectiveConfig(scopeRoot, options.userConfigDir ?? join(scopeRoot, '.oat', '__no-user-config__'), options.env);
|
|
127
|
+
if (isUserCursorScope(scopeRoot, options)) {
|
|
128
|
+
collectCursorTargetsFromProvider(effectiveConfig.user.workflow?.dispatchCeiling?.providers?.cursor, 'user-config', 'workflow.dispatchCeiling.providers', 'user-config', targets, mappings);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
for (const target of supportedTargets) {
|
|
132
|
+
addCursorTarget(target.ladderModelId, 'supported-catalogue', 'supported-catalogue', targets, mappings);
|
|
133
|
+
}
|
|
134
|
+
collectCursorTargetsFromProvider(effectiveConfig.shared.workflow?.dispatchCeiling?.providers?.cursor, 'repo-config', 'workflow.dispatchCeiling.providers', 'project-config', targets, mappings);
|
|
135
|
+
collectCursorTargetsFromProvider(effectiveConfig.local.workflow?.dispatchCeiling?.providers?.cursor, 'local-config', 'workflow.dispatchCeiling.providers', 'project-config', targets, mappings);
|
|
136
|
+
await collectProjectStateCursorTargets(scopeRoot, options, targets, mappings);
|
|
137
|
+
}
|
|
138
|
+
return [...targets.values()].sort((left, right) => left.mapping.ladderModelId.localeCompare(right.mapping.ladderModelId));
|
|
139
|
+
}
|
|
140
|
+
function canonicalPathAllowed(scopeRoot, canonicalEntry, allowedCanonicalPaths) {
|
|
141
|
+
if (!allowedCanonicalPaths?.length) {
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
return new Set(allowedCanonicalPaths).has(toRelativePath(scopeRoot, canonicalEntry.canonicalPath));
|
|
145
|
+
}
|
|
146
|
+
async function desiredRolesFromCanonical(canonicalEntries, targets) {
|
|
147
|
+
const desired = [];
|
|
148
|
+
for (const entry of canonicalEntries) {
|
|
149
|
+
if (entry.type !== 'agent' ||
|
|
150
|
+
!entry.isFile ||
|
|
151
|
+
!entry.name.endsWith('.md')) {
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
const agent = await parseCanonicalAgentFile(entry.canonicalPath);
|
|
155
|
+
if (!SUPPORTED_CURSOR_BASE_ROLES.includes(agent.name)) {
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
for (const target of targets) {
|
|
159
|
+
desired.push(materializeCursorAgent({
|
|
160
|
+
agent,
|
|
161
|
+
mapping: target.mapping,
|
|
162
|
+
owner: target.owner,
|
|
163
|
+
}));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
const names = new Set();
|
|
167
|
+
for (const role of desired) {
|
|
168
|
+
if (names.has(role.roleName)) {
|
|
169
|
+
throw new CliError(`Distinct Cursor targets produced the same Cursor role name ${role.roleName}. Refusing ambiguous role writes.`);
|
|
170
|
+
}
|
|
171
|
+
names.add(role.roleName);
|
|
172
|
+
}
|
|
173
|
+
return desired.sort((left, right) => left.roleName.localeCompare(right.roleName));
|
|
174
|
+
}
|
|
175
|
+
async function collectStaleManagedRoles(scopeRoot, desiredNames, cleanupOwners) {
|
|
176
|
+
let files;
|
|
177
|
+
try {
|
|
178
|
+
files = await readdir(join(scopeRoot, '.cursor', 'agents'));
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
files = [];
|
|
182
|
+
}
|
|
183
|
+
const stale = [];
|
|
184
|
+
for (const file of files) {
|
|
185
|
+
if (!file.endsWith('.md')) {
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
const roleName = basename(file, '.md');
|
|
189
|
+
if (desiredNames.has(roleName)) {
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
const content = await readOptionalFile(join(scopeRoot, '.cursor', 'agents', file));
|
|
193
|
+
if (!content || !isOatManagedCursorRoleFile(content, roleName)) {
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
const owner = readOatManagedCursorRoleOwner(content);
|
|
197
|
+
if (owner && cleanupOwners.includes(owner)) {
|
|
198
|
+
stale.push(roleName);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return stale.sort((left, right) => left.localeCompare(right));
|
|
202
|
+
}
|
|
203
|
+
function emptyPlan(isPartialSync, cleanupOwners) {
|
|
204
|
+
return {
|
|
205
|
+
provider: 'cursor',
|
|
206
|
+
operations: [],
|
|
207
|
+
managedEntries: [],
|
|
208
|
+
aggregateHash: hashContent(''),
|
|
209
|
+
metadata: { cleanupOwners, isPartialSync },
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
export async function computeCursorProjectExtensionPlan(scopeRoot, canonicalEntries, allowedCanonicalPaths, options = {}) {
|
|
213
|
+
const isPartialSync = allowedCanonicalPaths !== undefined && allowedCanonicalPaths.length > 0;
|
|
214
|
+
const cleanupOwners = isUserCursorScope(scopeRoot, options)
|
|
215
|
+
? ['user-config']
|
|
216
|
+
: ['supported-catalogue', 'project-config'];
|
|
217
|
+
if (options.enabled === false) {
|
|
218
|
+
return emptyPlan(isPartialSync, cleanupOwners);
|
|
219
|
+
}
|
|
220
|
+
const scopedCanonicalEntries = canonicalEntries.filter((entry) => canonicalPathAllowed(scopeRoot, entry, allowedCanonicalPaths));
|
|
221
|
+
if (isPartialSync && scopedCanonicalEntries.length === 0) {
|
|
222
|
+
return emptyPlan(true, cleanupOwners);
|
|
223
|
+
}
|
|
224
|
+
const targets = await readCursorMaterializationTargets(scopeRoot, options);
|
|
225
|
+
if (!isPartialSync &&
|
|
226
|
+
isUserCursorScope(scopeRoot, options) &&
|
|
227
|
+
targets.length > 0) {
|
|
228
|
+
const canonicalBaseRoles = new Set(canonicalEntries
|
|
229
|
+
.filter((entry) => entry.type === 'agent' && entry.isFile)
|
|
230
|
+
.map((entry) => entry.name.replace(/\.md$/i, '')));
|
|
231
|
+
const missingBaseRoles = SUPPORTED_CURSOR_BASE_ROLES.filter((role) => !canonicalBaseRoles.has(role));
|
|
232
|
+
if (missingBaseRoles.length > 0) {
|
|
233
|
+
throw new CliError(`Bundled managed Cursor role definitions are unavailable for user sync: ${missingBaseRoles.join(', ')}. Refusing stale user-role cleanup.`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
const desiredRoles = await desiredRolesFromCanonical(scopedCanonicalEntries, targets);
|
|
237
|
+
const desiredNames = new Set(desiredRoles.map((role) => role.roleName));
|
|
238
|
+
await assertNoUnmanagedCursorAgentCollisions(scopeRoot, desiredNames);
|
|
239
|
+
const staleRoles = isPartialSync
|
|
240
|
+
? []
|
|
241
|
+
: await collectStaleManagedRoles(scopeRoot, desiredNames, cleanupOwners);
|
|
242
|
+
const operations = [];
|
|
243
|
+
for (const role of desiredRoles) {
|
|
244
|
+
const rolePath = join(scopeRoot, '.cursor', 'agents', role.fileName);
|
|
245
|
+
const existingContent = await readOptionalFile(rolePath);
|
|
246
|
+
if (existingContent === null) {
|
|
247
|
+
operations.push({
|
|
248
|
+
provider: 'cursor',
|
|
249
|
+
action: 'create',
|
|
250
|
+
target: 'role',
|
|
251
|
+
path: toRelativePath(scopeRoot, rolePath),
|
|
252
|
+
reason: 'managed Cursor role file missing',
|
|
253
|
+
entryName: role.roleName,
|
|
254
|
+
roleName: role.roleName,
|
|
255
|
+
content: role.content,
|
|
256
|
+
});
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
const existingOwner = readOatManagedCursorRoleOwner(existingContent);
|
|
260
|
+
const existingRoleName = readOatManagedCursorRoleName(existingContent);
|
|
261
|
+
if (existingRoleName !== role.roleName ||
|
|
262
|
+
!existingOwner ||
|
|
263
|
+
!cleanupOwners.includes(existingOwner)) {
|
|
264
|
+
throw new CliError(`Refusing to update Cursor role ${role.roleName}: existing file is unmanaged or owned by ${existingOwner ?? 'unknown'}.`);
|
|
265
|
+
}
|
|
266
|
+
operations.push({
|
|
267
|
+
provider: 'cursor',
|
|
268
|
+
action: existingContent.trimEnd() === role.content.trimEnd()
|
|
269
|
+
? 'skip'
|
|
270
|
+
: 'update',
|
|
271
|
+
target: 'role',
|
|
272
|
+
path: toRelativePath(scopeRoot, rolePath),
|
|
273
|
+
reason: existingContent.trimEnd() === role.content.trimEnd()
|
|
274
|
+
? 'managed Cursor role file already in sync'
|
|
275
|
+
: 'managed Cursor role file differs from desired state',
|
|
276
|
+
entryName: role.roleName,
|
|
277
|
+
roleName: role.roleName,
|
|
278
|
+
...(existingContent.trimEnd() === role.content.trimEnd()
|
|
279
|
+
? {}
|
|
280
|
+
: { content: role.content }),
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
for (const roleName of staleRoles) {
|
|
284
|
+
operations.push({
|
|
285
|
+
provider: 'cursor',
|
|
286
|
+
action: 'remove',
|
|
287
|
+
target: 'role',
|
|
288
|
+
path: `.cursor/agents/${roleName}.md`,
|
|
289
|
+
reason: 'stale managed Cursor role removed',
|
|
290
|
+
entryName: roleName,
|
|
291
|
+
roleName,
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
return {
|
|
295
|
+
provider: 'cursor',
|
|
296
|
+
operations,
|
|
297
|
+
managedEntries: [...desiredNames, ...staleRoles],
|
|
298
|
+
aggregateHash: hashContent(desiredRoles.map((role) => role.content).join('\0')),
|
|
299
|
+
metadata: { cleanupOwners, isPartialSync },
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
async function readMutationPathStats(path) {
|
|
303
|
+
try {
|
|
304
|
+
return await lstat(path);
|
|
305
|
+
}
|
|
306
|
+
catch (error) {
|
|
307
|
+
if (error.code === 'ENOENT') {
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
throw error;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
async function assertSafeCursorMutationPath(scopeRoot, absolutePath) {
|
|
314
|
+
const resolvedScopeRoot = resolve(scopeRoot);
|
|
315
|
+
const relativePath = relative(resolvedScopeRoot, absolutePath);
|
|
316
|
+
if (relativePath === '..' ||
|
|
317
|
+
relativePath.startsWith(`..${sep}`) ||
|
|
318
|
+
isAbsolute(relativePath) ||
|
|
319
|
+
resolve(resolvedScopeRoot, relativePath) !== absolutePath) {
|
|
320
|
+
throw new CliError(`Cursor materialization path escapes the sync scope: ${absolutePath}`);
|
|
321
|
+
}
|
|
322
|
+
let currentPath = resolvedScopeRoot;
|
|
323
|
+
const parentParts = relativePath
|
|
324
|
+
.replaceAll('\\', '/')
|
|
325
|
+
.split('/')
|
|
326
|
+
.slice(0, -1);
|
|
327
|
+
for (const part of parentParts) {
|
|
328
|
+
currentPath = join(currentPath, part);
|
|
329
|
+
const stats = await readMutationPathStats(currentPath);
|
|
330
|
+
if (!stats) {
|
|
331
|
+
break;
|
|
332
|
+
}
|
|
333
|
+
if (stats.isSymbolicLink()) {
|
|
334
|
+
throw new CliError(`Cursor materialization parent is a symbolic link: ${toRelativePath(resolvedScopeRoot, currentPath)}`);
|
|
335
|
+
}
|
|
336
|
+
if (!stats.isDirectory()) {
|
|
337
|
+
throw new CliError(`Cursor materialization parent is not a directory: ${toRelativePath(resolvedScopeRoot, currentPath)}`);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
const targetStats = await readMutationPathStats(absolutePath);
|
|
341
|
+
if (targetStats?.isSymbolicLink()) {
|
|
342
|
+
throw new CliError(`Cursor materialization target is a symbolic link: ${relativePath.replaceAll('\\', '/')}`);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
export async function applyCursorProjectExtensionPlan(scopeRoot, plan) {
|
|
346
|
+
const result = {
|
|
347
|
+
applied: 0,
|
|
348
|
+
failed: 0,
|
|
349
|
+
skipped: 0,
|
|
350
|
+
};
|
|
351
|
+
for (const operation of plan.operations) {
|
|
352
|
+
if (operation.action === 'skip') {
|
|
353
|
+
result.skipped += 1;
|
|
354
|
+
continue;
|
|
355
|
+
}
|
|
356
|
+
const absolutePath = resolve(scopeRoot, operation.path);
|
|
357
|
+
try {
|
|
358
|
+
await assertSafeCursorMutationPath(scopeRoot, absolutePath);
|
|
359
|
+
if (operation.action === 'remove') {
|
|
360
|
+
await rm(absolutePath, { force: true });
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
await ensureDir(dirname(absolutePath));
|
|
364
|
+
await writeFile(absolutePath, operation.content ?? '', 'utf8');
|
|
365
|
+
}
|
|
366
|
+
result.applied += 1;
|
|
367
|
+
}
|
|
368
|
+
catch {
|
|
369
|
+
result.failed += 1;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
return result;
|
|
373
|
+
}
|
|
374
|
+
export function hasCursorExtensionChanges(plan) {
|
|
375
|
+
return hasMaterializationChanges(plan);
|
|
376
|
+
}
|
|
377
|
+
export function summarizeCursorExtension(plan) {
|
|
378
|
+
return summarizeMaterializationPlan(plan);
|
|
379
|
+
}
|
|
380
|
+
export function toCursorExtensionOperations(plan) {
|
|
381
|
+
const operations = toMaterializationOperations(plan);
|
|
382
|
+
return operations.map((operation, index) => ({
|
|
383
|
+
...operation,
|
|
384
|
+
roleName: plan.operations[index]?.roleName,
|
|
385
|
+
}));
|
|
386
|
+
}
|
|
387
|
+
export const cursorMaterializationExtension = {
|
|
388
|
+
provider: 'cursor',
|
|
389
|
+
computePlan(context) {
|
|
390
|
+
return computeCursorProjectExtensionPlan(context.scopeRoot, context.canonicalEntries, context.allowedCanonicalPaths, context.options);
|
|
391
|
+
},
|
|
392
|
+
applyPlan: applyCursorProjectExtensionPlan,
|
|
393
|
+
};
|
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
export { cursorAdapter } from './adapter.js';
|
|
2
|
+
export { CURSOR_MODEL_PIN_MAPPINGS, findCursorModelPinMapping, SUPPORTED_CURSOR_BASE_ROLES, SUPPORTED_CURSOR_ROLE_TARGETS, } from './codec/catalog.js';
|
|
3
|
+
export { assertNoUnmanagedCursorAgentCollisions, materializeCursorAgent, materializeCursorAgents, } from './codec/materialize.js';
|
|
4
|
+
export { buildCursorMaterializedRoleName, isOatManagedCursorRoleFile, readOatManagedCursorRoleName, readOatManagedCursorRoleOwner, } from './codec/shared.js';
|
|
2
5
|
export { CURSOR_PROJECT_MAPPINGS, CURSOR_USER_MAPPINGS } from './paths.js';
|
|
3
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/cursor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/cursor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EACL,yBAAyB,EACzB,yBAAyB,EACzB,2BAA2B,EAC3B,6BAA6B,GAC9B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,sCAAsC,EACtC,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,+BAA+B,EAC/B,0BAA0B,EAC1B,4BAA4B,EAC5B,6BAA6B,GAC9B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -1,2 +1,5 @@
|
|
|
1
1
|
export { cursorAdapter } from './adapter.js';
|
|
2
|
+
export { CURSOR_MODEL_PIN_MAPPINGS, findCursorModelPinMapping, SUPPORTED_CURSOR_BASE_ROLES, SUPPORTED_CURSOR_ROLE_TARGETS, } from './codec/catalog.js';
|
|
3
|
+
export { assertNoUnmanagedCursorAgentCollisions, materializeCursorAgent, materializeCursorAgents, } from './codec/materialize.js';
|
|
4
|
+
export { buildCursorMaterializedRoleName, isOatManagedCursorRoleFile, readOatManagedCursorRoleName, readOatManagedCursorRoleOwner, } from './codec/shared.js';
|
|
2
5
|
export { CURSOR_PROJECT_MAPPINGS, CURSOR_USER_MAPPINGS } from './paths.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../src/providers/cursor/paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAOnE,eAAO,MAAM,uBAAuB,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../src/providers/cursor/paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAOnE,eAAO,MAAM,uBAAuB,EAAE,WAAW,EAuBhD,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,WAAW,EAc7C,CAAC"}
|
|
@@ -3,8 +3,9 @@ export const CURSOR_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: ['.cursor/skills'],
|
|
8
9
|
},
|
|
9
10
|
{
|
|
10
11
|
contentType: 'agent',
|
|
@@ -26,8 +27,9 @@ export const CURSOR_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: ['.cursor/skills'],
|
|
31
33
|
},
|
|
32
34
|
{
|
|
33
35
|
contentType: 'agent',
|
|
@@ -49,9 +49,16 @@ export interface CursorCatalogResult {
|
|
|
49
49
|
sourceCommand: 'models' | 'list-models' | null;
|
|
50
50
|
diagnostic: string | null;
|
|
51
51
|
}
|
|
52
|
+
export interface CursorMaterializedModelDiagnostic {
|
|
53
|
+
ladderModelId: string;
|
|
54
|
+
availability: 'available' | 'missing' | 'unvalidated';
|
|
55
|
+
evidence: 'broad-cli-catalog';
|
|
56
|
+
message: string;
|
|
57
|
+
}
|
|
52
58
|
export declare function normalizeMatrixCellAvailability(result: MatrixCellAvailabilityResponse): MatrixCellAvailabilityResult;
|
|
53
59
|
export declare function probeCursorSubagentModel(value: string, options: ValidateMatrixCellOptions): Promise<CursorTaskProbeResult>;
|
|
54
60
|
export declare function resolveCursorModelCatalog(options: ValidateMatrixCellOptions): Promise<CursorCatalogResult>;
|
|
61
|
+
export declare function diagnoseCursorMaterializedModels(ladderModelIds: readonly string[], options: ValidateMatrixCellOptions): Promise<CursorMaterializedModelDiagnostic[]>;
|
|
55
62
|
export declare function validateCursorSubagentModel(value: string, options: ValidateMatrixCellOptions): Promise<MatrixCellAvailabilityResult>;
|
|
56
63
|
export declare function validateMatrixCell(provider: string, value: string, options: ValidateMatrixCellOptions): Promise<MatrixCellAvailabilityResponse>;
|
|
57
64
|
//# sourceMappingURL=availability.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"availability.d.ts","sourceRoot":"","sources":["../../../src/providers/identity/availability.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,eAAe,GAAG,aAAa,CAAC;AAE/E,MAAM,WAAW,4BAA4B;IAC3C,YAAY,EAAE,sBAAsB,CAAC;IACrC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,8BAA8B,GACtC,sBAAsB,GACtB,4BAA4B,CAAC;AAEjC,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,8BAA8B;IAC7C,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,cAAc,EAAE,CACd,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,qBAAqB,KAC3B,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACnC,QAAQ,EAAE,CACR,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,eAAe,KACrB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAED,MAAM,WAAW,yBAAyB;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC,8BAA8B,CAAC,CAAC;IACvD,MAAM,CAAC,EAAE;QACP,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,IAAI,CAAC;CACV;AAED,MAAM,WAAW,qBAAsB,SAAQ,4BAA4B;IACzE,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,YAAY,GAAG,qBAAqB,GAAG,MAAM,CAAC;CACzD;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,UAAU,GAAG,aAAa,GAAG,QAAQ,CAAC;IAC9C,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,aAAa,EAAE,QAAQ,GAAG,aAAa,GAAG,IAAI,CAAC;IAC/C,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAWD,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE,8BAA8B,GACrC,4BAA4B,CAE9B;AAwWD,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,qBAAqB,CAAC,CAwChC;AAED,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,mBAAmB,CAAC,CAkD9B;AAED,wBAAsB,2BAA2B,CAC/C,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,4BAA4B,CAAC,CAqBvC;AAED,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,8BAA8B,CAAC,CAuCzC"}
|
|
1
|
+
{"version":3,"file":"availability.d.ts","sourceRoot":"","sources":["../../../src/providers/identity/availability.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,eAAe,GAAG,aAAa,CAAC;AAE/E,MAAM,WAAW,4BAA4B;IAC3C,YAAY,EAAE,sBAAsB,CAAC;IACrC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,8BAA8B,GACtC,sBAAsB,GACtB,4BAA4B,CAAC;AAEjC,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,8BAA8B;IAC7C,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,cAAc,EAAE,CACd,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,qBAAqB,KAC3B,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACnC,QAAQ,EAAE,CACR,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,eAAe,KACrB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAED,MAAM,WAAW,yBAAyB;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC,8BAA8B,CAAC,CAAC;IACvD,MAAM,CAAC,EAAE;QACP,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,IAAI,CAAC;CACV;AAED,MAAM,WAAW,qBAAsB,SAAQ,4BAA4B;IACzE,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,YAAY,GAAG,qBAAqB,GAAG,MAAM,CAAC;CACzD;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,UAAU,GAAG,aAAa,GAAG,QAAQ,CAAC;IAC9C,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,aAAa,EAAE,QAAQ,GAAG,aAAa,GAAG,IAAI,CAAC;IAC/C,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,iCAAiC;IAChD,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,WAAW,GAAG,SAAS,GAAG,aAAa,CAAC;IACtD,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;CACjB;AAWD,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE,8BAA8B,GACrC,4BAA4B,CAE9B;AAwWD,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,qBAAqB,CAAC,CAwChC;AAED,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,mBAAmB,CAAC,CAkD9B;AAED,wBAAsB,gCAAgC,CACpD,cAAc,EAAE,SAAS,MAAM,EAAE,EACjC,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,iCAAiC,EAAE,CAAC,CAuB9C;AAED,wBAAsB,2BAA2B,CAC/C,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,4BAA4B,CAAC,CAqBvC;AAED,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,8BAA8B,CAAC,CAuCzC"}
|
|
@@ -348,6 +348,29 @@ export async function resolveCursorModelCatalog(options) {
|
|
|
348
348
|
diagnostic: cursorCatalogDiagnostic(attempts),
|
|
349
349
|
};
|
|
350
350
|
}
|
|
351
|
+
export async function diagnoseCursorMaterializedModels(ladderModelIds, options) {
|
|
352
|
+
const catalog = await resolveCursorModelCatalog(options);
|
|
353
|
+
return unique([...ladderModelIds]).map((ladderModelId) => {
|
|
354
|
+
if (catalog.status !== 'resolved') {
|
|
355
|
+
return {
|
|
356
|
+
ladderModelId,
|
|
357
|
+
availability: 'unvalidated',
|
|
358
|
+
evidence: 'broad-cli-catalog',
|
|
359
|
+
message: `Cursor broad CLI catalog availability for '${ladderModelId}' could not be checked; ` +
|
|
360
|
+
'definition-pin behavior and runtime identity were not tested.',
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
const available = catalog.candidates.includes(ladderModelId);
|
|
364
|
+
return {
|
|
365
|
+
ladderModelId,
|
|
366
|
+
availability: available ? 'available' : 'missing',
|
|
367
|
+
evidence: 'broad-cli-catalog',
|
|
368
|
+
message: available
|
|
369
|
+
? `Cursor broad CLI catalog lists '${ladderModelId}'; this does not verify the materialized definition pin or runtime identity.`
|
|
370
|
+
: `Cursor broad CLI catalog no longer lists '${ladderModelId}'; refresh the mapping or remove the stale materialized target. Definition-pin behavior and runtime identity were not tested.`,
|
|
371
|
+
};
|
|
372
|
+
});
|
|
373
|
+
}
|
|
351
374
|
export async function validateCursorSubagentModel(value, options) {
|
|
352
375
|
const taskProbe = await probeCursorSubagentModel(value, options);
|
|
353
376
|
if (taskProbe.decisive) {
|
|
@@ -4,10 +4,16 @@ export interface PathMapping {
|
|
|
4
4
|
canonicalDir: string;
|
|
5
5
|
providerDir: string;
|
|
6
6
|
nativeRead: boolean;
|
|
7
|
+
adoptionSourceDirs?: string[];
|
|
7
8
|
providerExtension?: string;
|
|
8
9
|
transformCanonical?: (canonicalContent: string, canonicalPath?: string) => string;
|
|
9
10
|
parseToCanonical?: (providerContent: string, providerPath?: string) => string;
|
|
10
11
|
}
|
|
12
|
+
export interface AdoptionSource {
|
|
13
|
+
contentType: ContentType;
|
|
14
|
+
directory: string;
|
|
15
|
+
mapping: PathMapping;
|
|
16
|
+
}
|
|
11
17
|
export interface ProviderAdapter {
|
|
12
18
|
name: string;
|
|
13
19
|
displayName: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.types.d.ts","sourceRoot":"","sources":["../../../src/providers/shared/adapter.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAEtE,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,WAAW,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kBAAkB,CAAC,EAAE,CACnB,gBAAgB,EAAE,MAAM,EACxB,aAAa,CAAC,EAAE,MAAM,KACnB,MAAM,CAAC;IACZ,gBAAgB,CAAC,EAAE,CAAC,eAAe,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;CAC/E;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,YAAY,CAAC;IAC9B,eAAe,EAAE,WAAW,EAAE,CAAC;IAC/B,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5C,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC9C;AAED,MAAM,MAAM,YAAY,GAAG,KAAK,CAAC"}
|
|
1
|
+
{"version":3,"file":"adapter.types.d.ts","sourceRoot":"","sources":["../../../src/providers/shared/adapter.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAEtE,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,WAAW,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kBAAkB,CAAC,EAAE,CACnB,gBAAgB,EAAE,MAAM,EACxB,aAAa,CAAC,EAAE,MAAM,KACnB,MAAM,CAAC;IACZ,gBAAgB,CAAC,EAAE,CAAC,eAAe,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;CAC/E;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,WAAW,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,YAAY,CAAC;IAC9B,eAAe,EAAE,WAAW,EAAE,CAAC;IAC/B,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5C,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CAC9C;AAED,MAAM,MAAM,YAAY,GAAG,KAAK,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { SyncConfig } from '../../config/sync-config.js';
|
|
2
2
|
import type { Scope } from '../../shared/types.js';
|
|
3
|
-
import type { PathMapping, ProviderAdapter } from './adapter.types.js';
|
|
3
|
+
import type { AdoptionSource, PathMapping, ProviderAdapter } from './adapter.types.js';
|
|
4
4
|
export declare function getActiveAdapters(adapters: ProviderAdapter[], scopeRoot: string): Promise<ProviderAdapter[]>;
|
|
5
5
|
export interface ConfigAwareAdaptersResult {
|
|
6
6
|
activeAdapters: ProviderAdapter[];
|
|
@@ -9,4 +9,5 @@ export interface ConfigAwareAdaptersResult {
|
|
|
9
9
|
}
|
|
10
10
|
export declare function getConfigAwareAdapters(adapters: ProviderAdapter[], scopeRoot: string, config: SyncConfig): Promise<ConfigAwareAdaptersResult>;
|
|
11
11
|
export declare function getSyncMappings(adapter: ProviderAdapter, scope: Scope): PathMapping[];
|
|
12
|
+
export declare function getAdoptionSources(adapter: ProviderAdapter, scope: Scope): AdoptionSource[];
|
|
12
13
|
//# sourceMappingURL=adapter.utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.utils.d.ts","sourceRoot":"","sources":["../../../src/providers/shared/adapter.utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"adapter.utils.d.ts","sourceRoot":"","sources":["../../../src/providers/shared/adapter.utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,KAAK,EACV,cAAc,EACd,WAAW,EACX,eAAe,EAChB,MAAM,iBAAiB,CAAC;AAazB,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,eAAe,EAAE,EAC3B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,EAAE,CAAC,CAW5B;AAED,MAAM,WAAW,yBAAyB;IACxC,cAAc,EAAE,eAAe,EAAE,CAAC;IAClC,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE,eAAe,EAAE,EAC3B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,yBAAyB,CAAC,CAqCpC;AAED,wBAAgB,eAAe,CAC7B,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,KAAK,GACX,WAAW,EAAE,CAcf;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,KAAK,GACX,cAAc,EAAE,CAsBlB"}
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
function getScopeMappings(adapter, scope) {
|
|
2
|
+
return scope === 'project'
|
|
3
|
+
? adapter.projectMappings
|
|
4
|
+
: scope === 'user'
|
|
5
|
+
? adapter.userMappings
|
|
6
|
+
: [...adapter.projectMappings, ...adapter.userMappings];
|
|
7
|
+
}
|
|
1
8
|
export async function getActiveAdapters(adapters, scopeRoot) {
|
|
2
9
|
const detected = await Promise.all(adapters.map(async (adapter) => ({
|
|
3
10
|
adapter,
|
|
@@ -39,12 +46,7 @@ export async function getConfigAwareAdapters(adapters, scopeRoot, config) {
|
|
|
39
46
|
};
|
|
40
47
|
}
|
|
41
48
|
export function getSyncMappings(adapter, scope) {
|
|
42
|
-
const
|
|
43
|
-
? adapter.projectMappings
|
|
44
|
-
: scope === 'user'
|
|
45
|
-
? adapter.userMappings
|
|
46
|
-
: [...adapter.projectMappings, ...adapter.userMappings];
|
|
47
|
-
const syncMappings = scopeMappings.filter((mapping) => !mapping.nativeRead);
|
|
49
|
+
const syncMappings = getScopeMappings(adapter, scope).filter((mapping) => !mapping.nativeRead);
|
|
48
50
|
const seen = new Set();
|
|
49
51
|
return syncMappings.filter((mapping) => {
|
|
50
52
|
const key = `${mapping.contentType}::${mapping.canonicalDir}::${mapping.providerDir}`;
|
|
@@ -55,3 +57,24 @@ export function getSyncMappings(adapter, scope) {
|
|
|
55
57
|
return true;
|
|
56
58
|
});
|
|
57
59
|
}
|
|
60
|
+
export function getAdoptionSources(adapter, scope) {
|
|
61
|
+
const sources = getScopeMappings(adapter, scope).flatMap((mapping) => {
|
|
62
|
+
const directories = mapping.nativeRead
|
|
63
|
+
? (mapping.adoptionSourceDirs ?? [])
|
|
64
|
+
: [mapping.providerDir];
|
|
65
|
+
return directories.map((directory) => ({
|
|
66
|
+
contentType: mapping.contentType,
|
|
67
|
+
directory,
|
|
68
|
+
mapping,
|
|
69
|
+
}));
|
|
70
|
+
});
|
|
71
|
+
const seen = new Set();
|
|
72
|
+
return sources.filter((source) => {
|
|
73
|
+
const key = `${source.contentType}::${source.directory}`;
|
|
74
|
+
if (seen.has(key)) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
seen.add(key);
|
|
78
|
+
return true;
|
|
79
|
+
});
|
|
80
|
+
}
|
|
@@ -3,4 +3,6 @@ export type { ConfigAwareAdaptersResult } from './adapter.utils.js';
|
|
|
3
3
|
export { getActiveAdapters, getConfigAwareAdapters, getSyncMappings, } from './adapter.utils.js';
|
|
4
4
|
export type { ProviderAgentCodec, ProviderAgentRecord, } from './agent-codec.types.js';
|
|
5
5
|
export { exportMarkdownAgentRecord, importMarkdownAgentRecord, } from './markdown-agent-codec.js';
|
|
6
|
+
export type { MaterializationAction, MaterializationApplyResult, MaterializationContext, MaterializationExtension, MaterializationOperation, MaterializationPlan, MaterializationPlanSummary, MaterializationWriteOperation, } from './materialization-extension.js';
|
|
7
|
+
export { hasMaterializationChanges, summarizeMaterializationPlan, toMaterializationOperations, } from './materialization-extension.js';
|
|
6
8
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/shared/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,YAAY,EACZ,WAAW,EACX,eAAe,GAChB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,eAAe,GAChB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/shared/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,YAAY,EACZ,WAAW,EACX,eAAe,GAChB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,eAAe,GAChB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,wBAAwB,CAAC;AAChC,YAAY,EACV,qBAAqB,EACrB,0BAA0B,EAC1B,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,EACxB,mBAAmB,EACnB,0BAA0B,EAC1B,6BAA6B,GAC9B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,yBAAyB,EACzB,4BAA4B,EAC5B,2BAA2B,GAC5B,MAAM,6BAA6B,CAAC"}
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
export { getActiveAdapters, getConfigAwareAdapters, getSyncMappings, } from './adapter.utils.js';
|
|
2
2
|
export { exportMarkdownAgentRecord, importMarkdownAgentRecord, } from './markdown-agent-codec.js';
|
|
3
|
+
export { hasMaterializationChanges, summarizeMaterializationPlan, toMaterializationOperations, } from './materialization-extension.js';
|