@hasna/skills 0.1.72 → 0.2.0

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.
@@ -17,6 +17,15 @@
17
17
  * Nothing moves on disk in this phase — the package just resolves the new
18
18
  * paths.
19
19
  */
20
+ export type PathKind = "config" | "data" | "state" | "cache";
21
+ export interface PathsResolverOptions {
22
+ app: string;
23
+ internal?: boolean;
24
+ platform?: string;
25
+ home?: string;
26
+ env?: Record<string, string | undefined>;
27
+ }
28
+ export declare function dataDir(options: PathsResolverOptions): string;
20
29
  /** Env var that relocates the skills data directory (the shipped override). */
21
30
  export declare const DATA_DIR_ENV = "HASNA_SKILLS_DIR";
22
31
  /** Wave-convention exact-app home aliases, honoured after HASNA_SKILLS_DIR. */
@@ -41,8 +50,15 @@ export declare function legacyDataRoot(): string;
41
50
  * Support/Hasna/skills` on macOS. The home override mirrors the pre-existing
42
51
  * `$HOME`-first resolution so the resolver follows the same home the legacy
43
52
  * path does.
53
+ *
54
+ * `env` is forwarded to the resolver: an injected env (e.g. `{}` for a
55
+ * staged home mirror) suppresses the process-level `HASNA_*_HOME` overrides,
56
+ * which describe THIS machine's live store and must not relocate a mirror.
57
+ * `@hasna/paths` applies env overrides before the injected home, so without
58
+ * this the resolver would ignore the mirror home whenever `HASNA_DATA_HOME`
59
+ * is set.
44
60
  */
45
- export declare function resolverDataRoot(home?: string): string;
61
+ export declare function resolverDataRoot(home?: string, env?: Record<string, string | undefined>): string;
46
62
  /**
47
63
  * Whether the resolver (XDG) data root should be adopted as the effective
48
64
  * data root. The resolver root is adopted only when the operator has set
@@ -81,5 +97,15 @@ export declare function getDataRoot(): string;
81
97
  * The skills app data root for an explicit home root, mirroring getDataRoot()
82
98
  * with the home injected. Used by the sync-home snapshot mapping to enumerate
83
99
  * the skills corpus under a staged home mirror (`homesRoot`) or the real home.
100
+ *
101
+ * Process-level overrides (`HASNA_SKILLS_DIR` / `HASNA_SKILLS_HOME` /
102
+ * `SKILLS_HOME`, and the data-kind `HASNA_DATA_HOME`) describe THIS machine's
103
+ * live store. They apply only when the requested home IS the process's own
104
+ * effective home; a staged mirror (a different home, e.g. an rsync'd
105
+ * remote-station `homesRoot`) must resolve its own layout — the mirror's XDG
106
+ * data root once the mirror itself carries a migrated store there, else the
107
+ * mirror's legacy `~/.hasna/skills` — never the local process's live data
108
+ * root. Snapshotting a staged home with the local `HASNA_DATA_HOME` set would
109
+ * otherwise read live local data instead of the supplied mirror.
84
110
  */
85
111
  export declare function skillsDataRootForHome(home: string): string;
@@ -20,3 +20,9 @@ export interface FeedbackResult {
20
20
  */
21
21
  export declare function getFeedbackDbPath(): string;
22
22
  export declare function saveFeedback(input: FeedbackInput): FeedbackResult;
23
+ /**
24
+ * True when this install is pointed at a Skills instance: the env var, its HASNA_-prefixed
25
+ * alias, or the config file written by `skills setup --api-url` / `skills login`. The check
26
+ * never throws - a broken config file means local mode, not a crash in `skills feedback`.
27
+ */
28
+ export declare function isApiMode(env?: Record<string, string | undefined>): boolean;
@@ -16,6 +16,8 @@ export interface InstallResult {
16
16
  path?: string;
17
17
  mode?: InstallMode;
18
18
  source?: InstallSource;
19
+ /** Exact published version when the caller asked for name@version (hasna/apps#1630). */
20
+ version?: string;
19
21
  }
20
22
  export interface InstallOptions {
21
23
  targetDir?: string;
@@ -25,7 +25,15 @@ export interface SkillPullClient {
25
25
  * `Response` is the natural transport type here: verification reads the
26
26
  * X-Skill-Bundle-Sha256 / X-Skill-Bundle-Signature headers off it.
27
27
  */
28
- getBundle(slug: string): Promise<Response | null>;
28
+ getBundle(slug: string, version?: string): Promise<Response | null>;
29
+ /**
30
+ * The registry's record of one published version (hasna/apps#1630), or null. Optional:
31
+ * an exact-version pull proves the received bytes against this digest; a client that
32
+ * cannot answer it falls back to the bundle's own digest header.
33
+ */
34
+ getSkillVersion?(slug: string, version: string): Promise<{
35
+ bundleSha256?: string;
36
+ } | null>;
29
37
  }
30
38
  export interface PullSkillsOptions extends PortableSkillOptions {
31
39
  /** Explicit skill names to pull. Ignored when `all` is set. */
@@ -136,3 +144,12 @@ export declare function writePullMarker(dir: string, record: {
136
144
  revisionId?: string;
137
145
  source?: "pull" | "sync";
138
146
  }): void;
147
+ /**
148
+ * Split `name@version` into its parts. A name without `@` pulls the current revision; an
149
+ * empty version (`name@`) is an error the caller reports. Scoped-looking names are not a
150
+ * concern here: skill slugs never start with `@`.
151
+ */
152
+ export declare function splitNameVersion(raw: string): {
153
+ name: string;
154
+ version?: string;
155
+ };
@@ -22,6 +22,16 @@ export declare class RemoteRequestError extends Error {
22
22
  * (`{ slug, pinnedAt, metadata }`). `pinnedAt`/`metadata` are server-reported
23
23
  * and may be absent.
24
24
  */
25
+ export interface RemoteSkillVersion {
26
+ slug: string;
27
+ version: string;
28
+ bundleSha256: string;
29
+ bundleByteSize: number;
30
+ storageKind?: string;
31
+ manifest?: Record<string, unknown>;
32
+ createdAt: string;
33
+ current?: boolean;
34
+ }
25
35
  export interface RemotePin {
26
36
  slug: string;
27
37
  pinnedAt?: string;
@@ -109,8 +119,12 @@ export declare class RemoteSkillsClient {
109
119
  * read the X-Skill-Bundle-Sha256 / X-Skill-Bundle-Signature headers, or null when the
110
120
  * instance serves no bundle for this skill (the metadata-only fallback path).
111
121
  */
112
- getBundle(slug: string): Promise<Response | null>;
122
+ getBundle(slug: string, version?: string): Promise<Response | null>;
113
123
  /** List the pins the instance holds for this principal. */
124
+ /** Every published version of a slug, newest first (hasna/apps#1630). */
125
+ listSkillVersions(slug: string): Promise<RemoteSkillVersion[]>;
126
+ /** One version's manifest, or null when the slug@version was never published. */
127
+ getSkillVersion(slug: string, version: string): Promise<RemoteSkillVersion | null>;
114
128
  listPins(): Promise<RemotePin[]>;
115
129
  /**
116
130
  * Pin a skill on the instance (upsert — pinning again refreshes it). The
@@ -0,0 +1,11 @@
1
+ /**
2
+ * What a skill version string may look like (hasna/apps#1630).
3
+ *
4
+ * The version becomes a path segment in the version-addressed object key and in the
5
+ * `/versions/:version` routes, so it is a closed alphabet rather than "whatever the
6
+ * publisher sent": no separators, no dot-only names, bounded length. Semver fits; so do
7
+ * date stamps and package-style prereleases.
8
+ */
9
+ export declare const SKILL_VERSION_PATTERN: RegExp;
10
+ export declare function isValidSkillVersion(value: unknown): boolean;
11
+ export declare const SKILL_VERSION_RULE = "1-128 characters: letters, digits, '.', '_', '+', '-'; must start with a letter or digit; no '..'";