@hasna/skills 0.10.10 → 0.10.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/dist/sdk/index.js CHANGED
@@ -32373,7 +32373,7 @@ var init_event_sink = __esm(() => {
32373
32373
  // package.json
32374
32374
  var package_default = {
32375
32375
  name: "@hasna/skills",
32376
- version: "0.10.10",
32376
+ version: "0.10.13",
32377
32377
  description: "Skills library for AI coding agents",
32378
32378
  type: "module",
32379
32379
  bin: {
@@ -40984,6 +40984,196 @@ export default async ({ directory }) => {
40984
40984
  // src/lib/agent-codex.ts
40985
40985
  import { isDeepStrictEqual as isDeepStrictEqual4 } from "util";
40986
40986
  var CODEX_SKILL_CONFIG_SECTIONS = /^\[\[skills\.config\]\][^\n]*(?:\n(?!\s*\[)[^\n]*)*/gm;
40987
+ var codexPathConfigRefusal = () => new Error("Codex skill path controls require ordinary [[skills.config]] TOML tables or a native single-line inline array; preserve and review unsupported inline, dotted, or malformed definitions before running skills hook install");
40988
+ function splitTopLevel(value, delimiter) {
40989
+ const result = [];
40990
+ let start = 0, square = 0, curly = 0, quote2 = null, escaped = false;
40991
+ for (let index = 0;index < value.length; index++) {
40992
+ const char = value[index];
40993
+ if (quote2 === "double") {
40994
+ if (escaped)
40995
+ escaped = false;
40996
+ else if (char === "\\")
40997
+ escaped = true;
40998
+ else if (char === '"')
40999
+ quote2 = null;
41000
+ continue;
41001
+ }
41002
+ if (quote2 === "literal") {
41003
+ if (char === "'")
41004
+ quote2 = null;
41005
+ continue;
41006
+ }
41007
+ if (char === '"') {
41008
+ quote2 = "double";
41009
+ continue;
41010
+ }
41011
+ if (char === "'") {
41012
+ quote2 = "literal";
41013
+ continue;
41014
+ }
41015
+ if (char === "[")
41016
+ square++;
41017
+ else if (char === "]") {
41018
+ if (--square < 0)
41019
+ return null;
41020
+ } else if (char === "{")
41021
+ curly++;
41022
+ else if (char === "}") {
41023
+ if (--curly < 0)
41024
+ return null;
41025
+ } else if (char === delimiter && square === 0 && curly === 0) {
41026
+ result.push(value.slice(start, index));
41027
+ start = index + 1;
41028
+ }
41029
+ }
41030
+ if (quote2 !== null || square !== 0 || curly !== 0)
41031
+ return null;
41032
+ result.push(value.slice(start));
41033
+ return result;
41034
+ }
41035
+ function inlineArrayEnd(value) {
41036
+ if (!value.startsWith("["))
41037
+ return null;
41038
+ let square = 0, curly = 0, quote2 = null, escaped = false;
41039
+ for (let index = 0;index < value.length; index++) {
41040
+ const char = value[index];
41041
+ if (quote2 === "double") {
41042
+ if (escaped)
41043
+ escaped = false;
41044
+ else if (char === "\\")
41045
+ escaped = true;
41046
+ else if (char === '"')
41047
+ quote2 = null;
41048
+ continue;
41049
+ }
41050
+ if (quote2 === "literal") {
41051
+ if (char === "'")
41052
+ quote2 = null;
41053
+ continue;
41054
+ }
41055
+ if (char === '"') {
41056
+ quote2 = "double";
41057
+ continue;
41058
+ }
41059
+ if (char === "'") {
41060
+ quote2 = "literal";
41061
+ continue;
41062
+ }
41063
+ if (char === "[")
41064
+ square++;
41065
+ else if (char === "]") {
41066
+ if (--square < 0)
41067
+ return null;
41068
+ if (square === 0 && curly === 0)
41069
+ return index;
41070
+ } else if (char === "{")
41071
+ curly++;
41072
+ else if (char === "}") {
41073
+ if (--curly < 0)
41074
+ return null;
41075
+ }
41076
+ }
41077
+ return null;
41078
+ }
41079
+ function inlineRowsAsTables(value, newline) {
41080
+ const end = inlineArrayEnd(value);
41081
+ if (end === null || value.slice(end + 1).trim() !== "" || value.includes(`
41082
+ `) || value.includes("\r"))
41083
+ return null;
41084
+ const elements = splitTopLevel(value.slice(1, end), ",");
41085
+ if (!elements)
41086
+ return null;
41087
+ const rows = elements.map((element) => element.trim()).filter(Boolean);
41088
+ if (rows.length === 0)
41089
+ return "";
41090
+ const sections = [];
41091
+ for (const row of rows) {
41092
+ if (!row.startsWith("{") || !row.endsWith("}"))
41093
+ return null;
41094
+ const fields = splitTopLevel(row.slice(1, -1), ",");
41095
+ if (!fields)
41096
+ return null;
41097
+ const lines = fields.map((field2) => field2.trim()).filter(Boolean);
41098
+ if (lines.some((line) => !/^(?:path|name|enabled)\s*=/.test(line)))
41099
+ return null;
41100
+ const keys2 = lines.map((line) => line.slice(0, line.indexOf("=")).trim());
41101
+ if (new Set(keys2).size !== keys2.length)
41102
+ return null;
41103
+ sections.push(`[[skills.config]]${newline}${lines.join(newline)}${newline}`);
41104
+ }
41105
+ return sections.join("");
41106
+ }
41107
+ function normalizeCodexInlinePathConfig(text2) {
41108
+ const before = Bun.TOML.parse(text2);
41109
+ if (!Array.isArray(before.skills?.config))
41110
+ return text2;
41111
+ if (before.skills.config.length === 0)
41112
+ throw codexPathConfigRefusal();
41113
+ const expectedWithoutConfig = structuredClone(before);
41114
+ delete expectedWithoutConfig.skills.config;
41115
+ try {
41116
+ if (isDeepStrictEqual4(Bun.TOML.parse(text2.replace(CODEX_SKILL_CONFIG_SECTIONS, "")), expectedWithoutConfig))
41117
+ return text2;
41118
+ } catch {}
41119
+ const matches = [];
41120
+ for (const assignment of text2.matchAll(/^([ \t]*config[ \t]*=[ \t]*)(.*?)(\r?)$/gm)) {
41121
+ const rawValue = assignment[2].trimEnd();
41122
+ let quote2 = null, escaped = false, comment = "";
41123
+ for (let index = 0;index < rawValue.length; index++) {
41124
+ const char = rawValue[index];
41125
+ if (quote2 === "double") {
41126
+ if (escaped)
41127
+ escaped = false;
41128
+ else if (char === "\\")
41129
+ escaped = true;
41130
+ else if (char === '"')
41131
+ quote2 = null;
41132
+ continue;
41133
+ }
41134
+ if (quote2 === "literal") {
41135
+ if (char === "'")
41136
+ quote2 = null;
41137
+ continue;
41138
+ }
41139
+ if (char === '"')
41140
+ quote2 = "double";
41141
+ else if (char === "'")
41142
+ quote2 = "literal";
41143
+ else if (char === "#") {
41144
+ comment = rawValue.slice(index);
41145
+ break;
41146
+ }
41147
+ }
41148
+ const value = comment ? rawValue.slice(0, rawValue.length - comment.length).trimEnd() : rawValue;
41149
+ const tableSections = inlineRowsAsTables(value, text2.includes(`\r
41150
+ `) ? `\r
41151
+ ` : `
41152
+ `);
41153
+ if (tableSections === null)
41154
+ continue;
41155
+ const start = assignment.index;
41156
+ const end = start + assignment[0].length;
41157
+ const withoutAssignment = text2.slice(0, start) + (comment ? comment : "") + assignment[3] + text2.slice(end);
41158
+ const separator = withoutAssignment.endsWith(`
41159
+ `) ? withoutAssignment.endsWith(`
41160
+
41161
+ `) ? "" : `
41162
+ ` : `
41163
+
41164
+ `;
41165
+ const candidate2 = withoutAssignment + (tableSections ? separator + tableSections : "");
41166
+ try {
41167
+ const after = Bun.TOML.parse(candidate2);
41168
+ const expected = structuredClone(before);
41169
+ if (isDeepStrictEqual4(after, expected))
41170
+ matches.push(candidate2);
41171
+ } catch {}
41172
+ }
41173
+ if (matches.length !== 1)
41174
+ throw codexPathConfigRefusal();
41175
+ return matches[0];
41176
+ }
40987
41177
  function assertCodexPathConfigEditable(text2) {
40988
41178
  const before = Bun.TOML.parse(text2);
40989
41179
  if (before.skills?.config === undefined)
@@ -40994,8 +41184,12 @@ function assertCodexPathConfigEditable(text2) {
40994
41184
  const withoutSections = Bun.TOML.parse(text2.replace(CODEX_SKILL_CONFIG_SECTIONS, ""));
40995
41185
  if (isDeepStrictEqual4(withoutSections, expected))
40996
41186
  return;
41187
+ const normalized = normalizeCodexInlinePathConfig(text2);
41188
+ const withoutNormalizedSections = Bun.TOML.parse(normalized.replace(CODEX_SKILL_CONFIG_SECTIONS, ""));
41189
+ if (isDeepStrictEqual4(withoutNormalizedSections, expected))
41190
+ return;
40997
41191
  } catch {}
40998
- throw new Error("Codex skill path controls require ordinary [[skills.config]] TOML tables; preserve and convert inline or dotted config arrays before running skills hook install");
41192
+ throw codexPathConfigRefusal();
40999
41193
  }
41000
41194
  function disableCodexBundledSkills(text2) {
41001
41195
  const before = Bun.TOML.parse(text2);
@@ -41100,6 +41294,33 @@ function canonicalAgentPath(path, aliases) {
41100
41294
  const absolute = resolve14(path), binding = aliases.find((item) => absolute === item.alias || absolute.startsWith(item.alias + sep4));
41101
41295
  return binding ? join21(binding.target, relative3(binding.alias, absolute)) : absolute;
41102
41296
  }
41297
+ function disabledCodexSkillPaths(config, aliases) {
41298
+ const skills = config.skills;
41299
+ if (!skills || typeof skills !== "object" || Array.isArray(skills))
41300
+ return [];
41301
+ const rows = skills.config;
41302
+ if (!Array.isArray(rows))
41303
+ return [];
41304
+ if (rows.some((entry) => !entry || typeof entry !== "object" || Array.isArray(entry) || typeof entry.enabled !== "boolean" || entry.path !== undefined && (typeof entry.path !== "string" || !isAbsolute15(entry.path)) || entry.name !== undefined && typeof entry.name !== "string"))
41305
+ return [];
41306
+ if (rows.some((entry) => entry.name !== undefined))
41307
+ return [];
41308
+ const settings = new Map;
41309
+ for (const entry of rows) {
41310
+ if (typeof entry.path !== "string" || !isAbsolute15(entry.path))
41311
+ continue;
41312
+ let document2;
41313
+ try {
41314
+ document2 = realpathSync4(canonicalAgentPath(entry.path, aliases));
41315
+ } catch {
41316
+ continue;
41317
+ }
41318
+ if (!document2.endsWith(`${sep4}SKILL.md`))
41319
+ continue;
41320
+ settings.set(document2, [...settings.get(document2) ?? [], entry.enabled === false]);
41321
+ }
41322
+ return [...settings].filter(([, values]) => values.length === 1 && values[0] === true).map(([document2]) => dirname14(document2));
41323
+ }
41103
41324
  function recheckRootAliases(aliases) {
41104
41325
  for (const binding of aliases) {
41105
41326
  if (!["claude", "codex"].includes(binding.agent) || binding.alias !== join21(binding.home, `.${binding.agent}`))
@@ -41209,6 +41430,9 @@ function projectAncestorDirectories(projects) {
41209
41430
  function inventoryNativeSkills(home = homedir3(), options = {}) {
41210
41431
  if (options.reviewedCacheAlias !== undefined && (!options.includeVendor || !isAbsolute15(options.reviewedCacheAlias) || resolve14(options.reviewedCacheAlias) !== options.reviewedCacheAlias))
41211
41432
  throw new Error("A reviewed cache alias requires vendor inventory and an exact absolute path");
41433
+ if (options.disabledVendorPaths?.some((path) => !isAbsolute15(path) || resolve14(path) !== path))
41434
+ throw new Error("Disabled vendor paths must be exact absolute paths");
41435
+ const disabledVendorPaths = new Set(options.disabledVendorPaths ?? []);
41212
41436
  const aliases = rootAliases(home, options.allowRootAliases);
41213
41437
  const selectedAgents = options.agents ? new Set(options.agents) : undefined;
41214
41438
  const includesAgent = (agent) => !selectedAgents || selectedAgents.has(agent);
@@ -41230,7 +41454,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
41230
41454
  throw new Error("Native skill discovery metadata limit exceeded");
41231
41455
  }
41232
41456
  let reviewedCacheAliasFound = false;
41233
- function verifiedSiblingCacheAlias(path, parent) {
41457
+ function verifiedSiblingCacheAlias(agent, path, parent) {
41234
41458
  const link = readlinkSync3(path), target = resolve14(parent, link);
41235
41459
  if (dirname14(target) !== parent || (isAbsolute15(link) ? link !== target : dirname14(link) !== "."))
41236
41460
  return false;
@@ -41240,9 +41464,13 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
41240
41464
  if (!scan?.complete || scan.entries > maxAliasProofEntries)
41241
41465
  return false;
41242
41466
  if (scan.hasSkills) {
41467
+ const targetSkills = entries.filter((entry) => entry.agent === agent && entry.vendor && (entry.path === target || entry.path.startsWith(target + sep4)));
41468
+ if (path === options.reviewedCacheAlias && targetSkills.length > 0)
41469
+ reviewedCacheAliasFound = true;
41470
+ if (agent === "codex" && targetSkills.length > 0 && targetSkills.every((entry) => disabledVendorPaths.has(entry.path)))
41471
+ return true;
41243
41472
  if (path !== options.reviewedCacheAlias)
41244
41473
  return false;
41245
- reviewedCacheAliasFound = true;
41246
41474
  }
41247
41475
  return true;
41248
41476
  }
@@ -41301,7 +41529,7 @@ function inventoryNativeSkills(home = homedir3(), options = {}) {
41301
41529
  const child = join21(path, name);
41302
41530
  if (isVendor && lstatSync18(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
41303
41531
  const target = statSync5(child, { throwIfNoEntry: false });
41304
- if (target?.isFile() || pluginCache && target?.isDirectory() && verifiedSiblingCacheAlias(child, path)) {
41532
+ if (target?.isFile() || pluginCache && target?.isDirectory() && verifiedSiblingCacheAlias(agent, child, path)) {
41305
41533
  scan.entries++;
41306
41534
  continue;
41307
41535
  }
@@ -41441,7 +41669,7 @@ function configureHooks(config, agent, command, profileId, nativeReady) {
41441
41669
  }
41442
41670
  function disableCodexSkills(text2, skills, aliases, bridgePath) {
41443
41671
  const bundled = disableCodexBundledSkills(text2);
41444
- let result = bundled;
41672
+ let result = normalizeCodexInlinePathConfig(bundled);
41445
41673
  const bridgeSelector = (entry) => typeof entry.name === "string" && entry.name.trim() === CLI_BRIDGE_NAME || typeof entry.path === "string" && [resolve14(bridgePath), resolve14(join21(bridgePath, "SKILL.md"))].includes(canonicalAgentPath(entry.path, aliases));
41446
41674
  const previousConfig = Bun.TOML.parse(bundled).skills?.config;
41447
41675
  if (previousConfig !== undefined && (!Array.isArray(previousConfig) || previousConfig.some((entry) => !entry || typeof entry !== "object" || entry.path !== undefined && entry.name !== undefined)))
@@ -41509,7 +41737,8 @@ function planAgentIntegration(options) {
41509
41737
  }
41510
41738
  return resolveAgentDiscovery({ home, agent, reviewed: options.discoveryInputs, retainedReview, canonical: (path) => canonicalAgentPath(path, aliases) });
41511
41739
  });
41512
- const nativeSkills = inventoryNativeSkills(home, { includeVendor: true, guardHermes: options.agents.includes("hermes"), agents: options.agents, projectDir: options.projectDir, agentRoots: discoveries.flatMap((binding) => binding.roots.map((path) => ({ agent: binding.agent, path }))), allowRootAliases: options.allowRootAliases });
41740
+ const codexConfig = options.agents.includes("codex") ? Bun.TOML.parse(readOptional(canonicalAgentPath(join21(home, ".codex", "config.toml"), aliases)) ?? "") : {};
41741
+ const nativeSkills = inventoryNativeSkills(home, { includeVendor: true, guardHermes: options.agents.includes("hermes"), agents: options.agents, projectDir: options.projectDir, agentRoots: discoveries.flatMap((binding) => binding.roots.map((path) => ({ agent: binding.agent, path }))), allowRootAliases: options.allowRootAliases, reviewedCacheAlias: options.reviewedCacheAlias, disabledVendorPaths: disabledCodexSkillPaths(codexConfig, aliases) });
41513
41742
  const changes = [];
41514
41743
  for (const agent of [...new Set(options.agents)]) {
41515
41744
  if (!INTEGRATION_AGENTS.includes(agent))
@@ -42031,7 +42260,7 @@ function assertManagedAgentBridge(agent, options = {}) {
42031
42260
  } catch (error) {
42032
42261
  throw new Error(`NATIVE_SKILL_DRIFT: ${error.message}`);
42033
42262
  }
42034
- const inventory = inventoryNativeSkills(home, { includeVendor: true, guardHermes: agent === "hermes", agents: [agent], projectDirs: [...roots], agentRoots: discovery.roots.map((path) => ({ agent, path })), allowRootAliases: aliases.length > 0 });
42263
+ const inventory = inventoryNativeSkills(home, { includeVendor: true, guardHermes: agent === "hermes", agents: [agent], projectDirs: [...roots], agentRoots: discovery.roots.map((path) => ({ agent, path })), allowRootAliases: aliases.length > 0, disabledVendorPaths: agent === "codex" ? disabledCodexSkillPaths(codexConfig, aliases) : [] });
42035
42264
  const unexpected = inventory.filter((entry) => visible(entry) && !entry.bridge && !disabledVendorSkill(entry));
42036
42265
  if (unexpected.length) {
42037
42266
  const paths = unexpected.slice(0, 3).map((entry) => {
@@ -63971,9 +64200,9 @@ class PostgresSkillsStore {
63971
64200
  }
63972
64201
  backend = { kind: "postgres", durable: true, label: "postgres" };
63973
64202
  sql;
63974
- constructor(databaseUrl) {
64203
+ constructor(databaseUrl, connectionOptions = {}) {
63975
64204
  const bunWithSql = Bun;
63976
- this.sql = new bunWithSql.SQL(databaseUrl, { max: resolvePoolMax() });
64205
+ this.sql = new bunWithSql.SQL(databaseUrl, { max: resolvePoolMax(), ...connectionOptions });
63977
64206
  }
63978
64207
  async verifyConnectivity() {
63979
64208
  try {
@@ -64068,7 +64297,7 @@ class PostgresSkillsStore {
64068
64297
  }
64069
64298
  await tx`
64070
64299
  INSERT INTO skills_audit_events (org_id, user_id, api_key_id, action, target_type, target_id, metadata_json)
64071
- VALUES (${actor.orgId}, ${actor.userId}, ${actor.apiKeyId}, ${"api_key_scopes_added"}, ${"api_key"}, ${keyId}, ${JSON.stringify({ added: addScopes, scopes: parseJsonArray(updated[0].scopes_json) })}::jsonb)
64300
+ VALUES (${actor.orgId}, ${actor.userId}, ${actor.apiKeyId}, ${"api_key_scopes_added"}, ${"api_key"}, ${keyId}, ${JSON.stringify({ added: addScopes, scopes: parseJsonArray(updated[0].scopes_json) })}::text::jsonb)
64072
64301
  `;
64073
64302
  return { kind: "updated", scopes: parseJsonArray(updated[0].scopes_json) };
64074
64303
  });
@@ -64077,9 +64306,9 @@ class PostgresSkillsStore {
64077
64306
  const current = expectedScopes;
64078
64307
  const scopes = [...current, ...addScopes.filter((scope2) => !current.includes(scope2))];
64079
64308
  return tx`
64080
- UPDATE api_keys SET scopes_json = ${JSON.stringify(scopes)}::jsonb
64309
+ UPDATE api_keys SET scopes_json = ${JSON.stringify(scopes)}::text::jsonb
64081
64310
  WHERE id = ${keyId} AND org_id = ${orgId} AND revoked_at IS NULL
64082
- AND scopes_json = ${JSON.stringify(expectedScopes)}::jsonb
64311
+ AND scopes_json = ${JSON.stringify(expectedScopes)}::text::jsonb
64083
64312
  RETURNING scopes_json
64084
64313
  `;
64085
64314
  }
@@ -64139,7 +64368,7 @@ class PostgresSkillsStore {
64139
64368
  operator_task_arn: input.operatorTaskArn,
64140
64369
  target_manifest_digest: input.manifestDigest,
64141
64370
  station_id: input.stationId
64142
- })}::jsonb)
64371
+ })}::text::jsonb)
64143
64372
  `;
64144
64373
  return { kind: "updated", scopes };
64145
64374
  });
@@ -0,0 +1,26 @@
1
+ export interface EnrollmentInspectionInput {
2
+ keyId: string;
3
+ orgId: string;
4
+ enrollmentOperationId: string;
5
+ enrollmentManifestDigest: string;
6
+ }
7
+ export interface EnrollmentInspectionResult {
8
+ status: "inspected";
9
+ target: {
10
+ state: "found";
11
+ scopes: string[];
12
+ } | {
13
+ state: "absent" | "revoked" | "mismatched" | "ambiguous";
14
+ };
15
+ audit: {
16
+ state: "absent" | "matching" | "mismatched" | "ambiguous";
17
+ };
18
+ }
19
+ type InspectionCode = "INVALID_INSPECTION_INPUT" | "POSTGRES_REQUIRED" | "INVALID_INSPECTION_RESULT" | "INSPECTION_FAILED" | "INSPECTION_SCHEMA_UNAVAILABLE" | "INSPECTION_ACCESS_DENIED" | "INSPECTION_WRITE_REFUSED" | "INSPECTION_TIMEOUT" | "INSPECTION_CONNECTION_FAILED";
20
+ export declare class EnrollmentInspectionError extends Error {
21
+ readonly code: InspectionCode;
22
+ constructor(code: InspectionCode);
23
+ }
24
+ /** Inspect metadata only. Deliberately does not import or initialize the application store. */
25
+ export declare function inspectEnrollment(databaseUrl: string, input: EnrollmentInspectionInput): Promise<EnrollmentInspectionResult>;
26
+ export {};
@@ -1,2 +1,15 @@
1
1
  import { Command } from "commander";
2
+ import { type EnrollmentInspectionInput } from "./enrollment-inspection.js";
3
+ type InspectionManifest = EnrollmentInspectionInput & {
4
+ app: "skills";
5
+ operation: "inspect-enrollment";
6
+ manifestVersion: 1;
7
+ operationId: string;
8
+ stationId: string;
9
+ expiresAt: string;
10
+ manifestDigest: string;
11
+ };
12
+ /** Inspection has its own authorization; a failed enrollment manifest cannot authorize it. */
13
+ export declare function readInspectionManifest(path: string, receiptPath: string): InspectionManifest;
2
14
  export declare function registerMaintenance(parent: Command): void;
15
+ export {};
@@ -25,6 +25,9 @@ export interface StoreOptions {
25
25
  * - anything else -> throws, naming what is supported
26
26
  */
27
27
  export declare function createStore(options?: StoreOptions): Promise<SkillsProductStore>;
28
+ export type OperatorScopeMaintenanceStore = Required<Pick<SkillsProductStore, "inspectOperatorScopeTarget" | "enrollPublishScopeByOperator" | "close">>;
29
+ /** Open only the existing scope-maintenance surface; never initialize or backfill the application store. */
30
+ export declare function openOperatorScopeMaintenance(databaseUrl: string): OperatorScopeMaintenanceStore;
28
31
  export declare class MemorySkillsStore implements SkillsProductStore {
29
32
  readonly selectionStore: MemorySkillSelectionStore;
30
33
  readonly executionGrantStore: MemoryExecutionGrantStore;
@@ -102,7 +105,12 @@ export declare class PostgresSkillsStore implements SkillsProductStore {
102
105
  get executionGrantStore(): PostgresExecutionGrantStore;
103
106
  readonly backend: StoreBackendInfo;
104
107
  private sql;
105
- constructor(databaseUrl: string);
108
+ constructor(databaseUrl: string, connectionOptions?: {
109
+ max?: number;
110
+ connectionTimeout?: number;
111
+ idleTimeout?: number;
112
+ connection?: Record<string, string>;
113
+ });
106
114
  /**
107
115
  * Bun's SQL client connects lazily, so constructing this store proves nothing about
108
116
  * the database being there. Without an explicit probe, a wrong host or a down
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/skills",
3
- "version": "0.10.10",
3
+ "version": "0.10.13",
4
4
  "description": "Skills library for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {