@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.
@@ -2737,6 +2737,18 @@ function rowToSkill(row) {
2737
2737
  ...row.replacement_slug ? { replacementSlug: String(row.replacement_slug) } : {}
2738
2738
  };
2739
2739
  }
2740
+ function rowToPublishedSelectionState(row) {
2741
+ return {
2742
+ slug: String(row.slug),
2743
+ version: String(row.version),
2744
+ current: row.skill_exists ? {
2745
+ lifecycle: row.lifecycle === "archived" ? "archived" : "active",
2746
+ ...row.tombstoned_at ? { tombstonedAt: dateString(row.tombstoned_at) } : {}
2747
+ } : null,
2748
+ versionBundleSha256: typeof row.bundle_sha256 === "string" ? row.bundle_sha256 : null,
2749
+ bundleAvailable: Boolean(row.bundle_available)
2750
+ };
2751
+ }
2740
2752
  function rowToPin(row) {
2741
2753
  return {
2742
2754
  orgId: String(row.org_id),
@@ -2809,6 +2821,13 @@ function rowToSkillVersion(row) {
2809
2821
  };
2810
2822
  }
2811
2823
 
2824
+ // src/lib/profile-limits.ts
2825
+ var MAX_PROFILE_SELECTIONS = 4096;
2826
+ var MAX_PROFILE_DOCUMENT_BYTES = 8 * 1024 * 1024;
2827
+ var MAX_SKILL_SESSION_ID_CHARS = 256;
2828
+ var PROFILE_SESSION_ENVELOPE_BYTES = MAX_PROFILE_SELECTIONS * 67 + MAX_SKILL_SESSION_ID_CHARS * 12 + 512;
2829
+ var MAX_RESOLVED_PROFILE_BYTES = MAX_PROFILE_DOCUMENT_BYTES - PROFILE_SESSION_ENVELOPE_BYTES;
2830
+
2812
2831
  // src/lib/revision.ts
2813
2832
  import { createHash as createHash2 } from "crypto";
2814
2833
  function revisionIdOf(content) {
@@ -3495,6 +3514,22 @@ class SqliteSkillsStore {
3495
3514
  const row = this.get("SELECT * FROM skills_versions WHERE org_id = ? AND slug = ? AND version = ? LIMIT 1", [principal.orgId, slug, version]);
3496
3515
  return row ? rowToSkillVersion(row) : null;
3497
3516
  }
3517
+ async getPublishedSelectionStates(principal, selections2) {
3518
+ if (selections2.length > MAX_PROFILE_SELECTIONS)
3519
+ throw new RangeError("Published selection lookup exceeds the profile selection limit");
3520
+ if (!selections2.length)
3521
+ return [];
3522
+ const requested = JSON.stringify(selections2.map(({ slug, version }) => ({ slug, version })));
3523
+ return this.all(`SELECT json_extract(q.value, '$.slug') AS slug, json_extract(q.value, '$.version') AS version,
3524
+ r.slug IS NOT NULL AS skill_exists, r.lifecycle, r.tombstoned_at,
3525
+ v.bundle_sha256, b.sha256 IS NOT NULL AS bundle_available
3526
+ FROM json_each(?) q
3527
+ LEFT JOIN skills_registry r ON r.org_id = ? AND r.slug = json_extract(q.value, '$.slug')
3528
+ LEFT JOIN skills_versions v ON v.org_id = ?
3529
+ AND v.slug = json_extract(q.value, '$.slug') AND v.version = json_extract(q.value, '$.version')
3530
+ LEFT JOIN skills_bundles b ON b.org_id = ? AND b.sha256 = v.bundle_sha256
3531
+ ORDER BY CAST(q.key AS INTEGER)`, [requested, principal.orgId, principal.orgId, principal.orgId]).map(rowToPublishedSelectionState);
3532
+ }
3498
3533
  async pinSkill(principal, slug, metadata = {}) {
3499
3534
  const row = this.get(`INSERT INTO skills_pins (org_id, principal, slug, pinned_at, metadata_json)
3500
3535
  VALUES (?, ?, ?, ?, ?)
@@ -3899,6 +3934,25 @@ class MemorySkillsStore {
3899
3934
  const found = this.versions.get(versionKey(principal.orgId, slug, version));
3900
3935
  return found && found.orgId === principal.orgId ? found : null;
3901
3936
  }
3937
+ async getPublishedSelectionStates(principal, selections2) {
3938
+ if (selections2.length > MAX_PROFILE_SELECTIONS)
3939
+ throw new RangeError("Published selection lookup exceeds the profile selection limit");
3940
+ return selections2.map(({ slug, version }) => {
3941
+ const current = this.skills.get(skillKey(principal.orgId, slug));
3942
+ const selectedVersion = this.versions.get(versionKey(principal.orgId, slug, version));
3943
+ const bundle = selectedVersion && this.bundles.get(skillKey(principal.orgId, selectedVersion.bundleSha256));
3944
+ return {
3945
+ slug,
3946
+ version,
3947
+ current: current?.orgId === principal.orgId ? {
3948
+ lifecycle: current.lifecycle,
3949
+ ...current.tombstonedAt ? { tombstonedAt: current.tombstonedAt } : {}
3950
+ } : null,
3951
+ versionBundleSha256: selectedVersion?.orgId === principal.orgId ? selectedVersion.bundleSha256 : null,
3952
+ bundleAvailable: bundle?.orgId === principal.orgId
3953
+ };
3954
+ });
3955
+ }
3902
3956
  async listSkills(principal) {
3903
3957
  return Array.from(this.skills.values()).filter((skill) => skill.orgId === principal.orgId && !skill.tombstonedAt).sort((a, b) => a.slug.localeCompare(b.slug));
3904
3958
  }
@@ -4707,6 +4761,25 @@ class PostgresSkillsStore {
4707
4761
  `;
4708
4762
  return rows[0] ? rowToSkillVersion(rows[0]) : null;
4709
4763
  }
4764
+ async getPublishedSelectionStates(principal, selections2) {
4765
+ if (selections2.length > MAX_PROFILE_SELECTIONS)
4766
+ throw new RangeError("Published selection lookup exceeds the profile selection limit");
4767
+ if (!selections2.length)
4768
+ return [];
4769
+ const requested = JSON.stringify(selections2.map(({ slug, version }) => ({ slug, version })));
4770
+ const rows = await this.sql`
4771
+ SELECT q.value->>'slug' AS slug, q.value->>'version' AS version,
4772
+ r.slug IS NOT NULL AS skill_exists, r.lifecycle, r.tombstoned_at,
4773
+ v.bundle_sha256, b.sha256 IS NOT NULL AS bundle_available
4774
+ FROM jsonb_array_elements(${requested}::text::jsonb) WITH ORDINALITY AS q(value, ordinal)
4775
+ LEFT JOIN skills_registry r ON r.org_id = ${principal.orgId} AND r.slug = q.value->>'slug'
4776
+ LEFT JOIN skills_versions v ON v.org_id = ${principal.orgId}
4777
+ AND v.slug = q.value->>'slug' AND v.version = q.value->>'version'
4778
+ LEFT JOIN skills_bundles b ON b.org_id = ${principal.orgId} AND b.sha256 = v.bundle_sha256
4779
+ ORDER BY q.ordinal
4780
+ `;
4781
+ return rows.map(rowToPublishedSelectionState);
4782
+ }
4710
4783
  async pinSkill(principal, slug, metadata = {}) {
4711
4784
  const rows = await this.sql`
4712
4785
  INSERT INTO skills_pins (org_id, principal, slug, pinned_at, metadata_json)