@hasna/skills 0.9.11 → 0.9.13
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/README.md +67 -0
- package/bin/index.js +17012 -16738
- package/bin/maintenance.js +73 -0
- package/bin/mcp.js +11621 -9834
- package/bin/migrate.js +36 -1
- package/bin/server.js +96 -25
- package/bin/worker.js +74 -8
- package/dist/cli/commands/profile-sync.d.ts +1 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.js +7981 -7547
- package/dist/lib/agent-codex-trust.d.ts +15 -0
- package/dist/lib/agent-discovery.d.ts +2 -1
- package/dist/lib/agent-integration.d.ts +15 -0
- package/dist/lib/authoring-path.d.ts +10 -0
- package/dist/lib/claude-marketplace-registry.d.ts +6 -0
- package/dist/lib/claude-settings-witness.d.ts +13 -0
- package/dist/lib/codex-hook-additions-review.d.ts +42 -0
- package/dist/lib/native-discovery-roots.d.ts +2 -0
- package/dist/sdk/index.js +916 -416
- package/dist/server/rows.d.ts +2 -1
- package/dist/server/sqlite-store.d.ts +2 -1
- package/dist/server/store.d.ts +3 -1
- package/dist/server/types.d.ts +18 -0
- package/docs/plugin-admission.md +36 -0
- package/docs/skill-standard.md +7 -1
- package/package.json +1 -1
package/bin/migrate.js
CHANGED
|
@@ -7,7 +7,7 @@ import { join as join5 } from "path";
|
|
|
7
7
|
// package.json
|
|
8
8
|
var package_default = {
|
|
9
9
|
name: "@hasna/skills",
|
|
10
|
-
version: "0.9.
|
|
10
|
+
version: "0.9.13",
|
|
11
11
|
description: "Skills library for AI coding agents",
|
|
12
12
|
type: "module",
|
|
13
13
|
bin: {
|
|
@@ -985,6 +985,18 @@ function rowToSkill(row) {
|
|
|
985
985
|
...row.replacement_slug ? { replacementSlug: String(row.replacement_slug) } : {}
|
|
986
986
|
};
|
|
987
987
|
}
|
|
988
|
+
function rowToPublishedSelectionState(row) {
|
|
989
|
+
return {
|
|
990
|
+
slug: String(row.slug),
|
|
991
|
+
version: String(row.version),
|
|
992
|
+
current: row.skill_exists ? {
|
|
993
|
+
lifecycle: row.lifecycle === "archived" ? "archived" : "active",
|
|
994
|
+
...row.tombstoned_at ? { tombstonedAt: dateString(row.tombstoned_at) } : {}
|
|
995
|
+
} : null,
|
|
996
|
+
versionBundleSha256: typeof row.bundle_sha256 === "string" ? row.bundle_sha256 : null,
|
|
997
|
+
bundleAvailable: Boolean(row.bundle_available)
|
|
998
|
+
};
|
|
999
|
+
}
|
|
988
1000
|
function rowToPin(row) {
|
|
989
1001
|
return {
|
|
990
1002
|
orgId: String(row.org_id),
|
|
@@ -1057,6 +1069,13 @@ function rowToSkillVersion(row) {
|
|
|
1057
1069
|
};
|
|
1058
1070
|
}
|
|
1059
1071
|
|
|
1072
|
+
// src/lib/profile-limits.ts
|
|
1073
|
+
var MAX_PROFILE_SELECTIONS = 4096;
|
|
1074
|
+
var MAX_PROFILE_DOCUMENT_BYTES = 8 * 1024 * 1024;
|
|
1075
|
+
var MAX_SKILL_SESSION_ID_CHARS = 256;
|
|
1076
|
+
var PROFILE_SESSION_ENVELOPE_BYTES = MAX_PROFILE_SELECTIONS * 67 + MAX_SKILL_SESSION_ID_CHARS * 12 + 512;
|
|
1077
|
+
var MAX_RESOLVED_PROFILE_BYTES = MAX_PROFILE_DOCUMENT_BYTES - PROFILE_SESSION_ENVELOPE_BYTES;
|
|
1078
|
+
|
|
1060
1079
|
// src/server/types.ts
|
|
1061
1080
|
class StaleLeaseGenerationError extends Error {
|
|
1062
1081
|
runId;
|
|
@@ -1758,6 +1777,22 @@ class SqliteSkillsStore {
|
|
|
1758
1777
|
const row = this.get("SELECT * FROM skills_versions WHERE org_id = ? AND slug = ? AND version = ? LIMIT 1", [principal.orgId, slug, version]);
|
|
1759
1778
|
return row ? rowToSkillVersion(row) : null;
|
|
1760
1779
|
}
|
|
1780
|
+
async getPublishedSelectionStates(principal, selections2) {
|
|
1781
|
+
if (selections2.length > MAX_PROFILE_SELECTIONS)
|
|
1782
|
+
throw new RangeError("Published selection lookup exceeds the profile selection limit");
|
|
1783
|
+
if (!selections2.length)
|
|
1784
|
+
return [];
|
|
1785
|
+
const requested = JSON.stringify(selections2.map(({ slug, version }) => ({ slug, version })));
|
|
1786
|
+
return this.all(`SELECT json_extract(q.value, '$.slug') AS slug, json_extract(q.value, '$.version') AS version,
|
|
1787
|
+
r.slug IS NOT NULL AS skill_exists, r.lifecycle, r.tombstoned_at,
|
|
1788
|
+
v.bundle_sha256, b.sha256 IS NOT NULL AS bundle_available
|
|
1789
|
+
FROM json_each(?) q
|
|
1790
|
+
LEFT JOIN skills_registry r ON r.org_id = ? AND r.slug = json_extract(q.value, '$.slug')
|
|
1791
|
+
LEFT JOIN skills_versions v ON v.org_id = ?
|
|
1792
|
+
AND v.slug = json_extract(q.value, '$.slug') AND v.version = json_extract(q.value, '$.version')
|
|
1793
|
+
LEFT JOIN skills_bundles b ON b.org_id = ? AND b.sha256 = v.bundle_sha256
|
|
1794
|
+
ORDER BY CAST(q.key AS INTEGER)`, [requested, principal.orgId, principal.orgId, principal.orgId]).map(rowToPublishedSelectionState);
|
|
1795
|
+
}
|
|
1761
1796
|
async pinSkill(principal, slug, metadata = {}) {
|
|
1762
1797
|
const row = this.get(`INSERT INTO skills_pins (org_id, principal, slug, pinned_at, metadata_json)
|
|
1763
1798
|
VALUES (?, ?, ?, ?, ?)
|
package/bin/server.js
CHANGED
|
@@ -24122,7 +24122,7 @@ var init_dist_es9 = __esm(() => {
|
|
|
24122
24122
|
// package.json
|
|
24123
24123
|
var package_default = {
|
|
24124
24124
|
name: "@hasna/skills",
|
|
24125
|
-
version: "0.9.
|
|
24125
|
+
version: "0.9.13",
|
|
24126
24126
|
description: "Skills library for AI coding agents",
|
|
24127
24127
|
type: "module",
|
|
24128
24128
|
bin: {
|
|
@@ -35194,6 +35194,18 @@ function rowToSkill(row) {
|
|
|
35194
35194
|
...row.replacement_slug ? { replacementSlug: String(row.replacement_slug) } : {}
|
|
35195
35195
|
};
|
|
35196
35196
|
}
|
|
35197
|
+
function rowToPublishedSelectionState(row) {
|
|
35198
|
+
return {
|
|
35199
|
+
slug: String(row.slug),
|
|
35200
|
+
version: String(row.version),
|
|
35201
|
+
current: row.skill_exists ? {
|
|
35202
|
+
lifecycle: row.lifecycle === "archived" ? "archived" : "active",
|
|
35203
|
+
...row.tombstoned_at ? { tombstonedAt: dateString(row.tombstoned_at) } : {}
|
|
35204
|
+
} : null,
|
|
35205
|
+
versionBundleSha256: typeof row.bundle_sha256 === "string" ? row.bundle_sha256 : null,
|
|
35206
|
+
bundleAvailable: Boolean(row.bundle_available)
|
|
35207
|
+
};
|
|
35208
|
+
}
|
|
35197
35209
|
function rowToPin(row) {
|
|
35198
35210
|
return {
|
|
35199
35211
|
orgId: String(row.org_id),
|
|
@@ -35266,6 +35278,25 @@ function rowToSkillVersion(row) {
|
|
|
35266
35278
|
};
|
|
35267
35279
|
}
|
|
35268
35280
|
|
|
35281
|
+
// src/lib/profile-limits.ts
|
|
35282
|
+
var MAX_PROFILE_SELECTIONS = 4096;
|
|
35283
|
+
var MAX_PROFILE_DOCUMENT_BYTES = 8 * 1024 * 1024;
|
|
35284
|
+
var MAX_SKILL_SESSION_ID_CHARS = 256;
|
|
35285
|
+
var PROFILE_SESSION_ENVELOPE_BYTES = MAX_PROFILE_SELECTIONS * 67 + MAX_SKILL_SESSION_ID_CHARS * 12 + 512;
|
|
35286
|
+
var MAX_RESOLVED_PROFILE_BYTES = MAX_PROFILE_DOCUMENT_BYTES - PROFILE_SESSION_ENVELOPE_BYTES;
|
|
35287
|
+
function profileDocumentBytes(value) {
|
|
35288
|
+
return new TextEncoder().encode(JSON.stringify(value)).byteLength;
|
|
35289
|
+
}
|
|
35290
|
+
function resolvedProfileSnapshot(profile2, authority) {
|
|
35291
|
+
return {
|
|
35292
|
+
profileId: profile2.id,
|
|
35293
|
+
workspaceId: profile2.workspaceId,
|
|
35294
|
+
profileRevision: profile2.revision,
|
|
35295
|
+
authority,
|
|
35296
|
+
selections: profile2.selections.map((selection) => ({ ...selection, authority, workspaceId: profile2.workspaceId, profileRevision: profile2.revision }))
|
|
35297
|
+
};
|
|
35298
|
+
}
|
|
35299
|
+
|
|
35269
35300
|
// src/server/types.ts
|
|
35270
35301
|
class StaleLeaseGenerationError extends Error {
|
|
35271
35302
|
runId;
|
|
@@ -35968,6 +35999,22 @@ class SqliteSkillsStore {
|
|
|
35968
35999
|
const row = this.get("SELECT * FROM skills_versions WHERE org_id = ? AND slug = ? AND version = ? LIMIT 1", [principal.orgId, slug, version2]);
|
|
35969
36000
|
return row ? rowToSkillVersion(row) : null;
|
|
35970
36001
|
}
|
|
36002
|
+
async getPublishedSelectionStates(principal, selections2) {
|
|
36003
|
+
if (selections2.length > MAX_PROFILE_SELECTIONS)
|
|
36004
|
+
throw new RangeError("Published selection lookup exceeds the profile selection limit");
|
|
36005
|
+
if (!selections2.length)
|
|
36006
|
+
return [];
|
|
36007
|
+
const requested = JSON.stringify(selections2.map(({ slug, version: version2 }) => ({ slug, version: version2 })));
|
|
36008
|
+
return this.all(`SELECT json_extract(q.value, '$.slug') AS slug, json_extract(q.value, '$.version') AS version,
|
|
36009
|
+
r.slug IS NOT NULL AS skill_exists, r.lifecycle, r.tombstoned_at,
|
|
36010
|
+
v.bundle_sha256, b.sha256 IS NOT NULL AS bundle_available
|
|
36011
|
+
FROM json_each(?) q
|
|
36012
|
+
LEFT JOIN skills_registry r ON r.org_id = ? AND r.slug = json_extract(q.value, '$.slug')
|
|
36013
|
+
LEFT JOIN skills_versions v ON v.org_id = ?
|
|
36014
|
+
AND v.slug = json_extract(q.value, '$.slug') AND v.version = json_extract(q.value, '$.version')
|
|
36015
|
+
LEFT JOIN skills_bundles b ON b.org_id = ? AND b.sha256 = v.bundle_sha256
|
|
36016
|
+
ORDER BY CAST(q.key AS INTEGER)`, [requested, principal.orgId, principal.orgId, principal.orgId]).map(rowToPublishedSelectionState);
|
|
36017
|
+
}
|
|
35971
36018
|
async pinSkill(principal, slug, metadata = {}) {
|
|
35972
36019
|
const row = this.get(`INSERT INTO skills_pins (org_id, principal, slug, pinned_at, metadata_json)
|
|
35973
36020
|
VALUES (?, ?, ?, ?, ?)
|
|
@@ -36532,25 +36579,6 @@ function selectionAliasError(selections2) {
|
|
|
36532
36579
|
}
|
|
36533
36580
|
}
|
|
36534
36581
|
|
|
36535
|
-
// src/lib/profile-limits.ts
|
|
36536
|
-
var MAX_PROFILE_SELECTIONS = 4096;
|
|
36537
|
-
var MAX_PROFILE_DOCUMENT_BYTES = 8 * 1024 * 1024;
|
|
36538
|
-
var MAX_SKILL_SESSION_ID_CHARS = 256;
|
|
36539
|
-
var PROFILE_SESSION_ENVELOPE_BYTES = MAX_PROFILE_SELECTIONS * 67 + MAX_SKILL_SESSION_ID_CHARS * 12 + 512;
|
|
36540
|
-
var MAX_RESOLVED_PROFILE_BYTES = MAX_PROFILE_DOCUMENT_BYTES - PROFILE_SESSION_ENVELOPE_BYTES;
|
|
36541
|
-
function profileDocumentBytes(value) {
|
|
36542
|
-
return new TextEncoder().encode(JSON.stringify(value)).byteLength;
|
|
36543
|
-
}
|
|
36544
|
-
function resolvedProfileSnapshot(profile2, authority) {
|
|
36545
|
-
return {
|
|
36546
|
-
profileId: profile2.id,
|
|
36547
|
-
workspaceId: profile2.workspaceId,
|
|
36548
|
-
profileRevision: profile2.revision,
|
|
36549
|
-
authority,
|
|
36550
|
-
selections: profile2.selections.map((selection) => ({ ...selection, authority, workspaceId: profile2.workspaceId, profileRevision: profile2.revision }))
|
|
36551
|
-
};
|
|
36552
|
-
}
|
|
36553
|
-
|
|
36554
36582
|
// src/lib/selection-cache.ts
|
|
36555
36583
|
class SkillSelectionError extends Error {
|
|
36556
36584
|
code;
|
|
@@ -37601,16 +37629,21 @@ function selected(value) {
|
|
|
37601
37629
|
return selections2;
|
|
37602
37630
|
}
|
|
37603
37631
|
async function validatePublished(store, principal, selections2) {
|
|
37604
|
-
|
|
37605
|
-
|
|
37632
|
+
const states = await store.getPublishedSelectionStates(principal, selections2);
|
|
37633
|
+
if (states.length !== selections2.length)
|
|
37634
|
+
throw new SkillRequestError(503, "SELECTION_UNAVAILABLE", "Selected publication state is unavailable");
|
|
37635
|
+
for (const [index, selection2] of selections2.entries()) {
|
|
37636
|
+
const state2 = states[index];
|
|
37637
|
+
if (!state2 || state2.slug !== selection2.slug || state2.version !== selection2.version)
|
|
37638
|
+
throw new SkillRequestError(503, "SELECTION_UNAVAILABLE", "Selected publication state is unavailable");
|
|
37639
|
+
const current = state2.current;
|
|
37606
37640
|
if (!current || current.tombstonedAt)
|
|
37607
37641
|
throw new SkillRequestError(current?.tombstonedAt ? 410 : 404, "SELECTION_UNAVAILABLE", `Selected skill '${selection2.slug}' is unavailable`);
|
|
37608
37642
|
if (current.lifecycle === "archived")
|
|
37609
37643
|
throw new SkillRequestError(409, "SELECTION_ARCHIVED", `Selected skill '${selection2.slug}' is archived`);
|
|
37610
|
-
|
|
37611
|
-
if (!version2 || `sha256:${version2.bundleSha256}` !== selection2.bundleDigest)
|
|
37644
|
+
if (!state2.versionBundleSha256 || `sha256:${state2.versionBundleSha256}` !== selection2.bundleDigest)
|
|
37612
37645
|
throw new SkillRequestError(409, "SELECTION_VERSION_MISMATCH", `Selected version of '${selection2.slug}' does not match its published digest`);
|
|
37613
|
-
if (!
|
|
37646
|
+
if (!state2.bundleAvailable)
|
|
37614
37647
|
throw new SkillRequestError(503, "SELECTION_BUNDLE_UNAVAILABLE", "Selected bundle is unavailable");
|
|
37615
37648
|
}
|
|
37616
37649
|
}
|
|
@@ -43171,6 +43204,25 @@ class MemorySkillsStore {
|
|
|
43171
43204
|
const found = this.versions.get(versionKey(principal.orgId, slug, version2));
|
|
43172
43205
|
return found && found.orgId === principal.orgId ? found : null;
|
|
43173
43206
|
}
|
|
43207
|
+
async getPublishedSelectionStates(principal, selections2) {
|
|
43208
|
+
if (selections2.length > MAX_PROFILE_SELECTIONS)
|
|
43209
|
+
throw new RangeError("Published selection lookup exceeds the profile selection limit");
|
|
43210
|
+
return selections2.map(({ slug, version: version2 }) => {
|
|
43211
|
+
const current = this.skills.get(skillKey(principal.orgId, slug));
|
|
43212
|
+
const selectedVersion = this.versions.get(versionKey(principal.orgId, slug, version2));
|
|
43213
|
+
const bundle = selectedVersion && this.bundles.get(skillKey(principal.orgId, selectedVersion.bundleSha256));
|
|
43214
|
+
return {
|
|
43215
|
+
slug,
|
|
43216
|
+
version: version2,
|
|
43217
|
+
current: current?.orgId === principal.orgId ? {
|
|
43218
|
+
lifecycle: current.lifecycle,
|
|
43219
|
+
...current.tombstonedAt ? { tombstonedAt: current.tombstonedAt } : {}
|
|
43220
|
+
} : null,
|
|
43221
|
+
versionBundleSha256: selectedVersion?.orgId === principal.orgId ? selectedVersion.bundleSha256 : null,
|
|
43222
|
+
bundleAvailable: bundle?.orgId === principal.orgId
|
|
43223
|
+
};
|
|
43224
|
+
});
|
|
43225
|
+
}
|
|
43174
43226
|
async listSkills(principal) {
|
|
43175
43227
|
return Array.from(this.skills.values()).filter((skill) => skill.orgId === principal.orgId && !skill.tombstonedAt).sort((a4, b4) => a4.slug.localeCompare(b4.slug));
|
|
43176
43228
|
}
|
|
@@ -43979,6 +44031,25 @@ class PostgresSkillsStore {
|
|
|
43979
44031
|
`;
|
|
43980
44032
|
return rows[0] ? rowToSkillVersion(rows[0]) : null;
|
|
43981
44033
|
}
|
|
44034
|
+
async getPublishedSelectionStates(principal, selections2) {
|
|
44035
|
+
if (selections2.length > MAX_PROFILE_SELECTIONS)
|
|
44036
|
+
throw new RangeError("Published selection lookup exceeds the profile selection limit");
|
|
44037
|
+
if (!selections2.length)
|
|
44038
|
+
return [];
|
|
44039
|
+
const requested = JSON.stringify(selections2.map(({ slug, version: version2 }) => ({ slug, version: version2 })));
|
|
44040
|
+
const rows = await this.sql`
|
|
44041
|
+
SELECT q.value->>'slug' AS slug, q.value->>'version' AS version,
|
|
44042
|
+
r.slug IS NOT NULL AS skill_exists, r.lifecycle, r.tombstoned_at,
|
|
44043
|
+
v.bundle_sha256, b.sha256 IS NOT NULL AS bundle_available
|
|
44044
|
+
FROM jsonb_array_elements(${requested}::text::jsonb) WITH ORDINALITY AS q(value, ordinal)
|
|
44045
|
+
LEFT JOIN skills_registry r ON r.org_id = ${principal.orgId} AND r.slug = q.value->>'slug'
|
|
44046
|
+
LEFT JOIN skills_versions v ON v.org_id = ${principal.orgId}
|
|
44047
|
+
AND v.slug = q.value->>'slug' AND v.version = q.value->>'version'
|
|
44048
|
+
LEFT JOIN skills_bundles b ON b.org_id = ${principal.orgId} AND b.sha256 = v.bundle_sha256
|
|
44049
|
+
ORDER BY q.ordinal
|
|
44050
|
+
`;
|
|
44051
|
+
return rows.map(rowToPublishedSelectionState);
|
|
44052
|
+
}
|
|
43982
44053
|
async pinSkill(principal, slug, metadata = {}) {
|
|
43983
44054
|
const rows = await this.sql`
|
|
43984
44055
|
INSERT INTO skills_pins (org_id, principal, slug, pinned_at, metadata_json)
|
package/bin/worker.js
CHANGED
|
@@ -24125,7 +24125,7 @@ import { randomUUID as randomUUID6 } from "crypto";
|
|
|
24125
24125
|
// package.json
|
|
24126
24126
|
var package_default = {
|
|
24127
24127
|
name: "@hasna/skills",
|
|
24128
|
-
version: "0.9.
|
|
24128
|
+
version: "0.9.13",
|
|
24129
24129
|
description: "Skills library for AI coding agents",
|
|
24130
24130
|
type: "module",
|
|
24131
24131
|
bin: {
|
|
@@ -34942,6 +34942,18 @@ function rowToSkill(row) {
|
|
|
34942
34942
|
...row.replacement_slug ? { replacementSlug: String(row.replacement_slug) } : {}
|
|
34943
34943
|
};
|
|
34944
34944
|
}
|
|
34945
|
+
function rowToPublishedSelectionState(row) {
|
|
34946
|
+
return {
|
|
34947
|
+
slug: String(row.slug),
|
|
34948
|
+
version: String(row.version),
|
|
34949
|
+
current: row.skill_exists ? {
|
|
34950
|
+
lifecycle: row.lifecycle === "archived" ? "archived" : "active",
|
|
34951
|
+
...row.tombstoned_at ? { tombstonedAt: dateString(row.tombstoned_at) } : {}
|
|
34952
|
+
} : null,
|
|
34953
|
+
versionBundleSha256: typeof row.bundle_sha256 === "string" ? row.bundle_sha256 : null,
|
|
34954
|
+
bundleAvailable: Boolean(row.bundle_available)
|
|
34955
|
+
};
|
|
34956
|
+
}
|
|
34945
34957
|
function rowToPin(row) {
|
|
34946
34958
|
return {
|
|
34947
34959
|
orgId: String(row.org_id),
|
|
@@ -35014,6 +35026,13 @@ function rowToSkillVersion(row) {
|
|
|
35014
35026
|
};
|
|
35015
35027
|
}
|
|
35016
35028
|
|
|
35029
|
+
// src/lib/profile-limits.ts
|
|
35030
|
+
var MAX_PROFILE_SELECTIONS = 4096;
|
|
35031
|
+
var MAX_PROFILE_DOCUMENT_BYTES = 8 * 1024 * 1024;
|
|
35032
|
+
var MAX_SKILL_SESSION_ID_CHARS = 256;
|
|
35033
|
+
var PROFILE_SESSION_ENVELOPE_BYTES = MAX_PROFILE_SELECTIONS * 67 + MAX_SKILL_SESSION_ID_CHARS * 12 + 512;
|
|
35034
|
+
var MAX_RESOLVED_PROFILE_BYTES = MAX_PROFILE_DOCUMENT_BYTES - PROFILE_SESSION_ENVELOPE_BYTES;
|
|
35035
|
+
|
|
35017
35036
|
// src/server/types.ts
|
|
35018
35037
|
class StaleLeaseGenerationError extends Error {
|
|
35019
35038
|
runId;
|
|
@@ -35715,6 +35734,22 @@ class SqliteSkillsStore {
|
|
|
35715
35734
|
const row = this.get("SELECT * FROM skills_versions WHERE org_id = ? AND slug = ? AND version = ? LIMIT 1", [principal.orgId, slug, version2]);
|
|
35716
35735
|
return row ? rowToSkillVersion(row) : null;
|
|
35717
35736
|
}
|
|
35737
|
+
async getPublishedSelectionStates(principal, selections2) {
|
|
35738
|
+
if (selections2.length > MAX_PROFILE_SELECTIONS)
|
|
35739
|
+
throw new RangeError("Published selection lookup exceeds the profile selection limit");
|
|
35740
|
+
if (!selections2.length)
|
|
35741
|
+
return [];
|
|
35742
|
+
const requested = JSON.stringify(selections2.map(({ slug, version: version2 }) => ({ slug, version: version2 })));
|
|
35743
|
+
return this.all(`SELECT json_extract(q.value, '$.slug') AS slug, json_extract(q.value, '$.version') AS version,
|
|
35744
|
+
r.slug IS NOT NULL AS skill_exists, r.lifecycle, r.tombstoned_at,
|
|
35745
|
+
v.bundle_sha256, b.sha256 IS NOT NULL AS bundle_available
|
|
35746
|
+
FROM json_each(?) q
|
|
35747
|
+
LEFT JOIN skills_registry r ON r.org_id = ? AND r.slug = json_extract(q.value, '$.slug')
|
|
35748
|
+
LEFT JOIN skills_versions v ON v.org_id = ?
|
|
35749
|
+
AND v.slug = json_extract(q.value, '$.slug') AND v.version = json_extract(q.value, '$.version')
|
|
35750
|
+
LEFT JOIN skills_bundles b ON b.org_id = ? AND b.sha256 = v.bundle_sha256
|
|
35751
|
+
ORDER BY CAST(q.key AS INTEGER)`, [requested, principal.orgId, principal.orgId, principal.orgId]).map(rowToPublishedSelectionState);
|
|
35752
|
+
}
|
|
35718
35753
|
async pinSkill(principal, slug, metadata = {}) {
|
|
35719
35754
|
const row = this.get(`INSERT INTO skills_pins (org_id, principal, slug, pinned_at, metadata_json)
|
|
35720
35755
|
VALUES (?, ?, ?, ?, ?)
|
|
@@ -35996,13 +36031,6 @@ var init_client = __esm2(() => {
|
|
|
35996
36031
|
init_client();
|
|
35997
36032
|
init_client();
|
|
35998
36033
|
|
|
35999
|
-
// src/lib/profile-limits.ts
|
|
36000
|
-
var MAX_PROFILE_SELECTIONS = 4096;
|
|
36001
|
-
var MAX_PROFILE_DOCUMENT_BYTES = 8 * 1024 * 1024;
|
|
36002
|
-
var MAX_SKILL_SESSION_ID_CHARS = 256;
|
|
36003
|
-
var PROFILE_SESSION_ENVELOPE_BYTES = MAX_PROFILE_SELECTIONS * 67 + MAX_SKILL_SESSION_ID_CHARS * 12 + 512;
|
|
36004
|
-
var MAX_RESOLVED_PROFILE_BYTES = MAX_PROFILE_DOCUMENT_BYTES - PROFILE_SESSION_ENVELOPE_BYTES;
|
|
36005
|
-
|
|
36006
36034
|
// src/lib/selection-cache.ts
|
|
36007
36035
|
var MAX_CACHED_PROFILE_AGE_MS = 24 * 60 * 60 * 1000;
|
|
36008
36036
|
|
|
@@ -36707,6 +36735,25 @@ class MemorySkillsStore {
|
|
|
36707
36735
|
const found = this.versions.get(versionKey(principal.orgId, slug, version2));
|
|
36708
36736
|
return found && found.orgId === principal.orgId ? found : null;
|
|
36709
36737
|
}
|
|
36738
|
+
async getPublishedSelectionStates(principal, selections2) {
|
|
36739
|
+
if (selections2.length > MAX_PROFILE_SELECTIONS)
|
|
36740
|
+
throw new RangeError("Published selection lookup exceeds the profile selection limit");
|
|
36741
|
+
return selections2.map(({ slug, version: version2 }) => {
|
|
36742
|
+
const current = this.skills.get(skillKey(principal.orgId, slug));
|
|
36743
|
+
const selectedVersion = this.versions.get(versionKey(principal.orgId, slug, version2));
|
|
36744
|
+
const bundle = selectedVersion && this.bundles.get(skillKey(principal.orgId, selectedVersion.bundleSha256));
|
|
36745
|
+
return {
|
|
36746
|
+
slug,
|
|
36747
|
+
version: version2,
|
|
36748
|
+
current: current?.orgId === principal.orgId ? {
|
|
36749
|
+
lifecycle: current.lifecycle,
|
|
36750
|
+
...current.tombstonedAt ? { tombstonedAt: current.tombstonedAt } : {}
|
|
36751
|
+
} : null,
|
|
36752
|
+
versionBundleSha256: selectedVersion?.orgId === principal.orgId ? selectedVersion.bundleSha256 : null,
|
|
36753
|
+
bundleAvailable: bundle?.orgId === principal.orgId
|
|
36754
|
+
};
|
|
36755
|
+
});
|
|
36756
|
+
}
|
|
36710
36757
|
async listSkills(principal) {
|
|
36711
36758
|
return Array.from(this.skills.values()).filter((skill) => skill.orgId === principal.orgId && !skill.tombstonedAt).sort((a3, b3) => a3.slug.localeCompare(b3.slug));
|
|
36712
36759
|
}
|
|
@@ -37515,6 +37562,25 @@ class PostgresSkillsStore {
|
|
|
37515
37562
|
`;
|
|
37516
37563
|
return rows[0] ? rowToSkillVersion(rows[0]) : null;
|
|
37517
37564
|
}
|
|
37565
|
+
async getPublishedSelectionStates(principal, selections2) {
|
|
37566
|
+
if (selections2.length > MAX_PROFILE_SELECTIONS)
|
|
37567
|
+
throw new RangeError("Published selection lookup exceeds the profile selection limit");
|
|
37568
|
+
if (!selections2.length)
|
|
37569
|
+
return [];
|
|
37570
|
+
const requested = JSON.stringify(selections2.map(({ slug, version: version2 }) => ({ slug, version: version2 })));
|
|
37571
|
+
const rows = await this.sql`
|
|
37572
|
+
SELECT q.value->>'slug' AS slug, q.value->>'version' AS version,
|
|
37573
|
+
r.slug IS NOT NULL AS skill_exists, r.lifecycle, r.tombstoned_at,
|
|
37574
|
+
v.bundle_sha256, b.sha256 IS NOT NULL AS bundle_available
|
|
37575
|
+
FROM jsonb_array_elements(${requested}::text::jsonb) WITH ORDINALITY AS q(value, ordinal)
|
|
37576
|
+
LEFT JOIN skills_registry r ON r.org_id = ${principal.orgId} AND r.slug = q.value->>'slug'
|
|
37577
|
+
LEFT JOIN skills_versions v ON v.org_id = ${principal.orgId}
|
|
37578
|
+
AND v.slug = q.value->>'slug' AND v.version = q.value->>'version'
|
|
37579
|
+
LEFT JOIN skills_bundles b ON b.org_id = ${principal.orgId} AND b.sha256 = v.bundle_sha256
|
|
37580
|
+
ORDER BY q.ordinal
|
|
37581
|
+
`;
|
|
37582
|
+
return rows.map(rowToPublishedSelectionState);
|
|
37583
|
+
}
|
|
37518
37584
|
async pinSkill(principal, slug, metadata = {}) {
|
|
37519
37585
|
const rows = await this.sql`
|
|
37520
37586
|
INSERT INTO skills_pins (org_id, principal, slug, pinned_at, metadata_json)
|
package/dist/index.d.ts
CHANGED
|
@@ -60,11 +60,12 @@ export type { SkillSelection, SkillProfile, ResolvedSkillSelection, ResolvedSkil
|
|
|
60
60
|
export { buildSkillContext } from "./lib/skill-context.js";
|
|
61
61
|
export { syncSelectionProfile } from "./lib/selection-resolver.js";
|
|
62
62
|
export { inspectSkillSession, reconcileSkillSession, type SessionReconciliationInput, type SessionReconciliationOptions } from "./lib/session-reconciliation.js";
|
|
63
|
-
export { planAgentIntegration, applyAgentIntegration, inventoryNativeSkills, archiveNativeSkills } from "./lib/agent-integration.js";
|
|
63
|
+
export { planAgentIntegration, planClaudeStopHookUpdate, applyAgentIntegration, inventoryNativeSkills, archiveNativeSkills } from "./lib/agent-integration.js";
|
|
64
64
|
export { captureDiscoveryDirectories, captureDiscoveryByteSources, captureDiscoveryPathSources, type DiscoveryDirectory, type DiscoverySource } from "./lib/agent-discovery.js";
|
|
65
|
-
export { captureClaudeMarketplaceRegistry } from "./lib/claude-marketplace-registry.js";
|
|
66
|
-
export { captureClaudeSettings } from "./lib/claude-settings-witness.js";
|
|
65
|
+
export { captureClaudeMarketplaceRegistry, captureClaudeMarketplaceRegistryV2 } from "./lib/claude-marketplace-registry.js";
|
|
66
|
+
export { captureClaudeSettings, captureClaudeSettingsV2 } from "./lib/claude-settings-witness.js";
|
|
67
67
|
export { buildPluginProjection, pluginTreeDigest, type PluginProjectionManifest, type PluginPayloadMapping, type PluginFileWitness } from "./lib/plugin-projection.js";
|
|
68
68
|
export { planPluginAdmission, admitPlugin, resolveAdmittedPlugin, pluginResolverCommand, type PluginAdmissionTarget, type PluginAdmissionBinding, type PluginAdmissionPrincipal, type PluginAdmissionPlan, type PluginAdmissionIdentity, type PluginBundleIdentity, type PluginRoutingIdentity, type PluginAdmissionReceipt } from "./lib/plugin-admission.js";
|
|
69
69
|
export { captureManagedPluginRegistry, type ManagedPluginRegistrationWitness } from "./lib/plugin-discovery.js";
|
|
70
70
|
export type { RemoteCreditCheckoutOptions, RemoteCreditCheckout, RemoteCreditCheckoutErrorCode } from "./lib/remote-credit-checkout.js";
|
|
71
|
+
export { assertPortableAuthoringPath, type PortableAuthoringPathOptions } from "./lib/authoring-path.js";
|