@hasna/skills 0.7.3 → 0.8.1
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 +161 -19
- package/bin/index.js +5321 -4850
- package/bin/mcp.js +7841 -7538
- package/bin/migrate.js +22 -60
- package/bin/server.js +73576 -20339
- package/bin/worker.js +65159 -19251
- package/dist/admin-contract.js +8 -8
- package/dist/cli/commands/recurring.d.ts +2 -0
- package/dist/index.js +2617 -2747
- package/dist/lib/canonical-json.d.ts +8 -0
- package/dist/lib/cli-mcp-parity.d.ts +1 -1
- package/dist/lib/config.d.ts +3 -23
- package/dist/lib/installer.d.ts +1 -1
- package/dist/lib/mcp-contracts.d.ts +1 -1
- package/dist/lib/portable-skills.d.ts +1 -1
- package/dist/lib/recurring-customer.d.ts +29 -0
- package/dist/lib/recurring-recovery.d.ts +82 -0
- package/dist/lib/recurring-surface.d.ts +252 -0
- package/dist/lib/registry-data/index.d.ts +1 -0
- package/dist/lib/registry-types.d.ts +2 -1
- package/dist/lib/registry.d.ts +2 -12
- package/dist/lib/release-dependencies.d.ts +3 -0
- package/dist/lib/remote-client.d.ts +13 -0
- package/dist/lib/remote-customer-operations.d.ts +1 -0
- package/dist/lib/remote-invitations.d.ts +1 -1
- package/dist/lib/remote-recurring-contract.d.ts +165 -0
- package/dist/lib/remote-recurring.d.ts +95 -0
- package/dist/lib/skill-aliases.d.ts +2 -3
- package/dist/mcp/mcp-test-client.d.ts +2 -2
- package/dist/mcp/remote-recurring-tools.d.ts +2 -0
- package/dist/sdk/executor.d.ts +5 -5
- package/dist/sdk/index.d.ts +4 -0
- package/dist/sdk/index.js +114864 -46432
- package/dist/sdk/registry.d.ts +3 -3
- package/dist/server/config.d.ts +1 -2
- package/dist/server/handlers.d.ts +5 -2
- package/dist/server/registry.d.ts +6 -3
- package/dist/server/skills-api.d.ts +6 -38
- package/dist/storage.js +5 -42
- package/package.json +3 -2
- package/dist/lib/registry-data/business-marketing.d.ts +0 -2
- package/dist/lib/registry-data/communication.d.ts +0 -2
- package/dist/lib/registry-data/content-generation.d.ts +0 -2
- package/dist/lib/registry-data/data-analysis.d.ts +0 -2
- package/dist/lib/registry-data/design-branding.d.ts +0 -2
- package/dist/lib/registry-data/development-tools.d.ts +0 -2
- package/dist/lib/registry-data/education-learning.d.ts +0 -2
- package/dist/lib/registry-data/event-management.d.ts +0 -2
- package/dist/lib/registry-data/finance-compliance.d.ts +0 -2
- package/dist/lib/registry-data/health-wellness.d.ts +0 -2
- package/dist/lib/registry-data/media-processing.d.ts +0 -2
- package/dist/lib/registry-data/productivity-organization.d.ts +0 -2
- package/dist/lib/registry-data/project-management.d.ts +0 -2
- package/dist/lib/registry-data/research-writing.d.ts +0 -2
- package/dist/lib/registry-data/science-academic.d.ts +0 -2
- package/dist/lib/registry-data/travel-lifestyle.d.ts +0 -2
- package/dist/lib/registry-data/web-browser.d.ts +0 -2
- package/dist/server/seed-bundled.d.ts +0 -20
package/dist/sdk/registry.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Registry + version service seam.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Unscoped registry helpers are retained as empty compatibility exports. Private
|
|
5
|
+
* catalogs require an authenticated RemoteSkillsClient. The version service is the seam
|
|
6
6
|
* for skills_registry versioning — the `version` column a published record carries, and
|
|
7
7
|
* the contract sibling work (hasna.skill.v1, skill-hash) builds on.
|
|
8
8
|
*/
|
|
@@ -16,7 +16,7 @@ export interface RegistryService {
|
|
|
16
16
|
getSkillMd(slug: string): string | null;
|
|
17
17
|
isValidSlug(slug: string): boolean;
|
|
18
18
|
}
|
|
19
|
-
/**
|
|
19
|
+
/** @deprecated Always empty. Use RemoteSkillsClient with the account's credentials. */
|
|
20
20
|
export declare const bundledRegistry: RegistryService;
|
|
21
21
|
/** Resolves the effective version of a published skill record. */
|
|
22
22
|
export interface RegistryVersionService {
|
package/dist/server/config.d.ts
CHANGED
|
@@ -3,12 +3,11 @@ export interface SkillsServerConfig {
|
|
|
3
3
|
port: number;
|
|
4
4
|
databaseUrl?: string;
|
|
5
5
|
bootstrapApiKey?: string;
|
|
6
|
-
/** Publish the bundled corpus as versioned skills on boot (default on; set HASNA_SKILLS_SEED_BUNDLED_CORPUS=0 to skip). */
|
|
7
|
-
seedBundledCorpus: boolean;
|
|
8
6
|
artifactBucket?: string;
|
|
9
7
|
artifactPrefix: string;
|
|
10
8
|
/** Optional expiring run-output namespace; immutable bundles retain artifactPrefix. */
|
|
11
9
|
runArtifactPrefix?: string;
|
|
10
|
+
/** @deprecated Unversioned execution is retired; this flag cannot enable it. */
|
|
12
11
|
inlineWorker: boolean;
|
|
13
12
|
/**
|
|
14
13
|
* HMAC key for signing served skill bundles. When set, the bundle endpoint adds
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
import { ArtifactStorage } from "./artifact-storage.js";
|
|
1
|
+
import type { ArtifactStorage } from "./artifact-storage.js";
|
|
2
2
|
import type { ServerRunRecord, SkillsProductStore } from "./types.js";
|
|
3
|
-
export declare
|
|
3
|
+
export declare const LEGACY_EXECUTION_RETIRED = "LEGACY_EXECUTION_RETIRED";
|
|
4
|
+
export declare const LEGACY_EXECUTION_GUIDANCE = "Unversioned runs have been retired. Publish and select a versioned executable, then use skills run <name>@<version> --target cloud.";
|
|
5
|
+
/** Drain old unversioned records without executing embedded skill implementations. */
|
|
6
|
+
export declare function executeRun(store: SkillsProductStore, run: ServerRunRecord, _storage?: ArtifactStorage): Promise<ServerRunRecord>;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { SkillMeta } from "../lib/registry-types.js";
|
|
2
2
|
export declare function isValidSkillSlug(slug: string): boolean;
|
|
3
|
+
/** @deprecated No shared catalog exists. Use the authenticated RemoteSkillsClient. */
|
|
3
4
|
export declare function listServerSkills(): SkillMeta[];
|
|
4
|
-
|
|
5
|
-
export declare function
|
|
5
|
+
/** @deprecated Unscoped lookup cannot select an organization's private skill. */
|
|
6
|
+
export declare function getServerSkill(_slug: string): SkillMeta | null;
|
|
7
|
+
/** @deprecated Unscoped lookup never reads the server's filesystem. */
|
|
8
|
+
export declare function getServerSkillMd(_slug: string): string | null;
|
|
@@ -59,19 +59,12 @@ export declare function parseIfMatch(value: string | null): string | undefined;
|
|
|
59
59
|
* so an object whose digest another row still references survives.
|
|
60
60
|
*/
|
|
61
61
|
export declare function tombstoneStatus(store: SkillsProductStore, artifactStorage: ArtifactStorage, principal: ApiPrincipal, record: ServerSkillRecord): Promise<"live" | "purged" | Record<string, unknown>>;
|
|
62
|
-
/**
|
|
63
|
-
* Bundled corpus plus this org's published skills, published winning on a slug collision.
|
|
64
|
-
*
|
|
65
|
-
* Same rule as the CLI-side merge in src/lib/registry-merge.ts and for the same reason: an
|
|
66
|
-
* organization that published `deploy-notes` on their own instance meant to override the
|
|
67
|
-
* bundled `deploy-notes` there.
|
|
68
|
-
*/
|
|
62
|
+
/** List only records belonging to the authenticated organization. */
|
|
69
63
|
export declare function listMergedSkills(store: SkillsProductStore, principal: ApiPrincipal): Promise<Record<string, unknown>[]>;
|
|
70
64
|
/**
|
|
71
65
|
* What a read of one slug resolves to: the org's published row (live or tombstoned) or
|
|
72
|
-
* nothing.
|
|
73
|
-
*
|
|
74
|
-
* because the caller asked for the skill this instance serves under that slug.
|
|
66
|
+
* nothing. Tombstones retain their 410 response until expiry; no machine-local
|
|
67
|
+
* content can substitute for an absent or deleted organization record.
|
|
75
68
|
*/
|
|
76
69
|
export type SkillReadResolution = {
|
|
77
70
|
kind: "published";
|
|
@@ -83,41 +76,16 @@ export type SkillReadResolution = {
|
|
|
83
76
|
kind: "absent";
|
|
84
77
|
};
|
|
85
78
|
export declare function resolvePublishedSkill(store: SkillsProductStore, artifactStorage: ArtifactStorage, principal: ApiPrincipal, slug: string): Promise<SkillReadResolution>;
|
|
86
|
-
/**
|
|
87
|
-
* Distinct tags across the org's registry view: the org's published tags (the
|
|
88
|
-
* indexed store query over the skills_tags projection, in both backends) plus
|
|
89
|
-
* the bundled corpus's, which is a fixed in-process set. The route serves the
|
|
90
|
-
* same universe GET /api/v1/skills serves, so a client can take any tag this
|
|
91
|
-
* list returns and filter with it. Sorted, de-duplicated, and emptied of blank
|
|
92
|
-
* entries to match the client contract (non-empty tag names).
|
|
93
|
-
*/
|
|
79
|
+
/** Distinct, non-empty tags in the authenticated organization's published catalog. */
|
|
94
80
|
export declare function listOrgTags(store: SkillsProductStore, principal: ApiPrincipal): Promise<string[]>;
|
|
95
|
-
/**
|
|
96
|
-
* The merged registry view (bundled + published) filtered to skills carrying an
|
|
97
|
-
* exact tag. Same merge rules and payloads as listMergedSkills - the tag filter
|
|
98
|
-
* narrows what GET /api/v1/skills would have returned, it does not switch to a
|
|
99
|
-
* different universe. The published half comes from the indexed store query;
|
|
100
|
-
* only the static bundled corpus is filtered in-process, and a bundled skill
|
|
101
|
-
* whose slug a published row occupies is excluded so published-wins precedence
|
|
102
|
-
* holds for tag reads exactly as it does for the unfiltered view.
|
|
103
|
-
*/
|
|
81
|
+
/** The same organization catalog filtered through the store's indexed tag query. */
|
|
104
82
|
export declare function listMergedSkillsByTag(store: SkillsProductStore, principal: ApiPrincipal, tag: string): Promise<Record<string, unknown>[]>;
|
|
105
83
|
/**
|
|
106
84
|
* The minimal per-skill wire row the tag/sync summary routes serve: the client's
|
|
107
85
|
* RemoteSkillSummary contract ({ slug, name?, version?, updatedAt? }).
|
|
108
86
|
*/
|
|
109
87
|
export declare function skillSummary(skill: Record<string, unknown>): Record<string, unknown>;
|
|
110
|
-
/**
|
|
111
|
-
* The principal's pins filtered to slugs whose skill (bundled or published, in
|
|
112
|
-
* this org's merged view) carries the exact tag. A pin carries no tag of its
|
|
113
|
-
* own - the filter resolves each pinned slug against the registry view, the
|
|
114
|
-
* same way the rest of the surface treats a pin as a fact about a skill.
|
|
115
|
-
*
|
|
116
|
-
* Published pins come from the indexed store query (skills_tags projection);
|
|
117
|
-
* the bundled-corpus half is resolved in-process against the static corpus and
|
|
118
|
-
* excludes slugs a published row occupies, so every pinned slug resolves
|
|
119
|
-
* through exactly one path (published wins) and no pin can appear twice.
|
|
120
|
-
*/
|
|
88
|
+
/** Only published skills in this organization can contribute tags to its pins. */
|
|
121
89
|
export declare function listPinsByTag(store: SkillsProductStore, principal: ApiPrincipal, tag: string): Promise<Record<string, unknown>[]>;
|
|
122
90
|
export declare function getMergedSkill(store: SkillsProductStore, artifactStorage: ArtifactStorage, principal: ApiPrincipal, slug: string): Promise<Record<string, unknown> | null>;
|
|
123
91
|
/**
|
package/dist/storage.js
CHANGED
|
@@ -52,14 +52,14 @@ import {
|
|
|
52
52
|
existsSync as existsSync4,
|
|
53
53
|
mkdirSync as mkdirSync3,
|
|
54
54
|
readFileSync as readFileSync3,
|
|
55
|
-
readdirSync
|
|
56
|
-
statSync
|
|
55
|
+
readdirSync,
|
|
56
|
+
statSync,
|
|
57
57
|
writeFileSync as writeFileSync3
|
|
58
58
|
} from "fs";
|
|
59
59
|
import { dirname as dirname2, join as join4, normalize, relative, sep } from "path";
|
|
60
60
|
|
|
61
61
|
// src/lib/config.ts
|
|
62
|
-
import { existsSync as existsSync2, readFileSync, writeFileSync, mkdirSync
|
|
62
|
+
import { existsSync as existsSync2, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
63
63
|
import { join as join2, dirname } from "path";
|
|
64
64
|
|
|
65
65
|
// src/lib/retired-settings.ts
|
|
@@ -171,12 +171,6 @@ function exactDataRoot() {
|
|
|
171
171
|
}
|
|
172
172
|
return;
|
|
173
173
|
}
|
|
174
|
-
function hasExactOverride(env = process.env) {
|
|
175
|
-
return Boolean(env[DATA_DIR_ENV]?.trim()) || Boolean(env[HASNA_SKILLS_HOME_ENV]?.trim()) || Boolean(env[SKILLS_HOME_ENV]?.trim());
|
|
176
|
-
}
|
|
177
|
-
function hasOperatorOverride(env = process.env) {
|
|
178
|
-
return hasExactOverride(env) || Boolean(env.HASNA_DATA_HOME?.trim());
|
|
179
|
-
}
|
|
180
174
|
function getDataRoot() {
|
|
181
175
|
const exact = exactDataRoot();
|
|
182
176
|
if (exact)
|
|
@@ -210,24 +204,6 @@ function validKeys() {
|
|
|
210
204
|
function allowedValues(key) {
|
|
211
205
|
return ENUM_KEYS[key];
|
|
212
206
|
}
|
|
213
|
-
function mergeDirectoryContents(sourceDir, targetDir) {
|
|
214
|
-
if (!existsSync2(sourceDir))
|
|
215
|
-
return;
|
|
216
|
-
mkdirSync(targetDir, { recursive: true });
|
|
217
|
-
for (const entry of readdirSync(sourceDir)) {
|
|
218
|
-
const sourcePath = join2(sourceDir, entry);
|
|
219
|
-
const targetPath = join2(targetDir, entry);
|
|
220
|
-
try {
|
|
221
|
-
const sourceStat = statSync(sourcePath);
|
|
222
|
-
if (sourceStat.isDirectory()) {
|
|
223
|
-
mergeDirectoryContents(sourcePath, targetPath);
|
|
224
|
-
continue;
|
|
225
|
-
}
|
|
226
|
-
if (!existsSync2(targetPath))
|
|
227
|
-
copyFileSync(sourcePath, targetPath);
|
|
228
|
-
} catch {}
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
207
|
function normalizeConfigValue(key, value) {
|
|
232
208
|
if (typeof value !== "string")
|
|
233
209
|
return;
|
|
@@ -249,19 +225,6 @@ function getDataDir() {
|
|
|
249
225
|
try {
|
|
250
226
|
mkdirSync(root, { recursive: true });
|
|
251
227
|
} catch {}
|
|
252
|
-
if (hasOperatorOverride())
|
|
253
|
-
return root;
|
|
254
|
-
const home = effectiveHome();
|
|
255
|
-
const oldDir = join2(home, ".skills");
|
|
256
|
-
const oldConfigFile = join2(home, ".skillsrc");
|
|
257
|
-
try {
|
|
258
|
-
mergeDirectoryContents(oldDir, root);
|
|
259
|
-
} catch {}
|
|
260
|
-
if (existsSync2(oldConfigFile) && !existsSync2(join2(root, "config.json"))) {
|
|
261
|
-
try {
|
|
262
|
-
copyFileSync(oldConfigFile, join2(root, "config.json"));
|
|
263
|
-
} catch {}
|
|
264
|
-
}
|
|
265
228
|
return root;
|
|
266
229
|
}
|
|
267
230
|
function getDataDirReadOnly() {
|
|
@@ -994,9 +957,9 @@ function parsePositiveInteger(value) {
|
|
|
994
957
|
}
|
|
995
958
|
function walkFiles(dir) {
|
|
996
959
|
const files = [];
|
|
997
|
-
for (const entry of
|
|
960
|
+
for (const entry of readdirSync(dir)) {
|
|
998
961
|
const full = join4(dir, entry);
|
|
999
|
-
const stats =
|
|
962
|
+
const stats = statSync(full);
|
|
1000
963
|
if (stats.isDirectory())
|
|
1001
964
|
files.push(...walkFiles(full));
|
|
1002
965
|
else
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hasna/skills",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "Skills library for AI coding agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -85,7 +85,8 @@
|
|
|
85
85
|
"author": "Hasna",
|
|
86
86
|
"license": "Apache-2.0",
|
|
87
87
|
"devDependencies": {
|
|
88
|
-
"@hasna/contracts": "1.0
|
|
88
|
+
"@hasna/contracts": "1.1.0",
|
|
89
|
+
"@hasna/secrets": "0.4.2",
|
|
89
90
|
"@types/bun": "1.3.14",
|
|
90
91
|
"@types/node": "25.2.3",
|
|
91
92
|
"@types/react": "^18.2.0",
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { ArtifactStorage } from "./artifact-storage.js";
|
|
2
|
-
import type { ApiPrincipal, SkillsProductStore } from "./types.js";
|
|
3
|
-
export interface SeedBundledCorpusOptions {
|
|
4
|
-
store: SkillsProductStore;
|
|
5
|
-
artifactStorage: ArtifactStorage;
|
|
6
|
-
principal: ApiPrincipal;
|
|
7
|
-
/** Version recorded for every seeded skill. Defaults to the package version. */
|
|
8
|
-
version?: string;
|
|
9
|
-
log?: (line: string) => void;
|
|
10
|
-
}
|
|
11
|
-
export interface SeedBundledCorpusResult {
|
|
12
|
-
version: string;
|
|
13
|
-
seeded: string[];
|
|
14
|
-
skipped: string[];
|
|
15
|
-
failed: Array<{
|
|
16
|
-
slug: string;
|
|
17
|
-
error: string;
|
|
18
|
-
}>;
|
|
19
|
-
}
|
|
20
|
-
export declare function seedBundledCorpus(options: SeedBundledCorpusOptions): Promise<SeedBundledCorpusResult>;
|