@nemesis-oss/ollama-sdk 1.5.1 → 1.7.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.
- package/CHANGELOG.md +4 -1
- package/README.md +31 -0
- package/dist/generated-api.d.cts +2 -2
- package/dist/generated-api.d.ts +2 -2
- package/dist/generated-runtime.cjs.map +1 -1
- package/dist/generated-runtime.d.cts +1 -1
- package/dist/generated-runtime.d.ts +1 -1
- package/dist/generated-runtime.js.map +1 -1
- package/dist/index.cjs +132 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -5
- package/dist/index.d.ts +20 -5
- package/dist/index.js +132 -6
- package/dist/index.js.map +1 -1
- package/dist/mcp-generated.d.cts +3 -3
- package/dist/mcp-generated.d.ts +3 -3
- package/dist/mcp-http.cjs +43 -4
- package/dist/mcp-http.cjs.map +1 -1
- package/dist/mcp-http.d.cts +5 -1
- package/dist/mcp-http.d.ts +5 -1
- package/dist/mcp-http.js +43 -4
- package/dist/mcp-http.js.map +1 -1
- package/dist/mcp-stdio.cjs +43 -4
- package/dist/mcp-stdio.cjs.map +1 -1
- package/dist/mcp-stdio.d.cts +5 -1
- package/dist/mcp-stdio.d.ts +5 -1
- package/dist/mcp-stdio.js +43 -4
- package/dist/mcp-stdio.js.map +1 -1
- package/dist/{runtime-IxRpUBjN.d.cts → runtime-bQ48I-RC.d.cts} +4 -2
- package/dist/{runtime-CVQkbYgF.d.ts → runtime-qwD72cpn.d.ts} +4 -2
- package/dist/skills.cjs.map +1 -1
- package/dist/skills.js.map +1 -1
- package/dist/types-CI-gM2u5.d.cts +139 -0
- package/dist/types-CI-gM2u5.d.ts +139 -0
- package/package.json +3 -1
- package/dist/types-MOsWXEE7.d.cts +0 -66
- package/dist/types-MOsWXEE7.d.ts +0 -66
package/dist/skills.cjs.map
CHANGED
|
@@ -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":";;;;;;AA0BO,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;AAsQO,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;;;AC7TA,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,MAAMA,gBAAA,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,YAAYC,SAAA,CAAK,IAAA,CAAK,SAAA,EAAW,KAAA,CAAM,MAAM,UAAU,CAAA;AAC7D,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,GAAU,MAAMC,iBAAA,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,GAAYD,SAAA,CAAK,IAAA,CAAK,SAAA,EAAW,MAAM,UAAU,CAAA;AACvD,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,MAAMC,iBAAA,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.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"]}
|
|
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:\n | 'listTools'\n | 'callTool'\n | 'tools/call'\n | 'tasks/get'\n | 'tasks/result'\n | 'tasks/cancel';\n readonly toolName?: string | undefined;\n readonly issues?: unknown;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & {\n mcpMethod:\n | 'listTools'\n | 'callTool'\n | 'tools/call'\n | 'tasks/get'\n | 'tasks/result'\n | 'tasks/cancel';\n toolName?: string | undefined;\n issues?: unknown;\n },\n ) {\n super(message, { ...options, code: 'mcp_error', retryable: options.retryable ?? false });\n this.mcpMethod = options.mcpMethod;\n this.toolName = options.toolName;\n this.issues = options.issues;\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.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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"]}
|
|
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:\n | 'listTools'\n | 'callTool'\n | 'tools/call'\n | 'tasks/get'\n | 'tasks/result'\n | 'tasks/cancel';\n readonly toolName?: string | undefined;\n readonly issues?: unknown;\n constructor(\n message: string,\n options: Omit<OllamaClientErrorOptions, 'code'> & {\n mcpMethod:\n | 'listTools'\n | 'callTool'\n | 'tools/call'\n | 'tasks/get'\n | 'tasks/result'\n | 'tasks/cancel';\n toolName?: string | undefined;\n issues?: unknown;\n },\n ) {\n super(message, { ...options, code: 'mcp_error', retryable: options.retryable ?? false });\n this.mcpMethod = options.mcpMethod;\n this.toolName = options.toolName;\n this.issues = options.issues;\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"]}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Duck-typed MCP (Model Context Protocol) client interfaces.
|
|
5
|
+
* Decoupled from any specific MCP SDK.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
interface McpToolAnnotations {
|
|
9
|
+
readonly title?: string | undefined;
|
|
10
|
+
readonly readOnlyHint?: boolean | undefined;
|
|
11
|
+
readonly destructiveHint?: boolean | undefined;
|
|
12
|
+
readonly idempotentHint?: boolean | undefined;
|
|
13
|
+
readonly openWorldHint?: boolean | undefined;
|
|
14
|
+
readonly [key: string]: unknown;
|
|
15
|
+
}
|
|
16
|
+
interface McpToolExecution {
|
|
17
|
+
readonly taskSupport?: 'forbidden' | 'optional' | 'required' | undefined;
|
|
18
|
+
readonly [key: string]: unknown;
|
|
19
|
+
}
|
|
20
|
+
interface McpIcon {
|
|
21
|
+
readonly src: string;
|
|
22
|
+
readonly mimeType?: string | undefined;
|
|
23
|
+
readonly sizes?: readonly string[] | undefined;
|
|
24
|
+
readonly theme?: 'light' | 'dark' | undefined;
|
|
25
|
+
readonly [key: string]: unknown;
|
|
26
|
+
}
|
|
27
|
+
interface McpRequestOptions {
|
|
28
|
+
readonly signal?: AbortSignal | undefined;
|
|
29
|
+
readonly allowInputRequired?: boolean | undefined;
|
|
30
|
+
}
|
|
31
|
+
interface McpElicitationFormRequest {
|
|
32
|
+
readonly mode?: 'form' | undefined;
|
|
33
|
+
readonly message: string;
|
|
34
|
+
readonly requestedSchema: Record<string, unknown>;
|
|
35
|
+
readonly [key: string]: unknown;
|
|
36
|
+
}
|
|
37
|
+
interface McpElicitationUrlRequest {
|
|
38
|
+
readonly mode: 'url';
|
|
39
|
+
readonly message: string;
|
|
40
|
+
readonly url: string;
|
|
41
|
+
readonly elicitationId: string;
|
|
42
|
+
readonly [key: string]: unknown;
|
|
43
|
+
}
|
|
44
|
+
type McpElicitationRequest = McpElicitationFormRequest | McpElicitationUrlRequest;
|
|
45
|
+
type McpElicitationResult = {
|
|
46
|
+
readonly action: 'accept';
|
|
47
|
+
readonly content?: Record<string, unknown> | undefined;
|
|
48
|
+
} | {
|
|
49
|
+
readonly action: 'decline' | 'cancel';
|
|
50
|
+
};
|
|
51
|
+
interface McpElicitationHandlers {
|
|
52
|
+
readonly form?: ((request: McpElicitationFormRequest) => Promise<McpElicitationResult> | McpElicitationResult) | undefined;
|
|
53
|
+
readonly url?: ((request: McpElicitationUrlRequest) => Promise<McpElicitationResult> | McpElicitationResult) | undefined;
|
|
54
|
+
}
|
|
55
|
+
interface McpToolDescriptor {
|
|
56
|
+
readonly name: string;
|
|
57
|
+
readonly title?: string | undefined;
|
|
58
|
+
readonly description?: string | undefined;
|
|
59
|
+
readonly inputSchema?: Record<string, unknown> | undefined;
|
|
60
|
+
readonly outputSchema?: Record<string, unknown> | undefined;
|
|
61
|
+
readonly annotations?: McpToolAnnotations | undefined;
|
|
62
|
+
readonly execution?: McpToolExecution | undefined;
|
|
63
|
+
readonly icons?: readonly McpIcon[] | undefined;
|
|
64
|
+
readonly _meta?: Record<string, unknown> | undefined;
|
|
65
|
+
}
|
|
66
|
+
interface McpListToolsResult {
|
|
67
|
+
readonly tools: readonly McpToolDescriptor[];
|
|
68
|
+
readonly nextCursor?: string | undefined;
|
|
69
|
+
}
|
|
70
|
+
interface McpListToolsParams {
|
|
71
|
+
readonly cursor?: string | undefined;
|
|
72
|
+
}
|
|
73
|
+
interface McpContentBlock {
|
|
74
|
+
readonly type: string;
|
|
75
|
+
readonly text?: string | undefined;
|
|
76
|
+
readonly annotations?: Record<string, unknown> | undefined;
|
|
77
|
+
readonly _meta?: Record<string, unknown> | undefined;
|
|
78
|
+
readonly [key: string]: unknown;
|
|
79
|
+
}
|
|
80
|
+
interface McpCallToolResult {
|
|
81
|
+
readonly content: readonly McpContentBlock[];
|
|
82
|
+
readonly structuredContent?: unknown;
|
|
83
|
+
readonly isError?: boolean | undefined;
|
|
84
|
+
readonly _meta?: Record<string, unknown> | undefined;
|
|
85
|
+
}
|
|
86
|
+
interface McpInputRequiredResult {
|
|
87
|
+
readonly resultType: 'input_required';
|
|
88
|
+
readonly inputRequests?: Record<string, unknown> | undefined;
|
|
89
|
+
readonly requestState?: string | undefined;
|
|
90
|
+
readonly [key: string]: unknown;
|
|
91
|
+
}
|
|
92
|
+
type McpTaskStatus = 'working' | 'input_required' | 'completed' | 'failed' | 'cancelled';
|
|
93
|
+
interface McpTask {
|
|
94
|
+
readonly taskId: string;
|
|
95
|
+
readonly status: McpTaskStatus;
|
|
96
|
+
readonly statusMessage?: string | undefined;
|
|
97
|
+
readonly createdAt: string;
|
|
98
|
+
readonly lastUpdatedAt: string;
|
|
99
|
+
readonly ttl?: number | undefined;
|
|
100
|
+
readonly pollInterval?: number | undefined;
|
|
101
|
+
}
|
|
102
|
+
type McpTaskMethod = 'tasks/get' | 'tasks/result' | 'tasks/cancel';
|
|
103
|
+
interface McpTaskRequest {
|
|
104
|
+
readonly method: McpTaskMethod;
|
|
105
|
+
readonly params: {
|
|
106
|
+
readonly taskId: string;
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
interface McpCreateTaskResult {
|
|
110
|
+
readonly task: McpTask;
|
|
111
|
+
readonly _meta?: Record<string, unknown> | undefined;
|
|
112
|
+
}
|
|
113
|
+
type McpToolCallResult = McpCallToolResult | McpInputRequiredResult | McpCreateTaskResult;
|
|
114
|
+
interface McpServerCapabilities {
|
|
115
|
+
readonly tasks?: {
|
|
116
|
+
readonly requests?: {
|
|
117
|
+
readonly tools?: {
|
|
118
|
+
readonly call?: Record<string, unknown> | undefined;
|
|
119
|
+
} | undefined;
|
|
120
|
+
} | undefined;
|
|
121
|
+
} | undefined;
|
|
122
|
+
readonly [key: string]: unknown;
|
|
123
|
+
}
|
|
124
|
+
interface McpClientLike {
|
|
125
|
+
getServerCapabilities?: (() => McpServerCapabilities | undefined) | undefined;
|
|
126
|
+
request?: (<T>(request: McpTaskRequest, resultSchema: z.ZodType<T>, options?: McpRequestOptions) => Promise<T>) | undefined;
|
|
127
|
+
listTools: (params?: McpListToolsParams, options?: McpRequestOptions) => Promise<McpListToolsResult>;
|
|
128
|
+
callTool: (params: {
|
|
129
|
+
readonly name: string;
|
|
130
|
+
readonly arguments?: Record<string, unknown>;
|
|
131
|
+
readonly task?: {
|
|
132
|
+
readonly ttl?: number | undefined;
|
|
133
|
+
} | undefined;
|
|
134
|
+
readonly inputResponses?: Record<string, unknown> | undefined;
|
|
135
|
+
readonly requestState?: string | undefined;
|
|
136
|
+
}, options?: McpRequestOptions) => Promise<McpToolCallResult>;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export type { McpClientLike as M, McpToolDescriptor as a, McpTask as b, McpCallToolResult as c, McpContentBlock as d, McpCreateTaskResult as e, McpElicitationFormRequest as f, McpElicitationHandlers as g, McpElicitationRequest as h, McpElicitationResult as i, McpElicitationUrlRequest as j, McpIcon as k, McpInputRequiredResult as l, McpListToolsParams as m, McpListToolsResult as n, McpRequestOptions as o, McpServerCapabilities as p, McpTaskMethod as q, McpTaskRequest as r, McpTaskStatus as s, McpToolAnnotations as t, McpToolCallResult as u, McpToolExecution as v };
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Duck-typed MCP (Model Context Protocol) client interfaces.
|
|
5
|
+
* Decoupled from any specific MCP SDK.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
interface McpToolAnnotations {
|
|
9
|
+
readonly title?: string | undefined;
|
|
10
|
+
readonly readOnlyHint?: boolean | undefined;
|
|
11
|
+
readonly destructiveHint?: boolean | undefined;
|
|
12
|
+
readonly idempotentHint?: boolean | undefined;
|
|
13
|
+
readonly openWorldHint?: boolean | undefined;
|
|
14
|
+
readonly [key: string]: unknown;
|
|
15
|
+
}
|
|
16
|
+
interface McpToolExecution {
|
|
17
|
+
readonly taskSupport?: 'forbidden' | 'optional' | 'required' | undefined;
|
|
18
|
+
readonly [key: string]: unknown;
|
|
19
|
+
}
|
|
20
|
+
interface McpIcon {
|
|
21
|
+
readonly src: string;
|
|
22
|
+
readonly mimeType?: string | undefined;
|
|
23
|
+
readonly sizes?: readonly string[] | undefined;
|
|
24
|
+
readonly theme?: 'light' | 'dark' | undefined;
|
|
25
|
+
readonly [key: string]: unknown;
|
|
26
|
+
}
|
|
27
|
+
interface McpRequestOptions {
|
|
28
|
+
readonly signal?: AbortSignal | undefined;
|
|
29
|
+
readonly allowInputRequired?: boolean | undefined;
|
|
30
|
+
}
|
|
31
|
+
interface McpElicitationFormRequest {
|
|
32
|
+
readonly mode?: 'form' | undefined;
|
|
33
|
+
readonly message: string;
|
|
34
|
+
readonly requestedSchema: Record<string, unknown>;
|
|
35
|
+
readonly [key: string]: unknown;
|
|
36
|
+
}
|
|
37
|
+
interface McpElicitationUrlRequest {
|
|
38
|
+
readonly mode: 'url';
|
|
39
|
+
readonly message: string;
|
|
40
|
+
readonly url: string;
|
|
41
|
+
readonly elicitationId: string;
|
|
42
|
+
readonly [key: string]: unknown;
|
|
43
|
+
}
|
|
44
|
+
type McpElicitationRequest = McpElicitationFormRequest | McpElicitationUrlRequest;
|
|
45
|
+
type McpElicitationResult = {
|
|
46
|
+
readonly action: 'accept';
|
|
47
|
+
readonly content?: Record<string, unknown> | undefined;
|
|
48
|
+
} | {
|
|
49
|
+
readonly action: 'decline' | 'cancel';
|
|
50
|
+
};
|
|
51
|
+
interface McpElicitationHandlers {
|
|
52
|
+
readonly form?: ((request: McpElicitationFormRequest) => Promise<McpElicitationResult> | McpElicitationResult) | undefined;
|
|
53
|
+
readonly url?: ((request: McpElicitationUrlRequest) => Promise<McpElicitationResult> | McpElicitationResult) | undefined;
|
|
54
|
+
}
|
|
55
|
+
interface McpToolDescriptor {
|
|
56
|
+
readonly name: string;
|
|
57
|
+
readonly title?: string | undefined;
|
|
58
|
+
readonly description?: string | undefined;
|
|
59
|
+
readonly inputSchema?: Record<string, unknown> | undefined;
|
|
60
|
+
readonly outputSchema?: Record<string, unknown> | undefined;
|
|
61
|
+
readonly annotations?: McpToolAnnotations | undefined;
|
|
62
|
+
readonly execution?: McpToolExecution | undefined;
|
|
63
|
+
readonly icons?: readonly McpIcon[] | undefined;
|
|
64
|
+
readonly _meta?: Record<string, unknown> | undefined;
|
|
65
|
+
}
|
|
66
|
+
interface McpListToolsResult {
|
|
67
|
+
readonly tools: readonly McpToolDescriptor[];
|
|
68
|
+
readonly nextCursor?: string | undefined;
|
|
69
|
+
}
|
|
70
|
+
interface McpListToolsParams {
|
|
71
|
+
readonly cursor?: string | undefined;
|
|
72
|
+
}
|
|
73
|
+
interface McpContentBlock {
|
|
74
|
+
readonly type: string;
|
|
75
|
+
readonly text?: string | undefined;
|
|
76
|
+
readonly annotations?: Record<string, unknown> | undefined;
|
|
77
|
+
readonly _meta?: Record<string, unknown> | undefined;
|
|
78
|
+
readonly [key: string]: unknown;
|
|
79
|
+
}
|
|
80
|
+
interface McpCallToolResult {
|
|
81
|
+
readonly content: readonly McpContentBlock[];
|
|
82
|
+
readonly structuredContent?: unknown;
|
|
83
|
+
readonly isError?: boolean | undefined;
|
|
84
|
+
readonly _meta?: Record<string, unknown> | undefined;
|
|
85
|
+
}
|
|
86
|
+
interface McpInputRequiredResult {
|
|
87
|
+
readonly resultType: 'input_required';
|
|
88
|
+
readonly inputRequests?: Record<string, unknown> | undefined;
|
|
89
|
+
readonly requestState?: string | undefined;
|
|
90
|
+
readonly [key: string]: unknown;
|
|
91
|
+
}
|
|
92
|
+
type McpTaskStatus = 'working' | 'input_required' | 'completed' | 'failed' | 'cancelled';
|
|
93
|
+
interface McpTask {
|
|
94
|
+
readonly taskId: string;
|
|
95
|
+
readonly status: McpTaskStatus;
|
|
96
|
+
readonly statusMessage?: string | undefined;
|
|
97
|
+
readonly createdAt: string;
|
|
98
|
+
readonly lastUpdatedAt: string;
|
|
99
|
+
readonly ttl?: number | undefined;
|
|
100
|
+
readonly pollInterval?: number | undefined;
|
|
101
|
+
}
|
|
102
|
+
type McpTaskMethod = 'tasks/get' | 'tasks/result' | 'tasks/cancel';
|
|
103
|
+
interface McpTaskRequest {
|
|
104
|
+
readonly method: McpTaskMethod;
|
|
105
|
+
readonly params: {
|
|
106
|
+
readonly taskId: string;
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
interface McpCreateTaskResult {
|
|
110
|
+
readonly task: McpTask;
|
|
111
|
+
readonly _meta?: Record<string, unknown> | undefined;
|
|
112
|
+
}
|
|
113
|
+
type McpToolCallResult = McpCallToolResult | McpInputRequiredResult | McpCreateTaskResult;
|
|
114
|
+
interface McpServerCapabilities {
|
|
115
|
+
readonly tasks?: {
|
|
116
|
+
readonly requests?: {
|
|
117
|
+
readonly tools?: {
|
|
118
|
+
readonly call?: Record<string, unknown> | undefined;
|
|
119
|
+
} | undefined;
|
|
120
|
+
} | undefined;
|
|
121
|
+
} | undefined;
|
|
122
|
+
readonly [key: string]: unknown;
|
|
123
|
+
}
|
|
124
|
+
interface McpClientLike {
|
|
125
|
+
getServerCapabilities?: (() => McpServerCapabilities | undefined) | undefined;
|
|
126
|
+
request?: (<T>(request: McpTaskRequest, resultSchema: z.ZodType<T>, options?: McpRequestOptions) => Promise<T>) | undefined;
|
|
127
|
+
listTools: (params?: McpListToolsParams, options?: McpRequestOptions) => Promise<McpListToolsResult>;
|
|
128
|
+
callTool: (params: {
|
|
129
|
+
readonly name: string;
|
|
130
|
+
readonly arguments?: Record<string, unknown>;
|
|
131
|
+
readonly task?: {
|
|
132
|
+
readonly ttl?: number | undefined;
|
|
133
|
+
} | undefined;
|
|
134
|
+
readonly inputResponses?: Record<string, unknown> | undefined;
|
|
135
|
+
readonly requestState?: string | undefined;
|
|
136
|
+
}, options?: McpRequestOptions) => Promise<McpToolCallResult>;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export type { McpClientLike as M, McpToolDescriptor as a, McpTask as b, McpCallToolResult as c, McpContentBlock as d, McpCreateTaskResult as e, McpElicitationFormRequest as f, McpElicitationHandlers as g, McpElicitationRequest as h, McpElicitationResult as i, McpElicitationUrlRequest as j, McpIcon as k, McpInputRequiredResult as l, McpListToolsParams as m, McpListToolsResult as n, McpRequestOptions as o, McpServerCapabilities as p, McpTaskMethod as q, McpTaskRequest as r, McpTaskStatus as s, McpToolAnnotations as t, McpToolCallResult as u, McpToolExecution as v };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nemesis-oss/ollama-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.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",
|
|
@@ -172,6 +172,7 @@
|
|
|
172
172
|
"test": "vitest run",
|
|
173
173
|
"test:watch": "vitest",
|
|
174
174
|
"test:coverage": "vitest run --coverage",
|
|
175
|
+
"test:conformance": "vitest run test/conformance/",
|
|
175
176
|
"verify:edge-runtime": "tsx scripts/verify-edge-runtime.ts",
|
|
176
177
|
"verify:contract-parity": "tsx scripts/verify-contract-parity.ts",
|
|
177
178
|
"contract:fetch": "tsx scripts/fetch-contract.ts",
|
|
@@ -186,6 +187,7 @@
|
|
|
186
187
|
"verify": "npm run typecheck && npm run lint && npm run test && npm run build && npm run verify:edge-runtime && npm run verify:contract-parity",
|
|
187
188
|
"example": "tsx",
|
|
188
189
|
"lab": "tsx lab/run.ts",
|
|
190
|
+
"lab:live": "npm run build && tsx lab/live-tour.ts",
|
|
189
191
|
"prepublishOnly": "npm run clean && npm run typecheck && npm run lint && npm run test && npm run build && npm run verify:edge-runtime && npm run verify:contract-parity"
|
|
190
192
|
},
|
|
191
193
|
"peerDependencies": {
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Duck-typed MCP (Model Context Protocol) client interfaces.
|
|
3
|
-
* Decoupled from any specific MCP SDK.
|
|
4
|
-
*/
|
|
5
|
-
interface McpToolAnnotations {
|
|
6
|
-
readonly title?: string | undefined;
|
|
7
|
-
readonly readOnlyHint?: boolean | undefined;
|
|
8
|
-
readonly destructiveHint?: boolean | undefined;
|
|
9
|
-
readonly idempotentHint?: boolean | undefined;
|
|
10
|
-
readonly openWorldHint?: boolean | undefined;
|
|
11
|
-
readonly [key: string]: unknown;
|
|
12
|
-
}
|
|
13
|
-
interface McpToolExecution {
|
|
14
|
-
readonly taskSupport?: 'forbidden' | 'optional' | 'required' | undefined;
|
|
15
|
-
readonly [key: string]: unknown;
|
|
16
|
-
}
|
|
17
|
-
interface McpIcon {
|
|
18
|
-
readonly src: string;
|
|
19
|
-
readonly mimeType?: string | undefined;
|
|
20
|
-
readonly sizes?: readonly string[] | undefined;
|
|
21
|
-
readonly theme?: 'light' | 'dark' | undefined;
|
|
22
|
-
readonly [key: string]: unknown;
|
|
23
|
-
}
|
|
24
|
-
interface McpRequestOptions {
|
|
25
|
-
readonly signal?: AbortSignal | undefined;
|
|
26
|
-
}
|
|
27
|
-
interface McpToolDescriptor {
|
|
28
|
-
readonly name: string;
|
|
29
|
-
readonly title?: string | undefined;
|
|
30
|
-
readonly description?: string | undefined;
|
|
31
|
-
readonly inputSchema?: Record<string, unknown> | undefined;
|
|
32
|
-
readonly outputSchema?: Record<string, unknown> | undefined;
|
|
33
|
-
readonly annotations?: McpToolAnnotations | undefined;
|
|
34
|
-
readonly execution?: McpToolExecution | undefined;
|
|
35
|
-
readonly icons?: readonly McpIcon[] | undefined;
|
|
36
|
-
readonly _meta?: Record<string, unknown> | undefined;
|
|
37
|
-
}
|
|
38
|
-
interface McpListToolsResult {
|
|
39
|
-
readonly tools: readonly McpToolDescriptor[];
|
|
40
|
-
readonly nextCursor?: string | undefined;
|
|
41
|
-
}
|
|
42
|
-
interface McpListToolsParams {
|
|
43
|
-
readonly cursor?: string | undefined;
|
|
44
|
-
}
|
|
45
|
-
interface McpContentBlock {
|
|
46
|
-
readonly type: string;
|
|
47
|
-
readonly text?: string | undefined;
|
|
48
|
-
readonly annotations?: Record<string, unknown> | undefined;
|
|
49
|
-
readonly _meta?: Record<string, unknown> | undefined;
|
|
50
|
-
readonly [key: string]: unknown;
|
|
51
|
-
}
|
|
52
|
-
interface McpCallToolResult {
|
|
53
|
-
readonly content: readonly McpContentBlock[];
|
|
54
|
-
readonly structuredContent?: unknown;
|
|
55
|
-
readonly isError?: boolean | undefined;
|
|
56
|
-
readonly _meta?: Record<string, unknown> | undefined;
|
|
57
|
-
}
|
|
58
|
-
interface McpClientLike {
|
|
59
|
-
listTools: (params?: McpListToolsParams, options?: McpRequestOptions) => Promise<McpListToolsResult>;
|
|
60
|
-
callTool: (params: {
|
|
61
|
-
readonly name: string;
|
|
62
|
-
readonly arguments?: Record<string, unknown>;
|
|
63
|
-
}, options?: McpRequestOptions) => Promise<McpCallToolResult>;
|
|
64
|
-
}
|
|
65
|
-
|
|
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 };
|