@zenti/sdk 0.1.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/.gitattributes +6 -0
- package/README.md +211 -0
- package/dist/PersonaLayer.d.ts +28 -0
- package/dist/PersonaLayer.js +89 -0
- package/dist/cli/commands/diff.d.ts +2 -0
- package/dist/cli/commands/diff.js +129 -0
- package/dist/cli/commands/init.d.ts +4 -0
- package/dist/cli/commands/init.js +88 -0
- package/dist/cli/commands/test.d.ts +5 -0
- package/dist/cli/commands/test.js +121 -0
- package/dist/cli/commands/validate.d.ts +2 -0
- package/dist/cli/commands/validate.js +80 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.js +42 -0
- package/dist/compiler/index.d.ts +5 -0
- package/dist/compiler/index.js +12 -0
- package/dist/compiler/toClaude.d.ts +15 -0
- package/dist/compiler/toClaude.js +62 -0
- package/dist/compiler/toGemini.d.ts +22 -0
- package/dist/compiler/toGemini.js +53 -0
- package/dist/compiler/toOpenAI.d.ts +17 -0
- package/dist/compiler/toOpenAI.js +51 -0
- package/dist/compiler/utils.d.ts +7 -0
- package/dist/compiler/utils.js +27 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +14 -0
- package/dist/parser/index.d.ts +34 -0
- package/dist/parser/index.js +160 -0
- package/examples/sofia.zenti +46 -0
- package/package.json +54 -0
- package/src/PersonaLayer.ts +63 -0
- package/src/cli/commands/diff.ts +112 -0
- package/src/cli/commands/init.ts +55 -0
- package/src/cli/commands/test.ts +105 -0
- package/src/cli/commands/validate.ts +52 -0
- package/src/cli/index.ts +47 -0
- package/src/compiler/index.ts +4 -0
- package/src/compiler/toClaude.ts +74 -0
- package/src/compiler/toGemini.ts +76 -0
- package/src/compiler/toOpenAI.ts +70 -0
- package/src/compiler/utils.ts +27 -0
- package/src/index.ts +14 -0
- package/src/parser/index.ts +164 -0
- package/tests/compiler.test.ts +218 -0
- package/tests/parser.test.ts +132 -0
- package/tsconfig.json +19 -0
- package/tsconfig.test.json +7 -0
package/.gitattributes
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# @zenti/sdk
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@zenti/sdk)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
SDK open source en TypeScript para capturar, almacenar y deployar personalidades de agentes IA de forma portable entre modelos — GPT, Claude, Gemini, Llama.
|
|
7
|
+
|
|
8
|
+
Define tu agente **una vez** en un archivo `.zenti` y despliégalo en cualquier LLM sin reescribir el system prompt.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Instalación
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# npm
|
|
16
|
+
npm install @zenti/sdk
|
|
17
|
+
|
|
18
|
+
# yarn
|
|
19
|
+
yarn add @zenti/sdk
|
|
20
|
+
|
|
21
|
+
# Global (para el CLI)
|
|
22
|
+
npm install -g @zenti/sdk
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Uso básico
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { PersonaLayer } from '@zenti/sdk';
|
|
31
|
+
|
|
32
|
+
const persona = PersonaLayer.load('./sofia.zenti');
|
|
33
|
+
|
|
34
|
+
// Despliega en Claude
|
|
35
|
+
const { system } = persona.deploy('claude');
|
|
36
|
+
|
|
37
|
+
// Despliega en OpenAI
|
|
38
|
+
const { system: openaiSystem, messages } = persona.deploy('openai');
|
|
39
|
+
|
|
40
|
+
// Despliega en Gemini
|
|
41
|
+
const { systemInstruction, contents } = persona.deploy('gemini');
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Formato `.zenti`
|
|
47
|
+
|
|
48
|
+
El archivo de personalidad usa YAML con 4 capas obligatorias:
|
|
49
|
+
|
|
50
|
+
```yaml
|
|
51
|
+
version: "1.0"
|
|
52
|
+
name: "Sofia"
|
|
53
|
+
|
|
54
|
+
# Capa 1 — Núcleo psicológico (Big Five, valores 0.0 a 1.0)
|
|
55
|
+
core:
|
|
56
|
+
openness: 0.7 # Creatividad y apertura a nuevas ideas
|
|
57
|
+
conscientiousness: 0.9 # Meticulosidad y organización
|
|
58
|
+
extraversion: 0.4 # Sociabilidad (< 0.5 = reservado)
|
|
59
|
+
agreeableness: 0.8 # Empatía y cooperación
|
|
60
|
+
neuroticism: 0.2 # Estabilidad emocional (0 = muy estable)
|
|
61
|
+
|
|
62
|
+
# Capa 2 — Identidad narrativa
|
|
63
|
+
identity:
|
|
64
|
+
role: "Asistente de soporte de TechCorp"
|
|
65
|
+
backstory: "Experta técnica con 5 años de experiencia, paciente y directa"
|
|
66
|
+
communication_style: "profesional con calidez, respuestas concisas"
|
|
67
|
+
|
|
68
|
+
# Capa 3 — Few-shot examples
|
|
69
|
+
examples:
|
|
70
|
+
on_brand:
|
|
71
|
+
- user: "no funciona"
|
|
72
|
+
agent: "Entiendo tu frustración. Cuéntame qué error ves."
|
|
73
|
+
off_brand:
|
|
74
|
+
- user: "no funciona"
|
|
75
|
+
agent: "No sé, prueba reiniciando."
|
|
76
|
+
|
|
77
|
+
# Capa 4 — Guardrails
|
|
78
|
+
guardrails:
|
|
79
|
+
always:
|
|
80
|
+
- "Reconocer el problema antes de dar solución"
|
|
81
|
+
never:
|
|
82
|
+
- "Decir 'no puedo' sin ofrecer alternativa"
|
|
83
|
+
escalate_if:
|
|
84
|
+
- "El usuario menciona cancelación"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Referencia de campos
|
|
88
|
+
|
|
89
|
+
| Campo | Tipo | Descripción |
|
|
90
|
+
|-------|------|-------------|
|
|
91
|
+
| `version` | `string` | Versión del formato (actualmente `"1.0"`) |
|
|
92
|
+
| `name` | `string` | Nombre del agente |
|
|
93
|
+
| `core.*` | `number` | Valores Big Five entre `0.0` y `1.0` |
|
|
94
|
+
| `identity.role` | `string` | Título o función del agente |
|
|
95
|
+
| `identity.backstory` | `string` | Perfil y experiencia del agente |
|
|
96
|
+
| `identity.communication_style` | `string` | Cómo se expresa el agente |
|
|
97
|
+
| `examples.on_brand` | `array` | Ejemplos de respuestas correctas |
|
|
98
|
+
| `examples.off_brand` | `array` | Ejemplos de respuestas a evitar |
|
|
99
|
+
| `guardrails.always` | `array` | Reglas que siempre deben cumplirse |
|
|
100
|
+
| `guardrails.never` | `array` | Comportamientos prohibidos |
|
|
101
|
+
| `guardrails.escalate_if` | `array` | Condiciones que activan escalación |
|
|
102
|
+
|
|
103
|
+
### Traducción Big Five → lenguaje natural
|
|
104
|
+
|
|
105
|
+
El compilador traduce automáticamente los valores numéricos a descriptores en el system prompt:
|
|
106
|
+
|
|
107
|
+
| Condición | Descripción generada |
|
|
108
|
+
|-----------|---------------------|
|
|
109
|
+
| `openness > 0.6` | creativo y curioso, abierto a explorar soluciones nuevas |
|
|
110
|
+
| `conscientiousness > 0.7` | metódico y confiable, siempre sigue los pasos correctos |
|
|
111
|
+
| `extraversion < 0.5` | reservado pero atento, responde con precisión sin ser efusivo |
|
|
112
|
+
| `agreeableness > 0.7` | empático y colaborativo, prioriza la satisfacción del usuario |
|
|
113
|
+
| `neuroticism < 0.3` | calmado bajo presión, mantiene tono estable ante usuarios frustrados |
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## CLI
|
|
118
|
+
|
|
119
|
+
### `zenti init`
|
|
120
|
+
Crea un archivo `persona.zenti` con template vacío en el directorio actual.
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
zenti init
|
|
124
|
+
zenti init --output ./agents/mi-agente.zenti
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### `zenti validate [archivo]`
|
|
128
|
+
Parsea y valida un archivo `.zenti`, mostrando errores o confirmación.
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
zenti validate
|
|
132
|
+
zenti validate ./sofia.zenti
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### `zenti test`
|
|
136
|
+
Carga el `.zenti` del directorio actual y abre un chat interactivo en la terminal usando Claude.
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
zenti test
|
|
140
|
+
zenti test --file ./sofia.zenti
|
|
141
|
+
zenti test --key sk-ant-...
|
|
142
|
+
# O establece ANTHROPIC_API_KEY en tu entorno
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### `zenti diff <archivo1> <archivo2>`
|
|
146
|
+
Compara dos archivos `.zenti` y muestra qué cambió entre versiones.
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
zenti diff sofia-v1.zenti sofia-v2.zenti
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Uso programático avanzado
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
import { PersonaLayer, toClaude, toOpenAI, toGemini, parseZenti } from '@zenti/sdk';
|
|
158
|
+
|
|
159
|
+
// Desde un string YAML (útil para tests o almacenamiento en DB)
|
|
160
|
+
const persona = PersonaLayer.fromString(yamlString);
|
|
161
|
+
|
|
162
|
+
// Acceder al objeto de personalidad directamente
|
|
163
|
+
const raw = persona.getPersona();
|
|
164
|
+
console.log(raw.core.openness);
|
|
165
|
+
|
|
166
|
+
// Compilar manualmente sin PersonaLayer
|
|
167
|
+
import * as fs from 'fs';
|
|
168
|
+
import { parseZenti } from '@zenti/sdk';
|
|
169
|
+
|
|
170
|
+
const zentiData = parseZenti(fs.readFileSync('sofia.zenti', 'utf-8'));
|
|
171
|
+
const claudePrompt = toClaude(zentiData);
|
|
172
|
+
const openaiConfig = toOpenAI(zentiData);
|
|
173
|
+
const geminiConfig = toGemini(zentiData);
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Desarrollo
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
git clone https://github.com/tu-org/zenti-sdk.git
|
|
182
|
+
cd zenti-sdk
|
|
183
|
+
npm install
|
|
184
|
+
npm run build # Compila TypeScript
|
|
185
|
+
npm test # Ejecuta los tests
|
|
186
|
+
npm run lint # Type-check sin emitir archivos
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Documentación
|
|
192
|
+
|
|
193
|
+
Documentación completa en: [docs.zenti.dev](https://docs.zenti.dev) *(próximamente)*
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Contribuciones
|
|
198
|
+
|
|
199
|
+
Las contribuciones son bienvenidas. Por favor abre un issue primero para discutir cambios mayores.
|
|
200
|
+
|
|
201
|
+
1. Fork el repositorio
|
|
202
|
+
2. Crea tu branch: `git checkout -b feature/mi-feature`
|
|
203
|
+
3. Commit tus cambios: `git commit -m 'feat: agregar soporte para X'`
|
|
204
|
+
4. Push: `git push origin feature/mi-feature`
|
|
205
|
+
5. Abre un Pull Request
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Licencia
|
|
210
|
+
|
|
211
|
+
MIT — ver [LICENSE](LICENSE) para más detalles.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ZentiPersona } from './parser';
|
|
2
|
+
import { ClaudeOutput } from './compiler/toClaude';
|
|
3
|
+
import { OpenAIOutput } from './compiler/toOpenAI';
|
|
4
|
+
import { GeminiOutput } from './compiler/toGemini';
|
|
5
|
+
export type DeployTarget = 'claude' | 'openai' | 'gemini';
|
|
6
|
+
export type DeployOutput<T extends DeployTarget> = T extends 'claude' ? ClaudeOutput : T extends 'openai' ? OpenAIOutput : GeminiOutput;
|
|
7
|
+
export declare class PersonaLayer {
|
|
8
|
+
private readonly persona;
|
|
9
|
+
private constructor();
|
|
10
|
+
/**
|
|
11
|
+
* Loads and validates a .zenti file from disk.
|
|
12
|
+
*/
|
|
13
|
+
static load(filePath: string): PersonaLayer;
|
|
14
|
+
/**
|
|
15
|
+
* Parses a .zenti file from a YAML string (useful for testing or in-memory use).
|
|
16
|
+
*/
|
|
17
|
+
static fromString(yamlContent: string): PersonaLayer;
|
|
18
|
+
getPersona(): ZentiPersona;
|
|
19
|
+
getName(): string;
|
|
20
|
+
/**
|
|
21
|
+
* Compiles the persona into the target model's native format.
|
|
22
|
+
*
|
|
23
|
+
* @param target - 'claude' | 'openai' | 'gemini'
|
|
24
|
+
* @returns The compiled output ready to pass to the model's API
|
|
25
|
+
*/
|
|
26
|
+
deploy<T extends DeployTarget>(target: T): DeployOutput<T>;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=PersonaLayer.d.ts.map
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.PersonaLayer = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const parser_1 = require("./parser");
|
|
40
|
+
const toClaude_1 = require("./compiler/toClaude");
|
|
41
|
+
const toOpenAI_1 = require("./compiler/toOpenAI");
|
|
42
|
+
const toGemini_1 = require("./compiler/toGemini");
|
|
43
|
+
class PersonaLayer {
|
|
44
|
+
constructor(persona) {
|
|
45
|
+
this.persona = persona;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Loads and validates a .zenti file from disk.
|
|
49
|
+
*/
|
|
50
|
+
static load(filePath) {
|
|
51
|
+
const absolutePath = path.resolve(filePath);
|
|
52
|
+
const content = fs.readFileSync(absolutePath, 'utf-8');
|
|
53
|
+
const persona = (0, parser_1.parseZenti)(content);
|
|
54
|
+
return new PersonaLayer(persona);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Parses a .zenti file from a YAML string (useful for testing or in-memory use).
|
|
58
|
+
*/
|
|
59
|
+
static fromString(yamlContent) {
|
|
60
|
+
const persona = (0, parser_1.parseZenti)(yamlContent);
|
|
61
|
+
return new PersonaLayer(persona);
|
|
62
|
+
}
|
|
63
|
+
getPersona() {
|
|
64
|
+
return this.persona;
|
|
65
|
+
}
|
|
66
|
+
getName() {
|
|
67
|
+
return this.persona.name;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Compiles the persona into the target model's native format.
|
|
71
|
+
*
|
|
72
|
+
* @param target - 'claude' | 'openai' | 'gemini'
|
|
73
|
+
* @returns The compiled output ready to pass to the model's API
|
|
74
|
+
*/
|
|
75
|
+
deploy(target) {
|
|
76
|
+
switch (target) {
|
|
77
|
+
case 'claude':
|
|
78
|
+
return (0, toClaude_1.toClaude)(this.persona);
|
|
79
|
+
case 'openai':
|
|
80
|
+
return (0, toOpenAI_1.toOpenAI)(this.persona);
|
|
81
|
+
case 'gemini':
|
|
82
|
+
return (0, toGemini_1.toGemini)(this.persona);
|
|
83
|
+
default:
|
|
84
|
+
throw new Error(`Target desconocido: ${target}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
exports.PersonaLayer = PersonaLayer;
|
|
89
|
+
//# sourceMappingURL=PersonaLayer.js.map
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.diffCommand = diffCommand;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const parser_1 = require("../../parser");
|
|
40
|
+
function diffCommand(file1, file2) {
|
|
41
|
+
const path1 = path.resolve(file1);
|
|
42
|
+
const path2 = path.resolve(file2);
|
|
43
|
+
if (!fs.existsSync(path1)) {
|
|
44
|
+
console.error(`Error: No se encontró: ${path1}`);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
if (!fs.existsSync(path2)) {
|
|
48
|
+
console.error(`Error: No se encontró: ${path2}`);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
const p1 = (0, parser_1.parseZenti)(fs.readFileSync(path1, 'utf-8'));
|
|
52
|
+
const p2 = (0, parser_1.parseZenti)(fs.readFileSync(path2, 'utf-8'));
|
|
53
|
+
const changes = [];
|
|
54
|
+
// Top-level scalars
|
|
55
|
+
if (p1.name !== p2.name) {
|
|
56
|
+
changes.push(` name: "${p1.name}" → "${p2.name}"`);
|
|
57
|
+
}
|
|
58
|
+
if (p1.version !== p2.version) {
|
|
59
|
+
changes.push(` version: "${p1.version}" → "${p2.version}"`);
|
|
60
|
+
}
|
|
61
|
+
// Core (Big Five)
|
|
62
|
+
const coreKeys = [
|
|
63
|
+
'openness',
|
|
64
|
+
'conscientiousness',
|
|
65
|
+
'extraversion',
|
|
66
|
+
'agreeableness',
|
|
67
|
+
'neuroticism',
|
|
68
|
+
];
|
|
69
|
+
coreKeys.forEach((key) => {
|
|
70
|
+
if (p1.core[key] !== p2.core[key]) {
|
|
71
|
+
changes.push(` core.${key}: ${p1.core[key]} → ${p2.core[key]}`);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
// Identity
|
|
75
|
+
const identityKeys = ['role', 'backstory', 'communication_style'];
|
|
76
|
+
identityKeys.forEach((key) => {
|
|
77
|
+
if (p1.identity[key] !== p2.identity[key]) {
|
|
78
|
+
changes.push(` identity.${key}: "${p1.identity[key]}" → "${p2.identity[key]}"`);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
// Guardrails (set diff)
|
|
82
|
+
const guardrailKeys = ['always', 'never', 'escalate_if'];
|
|
83
|
+
guardrailKeys.forEach((key) => {
|
|
84
|
+
const a1 = p1.guardrails[key];
|
|
85
|
+
const a2 = p2.guardrails[key];
|
|
86
|
+
a2
|
|
87
|
+
.filter((x) => !a1.includes(x))
|
|
88
|
+
.forEach((x) => changes.push(` + guardrails.${key}: "${x}"`));
|
|
89
|
+
a1
|
|
90
|
+
.filter((x) => !a2.includes(x))
|
|
91
|
+
.forEach((x) => changes.push(` - guardrails.${key}: "${x}"`));
|
|
92
|
+
});
|
|
93
|
+
// Examples (positional diff)
|
|
94
|
+
const exampleKeys = ['on_brand', 'off_brand'];
|
|
95
|
+
exampleKeys.forEach((key) => {
|
|
96
|
+
const ex1 = p1.examples[key];
|
|
97
|
+
const ex2 = p2.examples[key];
|
|
98
|
+
const maxLen = Math.max(ex1.length, ex2.length);
|
|
99
|
+
for (let i = 0; i < maxLen; i++) {
|
|
100
|
+
if (i >= ex1.length) {
|
|
101
|
+
changes.push(` + examples.${key}[${i}]: { user: "${ex2[i].user}", agent: "${ex2[i].agent}" }`);
|
|
102
|
+
}
|
|
103
|
+
else if (i >= ex2.length) {
|
|
104
|
+
changes.push(` - examples.${key}[${i}]: { user: "${ex1[i].user}", agent: "${ex1[i].agent}" }`);
|
|
105
|
+
}
|
|
106
|
+
else if (ex1[i].user !== ex2[i].user || ex1[i].agent !== ex2[i].agent) {
|
|
107
|
+
changes.push(` ~ examples.${key}[${i}]:`);
|
|
108
|
+
if (ex1[i].user !== ex2[i].user) {
|
|
109
|
+
changes.push(` user: "${ex1[i].user}" → "${ex2[i].user}"`);
|
|
110
|
+
}
|
|
111
|
+
if (ex1[i].agent !== ex2[i].agent) {
|
|
112
|
+
changes.push(` agent: "${ex1[i].agent}" → "${ex2[i].agent}"`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
// Output
|
|
118
|
+
console.log(`Comparando ${file1} → ${file2}`);
|
|
119
|
+
console.log('');
|
|
120
|
+
if (changes.length === 0) {
|
|
121
|
+
console.log('Sin diferencias — los archivos son idénticos en contenido.');
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
console.log(`CAMBIOS (${changes.length} diferencias):`);
|
|
125
|
+
console.log('');
|
|
126
|
+
changes.forEach((c) => console.log(c));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=diff.js.map
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.initCommand = initCommand;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const TEMPLATE = `version: "1.0"
|
|
40
|
+
name: "MiAgente"
|
|
41
|
+
|
|
42
|
+
# ── Capa 1: Núcleo psicológico (Big Five, valores 0.0 a 1.0) ──────────────
|
|
43
|
+
core:
|
|
44
|
+
openness: 0.5 # creatividad y apertura a nuevas ideas
|
|
45
|
+
conscientiousness: 0.5 # meticulosidad y organización
|
|
46
|
+
extraversion: 0.5 # sociabilidad y energía
|
|
47
|
+
agreeableness: 0.5 # empatía y cooperación
|
|
48
|
+
neuroticism: 0.5 # estabilidad emocional (0 = muy estable)
|
|
49
|
+
|
|
50
|
+
# ── Capa 2: Identidad narrativa ───────────────────────────────────────────
|
|
51
|
+
identity:
|
|
52
|
+
role: "Describe el rol de tu agente aquí"
|
|
53
|
+
backstory: "Describe el perfil y experiencia de tu agente"
|
|
54
|
+
communication_style: "Describe el estilo de comunicación"
|
|
55
|
+
|
|
56
|
+
# ── Capa 3: Few-shot examples ─────────────────────────────────────────────
|
|
57
|
+
examples:
|
|
58
|
+
on_brand:
|
|
59
|
+
- user: "Ejemplo de mensaje del usuario"
|
|
60
|
+
agent: "Ejemplo de respuesta correcta del agente"
|
|
61
|
+
off_brand:
|
|
62
|
+
- user: "Ejemplo de mensaje del usuario"
|
|
63
|
+
agent: "Ejemplo de respuesta incorrecta (para evitar)"
|
|
64
|
+
|
|
65
|
+
# ── Capa 4: Guardrails ────────────────────────────────────────────────────
|
|
66
|
+
guardrails:
|
|
67
|
+
always:
|
|
68
|
+
- "Siempre hacer esto"
|
|
69
|
+
never:
|
|
70
|
+
- "Nunca hacer esto"
|
|
71
|
+
escalate_if:
|
|
72
|
+
- "Condición que requiere escalar la conversación"
|
|
73
|
+
`;
|
|
74
|
+
function initCommand(options) {
|
|
75
|
+
const outputPath = path.resolve(options.output ?? path.join(process.cwd(), 'persona.zenti'));
|
|
76
|
+
if (fs.existsSync(outputPath)) {
|
|
77
|
+
console.error(`Error: El archivo ya existe: ${outputPath}`);
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
fs.writeFileSync(outputPath, TEMPLATE, 'utf-8');
|
|
81
|
+
console.log(`✓ Archivo creado: ${outputPath}`);
|
|
82
|
+
console.log('');
|
|
83
|
+
console.log('Próximos pasos:');
|
|
84
|
+
console.log(' 1. Edita el archivo con la personalidad de tu agente');
|
|
85
|
+
console.log(' 2. Valida con: zenti validate');
|
|
86
|
+
console.log(' 3. Prueba en terminal con: zenti test');
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.testCommand = testCommand;
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const readline = __importStar(require("readline"));
|
|
43
|
+
const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
|
|
44
|
+
const parser_1 = require("../../parser");
|
|
45
|
+
const toClaude_1 = require("../../compiler/toClaude");
|
|
46
|
+
const MODEL = 'claude-sonnet-4-6';
|
|
47
|
+
function findZentiFile() {
|
|
48
|
+
const files = fs.readdirSync(process.cwd()).filter((f) => f.endsWith('.zenti'));
|
|
49
|
+
return files.length > 0 ? files[0] : null;
|
|
50
|
+
}
|
|
51
|
+
function question(rl, prompt) {
|
|
52
|
+
return new Promise((resolve) => rl.question(prompt, resolve));
|
|
53
|
+
}
|
|
54
|
+
async function testCommand(options) {
|
|
55
|
+
// ── Resolve .zenti file ──────────────────────────────────────────────────
|
|
56
|
+
const filePath = options.file ?? findZentiFile();
|
|
57
|
+
if (!filePath) {
|
|
58
|
+
console.error('Error: No se encontró ningún archivo .zenti en el directorio actual.');
|
|
59
|
+
console.error('Usa --file <ruta> para especificar uno manualmente.');
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
const resolved = path.resolve(filePath);
|
|
63
|
+
if (!fs.existsSync(resolved)) {
|
|
64
|
+
console.error(`Error: No se encontró el archivo: ${resolved}`);
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
// ── Load and compile persona ─────────────────────────────────────────────
|
|
68
|
+
const content = fs.readFileSync(resolved, 'utf-8');
|
|
69
|
+
const persona = (0, parser_1.parseZenti)(content);
|
|
70
|
+
const { system } = (0, toClaude_1.toClaude)(persona);
|
|
71
|
+
console.log(`\nPersonalidad cargada: ${persona.name}`);
|
|
72
|
+
console.log(`Rol: ${persona.identity.role}`);
|
|
73
|
+
console.log(`Modelo: ${MODEL}\n`);
|
|
74
|
+
// ── Resolve API key ──────────────────────────────────────────────────────
|
|
75
|
+
let apiKey = options.key ?? process.env.ANTHROPIC_API_KEY;
|
|
76
|
+
if (!apiKey) {
|
|
77
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
78
|
+
apiKey = (await question(rl, 'ANTHROPIC_API_KEY: ')).trim();
|
|
79
|
+
rl.close();
|
|
80
|
+
if (!apiKey) {
|
|
81
|
+
console.error('Error: Se requiere una API key.');
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const client = new sdk_1.default({ apiKey });
|
|
86
|
+
const messages = [];
|
|
87
|
+
console.log(`Chat con ${persona.name} iniciado. Escribe "exit" para salir.`);
|
|
88
|
+
console.log('─'.repeat(60));
|
|
89
|
+
// ── Interactive chat loop ────────────────────────────────────────────────
|
|
90
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
91
|
+
const loop = async () => {
|
|
92
|
+
const input = (await question(rl, '\nTú: ')).trim();
|
|
93
|
+
if (input.toLowerCase() === 'exit' || input.toLowerCase() === 'quit') {
|
|
94
|
+
console.log('\n¡Hasta luego!');
|
|
95
|
+
rl.close();
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (!input) {
|
|
99
|
+
return loop();
|
|
100
|
+
}
|
|
101
|
+
messages.push({ role: 'user', content: input });
|
|
102
|
+
try {
|
|
103
|
+
const response = await client.messages.create({
|
|
104
|
+
model: MODEL,
|
|
105
|
+
max_tokens: 1024,
|
|
106
|
+
system,
|
|
107
|
+
messages,
|
|
108
|
+
});
|
|
109
|
+
const assistantText = response.content[0].type === 'text' ? response.content[0].text : '';
|
|
110
|
+
messages.push({ role: 'assistant', content: assistantText });
|
|
111
|
+
console.log(`\n${persona.name}: ${assistantText}`);
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
const msg = e.message;
|
|
115
|
+
console.error(`\nError al contactar la API: ${msg}`);
|
|
116
|
+
}
|
|
117
|
+
return loop();
|
|
118
|
+
};
|
|
119
|
+
await loop();
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=test.js.map
|