@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.
Files changed (58) hide show
  1. package/README.md +161 -19
  2. package/bin/index.js +5321 -4850
  3. package/bin/mcp.js +7841 -7538
  4. package/bin/migrate.js +22 -60
  5. package/bin/server.js +73576 -20339
  6. package/bin/worker.js +65159 -19251
  7. package/dist/admin-contract.js +8 -8
  8. package/dist/cli/commands/recurring.d.ts +2 -0
  9. package/dist/index.js +2617 -2747
  10. package/dist/lib/canonical-json.d.ts +8 -0
  11. package/dist/lib/cli-mcp-parity.d.ts +1 -1
  12. package/dist/lib/config.d.ts +3 -23
  13. package/dist/lib/installer.d.ts +1 -1
  14. package/dist/lib/mcp-contracts.d.ts +1 -1
  15. package/dist/lib/portable-skills.d.ts +1 -1
  16. package/dist/lib/recurring-customer.d.ts +29 -0
  17. package/dist/lib/recurring-recovery.d.ts +82 -0
  18. package/dist/lib/recurring-surface.d.ts +252 -0
  19. package/dist/lib/registry-data/index.d.ts +1 -0
  20. package/dist/lib/registry-types.d.ts +2 -1
  21. package/dist/lib/registry.d.ts +2 -12
  22. package/dist/lib/release-dependencies.d.ts +3 -0
  23. package/dist/lib/remote-client.d.ts +13 -0
  24. package/dist/lib/remote-customer-operations.d.ts +1 -0
  25. package/dist/lib/remote-invitations.d.ts +1 -1
  26. package/dist/lib/remote-recurring-contract.d.ts +165 -0
  27. package/dist/lib/remote-recurring.d.ts +95 -0
  28. package/dist/lib/skill-aliases.d.ts +2 -3
  29. package/dist/mcp/mcp-test-client.d.ts +2 -2
  30. package/dist/mcp/remote-recurring-tools.d.ts +2 -0
  31. package/dist/sdk/executor.d.ts +5 -5
  32. package/dist/sdk/index.d.ts +4 -0
  33. package/dist/sdk/index.js +114864 -46432
  34. package/dist/sdk/registry.d.ts +3 -3
  35. package/dist/server/config.d.ts +1 -2
  36. package/dist/server/handlers.d.ts +5 -2
  37. package/dist/server/registry.d.ts +6 -3
  38. package/dist/server/skills-api.d.ts +6 -38
  39. package/dist/storage.js +5 -42
  40. package/package.json +3 -2
  41. package/dist/lib/registry-data/business-marketing.d.ts +0 -2
  42. package/dist/lib/registry-data/communication.d.ts +0 -2
  43. package/dist/lib/registry-data/content-generation.d.ts +0 -2
  44. package/dist/lib/registry-data/data-analysis.d.ts +0 -2
  45. package/dist/lib/registry-data/design-branding.d.ts +0 -2
  46. package/dist/lib/registry-data/development-tools.d.ts +0 -2
  47. package/dist/lib/registry-data/education-learning.d.ts +0 -2
  48. package/dist/lib/registry-data/event-management.d.ts +0 -2
  49. package/dist/lib/registry-data/finance-compliance.d.ts +0 -2
  50. package/dist/lib/registry-data/health-wellness.d.ts +0 -2
  51. package/dist/lib/registry-data/media-processing.d.ts +0 -2
  52. package/dist/lib/registry-data/productivity-organization.d.ts +0 -2
  53. package/dist/lib/registry-data/project-management.d.ts +0 -2
  54. package/dist/lib/registry-data/research-writing.d.ts +0 -2
  55. package/dist/lib/registry-data/science-academic.d.ts +0 -2
  56. package/dist/lib/registry-data/travel-lifestyle.d.ts +0 -2
  57. package/dist/lib/registry-data/web-browser.d.ts +0 -2
  58. package/dist/server/seed-bundled.d.ts +0 -20
@@ -0,0 +1,8 @@
1
+ /** Bounded canonical JSON for portable integrity checks, not an authority token.
2
+ * Object keys use JavaScript code-unit order. Values that JSON would silently
3
+ * drop or transform are refused, including accessors and sparse array slots. */
4
+ export declare function canonicalJson(value: unknown, maximumBytes?: number): string;
5
+ /** Internal parser bound: response wrappers consume depth independently of the
6
+ * immutable payload. The public canonical helpers retain their 64-level bound. */
7
+ export declare function canonicalJsonAtDepth(value: unknown, maximumBytes: number, maximumDepth: number): string;
8
+ export declare function canonicalJsonSha256(value: unknown, maximumBytes?: number): string;
@@ -1,4 +1,4 @@
1
- export type SkillsCliMcpParityDomain = "discovery" | "portable-skills" | "runtime" | "tool-primitives" | "validation";
1
+ export type SkillsCliMcpParityDomain = "recurring-consent" | "discovery" | "portable-skills" | "runtime" | "tool-primitives" | "validation";
2
2
  export interface SkillsCliMcpParityEntry {
3
3
  domain: SkillsCliMcpParityDomain;
4
4
  operation: string;
@@ -4,7 +4,6 @@
4
4
  * Loads configuration from:
5
5
  * 1. Project-local: ./skills.config.json (highest priority)
6
6
  * 2. Global: ~/.hasna/skills/config.json (JSON format, lowest priority)
7
- * (backward compat: also checks ~/.skillsrc)
8
7
  *
9
8
  * Values from the project config override global config.
10
9
  */
@@ -83,35 +82,16 @@ export declare function isOwnerLayoutMigrated(appDir: string): boolean;
83
82
  /**
84
83
  * Get the data directory for skills global config/data.
85
84
  * Default: ~/.hasna/skills/, overridable with $HASNA_SKILLS_DIR.
86
- * Auto-migrates from ~/.skills/ and ~/.skillsrc without deleting legacy data.
85
+ * Legacy directories and configuration are never imported during resolution.
87
86
  */
88
87
  export declare function getDataDir(): string;
89
- /**
90
- * Write-free data-dir resolution for read-only paths (e.g. `sync --dry-run`).
91
- *
92
- * getDataDir() itself writes: it mkdirs the app folder, merges legacy ~/.skills
93
- * content and copies the legacy config file. A dry run must resolve the SAME
94
- * directory a real run would use without performing any of that — the app-home
95
- * resolver (getDataRoot) is already write-free, so this mirrors it directly.
96
- */
88
+ /** Resolve the same app data root without creating directories. */
97
89
  export declare function getDataDirReadOnly(): string;
98
90
  /**
99
91
  * Get the config file path for a given scope, write-free (see getDataDirReadOnly).
100
92
  */
101
93
  export declare function getConfigPathReadOnly(scope: ConfigScope): string;
102
- /**
103
- * Load merged config (project-local overrides global) without the writes
104
- * getDataDir() performs on the write path.
105
- *
106
- * The write path folds the legacy ~/.skillsrc into canonical config.json as part of
107
- * getDataDir()'s migration — copied ONLY when canonical config.json is absent, and
108
- * the legacy migration is skipped entirely when a data-directory override is active.
109
- * This mirrors that FILE-LEVEL precedence, never field-level merging: canonical
110
- * config.json, when present, is the whole global config; legacy ~/.skillsrc is read
111
- * only in the exact situation the write path would copy it (no canonical file, no
112
- * override). Field-level merging would inherit stale legacy values beneath a
113
- * canonical config that omits them, so the two paths must agree exactly.
114
- */
94
+ /** Read only the canonical global and explicitly selected project configuration. */
115
95
  export declare function loadConfigReadOnly(): SkillsConfig;
116
96
  /**
117
97
  * Get the config file path for a given scope
@@ -48,7 +48,7 @@ interface MetaFile {
48
48
  disabled?: string[];
49
49
  }
50
50
  /**
51
- * Get the path to a bundled skill in the package.
51
+ * Resolve a skill only inside the owned cache or an explicit authoring source.
52
52
  */
53
53
  export declare function getSkillPath(name: string): string;
54
54
  /**
@@ -21,7 +21,7 @@ export interface JsonSchemaObject {
21
21
  oneOf?: JsonSchemaObject[];
22
22
  }
23
23
  export type McpToolCategory = "agent-session" | "discovery" | "execution" | "feedback" | "metadata" | "pinning" | "scaffolding" | "scheduling" | "storage" | "validation";
24
- export type McpToolSideEffect = "filesystem" | "local-process-or-remote-run" | "none" | "schedule-state";
24
+ export type McpToolSideEffect = "filesystem" | "remote-state" | "remote-state-and-filesystem" | "local-process-or-remote-run" | "none" | "schedule-state";
25
25
  export interface McpToolContract {
26
26
  name: string;
27
27
  title: string;
@@ -20,7 +20,7 @@ export * from "./portable-skills-types.js";
20
20
  * exists there (the record is the authority; a skills/ directory someone
21
21
  * created by hand is not the corpus)
22
22
  * 3. `getDataDir()` - <app folder>/installed (pre-migration corpus,
23
- * with the legacy auto-copy migration), where the app folder is
23
+ * without importing any legacy directories), where the app folder is
24
24
  * $HASNA_SKILLS_DIR, else ~/.hasna/skills
25
25
  *
26
26
  * The app folder holds app data (config.json, skills.db, auth.json); the corpus
@@ -0,0 +1,29 @@
1
+ import { type RemoteWorkspaceContext } from "./remote-workspace-selection.js";
2
+ import { type RecurringAction, type RecurringInputs, type RecurringResults } from "./remote-recurring.js";
3
+ type Env = Record<string, string | undefined>;
4
+ export declare class RecurringCustomerError extends Error {
5
+ readonly code: string;
6
+ constructor(code: string, message: string);
7
+ }
8
+ export interface RecurringCustomer {
9
+ readonly apiOrigin: string;
10
+ readonly profile: string | null;
11
+ readonly context: RemoteWorkspaceContext | undefined;
12
+ /** Present only after actual fresh session and selected-workspace verification. */
13
+ readonly organizationId: string | undefined;
14
+ assertCurrent(): Promise<void>;
15
+ call<A extends RecurringAction>(action: A, input: RecurringInputs[A]): Promise<RecurringResults[A]>;
16
+ requestCode(email: string): Promise<void>;
17
+ fresh(email: string, code: string): Promise<RecurringCustomer>;
18
+ }
19
+ /** Capture before prompting. Fresh authority comes only from the existing OTP and
20
+ * workspace session verifier; a profile/context never grants that authority. */
21
+ export declare function prepareRecurringCustomer(requested?: RemoteWorkspaceContext, source?: Env): Promise<RecurringCustomer>;
22
+ /** Never echo authentication/transport bodies or caller-supplied credentials. */
23
+ export declare function recurringCustomerError(error: unknown): {
24
+ status?: number | undefined;
25
+ code: string;
26
+ error: string;
27
+ outcomeUnknown: boolean;
28
+ };
29
+ export {};
@@ -0,0 +1,82 @@
1
+ import { z } from "zod/v4";
2
+ import { type RecurringActivation, type RecurringPreview, type RecurringConsentView } from "./remote-recurring.js";
3
+ import { type RecurringCustomer } from "./recurring-customer.js";
4
+ declare const intentSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
5
+ contractVersion: z.ZodLiteral<1>;
6
+ apiOrigin: z.ZodString;
7
+ profile: z.ZodNullable<z.ZodString>;
8
+ organizationId: z.ZodString;
9
+ userId: z.ZodString;
10
+ membershipId: z.ZodString;
11
+ operation: z.ZodLiteral<"activate">;
12
+ draftId: z.ZodString;
13
+ termsSha256: z.ZodString;
14
+ approvalDeadline: z.ZodString;
15
+ approval: z.ZodObject<{
16
+ contractVersion: z.ZodLiteral<1>;
17
+ acceptedTermsSha256: z.ZodString;
18
+ acceptance: z.ZodLiteral<"authorize-recurring-credit-use">;
19
+ idempotencyKey: z.ZodString;
20
+ }, z.core.$strict>;
21
+ }, z.core.$strict>, z.ZodObject<{
22
+ contractVersion: z.ZodLiteral<1>;
23
+ apiOrigin: z.ZodString;
24
+ profile: z.ZodNullable<z.ZodString>;
25
+ organizationId: z.ZodString;
26
+ userId: z.ZodString;
27
+ membershipId: z.ZodString;
28
+ operation: z.ZodLiteral<"revoke">;
29
+ consentId: z.ZodString;
30
+ }, z.core.$strict>], "operation">;
31
+ type Intent = z.infer<typeof intentSchema>;
32
+ /** Refuse a substituted target before displaying saved terms or requesting OTP.
33
+ * The recovery executor repeats this fence while holding the original record. */
34
+ export declare function bindRecurringRecovery(customer: RecurringCustomer, intent: Intent): void;
35
+ export declare function prepareRecurringActivation(customer: RecurringCustomer, directory: string, draftId: string, approval: RecurringActivation): Promise<RecurringPreview>;
36
+ export declare function prepareRecurringRevocation(customer: RecurringCustomer, directory: string, consentId: string): Promise<RecurringConsentView>;
37
+ export declare function readRecurringRecovery(directory: string): {
38
+ intent: {
39
+ contractVersion: 1;
40
+ apiOrigin: string;
41
+ profile: string | null;
42
+ organizationId: string;
43
+ userId: string;
44
+ membershipId: string;
45
+ operation: "activate";
46
+ draftId: string;
47
+ termsSha256: string;
48
+ approvalDeadline: string;
49
+ approval: {
50
+ contractVersion: 1;
51
+ acceptedTermsSha256: string;
52
+ acceptance: "authorize-recurring-credit-use";
53
+ idempotencyKey: string;
54
+ };
55
+ } | {
56
+ contractVersion: 1;
57
+ apiOrigin: string;
58
+ profile: string | null;
59
+ organizationId: string;
60
+ userId: string;
61
+ membershipId: string;
62
+ operation: "revoke";
63
+ consentId: string;
64
+ };
65
+ phase: "pending" | "prepared" | "observed";
66
+ consentId: string | null;
67
+ };
68
+ export interface RecurringRecoveryOptions {
69
+ confirm: boolean;
70
+ email?: string;
71
+ code?: string;
72
+ }
73
+ /** One explicit action, never an internal POST retry. Pending remains uncertain
74
+ * even when later verification, local persistence or custody checks fail. */
75
+ export declare function continueRecurringRecovery(customer: RecurringCustomer, directory: string, options: RecurringRecoveryOptions): Promise<{
76
+ recoveryDirectory: string;
77
+ operation: "activate" | "revoke";
78
+ outcomeUnknown: boolean;
79
+ phase: "pending" | "prepared" | "observed";
80
+ result: unknown;
81
+ }>;
82
+ export {};
@@ -0,0 +1,252 @@
1
+ import { z } from "zod/v4";
2
+ import { type RecurringPreview } from "./remote-recurring.js";
3
+ export declare const recurringSurfaceSchemas: {
4
+ preview: z.ZodObject<{
5
+ request: z.ZodObject<{
6
+ contractVersion: z.ZodLiteral<1>;
7
+ skill: z.ZodString;
8
+ input: z.ZodRecord<z.ZodString, z.ZodJSONSchema>;
9
+ args: z.ZodArray<z.ZodString>;
10
+ runtime: z.ZodObject<{
11
+ timeoutMs: z.ZodNumber;
12
+ maxOutputBytes: z.ZodNumber;
13
+ maxAttempts: z.ZodNumber;
14
+ connectorOperations: z.ZodArray<z.ZodObject<{
15
+ connectorSlug: z.ZodString;
16
+ operationName: z.ZodString;
17
+ }, z.core.$strict>>;
18
+ }, z.core.$strict>;
19
+ everyMinutes: z.ZodNumber;
20
+ startsAt: z.ZodString;
21
+ expiresAt: z.ZodString;
22
+ dispatchGraceSeconds: z.ZodNumber;
23
+ period: z.ZodLiteral<"utc-day">;
24
+ inFlightPolicy: z.ZodLiteral<"finish-authorized-attempt">;
25
+ maxCreditsPerRun: z.ZodNumber;
26
+ maxCreditsPerPeriod: z.ZodNumber;
27
+ maxCreditsTotal: z.ZodNumber;
28
+ maxOccurrencesPerPeriod: z.ZodNumber;
29
+ maxOccurrencesTotal: z.ZodNumber;
30
+ }, z.core.$strict>;
31
+ userId: z.ZodOptional<z.ZodString>;
32
+ membershipId: z.ZodOptional<z.ZodString>;
33
+ }, z.core.$strict>;
34
+ draft: z.ZodObject<{
35
+ draftId: z.ZodString;
36
+ userId: z.ZodOptional<z.ZodString>;
37
+ membershipId: z.ZodOptional<z.ZodString>;
38
+ }, z.core.$strict>;
39
+ activate: z.ZodObject<{
40
+ draftId: z.ZodString;
41
+ approval: z.ZodObject<{
42
+ contractVersion: z.ZodLiteral<1>;
43
+ acceptedTermsSha256: z.ZodString;
44
+ acceptance: z.ZodLiteral<"authorize-recurring-credit-use">;
45
+ idempotencyKey: z.ZodString;
46
+ }, z.core.$strict>;
47
+ recoveryDirectory: z.ZodString;
48
+ email: z.ZodString;
49
+ code: z.ZodOptional<z.ZodString>;
50
+ confirm: z.ZodOptional<z.ZodBoolean>;
51
+ userId: z.ZodOptional<z.ZodString>;
52
+ membershipId: z.ZodOptional<z.ZodString>;
53
+ }, z.core.$strict>;
54
+ list: z.ZodObject<{
55
+ limit: z.ZodOptional<z.ZodNumber>;
56
+ cursor: z.ZodOptional<z.ZodString>;
57
+ userId: z.ZodOptional<z.ZodString>;
58
+ membershipId: z.ZodOptional<z.ZodString>;
59
+ }, z.core.$strict>;
60
+ get: z.ZodObject<{
61
+ consentId: z.ZodString;
62
+ userId: z.ZodOptional<z.ZodString>;
63
+ membershipId: z.ZodOptional<z.ZodString>;
64
+ }, z.core.$strict>;
65
+ occurrences: z.ZodObject<{
66
+ consentId: z.ZodString;
67
+ limit: z.ZodOptional<z.ZodNumber>;
68
+ cursor: z.ZodOptional<z.ZodString>;
69
+ userId: z.ZodOptional<z.ZodString>;
70
+ membershipId: z.ZodOptional<z.ZodString>;
71
+ }, z.core.$strict>;
72
+ revoke: z.ZodObject<{
73
+ consentId: z.ZodString;
74
+ recoveryDirectory: z.ZodString;
75
+ confirm: z.ZodLiteral<true>;
76
+ userId: z.ZodOptional<z.ZodString>;
77
+ membershipId: z.ZodOptional<z.ZodString>;
78
+ }, z.core.$strict>;
79
+ recover: z.ZodObject<{
80
+ recoveryDirectory: z.ZodString;
81
+ confirm: z.ZodOptional<z.ZodBoolean>;
82
+ email: z.ZodOptional<z.ZodString>;
83
+ code: z.ZodOptional<z.ZodString>;
84
+ userId: z.ZodOptional<z.ZodString>;
85
+ membershipId: z.ZodOptional<z.ZodString>;
86
+ }, z.core.$strict>;
87
+ verification: z.ZodObject<{
88
+ draftId: z.ZodString;
89
+ email: z.ZodString;
90
+ confirm: z.ZodLiteral<true>;
91
+ userId: z.ZodOptional<z.ZodString>;
92
+ membershipId: z.ZodOptional<z.ZodString>;
93
+ }, z.core.$strict>;
94
+ };
95
+ export type RecurringSurfaceAction = keyof typeof recurringSurfaceSchemas;
96
+ export declare const recurringSurfaceOperations: readonly [{
97
+ readonly action: "preview";
98
+ readonly name: "preview_recurring_consent";
99
+ readonly title: "Preview recurring consent";
100
+ readonly cli: "preview";
101
+ readonly read: false;
102
+ readonly recovery: false;
103
+ }, {
104
+ readonly action: "draft";
105
+ readonly name: "get_recurring_draft";
106
+ readonly title: "Read original recurring draft";
107
+ readonly cli: "draft";
108
+ readonly read: true;
109
+ readonly recovery: false;
110
+ }, {
111
+ readonly action: "activate";
112
+ readonly name: "activate_recurring_consent";
113
+ readonly title: "Authorize recurring credit use";
114
+ readonly cli: "activate";
115
+ readonly read: false;
116
+ readonly recovery: true;
117
+ }, {
118
+ readonly action: "list";
119
+ readonly name: "list_recurring_consents";
120
+ readonly title: "List recurring consents";
121
+ readonly cli: "list";
122
+ readonly read: true;
123
+ readonly recovery: false;
124
+ }, {
125
+ readonly action: "get";
126
+ readonly name: "get_recurring_consent";
127
+ readonly title: "Inspect recurring consent and budgets";
128
+ readonly cli: "get";
129
+ readonly read: true;
130
+ readonly recovery: false;
131
+ }, {
132
+ readonly action: "occurrences";
133
+ readonly name: "list_recurring_occurrences";
134
+ readonly title: "Inspect recurring occurrence history";
135
+ readonly cli: "occurrences";
136
+ readonly read: true;
137
+ readonly recovery: false;
138
+ }, {
139
+ readonly action: "revoke";
140
+ readonly name: "revoke_recurring_consent";
141
+ readonly title: "Revoke recurring authority";
142
+ readonly cli: "revoke";
143
+ readonly read: false;
144
+ readonly recovery: true;
145
+ }, {
146
+ readonly action: "recover";
147
+ readonly name: "recover_recurring_consent";
148
+ readonly title: "Reconcile original recurring request";
149
+ readonly cli: "recover";
150
+ readonly read: false;
151
+ readonly recovery: true;
152
+ }, {
153
+ readonly action: "verification";
154
+ readonly name: "request_recurring_verification";
155
+ readonly title: "Request recurring approval verification";
156
+ readonly cli: "verification";
157
+ readonly read: false;
158
+ readonly recovery: false;
159
+ }];
160
+ /** The host must obtain explicit acceptance and a real human OTP. A boolean alone
161
+ * never grants recurring authority. Host request history may retain supplied OTPs. */
162
+ export declare function recurringMcpSchema(action: RecurringSurfaceAction): z.ZodObject<{
163
+ request: z.ZodObject<{
164
+ contractVersion: z.ZodLiteral<1>;
165
+ skill: z.ZodString;
166
+ input: z.ZodRecord<z.ZodString, z.ZodJSONSchema>;
167
+ args: z.ZodArray<z.ZodString>;
168
+ runtime: z.ZodObject<{
169
+ timeoutMs: z.ZodNumber;
170
+ maxOutputBytes: z.ZodNumber;
171
+ maxAttempts: z.ZodNumber;
172
+ connectorOperations: z.ZodArray<z.ZodObject<{
173
+ connectorSlug: z.ZodString;
174
+ operationName: z.ZodString;
175
+ }, z.core.$strict>>;
176
+ }, z.core.$strict>;
177
+ everyMinutes: z.ZodNumber;
178
+ startsAt: z.ZodString;
179
+ expiresAt: z.ZodString;
180
+ dispatchGraceSeconds: z.ZodNumber;
181
+ period: z.ZodLiteral<"utc-day">;
182
+ inFlightPolicy: z.ZodLiteral<"finish-authorized-attempt">;
183
+ maxCreditsPerRun: z.ZodNumber;
184
+ maxCreditsPerPeriod: z.ZodNumber;
185
+ maxCreditsTotal: z.ZodNumber;
186
+ maxOccurrencesPerPeriod: z.ZodNumber;
187
+ maxOccurrencesTotal: z.ZodNumber;
188
+ }, z.core.$strict>;
189
+ userId: z.ZodOptional<z.ZodString>;
190
+ membershipId: z.ZodOptional<z.ZodString>;
191
+ }, z.core.$strict> | z.ZodObject<{
192
+ draftId: z.ZodString;
193
+ userId: z.ZodOptional<z.ZodString>;
194
+ membershipId: z.ZodOptional<z.ZodString>;
195
+ }, z.core.$strict> | z.ZodObject<{
196
+ limit: z.ZodOptional<z.ZodNumber>;
197
+ cursor: z.ZodOptional<z.ZodString>;
198
+ userId: z.ZodOptional<z.ZodString>;
199
+ membershipId: z.ZodOptional<z.ZodString>;
200
+ }, z.core.$strict> | z.ZodObject<{
201
+ consentId: z.ZodString;
202
+ userId: z.ZodOptional<z.ZodString>;
203
+ membershipId: z.ZodOptional<z.ZodString>;
204
+ }, z.core.$strict> | z.ZodObject<{
205
+ recoveryDirectory: z.ZodString;
206
+ confirm: z.ZodOptional<z.ZodBoolean>;
207
+ email: z.ZodOptional<z.ZodString>;
208
+ code: z.ZodOptional<z.ZodString>;
209
+ userId: z.ZodOptional<z.ZodString>;
210
+ membershipId: z.ZodOptional<z.ZodString>;
211
+ }, z.core.$strict>;
212
+ export interface RecurringInteraction {
213
+ accept(draft: RecurringPreview): Promise<boolean>;
214
+ verification(email: string, requestCode: () => Promise<void>): Promise<string | null>;
215
+ }
216
+ /** Shared CLI/MCP orchestration only. The SDK owns wire validation/transport; the
217
+ * selected server owns grants, freshness, prices, financial state and execution. */
218
+ export declare function executeRecurringSurface(action: RecurringSurfaceAction, raw: unknown, env?: Record<string, string | undefined>, interaction?: RecurringInteraction): Promise<RecurringPreview | import("./remote-recurring-contract.js").RecurringConsentView | import("./remote-recurring-contract.js").RecurringPage<import("./remote-recurring-contract.js").RecurringConsentView> | import("./remote-recurring-contract.js").RecurringPage<import("./remote-recurring-contract.js").RecurringOccurrenceView> | {
219
+ recoveryDirectory: string;
220
+ operation: "activate" | "revoke";
221
+ outcomeUnknown: boolean;
222
+ phase: "pending" | "prepared" | "observed";
223
+ result: unknown;
224
+ } | {
225
+ cancelled: boolean;
226
+ activated: boolean;
227
+ } | {
228
+ verificationRequested: boolean;
229
+ deliveryConfirmed: boolean;
230
+ draftId: string;
231
+ activated: boolean;
232
+ cancelled?: undefined;
233
+ outcomeUnknown?: undefined;
234
+ recoveryDirectory?: undefined;
235
+ } | {
236
+ recoveryDirectory: string;
237
+ phase: string;
238
+ outcomeUnknown: boolean;
239
+ cancelled: boolean;
240
+ activated: boolean;
241
+ verificationRequested?: undefined;
242
+ deliveryConfirmed?: undefined;
243
+ draftId?: undefined;
244
+ } | {
245
+ cancelled: boolean;
246
+ outcomeUnknown: boolean;
247
+ recoveryDirectory: string;
248
+ verificationRequested?: undefined;
249
+ deliveryConfirmed?: undefined;
250
+ draftId?: undefined;
251
+ activated?: undefined;
252
+ } | null>;
@@ -1,2 +1,3 @@
1
1
  import type { SkillMeta } from "../registry-types.js";
2
+ /** @deprecated Skills are loaded from an account or an explicitly selected local source. */
2
3
  export declare const SKILLS: SkillMeta[];
@@ -38,5 +38,6 @@ export interface SkillAvailabilityMetadata {
38
38
  }
39
39
  export declare const CATEGORIES: readonly ["Development Tools", "Business & Marketing", "Productivity & Organization", "Project Management", "Content Generation", "Finance & Compliance", "Data & Analysis", "Media Processing", "Design & Branding", "Web & Browser", "Research & Writing", "Science & Academic", "Education & Learning", "Communication", "Health & Wellness", "Travel & Lifestyle", "Event Management"];
40
40
  export type Category = (typeof CATEGORIES)[number];
41
- export declare const BASIC_SKILL_NAMES: readonly ["blog-article", "ad-creative-pack", "email-sequence", "seo-content-pack", "social-content-calendar", "pitch-deck", "proposal-pack", "market-research-report"];
41
+ /** @deprecated There is no software-owned default selection. Use an account profile. */
42
+ export declare const BASIC_SKILL_NAMES: readonly string[];
42
43
  export type SkillRegistryProfile = "basic" | "all";
@@ -7,19 +7,9 @@ export { BASIC_SKILL_NAMES, CATEGORIES, SKILLS };
7
7
  export type { Category, SkillMeta, SkillRegistryProfile };
8
8
  export declare function isBasicSkillName(name: string): boolean;
9
9
  export declare function findExtensionSkillPath(name: string): string | null;
10
- /**
11
- * Load the full registry: official skills merged with a configured private
12
- * extension checkout and global custom skills from the canonical local corpus
13
- * — <app folder>/installed/<name>/ before the owner-layout migration, <app
14
- * folder>/skills/<name>/ after it (resolveCorpusRoot(), the one resolution
15
- * every discovery path shares) — plus the legacy ~/.hasna/skills/custom/<name>/
16
- * migration safety net.
17
- *
18
- * Custom skills take precedence over extensions, which take precedence over
19
- * official skills. Extension skills are read in place and never copied into the
20
- * corpus. Results are cached for 5 seconds.
21
- */
10
+ /** Discover the Skills-owned cache and explicitly configured authoring sources. */
22
11
  export declare function loadRegistry(cwd?: string): SkillMeta[];
12
+ /** Compatibility name for the caller's own catalog; no baked-in default selection. */
23
13
  export declare function loadBasicRegistry(cwd?: string): SkillMeta[];
24
14
  export declare function loadRegistryProfile(profile?: SkillRegistryProfile, cwd?: string): SkillMeta[];
25
15
  /** Invalidate the registry cache (e.g. after installing a custom skill). */
@@ -1,3 +1,4 @@
1
+ type Context = Record<string, string | null>;
1
2
  /** Verifies installed resolution against the selected standalone frozen lock.
2
3
  * This is a graph/version check; the separate frozen installer receipt binds
3
4
  * registry integrity. Package payload attestation is not inferred from version. */
@@ -17,6 +18,7 @@ export declare function verifyProducerDependencies(packageRoot: string): {
17
18
  version: string;
18
19
  manifestSha256: string;
19
20
  relativePath: string;
21
+ context: Context;
20
22
  }[];
21
23
  edges: {
22
24
  from: string;
@@ -25,3 +27,4 @@ export declare function verifyProducerDependencies(packageRoot: string): {
25
27
  optionalAbsent?: boolean;
26
28
  }[];
27
29
  };
30
+ export {};
@@ -1,3 +1,4 @@
1
+ import { type RecurringRequest, type RecurringActivation, type RecurringListOptions, type RecurringCapability, type RecurringConsentView, type RecurringOccurrenceView, type RecurringPage } from "./remote-recurring.js";
1
2
  import { type ListRemoteWorkspaceInvitations, type IssueRemoteWorkspaceInvitation, type ResendRemoteWorkspaceInvitation, type RevokeRemoteWorkspaceInvitation, type AcceptRemoteWorkspaceInvitation } from "./remote-invitations.js";
2
3
  import { type LeaveRemoteWorkspace, type RemoteWorkspaceLeaveResult } from "./remote-workspace-leave.js";
3
4
  import { type RemoteWorkspaceContext, type RemoteAccountWorkspaces, type RemoteWorkspaceSession, type RemoteWorkspaceSelectionErrorCode } from "./remote-workspace-selection.js";
@@ -130,6 +131,7 @@ export declare class RemoteSkillsClient {
130
131
  boundedRunApproval?: boolean;
131
132
  unit?: string;
132
133
  };
134
+ recurringConsents?: RecurringCapability;
133
135
  }>;
134
136
  /** Quote first and fail closed when the caller has not approved the required credits. */
135
137
  submitQuotedRun(slug: string, input?: Record<string, unknown>, args?: string[], approval?: RemoteRunApproval): Promise<RemoteSkillRunContract>;
@@ -167,6 +169,17 @@ export declare class RemoteSkillsClient {
167
169
  /** One bounded operation, bound to the observed current incarnation. No retries,
168
170
  * key/session persistence or post-acceptance selection of another workspace. */
169
171
  private requestWorkspaceInvitation;
172
+ previewRecurringConsent(request: RecurringRequest, context?: RemoteWorkspaceContext): Promise<import("./remote-recurring-contract.js").RecurringPreview>;
173
+ getRecurringDraft(draftId: string, context?: RemoteWorkspaceContext): Promise<import("./remote-recurring-contract.js").RecurringPreview | null>;
174
+ activateRecurringConsent(draftId: string, approval: RecurringActivation, context?: RemoteWorkspaceContext): Promise<import("./remote-recurring-contract.js").RecurringActivationResult>;
175
+ listRecurringConsents(options?: RecurringListOptions, context?: RemoteWorkspaceContext): Promise<RecurringPage<RecurringConsentView>>;
176
+ getRecurringConsent(consentId: string, context?: RemoteWorkspaceContext): Promise<RecurringConsentView | null>;
177
+ listRecurringOccurrences(consentId: string, options?: RecurringListOptions, context?: RemoteWorkspaceContext): Promise<RecurringPage<RecurringOccurrenceView>>;
178
+ revokeRecurringConsent(consentId: string, context?: RemoteWorkspaceContext): Promise<import("./remote-recurring-contract.js").RecurringRevocation>;
179
+ /** One explicit operation on a captured connection. No policy inference,
180
+ * credential persistence, POST retries or replacement idempotency keys. */
181
+ private requestRecurring;
182
+ private dispatchRecurring;
170
183
  listApiKeys(): Promise<Record<string, unknown>[]>;
171
184
  createApiKey(name: string, scopes?: string[]): Promise<{
172
185
  key: string;
@@ -19,6 +19,7 @@ export declare const REMOTE_CUSTOMER_OPERATIONS: readonly [{
19
19
  boundedRunApproval?: boolean;
20
20
  unit?: string;
21
21
  };
22
+ recurringConsents?: import("./remote-recurring.js").RecurringCapability;
22
23
  }>;
23
24
  }, {
24
25
  readonly name: "list_remote_skills";
@@ -84,7 +84,7 @@ export declare class RemoteWorkspaceInvitationReadError extends Error {
84
84
  readonly code = "INVITATION_READ_FAILED";
85
85
  constructor();
86
86
  }
87
- export declare function invitationFailure(value: unknown, status: number): "INVALID_REQUEST" | "ACCOUNT_UNAVAILABLE" | "INTERACTIVE_SESSION_REQUIRED" | "WORKSPACE_ADMIN_REQUIRED" | "INVITATION_FORBIDDEN" | "INVITATION_UNAVAILABLE" | "INVITATION_CHANGED" | "INVITATION_EXISTS" | "ALREADY_MEMBER" | "IDEMPOTENCY_CONFLICT" | "INVITATION_LIMIT" | "INVITATION_BUSY" | "INVITATION_DELIVERY_UNAVAILABLE" | null;
87
+ export declare function invitationFailure(value: unknown, status: number): "ACCOUNT_UNAVAILABLE" | "INTERACTIVE_SESSION_REQUIRED" | "INVALID_REQUEST" | "WORKSPACE_ADMIN_REQUIRED" | "INVITATION_FORBIDDEN" | "INVITATION_UNAVAILABLE" | "INVITATION_CHANGED" | "INVITATION_EXISTS" | "ALREADY_MEMBER" | "IDEMPOTENCY_CONFLICT" | "INVITATION_LIMIT" | "INVITATION_BUSY" | "INVITATION_DELIVERY_UNAVAILABLE" | null;
88
88
  export type InvitationAction = "list" | "get" | "issue" | "resend" | "revoke" | "accept";
89
89
  export type InvitationInputs = {
90
90
  list: ListRemoteWorkspaceInvitations;