ethos-academy 0.2.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/dist/index.cjs +211 -0
- package/dist/index.d.cts +247 -0
- package/dist/index.d.ts +247 -0
- package/dist/index.js +182 -0
- package/package.json +36 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
EthosAcademy: () => EthosAcademy,
|
|
24
|
+
EthosClient: () => EthosAcademy,
|
|
25
|
+
completePracticeSession: () => completePracticeSession
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(index_exports);
|
|
28
|
+
|
|
29
|
+
// src/client.ts
|
|
30
|
+
var DEFAULT_BASE_URL = "https://api.ethos-academy.com";
|
|
31
|
+
var DEFAULT_TIMEOUT = 15e3;
|
|
32
|
+
var DATA_MAP_KEYS = /* @__PURE__ */ new Set([
|
|
33
|
+
"traitScores",
|
|
34
|
+
"traitAverages",
|
|
35
|
+
"dimensionAverages",
|
|
36
|
+
"tierScores",
|
|
37
|
+
"dimensions",
|
|
38
|
+
"dimensionDeltas",
|
|
39
|
+
"traitProgress"
|
|
40
|
+
]);
|
|
41
|
+
function toCamelCase(key) {
|
|
42
|
+
return key.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
|
|
43
|
+
}
|
|
44
|
+
function transformKeys(obj, preserveKeys = false) {
|
|
45
|
+
if (Array.isArray(obj)) {
|
|
46
|
+
return obj.map((item) => transformKeys(item));
|
|
47
|
+
}
|
|
48
|
+
if (obj !== null && typeof obj === "object") {
|
|
49
|
+
const result = {};
|
|
50
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
51
|
+
const newKey = preserveKeys ? key : toCamelCase(key);
|
|
52
|
+
result[newKey] = transformKeys(value, DATA_MAP_KEYS.has(newKey));
|
|
53
|
+
}
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
return obj;
|
|
57
|
+
}
|
|
58
|
+
var EthosAcademy = class {
|
|
59
|
+
apiKey;
|
|
60
|
+
baseUrl;
|
|
61
|
+
timeout;
|
|
62
|
+
constructor(config) {
|
|
63
|
+
this.apiKey = config.apiKey;
|
|
64
|
+
this.baseUrl = (config.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
|
|
65
|
+
this.timeout = config.timeout || DEFAULT_TIMEOUT;
|
|
66
|
+
}
|
|
67
|
+
async fetch(path, options) {
|
|
68
|
+
const controller = new AbortController();
|
|
69
|
+
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
70
|
+
try {
|
|
71
|
+
const res = await fetch(`${this.baseUrl}${path}`, {
|
|
72
|
+
headers: {
|
|
73
|
+
"Content-Type": "application/json",
|
|
74
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
75
|
+
},
|
|
76
|
+
...options,
|
|
77
|
+
signal: controller.signal
|
|
78
|
+
});
|
|
79
|
+
if (!res.ok) {
|
|
80
|
+
const body = await res.text().catch(() => "");
|
|
81
|
+
throw new Error(`Ethos API error ${res.status}: ${body}`);
|
|
82
|
+
}
|
|
83
|
+
const data = await res.json();
|
|
84
|
+
return transformKeys(data);
|
|
85
|
+
} finally {
|
|
86
|
+
clearTimeout(timer);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// ── Evaluation ──────────────────────────────────────────────────
|
|
90
|
+
async evaluateIncoming(text, source, sourceName) {
|
|
91
|
+
return this.fetch("/evaluate/incoming", {
|
|
92
|
+
method: "POST",
|
|
93
|
+
body: JSON.stringify({
|
|
94
|
+
text,
|
|
95
|
+
source,
|
|
96
|
+
source_name: sourceName || null
|
|
97
|
+
})
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
async evaluateOutgoing(text, source, sourceName) {
|
|
101
|
+
return this.fetch("/evaluate/outgoing", {
|
|
102
|
+
method: "POST",
|
|
103
|
+
body: JSON.stringify({
|
|
104
|
+
text,
|
|
105
|
+
source,
|
|
106
|
+
source_name: sourceName || null
|
|
107
|
+
})
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
// ── Agent Profile ───────────────────────────────────────────────
|
|
111
|
+
async getAgent(agentId) {
|
|
112
|
+
return this.fetch(
|
|
113
|
+
`/agent/${encodeURIComponent(agentId)}`
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
async getCharacterReport(agentId) {
|
|
117
|
+
return this.fetch(
|
|
118
|
+
`/agent/${encodeURIComponent(agentId)}/character`
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
// ── Exam ────────────────────────────────────────────────────────
|
|
122
|
+
async registerForExam(agentId, options) {
|
|
123
|
+
return this.fetch(
|
|
124
|
+
`/agent/${encodeURIComponent(agentId)}/exam`,
|
|
125
|
+
{
|
|
126
|
+
method: "POST",
|
|
127
|
+
body: JSON.stringify({
|
|
128
|
+
agent_name: options?.agentName || null,
|
|
129
|
+
specialty: options?.specialty || null,
|
|
130
|
+
model: options?.model || null,
|
|
131
|
+
guardian_name: options?.guardianName || null
|
|
132
|
+
})
|
|
133
|
+
}
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
async submitExamResponse(agentId, examId, questionId, responseText) {
|
|
137
|
+
return this.fetch(
|
|
138
|
+
`/agent/${encodeURIComponent(agentId)}/exam/${encodeURIComponent(examId)}/answer`,
|
|
139
|
+
{
|
|
140
|
+
method: "POST",
|
|
141
|
+
body: JSON.stringify({
|
|
142
|
+
question_id: questionId,
|
|
143
|
+
response_text: responseText
|
|
144
|
+
})
|
|
145
|
+
}
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
async getExamResults(agentId, examId) {
|
|
149
|
+
return this.fetch(
|
|
150
|
+
`/agent/${encodeURIComponent(agentId)}/exam/${encodeURIComponent(examId)}`
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
// ── Practice ────────────────────────────────────────────────────
|
|
154
|
+
async getPendingPractice(agentId) {
|
|
155
|
+
const data = await this.fetch(
|
|
156
|
+
`/agent/${encodeURIComponent(agentId)}/practice`
|
|
157
|
+
);
|
|
158
|
+
if (data.status === "caught_up") {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
return data;
|
|
162
|
+
}
|
|
163
|
+
async submitPracticeResponse(agentId, sessionId, scenarioId, responseText) {
|
|
164
|
+
return this.fetch(
|
|
165
|
+
`/agent/${encodeURIComponent(agentId)}/practice/${encodeURIComponent(sessionId)}/answer`,
|
|
166
|
+
{
|
|
167
|
+
method: "POST",
|
|
168
|
+
body: JSON.stringify({
|
|
169
|
+
scenario_id: scenarioId,
|
|
170
|
+
response_text: responseText
|
|
171
|
+
})
|
|
172
|
+
}
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
async getPracticeProgress(agentId) {
|
|
176
|
+
return this.fetch(
|
|
177
|
+
`/agent/${encodeURIComponent(agentId)}/practice/progress`
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
// src/practice.ts
|
|
183
|
+
async function completePracticeSession(client, agentId, respond) {
|
|
184
|
+
const session = await client.getPendingPractice(agentId);
|
|
185
|
+
if (!session) {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
let currentIndex = session.completedScenarios;
|
|
189
|
+
const scenarios = session.scenarios;
|
|
190
|
+
while (currentIndex < scenarios.length) {
|
|
191
|
+
const scenario = scenarios[currentIndex];
|
|
192
|
+
const responseText = await respond(scenario.prompt);
|
|
193
|
+
const result = await client.submitPracticeResponse(
|
|
194
|
+
agentId,
|
|
195
|
+
session.sessionId,
|
|
196
|
+
scenario.scenarioId,
|
|
197
|
+
responseText
|
|
198
|
+
);
|
|
199
|
+
if (result.complete && result.progress) {
|
|
200
|
+
return result.progress;
|
|
201
|
+
}
|
|
202
|
+
currentIndex++;
|
|
203
|
+
}
|
|
204
|
+
return client.getPracticeProgress(agentId);
|
|
205
|
+
}
|
|
206
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
207
|
+
0 && (module.exports = {
|
|
208
|
+
EthosAcademy,
|
|
209
|
+
EthosClient,
|
|
210
|
+
completePracticeSession
|
|
211
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript interfaces for the Ethos Academy SDK.
|
|
3
|
+
* All properties use camelCase (transformed from snake_case API responses).
|
|
4
|
+
*/
|
|
5
|
+
interface TraitScore {
|
|
6
|
+
name: string;
|
|
7
|
+
dimension: string;
|
|
8
|
+
polarity: string;
|
|
9
|
+
score: number;
|
|
10
|
+
indicators: DetectedIndicator[];
|
|
11
|
+
}
|
|
12
|
+
interface DetectedIndicator {
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
trait: string;
|
|
16
|
+
confidence: number;
|
|
17
|
+
severity: number;
|
|
18
|
+
evidence: string;
|
|
19
|
+
}
|
|
20
|
+
interface IntentClassification {
|
|
21
|
+
rhetoricalMode: string;
|
|
22
|
+
primaryIntent: string;
|
|
23
|
+
actionRequested: string;
|
|
24
|
+
costToReader: string;
|
|
25
|
+
stakesReality: string;
|
|
26
|
+
proportionality: string;
|
|
27
|
+
personaType: string;
|
|
28
|
+
relationalQuality: string;
|
|
29
|
+
claims: Array<{
|
|
30
|
+
claim: string;
|
|
31
|
+
type: string;
|
|
32
|
+
}>;
|
|
33
|
+
}
|
|
34
|
+
interface EvaluationResult {
|
|
35
|
+
ethos: number;
|
|
36
|
+
logos: number;
|
|
37
|
+
pathos: number;
|
|
38
|
+
flags: string[];
|
|
39
|
+
phronesis: string;
|
|
40
|
+
traits: Record<string, TraitScore>;
|
|
41
|
+
detectedIndicators: DetectedIndicator[];
|
|
42
|
+
evaluationId: string;
|
|
43
|
+
routingTier: string;
|
|
44
|
+
keywordDensity: number;
|
|
45
|
+
modelUsed: string;
|
|
46
|
+
agentModel: string;
|
|
47
|
+
createdAt: string;
|
|
48
|
+
alignmentStatus: string;
|
|
49
|
+
tierScores: Record<string, number>;
|
|
50
|
+
direction: string | null;
|
|
51
|
+
confidence: number;
|
|
52
|
+
intentClassification: IntentClassification | null;
|
|
53
|
+
scoringReasoning: string;
|
|
54
|
+
}
|
|
55
|
+
interface AgentProfile {
|
|
56
|
+
agentId: string;
|
|
57
|
+
agentName: string;
|
|
58
|
+
agentModel: string;
|
|
59
|
+
createdAt: string;
|
|
60
|
+
evaluationCount: number;
|
|
61
|
+
dimensionAverages: Record<string, number>;
|
|
62
|
+
traitAverages: Record<string, number>;
|
|
63
|
+
phronesisTrend: string;
|
|
64
|
+
alignmentHistory: string[];
|
|
65
|
+
enrolled: boolean;
|
|
66
|
+
enrolledAt: string;
|
|
67
|
+
guardianName: string;
|
|
68
|
+
entranceExamCompleted: boolean;
|
|
69
|
+
agentSpecialty: string;
|
|
70
|
+
}
|
|
71
|
+
interface HomeworkFocus {
|
|
72
|
+
trait: string;
|
|
73
|
+
priority: string;
|
|
74
|
+
currentScore: number;
|
|
75
|
+
targetScore: number;
|
|
76
|
+
instruction: string;
|
|
77
|
+
exampleFlagged: string;
|
|
78
|
+
exampleImproved: string;
|
|
79
|
+
systemPromptAddition: string;
|
|
80
|
+
}
|
|
81
|
+
interface Homework {
|
|
82
|
+
focusAreas: HomeworkFocus[];
|
|
83
|
+
avoidPatterns: string[];
|
|
84
|
+
strengths: string[];
|
|
85
|
+
directive: string;
|
|
86
|
+
}
|
|
87
|
+
interface DailyReportCard {
|
|
88
|
+
reportId: string;
|
|
89
|
+
agentId: string;
|
|
90
|
+
agentName: string;
|
|
91
|
+
reportDate: string;
|
|
92
|
+
generatedAt: string;
|
|
93
|
+
overallScore: number;
|
|
94
|
+
grade: string;
|
|
95
|
+
trend: string;
|
|
96
|
+
ethos: number;
|
|
97
|
+
logos: number;
|
|
98
|
+
pathos: number;
|
|
99
|
+
traitAverages: Record<string, number>;
|
|
100
|
+
homework: Homework;
|
|
101
|
+
summary: string;
|
|
102
|
+
insights: Array<{
|
|
103
|
+
trait: string;
|
|
104
|
+
severity: string;
|
|
105
|
+
message: string;
|
|
106
|
+
evidence: Record<string, unknown>;
|
|
107
|
+
}>;
|
|
108
|
+
}
|
|
109
|
+
interface ExamQuestion {
|
|
110
|
+
id: string;
|
|
111
|
+
section: string;
|
|
112
|
+
prompt: string;
|
|
113
|
+
phase: string;
|
|
114
|
+
questionType: string;
|
|
115
|
+
}
|
|
116
|
+
interface ExamRegistration {
|
|
117
|
+
examId: string;
|
|
118
|
+
agentId: string;
|
|
119
|
+
questionNumber: number;
|
|
120
|
+
totalQuestions: number;
|
|
121
|
+
question: ExamQuestion;
|
|
122
|
+
message: string;
|
|
123
|
+
}
|
|
124
|
+
interface ExamAnswerResult {
|
|
125
|
+
questionNumber: number;
|
|
126
|
+
totalQuestions: number;
|
|
127
|
+
question: ExamQuestion | null;
|
|
128
|
+
complete: boolean;
|
|
129
|
+
phase: string;
|
|
130
|
+
questionType: string;
|
|
131
|
+
agentId: string;
|
|
132
|
+
message: string;
|
|
133
|
+
}
|
|
134
|
+
interface ExamReportCard {
|
|
135
|
+
examId: string;
|
|
136
|
+
agentId: string;
|
|
137
|
+
reportCardUrl: string;
|
|
138
|
+
phronesisScore: number;
|
|
139
|
+
alignmentStatus: string;
|
|
140
|
+
dimensions: Record<string, number>;
|
|
141
|
+
tierScores: Record<string, number>;
|
|
142
|
+
homework: Homework;
|
|
143
|
+
}
|
|
144
|
+
interface PracticeScenario {
|
|
145
|
+
scenarioId: string;
|
|
146
|
+
trait: string;
|
|
147
|
+
dimension: string;
|
|
148
|
+
prompt: string;
|
|
149
|
+
difficulty: string;
|
|
150
|
+
focusAreaPriority: string;
|
|
151
|
+
}
|
|
152
|
+
interface PracticeSession {
|
|
153
|
+
sessionId: string;
|
|
154
|
+
agentId: string;
|
|
155
|
+
createdAt: string;
|
|
156
|
+
scenarios: PracticeScenario[];
|
|
157
|
+
totalScenarios: number;
|
|
158
|
+
completedScenarios: number;
|
|
159
|
+
status: string;
|
|
160
|
+
homeworkSnapshot: Homework;
|
|
161
|
+
}
|
|
162
|
+
interface PracticeProgress {
|
|
163
|
+
agentId: string;
|
|
164
|
+
sessionCount: number;
|
|
165
|
+
totalPracticeEvaluations: number;
|
|
166
|
+
traitProgress: Record<string, {
|
|
167
|
+
baseline: number;
|
|
168
|
+
practice: number;
|
|
169
|
+
delta: number;
|
|
170
|
+
}>;
|
|
171
|
+
overallDelta: number;
|
|
172
|
+
improvingTraits: string[];
|
|
173
|
+
decliningTraits: string[];
|
|
174
|
+
latestSessionDate: string;
|
|
175
|
+
nextAction: string;
|
|
176
|
+
}
|
|
177
|
+
interface PracticeAnswerResult {
|
|
178
|
+
sessionId: string;
|
|
179
|
+
scenarioId: string;
|
|
180
|
+
scenarioNumber: number;
|
|
181
|
+
totalScenarios: number;
|
|
182
|
+
nextScenario: PracticeScenario | null;
|
|
183
|
+
complete: boolean;
|
|
184
|
+
message: string;
|
|
185
|
+
progress: PracticeProgress | null;
|
|
186
|
+
}
|
|
187
|
+
interface EthosClientConfig {
|
|
188
|
+
apiKey: string;
|
|
189
|
+
baseUrl?: string;
|
|
190
|
+
timeout?: number;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* EthosAcademy — TypeScript SDK for the Ethos Academy REST API.
|
|
195
|
+
*
|
|
196
|
+
* Handles authentication, snake_case -> camelCase transformation,
|
|
197
|
+
* and typed API calls.
|
|
198
|
+
*/
|
|
199
|
+
|
|
200
|
+
declare class EthosAcademy {
|
|
201
|
+
private apiKey;
|
|
202
|
+
private baseUrl;
|
|
203
|
+
private timeout;
|
|
204
|
+
constructor(config: EthosClientConfig);
|
|
205
|
+
private fetch;
|
|
206
|
+
evaluateIncoming(text: string, source: string, sourceName?: string): Promise<EvaluationResult>;
|
|
207
|
+
evaluateOutgoing(text: string, source: string, sourceName?: string): Promise<EvaluationResult>;
|
|
208
|
+
getAgent(agentId: string): Promise<AgentProfile>;
|
|
209
|
+
getCharacterReport(agentId: string): Promise<DailyReportCard>;
|
|
210
|
+
registerForExam(agentId: string, options?: {
|
|
211
|
+
agentName?: string;
|
|
212
|
+
specialty?: string;
|
|
213
|
+
model?: string;
|
|
214
|
+
guardianName?: string;
|
|
215
|
+
}): Promise<ExamRegistration>;
|
|
216
|
+
submitExamResponse(agentId: string, examId: string, questionId: string, responseText: string): Promise<ExamAnswerResult>;
|
|
217
|
+
getExamResults(agentId: string, examId: string): Promise<ExamReportCard>;
|
|
218
|
+
getPendingPractice(agentId: string): Promise<PracticeSession | null>;
|
|
219
|
+
submitPracticeResponse(agentId: string, sessionId: string, scenarioId: string, responseText: string): Promise<PracticeAnswerResult>;
|
|
220
|
+
getPracticeProgress(agentId: string): Promise<PracticeProgress>;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Practice-specific utilities for the Ethos Academy SDK.
|
|
225
|
+
*
|
|
226
|
+
* Provides a high-level `completePracticeSession` helper that runs
|
|
227
|
+
* through all pending scenarios using a user-supplied response function.
|
|
228
|
+
*/
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Response function the agent implements.
|
|
232
|
+
* Receives scenario prompt text, returns the agent's response.
|
|
233
|
+
*/
|
|
234
|
+
type RespondFn = (scenarioPrompt: string) => Promise<string>;
|
|
235
|
+
/**
|
|
236
|
+
* Complete all pending practice scenarios in a session.
|
|
237
|
+
*
|
|
238
|
+
* Usage:
|
|
239
|
+
* ```ts
|
|
240
|
+
* const progress = await completePracticeSession(client, agentId, async (prompt) => {
|
|
241
|
+
* return await myAgent.respond(prompt);
|
|
242
|
+
* });
|
|
243
|
+
* ```
|
|
244
|
+
*/
|
|
245
|
+
declare function completePracticeSession(client: EthosAcademy, agentId: string, respond: RespondFn): Promise<PracticeProgress | null>;
|
|
246
|
+
|
|
247
|
+
export { type AgentProfile, type DailyReportCard, type DetectedIndicator, EthosAcademy, EthosAcademy as EthosClient, type EthosClientConfig, type EvaluationResult, type ExamAnswerResult, type ExamQuestion, type ExamRegistration, type ExamReportCard, type Homework, type HomeworkFocus, type IntentClassification, type PracticeAnswerResult, type PracticeProgress, type PracticeScenario, type PracticeSession, type RespondFn, type TraitScore, completePracticeSession };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript interfaces for the Ethos Academy SDK.
|
|
3
|
+
* All properties use camelCase (transformed from snake_case API responses).
|
|
4
|
+
*/
|
|
5
|
+
interface TraitScore {
|
|
6
|
+
name: string;
|
|
7
|
+
dimension: string;
|
|
8
|
+
polarity: string;
|
|
9
|
+
score: number;
|
|
10
|
+
indicators: DetectedIndicator[];
|
|
11
|
+
}
|
|
12
|
+
interface DetectedIndicator {
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
trait: string;
|
|
16
|
+
confidence: number;
|
|
17
|
+
severity: number;
|
|
18
|
+
evidence: string;
|
|
19
|
+
}
|
|
20
|
+
interface IntentClassification {
|
|
21
|
+
rhetoricalMode: string;
|
|
22
|
+
primaryIntent: string;
|
|
23
|
+
actionRequested: string;
|
|
24
|
+
costToReader: string;
|
|
25
|
+
stakesReality: string;
|
|
26
|
+
proportionality: string;
|
|
27
|
+
personaType: string;
|
|
28
|
+
relationalQuality: string;
|
|
29
|
+
claims: Array<{
|
|
30
|
+
claim: string;
|
|
31
|
+
type: string;
|
|
32
|
+
}>;
|
|
33
|
+
}
|
|
34
|
+
interface EvaluationResult {
|
|
35
|
+
ethos: number;
|
|
36
|
+
logos: number;
|
|
37
|
+
pathos: number;
|
|
38
|
+
flags: string[];
|
|
39
|
+
phronesis: string;
|
|
40
|
+
traits: Record<string, TraitScore>;
|
|
41
|
+
detectedIndicators: DetectedIndicator[];
|
|
42
|
+
evaluationId: string;
|
|
43
|
+
routingTier: string;
|
|
44
|
+
keywordDensity: number;
|
|
45
|
+
modelUsed: string;
|
|
46
|
+
agentModel: string;
|
|
47
|
+
createdAt: string;
|
|
48
|
+
alignmentStatus: string;
|
|
49
|
+
tierScores: Record<string, number>;
|
|
50
|
+
direction: string | null;
|
|
51
|
+
confidence: number;
|
|
52
|
+
intentClassification: IntentClassification | null;
|
|
53
|
+
scoringReasoning: string;
|
|
54
|
+
}
|
|
55
|
+
interface AgentProfile {
|
|
56
|
+
agentId: string;
|
|
57
|
+
agentName: string;
|
|
58
|
+
agentModel: string;
|
|
59
|
+
createdAt: string;
|
|
60
|
+
evaluationCount: number;
|
|
61
|
+
dimensionAverages: Record<string, number>;
|
|
62
|
+
traitAverages: Record<string, number>;
|
|
63
|
+
phronesisTrend: string;
|
|
64
|
+
alignmentHistory: string[];
|
|
65
|
+
enrolled: boolean;
|
|
66
|
+
enrolledAt: string;
|
|
67
|
+
guardianName: string;
|
|
68
|
+
entranceExamCompleted: boolean;
|
|
69
|
+
agentSpecialty: string;
|
|
70
|
+
}
|
|
71
|
+
interface HomeworkFocus {
|
|
72
|
+
trait: string;
|
|
73
|
+
priority: string;
|
|
74
|
+
currentScore: number;
|
|
75
|
+
targetScore: number;
|
|
76
|
+
instruction: string;
|
|
77
|
+
exampleFlagged: string;
|
|
78
|
+
exampleImproved: string;
|
|
79
|
+
systemPromptAddition: string;
|
|
80
|
+
}
|
|
81
|
+
interface Homework {
|
|
82
|
+
focusAreas: HomeworkFocus[];
|
|
83
|
+
avoidPatterns: string[];
|
|
84
|
+
strengths: string[];
|
|
85
|
+
directive: string;
|
|
86
|
+
}
|
|
87
|
+
interface DailyReportCard {
|
|
88
|
+
reportId: string;
|
|
89
|
+
agentId: string;
|
|
90
|
+
agentName: string;
|
|
91
|
+
reportDate: string;
|
|
92
|
+
generatedAt: string;
|
|
93
|
+
overallScore: number;
|
|
94
|
+
grade: string;
|
|
95
|
+
trend: string;
|
|
96
|
+
ethos: number;
|
|
97
|
+
logos: number;
|
|
98
|
+
pathos: number;
|
|
99
|
+
traitAverages: Record<string, number>;
|
|
100
|
+
homework: Homework;
|
|
101
|
+
summary: string;
|
|
102
|
+
insights: Array<{
|
|
103
|
+
trait: string;
|
|
104
|
+
severity: string;
|
|
105
|
+
message: string;
|
|
106
|
+
evidence: Record<string, unknown>;
|
|
107
|
+
}>;
|
|
108
|
+
}
|
|
109
|
+
interface ExamQuestion {
|
|
110
|
+
id: string;
|
|
111
|
+
section: string;
|
|
112
|
+
prompt: string;
|
|
113
|
+
phase: string;
|
|
114
|
+
questionType: string;
|
|
115
|
+
}
|
|
116
|
+
interface ExamRegistration {
|
|
117
|
+
examId: string;
|
|
118
|
+
agentId: string;
|
|
119
|
+
questionNumber: number;
|
|
120
|
+
totalQuestions: number;
|
|
121
|
+
question: ExamQuestion;
|
|
122
|
+
message: string;
|
|
123
|
+
}
|
|
124
|
+
interface ExamAnswerResult {
|
|
125
|
+
questionNumber: number;
|
|
126
|
+
totalQuestions: number;
|
|
127
|
+
question: ExamQuestion | null;
|
|
128
|
+
complete: boolean;
|
|
129
|
+
phase: string;
|
|
130
|
+
questionType: string;
|
|
131
|
+
agentId: string;
|
|
132
|
+
message: string;
|
|
133
|
+
}
|
|
134
|
+
interface ExamReportCard {
|
|
135
|
+
examId: string;
|
|
136
|
+
agentId: string;
|
|
137
|
+
reportCardUrl: string;
|
|
138
|
+
phronesisScore: number;
|
|
139
|
+
alignmentStatus: string;
|
|
140
|
+
dimensions: Record<string, number>;
|
|
141
|
+
tierScores: Record<string, number>;
|
|
142
|
+
homework: Homework;
|
|
143
|
+
}
|
|
144
|
+
interface PracticeScenario {
|
|
145
|
+
scenarioId: string;
|
|
146
|
+
trait: string;
|
|
147
|
+
dimension: string;
|
|
148
|
+
prompt: string;
|
|
149
|
+
difficulty: string;
|
|
150
|
+
focusAreaPriority: string;
|
|
151
|
+
}
|
|
152
|
+
interface PracticeSession {
|
|
153
|
+
sessionId: string;
|
|
154
|
+
agentId: string;
|
|
155
|
+
createdAt: string;
|
|
156
|
+
scenarios: PracticeScenario[];
|
|
157
|
+
totalScenarios: number;
|
|
158
|
+
completedScenarios: number;
|
|
159
|
+
status: string;
|
|
160
|
+
homeworkSnapshot: Homework;
|
|
161
|
+
}
|
|
162
|
+
interface PracticeProgress {
|
|
163
|
+
agentId: string;
|
|
164
|
+
sessionCount: number;
|
|
165
|
+
totalPracticeEvaluations: number;
|
|
166
|
+
traitProgress: Record<string, {
|
|
167
|
+
baseline: number;
|
|
168
|
+
practice: number;
|
|
169
|
+
delta: number;
|
|
170
|
+
}>;
|
|
171
|
+
overallDelta: number;
|
|
172
|
+
improvingTraits: string[];
|
|
173
|
+
decliningTraits: string[];
|
|
174
|
+
latestSessionDate: string;
|
|
175
|
+
nextAction: string;
|
|
176
|
+
}
|
|
177
|
+
interface PracticeAnswerResult {
|
|
178
|
+
sessionId: string;
|
|
179
|
+
scenarioId: string;
|
|
180
|
+
scenarioNumber: number;
|
|
181
|
+
totalScenarios: number;
|
|
182
|
+
nextScenario: PracticeScenario | null;
|
|
183
|
+
complete: boolean;
|
|
184
|
+
message: string;
|
|
185
|
+
progress: PracticeProgress | null;
|
|
186
|
+
}
|
|
187
|
+
interface EthosClientConfig {
|
|
188
|
+
apiKey: string;
|
|
189
|
+
baseUrl?: string;
|
|
190
|
+
timeout?: number;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* EthosAcademy — TypeScript SDK for the Ethos Academy REST API.
|
|
195
|
+
*
|
|
196
|
+
* Handles authentication, snake_case -> camelCase transformation,
|
|
197
|
+
* and typed API calls.
|
|
198
|
+
*/
|
|
199
|
+
|
|
200
|
+
declare class EthosAcademy {
|
|
201
|
+
private apiKey;
|
|
202
|
+
private baseUrl;
|
|
203
|
+
private timeout;
|
|
204
|
+
constructor(config: EthosClientConfig);
|
|
205
|
+
private fetch;
|
|
206
|
+
evaluateIncoming(text: string, source: string, sourceName?: string): Promise<EvaluationResult>;
|
|
207
|
+
evaluateOutgoing(text: string, source: string, sourceName?: string): Promise<EvaluationResult>;
|
|
208
|
+
getAgent(agentId: string): Promise<AgentProfile>;
|
|
209
|
+
getCharacterReport(agentId: string): Promise<DailyReportCard>;
|
|
210
|
+
registerForExam(agentId: string, options?: {
|
|
211
|
+
agentName?: string;
|
|
212
|
+
specialty?: string;
|
|
213
|
+
model?: string;
|
|
214
|
+
guardianName?: string;
|
|
215
|
+
}): Promise<ExamRegistration>;
|
|
216
|
+
submitExamResponse(agentId: string, examId: string, questionId: string, responseText: string): Promise<ExamAnswerResult>;
|
|
217
|
+
getExamResults(agentId: string, examId: string): Promise<ExamReportCard>;
|
|
218
|
+
getPendingPractice(agentId: string): Promise<PracticeSession | null>;
|
|
219
|
+
submitPracticeResponse(agentId: string, sessionId: string, scenarioId: string, responseText: string): Promise<PracticeAnswerResult>;
|
|
220
|
+
getPracticeProgress(agentId: string): Promise<PracticeProgress>;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Practice-specific utilities for the Ethos Academy SDK.
|
|
225
|
+
*
|
|
226
|
+
* Provides a high-level `completePracticeSession` helper that runs
|
|
227
|
+
* through all pending scenarios using a user-supplied response function.
|
|
228
|
+
*/
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Response function the agent implements.
|
|
232
|
+
* Receives scenario prompt text, returns the agent's response.
|
|
233
|
+
*/
|
|
234
|
+
type RespondFn = (scenarioPrompt: string) => Promise<string>;
|
|
235
|
+
/**
|
|
236
|
+
* Complete all pending practice scenarios in a session.
|
|
237
|
+
*
|
|
238
|
+
* Usage:
|
|
239
|
+
* ```ts
|
|
240
|
+
* const progress = await completePracticeSession(client, agentId, async (prompt) => {
|
|
241
|
+
* return await myAgent.respond(prompt);
|
|
242
|
+
* });
|
|
243
|
+
* ```
|
|
244
|
+
*/
|
|
245
|
+
declare function completePracticeSession(client: EthosAcademy, agentId: string, respond: RespondFn): Promise<PracticeProgress | null>;
|
|
246
|
+
|
|
247
|
+
export { type AgentProfile, type DailyReportCard, type DetectedIndicator, EthosAcademy, EthosAcademy as EthosClient, type EthosClientConfig, type EvaluationResult, type ExamAnswerResult, type ExamQuestion, type ExamRegistration, type ExamReportCard, type Homework, type HomeworkFocus, type IntentClassification, type PracticeAnswerResult, type PracticeProgress, type PracticeScenario, type PracticeSession, type RespondFn, type TraitScore, completePracticeSession };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
// src/client.ts
|
|
2
|
+
var DEFAULT_BASE_URL = "https://api.ethos-academy.com";
|
|
3
|
+
var DEFAULT_TIMEOUT = 15e3;
|
|
4
|
+
var DATA_MAP_KEYS = /* @__PURE__ */ new Set([
|
|
5
|
+
"traitScores",
|
|
6
|
+
"traitAverages",
|
|
7
|
+
"dimensionAverages",
|
|
8
|
+
"tierScores",
|
|
9
|
+
"dimensions",
|
|
10
|
+
"dimensionDeltas",
|
|
11
|
+
"traitProgress"
|
|
12
|
+
]);
|
|
13
|
+
function toCamelCase(key) {
|
|
14
|
+
return key.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
|
|
15
|
+
}
|
|
16
|
+
function transformKeys(obj, preserveKeys = false) {
|
|
17
|
+
if (Array.isArray(obj)) {
|
|
18
|
+
return obj.map((item) => transformKeys(item));
|
|
19
|
+
}
|
|
20
|
+
if (obj !== null && typeof obj === "object") {
|
|
21
|
+
const result = {};
|
|
22
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
23
|
+
const newKey = preserveKeys ? key : toCamelCase(key);
|
|
24
|
+
result[newKey] = transformKeys(value, DATA_MAP_KEYS.has(newKey));
|
|
25
|
+
}
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
return obj;
|
|
29
|
+
}
|
|
30
|
+
var EthosAcademy = class {
|
|
31
|
+
apiKey;
|
|
32
|
+
baseUrl;
|
|
33
|
+
timeout;
|
|
34
|
+
constructor(config) {
|
|
35
|
+
this.apiKey = config.apiKey;
|
|
36
|
+
this.baseUrl = (config.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
|
|
37
|
+
this.timeout = config.timeout || DEFAULT_TIMEOUT;
|
|
38
|
+
}
|
|
39
|
+
async fetch(path, options) {
|
|
40
|
+
const controller = new AbortController();
|
|
41
|
+
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
42
|
+
try {
|
|
43
|
+
const res = await fetch(`${this.baseUrl}${path}`, {
|
|
44
|
+
headers: {
|
|
45
|
+
"Content-Type": "application/json",
|
|
46
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
47
|
+
},
|
|
48
|
+
...options,
|
|
49
|
+
signal: controller.signal
|
|
50
|
+
});
|
|
51
|
+
if (!res.ok) {
|
|
52
|
+
const body = await res.text().catch(() => "");
|
|
53
|
+
throw new Error(`Ethos API error ${res.status}: ${body}`);
|
|
54
|
+
}
|
|
55
|
+
const data = await res.json();
|
|
56
|
+
return transformKeys(data);
|
|
57
|
+
} finally {
|
|
58
|
+
clearTimeout(timer);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// ── Evaluation ──────────────────────────────────────────────────
|
|
62
|
+
async evaluateIncoming(text, source, sourceName) {
|
|
63
|
+
return this.fetch("/evaluate/incoming", {
|
|
64
|
+
method: "POST",
|
|
65
|
+
body: JSON.stringify({
|
|
66
|
+
text,
|
|
67
|
+
source,
|
|
68
|
+
source_name: sourceName || null
|
|
69
|
+
})
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
async evaluateOutgoing(text, source, sourceName) {
|
|
73
|
+
return this.fetch("/evaluate/outgoing", {
|
|
74
|
+
method: "POST",
|
|
75
|
+
body: JSON.stringify({
|
|
76
|
+
text,
|
|
77
|
+
source,
|
|
78
|
+
source_name: sourceName || null
|
|
79
|
+
})
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
// ── Agent Profile ───────────────────────────────────────────────
|
|
83
|
+
async getAgent(agentId) {
|
|
84
|
+
return this.fetch(
|
|
85
|
+
`/agent/${encodeURIComponent(agentId)}`
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
async getCharacterReport(agentId) {
|
|
89
|
+
return this.fetch(
|
|
90
|
+
`/agent/${encodeURIComponent(agentId)}/character`
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
// ── Exam ────────────────────────────────────────────────────────
|
|
94
|
+
async registerForExam(agentId, options) {
|
|
95
|
+
return this.fetch(
|
|
96
|
+
`/agent/${encodeURIComponent(agentId)}/exam`,
|
|
97
|
+
{
|
|
98
|
+
method: "POST",
|
|
99
|
+
body: JSON.stringify({
|
|
100
|
+
agent_name: options?.agentName || null,
|
|
101
|
+
specialty: options?.specialty || null,
|
|
102
|
+
model: options?.model || null,
|
|
103
|
+
guardian_name: options?.guardianName || null
|
|
104
|
+
})
|
|
105
|
+
}
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
async submitExamResponse(agentId, examId, questionId, responseText) {
|
|
109
|
+
return this.fetch(
|
|
110
|
+
`/agent/${encodeURIComponent(agentId)}/exam/${encodeURIComponent(examId)}/answer`,
|
|
111
|
+
{
|
|
112
|
+
method: "POST",
|
|
113
|
+
body: JSON.stringify({
|
|
114
|
+
question_id: questionId,
|
|
115
|
+
response_text: responseText
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
async getExamResults(agentId, examId) {
|
|
121
|
+
return this.fetch(
|
|
122
|
+
`/agent/${encodeURIComponent(agentId)}/exam/${encodeURIComponent(examId)}`
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
// ── Practice ────────────────────────────────────────────────────
|
|
126
|
+
async getPendingPractice(agentId) {
|
|
127
|
+
const data = await this.fetch(
|
|
128
|
+
`/agent/${encodeURIComponent(agentId)}/practice`
|
|
129
|
+
);
|
|
130
|
+
if (data.status === "caught_up") {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
return data;
|
|
134
|
+
}
|
|
135
|
+
async submitPracticeResponse(agentId, sessionId, scenarioId, responseText) {
|
|
136
|
+
return this.fetch(
|
|
137
|
+
`/agent/${encodeURIComponent(agentId)}/practice/${encodeURIComponent(sessionId)}/answer`,
|
|
138
|
+
{
|
|
139
|
+
method: "POST",
|
|
140
|
+
body: JSON.stringify({
|
|
141
|
+
scenario_id: scenarioId,
|
|
142
|
+
response_text: responseText
|
|
143
|
+
})
|
|
144
|
+
}
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
async getPracticeProgress(agentId) {
|
|
148
|
+
return this.fetch(
|
|
149
|
+
`/agent/${encodeURIComponent(agentId)}/practice/progress`
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
// src/practice.ts
|
|
155
|
+
async function completePracticeSession(client, agentId, respond) {
|
|
156
|
+
const session = await client.getPendingPractice(agentId);
|
|
157
|
+
if (!session) {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
let currentIndex = session.completedScenarios;
|
|
161
|
+
const scenarios = session.scenarios;
|
|
162
|
+
while (currentIndex < scenarios.length) {
|
|
163
|
+
const scenario = scenarios[currentIndex];
|
|
164
|
+
const responseText = await respond(scenario.prompt);
|
|
165
|
+
const result = await client.submitPracticeResponse(
|
|
166
|
+
agentId,
|
|
167
|
+
session.sessionId,
|
|
168
|
+
scenario.scenarioId,
|
|
169
|
+
responseText
|
|
170
|
+
);
|
|
171
|
+
if (result.complete && result.progress) {
|
|
172
|
+
return result.progress;
|
|
173
|
+
}
|
|
174
|
+
currentIndex++;
|
|
175
|
+
}
|
|
176
|
+
return client.getPracticeProgress(agentId);
|
|
177
|
+
}
|
|
178
|
+
export {
|
|
179
|
+
EthosAcademy,
|
|
180
|
+
EthosAcademy as EthosClient,
|
|
181
|
+
completePracticeSession
|
|
182
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ethos-academy",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "TypeScript SDK for Ethos Academy — score AI agent messages for honesty, accuracy, and intent",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.cjs",
|
|
7
|
+
"module": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": ["dist"],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsup",
|
|
19
|
+
"test": "node --test dist/**/*.test.js",
|
|
20
|
+
"prepublishOnly": "npm run build"
|
|
21
|
+
},
|
|
22
|
+
"keywords": ["ethos", "ai", "alignment", "evaluation", "agents"],
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://github.com/allierays/ethos-academy.git",
|
|
27
|
+
"directory": "packages/ethos-sdk"
|
|
28
|
+
},
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"tsup": "^8.0.0",
|
|
34
|
+
"typescript": "^5.4.0"
|
|
35
|
+
}
|
|
36
|
+
}
|