@nemesis-oss/ollama-sdk 1.4.1 → 1.5.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.
Files changed (35) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +23 -2
  3. package/dist/{compose-DfAqKAFj.d.ts → compose-DLStUfaF.d.ts} +2 -2
  4. package/dist/{compose-BR70yb4W.d.cts → compose-DS-UWFx8.d.cts} +2 -2
  5. package/dist/generated-api.d.cts +4 -3
  6. package/dist/generated-api.d.ts +4 -3
  7. package/dist/generated-runtime.cjs +161 -1
  8. package/dist/generated-runtime.cjs.map +1 -1
  9. package/dist/generated-runtime.d.cts +35 -2
  10. package/dist/generated-runtime.d.ts +35 -2
  11. package/dist/generated-runtime.js +160 -2
  12. package/dist/generated-runtime.js.map +1 -1
  13. package/dist/index.cjs +158 -1
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.cts +8 -8
  16. package/dist/index.d.ts +8 -8
  17. package/dist/index.js +158 -2
  18. package/dist/index.js.map +1 -1
  19. package/dist/mcp-generated.d.cts +4 -3
  20. package/dist/mcp-generated.d.ts +4 -3
  21. package/dist/mcp-http.d.cts +1 -1
  22. package/dist/mcp-http.d.ts +1 -1
  23. package/dist/mcp-stdio.d.cts +1 -1
  24. package/dist/mcp-stdio.d.ts +1 -1
  25. package/dist/{index-DIQ8NUbU.d.ts → runtime-CVQkbYgF.d.ts} +40 -2
  26. package/dist/{index-2RIErNT5.d.cts → runtime-IxRpUBjN.d.cts} +40 -2
  27. package/dist/skills.cjs.map +1 -1
  28. package/dist/skills.d.cts +3 -3
  29. package/dist/skills.d.ts +3 -3
  30. package/dist/skills.js.map +1 -1
  31. package/dist/{types-BQhgW-du.d.cts → types-5PAjLoCp.d.cts} +1 -1
  32. package/dist/{types-BQhgW-du.d.ts → types-5PAjLoCp.d.ts} +1 -1
  33. package/dist/{types-B9_axjum.d.cts → types-MOsWXEE7.d.cts} +1 -1
  34. package/dist/{types-B9_axjum.d.ts → types-MOsWXEE7.d.ts} +1 -1
  35. package/package.json +1 -1
@@ -1,6 +1,7 @@
1
- import { M as McpToolDescriptor } from './types-B9_axjum.cjs';
2
- import { O as OllamaRuntime } from './index-2RIErNT5.cjs';
3
- import './types-BQhgW-du.cjs';
1
+ import { a as McpToolDescriptor } from './types-MOsWXEE7.cjs';
2
+ import { O as OllamaRuntime } from './runtime-IxRpUBjN.cjs';
3
+ import './types-5PAjLoCp.cjs';
4
+ import 'zod';
4
5
 
5
6
  interface GeneratedToolEntry extends McpToolDescriptor {
6
7
  readonly _operationId: string;
@@ -1,6 +1,7 @@
1
- import { M as McpToolDescriptor } from './types-B9_axjum.js';
2
- import { O as OllamaRuntime } from './index-DIQ8NUbU.js';
3
- import './types-BQhgW-du.js';
1
+ import { a as McpToolDescriptor } from './types-MOsWXEE7.js';
2
+ import { O as OllamaRuntime } from './runtime-CVQkbYgF.js';
3
+ import './types-5PAjLoCp.js';
4
+ import 'zod';
4
5
 
5
6
  interface GeneratedToolEntry extends McpToolDescriptor {
6
7
  readonly _operationId: string;
@@ -1,4 +1,4 @@
1
- import { a as McpClientLike } from './types-B9_axjum.cjs';
1
+ import { M as McpClientLike } from './types-MOsWXEE7.cjs';
2
2
 
3
3
  /**
4
4
  * Optional remote MCP transport connectors.
@@ -1,4 +1,4 @@
1
- import { a as McpClientLike } from './types-B9_axjum.js';
1
+ import { M as McpClientLike } from './types-MOsWXEE7.js';
2
2
 
3
3
  /**
4
4
  * Optional remote MCP transport connectors.
@@ -1,4 +1,4 @@
1
- import { a as McpClientLike } from './types-B9_axjum.cjs';
1
+ import { M as McpClientLike } from './types-MOsWXEE7.cjs';
2
2
 
3
3
  /**
4
4
  * Optional Node.js MCP stdio connector.
@@ -1,4 +1,4 @@
1
- import { a as McpClientLike } from './types-B9_axjum.js';
1
+ import { M as McpClientLike } from './types-MOsWXEE7.js';
2
2
 
3
3
  /**
4
4
  * Optional Node.js MCP stdio connector.
@@ -1,4 +1,5 @@
1
- import { M as Message, k as ChatResponse, l as GenerateResponse, a as ToolCall, e as ProgressResponse } from './types-BQhgW-du.js';
1
+ import { r as Message, h as ChatResponse, i as GenerateResponse, q as ToolCall, b as ProgressResponse } from './types-5PAjLoCp.js';
2
+ import { z } from 'zod';
2
3
 
3
4
  /**
4
5
  * Request/response middleware pipeline.
@@ -101,6 +102,7 @@ declare function parseSseStream(stream: ReadableStream<Uint8Array>): AsyncGenera
101
102
  /**
102
103
  * Structured, typed error hierarchy for OllamaClient.
103
104
  */
105
+
104
106
  interface OllamaErrorRequestContext {
105
107
  readonly method?: string | undefined;
106
108
  readonly url?: string | undefined;
@@ -177,6 +179,22 @@ declare class OllamaToolValidationError extends OllamaClientError {
177
179
  issues?: unknown;
178
180
  });
179
181
  }
182
+ /**
183
+ * Thrown by `OllamaRuntime.invoke` when `validateRequests: true` is set and
184
+ * the request body fails Zod validation against the operation's registered
185
+ * schema. See ADR 0020 (runtime Zod validation).
186
+ *
187
+ * The error carries the original Zod issues so callers can inspect which
188
+ * fields failed. No HTTP request is made when this error is thrown.
189
+ */
190
+ declare class OllamaRequestValidationError extends OllamaClientError {
191
+ readonly operationId: string;
192
+ readonly issues: readonly z.ZodIssue[];
193
+ constructor(message: string, options: Omit<OllamaClientErrorOptions, 'code'> & {
194
+ operationId: string;
195
+ issues: readonly z.ZodIssue[];
196
+ });
197
+ }
180
198
  declare class OllamaToolTimeoutError extends OllamaClientError {
181
199
  readonly toolName: string;
182
200
  readonly timeoutMs: number;
@@ -565,6 +583,26 @@ interface OllamaRuntimeOptions {
565
583
  * against this value at request time.
566
584
  */
567
585
  readonly serverVersion?: string;
586
+ /**
587
+ * When `true`, the runtime validates every request body against the
588
+ * generated Zod schema before sending it. Defaults to `false` — opt-in.
589
+ *
590
+ * Validation behavior:
591
+ * - If the operation has a registered request schema (see
592
+ * {@link schema-registry.ts}), the body is parsed via `safeParse`.
593
+ * - On parse failure, throws `OllamaRequestValidationError` with the
594
+ * Zod issues attached. No HTTP request is made.
595
+ * - On parse success, the parsed (and stripped of unknown fields) body
596
+ * is sent — this means callers can't accidentally send extra fields
597
+ * that the contract doesn't allow.
598
+ * - If the operation has NO registered schema (e.g. GET endpoints,
599
+ * `/v1/systemone`, OpenAI/Anthropic compat surfaces), validation is
600
+ * skipped silently.
601
+ *
602
+ * Response validation is intentionally NOT enabled — see ADR 0020 for
603
+ * the rationale (forward-compat with wire-format extensions).
604
+ */
605
+ readonly validateRequests?: boolean;
568
606
  }
569
607
  /** The runtime seam. */
570
608
  declare class OllamaRuntime {
@@ -580,4 +618,4 @@ declare class OllamaRuntime {
580
618
  invoke<T = unknown>(req: InvokeRequest): Promise<T>;
581
619
  }
582
620
 
583
- export { OllamaToolValidationError as $, type AbortableAsyncIterable as A, type BinaryBody as B, type ChatStreamResult as C, type DoneEvent as D, type ErrorEvent as E, type FetchLike as F, type GenerateStreamResult as G, HttpClient as H, OllamaMcpError as I, OllamaModelRoutingError as J, OllamaNetworkError as K, type Logger as L, type Middleware as M, NANOS_PER_MS as N, OllamaRuntime as O, type ProgressStreamResult as P, OllamaNotFoundError as Q, type RequestLifecycleHook as R, type SseEvent as S, type TokenUsage as T, OllamaQuotaExceededError as U, OllamaRateLimitError as V, OllamaServerError as W, OllamaSkillInvalidError as X, OllamaSkillNotFoundError as Y, OllamaTimeoutError as Z, OllamaToolTimeoutError as _, type OllamaStreamEvent as a, OllamaUnsupportedCapabilityError as a0, type RequestContext as a1, type RequestLifecycleEvent as a2, type ResponseContext as a3, type ThinkingEvent as a4, type TokenEvent as a5, type ToolCallEvent as a6, composeMiddleware as a7, createConsoleLogger as a8, extractUsage as a9, mapError as aa, parseSseStream as ab, type OperationDefinition as ac, type InvokeRequest as ad, type OllamaRuntimeOptions as ae, type SchemaRef as af, type OllamaStreamEventType as b, OllamaClientError as c, type RawUsageSource as d, type HttpBody as e, type HttpClientOptions as f, type HttpRequestOptions as g, type LifecycleErrorEvent as h, type LifecycleRetryEvent as i, type LifecycleStartEvent as j, type LifecycleSuccessEvent as k, type LogFn as l, type MessageEvent as m, type MiddlewareContext as n, NANOS_PER_SECOND as o, NOOP_LOGGER as p, type NextFunction as q, OllamaAbortError as r, OllamaAgentMaxIterationsError as s, OllamaAgentMaxToolCallsError as t, OllamaAuthError as u, type OllamaClientErrorOptions as v, type OllamaErrorRequestContext as w, type OllamaErrorResponseContext as x, OllamaGenericClientError as y, OllamaIncompatibleModelError as z };
621
+ export { OllamaServerError as $, type AbortableAsyncIterable as A, type BinaryBody as B, type ChatStreamResult as C, type DoneEvent as D, type ErrorEvent as E, type FetchLike as F, type GenerateStreamResult as G, HttpClient as H, type InvokeRequest as I, type OllamaErrorResponseContext as J, OllamaGenericClientError as K, type Logger as L, type Middleware as M, NANOS_PER_MS as N, OllamaRuntime as O, type ProgressStreamResult as P, OllamaIncompatibleModelError as Q, type RequestLifecycleHook as R, type SchemaRef as S, type TokenUsage as T, OllamaMcpError as U, OllamaModelRoutingError as V, OllamaNetworkError as W, OllamaNotFoundError as X, OllamaQuotaExceededError as Y, OllamaRateLimitError as Z, OllamaRequestValidationError as _, type OperationDefinition as a, OllamaSkillInvalidError as a0, OllamaSkillNotFoundError as a1, OllamaTimeoutError as a2, OllamaToolTimeoutError as a3, OllamaToolValidationError as a4, OllamaUnsupportedCapabilityError as a5, type RequestContext as a6, type RequestLifecycleEvent as a7, type ResponseContext as a8, type ThinkingEvent as a9, type TokenEvent as aa, type ToolCallEvent as ab, composeMiddleware as ac, createConsoleLogger as ad, extractUsage as ae, mapError as af, parseSseStream as ag, type OllamaRuntimeOptions as b, type OllamaStreamEvent as c, type OllamaStreamEventType as d, type SseEvent as e, OllamaClientError as f, type RawUsageSource as g, type HttpBody as h, type HttpClientOptions as i, type HttpRequestOptions as j, type LifecycleErrorEvent as k, type LifecycleRetryEvent as l, type LifecycleStartEvent as m, type LifecycleSuccessEvent as n, type LogFn as o, type MessageEvent as p, type MiddlewareContext as q, NANOS_PER_SECOND as r, NOOP_LOGGER as s, type NextFunction as t, OllamaAbortError as u, OllamaAgentMaxIterationsError as v, OllamaAgentMaxToolCallsError as w, OllamaAuthError as x, type OllamaClientErrorOptions as y, type OllamaErrorRequestContext as z };
@@ -1,4 +1,5 @@
1
- import { M as Message, k as ChatResponse, l as GenerateResponse, a as ToolCall, e as ProgressResponse } from './types-BQhgW-du.cjs';
1
+ import { r as Message, h as ChatResponse, i as GenerateResponse, q as ToolCall, b as ProgressResponse } from './types-5PAjLoCp.cjs';
2
+ import { z } from 'zod';
2
3
 
3
4
  /**
4
5
  * Request/response middleware pipeline.
@@ -101,6 +102,7 @@ declare function parseSseStream(stream: ReadableStream<Uint8Array>): AsyncGenera
101
102
  /**
102
103
  * Structured, typed error hierarchy for OllamaClient.
103
104
  */
105
+
104
106
  interface OllamaErrorRequestContext {
105
107
  readonly method?: string | undefined;
106
108
  readonly url?: string | undefined;
@@ -177,6 +179,22 @@ declare class OllamaToolValidationError extends OllamaClientError {
177
179
  issues?: unknown;
178
180
  });
179
181
  }
182
+ /**
183
+ * Thrown by `OllamaRuntime.invoke` when `validateRequests: true` is set and
184
+ * the request body fails Zod validation against the operation's registered
185
+ * schema. See ADR 0020 (runtime Zod validation).
186
+ *
187
+ * The error carries the original Zod issues so callers can inspect which
188
+ * fields failed. No HTTP request is made when this error is thrown.
189
+ */
190
+ declare class OllamaRequestValidationError extends OllamaClientError {
191
+ readonly operationId: string;
192
+ readonly issues: readonly z.ZodIssue[];
193
+ constructor(message: string, options: Omit<OllamaClientErrorOptions, 'code'> & {
194
+ operationId: string;
195
+ issues: readonly z.ZodIssue[];
196
+ });
197
+ }
180
198
  declare class OllamaToolTimeoutError extends OllamaClientError {
181
199
  readonly toolName: string;
182
200
  readonly timeoutMs: number;
@@ -565,6 +583,26 @@ interface OllamaRuntimeOptions {
565
583
  * against this value at request time.
566
584
  */
567
585
  readonly serverVersion?: string;
586
+ /**
587
+ * When `true`, the runtime validates every request body against the
588
+ * generated Zod schema before sending it. Defaults to `false` — opt-in.
589
+ *
590
+ * Validation behavior:
591
+ * - If the operation has a registered request schema (see
592
+ * {@link schema-registry.ts}), the body is parsed via `safeParse`.
593
+ * - On parse failure, throws `OllamaRequestValidationError` with the
594
+ * Zod issues attached. No HTTP request is made.
595
+ * - On parse success, the parsed (and stripped of unknown fields) body
596
+ * is sent — this means callers can't accidentally send extra fields
597
+ * that the contract doesn't allow.
598
+ * - If the operation has NO registered schema (e.g. GET endpoints,
599
+ * `/v1/systemone`, OpenAI/Anthropic compat surfaces), validation is
600
+ * skipped silently.
601
+ *
602
+ * Response validation is intentionally NOT enabled — see ADR 0020 for
603
+ * the rationale (forward-compat with wire-format extensions).
604
+ */
605
+ readonly validateRequests?: boolean;
568
606
  }
569
607
  /** The runtime seam. */
570
608
  declare class OllamaRuntime {
@@ -580,4 +618,4 @@ declare class OllamaRuntime {
580
618
  invoke<T = unknown>(req: InvokeRequest): Promise<T>;
581
619
  }
582
620
 
583
- export { OllamaToolValidationError as $, type AbortableAsyncIterable as A, type BinaryBody as B, type ChatStreamResult as C, type DoneEvent as D, type ErrorEvent as E, type FetchLike as F, type GenerateStreamResult as G, HttpClient as H, OllamaMcpError as I, OllamaModelRoutingError as J, OllamaNetworkError as K, type Logger as L, type Middleware as M, NANOS_PER_MS as N, OllamaRuntime as O, type ProgressStreamResult as P, OllamaNotFoundError as Q, type RequestLifecycleHook as R, type SseEvent as S, type TokenUsage as T, OllamaQuotaExceededError as U, OllamaRateLimitError as V, OllamaServerError as W, OllamaSkillInvalidError as X, OllamaSkillNotFoundError as Y, OllamaTimeoutError as Z, OllamaToolTimeoutError as _, type OllamaStreamEvent as a, OllamaUnsupportedCapabilityError as a0, type RequestContext as a1, type RequestLifecycleEvent as a2, type ResponseContext as a3, type ThinkingEvent as a4, type TokenEvent as a5, type ToolCallEvent as a6, composeMiddleware as a7, createConsoleLogger as a8, extractUsage as a9, mapError as aa, parseSseStream as ab, type OperationDefinition as ac, type InvokeRequest as ad, type OllamaRuntimeOptions as ae, type SchemaRef as af, type OllamaStreamEventType as b, OllamaClientError as c, type RawUsageSource as d, type HttpBody as e, type HttpClientOptions as f, type HttpRequestOptions as g, type LifecycleErrorEvent as h, type LifecycleRetryEvent as i, type LifecycleStartEvent as j, type LifecycleSuccessEvent as k, type LogFn as l, type MessageEvent as m, type MiddlewareContext as n, NANOS_PER_SECOND as o, NOOP_LOGGER as p, type NextFunction as q, OllamaAbortError as r, OllamaAgentMaxIterationsError as s, OllamaAgentMaxToolCallsError as t, OllamaAuthError as u, type OllamaClientErrorOptions as v, type OllamaErrorRequestContext as w, type OllamaErrorResponseContext as x, OllamaGenericClientError as y, OllamaIncompatibleModelError as z };
621
+ export { OllamaServerError as $, type AbortableAsyncIterable as A, type BinaryBody as B, type ChatStreamResult as C, type DoneEvent as D, type ErrorEvent as E, type FetchLike as F, type GenerateStreamResult as G, HttpClient as H, type InvokeRequest as I, type OllamaErrorResponseContext as J, OllamaGenericClientError as K, type Logger as L, type Middleware as M, NANOS_PER_MS as N, OllamaRuntime as O, type ProgressStreamResult as P, OllamaIncompatibleModelError as Q, type RequestLifecycleHook as R, type SchemaRef as S, type TokenUsage as T, OllamaMcpError as U, OllamaModelRoutingError as V, OllamaNetworkError as W, OllamaNotFoundError as X, OllamaQuotaExceededError as Y, OllamaRateLimitError as Z, OllamaRequestValidationError as _, type OperationDefinition as a, OllamaSkillInvalidError as a0, OllamaSkillNotFoundError as a1, OllamaTimeoutError as a2, OllamaToolTimeoutError as a3, OllamaToolValidationError as a4, OllamaUnsupportedCapabilityError as a5, type RequestContext as a6, type RequestLifecycleEvent as a7, type ResponseContext as a8, type ThinkingEvent as a9, type TokenEvent as aa, type ToolCallEvent as ab, composeMiddleware as ac, createConsoleLogger as ad, extractUsage as ae, mapError as af, parseSseStream as ag, type OllamaRuntimeOptions as b, type OllamaStreamEvent as c, type OllamaStreamEventType as d, type SseEvent as e, OllamaClientError as f, type RawUsageSource as g, type HttpBody as h, type HttpClientOptions as i, type HttpRequestOptions as j, type LifecycleErrorEvent as k, type LifecycleRetryEvent as l, type LifecycleStartEvent as m, type LifecycleSuccessEvent as n, type LogFn as o, type MessageEvent as p, type MiddlewareContext as q, NANOS_PER_SECOND as r, NOOP_LOGGER as s, type NextFunction as t, OllamaAbortError as u, OllamaAgentMaxIterationsError as v, OllamaAgentMaxToolCallsError as w, OllamaAuthError as x, type OllamaClientErrorOptions as y, type OllamaErrorRequestContext as z };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/skills/frontmatter.ts","../src/skills/compose.ts","../src/skills/skill-registry.ts"],"names":["readdir","join","readFile"],"mappings":"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","file":"skills.cjs","sourcesContent":["/**\n * Structured, typed error hierarchy for OllamaClient.\n */\n\nexport interface OllamaErrorRequestContext {\n readonly method?: string | undefined;\n readonly url?: string | undefined;\n readonly model?: string | undefined;\n}\n\nexport interface OllamaErrorResponseContext {\n readonly status?: number | undefined;\n readonly headers?: Record<string, string> | undefined;\n readonly body?: unknown;\n}\n\nexport interface OllamaClientErrorOptions extends ErrorOptions {\n readonly code: string;\n readonly status?: number | undefined;\n readonly retryable?: boolean | undefined;\n readonly request?: OllamaErrorRequestContext | undefined;\n readonly response?: OllamaErrorResponseContext | undefined;\n}\n\nexport class OllamaClientError extends Error {\n readonly code: string;\n readonly status?: number | undefined;\n readonly retryable: boolean;\n readonly request?: OllamaErrorRequestContext | undefined;\n readonly response?: OllamaErrorResponseContext | undefined;\n\n constructor(message: string, options: OllamaClientErrorOptions) {\n super(message, { cause: options.cause });\n this.name = this.constructor.name;\n this.code = options.code;\n this.status = options.status;\n this.retryable = options.retryable ?? false;\n this.request = options.request;\n this.response = options.response;\n }\n}\n\nexport class OllamaNetworkError extends OllamaClientError {\n constructor(\n message: string,\n options?: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> | undefined,\n ) {\n super(message, { ...options, code: 'network_error', retryable: true });\n }\n}\n\nexport class OllamaTimeoutError extends OllamaClientError {\n readonly timeoutMs?: number | undefined;\n constructor(\n message: string,\n options?:\n | (Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & { timeoutMs?: number | undefined })\n | undefined,\n ) {\n super(message, { ...options, code: 'timeout', retryable: true });\n this.timeoutMs = options?.timeoutMs;\n }\n}\n\nexport class OllamaAuthError extends OllamaClientError {\n constructor(\n message: string,\n options?: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> | undefined,\n ) {\n super(message, { ...options, code: 'auth_error', retryable: false });\n }\n}\n\nexport class OllamaNotFoundError extends OllamaClientError {\n constructor(\n message: string,\n options?: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> | undefined,\n ) {\n super(message, { ...options, code: 'not_found', retryable: false });\n }\n}\n\nexport class OllamaRateLimitError extends OllamaClientError {\n readonly retryAfterMs?: number | undefined;\n constructor(\n message: string,\n options?:\n | (Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & {\n retryAfterMs?: number | undefined;\n })\n | undefined,\n ) {\n super(message, { ...options, code: 'rate_limited', retryable: true });\n this.retryAfterMs = options?.retryAfterMs;\n }\n}\n\n/**\n * Thrown client-side, before a network request is made, by `QuotaManager.assertCanProceed`\n * (see `src/quota.ts`) when issuing the request would exceed a configured usage budget for\n * one of its rolling windows. This is distinct from `OllamaRateLimitError`, which reflects\n * the server's own 429 response — Ollama Cloud does not expose account-level quota via the\n * API, so `QuotaManager` tracks usage against budgets the caller configures locally and\n * fails fast rather than waiting for the server to reject the request.\n */\nexport class OllamaQuotaExceededError extends OllamaClientError {\n readonly windowId: string;\n readonly resetAt: number;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & {\n windowId: string;\n resetAt: number;\n },\n ) {\n super(message, { ...options, code: 'quota_exceeded', retryable: false });\n this.windowId = options.windowId;\n this.resetAt = options.resetAt;\n }\n}\n\nexport class OllamaServerError extends OllamaClientError {\n constructor(\n message: string,\n options?: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> | undefined,\n ) {\n super(message, { ...options, code: 'server_error', retryable: true });\n }\n}\n\nexport class OllamaAbortError extends OllamaClientError {\n constructor(\n message: string,\n options?: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> | undefined,\n ) {\n super(message, { ...options, code: 'aborted', retryable: false });\n }\n}\n\nexport class OllamaToolValidationError extends OllamaClientError {\n readonly toolName: string;\n readonly issues?: unknown;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & { toolName: string; issues?: unknown },\n ) {\n super(message, { ...options, code: 'tool_validation_error', retryable: false });\n this.toolName = options.toolName;\n this.issues = options.issues;\n }\n}\n\nexport class OllamaToolTimeoutError extends OllamaClientError {\n readonly toolName: string;\n readonly timeoutMs: number;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & {\n toolName: string;\n timeoutMs: number;\n },\n ) {\n super(message, { ...options, code: 'tool_timeout', retryable: false });\n this.toolName = options.toolName;\n this.timeoutMs = options.timeoutMs;\n }\n}\n\n/**\n * Thrown client-side, before a network request is made, when a request asks for a\n * capability an endpoint is known not to support (e.g. structured output `format` against\n * an Ollama Cloud endpoint — see `ModelCapabilities.supportsStructuredOutputRequest` in\n * `src/capabilities/capabilities.ts`). Its `code` is included in `DEFAULT_FAILOVER_CODES`\n * by default, so in a multi-endpoint setup it causes failover to the next candidate rather\n * than failing outright — it only surfaces to the caller if every candidate is rejected.\n */\nexport class OllamaUnsupportedCapabilityError extends OllamaClientError {\n readonly capability: string;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & { capability: string },\n ) {\n super(message, { ...options, code: 'unsupported_capability', retryable: false });\n this.capability = options.capability;\n }\n}\n\n/**\n * Thrown client-side, before any network call, when `config.endpoints` uses\n * `OllamaEndpoint.models` to scope endpoints/credentials to specific models and the\n * requested `model` isn't in any configured endpoint's allow-list. This is a routing\n * misconfiguration, not a connectivity problem — the SDK deliberately does not \"probe\"\n * unauthorized endpoints to find one that happens to work (that would burn quota on keys\n * that were never entitled to the model and produce non-deterministic startup behavior).\n */\nexport class OllamaModelRoutingError extends OllamaClientError {\n readonly model: string;\n readonly availableModels: readonly string[];\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & {\n model: string;\n availableModels: readonly string[];\n },\n ) {\n super(message, { ...options, code: 'model_routing_error', retryable: false });\n this.model = options.model;\n this.availableModels = options.availableModels;\n }\n}\n\n/**\n * Thrown before an agent tool loop starts when the selected model's /api/show metadata\n * does not advertise a capability required by the loop.\n */\nexport class OllamaIncompatibleModelError extends OllamaClientError {\n readonly model: string;\n readonly capability: string;\n readonly reportedCapabilities: readonly string[];\n\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & {\n model: string;\n capability: string;\n reportedCapabilities: readonly string[];\n },\n ) {\n super(message, { ...options, code: 'incompatible_model', retryable: false });\n this.model = options.model;\n this.capability = options.capability;\n this.reportedCapabilities = options.reportedCapabilities;\n }\n}\nexport class OllamaAgentMaxToolCallsError extends OllamaClientError {\n readonly maxToolCalls: number;\n readonly toolCallsExecuted: number;\n\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & {\n maxToolCalls: number;\n toolCallsExecuted: number;\n },\n ) {\n super(message, { ...options, code: 'agent_max_tool_calls_exceeded', retryable: false });\n this.maxToolCalls = options.maxToolCalls;\n this.toolCallsExecuted = options.toolCallsExecuted;\n }\n}\n\nexport class OllamaAgentMaxIterationsError extends OllamaClientError {\n readonly maxIterations: number;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & { maxIterations: number },\n ) {\n super(message, { ...options, code: 'agent_max_iterations_exceeded', retryable: false });\n this.maxIterations = options.maxIterations;\n }\n}\n\nexport class OllamaMcpError extends OllamaClientError {\n readonly mcpMethod: 'listTools' | 'callTool';\n readonly toolName?: string | undefined;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & {\n mcpMethod: 'listTools' | 'callTool';\n toolName?: string | undefined;\n },\n ) {\n super(message, { ...options, code: 'mcp_error', retryable: options.retryable ?? false });\n this.mcpMethod = options.mcpMethod;\n this.toolName = options.toolName;\n }\n}\n\nexport class OllamaSkillNotFoundError extends OllamaClientError {\n readonly skillName: string;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & { skillName: string },\n ) {\n super(message, { ...options, code: 'skill_not_found', retryable: false });\n this.skillName = options.skillName;\n }\n}\n\nexport class OllamaSkillInvalidError extends OllamaClientError {\n readonly skillName: string;\n readonly path?: string | undefined;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & {\n skillName: string;\n path?: string | undefined;\n },\n ) {\n super(message, { ...options, code: 'skill_invalid', retryable: false });\n this.skillName = options.skillName;\n this.path = options.path;\n }\n}\n\nexport class OllamaGenericClientError extends OllamaClientError {\n constructor(message: string, options?: Omit<OllamaClientErrorOptions, 'code'> | undefined) {\n super(message, { ...options, code: 'client_error' });\n }\n}\n\nfunction isDomAbortError(error: unknown): error is DOMException {\n return (\n typeof DOMException !== 'undefined' &&\n error instanceof DOMException &&\n error.name === 'AbortError'\n );\n}\n\nfunction statusToError(\n status: number,\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code' | 'status'>,\n): OllamaClientError {\n if (status === 401 || status === 403) {\n return new OllamaAuthError(message, { ...options, status });\n }\n if (status === 404) {\n return new OllamaNotFoundError(message, { ...options, status });\n }\n if (status === 429) {\n return new OllamaRateLimitError(message, { ...options, status });\n }\n if (status >= 500) {\n return new OllamaServerError(message, { ...options, status });\n }\n return new OllamaGenericClientError(message, { ...options, status });\n}\n\n/**\n * Maps arbitrary thrown exceptions into structured OllamaClientError instances.\n */\nexport function mapError(\n error: unknown,\n context: {\n request?: OllamaErrorRequestContext | undefined;\n response?: OllamaErrorResponseContext | undefined;\n } = {},\n): OllamaClientError {\n if (error instanceof OllamaClientError) {\n return error;\n }\n if (isDomAbortError(error)) {\n return new OllamaAbortError(error.message || 'Request was aborted', {\n cause: error,\n request: context.request,\n });\n }\n if (error instanceof TypeError) {\n return new OllamaNetworkError(error.message || 'Network request failed', {\n cause: error,\n request: context.request,\n });\n }\n if (context.response?.status !== undefined) {\n const message = error instanceof Error ? error.message : String(error);\n return statusToError(context.response.status, message, {\n cause: error,\n request: context.request,\n response: context.response,\n });\n }\n const message = error instanceof Error ? error.message : String(error);\n return new OllamaGenericClientError(message, {\n cause: error,\n request: context.request,\n response: context.response,\n });\n}\n","/**\n * Lightweight frontmatter parser for SKILL.md files.\n */\n\nimport { OllamaSkillInvalidError } from '../errors.js';\nimport type { SkillFrontmatter } from './types.js';\n\nexport interface ParsedFrontmatter {\n readonly frontmatter: SkillFrontmatter;\n readonly body: string;\n}\n\nfunction parseYamlValue(raw: string): unknown {\n const trimmed = raw.trim();\n if (trimmed === 'true') return true;\n if (trimmed === 'false') return false;\n if (!Number.isNaN(Number(trimmed)) && trimmed !== '') return Number(trimmed);\n if (\n (trimmed.startsWith('\"') && trimmed.endsWith('\"')) ||\n (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\"))\n ) {\n return trimmed.slice(1, -1);\n }\n return trimmed;\n}\n\nfunction parseYamlBlock(yamlText: string): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n const lines = yamlText.split('\\n');\n let currentKey: string | undefined;\n let currentList: unknown[] | undefined;\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n\n if (trimmed.startsWith('- ') && currentKey) {\n if (!currentList) {\n currentList = [];\n result[currentKey] = currentList;\n }\n currentList.push(parseYamlValue(trimmed.slice(2)));\n continue;\n }\n\n currentList = undefined;\n const colonIndex = line.indexOf(':');\n if (colonIndex > 0) {\n const key = line.slice(0, colonIndex).trim();\n const valStr = line.slice(colonIndex + 1).trim();\n currentKey = key;\n if (valStr.length > 0) {\n result[key] = parseYamlValue(valStr);\n }\n }\n }\n\n return result;\n}\n\nexport function parseFrontmatter(source: string, path = ''): ParsedFrontmatter {\n const match = source.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?([\\s\\S]*)$/);\n if (!match) {\n throw new OllamaSkillInvalidError('Missing YAML frontmatter delimiters (---)', {\n skillName: path || 'unknown',\n path,\n });\n }\n\n const rawYaml = match[1] ?? '';\n const body = match[2]?.trim() ?? '';\n const parsed = parseYamlBlock(rawYaml);\n\n if (!parsed['name'] || typeof parsed['name'] !== 'string') {\n throw new OllamaSkillInvalidError('Frontmatter missing required string \"name\"', {\n skillName: String(parsed['name'] ?? 'unknown'),\n path,\n });\n }\n if (!parsed['description'] || typeof parsed['description'] !== 'string') {\n throw new OllamaSkillInvalidError('Frontmatter missing required string \"description\"', {\n skillName: parsed['name'],\n path,\n });\n }\n\n return {\n frontmatter: parsed as unknown as SkillFrontmatter,\n body,\n };\n}\n","/**\n * Skill composition and context injection.\n */\n\nimport type { Message } from '../types.js';\nimport type { ToolRegistry } from '../tools/registry.js';\nimport type { Skill } from './types.js';\n\nexport interface ApplySkillOptions {\n readonly messages: readonly Message[];\n readonly tools?: ToolRegistry;\n}\n\nexport interface AppliedSkillResult {\n readonly messages: readonly Message[];\n readonly tools?: ToolRegistry;\n}\n\n/**\n * Injects a skill's body into messages as a system prompt and applies allowed tool filters.\n */\nexport function applySkill(skill: Skill, options: ApplySkillOptions): AppliedSkillResult {\n const systemPrompt = `[Skill: ${skill.name}]\\n${skill.description}\\n\\n${skill.body}`;\n const messages = [...options.messages];\n const systemIndex = messages.findIndex((m) => m.role === 'system');\n\n if (systemIndex >= 0) {\n const existing = messages[systemIndex];\n if (existing) {\n messages[systemIndex] = {\n role: 'system',\n content: `${existing.content}\\n\\n${systemPrompt}`,\n };\n }\n } else {\n messages.unshift({ role: 'system', content: systemPrompt });\n }\n\n return {\n messages,\n ...(options.tools !== undefined ? { tools: options.tools } : {}),\n };\n}\n","/**\n * Node.js filesystem skill registry for SKILL.md packages.\n */\n\nimport { readdir, readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { OllamaSkillNotFoundError } from '../errors.js';\nimport { parseFrontmatter } from './frontmatter.js';\nimport type { Skill, SkillSummary } from './types.js';\n\nexport interface SkillRegistryOptions {\n readonly directory: string;\n}\n\nexport class SkillRegistry {\n readonly directory: string;\n\n constructor(options: SkillRegistryOptions) {\n this.directory = options.directory;\n }\n\n async list(): Promise<SkillSummary[]> {\n const entries = await readdir(this.directory, { withFileTypes: true });\n const summaries: SkillSummary[] = [];\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const skillPath = join(this.directory, entry.name, 'SKILL.md');\n try {\n const content = await readFile(skillPath, 'utf-8');\n const parsed = parseFrontmatter(content, skillPath);\n summaries.push({\n name: parsed.frontmatter.name,\n description: parsed.frontmatter.description,\n path: skillPath,\n });\n } catch {\n // Skip directories without valid SKILL.md\n }\n }\n\n return summaries;\n }\n\n async load(name: string): Promise<Skill> {\n const skillPath = join(this.directory, name, 'SKILL.md');\n try {\n const content = await readFile(skillPath, 'utf-8');\n const parsed = parseFrontmatter(content, skillPath);\n return {\n name: parsed.frontmatter.name,\n description: parsed.frontmatter.description,\n path: skillPath,\n frontmatter: parsed.frontmatter,\n body: parsed.body,\n allowedTools: parsed.frontmatter['allowed-tools'],\n };\n } catch (err) {\n throw new OllamaSkillNotFoundError(`Skill \"${name}\" not found at ${skillPath}`, {\n skillName: name,\n cause: err,\n });\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/skills/frontmatter.ts","../src/skills/compose.ts","../src/skills/skill-registry.ts"],"names":["readdir","join","readFile"],"mappings":"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","file":"skills.cjs","sourcesContent":["/**\n * Structured, typed error hierarchy for OllamaClient.\n */\n\nimport type { z } from 'zod';\n\nexport interface OllamaErrorRequestContext {\n readonly method?: string | undefined;\n readonly url?: string | undefined;\n readonly model?: string | undefined;\n}\n\nexport interface OllamaErrorResponseContext {\n readonly status?: number | undefined;\n readonly headers?: Record<string, string> | undefined;\n readonly body?: unknown;\n}\n\nexport interface OllamaClientErrorOptions extends ErrorOptions {\n readonly code: string;\n readonly status?: number | undefined;\n readonly retryable?: boolean | undefined;\n readonly request?: OllamaErrorRequestContext | undefined;\n readonly response?: OllamaErrorResponseContext | undefined;\n}\n\nexport class OllamaClientError extends Error {\n readonly code: string;\n readonly status?: number | undefined;\n readonly retryable: boolean;\n readonly request?: OllamaErrorRequestContext | undefined;\n readonly response?: OllamaErrorResponseContext | undefined;\n\n constructor(message: string, options: OllamaClientErrorOptions) {\n super(message, { cause: options.cause });\n this.name = this.constructor.name;\n this.code = options.code;\n this.status = options.status;\n this.retryable = options.retryable ?? false;\n this.request = options.request;\n this.response = options.response;\n }\n}\n\nexport class OllamaNetworkError extends OllamaClientError {\n constructor(\n message: string,\n options?: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> | undefined,\n ) {\n super(message, { ...options, code: 'network_error', retryable: true });\n }\n}\n\nexport class OllamaTimeoutError extends OllamaClientError {\n readonly timeoutMs?: number | undefined;\n constructor(\n message: string,\n options?:\n | (Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & { timeoutMs?: number | undefined })\n | undefined,\n ) {\n super(message, { ...options, code: 'timeout', retryable: true });\n this.timeoutMs = options?.timeoutMs;\n }\n}\n\nexport class OllamaAuthError extends OllamaClientError {\n constructor(\n message: string,\n options?: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> | undefined,\n ) {\n super(message, { ...options, code: 'auth_error', retryable: false });\n }\n}\n\nexport class OllamaNotFoundError extends OllamaClientError {\n constructor(\n message: string,\n options?: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> | undefined,\n ) {\n super(message, { ...options, code: 'not_found', retryable: false });\n }\n}\n\nexport class OllamaRateLimitError extends OllamaClientError {\n readonly retryAfterMs?: number | undefined;\n constructor(\n message: string,\n options?:\n | (Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & {\n retryAfterMs?: number | undefined;\n })\n | undefined,\n ) {\n super(message, { ...options, code: 'rate_limited', retryable: true });\n this.retryAfterMs = options?.retryAfterMs;\n }\n}\n\n/**\n * Thrown client-side, before a network request is made, by `QuotaManager.assertCanProceed`\n * (see `src/quota.ts`) when issuing the request would exceed a configured usage budget for\n * one of its rolling windows. This is distinct from `OllamaRateLimitError`, which reflects\n * the server's own 429 response — Ollama Cloud does not expose account-level quota via the\n * API, so `QuotaManager` tracks usage against budgets the caller configures locally and\n * fails fast rather than waiting for the server to reject the request.\n */\nexport class OllamaQuotaExceededError extends OllamaClientError {\n readonly windowId: string;\n readonly resetAt: number;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & {\n windowId: string;\n resetAt: number;\n },\n ) {\n super(message, { ...options, code: 'quota_exceeded', retryable: false });\n this.windowId = options.windowId;\n this.resetAt = options.resetAt;\n }\n}\n\nexport class OllamaServerError extends OllamaClientError {\n constructor(\n message: string,\n options?: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> | undefined,\n ) {\n super(message, { ...options, code: 'server_error', retryable: true });\n }\n}\n\nexport class OllamaAbortError extends OllamaClientError {\n constructor(\n message: string,\n options?: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> | undefined,\n ) {\n super(message, { ...options, code: 'aborted', retryable: false });\n }\n}\n\nexport class OllamaToolValidationError extends OllamaClientError {\n readonly toolName: string;\n readonly issues?: unknown;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & { toolName: string; issues?: unknown },\n ) {\n super(message, { ...options, code: 'tool_validation_error', retryable: false });\n this.toolName = options.toolName;\n this.issues = options.issues;\n }\n}\n\n/**\n * Thrown by `OllamaRuntime.invoke` when `validateRequests: true` is set and\n * the request body fails Zod validation against the operation's registered\n * schema. See ADR 0020 (runtime Zod validation).\n *\n * The error carries the original Zod issues so callers can inspect which\n * fields failed. No HTTP request is made when this error is thrown.\n */\nexport class OllamaRequestValidationError extends OllamaClientError {\n readonly operationId: string;\n readonly issues: readonly z.ZodIssue[];\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & {\n operationId: string;\n issues: readonly z.ZodIssue[];\n },\n ) {\n super(message, { ...options, code: 'request_validation_error', retryable: false });\n this.operationId = options.operationId;\n this.issues = options.issues;\n }\n}\n\nexport class OllamaToolTimeoutError extends OllamaClientError {\n readonly toolName: string;\n readonly timeoutMs: number;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & {\n toolName: string;\n timeoutMs: number;\n },\n ) {\n super(message, { ...options, code: 'tool_timeout', retryable: false });\n this.toolName = options.toolName;\n this.timeoutMs = options.timeoutMs;\n }\n}\n\n/**\n * Thrown client-side, before a network request is made, when a request asks for a\n * capability an endpoint is known not to support (e.g. structured output `format` against\n * an Ollama Cloud endpoint — see `ModelCapabilities.supportsStructuredOutputRequest` in\n * `src/capabilities/capabilities.ts`). Its `code` is included in `DEFAULT_FAILOVER_CODES`\n * by default, so in a multi-endpoint setup it causes failover to the next candidate rather\n * than failing outright — it only surfaces to the caller if every candidate is rejected.\n */\nexport class OllamaUnsupportedCapabilityError extends OllamaClientError {\n readonly capability: string;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & { capability: string },\n ) {\n super(message, { ...options, code: 'unsupported_capability', retryable: false });\n this.capability = options.capability;\n }\n}\n\n/**\n * Thrown client-side, before any network call, when `config.endpoints` uses\n * `OllamaEndpoint.models` to scope endpoints/credentials to specific models and the\n * requested `model` isn't in any configured endpoint's allow-list. This is a routing\n * misconfiguration, not a connectivity problem — the SDK deliberately does not \"probe\"\n * unauthorized endpoints to find one that happens to work (that would burn quota on keys\n * that were never entitled to the model and produce non-deterministic startup behavior).\n */\nexport class OllamaModelRoutingError extends OllamaClientError {\n readonly model: string;\n readonly availableModels: readonly string[];\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & {\n model: string;\n availableModels: readonly string[];\n },\n ) {\n super(message, { ...options, code: 'model_routing_error', retryable: false });\n this.model = options.model;\n this.availableModels = options.availableModels;\n }\n}\n\n/**\n * Thrown before an agent tool loop starts when the selected model's /api/show metadata\n * does not advertise a capability required by the loop.\n */\nexport class OllamaIncompatibleModelError extends OllamaClientError {\n readonly model: string;\n readonly capability: string;\n readonly reportedCapabilities: readonly string[];\n\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & {\n model: string;\n capability: string;\n reportedCapabilities: readonly string[];\n },\n ) {\n super(message, { ...options, code: 'incompatible_model', retryable: false });\n this.model = options.model;\n this.capability = options.capability;\n this.reportedCapabilities = options.reportedCapabilities;\n }\n}\nexport class OllamaAgentMaxToolCallsError extends OllamaClientError {\n readonly maxToolCalls: number;\n readonly toolCallsExecuted: number;\n\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & {\n maxToolCalls: number;\n toolCallsExecuted: number;\n },\n ) {\n super(message, { ...options, code: 'agent_max_tool_calls_exceeded', retryable: false });\n this.maxToolCalls = options.maxToolCalls;\n this.toolCallsExecuted = options.toolCallsExecuted;\n }\n}\n\nexport class OllamaAgentMaxIterationsError extends OllamaClientError {\n readonly maxIterations: number;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & { maxIterations: number },\n ) {\n super(message, { ...options, code: 'agent_max_iterations_exceeded', retryable: false });\n this.maxIterations = options.maxIterations;\n }\n}\n\nexport class OllamaMcpError extends OllamaClientError {\n readonly mcpMethod: 'listTools' | 'callTool';\n readonly toolName?: string | undefined;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & {\n mcpMethod: 'listTools' | 'callTool';\n toolName?: string | undefined;\n },\n ) {\n super(message, { ...options, code: 'mcp_error', retryable: options.retryable ?? false });\n this.mcpMethod = options.mcpMethod;\n this.toolName = options.toolName;\n }\n}\n\nexport class OllamaSkillNotFoundError extends OllamaClientError {\n readonly skillName: string;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & { skillName: string },\n ) {\n super(message, { ...options, code: 'skill_not_found', retryable: false });\n this.skillName = options.skillName;\n }\n}\n\nexport class OllamaSkillInvalidError extends OllamaClientError {\n readonly skillName: string;\n readonly path?: string | undefined;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & {\n skillName: string;\n path?: string | undefined;\n },\n ) {\n super(message, { ...options, code: 'skill_invalid', retryable: false });\n this.skillName = options.skillName;\n this.path = options.path;\n }\n}\n\nexport class OllamaGenericClientError extends OllamaClientError {\n constructor(message: string, options?: Omit<OllamaClientErrorOptions, 'code'> | undefined) {\n super(message, { ...options, code: 'client_error' });\n }\n}\n\nfunction isDomAbortError(error: unknown): error is DOMException {\n return (\n typeof DOMException !== 'undefined' &&\n error instanceof DOMException &&\n error.name === 'AbortError'\n );\n}\n\nfunction statusToError(\n status: number,\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code' | 'status'>,\n): OllamaClientError {\n if (status === 401 || status === 403) {\n return new OllamaAuthError(message, { ...options, status });\n }\n if (status === 404) {\n return new OllamaNotFoundError(message, { ...options, status });\n }\n if (status === 429) {\n return new OllamaRateLimitError(message, { ...options, status });\n }\n if (status >= 500) {\n return new OllamaServerError(message, { ...options, status });\n }\n return new OllamaGenericClientError(message, { ...options, status });\n}\n\n/**\n * Maps arbitrary thrown exceptions into structured OllamaClientError instances.\n */\nexport function mapError(\n error: unknown,\n context: {\n request?: OllamaErrorRequestContext | undefined;\n response?: OllamaErrorResponseContext | undefined;\n } = {},\n): OllamaClientError {\n if (error instanceof OllamaClientError) {\n return error;\n }\n if (isDomAbortError(error)) {\n return new OllamaAbortError(error.message || 'Request was aborted', {\n cause: error,\n request: context.request,\n });\n }\n if (error instanceof TypeError) {\n return new OllamaNetworkError(error.message || 'Network request failed', {\n cause: error,\n request: context.request,\n });\n }\n if (context.response?.status !== undefined) {\n const message = error instanceof Error ? error.message : String(error);\n return statusToError(context.response.status, message, {\n cause: error,\n request: context.request,\n response: context.response,\n });\n }\n const message = error instanceof Error ? error.message : String(error);\n return new OllamaGenericClientError(message, {\n cause: error,\n request: context.request,\n response: context.response,\n });\n}\n","/**\n * Lightweight frontmatter parser for SKILL.md files.\n */\n\nimport { OllamaSkillInvalidError } from '../errors.js';\nimport type { SkillFrontmatter } from './types.js';\n\nexport interface ParsedFrontmatter {\n readonly frontmatter: SkillFrontmatter;\n readonly body: string;\n}\n\nfunction parseYamlValue(raw: string): unknown {\n const trimmed = raw.trim();\n if (trimmed === 'true') return true;\n if (trimmed === 'false') return false;\n if (!Number.isNaN(Number(trimmed)) && trimmed !== '') return Number(trimmed);\n if (\n (trimmed.startsWith('\"') && trimmed.endsWith('\"')) ||\n (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\"))\n ) {\n return trimmed.slice(1, -1);\n }\n return trimmed;\n}\n\nfunction parseYamlBlock(yamlText: string): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n const lines = yamlText.split('\\n');\n let currentKey: string | undefined;\n let currentList: unknown[] | undefined;\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n\n if (trimmed.startsWith('- ') && currentKey) {\n if (!currentList) {\n currentList = [];\n result[currentKey] = currentList;\n }\n currentList.push(parseYamlValue(trimmed.slice(2)));\n continue;\n }\n\n currentList = undefined;\n const colonIndex = line.indexOf(':');\n if (colonIndex > 0) {\n const key = line.slice(0, colonIndex).trim();\n const valStr = line.slice(colonIndex + 1).trim();\n currentKey = key;\n if (valStr.length > 0) {\n result[key] = parseYamlValue(valStr);\n }\n }\n }\n\n return result;\n}\n\nexport function parseFrontmatter(source: string, path = ''): ParsedFrontmatter {\n const match = source.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?([\\s\\S]*)$/);\n if (!match) {\n throw new OllamaSkillInvalidError('Missing YAML frontmatter delimiters (---)', {\n skillName: path || 'unknown',\n path,\n });\n }\n\n const rawYaml = match[1] ?? '';\n const body = match[2]?.trim() ?? '';\n const parsed = parseYamlBlock(rawYaml);\n\n if (!parsed['name'] || typeof parsed['name'] !== 'string') {\n throw new OllamaSkillInvalidError('Frontmatter missing required string \"name\"', {\n skillName: String(parsed['name'] ?? 'unknown'),\n path,\n });\n }\n if (!parsed['description'] || typeof parsed['description'] !== 'string') {\n throw new OllamaSkillInvalidError('Frontmatter missing required string \"description\"', {\n skillName: parsed['name'],\n path,\n });\n }\n\n return {\n frontmatter: parsed as unknown as SkillFrontmatter,\n body,\n };\n}\n","/**\n * Skill composition and context injection.\n */\n\nimport type { Message } from '../types.js';\nimport type { ToolRegistry } from '../tools/registry.js';\nimport type { Skill } from './types.js';\n\nexport interface ApplySkillOptions {\n readonly messages: readonly Message[];\n readonly tools?: ToolRegistry;\n}\n\nexport interface AppliedSkillResult {\n readonly messages: readonly Message[];\n readonly tools?: ToolRegistry;\n}\n\n/**\n * Injects a skill's body into messages as a system prompt and applies allowed tool filters.\n */\nexport function applySkill(skill: Skill, options: ApplySkillOptions): AppliedSkillResult {\n const systemPrompt = `[Skill: ${skill.name}]\\n${skill.description}\\n\\n${skill.body}`;\n const messages = [...options.messages];\n const systemIndex = messages.findIndex((m) => m.role === 'system');\n\n if (systemIndex >= 0) {\n const existing = messages[systemIndex];\n if (existing) {\n messages[systemIndex] = {\n role: 'system',\n content: `${existing.content}\\n\\n${systemPrompt}`,\n };\n }\n } else {\n messages.unshift({ role: 'system', content: systemPrompt });\n }\n\n return {\n messages,\n ...(options.tools !== undefined ? { tools: options.tools } : {}),\n };\n}\n","/**\n * Node.js filesystem skill registry for SKILL.md packages.\n */\n\nimport { readdir, readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { OllamaSkillNotFoundError } from '../errors.js';\nimport { parseFrontmatter } from './frontmatter.js';\nimport type { Skill, SkillSummary } from './types.js';\n\nexport interface SkillRegistryOptions {\n readonly directory: string;\n}\n\nexport class SkillRegistry {\n readonly directory: string;\n\n constructor(options: SkillRegistryOptions) {\n this.directory = options.directory;\n }\n\n async list(): Promise<SkillSummary[]> {\n const entries = await readdir(this.directory, { withFileTypes: true });\n const summaries: SkillSummary[] = [];\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const skillPath = join(this.directory, entry.name, 'SKILL.md');\n try {\n const content = await readFile(skillPath, 'utf-8');\n const parsed = parseFrontmatter(content, skillPath);\n summaries.push({\n name: parsed.frontmatter.name,\n description: parsed.frontmatter.description,\n path: skillPath,\n });\n } catch {\n // Skip directories without valid SKILL.md\n }\n }\n\n return summaries;\n }\n\n async load(name: string): Promise<Skill> {\n const skillPath = join(this.directory, name, 'SKILL.md');\n try {\n const content = await readFile(skillPath, 'utf-8');\n const parsed = parseFrontmatter(content, skillPath);\n return {\n name: parsed.frontmatter.name,\n description: parsed.frontmatter.description,\n path: skillPath,\n frontmatter: parsed.frontmatter,\n body: parsed.body,\n allowedTools: parsed.frontmatter['allowed-tools'],\n };\n } catch (err) {\n throw new OllamaSkillNotFoundError(`Skill \"${name}\" not found at ${skillPath}`, {\n skillName: name,\n cause: err,\n });\n }\n }\n}\n"]}
package/dist/skills.d.cts CHANGED
@@ -1,6 +1,6 @@
1
- import { S as SkillSummary, a as Skill } from './compose-BR70yb4W.cjs';
2
- export { A as AppliedSkillResult, b as ApplySkillOptions, P as ParsedFrontmatter, c as SkillFrontmatter, d as applySkill, p as parseFrontmatter } from './compose-BR70yb4W.cjs';
3
- import './types-BQhgW-du.cjs';
1
+ import { g as SkillSummary, S as Skill } from './compose-DS-UWFx8.cjs';
2
+ export { d as AppliedSkillResult, e as ApplySkillOptions, P as ParsedFrontmatter, f as SkillFrontmatter, l as applySkill, p as parseFrontmatter } from './compose-DS-UWFx8.cjs';
3
+ import './types-5PAjLoCp.cjs';
4
4
  import 'zod';
5
5
 
6
6
  /**
package/dist/skills.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { S as SkillSummary, a as Skill } from './compose-DfAqKAFj.js';
2
- export { A as AppliedSkillResult, b as ApplySkillOptions, P as ParsedFrontmatter, c as SkillFrontmatter, d as applySkill, p as parseFrontmatter } from './compose-DfAqKAFj.js';
3
- import './types-BQhgW-du.js';
1
+ import { g as SkillSummary, S as Skill } from './compose-DLStUfaF.js';
2
+ export { d as AppliedSkillResult, e as ApplySkillOptions, P as ParsedFrontmatter, f as SkillFrontmatter, l as applySkill, p as parseFrontmatter } from './compose-DLStUfaF.js';
3
+ import './types-5PAjLoCp.js';
4
4
  import 'zod';
5
5
 
6
6
  /**
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/skills/frontmatter.ts","../src/skills/compose.ts","../src/skills/skill-registry.ts"],"names":[],"mappings":";;;;AAwBO,IAAM,iBAAA,GAAN,cAAgC,KAAA,CAAM;AAAA,EAClC,IAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EAET,WAAA,CAAY,SAAiB,OAAA,EAAmC;AAC9D,IAAA,KAAA,CAAM,OAAA,EAAS,EAAE,KAAA,EAAO,OAAA,CAAQ,OAAO,CAAA;AACvC,IAAA,IAAA,CAAK,IAAA,GAAO,KAAK,WAAA,CAAY,IAAA;AAC7B,IAAA,IAAA,CAAK,OAAO,OAAA,CAAQ,IAAA;AACpB,IAAA,IAAA,CAAK,SAAS,OAAA,CAAQ,MAAA;AACtB,IAAA,IAAA,CAAK,SAAA,GAAY,QAAQ,SAAA,IAAa,KAAA;AACtC,IAAA,IAAA,CAAK,UAAU,OAAA,CAAQ,OAAA;AACvB,IAAA,IAAA,CAAK,WAAW,OAAA,CAAQ,QAAA;AAAA,EAC1B;AACF,CAAA;AA8OO,IAAM,wBAAA,GAAN,cAAuC,iBAAA,CAAkB;AAAA,EACrD,SAAA;AAAA,EACT,WAAA,CACE,SACA,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,EAAE,GAAG,OAAA,EAAS,MAAM,iBAAA,EAAmB,SAAA,EAAW,OAAO,CAAA;AACxE,IAAA,IAAA,CAAK,YAAY,OAAA,CAAQ,SAAA;AAAA,EAC3B;AACF,CAAA;AAEO,IAAM,uBAAA,GAAN,cAAsC,iBAAA,CAAkB;AAAA,EACpD,SAAA;AAAA,EACA,IAAA;AAAA,EACT,WAAA,CACE,SACA,OAAA,EAIA;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,EAAE,GAAG,OAAA,EAAS,MAAM,eAAA,EAAiB,SAAA,EAAW,OAAO,CAAA;AACtE,IAAA,IAAA,CAAK,YAAY,OAAA,CAAQ,SAAA;AACzB,IAAA,IAAA,CAAK,OAAO,OAAA,CAAQ,IAAA;AAAA,EACtB;AACF,CAAA;;;ACnSA,SAAS,eAAe,GAAA,EAAsB;AAC5C,EAAA,MAAM,OAAA,GAAU,IAAI,IAAA,EAAK;AACzB,EAAA,IAAI,OAAA,KAAY,QAAQ,OAAO,IAAA;AAC/B,EAAA,IAAI,OAAA,KAAY,SAAS,OAAO,KAAA;AAChC,EAAA,IAAI,CAAC,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,OAAO,CAAC,CAAA,IAAK,OAAA,KAAY,EAAA,EAAI,OAAO,MAAA,CAAO,OAAO,CAAA;AAC3E,EAAA,IACG,OAAA,CAAQ,UAAA,CAAW,GAAG,CAAA,IAAK,QAAQ,QAAA,CAAS,GAAG,CAAA,IAC/C,OAAA,CAAQ,WAAW,GAAG,CAAA,IAAK,OAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,EAChD;AACA,IAAA,OAAO,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAAA,EAC5B;AACA,EAAA,OAAO,OAAA;AACT;AAEA,SAAS,eAAe,QAAA,EAA2C;AACjE,EAAA,MAAM,SAAkC,EAAC;AACzC,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,KAAA,CAAM,IAAI,CAAA;AACjC,EAAA,IAAI,UAAA;AACJ,EAAA,IAAI,WAAA;AAEJ,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,MAAM,OAAA,GAAU,KAAK,IAAA,EAAK;AAC1B,IAAA,IAAI,CAAC,OAAA,IAAW,OAAA,CAAQ,UAAA,CAAW,GAAG,CAAA,EAAG;AAEzC,IAAA,IAAI,OAAA,CAAQ,UAAA,CAAW,IAAI,CAAA,IAAK,UAAA,EAAY;AAC1C,MAAA,IAAI,CAAC,WAAA,EAAa;AAChB,QAAA,WAAA,GAAc,EAAC;AACf,QAAA,MAAA,CAAO,UAAU,CAAA,GAAI,WAAA;AAAA,MACvB;AACA,MAAA,WAAA,CAAY,KAAK,cAAA,CAAe,OAAA,CAAQ,KAAA,CAAM,CAAC,CAAC,CAAC,CAAA;AACjD,MAAA;AAAA,IACF;AAEA,IAAA,WAAA,GAAc,MAAA;AACd,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,OAAA,CAAQ,GAAG,CAAA;AACnC,IAAA,IAAI,aAAa,CAAA,EAAG;AAClB,MAAA,MAAM,MAAM,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,UAAU,EAAE,IAAA,EAAK;AAC3C,MAAA,MAAM,SAAS,IAAA,CAAK,KAAA,CAAM,UAAA,GAAa,CAAC,EAAE,IAAA,EAAK;AAC/C,MAAA,UAAA,GAAa,GAAA;AACb,MAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACrB,QAAA,MAAA,CAAO,GAAG,CAAA,GAAI,cAAA,CAAe,MAAM,CAAA;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAEO,SAAS,gBAAA,CAAiB,MAAA,EAAgB,IAAA,GAAO,EAAA,EAAuB;AAC7E,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,6CAA6C,CAAA;AACxE,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,MAAM,IAAI,wBAAwB,2CAAA,EAA6C;AAAA,MAC7E,WAAW,IAAA,IAAQ,SAAA;AAAA,MACnB;AAAA,KACD,CAAA;AAAA,EACH;AAEA,EAAA,MAAM,OAAA,GAAU,KAAA,CAAM,CAAC,CAAA,IAAK,EAAA;AAC5B,EAAA,MAAM,IAAA,GAAO,KAAA,CAAM,CAAC,CAAA,EAAG,MAAK,IAAK,EAAA;AACjC,EAAA,MAAM,MAAA,GAAS,eAAe,OAAO,CAAA;AAErC,EAAA,IAAI,CAAC,OAAO,MAAM,CAAA,IAAK,OAAO,MAAA,CAAO,MAAM,MAAM,QAAA,EAAU;AACzD,IAAA,MAAM,IAAI,wBAAwB,4CAAA,EAA8C;AAAA,MAC9E,SAAA,EAAW,MAAA,CAAO,MAAA,CAAO,MAAM,KAAK,SAAS,CAAA;AAAA,MAC7C;AAAA,KACD,CAAA;AAAA,EACH;AACA,EAAA,IAAI,CAAC,OAAO,aAAa,CAAA,IAAK,OAAO,MAAA,CAAO,aAAa,MAAM,QAAA,EAAU;AACvE,IAAA,MAAM,IAAI,wBAAwB,mDAAA,EAAqD;AAAA,MACrF,SAAA,EAAW,OAAO,MAAM,CAAA;AAAA,MACxB;AAAA,KACD,CAAA;AAAA,EACH;AAEA,EAAA,OAAO;AAAA,IACL,WAAA,EAAa,MAAA;AAAA,IACb;AAAA,GACF;AACF;;;ACrEO,SAAS,UAAA,CAAW,OAAc,OAAA,EAAgD;AACvF,EAAA,MAAM,YAAA,GAAe,CAAA,QAAA,EAAW,KAAA,CAAM,IAAI,CAAA;AAAA,EAAM,MAAM,WAAW;;AAAA,EAAO,MAAM,IAAI,CAAA,CAAA;AAClF,EAAA,MAAM,QAAA,GAAW,CAAC,GAAG,OAAA,CAAQ,QAAQ,CAAA;AACrC,EAAA,MAAM,cAAc,QAAA,CAAS,SAAA,CAAU,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,QAAQ,CAAA;AAEjE,EAAA,IAAI,eAAe,CAAA,EAAG;AACpB,IAAA,MAAM,QAAA,GAAW,SAAS,WAAW,CAAA;AACrC,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,QAAA,CAAS,WAAW,CAAA,GAAI;AAAA,QACtB,IAAA,EAAM,QAAA;AAAA,QACN,OAAA,EAAS,CAAA,EAAG,QAAA,CAAS,OAAO;;AAAA,EAAO,YAAY,CAAA;AAAA,OACjD;AAAA,IACF;AAAA,EACF,CAAA,MAAO;AACL,IAAA,QAAA,CAAS,QAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,OAAA,EAAS,cAAc,CAAA;AAAA,EAC5D;AAEA,EAAA,OAAO;AAAA,IACL,QAAA;AAAA,IACA,GAAI,QAAQ,KAAA,KAAU,MAAA,GAAY,EAAE,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAM,GAAI;AAAC,GAChE;AACF;AC5BO,IAAM,gBAAN,MAAoB;AAAA,EAChB,SAAA;AAAA,EAET,YAAY,OAAA,EAA+B;AACzC,IAAA,IAAA,CAAK,YAAY,OAAA,CAAQ,SAAA;AAAA,EAC3B;AAAA,EAEA,MAAM,IAAA,GAAgC;AACpC,IAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,IAAA,CAAK,WAAW,EAAE,aAAA,EAAe,MAAM,CAAA;AACrE,IAAA,MAAM,YAA4B,EAAC;AAEnC,IAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,MAAA,IAAI,CAAC,KAAA,CAAM,WAAA,EAAY,EAAG;AAC1B,MAAA,MAAM,YAAY,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,KAAA,CAAM,MAAM,UAAU,CAAA;AAC7D,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,GAAU,MAAM,QAAA,CAAS,SAAA,EAAW,OAAO,CAAA;AACjD,QAAA,MAAM,MAAA,GAAS,gBAAA,CAAiB,OAAA,EAAS,SAAS,CAAA;AAClD,QAAA,SAAA,CAAU,IAAA,CAAK;AAAA,UACb,IAAA,EAAM,OAAO,WAAA,CAAY,IAAA;AAAA,UACzB,WAAA,EAAa,OAAO,WAAA,CAAY,WAAA;AAAA,UAChC,IAAA,EAAM;AAAA,SACP,CAAA;AAAA,MACH,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAEA,IAAA,OAAO,SAAA;AAAA,EACT;AAAA,EAEA,MAAM,KAAK,IAAA,EAA8B;AACvC,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,MAAM,UAAU,CAAA;AACvD,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,MAAM,QAAA,CAAS,SAAA,EAAW,OAAO,CAAA;AACjD,MAAA,MAAM,MAAA,GAAS,gBAAA,CAAiB,OAAA,EAAS,SAAS,CAAA;AAClD,MAAA,OAAO;AAAA,QACL,IAAA,EAAM,OAAO,WAAA,CAAY,IAAA;AAAA,QACzB,WAAA,EAAa,OAAO,WAAA,CAAY,WAAA;AAAA,QAChC,IAAA,EAAM,SAAA;AAAA,QACN,aAAa,MAAA,CAAO,WAAA;AAAA,QACpB,MAAM,MAAA,CAAO,IAAA;AAAA,QACb,YAAA,EAAc,MAAA,CAAO,WAAA,CAAY,eAAe;AAAA,OAClD;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,IAAI,wBAAA,CAAyB,CAAA,OAAA,EAAU,IAAI,CAAA,eAAA,EAAkB,SAAS,CAAA,CAAA,EAAI;AAAA,QAC9E,SAAA,EAAW,IAAA;AAAA,QACX,KAAA,EAAO;AAAA,OACR,CAAA;AAAA,IACH;AAAA,EACF;AACF","file":"skills.js","sourcesContent":["/**\n * Structured, typed error hierarchy for OllamaClient.\n */\n\nexport interface OllamaErrorRequestContext {\n readonly method?: string | undefined;\n readonly url?: string | undefined;\n readonly model?: string | undefined;\n}\n\nexport interface OllamaErrorResponseContext {\n readonly status?: number | undefined;\n readonly headers?: Record<string, string> | undefined;\n readonly body?: unknown;\n}\n\nexport interface OllamaClientErrorOptions extends ErrorOptions {\n readonly code: string;\n readonly status?: number | undefined;\n readonly retryable?: boolean | undefined;\n readonly request?: OllamaErrorRequestContext | undefined;\n readonly response?: OllamaErrorResponseContext | undefined;\n}\n\nexport class OllamaClientError extends Error {\n readonly code: string;\n readonly status?: number | undefined;\n readonly retryable: boolean;\n readonly request?: OllamaErrorRequestContext | undefined;\n readonly response?: OllamaErrorResponseContext | undefined;\n\n constructor(message: string, options: OllamaClientErrorOptions) {\n super(message, { cause: options.cause });\n this.name = this.constructor.name;\n this.code = options.code;\n this.status = options.status;\n this.retryable = options.retryable ?? false;\n this.request = options.request;\n this.response = options.response;\n }\n}\n\nexport class OllamaNetworkError extends OllamaClientError {\n constructor(\n message: string,\n options?: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> | undefined,\n ) {\n super(message, { ...options, code: 'network_error', retryable: true });\n }\n}\n\nexport class OllamaTimeoutError extends OllamaClientError {\n readonly timeoutMs?: number | undefined;\n constructor(\n message: string,\n options?:\n | (Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & { timeoutMs?: number | undefined })\n | undefined,\n ) {\n super(message, { ...options, code: 'timeout', retryable: true });\n this.timeoutMs = options?.timeoutMs;\n }\n}\n\nexport class OllamaAuthError extends OllamaClientError {\n constructor(\n message: string,\n options?: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> | undefined,\n ) {\n super(message, { ...options, code: 'auth_error', retryable: false });\n }\n}\n\nexport class OllamaNotFoundError extends OllamaClientError {\n constructor(\n message: string,\n options?: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> | undefined,\n ) {\n super(message, { ...options, code: 'not_found', retryable: false });\n }\n}\n\nexport class OllamaRateLimitError extends OllamaClientError {\n readonly retryAfterMs?: number | undefined;\n constructor(\n message: string,\n options?:\n | (Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & {\n retryAfterMs?: number | undefined;\n })\n | undefined,\n ) {\n super(message, { ...options, code: 'rate_limited', retryable: true });\n this.retryAfterMs = options?.retryAfterMs;\n }\n}\n\n/**\n * Thrown client-side, before a network request is made, by `QuotaManager.assertCanProceed`\n * (see `src/quota.ts`) when issuing the request would exceed a configured usage budget for\n * one of its rolling windows. This is distinct from `OllamaRateLimitError`, which reflects\n * the server's own 429 response — Ollama Cloud does not expose account-level quota via the\n * API, so `QuotaManager` tracks usage against budgets the caller configures locally and\n * fails fast rather than waiting for the server to reject the request.\n */\nexport class OllamaQuotaExceededError extends OllamaClientError {\n readonly windowId: string;\n readonly resetAt: number;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & {\n windowId: string;\n resetAt: number;\n },\n ) {\n super(message, { ...options, code: 'quota_exceeded', retryable: false });\n this.windowId = options.windowId;\n this.resetAt = options.resetAt;\n }\n}\n\nexport class OllamaServerError extends OllamaClientError {\n constructor(\n message: string,\n options?: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> | undefined,\n ) {\n super(message, { ...options, code: 'server_error', retryable: true });\n }\n}\n\nexport class OllamaAbortError extends OllamaClientError {\n constructor(\n message: string,\n options?: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> | undefined,\n ) {\n super(message, { ...options, code: 'aborted', retryable: false });\n }\n}\n\nexport class OllamaToolValidationError extends OllamaClientError {\n readonly toolName: string;\n readonly issues?: unknown;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & { toolName: string; issues?: unknown },\n ) {\n super(message, { ...options, code: 'tool_validation_error', retryable: false });\n this.toolName = options.toolName;\n this.issues = options.issues;\n }\n}\n\nexport class OllamaToolTimeoutError extends OllamaClientError {\n readonly toolName: string;\n readonly timeoutMs: number;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & {\n toolName: string;\n timeoutMs: number;\n },\n ) {\n super(message, { ...options, code: 'tool_timeout', retryable: false });\n this.toolName = options.toolName;\n this.timeoutMs = options.timeoutMs;\n }\n}\n\n/**\n * Thrown client-side, before a network request is made, when a request asks for a\n * capability an endpoint is known not to support (e.g. structured output `format` against\n * an Ollama Cloud endpoint — see `ModelCapabilities.supportsStructuredOutputRequest` in\n * `src/capabilities/capabilities.ts`). Its `code` is included in `DEFAULT_FAILOVER_CODES`\n * by default, so in a multi-endpoint setup it causes failover to the next candidate rather\n * than failing outright — it only surfaces to the caller if every candidate is rejected.\n */\nexport class OllamaUnsupportedCapabilityError extends OllamaClientError {\n readonly capability: string;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & { capability: string },\n ) {\n super(message, { ...options, code: 'unsupported_capability', retryable: false });\n this.capability = options.capability;\n }\n}\n\n/**\n * Thrown client-side, before any network call, when `config.endpoints` uses\n * `OllamaEndpoint.models` to scope endpoints/credentials to specific models and the\n * requested `model` isn't in any configured endpoint's allow-list. This is a routing\n * misconfiguration, not a connectivity problem — the SDK deliberately does not \"probe\"\n * unauthorized endpoints to find one that happens to work (that would burn quota on keys\n * that were never entitled to the model and produce non-deterministic startup behavior).\n */\nexport class OllamaModelRoutingError extends OllamaClientError {\n readonly model: string;\n readonly availableModels: readonly string[];\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & {\n model: string;\n availableModels: readonly string[];\n },\n ) {\n super(message, { ...options, code: 'model_routing_error', retryable: false });\n this.model = options.model;\n this.availableModels = options.availableModels;\n }\n}\n\n/**\n * Thrown before an agent tool loop starts when the selected model's /api/show metadata\n * does not advertise a capability required by the loop.\n */\nexport class OllamaIncompatibleModelError extends OllamaClientError {\n readonly model: string;\n readonly capability: string;\n readonly reportedCapabilities: readonly string[];\n\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & {\n model: string;\n capability: string;\n reportedCapabilities: readonly string[];\n },\n ) {\n super(message, { ...options, code: 'incompatible_model', retryable: false });\n this.model = options.model;\n this.capability = options.capability;\n this.reportedCapabilities = options.reportedCapabilities;\n }\n}\nexport class OllamaAgentMaxToolCallsError extends OllamaClientError {\n readonly maxToolCalls: number;\n readonly toolCallsExecuted: number;\n\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & {\n maxToolCalls: number;\n toolCallsExecuted: number;\n },\n ) {\n super(message, { ...options, code: 'agent_max_tool_calls_exceeded', retryable: false });\n this.maxToolCalls = options.maxToolCalls;\n this.toolCallsExecuted = options.toolCallsExecuted;\n }\n}\n\nexport class OllamaAgentMaxIterationsError extends OllamaClientError {\n readonly maxIterations: number;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & { maxIterations: number },\n ) {\n super(message, { ...options, code: 'agent_max_iterations_exceeded', retryable: false });\n this.maxIterations = options.maxIterations;\n }\n}\n\nexport class OllamaMcpError extends OllamaClientError {\n readonly mcpMethod: 'listTools' | 'callTool';\n readonly toolName?: string | undefined;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & {\n mcpMethod: 'listTools' | 'callTool';\n toolName?: string | undefined;\n },\n ) {\n super(message, { ...options, code: 'mcp_error', retryable: options.retryable ?? false });\n this.mcpMethod = options.mcpMethod;\n this.toolName = options.toolName;\n }\n}\n\nexport class OllamaSkillNotFoundError extends OllamaClientError {\n readonly skillName: string;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & { skillName: string },\n ) {\n super(message, { ...options, code: 'skill_not_found', retryable: false });\n this.skillName = options.skillName;\n }\n}\n\nexport class OllamaSkillInvalidError extends OllamaClientError {\n readonly skillName: string;\n readonly path?: string | undefined;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & {\n skillName: string;\n path?: string | undefined;\n },\n ) {\n super(message, { ...options, code: 'skill_invalid', retryable: false });\n this.skillName = options.skillName;\n this.path = options.path;\n }\n}\n\nexport class OllamaGenericClientError extends OllamaClientError {\n constructor(message: string, options?: Omit<OllamaClientErrorOptions, 'code'> | undefined) {\n super(message, { ...options, code: 'client_error' });\n }\n}\n\nfunction isDomAbortError(error: unknown): error is DOMException {\n return (\n typeof DOMException !== 'undefined' &&\n error instanceof DOMException &&\n error.name === 'AbortError'\n );\n}\n\nfunction statusToError(\n status: number,\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code' | 'status'>,\n): OllamaClientError {\n if (status === 401 || status === 403) {\n return new OllamaAuthError(message, { ...options, status });\n }\n if (status === 404) {\n return new OllamaNotFoundError(message, { ...options, status });\n }\n if (status === 429) {\n return new OllamaRateLimitError(message, { ...options, status });\n }\n if (status >= 500) {\n return new OllamaServerError(message, { ...options, status });\n }\n return new OllamaGenericClientError(message, { ...options, status });\n}\n\n/**\n * Maps arbitrary thrown exceptions into structured OllamaClientError instances.\n */\nexport function mapError(\n error: unknown,\n context: {\n request?: OllamaErrorRequestContext | undefined;\n response?: OllamaErrorResponseContext | undefined;\n } = {},\n): OllamaClientError {\n if (error instanceof OllamaClientError) {\n return error;\n }\n if (isDomAbortError(error)) {\n return new OllamaAbortError(error.message || 'Request was aborted', {\n cause: error,\n request: context.request,\n });\n }\n if (error instanceof TypeError) {\n return new OllamaNetworkError(error.message || 'Network request failed', {\n cause: error,\n request: context.request,\n });\n }\n if (context.response?.status !== undefined) {\n const message = error instanceof Error ? error.message : String(error);\n return statusToError(context.response.status, message, {\n cause: error,\n request: context.request,\n response: context.response,\n });\n }\n const message = error instanceof Error ? error.message : String(error);\n return new OllamaGenericClientError(message, {\n cause: error,\n request: context.request,\n response: context.response,\n });\n}\n","/**\n * Lightweight frontmatter parser for SKILL.md files.\n */\n\nimport { OllamaSkillInvalidError } from '../errors.js';\nimport type { SkillFrontmatter } from './types.js';\n\nexport interface ParsedFrontmatter {\n readonly frontmatter: SkillFrontmatter;\n readonly body: string;\n}\n\nfunction parseYamlValue(raw: string): unknown {\n const trimmed = raw.trim();\n if (trimmed === 'true') return true;\n if (trimmed === 'false') return false;\n if (!Number.isNaN(Number(trimmed)) && trimmed !== '') return Number(trimmed);\n if (\n (trimmed.startsWith('\"') && trimmed.endsWith('\"')) ||\n (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\"))\n ) {\n return trimmed.slice(1, -1);\n }\n return trimmed;\n}\n\nfunction parseYamlBlock(yamlText: string): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n const lines = yamlText.split('\\n');\n let currentKey: string | undefined;\n let currentList: unknown[] | undefined;\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n\n if (trimmed.startsWith('- ') && currentKey) {\n if (!currentList) {\n currentList = [];\n result[currentKey] = currentList;\n }\n currentList.push(parseYamlValue(trimmed.slice(2)));\n continue;\n }\n\n currentList = undefined;\n const colonIndex = line.indexOf(':');\n if (colonIndex > 0) {\n const key = line.slice(0, colonIndex).trim();\n const valStr = line.slice(colonIndex + 1).trim();\n currentKey = key;\n if (valStr.length > 0) {\n result[key] = parseYamlValue(valStr);\n }\n }\n }\n\n return result;\n}\n\nexport function parseFrontmatter(source: string, path = ''): ParsedFrontmatter {\n const match = source.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?([\\s\\S]*)$/);\n if (!match) {\n throw new OllamaSkillInvalidError('Missing YAML frontmatter delimiters (---)', {\n skillName: path || 'unknown',\n path,\n });\n }\n\n const rawYaml = match[1] ?? '';\n const body = match[2]?.trim() ?? '';\n const parsed = parseYamlBlock(rawYaml);\n\n if (!parsed['name'] || typeof parsed['name'] !== 'string') {\n throw new OllamaSkillInvalidError('Frontmatter missing required string \"name\"', {\n skillName: String(parsed['name'] ?? 'unknown'),\n path,\n });\n }\n if (!parsed['description'] || typeof parsed['description'] !== 'string') {\n throw new OllamaSkillInvalidError('Frontmatter missing required string \"description\"', {\n skillName: parsed['name'],\n path,\n });\n }\n\n return {\n frontmatter: parsed as unknown as SkillFrontmatter,\n body,\n };\n}\n","/**\n * Skill composition and context injection.\n */\n\nimport type { Message } from '../types.js';\nimport type { ToolRegistry } from '../tools/registry.js';\nimport type { Skill } from './types.js';\n\nexport interface ApplySkillOptions {\n readonly messages: readonly Message[];\n readonly tools?: ToolRegistry;\n}\n\nexport interface AppliedSkillResult {\n readonly messages: readonly Message[];\n readonly tools?: ToolRegistry;\n}\n\n/**\n * Injects a skill's body into messages as a system prompt and applies allowed tool filters.\n */\nexport function applySkill(skill: Skill, options: ApplySkillOptions): AppliedSkillResult {\n const systemPrompt = `[Skill: ${skill.name}]\\n${skill.description}\\n\\n${skill.body}`;\n const messages = [...options.messages];\n const systemIndex = messages.findIndex((m) => m.role === 'system');\n\n if (systemIndex >= 0) {\n const existing = messages[systemIndex];\n if (existing) {\n messages[systemIndex] = {\n role: 'system',\n content: `${existing.content}\\n\\n${systemPrompt}`,\n };\n }\n } else {\n messages.unshift({ role: 'system', content: systemPrompt });\n }\n\n return {\n messages,\n ...(options.tools !== undefined ? { tools: options.tools } : {}),\n };\n}\n","/**\n * Node.js filesystem skill registry for SKILL.md packages.\n */\n\nimport { readdir, readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { OllamaSkillNotFoundError } from '../errors.js';\nimport { parseFrontmatter } from './frontmatter.js';\nimport type { Skill, SkillSummary } from './types.js';\n\nexport interface SkillRegistryOptions {\n readonly directory: string;\n}\n\nexport class SkillRegistry {\n readonly directory: string;\n\n constructor(options: SkillRegistryOptions) {\n this.directory = options.directory;\n }\n\n async list(): Promise<SkillSummary[]> {\n const entries = await readdir(this.directory, { withFileTypes: true });\n const summaries: SkillSummary[] = [];\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const skillPath = join(this.directory, entry.name, 'SKILL.md');\n try {\n const content = await readFile(skillPath, 'utf-8');\n const parsed = parseFrontmatter(content, skillPath);\n summaries.push({\n name: parsed.frontmatter.name,\n description: parsed.frontmatter.description,\n path: skillPath,\n });\n } catch {\n // Skip directories without valid SKILL.md\n }\n }\n\n return summaries;\n }\n\n async load(name: string): Promise<Skill> {\n const skillPath = join(this.directory, name, 'SKILL.md');\n try {\n const content = await readFile(skillPath, 'utf-8');\n const parsed = parseFrontmatter(content, skillPath);\n return {\n name: parsed.frontmatter.name,\n description: parsed.frontmatter.description,\n path: skillPath,\n frontmatter: parsed.frontmatter,\n body: parsed.body,\n allowedTools: parsed.frontmatter['allowed-tools'],\n };\n } catch (err) {\n throw new OllamaSkillNotFoundError(`Skill \"${name}\" not found at ${skillPath}`, {\n skillName: name,\n cause: err,\n });\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/skills/frontmatter.ts","../src/skills/compose.ts","../src/skills/skill-registry.ts"],"names":[],"mappings":"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","file":"skills.js","sourcesContent":["/**\n * Structured, typed error hierarchy for OllamaClient.\n */\n\nimport type { z } from 'zod';\n\nexport interface OllamaErrorRequestContext {\n readonly method?: string | undefined;\n readonly url?: string | undefined;\n readonly model?: string | undefined;\n}\n\nexport interface OllamaErrorResponseContext {\n readonly status?: number | undefined;\n readonly headers?: Record<string, string> | undefined;\n readonly body?: unknown;\n}\n\nexport interface OllamaClientErrorOptions extends ErrorOptions {\n readonly code: string;\n readonly status?: number | undefined;\n readonly retryable?: boolean | undefined;\n readonly request?: OllamaErrorRequestContext | undefined;\n readonly response?: OllamaErrorResponseContext | undefined;\n}\n\nexport class OllamaClientError extends Error {\n readonly code: string;\n readonly status?: number | undefined;\n readonly retryable: boolean;\n readonly request?: OllamaErrorRequestContext | undefined;\n readonly response?: OllamaErrorResponseContext | undefined;\n\n constructor(message: string, options: OllamaClientErrorOptions) {\n super(message, { cause: options.cause });\n this.name = this.constructor.name;\n this.code = options.code;\n this.status = options.status;\n this.retryable = options.retryable ?? false;\n this.request = options.request;\n this.response = options.response;\n }\n}\n\nexport class OllamaNetworkError extends OllamaClientError {\n constructor(\n message: string,\n options?: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> | undefined,\n ) {\n super(message, { ...options, code: 'network_error', retryable: true });\n }\n}\n\nexport class OllamaTimeoutError extends OllamaClientError {\n readonly timeoutMs?: number | undefined;\n constructor(\n message: string,\n options?:\n | (Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & { timeoutMs?: number | undefined })\n | undefined,\n ) {\n super(message, { ...options, code: 'timeout', retryable: true });\n this.timeoutMs = options?.timeoutMs;\n }\n}\n\nexport class OllamaAuthError extends OllamaClientError {\n constructor(\n message: string,\n options?: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> | undefined,\n ) {\n super(message, { ...options, code: 'auth_error', retryable: false });\n }\n}\n\nexport class OllamaNotFoundError extends OllamaClientError {\n constructor(\n message: string,\n options?: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> | undefined,\n ) {\n super(message, { ...options, code: 'not_found', retryable: false });\n }\n}\n\nexport class OllamaRateLimitError extends OllamaClientError {\n readonly retryAfterMs?: number | undefined;\n constructor(\n message: string,\n options?:\n | (Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & {\n retryAfterMs?: number | undefined;\n })\n | undefined,\n ) {\n super(message, { ...options, code: 'rate_limited', retryable: true });\n this.retryAfterMs = options?.retryAfterMs;\n }\n}\n\n/**\n * Thrown client-side, before a network request is made, by `QuotaManager.assertCanProceed`\n * (see `src/quota.ts`) when issuing the request would exceed a configured usage budget for\n * one of its rolling windows. This is distinct from `OllamaRateLimitError`, which reflects\n * the server's own 429 response — Ollama Cloud does not expose account-level quota via the\n * API, so `QuotaManager` tracks usage against budgets the caller configures locally and\n * fails fast rather than waiting for the server to reject the request.\n */\nexport class OllamaQuotaExceededError extends OllamaClientError {\n readonly windowId: string;\n readonly resetAt: number;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & {\n windowId: string;\n resetAt: number;\n },\n ) {\n super(message, { ...options, code: 'quota_exceeded', retryable: false });\n this.windowId = options.windowId;\n this.resetAt = options.resetAt;\n }\n}\n\nexport class OllamaServerError extends OllamaClientError {\n constructor(\n message: string,\n options?: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> | undefined,\n ) {\n super(message, { ...options, code: 'server_error', retryable: true });\n }\n}\n\nexport class OllamaAbortError extends OllamaClientError {\n constructor(\n message: string,\n options?: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> | undefined,\n ) {\n super(message, { ...options, code: 'aborted', retryable: false });\n }\n}\n\nexport class OllamaToolValidationError extends OllamaClientError {\n readonly toolName: string;\n readonly issues?: unknown;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & { toolName: string; issues?: unknown },\n ) {\n super(message, { ...options, code: 'tool_validation_error', retryable: false });\n this.toolName = options.toolName;\n this.issues = options.issues;\n }\n}\n\n/**\n * Thrown by `OllamaRuntime.invoke` when `validateRequests: true` is set and\n * the request body fails Zod validation against the operation's registered\n * schema. See ADR 0020 (runtime Zod validation).\n *\n * The error carries the original Zod issues so callers can inspect which\n * fields failed. No HTTP request is made when this error is thrown.\n */\nexport class OllamaRequestValidationError extends OllamaClientError {\n readonly operationId: string;\n readonly issues: readonly z.ZodIssue[];\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & {\n operationId: string;\n issues: readonly z.ZodIssue[];\n },\n ) {\n super(message, { ...options, code: 'request_validation_error', retryable: false });\n this.operationId = options.operationId;\n this.issues = options.issues;\n }\n}\n\nexport class OllamaToolTimeoutError extends OllamaClientError {\n readonly toolName: string;\n readonly timeoutMs: number;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & {\n toolName: string;\n timeoutMs: number;\n },\n ) {\n super(message, { ...options, code: 'tool_timeout', retryable: false });\n this.toolName = options.toolName;\n this.timeoutMs = options.timeoutMs;\n }\n}\n\n/**\n * Thrown client-side, before a network request is made, when a request asks for a\n * capability an endpoint is known not to support (e.g. structured output `format` against\n * an Ollama Cloud endpoint — see `ModelCapabilities.supportsStructuredOutputRequest` in\n * `src/capabilities/capabilities.ts`). Its `code` is included in `DEFAULT_FAILOVER_CODES`\n * by default, so in a multi-endpoint setup it causes failover to the next candidate rather\n * than failing outright — it only surfaces to the caller if every candidate is rejected.\n */\nexport class OllamaUnsupportedCapabilityError extends OllamaClientError {\n readonly capability: string;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & { capability: string },\n ) {\n super(message, { ...options, code: 'unsupported_capability', retryable: false });\n this.capability = options.capability;\n }\n}\n\n/**\n * Thrown client-side, before any network call, when `config.endpoints` uses\n * `OllamaEndpoint.models` to scope endpoints/credentials to specific models and the\n * requested `model` isn't in any configured endpoint's allow-list. This is a routing\n * misconfiguration, not a connectivity problem — the SDK deliberately does not \"probe\"\n * unauthorized endpoints to find one that happens to work (that would burn quota on keys\n * that were never entitled to the model and produce non-deterministic startup behavior).\n */\nexport class OllamaModelRoutingError extends OllamaClientError {\n readonly model: string;\n readonly availableModels: readonly string[];\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & {\n model: string;\n availableModels: readonly string[];\n },\n ) {\n super(message, { ...options, code: 'model_routing_error', retryable: false });\n this.model = options.model;\n this.availableModels = options.availableModels;\n }\n}\n\n/**\n * Thrown before an agent tool loop starts when the selected model's /api/show metadata\n * does not advertise a capability required by the loop.\n */\nexport class OllamaIncompatibleModelError extends OllamaClientError {\n readonly model: string;\n readonly capability: string;\n readonly reportedCapabilities: readonly string[];\n\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code' | 'retryable'> & {\n model: string;\n capability: string;\n reportedCapabilities: readonly string[];\n },\n ) {\n super(message, { ...options, code: 'incompatible_model', retryable: false });\n this.model = options.model;\n this.capability = options.capability;\n this.reportedCapabilities = options.reportedCapabilities;\n }\n}\nexport class OllamaAgentMaxToolCallsError extends OllamaClientError {\n readonly maxToolCalls: number;\n readonly toolCallsExecuted: number;\n\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & {\n maxToolCalls: number;\n toolCallsExecuted: number;\n },\n ) {\n super(message, { ...options, code: 'agent_max_tool_calls_exceeded', retryable: false });\n this.maxToolCalls = options.maxToolCalls;\n this.toolCallsExecuted = options.toolCallsExecuted;\n }\n}\n\nexport class OllamaAgentMaxIterationsError extends OllamaClientError {\n readonly maxIterations: number;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & { maxIterations: number },\n ) {\n super(message, { ...options, code: 'agent_max_iterations_exceeded', retryable: false });\n this.maxIterations = options.maxIterations;\n }\n}\n\nexport class OllamaMcpError extends OllamaClientError {\n readonly mcpMethod: 'listTools' | 'callTool';\n readonly toolName?: string | undefined;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & {\n mcpMethod: 'listTools' | 'callTool';\n toolName?: string | undefined;\n },\n ) {\n super(message, { ...options, code: 'mcp_error', retryable: options.retryable ?? false });\n this.mcpMethod = options.mcpMethod;\n this.toolName = options.toolName;\n }\n}\n\nexport class OllamaSkillNotFoundError extends OllamaClientError {\n readonly skillName: string;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & { skillName: string },\n ) {\n super(message, { ...options, code: 'skill_not_found', retryable: false });\n this.skillName = options.skillName;\n }\n}\n\nexport class OllamaSkillInvalidError extends OllamaClientError {\n readonly skillName: string;\n readonly path?: string | undefined;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & {\n skillName: string;\n path?: string | undefined;\n },\n ) {\n super(message, { ...options, code: 'skill_invalid', retryable: false });\n this.skillName = options.skillName;\n this.path = options.path;\n }\n}\n\nexport class OllamaGenericClientError extends OllamaClientError {\n constructor(message: string, options?: Omit<OllamaClientErrorOptions, 'code'> | undefined) {\n super(message, { ...options, code: 'client_error' });\n }\n}\n\nfunction isDomAbortError(error: unknown): error is DOMException {\n return (\n typeof DOMException !== 'undefined' &&\n error instanceof DOMException &&\n error.name === 'AbortError'\n );\n}\n\nfunction statusToError(\n status: number,\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code' | 'status'>,\n): OllamaClientError {\n if (status === 401 || status === 403) {\n return new OllamaAuthError(message, { ...options, status });\n }\n if (status === 404) {\n return new OllamaNotFoundError(message, { ...options, status });\n }\n if (status === 429) {\n return new OllamaRateLimitError(message, { ...options, status });\n }\n if (status >= 500) {\n return new OllamaServerError(message, { ...options, status });\n }\n return new OllamaGenericClientError(message, { ...options, status });\n}\n\n/**\n * Maps arbitrary thrown exceptions into structured OllamaClientError instances.\n */\nexport function mapError(\n error: unknown,\n context: {\n request?: OllamaErrorRequestContext | undefined;\n response?: OllamaErrorResponseContext | undefined;\n } = {},\n): OllamaClientError {\n if (error instanceof OllamaClientError) {\n return error;\n }\n if (isDomAbortError(error)) {\n return new OllamaAbortError(error.message || 'Request was aborted', {\n cause: error,\n request: context.request,\n });\n }\n if (error instanceof TypeError) {\n return new OllamaNetworkError(error.message || 'Network request failed', {\n cause: error,\n request: context.request,\n });\n }\n if (context.response?.status !== undefined) {\n const message = error instanceof Error ? error.message : String(error);\n return statusToError(context.response.status, message, {\n cause: error,\n request: context.request,\n response: context.response,\n });\n }\n const message = error instanceof Error ? error.message : String(error);\n return new OllamaGenericClientError(message, {\n cause: error,\n request: context.request,\n response: context.response,\n });\n}\n","/**\n * Lightweight frontmatter parser for SKILL.md files.\n */\n\nimport { OllamaSkillInvalidError } from '../errors.js';\nimport type { SkillFrontmatter } from './types.js';\n\nexport interface ParsedFrontmatter {\n readonly frontmatter: SkillFrontmatter;\n readonly body: string;\n}\n\nfunction parseYamlValue(raw: string): unknown {\n const trimmed = raw.trim();\n if (trimmed === 'true') return true;\n if (trimmed === 'false') return false;\n if (!Number.isNaN(Number(trimmed)) && trimmed !== '') return Number(trimmed);\n if (\n (trimmed.startsWith('\"') && trimmed.endsWith('\"')) ||\n (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\"))\n ) {\n return trimmed.slice(1, -1);\n }\n return trimmed;\n}\n\nfunction parseYamlBlock(yamlText: string): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n const lines = yamlText.split('\\n');\n let currentKey: string | undefined;\n let currentList: unknown[] | undefined;\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n\n if (trimmed.startsWith('- ') && currentKey) {\n if (!currentList) {\n currentList = [];\n result[currentKey] = currentList;\n }\n currentList.push(parseYamlValue(trimmed.slice(2)));\n continue;\n }\n\n currentList = undefined;\n const colonIndex = line.indexOf(':');\n if (colonIndex > 0) {\n const key = line.slice(0, colonIndex).trim();\n const valStr = line.slice(colonIndex + 1).trim();\n currentKey = key;\n if (valStr.length > 0) {\n result[key] = parseYamlValue(valStr);\n }\n }\n }\n\n return result;\n}\n\nexport function parseFrontmatter(source: string, path = ''): ParsedFrontmatter {\n const match = source.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?([\\s\\S]*)$/);\n if (!match) {\n throw new OllamaSkillInvalidError('Missing YAML frontmatter delimiters (---)', {\n skillName: path || 'unknown',\n path,\n });\n }\n\n const rawYaml = match[1] ?? '';\n const body = match[2]?.trim() ?? '';\n const parsed = parseYamlBlock(rawYaml);\n\n if (!parsed['name'] || typeof parsed['name'] !== 'string') {\n throw new OllamaSkillInvalidError('Frontmatter missing required string \"name\"', {\n skillName: String(parsed['name'] ?? 'unknown'),\n path,\n });\n }\n if (!parsed['description'] || typeof parsed['description'] !== 'string') {\n throw new OllamaSkillInvalidError('Frontmatter missing required string \"description\"', {\n skillName: parsed['name'],\n path,\n });\n }\n\n return {\n frontmatter: parsed as unknown as SkillFrontmatter,\n body,\n };\n}\n","/**\n * Skill composition and context injection.\n */\n\nimport type { Message } from '../types.js';\nimport type { ToolRegistry } from '../tools/registry.js';\nimport type { Skill } from './types.js';\n\nexport interface ApplySkillOptions {\n readonly messages: readonly Message[];\n readonly tools?: ToolRegistry;\n}\n\nexport interface AppliedSkillResult {\n readonly messages: readonly Message[];\n readonly tools?: ToolRegistry;\n}\n\n/**\n * Injects a skill's body into messages as a system prompt and applies allowed tool filters.\n */\nexport function applySkill(skill: Skill, options: ApplySkillOptions): AppliedSkillResult {\n const systemPrompt = `[Skill: ${skill.name}]\\n${skill.description}\\n\\n${skill.body}`;\n const messages = [...options.messages];\n const systemIndex = messages.findIndex((m) => m.role === 'system');\n\n if (systemIndex >= 0) {\n const existing = messages[systemIndex];\n if (existing) {\n messages[systemIndex] = {\n role: 'system',\n content: `${existing.content}\\n\\n${systemPrompt}`,\n };\n }\n } else {\n messages.unshift({ role: 'system', content: systemPrompt });\n }\n\n return {\n messages,\n ...(options.tools !== undefined ? { tools: options.tools } : {}),\n };\n}\n","/**\n * Node.js filesystem skill registry for SKILL.md packages.\n */\n\nimport { readdir, readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { OllamaSkillNotFoundError } from '../errors.js';\nimport { parseFrontmatter } from './frontmatter.js';\nimport type { Skill, SkillSummary } from './types.js';\n\nexport interface SkillRegistryOptions {\n readonly directory: string;\n}\n\nexport class SkillRegistry {\n readonly directory: string;\n\n constructor(options: SkillRegistryOptions) {\n this.directory = options.directory;\n }\n\n async list(): Promise<SkillSummary[]> {\n const entries = await readdir(this.directory, { withFileTypes: true });\n const summaries: SkillSummary[] = [];\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const skillPath = join(this.directory, entry.name, 'SKILL.md');\n try {\n const content = await readFile(skillPath, 'utf-8');\n const parsed = parseFrontmatter(content, skillPath);\n summaries.push({\n name: parsed.frontmatter.name,\n description: parsed.frontmatter.description,\n path: skillPath,\n });\n } catch {\n // Skip directories without valid SKILL.md\n }\n }\n\n return summaries;\n }\n\n async load(name: string): Promise<Skill> {\n const skillPath = join(this.directory, name, 'SKILL.md');\n try {\n const content = await readFile(skillPath, 'utf-8');\n const parsed = parseFrontmatter(content, skillPath);\n return {\n name: parsed.frontmatter.name,\n description: parsed.frontmatter.description,\n path: skillPath,\n frontmatter: parsed.frontmatter,\n body: parsed.body,\n allowedTools: parsed.frontmatter['allowed-tools'],\n };\n } catch (err) {\n throw new OllamaSkillNotFoundError(`Skill \"${name}\" not found at ${skillPath}`, {\n skillName: name,\n cause: err,\n });\n }\n }\n}\n"]}
@@ -400,4 +400,4 @@ interface WebFetchResponse {
400
400
  readonly links?: readonly string[] | undefined;
401
401
  }
402
402
 
403
- export type { ToolParameters as A, ToolProperty as B, CreateRequestOptions as C, DeleteRequestOptions as D, EmbedRequestOptions as E, FormatOption as F, GenerateRequestOptions as G, WebSearchResult as H, ListResponse as L, Message as M, PullRequestOptions as P, RequestCancellationOptions as R, ShowRequestOptions as S, ToolDefinition as T, VersionResponse as V, WebSearchRequestOptions as W, ToolCall as a, ThinkingMetadata as b, ModelResponse as c, ShowResponse as d, ProgressResponse as e, PushRequestOptions as f, StatusResponse as g, CopyRequestOptions as h, PsResponse as i, ChatRequestOptions as j, ChatResponse as k, GenerateResponse as l, EmbedResponse as m, EmbeddingsRequestOptions as n, EmbeddingsResponse as o, WebSearchResponse as p, WebFetchRequestOptions as q, WebFetchResponse as r, ModelOptions as s, ThinkValue as t, Logprob as u, LogprobToken as v, ModelDetails as w, Role as x, ToolCallFunction as y, ToolFunctionDefinition as z };
403
+ export type { ToolParameters as A, ToolProperty as B, CreateRequestOptions as C, DeleteRequestOptions as D, EmbedRequestOptions as E, FormatOption as F, GenerateRequestOptions as G, WebSearchResult as H, ListResponse as L, ModelResponse as M, PullRequestOptions as P, RequestCancellationOptions as R, ShowRequestOptions as S, ThinkingMetadata as T, VersionResponse as V, WebSearchRequestOptions as W, ShowResponse as a, ProgressResponse as b, PushRequestOptions as c, StatusResponse as d, CopyRequestOptions as e, PsResponse as f, ChatRequestOptions as g, ChatResponse as h, GenerateResponse as i, EmbedResponse as j, EmbeddingsRequestOptions as k, EmbeddingsResponse as l, WebSearchResponse as m, WebFetchRequestOptions as n, WebFetchResponse as o, ToolDefinition as p, ToolCall as q, Message as r, ModelOptions as s, ThinkValue as t, Logprob as u, LogprobToken as v, ModelDetails as w, Role as x, ToolCallFunction as y, ToolFunctionDefinition as z };
@@ -400,4 +400,4 @@ interface WebFetchResponse {
400
400
  readonly links?: readonly string[] | undefined;
401
401
  }
402
402
 
403
- export type { ToolParameters as A, ToolProperty as B, CreateRequestOptions as C, DeleteRequestOptions as D, EmbedRequestOptions as E, FormatOption as F, GenerateRequestOptions as G, WebSearchResult as H, ListResponse as L, Message as M, PullRequestOptions as P, RequestCancellationOptions as R, ShowRequestOptions as S, ToolDefinition as T, VersionResponse as V, WebSearchRequestOptions as W, ToolCall as a, ThinkingMetadata as b, ModelResponse as c, ShowResponse as d, ProgressResponse as e, PushRequestOptions as f, StatusResponse as g, CopyRequestOptions as h, PsResponse as i, ChatRequestOptions as j, ChatResponse as k, GenerateResponse as l, EmbedResponse as m, EmbeddingsRequestOptions as n, EmbeddingsResponse as o, WebSearchResponse as p, WebFetchRequestOptions as q, WebFetchResponse as r, ModelOptions as s, ThinkValue as t, Logprob as u, LogprobToken as v, ModelDetails as w, Role as x, ToolCallFunction as y, ToolFunctionDefinition as z };
403
+ export type { ToolParameters as A, ToolProperty as B, CreateRequestOptions as C, DeleteRequestOptions as D, EmbedRequestOptions as E, FormatOption as F, GenerateRequestOptions as G, WebSearchResult as H, ListResponse as L, ModelResponse as M, PullRequestOptions as P, RequestCancellationOptions as R, ShowRequestOptions as S, ThinkingMetadata as T, VersionResponse as V, WebSearchRequestOptions as W, ShowResponse as a, ProgressResponse as b, PushRequestOptions as c, StatusResponse as d, CopyRequestOptions as e, PsResponse as f, ChatRequestOptions as g, ChatResponse as h, GenerateResponse as i, EmbedResponse as j, EmbeddingsRequestOptions as k, EmbeddingsResponse as l, WebSearchResponse as m, WebFetchRequestOptions as n, WebFetchResponse as o, ToolDefinition as p, ToolCall as q, Message as r, ModelOptions as s, ThinkValue as t, Logprob as u, LogprobToken as v, ModelDetails as w, Role as x, ToolCallFunction as y, ToolFunctionDefinition as z };
@@ -63,4 +63,4 @@ interface McpClientLike {
63
63
  }, options?: McpRequestOptions) => Promise<McpCallToolResult>;
64
64
  }
65
65
 
66
- export type { McpToolDescriptor as M, McpClientLike as a, McpCallToolResult as b, McpContentBlock as c, McpIcon as d, McpListToolsParams as e, McpListToolsResult as f, McpRequestOptions as g, McpToolAnnotations as h, McpToolExecution as i };
66
+ export type { McpClientLike as M, McpToolDescriptor as a, McpCallToolResult as b, McpContentBlock as c, McpIcon as d, McpListToolsParams as e, McpListToolsResult as f, McpRequestOptions as g, McpToolAnnotations as h, McpToolExecution as i };
@@ -63,4 +63,4 @@ interface McpClientLike {
63
63
  }, options?: McpRequestOptions) => Promise<McpCallToolResult>;
64
64
  }
65
65
 
66
- export type { McpToolDescriptor as M, McpClientLike as a, McpCallToolResult as b, McpContentBlock as c, McpIcon as d, McpListToolsParams as e, McpListToolsResult as f, McpRequestOptions as g, McpToolAnnotations as h, McpToolExecution as i };
66
+ export type { McpClientLike as M, McpToolDescriptor as a, McpCallToolResult as b, McpContentBlock as c, McpIcon as d, McpListToolsParams as e, McpListToolsResult as f, McpRequestOptions as g, McpToolAnnotations as h, McpToolExecution as i };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nemesis-oss/ollama-sdk",
3
- "version": "1.4.1",
3
+ "version": "1.5.0",
4
4
  "description": "Production-grade TypeScript SDK for Ollama with native fetch, high availability failover, multi-turn tool calling, structured outputs, reasoning stream tokens, OpenAI/Anthropic bridges, MCP, Web Stream adapters, and a contract-first hybrid architecture that generates TypeScript types, API classes, MCP tools, and Zod schemas from a single canonical IR.",
5
5
  "keywords": [
6
6
  "ollama",