@fhiron/sdk 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/_linter/catalog.js +3 -3
- package/src/_linter/i18n.js +16 -16
- package/src/_linter/rules.d.ts +12 -0
- package/src/_linter/terminology.js +1 -1
- package/src/http.js +7 -2
- package/src/index.d.ts +1 -1
package/README.md
CHANGED
|
@@ -112,7 +112,7 @@ try {
|
|
|
112
112
|
|----------------------|--------|
|
|
113
113
|
| `FhironAuthError` | HTTP 401 / 403: key ausente, inválida o sin permisos. |
|
|
114
114
|
| `FhironQuotaError` | HTTP 429: cuota agotada (`.upgradeUrl`). |
|
|
115
|
-
| `FhironRequestError` | HTTP 400 / 415
|
|
115
|
+
| `FhironRequestError` | HTTP 400 / 415: petición malformada (JSON inválido, Content-Type incorrecto). Un recurso inválido NO lanza: devuelve un resultado con `ok:false` y los errores en `result.errors`. |
|
|
116
116
|
| `FhironServerError` | HTTP 5xx: servidor o motor. Reintentable. |
|
|
117
117
|
| `FhironTimeoutError` | Supera `timeout`. Reintentable. |
|
|
118
118
|
| `FhironNetworkError` | Fallo de red / offline. Reintentable. |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fhiron/sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Fhiron SDK — embebe validación FHIR® contra CL Core v1.9.4 en tu app. Mismo motor que @fhiron/mcp-connector y @fhiron/cli. Cliente tipado, errores en español, zero dependencies. Node 18+, ESM y CommonJS.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "src/index.js",
|
package/src/_linter/catalog.js
CHANGED
|
@@ -486,7 +486,7 @@ const CATALOG = {
|
|
|
486
486
|
},
|
|
487
487
|
"cl-cov-04": {
|
|
488
488
|
why: "Coverage en Chile debe identificar al titular de la cobertura. Para Fonasa es el RUN del cotizante, para ISAPRE el número de contrato. Sin `subscriberId` el dispensador no puede liquidar.",
|
|
489
|
-
suggestion: "`subscriberId: \"15420097-
|
|
489
|
+
suggestion: "`subscriberId: \"15420097-5\"` (RUN del cotizante en Fonasa) o número de contrato ISAPRE.",
|
|
490
490
|
docsUrl: DOCS("cl-cov-04"),
|
|
491
491
|
},
|
|
492
492
|
"cl-imm-05": {
|
|
@@ -585,12 +585,12 @@ const CATALOG = {
|
|
|
585
585
|
docsUrl: DOCS("mcp-quota-01"),
|
|
586
586
|
},
|
|
587
587
|
"mcp-net-01": {
|
|
588
|
-
why: "No se pudo establecer conexión con Fhiron
|
|
588
|
+
why: "No se pudo establecer conexión con Fhiron Inspect: red caída, firewall, DNS o el servicio está reiniciando.",
|
|
589
589
|
suggestion: "Revisa tu conexión, el firewall corporativo y el estado del servicio en https://status.fhiron.cl.",
|
|
590
590
|
docsUrl: DOCS("mcp-net-01"),
|
|
591
591
|
},
|
|
592
592
|
"mcp-server-01": {
|
|
593
|
-
why: "El servidor respondió 500
|
|
593
|
+
why: "El servidor respondió 500: bug en Fhiron Inspect, no en tu recurso.",
|
|
594
594
|
suggestion: "Reintenta en unos segundos. Si persiste, reporta el caso en https://github.com/Fhironstack/skills/issues incluyendo el recurso (sin datos sensibles).",
|
|
595
595
|
docsUrl: DOCS("mcp-server-01"),
|
|
596
596
|
},
|
package/src/_linter/i18n.js
CHANGED
|
@@ -26,8 +26,8 @@ const DICT = {
|
|
|
26
26
|
|
|
27
27
|
// ── serverInfo description ────────────────────────────────────────────────
|
|
28
28
|
"server.description": {
|
|
29
|
-
es: "Fhiron
|
|
30
|
-
en: "Fhiron
|
|
29
|
+
es: "Fhiron Inspect — validación FHIR contra CL Core v1.9.4 con errores en español, ejemplos válidos y catálogos terminológicos chilenos (DEIS, TFC, CIE-10).",
|
|
30
|
+
en: "Fhiron Inspect — FHIR validation against CL Core v1.9.4 with educational issue feedback, valid resource examples, and Chilean terminology catalogs (DEIS, TFC, ICD-10). Server messages are localized; rule explanations remain in Spanish (CL Core is a Chilean implementation guide).",
|
|
31
31
|
},
|
|
32
32
|
|
|
33
33
|
// ── Tool descriptions ─────────────────────────────────────────────────────
|
|
@@ -68,7 +68,7 @@ const DICT = {
|
|
|
68
68
|
en: "[FIX] Apply a mechanical quickFix to a FHIR resource using RFC 6901 jsonPointer. QuickFixes come from the `issues[]` array of fhiron_validate or fhiron_lint. Returns the patched resource as JSON. Idempotent: applying the same fix twice yields the same result. Call this tool immediately after validating if the issue has `quickFix` — the AI can auto-correct without asking the user.",
|
|
69
69
|
},
|
|
70
70
|
"tool.get_example.desc": {
|
|
71
|
-
es: "[SCAFFOLD] Devuelve un recurso FHIR válido CL Core v1.9.4 listo para editar (Patient, Practitioner, Observation, Medication, MedicationRequest, Encounter, Condition, AllergyIntolerance, Procedure, Coverage, Organization, Immunization, DiagnosticReport, Bundle). Útil cuando la IA necesita scaffolding sin alucinar codes, systems o el formato del RUN.
|
|
71
|
+
es: "[SCAFFOLD] Devuelve un recurso FHIR válido CL Core v1.9.4 listo para editar (Patient, Practitioner, Observation, Medication, MedicationRequest, Encounter, Condition, AllergyIntolerance, Procedure, Coverage, Organization, Immunization, DiagnosticReport, Bundle). Útil cuando la IA necesita scaffolding sin alucinar codes, systems o el formato del RUN. Llama esta tool antes de armar un recurso desde cero.",
|
|
72
72
|
en: "[SCAFFOLD] Return a valid CL Core v1.9.4 FHIR resource ready to edit (Patient, Practitioner, Observation, Medication, MedicationRequest, Encounter, Condition, AllergyIntolerance, Procedure, Coverage, Organization, Immunization, DiagnosticReport, Bundle). Useful when the AI needs scaffolding without hallucinating codes, systems or RUN format. Call this tool before building a resource from scratch.",
|
|
73
73
|
},
|
|
74
74
|
"tool.search_terminology.desc": {
|
|
@@ -76,7 +76,7 @@ const DICT = {
|
|
|
76
76
|
en: "[TERMINOLOGY] Search Chilean terminology catalogs: DEIS communes (system 'deis-comuna'), DEIS facilities ('deis-establecimiento'), ATC/TFC medications ('tfc'), ICD-10 diagnoses ('cie10'), CSTipoIdentificador ('identificadores'). Call this tool BEFORE inventing a code — the AI should look up, not guess.",
|
|
77
77
|
},
|
|
78
78
|
"tool.explain_code.desc": {
|
|
79
|
-
es: "[EXPLAIN] Devuelve la explicación pedagógica completa de un código de error (cl-run-01, cl-patient-04, hapi-error, mcp-quota-01, etc.): qué falla, por qué, qué perfil CL Core lo indica, link de docs, fix sugerido y ejemplo correcto.
|
|
79
|
+
es: "[EXPLAIN] Devuelve la explicación pedagógica completa de un código de error (cl-run-01, cl-patient-04, hapi-error, mcp-quota-01, etc.): qué falla, por qué, qué perfil CL Core lo indica, link de docs, fix sugerido y ejemplo correcto. Llama esta tool cuando el usuario pregunta '¿qué significa este error?' o '¿por qué falla?'.",
|
|
80
80
|
en: "[EXPLAIN] Return the full educational explanation of an error code (cl-run-01, cl-patient-04, hapi-error, mcp-quota-01, etc.): what fails, why, which CL Core profile flags it, docs link, suggested fix and valid example. Call this tool when the user asks 'what does this error mean?' or 'why is it failing?'.",
|
|
81
81
|
},
|
|
82
82
|
|
|
@@ -137,12 +137,12 @@ const DICT = {
|
|
|
137
137
|
},
|
|
138
138
|
"err.resource_type.short": { es: "Falta resourceType.", en: "Missing resourceType." },
|
|
139
139
|
"err.timeout": {
|
|
140
|
-
es: "Fhiron
|
|
141
|
-
en: "Fhiron
|
|
140
|
+
es: "Fhiron Inspect tardó más de 10s en responder. Reintenta en un momento.",
|
|
141
|
+
en: "Fhiron Inspect took longer than 10s to respond. Please retry in a moment.",
|
|
142
142
|
},
|
|
143
143
|
"err.network": {
|
|
144
|
-
es: (v) => `No se pudo conectar a Fhiron
|
|
145
|
-
en: (v) => `Could not connect to Fhiron
|
|
144
|
+
es: (v) => `No se pudo conectar a Fhiron Inspect (${v.endpoint}). Revisa tu conexión o el estado del servicio en status.fhiron.cl.`,
|
|
145
|
+
en: (v) => `Could not connect to Fhiron Inspect (${v.endpoint}). Check your connection or service status at status.fhiron.cl.`,
|
|
146
146
|
},
|
|
147
147
|
"err.auth": {
|
|
148
148
|
es: (v) => `API key rechazada (HTTP ${v.status}). Verifica el valor en https://fhiron.cl/dashboard/connect-ai.`,
|
|
@@ -154,16 +154,16 @@ const DICT = {
|
|
|
154
154
|
en: (v) => `${v.detail} Upgrade your plan at https://fhiron.cl/precios.`,
|
|
155
155
|
},
|
|
156
156
|
"err.server_500": {
|
|
157
|
-
es: "Fhiron
|
|
158
|
-
en: "Fhiron
|
|
157
|
+
es: "Fhiron Inspect tuvo un error interno. Intenta de nuevo en unos segundos.",
|
|
158
|
+
en: "Fhiron Inspect had an internal error. Please retry in a few seconds.",
|
|
159
159
|
},
|
|
160
160
|
"err.server_5xx": {
|
|
161
161
|
es: (v) => `Servicio temporalmente no disponible (HTTP ${v.status}). Reintenta en 1-2 minutos o revisa status.fhiron.cl.`,
|
|
162
162
|
en: (v) => `Service temporarily unavailable (HTTP ${v.status}). Retry in 1-2 minutes or check status.fhiron.cl.`,
|
|
163
163
|
},
|
|
164
164
|
"err.server_other": {
|
|
165
|
-
es: (v) => `Fhiron
|
|
166
|
-
en: (v) => `Fhiron
|
|
165
|
+
es: (v) => `Fhiron Inspect respondió ${v.status}: ${v.detail}`,
|
|
166
|
+
en: (v) => `Fhiron Inspect responded ${v.status}: ${v.detail}`,
|
|
167
167
|
},
|
|
168
168
|
"err.unknown_tool": {
|
|
169
169
|
es: (v) => `Herramienta desconocida: ${v.name}. Disponibles: ${v.list}.`,
|
|
@@ -235,8 +235,8 @@ const DICT = {
|
|
|
235
235
|
// ── Logging notifications (M8) ────────────────────────────────────────────
|
|
236
236
|
"log.lint.start": { es: (v) => `Linter local sobre ${v.resourceType}…`, en: (v) => `Local linter on ${v.resourceType}…` },
|
|
237
237
|
"log.lint.done": { es: (v) => `Linter local: ${v.errors} error(es), ${v.warnings} advertencia(s).`, en: (v) => `Local linter: ${v.errors} error(s), ${v.warnings} warning(s).` },
|
|
238
|
-
"log.bridge.call": { es: (v) => `Llamando a HAPI
|
|
239
|
-
"log.bridge.done": { es: (v) => `
|
|
238
|
+
"log.bridge.call": { es: (v) => `Llamando a HAPI Inspect (${v.endpoint})…`, en: (v) => `Calling HAPI Inspect (${v.endpoint})…` },
|
|
239
|
+
"log.bridge.done": { es: (v) => `Inspect respondió en ${v.ms}ms (status ${v.status}).`, en: (v) => `Inspect responded in ${v.ms}ms (status ${v.status}).` },
|
|
240
240
|
|
|
241
241
|
// ── RUN — errores de validación (módulo 11) ───────────────────────────────
|
|
242
242
|
"run.err.no_dash": {
|
|
@@ -358,8 +358,8 @@ const DICT = {
|
|
|
358
358
|
en: (v) => `Method '${v.method}' requires completing the initialize handshake + notifications/initialized first (MCP spec).`,
|
|
359
359
|
},
|
|
360
360
|
"bridge.fallback.server_error": {
|
|
361
|
-
es: "Fhiron
|
|
362
|
-
en: "Fhiron
|
|
361
|
+
es: "Fhiron Inspect respondió con un error inesperado. Intenta de nuevo en unos segundos.",
|
|
362
|
+
en: "Fhiron Inspect responded with an unexpected error. Please retry in a few seconds.",
|
|
363
363
|
},
|
|
364
364
|
"explain.fallback.no_context": {
|
|
365
365
|
es: "No hay explicación adicional disponible para este código.",
|
package/src/_linter/rules.d.ts
CHANGED
|
@@ -103,3 +103,15 @@ export declare function listCodes(): string[];
|
|
|
103
103
|
* Si el código no está en el catálogo, devuelve el issue intacto.
|
|
104
104
|
*/
|
|
105
105
|
export declare function enrichIssue(issue: LintIssue): LintIssue;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Recursos FHIR de ejemplo válidos contra CL Core, indexados por resourceType.
|
|
109
|
+
* Usados por el demo público, el MCP (`fhiron_get_example`) y los docs.
|
|
110
|
+
*/
|
|
111
|
+
export declare const EXAMPLES: Record<string, Record<string, unknown>>;
|
|
112
|
+
|
|
113
|
+
/** Devuelve un recurso de ejemplo válido para el resourceType dado, o null. */
|
|
114
|
+
export declare function getExample(resourceType: string): Record<string, unknown> | null;
|
|
115
|
+
|
|
116
|
+
/** Lista los resourceType para los que hay ejemplo disponible. */
|
|
117
|
+
export declare function listExamples(): string[];
|
package/src/http.js
CHANGED
|
@@ -76,7 +76,11 @@ async function postJson(url, opts) {
|
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
// HTTP 422 NO es un error de petición: es el resultado de validación cuando
|
|
80
|
+
// el recurso es inválido. El endpoint /api/validate responde `valid ? 200 : 422`
|
|
81
|
+
// con el mismo body (ValidateResponse: { valid, errors, warnings, issues, ... }).
|
|
82
|
+
// Igual que @fhiron/mcp-connector, tratamos 422 como respuesta normalizable.
|
|
83
|
+
if (res.ok || res.status === 422) return payload;
|
|
80
84
|
|
|
81
85
|
throwForStatus(res.status, payload);
|
|
82
86
|
}
|
|
@@ -109,7 +113,8 @@ function throwForStatus(status, payload) {
|
|
|
109
113
|
{ ...details, upgradeUrl: (payload && payload.upgrade_url) || 'https://fhiron.cl/precios' },
|
|
110
114
|
);
|
|
111
115
|
}
|
|
112
|
-
|
|
116
|
+
// 422 ya no llega aquí (se trata como resultado de validación en postJson).
|
|
117
|
+
if (status === 400 || status === 415) {
|
|
113
118
|
throw new FhironRequestError(
|
|
114
119
|
serverMsg || `La petición no es válida (HTTP ${status}).`,
|
|
115
120
|
details,
|
package/src/index.d.ts
CHANGED
|
@@ -108,7 +108,7 @@ export declare class FhironAuthError extends FhironError {}
|
|
|
108
108
|
export declare class FhironQuotaError extends FhironError {
|
|
109
109
|
upgradeUrl?: string;
|
|
110
110
|
}
|
|
111
|
-
/** HTTP 400/415
|
|
111
|
+
/** HTTP 400/415: problema de forma de la petición (el 422 es resultado de validación, no error). */
|
|
112
112
|
export declare class FhironRequestError extends FhironError {}
|
|
113
113
|
/** HTTP 5xx (reintentable). */
|
|
114
114
|
export declare class FhironServerError extends FhironError {}
|