@hasna/skills 0.5.11 → 0.6.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.
Files changed (51) hide show
  1. package/README.md +95 -53
  2. package/bin/index.js +17704 -30170
  3. package/bin/mcp.js +6856 -21003
  4. package/bin/migrate.js +108 -6
  5. package/bin/server.js +5827 -565
  6. package/bin/worker.js +489 -135
  7. package/dist/admin-contract.d.ts +13 -13
  8. package/dist/admin-contract.js +28 -47
  9. package/dist/cli/commands/agent-integration.d.ts +2 -0
  10. package/dist/cli/commands/context.d.ts +19 -0
  11. package/dist/cli/commands/install.d.ts +1 -0
  12. package/dist/cli/commands/profile-sync.d.ts +10 -0
  13. package/dist/cli/commands/profiles.d.ts +2 -0
  14. package/dist/cli/commands/runtime.d.ts +0 -3
  15. package/dist/cli/output.d.ts +2 -0
  16. package/dist/index.d.ts +5 -0
  17. package/dist/index.js +5406 -19111
  18. package/dist/lib/agent-integration.d.ts +74 -0
  19. package/dist/lib/cloud-executions.d.ts +39 -0
  20. package/dist/lib/managed-policy.d.ts +6 -0
  21. package/dist/lib/profile-admin.d.ts +4 -0
  22. package/dist/lib/profile-client.d.ts +19 -0
  23. package/dist/lib/read-access.d.ts +3 -23
  24. package/dist/lib/selected-document.d.ts +6 -0
  25. package/dist/lib/selected-run.d.ts +31 -0
  26. package/dist/lib/selection-cache.d.ts +40 -0
  27. package/dist/lib/selection-resolver.d.ts +75 -0
  28. package/dist/lib/skill-context.d.ts +43 -0
  29. package/dist/lib/skillinfo.d.ts +2 -0
  30. package/dist/sdk/execution/dispatchers/ecs.d.ts +8 -0
  31. package/dist/sdk/index.d.ts +2 -0
  32. package/dist/sdk/index.js +9911 -8305
  33. package/dist/server/app.d.ts +7 -1
  34. package/dist/server/artifact-storage.d.ts +7 -10
  35. package/dist/server/auth.d.ts +2 -0
  36. package/dist/server/config.d.ts +2 -0
  37. package/dist/server/profile-api.d.ts +3 -0
  38. package/dist/server/runtime-api.d.ts +31 -0
  39. package/dist/server/runtime-policy.d.ts +25 -0
  40. package/dist/server/runtime-store.d.ts +73 -0
  41. package/dist/server/runtime-worker.d.ts +19 -0
  42. package/dist/server/selection-store.d.ts +39 -0
  43. package/dist/server/sqlite-store.d.ts +2 -0
  44. package/dist/server/store.d.ts +3 -0
  45. package/dist/server/types.d.ts +3 -0
  46. package/dist/types/skill-selection.d.ts +41 -0
  47. package/migrations/postgres/0007_skill_profiles.sql +19 -0
  48. package/migrations/postgres/0008_skill_runtime.sql +14 -0
  49. package/migrations/sqlite/0007_skill_profiles.sql +19 -0
  50. package/migrations/sqlite/0008_skill_runtime.sql +14 -0
  51. package/package.json +1 -1
@@ -0,0 +1,74 @@
1
+ export type IntegrationAgent = "claude" | "codex";
2
+ export type ContextHookEvent = "UserPromptSubmit" | "SessionStart" | "SubagentStart";
3
+ export interface AgentRootAlias {
4
+ agent: IntegrationAgent;
5
+ home: string;
6
+ alias: string;
7
+ target: string;
8
+ link: string;
9
+ aliasIdentity: string;
10
+ targetIdentity: string;
11
+ }
12
+ export interface NativeSkillEntry {
13
+ agent: string;
14
+ path: string;
15
+ hash: string;
16
+ managed: boolean;
17
+ vendor: boolean;
18
+ rootAlias?: AgentRootAlias;
19
+ }
20
+ export interface AgentConfigChange {
21
+ path: string;
22
+ before: string | null;
23
+ after: string;
24
+ }
25
+ export interface AgentIntegrationPlan {
26
+ dataDir: string;
27
+ profileId: string;
28
+ changes: AgentConfigChange[];
29
+ nativeSkills: NativeSkillEntry[];
30
+ rootAliases?: AgentRootAlias[];
31
+ }
32
+ export declare function inventoryNativeSkills(home?: string, options?: {
33
+ includeVendor?: boolean;
34
+ projectDir?: string;
35
+ allowRootAliases?: boolean;
36
+ }): NativeSkillEntry[];
37
+ /** Planning is read-only; credentials and unrelated settings never appear in CLI output. */
38
+ export declare function planAgentIntegration(options: {
39
+ home?: string;
40
+ dataDir?: string;
41
+ agents: IntegrationAgent[];
42
+ command?: string;
43
+ profileId?: string;
44
+ includeVendor?: boolean;
45
+ projectDir?: string;
46
+ allowRootAliases?: boolean;
47
+ }): AgentIntegrationPlan;
48
+ export declare function applyAgentIntegration(plan: AgentIntegrationPlan): {
49
+ changed: string[];
50
+ backups: string[];
51
+ rootAliases?: AgentRootAlias[];
52
+ };
53
+ export declare function archiveNativeSkills(inventory: NativeSkillEntry[], options: {
54
+ dataDir?: string;
55
+ includeUnmanaged?: boolean;
56
+ allowRootAliases?: boolean;
57
+ }): {
58
+ entries: Array<{
59
+ source: string;
60
+ archive: string;
61
+ hash: string;
62
+ }>;
63
+ rootAliases?: AgentRootAlias[];
64
+ };
65
+ export declare function hookContextOutput(event: string, result: {
66
+ context: string;
67
+ receipt?: unknown;
68
+ omitted?: Array<{
69
+ slug: string;
70
+ version: string;
71
+ loadCommand: string;
72
+ }>;
73
+ }): Record<string, unknown>;
74
+ export declare function assertNativeExportAllowed(dataDir?: string): void;
@@ -0,0 +1,39 @@
1
+ export interface CloudExecution {
2
+ contractVersion: 1;
3
+ id: string;
4
+ target: "cloud";
5
+ skill: string;
6
+ version: string;
7
+ bundleDigest: string;
8
+ inputDigest: string;
9
+ runtimeImageDigest: string;
10
+ status: "admitted" | "leased" | "running" | "succeeded" | "failed" | "cancelled";
11
+ exitCode?: number;
12
+ artifacts: {
13
+ name: string;
14
+ contentType: string;
15
+ sha256: string;
16
+ byteSize: number;
17
+ }[];
18
+ }
19
+ export declare class CloudExecutionClient {
20
+ private apiOrigin;
21
+ private apiKey;
22
+ constructor(apiOrigin: string, apiKey: string);
23
+ static configured(): Promise<CloudExecutionClient>;
24
+ private request;
25
+ submit(slug: string, version: string, input: unknown, key: string, selection?: {
26
+ bundleDigest: string;
27
+ workspaceId?: string;
28
+ authority?: string;
29
+ }): Promise<CloudExecution>;
30
+ get(id: string): Promise<CloudExecution>;
31
+ logs(id: string): Promise<unknown>;
32
+ artifacts(id: string): Promise<CloudExecution["artifacts"]>;
33
+ download(id: string, name: string): Promise<Uint8Array>;
34
+ cancel(id: string): Promise<CloudExecution>;
35
+ wait(id: string, options?: {
36
+ timeoutMs?: number;
37
+ intervalMs?: number;
38
+ }): Promise<CloudExecution>;
39
+ }
@@ -0,0 +1,6 @@
1
+ /** Lightweight, write-free policy check; importing agent integration would create an installer cycle. */
2
+ export declare function readManagedSkillPolicy(dataDir?: string): {
3
+ loading?: string;
4
+ profileId?: string;
5
+ } | null;
6
+ export declare function requiresCliSkillLoading(dataDir?: string): boolean;
@@ -0,0 +1,4 @@
1
+ import type { SkillProfile, SkillSelection, StationSkillState } from "../types/skill-selection.js";
2
+ export declare function readSkillProfile(profileId: string): Promise<SkillProfile>;
3
+ export declare function saveSkillProfile(profileId: string, selections: SkillSelection[], revision?: string): Promise<SkillProfile>;
4
+ export declare function readStationSkillState(stationId: string): Promise<StationSkillState>;
@@ -0,0 +1,19 @@
1
+ import type { ResolvedSkillProfile, StationSkillState, StationSkillStateInput } from "../types/skill-selection.js";
2
+ export interface ProfileClient {
3
+ readonly authority: string;
4
+ resolveProfile(id: string): Promise<ResolvedSkillProfile>;
5
+ recordStation(id: string, state: StationSkillStateInput): Promise<StationSkillState>;
6
+ getBundle(slug: string, version: string): Promise<Response | null>;
7
+ }
8
+ export declare class HttpProfileClient implements ProfileClient {
9
+ private key;
10
+ readonly authority: string;
11
+ private origin;
12
+ constructor(key: string, origin: string);
13
+ private request;
14
+ private read;
15
+ resolveProfile(id: string): Promise<ResolvedSkillProfile>;
16
+ recordStation(id: string, input: StationSkillStateInput): Promise<StationSkillState>;
17
+ getBundle(slug: string, version: string): Promise<Response | null>;
18
+ }
19
+ export declare function createProfileClient(): Promise<ProfileClient>;
@@ -52,29 +52,9 @@ export declare function requireSkillsReadAccess(env?: Env, options?: SkillsFleet
52
52
  * The registry a browsing surface should show — the CLI's `list` / `search` /
53
53
  * `categories` / `tags` and the MCP discovery tools, from ONE implementation.
54
54
  *
55
- * The default read path is folder UNION cloud: whenever the install is pointed
56
- * at a hosted instance (a resolved credential, and HASNA_SKILLS_API_URL for your
57
- * own instance) the authenticated remote registry joins the local listing even
58
- * without `--remote`. The explicit local opt-in keeps today's exact local
59
- * output; an unconfigured or auth-missing install is a refusal, thrown from the
60
- * shared ladder (fail-closed R1 — see mergeRemoteRegistry()).
61
- *
62
- * `--remote` used to REPLACE the local registry: `skills list --remote` returned exactly
63
- * what the instance served and nothing else, so the bundled corpus and every skill the
64
- * operator had written locally disappeared from the listing the moment they pointed the
65
- * CLI at their own server. It now MERGES, under the precedence documented in
66
- * src/lib/registry-merge.ts: custom > extension > local > remote > official, "whichever
67
- * copy this machine would actually use wins the listing".
68
- *
69
- * The profile (`all` vs the curated basic set) applies to the local half only. The
70
- * instance's skills are never filtered by it: the basic profile is a hand-written list of
71
- * ten bundled names, so applying it to remote entries would drop every published skill
72
- * from `skills list --remote` - the same disappearance this change exists to fix.
73
- *
74
- * A remote failure is still fatal. An explicit `--remote` request (and a configured,
75
- * authenticated default read) that fails surfaces a clear error, and silently returning
76
- * the local half of a merge the user asked to include the remote half in would report
77
- * success for a listing that is missing entries.
55
+ * A configured API is authoritative. Drafts and extension folders cannot shadow
56
+ * published metadata. Local authoring discovery requires the explicit local opt-in;
57
+ * authentication and network failures never fall back to local content.
78
58
  */
79
59
  export declare function getBrowseRegistry(options?: {
80
60
  all?: boolean;
@@ -0,0 +1,6 @@
1
+ /** Documentation comes only from the already verified selected bundle. */
2
+ import type { SkillBundleEntry } from "./skill-bundle.js";
3
+ export declare function readSelectedDocument(entries: SkillBundleEntry[], file?: string): {
4
+ file: string;
5
+ content: string;
6
+ };
@@ -0,0 +1,31 @@
1
+ import type { ResolvedSkillSelection } from "../types/skill-selection.js";
2
+ import type { SkillBundleEntry } from "./skill-bundle.js";
3
+ import { type SelectionResolverOptions } from "./selection-resolver.js";
4
+ export interface ResolvedSelectedRun {
5
+ selection: ResolvedSkillSelection;
6
+ kind: "instruction" | "executable";
7
+ entries: SkillBundleEntry[];
8
+ manifest: Record<string, any>;
9
+ packageJson: Record<string, any>;
10
+ cacheDir: string;
11
+ }
12
+ export declare function resolveSelectedRun(spec: string, profileId: string, options?: SelectionResolverOptions): Promise<ResolvedSelectedRun>;
13
+ export interface SelectedLocalRunOptions {
14
+ args?: string[];
15
+ input?: unknown;
16
+ cwd?: string;
17
+ timeoutMs?: number;
18
+ /** Only explicitly supplied environment values are available to declared secret references. */
19
+ env?: Record<string, string>;
20
+ }
21
+ export declare function executeSelectedLocal(selected: ResolvedSelectedRun, options?: SelectedLocalRunOptions): Promise<{
22
+ exitCode: number;
23
+ stdout: string;
24
+ stderr: string;
25
+ error?: string;
26
+ selection: ResolvedSkillSelection;
27
+ target: "local";
28
+ runtime: any;
29
+ inputDigest: string;
30
+ runDirectory: string;
31
+ }>;
@@ -0,0 +1,40 @@
1
+ import { type SkillBundleEntry } from "./skill-bundle.js";
2
+ import type { ResolvedSkillProfile, ResolvedSkillSelection } from "../types/skill-selection.js";
3
+ export declare class SkillSelectionError extends Error {
4
+ readonly code: string;
5
+ constructor(code: string, message: string);
6
+ }
7
+ export interface SelectionCacheOptions {
8
+ cacheDir?: string;
9
+ now?: () => number;
10
+ }
11
+ export interface CachedSelectionProfile {
12
+ schemaVersion: 1;
13
+ verifiedAt: string;
14
+ profile: ResolvedSkillProfile;
15
+ }
16
+ export interface SkillSessionReceipt extends CachedSelectionProfile {
17
+ sessionId: string;
18
+ loaded: string[];
19
+ }
20
+ export declare const MAX_CACHED_PROFILE_AGE_MS: number;
21
+ export declare const SELECTION_LOCK_FILE = "selection.lock.json";
22
+ export declare function selectionCacheRoot(options?: SelectionCacheOptions): string;
23
+ export declare function selectionKey(selection: ResolvedSkillSelection): string;
24
+ export declare function validateSelection(selection: ResolvedSkillSelection): void;
25
+ export declare function validateResolvedProfile(profile: ResolvedSkillProfile, authority?: string): void;
26
+ export declare function selectionBundlePath(selection: ResolvedSkillSelection, options?: SelectionCacheOptions): string;
27
+ export declare function writeSelectionJson(path: string, value: unknown): void;
28
+ export declare function readSelectionJson<T>(path: string): T | null;
29
+ export declare function readCachedSelection(selection: ResolvedSkillSelection, options?: SelectionCacheOptions): Promise<SkillBundleEntry[] | null>;
30
+ export declare function cacheSelectionBundle(selection: ResolvedSkillSelection, response: Response | null, options?: SelectionCacheOptions): Promise<SkillBundleEntry[]>;
31
+ export declare function activateSelectionProfile(profile: ResolvedSkillProfile, options?: SelectionCacheOptions): CachedSelectionProfile;
32
+ export declare function readSelectionProfile(profileId: string, options?: SelectionCacheOptions): CachedSelectionProfile | null;
33
+ export declare function validateSelectionReceipt(receipt: CachedSelectionProfile): void;
34
+ export declare function assertFreshCachedProfile(receipt: CachedSelectionProfile, options?: SelectionCacheOptions & {
35
+ maxAgeMs?: number;
36
+ }): void;
37
+ export declare function projectSelectionLockPath(projectDir: string): string;
38
+ export declare function readProjectSelection(projectDir: string): CachedSelectionProfile | null;
39
+ export declare function sessionReceiptPath(sessionId: string, options?: SelectionCacheOptions): string;
40
+ export declare function readSkillSession(sessionId: string, options?: SelectionCacheOptions): SkillSessionReceipt | null;
@@ -0,0 +1,75 @@
1
+ /** One resolution path for API-selected content. Local drafts cannot shadow a published selection. */
2
+ import { type ProfileClient } from "./profile-client.js";
3
+ import type { ResolvedSkillProfile, ResolvedSkillSelection } from "../types/skill-selection.js";
4
+ import type { SkillBundleEntry } from "./skill-bundle.js";
5
+ import { type CachedSelectionProfile, type SelectionCacheOptions, type SkillSessionReceipt } from "./selection-cache.js";
6
+ export interface SelectionResolverOptions extends SelectionCacheOptions {
7
+ client?: ProfileClient;
8
+ cached?: boolean;
9
+ /** Explicit cached authority binding, checked even when no credential is read. */
10
+ authority?: string;
11
+ workspaceId?: string;
12
+ maxAgeMs?: number;
13
+ projectDir?: string;
14
+ sessionId?: string;
15
+ /** A newly spawned subagent inherits the parent's pinned snapshot, never its dedup state. */
16
+ parentSessionId?: string;
17
+ }
18
+ export interface SyncSelectionProfileOptions extends SelectionCacheOptions {
19
+ client?: ProfileClient;
20
+ projectDir?: string;
21
+ stationId?: string;
22
+ check?: boolean;
23
+ }
24
+ export declare function syncSelectionProfile(profileId: string, options?: SyncSelectionProfileOptions): Promise<{
25
+ profile: ResolvedSkillProfile;
26
+ receipt: CachedSelectionProfile | null;
27
+ changed: boolean;
28
+ downloaded: number;
29
+ stationReported: boolean;
30
+ }>;
31
+ export interface ResolvedSelectionContext {
32
+ receipt: CachedSelectionProfile;
33
+ session: SkillSessionReceipt | null;
34
+ inheritedLoaded?: string[];
35
+ client?: ProfileClient;
36
+ }
37
+ export declare function resolveSelectionContext(profileId: string, options?: SelectionResolverOptions): Promise<ResolvedSelectionContext>;
38
+ export declare function readSelectedEntries(selection: ResolvedSkillSelection, context: ResolvedSelectionContext, options?: SelectionResolverOptions): Promise<SkillBundleEntry[]>;
39
+ export declare function exactProfileSelection(spec: string, profile: ResolvedSkillProfile): ResolvedSkillSelection;
40
+ export declare function loadSelectedSkill(spec: string, profileId: string, options?: SelectionResolverOptions & {
41
+ file?: string;
42
+ }): Promise<{
43
+ content: string;
44
+ selection: ResolvedSkillSelection;
45
+ receipt: {
46
+ file: string;
47
+ source: string;
48
+ verifiedAt: string;
49
+ authority: string;
50
+ workspaceId: string;
51
+ profileRevision: string;
52
+ slug: string;
53
+ version: string;
54
+ bundleDigest: string;
55
+ triggers?: {
56
+ keywords?: string[];
57
+ paths?: string[];
58
+ always?: boolean;
59
+ };
60
+ };
61
+ }>;
62
+ /** Pin the resolved profile metadata without copying a definition into the project. */
63
+ export declare function pinSelectedSkillVersion(spec: string, profileId: string, options: SelectionResolverOptions & {
64
+ projectDir: string;
65
+ }): Promise<{
66
+ selection: ResolvedSkillSelection;
67
+ path: string;
68
+ }>;
69
+ export declare function selectedSkillRequirements(spec: string, profileId: string, options?: SelectionResolverOptions): Promise<{
70
+ selection: ResolvedSkillSelection;
71
+ envVars: string[];
72
+ systemDeps: string[];
73
+ cliCommand: string | null;
74
+ dependencies: Record<string, string>;
75
+ }>;
@@ -0,0 +1,43 @@
1
+ import type { ResolvedSkillSelection } from "../types/skill-selection.js";
2
+ import { type SelectionResolverOptions } from "./selection-resolver.js";
3
+ export interface SkillContextInput {
4
+ prompt?: string;
5
+ cwd?: string;
6
+ sessionId?: string;
7
+ profileId?: string;
8
+ restore?: boolean;
9
+ agentId?: string;
10
+ skills?: string[];
11
+ paths?: string[];
12
+ }
13
+ export interface SkillContextOptions extends SelectionResolverOptions {
14
+ maxChars?: number;
15
+ maxSkills?: number;
16
+ }
17
+ export interface ContextSelectionReceipt extends ResolvedSkillSelection {
18
+ reason: string;
19
+ }
20
+ export interface SkillContextResult {
21
+ context: string;
22
+ selections: ContextSelectionReceipt[];
23
+ omitted: Array<{
24
+ slug: string;
25
+ version: string;
26
+ reason: string;
27
+ loadCommand: string;
28
+ }>;
29
+ receipt: {
30
+ schemaVersion: 1;
31
+ id: string;
32
+ profileId: string;
33
+ profileRevision: string;
34
+ authority: string;
35
+ workspaceId: string;
36
+ source: "api" | "verified-cache";
37
+ sessionId?: string;
38
+ restored: boolean;
39
+ chars: number;
40
+ selections: ContextSelectionReceipt[];
41
+ };
42
+ }
43
+ export declare function buildSkillContext(input: SkillContextInput, options?: SkillContextOptions): Promise<SkillContextResult>;
@@ -25,6 +25,8 @@ export declare function getSkillBestDoc(name: string): string | null;
25
25
  * Extract requirements from a skill's source files
26
26
  */
27
27
  export declare function getSkillRequirements(name: string): SkillRequirements | null;
28
+ /** Shared parser for verified bundle content and explicit local authoring files. */
29
+ export declare function getSkillRequirementsFromContent(name: string, texts: string[], dependencies?: Record<string, string>, meta?: SkillMeta): SkillRequirements;
28
30
  export interface SkillDependencyStatus {
29
31
  name: string;
30
32
  version: string;
@@ -82,6 +82,13 @@ export interface EcsDispatcherOptions {
82
82
  /** Claim identity; defaults to "dispatcher". */
83
83
  workerId?: string;
84
84
  now?: () => Date;
85
+ /** Trusted per-attempt supervisor transport. Must be deterministic for the frozen
86
+ * admission: a replay keeps the identical ECS clientToken and request. Never
87
+ * inherited by the skill process. */
88
+ supervisorEnvironment?: (admission: FrozenAdmission, attempt: AttemptRecord) => {
89
+ name: string;
90
+ value: string;
91
+ }[];
85
92
  }
86
93
  export type LaunchOutcome = {
87
94
  kind: "launched";
@@ -128,6 +135,7 @@ export declare class EcsDispatcher implements Dispatcher {
128
135
  private readonly receipts;
129
136
  private readonly workerId;
130
137
  private readonly now;
138
+ private readonly supervisorEnvironment;
131
139
  constructor(config: EcsDispatcherConfig, client: EcsRunTaskClient, options: EcsDispatcherOptions);
132
140
  /** sdk Dispatcher surface: submit an ADMITTED run (execution domain) to the launch machinery. */
133
141
  submit(run: FrozenAdmission): Promise<DispatchResult>;
@@ -15,6 +15,8 @@
15
15
  * — the shared @hasna/contracts ladder — instead of reading an environment
16
16
  * variable of its own. See lib/fleet-credentials.ts.
17
17
  */
18
+ export { HttpProfileClient, createProfileClient, type ProfileClient } from "../lib/profile-client.js";
19
+ export type { SkillSelection, SkillProfile, ResolvedSkillSelection, ResolvedSkillProfile, StationSkillStateInput, StationSkillState } from "../types/skill-selection.js";
18
20
  export { MissingSkillsFleetError, SkillsFleetCredentialError, SKILLS_API_KEY_ENV, SKILLS_API_URL_ENV, SKILLS_APP, SKILLS_LOCAL_OPT_IN_ENV_KEYS, configuredSkillsApiUrl, isSkillsLocalOptIn, noticeLocalSkillsMode, normalizeSkillsApiOrigin, requireSkillsApiOrigin, requireSkillsFleet, resolveSkillsApiOrigin, resolveSkillsFleet, selectsSkillsLocalMode, skillsCredentialFilePath, skillsCredentialFiles, skillsCredentialOrReason, type HostedSkillsFleet, type LocalSkillsFleet, type SkillsFleet, type SkillsFleetErrorCode, type SkillsFleetOptions, } from "../lib/fleet-credentials.js";
19
21
  export * from "./server.js";
20
22
  export * from "./registry.js";