coaiajs 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.
Files changed (181) hide show
  1. package/dist/mcp/config.d.ts +4 -0
  2. package/dist/mcp/config.d.ts.map +1 -0
  3. package/dist/mcp/config.js +52 -26
  4. package/dist/mcp/config.js.map +1 -0
  5. package/dist/mcp/prompts.d.ts +19 -0
  6. package/dist/mcp/prompts.d.ts.map +1 -0
  7. package/dist/mcp/prompts.js +111 -0
  8. package/dist/mcp/prompts.js.map +1 -0
  9. package/dist/mcp/resources.d.ts +5 -0
  10. package/dist/mcp/resources.d.ts.map +1 -0
  11. package/dist/mcp/resources.js +77 -0
  12. package/dist/mcp/resources.js.map +1 -0
  13. package/dist/mcp/server.d.ts.map +1 -0
  14. package/dist/mcp/server.js +164 -73
  15. package/dist/mcp/server.js.map +1 -0
  16. package/dist/mcp/tools/coaiapy-tools.d.ts.map +1 -0
  17. package/dist/mcp/tools/coaiapy-tools.js +1 -0
  18. package/dist/mcp/tools/coaiapy-tools.js.map +1 -0
  19. package/dist/mcp/tools/index.d.ts.map +1 -0
  20. package/dist/mcp/tools/index.js.map +1 -0
  21. package/dist/src/audio.d.ts.map +1 -0
  22. package/dist/src/audio.js.map +1 -0
  23. package/dist/src/cli-helpers.d.ts.map +1 -0
  24. package/dist/src/cli-helpers.js.map +1 -0
  25. package/dist/src/cli.d.ts.map +1 -0
  26. package/dist/src/cli.js.map +1 -0
  27. package/dist/src/config.d.ts.map +1 -0
  28. package/dist/src/config.js.map +1 -0
  29. package/dist/src/environment.d.ts.map +1 -0
  30. package/dist/src/environment.js.map +1 -0
  31. package/dist/src/github.d.ts.map +1 -0
  32. package/dist/src/github.js.map +1 -0
  33. package/dist/src/index.d.ts +13 -0
  34. package/dist/src/index.d.ts.map +1 -0
  35. package/dist/src/index.js +13 -0
  36. package/dist/src/index.js.map +1 -0
  37. package/dist/src/langfuse/client.d.ts.map +1 -0
  38. package/dist/src/langfuse/client.js.map +1 -0
  39. package/dist/src/langfuse/comments.d.ts.map +1 -0
  40. package/dist/src/langfuse/comments.js.map +1 -0
  41. package/dist/src/langfuse/datasets.d.ts.map +1 -0
  42. package/dist/src/langfuse/datasets.js.map +1 -0
  43. package/dist/src/langfuse/index.d.ts.map +1 -0
  44. package/dist/src/langfuse/index.js.map +1 -0
  45. package/dist/src/langfuse/media.d.ts.map +1 -0
  46. package/dist/src/langfuse/media.js.map +1 -0
  47. package/dist/src/langfuse/observations.d.ts.map +1 -0
  48. package/dist/src/langfuse/observations.js.map +1 -0
  49. package/dist/src/langfuse/prompts.d.ts.map +1 -0
  50. package/dist/src/langfuse/prompts.js.map +1 -0
  51. package/dist/src/langfuse/scores.d.ts.map +1 -0
  52. package/dist/src/langfuse/scores.js.map +1 -0
  53. package/dist/src/langfuse/traces.d.ts.map +1 -0
  54. package/dist/src/langfuse/traces.js.map +1 -0
  55. package/dist/src/llm.d.ts.map +1 -0
  56. package/dist/src/llm.js.map +1 -0
  57. package/dist/src/narrative/graph-manager.d.ts.map +1 -0
  58. package/dist/src/narrative/graph-manager.js.map +1 -0
  59. package/dist/src/narrative/index.d.ts +32 -1
  60. package/dist/src/narrative/index.d.ts.map +1 -0
  61. package/dist/src/narrative/index.js +97 -1
  62. package/dist/src/narrative/index.js.map +1 -0
  63. package/dist/src/narrative/markdown-export.d.ts.map +1 -0
  64. package/dist/src/narrative/markdown-export.js.map +1 -0
  65. package/dist/src/narrative/tool-definitions.d.ts.map +1 -0
  66. package/dist/src/narrative/tool-definitions.js.map +1 -0
  67. package/dist/src/narrative/tool-handlers.d.ts.map +1 -0
  68. package/dist/src/narrative/tool-handlers.js.map +1 -0
  69. package/dist/src/narrative/types.d.ts.map +1 -0
  70. package/dist/src/narrative/types.js.map +1 -0
  71. package/dist/src/narrative/validation.d.ts.map +1 -0
  72. package/dist/src/narrative/validation.js.map +1 -0
  73. package/dist/src/pde/index.d.ts +4 -0
  74. package/dist/src/pde/index.d.ts.map +1 -0
  75. package/dist/src/pde/index.js +19 -0
  76. package/dist/src/pde/index.js.map +1 -0
  77. package/dist/src/pde/mcp-handlers.d.ts.map +1 -0
  78. package/dist/src/pde/mcp-handlers.js.map +1 -0
  79. package/dist/src/pde/mcp-tools.d.ts.map +1 -0
  80. package/dist/src/pde/mcp-tools.js.map +1 -0
  81. package/dist/src/pde/session-manager.d.ts.map +1 -0
  82. package/dist/src/pde/session-manager.js.map +1 -0
  83. package/dist/src/pde/stc-mapper.d.ts.map +1 -0
  84. package/dist/src/pde/stc-mapper.js.map +1 -0
  85. package/dist/src/pipeline/index.d.ts.map +1 -0
  86. package/dist/src/pipeline/index.js.map +1 -0
  87. package/dist/src/pipeline/template-engine.d.ts.map +1 -0
  88. package/dist/src/pipeline/template-engine.js.map +1 -0
  89. package/dist/src/planning/index.d.ts +3 -0
  90. package/dist/src/planning/index.d.ts.map +1 -0
  91. package/dist/src/planning/index.js +13 -0
  92. package/dist/src/planning/index.js.map +1 -0
  93. package/dist/src/planning/mcp-handlers.d.ts.map +1 -0
  94. package/dist/src/planning/mcp-handlers.js.map +1 -0
  95. package/dist/src/planning/mcp-tools.d.ts.map +1 -0
  96. package/dist/src/planning/mcp-tools.js.map +1 -0
  97. package/dist/src/planning/plan-parser.d.ts.map +1 -0
  98. package/dist/src/planning/plan-parser.js.map +1 -0
  99. package/dist/src/redis.d.ts.map +1 -0
  100. package/dist/src/redis.js.map +1 -0
  101. package/dist/src/types.d.ts.map +1 -0
  102. package/dist/src/types.js.map +1 -0
  103. package/package.json +66 -1
  104. package/rispecs/00-coaiajs-platform.spec.md +18 -6
  105. package/rispecs/01-core-config.spec.md +7 -37
  106. package/rispecs/02-redis-module.spec.md +2 -1
  107. package/rispecs/03-langfuse-module.spec.md +7 -5
  108. package/rispecs/04-narrative-engine.spec.md +9 -9
  109. package/rispecs/05-pde-engine.spec.md +23 -23
  110. package/rispecs/06-planning-engine.spec.md +14 -13
  111. package/rispecs/07-pipeline-templates.spec.md +7 -7
  112. package/rispecs/08-cli-interface.spec.md +13 -25
  113. package/rispecs/09-mcp-server.spec.md +41 -44
  114. package/rispecs/10-audio-module.spec.md +3 -3
  115. package/rispecs/KINSHIP.md +4 -4
  116. package/rispecs/README.md +33 -7
  117. package/articles/academic/creative-orientation-vs-problem-solving.md +0 -177
  118. package/articles/academic/jsonl-knowledge-graphs-agent-memory.md +0 -142
  119. package/articles/academic/langfuse-observability-llm-pipelines.md +0 -144
  120. package/articles/academic/medicine-wheel-software-architecture.md +0 -163
  121. package/articles/academic/mmot-autonomous-agents.md +0 -156
  122. package/articles/academic/model-context-protocol-interagent.md +0 -161
  123. package/articles/academic/pde-prompt-decomposition.md +0 -186
  124. package/articles/academic/structural-tension-in-ai-agents.md +0 -134
  125. package/articles/reviews/mcp-protocol-design-review.md +0 -170
  126. package/articles/reviews/observability-ai-systems-review.md +0 -176
  127. package/articles/reviews/prompt-engineering-decomposition-review.md +0 -184
  128. package/articles/surveys/agent-orchestration-survey.md +0 -186
  129. package/articles/surveys/knowledge-graph-storage-survey.md +0 -204
  130. package/articles/surveys/structural-tension-methodology-survey.md +0 -154
  131. package/articles/technical/aws-sdk-v3-polly.md +0 -270
  132. package/articles/technical/commander-cli-framework.md +0 -262
  133. package/articles/technical/dotenv-config-patterns.md +0 -360
  134. package/articles/technical/ioredis-vs-redis.md +0 -142
  135. package/articles/technical/langfuse-js-sdk-vs-rest.md +0 -191
  136. package/articles/technical/mcp-sdk-typescript.md +0 -291
  137. package/articles/technical/octokit-github-api.md +0 -293
  138. package/articles/technical/openai-sdk-modern.md +0 -231
  139. package/articles/technical/yaml-parsing-node.md +0 -266
  140. package/articles/technical/zod-runtime-validation.md +0 -212
  141. package/mcp/config.ts +0 -196
  142. package/mcp/server.ts +0 -402
  143. package/mcp/tools/coaiapy-tools.ts +0 -364
  144. package/mcp/tools/index.ts +0 -4
  145. package/src/audio.ts +0 -76
  146. package/src/cli-helpers.ts +0 -86
  147. package/src/cli.ts +0 -1223
  148. package/src/config.ts +0 -172
  149. package/src/environment.ts +0 -171
  150. package/src/github.ts +0 -143
  151. package/src/langfuse/client.ts +0 -105
  152. package/src/langfuse/comments.ts +0 -52
  153. package/src/langfuse/datasets.ts +0 -178
  154. package/src/langfuse/index.ts +0 -33
  155. package/src/langfuse/media.ts +0 -193
  156. package/src/langfuse/observations.ts +0 -131
  157. package/src/langfuse/prompts.ts +0 -157
  158. package/src/langfuse/scores.ts +0 -456
  159. package/src/langfuse/traces.ts +0 -276
  160. package/src/llm.ts +0 -106
  161. package/src/narrative/graph-manager.ts +0 -1358
  162. package/src/narrative/index.ts +0 -32
  163. package/src/narrative/markdown-export.ts +0 -535
  164. package/src/narrative/tool-definitions.ts +0 -635
  165. package/src/narrative/tool-handlers.ts +0 -528
  166. package/src/narrative/types.ts +0 -9
  167. package/src/narrative/validation.ts +0 -179
  168. package/src/pde/index.ts +0 -8
  169. package/src/pde/mcp-handlers.ts +0 -359
  170. package/src/pde/mcp-tools.ts +0 -201
  171. package/src/pde/session-manager.ts +0 -248
  172. package/src/pde/stc-mapper.ts +0 -298
  173. package/src/pipeline/index.ts +0 -7
  174. package/src/pipeline/template-engine.ts +0 -398
  175. package/src/planning/index.ts +0 -13
  176. package/src/planning/mcp-handlers.ts +0 -369
  177. package/src/planning/mcp-tools.ts +0 -155
  178. package/src/planning/plan-parser.ts +0 -587
  179. package/src/redis.ts +0 -97
  180. package/src/types.ts +0 -280
  181. package/tsconfig.json +0 -26
@@ -1,456 +0,0 @@
1
- // coaiajs/src/langfuse/scores.ts — Score operations
2
- // Port of cofuse.py score functions including configs, presets, import/export
3
-
4
- import { readFileSync, writeFileSync } from 'node:fs';
5
- import { getClient, nowISO } from './client.js';
6
- import type { ScoreConfig } from '../types.js';
7
-
8
- export interface ScoreFilters {
9
- userId?: string;
10
- name?: string;
11
- fromTimestamp?: string;
12
- toTimestamp?: string;
13
- configId?: string;
14
- page?: number;
15
- }
16
-
17
- // ─── Score CRUD ─────────────────────────────────────────────────────
18
-
19
- export async function createScore(params: {
20
- id?: string;
21
- name?: string;
22
- value: number;
23
- traceId?: string;
24
- observationId?: string;
25
- configId?: string;
26
- comment?: string;
27
- }): Promise<string> {
28
- const client = getClient();
29
- const data: Record<string, unknown> = { value: params.value };
30
-
31
- if (params.id) data.id = params.id;
32
- if (params.name) data.name = params.name;
33
- if (params.traceId) data.traceId = params.traceId;
34
- if (params.observationId) data.observationId = params.observationId;
35
- if (params.configId) data.configId = params.configId;
36
- if (params.comment) data.comment = params.comment;
37
-
38
- const result = await client.request<unknown>('POST', '/api/public/scores', data);
39
- return JSON.stringify(result, null, 2);
40
- }
41
-
42
- export async function applyScoreToTrace(
43
- traceId: string,
44
- scoreId: string,
45
- value: number,
46
- ): Promise<string> {
47
- return createScoreForTarget({
48
- targetType: 'trace',
49
- targetId: traceId,
50
- scoreId,
51
- value,
52
- });
53
- }
54
-
55
- export async function createScoreForTarget(params: {
56
- targetType: 'trace' | 'session';
57
- targetId: string;
58
- scoreId?: string;
59
- value: number;
60
- scoreName?: string;
61
- observationId?: string;
62
- configId?: string;
63
- comment?: string;
64
- }): Promise<string> {
65
- const client = getClient();
66
- const data: Record<string, unknown> = { value: params.value };
67
-
68
- if (params.targetType === 'trace') {
69
- data.traceId = params.targetId;
70
- if (params.observationId) data.observationId = params.observationId;
71
- } else {
72
- data.sessionId = params.targetId;
73
- }
74
-
75
- if (params.configId) {
76
- data.configId = params.configId;
77
- } else {
78
- if (params.scoreId) data.id = params.scoreId;
79
- if (params.scoreName) data.name = params.scoreName;
80
- }
81
-
82
- if (params.comment) data.comment = params.comment;
83
-
84
- const result = await client.request<unknown>('POST', '/api/public/scores', data);
85
- return JSON.stringify(result, null, 2);
86
- }
87
-
88
- export async function listScores(filters: ScoreFilters): Promise<string> {
89
- const client = getClient();
90
- const allScores: unknown[] = [];
91
- let page = filters.page ?? 1;
92
-
93
- while (true) {
94
- const params = new URLSearchParams({ page: String(page) });
95
- if (filters.userId) params.set('userId', filters.userId);
96
- if (filters.name) params.set('name', filters.name);
97
- if (filters.fromTimestamp) params.set('fromTimestamp', filters.fromTimestamp);
98
- if (filters.toTimestamp) params.set('toTimestamp', filters.toTimestamp);
99
- if (filters.configId) params.set('configId', filters.configId);
100
-
101
- const data = await client.request<Record<string, unknown>>(
102
- 'GET',
103
- `/api/public/v2/scores?${params.toString()}`,
104
- );
105
-
106
- const scores = (data as Record<string, unknown>).data;
107
- if (!scores || !Array.isArray(scores) || scores.length === 0) break;
108
- allScores.push(...scores);
109
-
110
- if (!shouldContinuePagination(data, page)) break;
111
- page++;
112
- }
113
-
114
- return JSON.stringify(allScores, null, 2);
115
- }
116
-
117
- // ─── Score Configs ──────────────────────────────────────────────────
118
-
119
- export async function listScoreConfigs(): Promise<string> {
120
- const client = getClient();
121
- const allConfigs: unknown[] = [];
122
- let page = 1;
123
-
124
- while (true) {
125
- const data = await client.request<Record<string, unknown>>(
126
- 'GET',
127
- `/api/public/score-configs?page=${page}`,
128
- );
129
-
130
- const configs = (data as Record<string, unknown>).data;
131
- if (!configs || !Array.isArray(configs) || configs.length === 0) break;
132
- allConfigs.push(...configs);
133
-
134
- if (!shouldContinuePagination(data, page)) break;
135
- page++;
136
- }
137
-
138
- return JSON.stringify(allConfigs, null, 2);
139
- }
140
-
141
- export async function getScoreConfig(configId: string): Promise<string> {
142
- const client = getClient();
143
- const result = await client.request<unknown>('GET', `/api/public/score-configs/${configId}`);
144
- return JSON.stringify(result, null, 2);
145
- }
146
-
147
- export async function createScoreConfig(params: {
148
- name: string;
149
- dataType: 'NUMERIC' | 'CATEGORICAL' | 'BOOLEAN';
150
- description?: string;
151
- categories?: Array<{ label: string; value: number }>;
152
- minValue?: number;
153
- maxValue?: number;
154
- }): Promise<string> {
155
- const client = getClient();
156
- const data: Record<string, unknown> = {
157
- name: params.name,
158
- dataType: params.dataType,
159
- };
160
-
161
- if (params.description) data.description = params.description;
162
- if (params.categories) data.categories = params.categories;
163
- if (params.minValue !== undefined) data.minValue = params.minValue;
164
- if (params.maxValue !== undefined) data.maxValue = params.maxValue;
165
-
166
- const result = await client.request<unknown>('POST', '/api/public/score-configs', data);
167
- return JSON.stringify(result, null, 2);
168
- }
169
-
170
- export async function exportScoreConfigs(outputFile: string): Promise<string> {
171
- const configsRaw = await listScoreConfigs();
172
- const configs = JSON.parse(configsRaw) as Record<string, unknown>[];
173
-
174
- const exported = configs.map((c) => ({
175
- name: c.name,
176
- dataType: c.dataType,
177
- description: c.description,
178
- categories: c.categories,
179
- minValue: c.minValue,
180
- maxValue: c.maxValue,
181
- metadata: {
182
- id: c.id,
183
- createdAt: c.createdAt,
184
- updatedAt: c.updatedAt,
185
- projectId: c.projectId,
186
- isArchived: c.isArchived,
187
- },
188
- }));
189
-
190
- const exportData = {
191
- version: '1.0',
192
- exportedAt: nowISO(),
193
- totalConfigs: exported.length,
194
- configs: exported,
195
- };
196
-
197
- const json = JSON.stringify(exportData, null, 2);
198
- if (outputFile) {
199
- writeFileSync(outputFile, json, 'utf-8');
200
- }
201
- return json;
202
- }
203
-
204
- export async function importScoreConfigs(
205
- importFile: string,
206
- options?: { allowDuplicates?: boolean; selectedConfigs?: string[] },
207
- ): Promise<string> {
208
- let importData: Record<string, unknown>;
209
- try {
210
- importData = JSON.parse(readFileSync(importFile, 'utf-8')) as Record<string, unknown>;
211
- } catch (e) {
212
- return `❌ Failed to read import file: ${e}`;
213
- }
214
-
215
- const configsList = Array.isArray(importData)
216
- ? importData
217
- : (importData.configs as unknown[]) ?? [];
218
-
219
- if (!configsList.length) return '❌ No score configs found in import file.';
220
-
221
- const existingRaw = await listScoreConfigs();
222
- const existing = JSON.parse(existingRaw) as Record<string, unknown>[];
223
- const existingNames = new Set(existing.map((c) => String(c.name).toLowerCase()));
224
-
225
- const selected = options?.selectedConfigs
226
- ? new Set(options.selectedConfigs.map((n) => n.toLowerCase()))
227
- : null;
228
-
229
- const results: string[] = [];
230
- let imported = 0;
231
- let skipped = 0;
232
-
233
- for (const raw of configsList) {
234
- const cfg = raw as Record<string, unknown>;
235
- const name = String(cfg.name);
236
-
237
- if (selected && !selected.has(name.toLowerCase())) continue;
238
- if (existingNames.has(name.toLowerCase()) && !options?.allowDuplicates) {
239
- results.push(` ⏭️ '${name}' — skipped (duplicate)`);
240
- skipped++;
241
- continue;
242
- }
243
-
244
- try {
245
- const result = await createScoreConfig({
246
- name,
247
- dataType: cfg.dataType as 'NUMERIC' | 'CATEGORICAL' | 'BOOLEAN',
248
- description: cfg.description as string | undefined,
249
- categories: cfg.categories as Array<{ label: string; value: number }> | undefined,
250
- minValue: cfg.minValue as number | undefined,
251
- maxValue: cfg.maxValue as number | undefined,
252
- });
253
- const parsed = JSON.parse(result);
254
- results.push(` ✅ '${name}' (ID: ${parsed.id ?? 'created'})`);
255
- imported++;
256
- } catch (e) {
257
- results.push(` ❌ '${name}' — ${e}`);
258
- }
259
- }
260
-
261
- return [
262
- `📁 Import: ${importFile}`,
263
- `📊 Summary: ${imported} imported, ${skipped} skipped`,
264
- ...results,
265
- ].join('\n');
266
- }
267
-
268
- // ─── Score Config Caching / Apply ───────────────────────────────────
269
-
270
- export async function applyScoreConfig(
271
- configNameOrId: string,
272
- targetType: string,
273
- targetId: string,
274
- value: number,
275
- observationId?: string,
276
- comment?: string,
277
- ): Promise<string> {
278
- // Resolve config: try by ID first, then search by name
279
- let configId: string | undefined;
280
-
281
- try {
282
- const configJson = await getScoreConfig(configNameOrId);
283
- const config = JSON.parse(configJson);
284
- if (config.id) configId = config.id;
285
- } catch {
286
- // Try listing and searching by name
287
- const allJson = await listScoreConfigs();
288
- const all = JSON.parse(allJson) as Record<string, unknown>[];
289
- const match = all.find(
290
- (c) => String(c.name).toLowerCase() === configNameOrId.toLowerCase(),
291
- );
292
- if (match) configId = String(match.id);
293
- }
294
-
295
- if (!configId) {
296
- return JSON.stringify({ error: `Score config '${configNameOrId}' not found` });
297
- }
298
-
299
- return createScoreForTarget({
300
- targetType: targetType as 'trace' | 'session',
301
- targetId,
302
- configId,
303
- value,
304
- observationId,
305
- comment,
306
- });
307
- }
308
-
309
- // ─── Presets ────────────────────────────────────────────────────────
310
-
311
- export function getBuiltInPresets(): ScoreConfig[] {
312
- return BUILT_IN_PRESETS.map((p) => ({ ...p }));
313
- }
314
-
315
- export async function installPreset(
316
- name: string,
317
- checkDuplicates = true,
318
- ): Promise<string> {
319
- const preset = BUILT_IN_PRESETS.find((p) => p.name.toLowerCase() === name.toLowerCase());
320
- if (!preset) {
321
- return JSON.stringify({ error: `Preset '${name}' not found` });
322
- }
323
-
324
- if (checkDuplicates) {
325
- const existingRaw = await listScoreConfigs();
326
- const existing = JSON.parse(existingRaw) as Record<string, unknown>[];
327
- const dup = existing.find((c) => String(c.name).toLowerCase() === preset.name.toLowerCase());
328
- if (dup) {
329
- return JSON.stringify({
330
- warning: `Score config '${preset.name}' already exists (ID: ${dup.id})`,
331
- existingId: dup.id,
332
- });
333
- }
334
- }
335
-
336
- return createScoreConfig({
337
- name: preset.name,
338
- dataType: preset.dataType,
339
- description: preset.description,
340
- categories: preset.categories,
341
- minValue: preset.minValue,
342
- maxValue: preset.maxValue,
343
- });
344
- }
345
-
346
- // ─── Formatters ─────────────────────────────────────────────────────
347
-
348
- export function formatScoresTable(json: unknown): string {
349
- try {
350
- const raw = typeof json === 'string' ? JSON.parse(json) : json;
351
- const scores: Record<string, unknown>[] = Array.isArray(raw)
352
- ? raw
353
- : (raw as Record<string, unknown>).data as Record<string, unknown>[] ?? [];
354
-
355
- if (!scores.length) return 'No scores found.';
356
-
357
- const headers = ['ID', 'Name', 'Value', 'Created', 'Trace ID'];
358
- const rows = scores.map((s) => [
359
- trunc(String(s.id ?? 'N/A'), 20),
360
- trunc(String(s.name ?? 'N/A'), 20),
361
- String(s.value ?? 'N/A'),
362
- String(s.createdAt ?? 'N/A').slice(0, 16),
363
- trunc(String(s.traceId ?? 'N/A'), 20),
364
- ]);
365
-
366
- return formatTable(headers, rows) + `\nTotal scores: ${scores.length}`;
367
- } catch (e) {
368
- return `Error formatting scores: ${e}`;
369
- }
370
- }
371
-
372
- export function formatScoreConfigsTable(json: unknown): string {
373
- try {
374
- const raw = typeof json === 'string' ? JSON.parse(json) : json;
375
- const configs: Record<string, unknown>[] = Array.isArray(raw)
376
- ? raw
377
- : (raw as Record<string, unknown>).data as Record<string, unknown>[] ?? [];
378
-
379
- if (!configs.length) return 'No score configs found.';
380
-
381
- const headers = ['ID', 'Name', 'Data Type', 'Description', 'Created'];
382
- const rows = configs.map((c) => [
383
- trunc(String(c.id ?? 'N/A'), 20),
384
- trunc(String(c.name ?? 'N/A'), 20),
385
- String(c.dataType ?? 'N/A'),
386
- trunc(String(c.description ?? 'N/A'), 35),
387
- String(c.createdAt ?? 'N/A').slice(0, 16),
388
- ]);
389
-
390
- return formatTable(headers, rows) + `\nTotal score configs: ${configs.length}`;
391
- } catch (e) {
392
- return `Error formatting score configs: ${e}`;
393
- }
394
- }
395
-
396
- // ─── Built-in Presets ───────────────────────────────────────────────
397
-
398
- const BUILT_IN_PRESETS: ScoreConfig[] = [
399
- // Narrative & Storytelling
400
- { name: 'Narrative Coherence', dataType: 'CATEGORICAL', description: 'Evaluates how well story elements connect and flow together logically.', categories: [{ label: 'Incoherent', value: 1 }, { label: 'Loosely Connected', value: 2 }, { label: 'Coherent', value: 3 }, { label: 'Well-Structured', value: 4 }, { label: 'Masterfully Woven', value: 5 }] },
401
- { name: 'Character Development', dataType: 'CATEGORICAL', description: 'Measures the depth and growth of characters throughout the narrative.', categories: [{ label: 'Flat/Static', value: 1 }, { label: 'Basic Development', value: 2 }, { label: 'Moderate Growth', value: 3 }, { label: 'Rich Development', value: 4 }, { label: 'Complex Evolution', value: 5 }] },
402
- { name: 'Emotional Resonance', dataType: 'CATEGORICAL', description: 'Evaluates the emotional impact and connection with the audience.', categories: [{ label: 'No Emotional Impact', value: 1 }, { label: 'Mild Resonance', value: 2 }, { label: 'Moderate Impact', value: 3 }, { label: 'Strong Emotional Connection', value: 4 }, { label: 'Deeply Moving', value: 5 }] },
403
- { name: 'Originality', dataType: 'CATEGORICAL', description: 'Evaluates the uniqueness and freshness of the ideas or expression.', categories: [{ label: 'Unoriginal', value: 1 }, { label: 'Low Originality', value: 2 }, { label: 'Moderate Originality', value: 3 }, { label: 'High Originality', value: 4 }, { label: 'Highly Original', value: 5 }] },
404
- { name: 'Thematic Depth', dataType: 'CATEGORICAL', description: 'Measures the depth and sophistication of underlying themes.', categories: [{ label: 'Surface Level', value: 1 }, { label: 'Basic Themes', value: 2 }, { label: 'Developed Themes', value: 3 }, { label: 'Rich Thematic Content', value: 4 }, { label: 'Profound Depth', value: 5 }] },
405
- // AI Response Evaluation
406
- { name: 'Helpfulness', dataType: 'CATEGORICAL', description: 'Measures how well the response addresses the user\'s needs.', categories: [{ label: 'Not Helpful', value: 1 }, { label: 'Slightly Helpful', value: 2 }, { label: 'Moderately Helpful', value: 3 }, { label: 'Very Helpful', value: 4 }, { label: 'Extremely Helpful', value: 5 }] },
407
- { name: 'Accuracy', dataType: 'CATEGORICAL', description: 'Evaluates the factual correctness and precision of information.', categories: [{ label: 'Inaccurate', value: 1 }, { label: 'Mostly Inaccurate', value: 2 }, { label: 'Partially Accurate', value: 3 }, { label: 'Mostly Accurate', value: 4 }, { label: 'Completely Accurate', value: 5 }] },
408
- { name: 'Safety', dataType: 'CATEGORICAL', description: 'Assesses whether the content is safe and free from harmful elements.', categories: [{ label: 'Unsafe/Harmful', value: 1 }, { label: 'Potentially Unsafe', value: 2 }, { label: 'Neutral/Safe', value: 3 }, { label: 'Very Safe', value: 4 }, { label: 'Exemplarily Safe', value: 5 }] },
409
- { name: 'Relevance', dataType: 'CATEGORICAL', description: 'Measures how well the response relates to the specific query.', categories: [{ label: 'Irrelevant', value: 1 }, { label: 'Slightly Relevant', value: 2 }, { label: 'Moderately Relevant', value: 3 }, { label: 'Highly Relevant', value: 4 }, { label: 'Perfectly Relevant', value: 5 }] },
410
- { name: 'Completeness', dataType: 'CATEGORICAL', description: 'Evaluates whether the response fully addresses all aspects.', categories: [{ label: 'Incomplete', value: 1 }, { label: 'Partially Complete', value: 2 }, { label: 'Mostly Complete', value: 3 }, { label: 'Very Complete', value: 4 }, { label: 'Comprehensive', value: 5 }] },
411
- // General Content
412
- { name: 'Clarity', dataType: 'CATEGORICAL', description: 'Measures how easy it is to understand the content.', categories: [{ label: 'Unclear', value: 1 }, { label: 'Moderately Clear', value: 2 }, { label: 'Clear', value: 3 }, { label: 'Very Clear', value: 4 }, { label: 'Excellent Clarity', value: 5 }] },
413
- { name: 'Engagement', dataType: 'CATEGORICAL', description: 'Evaluates how well the content captures attention.', categories: [{ label: 'Disengaging', value: 1 }, { label: 'Slightly Engaging', value: 2 }, { label: 'Engaging', value: 3 }, { label: 'Very Engaging', value: 4 }, { label: 'Highly Engaging', value: 5 }] },
414
- { name: 'Tone Appropriateness', dataType: 'CATEGORICAL', description: 'Assesses whether the tone matches context and audience expectations.', categories: [{ label: 'Inappropriate Tone', value: 1 }, { label: 'Somewhat Inappropriate', value: 2 }, { label: 'Acceptable Tone', value: 3 }, { label: 'Well-Matched Tone', value: 4 }, { label: 'Perfect Tone', value: 5 }] },
415
- { name: 'Conciseness', dataType: 'CATEGORICAL', description: 'Evaluates the efficiency of communication.', categories: [{ label: 'Verbose/Wordy', value: 1 }, { label: 'Somewhat Verbose', value: 2 }, { label: 'Balanced', value: 3 }, { label: 'Concise', value: 4 }, { label: 'Perfectly Concise', value: 5 }] },
416
- // Technical Quality
417
- { name: 'Structure & Organization', dataType: 'CATEGORICAL', description: 'Evaluates the logical organization and structural quality.', categories: [{ label: 'Disorganized', value: 1 }, { label: 'Basic Structure', value: 2 }, { label: 'Well-Organized', value: 3 }, { label: 'Excellent Structure', value: 4 }, { label: 'Masterful Organization', value: 5 }] },
418
- { name: 'Language Quality', dataType: 'CATEGORICAL', description: 'Assesses grammar, vocabulary usage, and linguistic competence.', categories: [{ label: 'Poor Language', value: 1 }, { label: 'Fair Language', value: 2 }, { label: 'Good Language', value: 3 }, { label: 'Excellent Language', value: 4 }, { label: 'Exceptional Language', value: 5 }] },
419
- // Specialized
420
- { name: 'Critical Thinking', dataType: 'CATEGORICAL', description: 'Measures the depth of analysis, reasoning, and intellectual rigor.', categories: [{ label: 'No Critical Analysis', value: 1 }, { label: 'Basic Analysis', value: 2 }, { label: 'Sound Reasoning', value: 3 }, { label: 'Strong Critical Thinking', value: 4 }, { label: 'Exceptional Analysis', value: 5 }] },
421
- { name: 'Evidence Support', dataType: 'CATEGORICAL', description: 'Evaluates the use and quality of supporting evidence.', categories: [{ label: 'No Evidence', value: 1 }, { label: 'Weak Evidence', value: 2 }, { label: 'Adequate Evidence', value: 3 }, { label: 'Strong Evidence', value: 4 }, { label: 'Compelling Evidence', value: 5 }] },
422
- { name: 'Innovation', dataType: 'CATEGORICAL', description: 'Assesses creativity and novel approaches in problem-solving.', categories: [{ label: 'Conventional', value: 1 }, { label: 'Slightly Creative', value: 2 }, { label: 'Moderately Innovative', value: 3 }, { label: 'Highly Innovative', value: 4 }, { label: 'Groundbreaking', value: 5 }] },
423
- // Numeric
424
- { name: 'Overall Quality', dataType: 'NUMERIC', description: 'General numeric assessment of overall content quality.', minValue: 0, maxValue: 10 },
425
- { name: 'Performance Score', dataType: 'NUMERIC', description: 'Numeric performance evaluation score.', minValue: 0, maxValue: 100 },
426
- // Boolean
427
- { name: 'Meets Requirements', dataType: 'BOOLEAN', description: 'Binary assessment of whether content meets specified requirements.' },
428
- ];
429
-
430
- // ─── Helpers ────────────────────────────────────────────────────────
431
-
432
- function shouldContinuePagination(data: Record<string, unknown>, currentPage: number): boolean {
433
- const meta = data.meta as Record<string, unknown> | undefined;
434
- if (meta?.totalPages) {
435
- return (meta.page as number ?? currentPage) < (meta.totalPages as number);
436
- }
437
- if (data.hasNextPage) return true;
438
- if (data.totalPages && currentPage < (data.totalPages as number)) return true;
439
- return false;
440
- }
441
-
442
- function trunc(s: string, len: number): string {
443
- return s.length > len ? s.slice(0, len - 3) + '...' : s;
444
- }
445
-
446
- function formatTable(headers: string[], rows: string[][]): string {
447
- const widths = headers.map((h, i) =>
448
- Math.max(h.length, ...rows.map((r) => (r[i] ?? '').length)),
449
- );
450
- const sep = '+' + widths.map((w) => '-'.repeat(w + 2)).join('+') + '+';
451
- const hdr = '| ' + headers.map((h, i) => h.padEnd(widths[i])).join(' | ') + ' |';
452
- const body = rows.map(
453
- (r) => '| ' + r.map((c, i) => (c ?? '').padEnd(widths[i])).join(' | ') + ' |',
454
- );
455
- return [sep, hdr, sep, ...body, sep].join('\n');
456
- }