@minhpnq1807/contextos 0.5.49 → 0.5.50
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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.50
|
|
4
|
+
|
|
5
|
+
- **Explicit skill activation:** Prompt skills named with `$skill-name` are now preserved and ranked before semantic suggestions, so user-requested skills such as `$threejs` or `$design-taste-frontend` appear in prompt context even when semantic ranking would not select them.
|
|
6
|
+
- **Agents skill root discovery:** Skill discovery now scans project and global `.agents/skills` roots in addition to Codex, Claude, Gemini, and skillshare roots.
|
|
7
|
+
|
|
3
8
|
## 0.5.49
|
|
4
9
|
|
|
5
10
|
- **Cold-cache MCP smoke:** `npm run test:mcp` now verifies the MCP tool contract without requiring a pre-downloaded ContextOS embedding model. When the model exists it still runs the semantic/performance smoke; otherwise it asserts cold-cache fallback behavior so publish CI does not fail before model warmup.
|
package/package.json
CHANGED
|
@@ -22,11 +22,13 @@ const scanCache = new Map();
|
|
|
22
22
|
export function skillSearchRoots({ cwd = process.cwd(), home = os.homedir() } = {}) {
|
|
23
23
|
return [
|
|
24
24
|
path.join(cwd, ".codex", "skills"),
|
|
25
|
+
path.join(cwd, ".agents", "skills"),
|
|
25
26
|
path.join(cwd, ".claude", "skills"),
|
|
26
27
|
path.join(cwd, ".gemini", "skills"),
|
|
27
28
|
path.join(cwd, ".gemini", "antigravity", "skills"),
|
|
28
29
|
path.join(cwd, ".gemini", "antigravity-cli", "skills"),
|
|
29
30
|
path.join(home, ".codex", "skills"),
|
|
31
|
+
path.join(home, ".agents", "skills"),
|
|
30
32
|
path.join(home, ".claude", "skills"),
|
|
31
33
|
path.join(home, ".config", "skillshare", "skills"),
|
|
32
34
|
path.join(home, ".gemini", "skills"),
|
|
@@ -171,6 +173,7 @@ export async function suggestSkills({
|
|
|
171
173
|
const catalog = dedupeSkills(skills);
|
|
172
174
|
const query = fusedProjectQuery({ prompt, cwd, dataDir });
|
|
173
175
|
const byId = new Map(catalog.map((skill) => [skillIndexId(skill), skill]));
|
|
176
|
+
const explicitSkills = explicitSkillSuggestions({ prompt, byId });
|
|
174
177
|
|
|
175
178
|
if (dataDir) {
|
|
176
179
|
const indexed = await indexedSearcher({
|
|
@@ -181,20 +184,23 @@ export async function suggestSkills({
|
|
|
181
184
|
allowRemote: false
|
|
182
185
|
});
|
|
183
186
|
if (indexed.status === "enabled" && indexed.items.length) {
|
|
184
|
-
return finalizeSkillScores(
|
|
187
|
+
return finalizeSkillScores([
|
|
188
|
+
...explicitSkills,
|
|
189
|
+
...indexed.items
|
|
185
190
|
.map((item) => {
|
|
186
191
|
const skill = byId.get(item.id);
|
|
187
192
|
if (!skill) return null;
|
|
188
193
|
return skillScoreFromEmbedding(skill, item.embeddingScore, [`embedding:${Number(item.embeddingScore || 0).toFixed(2)}`]);
|
|
189
194
|
})
|
|
190
|
-
.filter(Boolean)
|
|
195
|
+
.filter(Boolean)
|
|
196
|
+
], limit);
|
|
191
197
|
}
|
|
192
198
|
}
|
|
193
199
|
|
|
194
|
-
if (catalog.length > DEFAULT_EMBEDDING_CANDIDATES) return
|
|
200
|
+
if (catalog.length > DEFAULT_EMBEDDING_CANDIDATES) return finalizeSkillScores(explicitSkills, limit);
|
|
195
201
|
|
|
196
202
|
const embeddingCandidates = catalog.map((skill, index) => skillRule({ skill, index }));
|
|
197
|
-
if (!embeddingCandidates.length) return
|
|
203
|
+
if (!embeddingCandidates.length) return finalizeSkillScores(explicitSkills, limit);
|
|
198
204
|
|
|
199
205
|
const embedding = await embeddingEnhancer(embeddingCandidates, query, {
|
|
200
206
|
dataDir,
|
|
@@ -203,7 +209,30 @@ export async function suggestSkills({
|
|
|
203
209
|
allowRemote: false
|
|
204
210
|
});
|
|
205
211
|
|
|
206
|
-
return finalizeSkillScores(embedding.rules, limit);
|
|
212
|
+
return finalizeSkillScores([...explicitSkills, ...embedding.rules], limit);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function explicitSkillSuggestions({ prompt = "", byId = new Map() } = {}) {
|
|
216
|
+
const names = extractExplicitSkillNames(prompt);
|
|
217
|
+
return names
|
|
218
|
+
.map((name, index) => ({ skill: byId.get(normalize(name)), index }))
|
|
219
|
+
.filter(({ skill }) => Boolean(skill))
|
|
220
|
+
.map(({ skill, index }) => skillScoreFromEmbedding(skill, 1 - index * 0.0001, ["explicit-skill"]));
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function extractExplicitSkillNames(prompt = "") {
|
|
224
|
+
const names = [];
|
|
225
|
+
const seen = new Set();
|
|
226
|
+
const pattern = /(?:^|[\s([{,])\$([A-Za-z0-9][A-Za-z0-9_.:-]*)/g;
|
|
227
|
+
let match;
|
|
228
|
+
while ((match = pattern.exec(String(prompt || "")))) {
|
|
229
|
+
const name = match[1];
|
|
230
|
+
const key = normalize(name);
|
|
231
|
+
if (!key || seen.has(key)) continue;
|
|
232
|
+
seen.add(key);
|
|
233
|
+
names.push(name);
|
|
234
|
+
}
|
|
235
|
+
return names;
|
|
207
236
|
}
|
|
208
237
|
|
|
209
238
|
function finalizeSkillScores(skills, limit) {
|