coaiajs 0.2.0 → 0.3.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/.claude/settings.local.json +2 -1
- package/.claude-plugin/marketplace.json +26 -0
- package/coaiajs-langfuse-claude-plugin/.claude-plugin/marketplace.json +16 -0
- package/coaiajs-langfuse-claude-plugin/.claude-plugin/plugin.json +10 -0
- package/coaiajs-langfuse-claude-plugin/.mcp.json +8 -0
- package/coaiajs-langfuse-claude-plugin/README.md +60 -0
- package/dist/mcp/server.js +2 -1
- package/dist/src/cli.js +2 -1
- package/dist/src/langfuse/index.d.ts +2 -2
- package/dist/src/langfuse/index.js +2 -2
- package/dist/src/langfuse/observations.d.ts +8 -1
- package/dist/src/langfuse/observations.js +29 -7
- package/dist/src/langfuse/traces.d.ts +19 -1
- package/dist/src/langfuse/traces.js +37 -2
- package/dist/src/version.d.ts +3 -0
- package/dist/src/version.js +33 -0
- package/mcp/server.ts +2 -1
- package/package.json +3 -3
- package/src/cli.ts +2 -1
- package/src/langfuse/index.ts +6 -2
- package/src/langfuse/observations.ts +29 -5
- package/src/langfuse/traces.ts +53 -2
- package/src/version.ts +39 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "coaiajs-marketplace",
|
|
3
|
+
"owner": {
|
|
4
|
+
"name": "Guillaume Isabelle",
|
|
5
|
+
"email": "jgi@jgwill.com",
|
|
6
|
+
"url": "https://github.com/jgwill"
|
|
7
|
+
},
|
|
8
|
+
"metadata": {
|
|
9
|
+
"description": "CoAIA Claude Code plugins",
|
|
10
|
+
"version": "0.3.0"
|
|
11
|
+
},
|
|
12
|
+
"plugins": [
|
|
13
|
+
{
|
|
14
|
+
"name": "coaiajs-langfuse",
|
|
15
|
+
"source": "./coaiajs-langfuse-claude-plugin",
|
|
16
|
+
"description": "CoAIA unified MCP — 64+ tools (structural tension charts, narrative knowledge graph, PDE, planning, Redis tash/fetch, Langfuse tracing).",
|
|
17
|
+
"version": "0.3.0",
|
|
18
|
+
"author": {
|
|
19
|
+
"name": "Guillaume Isabelle",
|
|
20
|
+
"url": "https://github.com/jgwill"
|
|
21
|
+
},
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"keywords": ["coaia", "mcp", "structural-tension", "narrative", "pde", "planning", "langfuse"]
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "coaiajs-marketplace",
|
|
3
|
+
"owner": { "name": "Guillaume Isabelle", "email": "jgi@jgwill.com", "url": "https://github.com/jgwill" },
|
|
4
|
+
"metadata": { "description": "CoAIA Claude Code plugins", "version": "0.3.0" },
|
|
5
|
+
"plugins": [
|
|
6
|
+
{
|
|
7
|
+
"name": "coaiajs-langfuse",
|
|
8
|
+
"source": "./",
|
|
9
|
+
"description": "CoAIA unified MCP — 64+ tools (structural tension, narrative graph, PDE, planning, Redis tash/fetch, Langfuse tracing).",
|
|
10
|
+
"version": "0.3.0",
|
|
11
|
+
"author": { "name": "Guillaume Isabelle", "url": "https://github.com/jgwill" },
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"keywords": ["coaia", "mcp", "structural-tension", "narrative", "pde", "planning", "langfuse"]
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "coaiajs-langfuse",
|
|
3
|
+
"description": "CoAIA unified MCP for Claude Code — 64+ tools across structural-tension charts, narrative knowledge graph, Prompt Decomposition Engine (PDE), action planning, Redis tash/fetch, and Langfuse tracing. Bundles the published `coaiajs` npm package's `coaiajs-mcp` server via npx.",
|
|
4
|
+
"version": "0.3.0",
|
|
5
|
+
"author": { "name": "Guillaume Isabelle", "email": "jgi@jgwill.com", "url": "https://github.com/jgwill" },
|
|
6
|
+
"homepage": "https://github.com/jgwill/coaiajs/tree/master/coaiajs-langfuse-claude-plugin",
|
|
7
|
+
"repository": "https://github.com/jgwill/coaiajs",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"keywords": ["coaia", "mcp", "structural-tension", "narrative", "pde", "planning", "langfuse"]
|
|
10
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# coaiajs-langfuse — Claude Code Plugin
|
|
2
|
+
|
|
3
|
+
A Claude Code plugin that registers the `coaiajs-mcp` server — 64+ tools, 3 prompts, and 3 resources — as an MCP server inside Claude Code. It does not bundle its own copy of the server; it launches the published `coaiajs` npm package on demand via `npx`:
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
npx -y --package=coaiajs coaiajs-mcp
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
That command is declared in `.mcp.json` at the root of this plugin, which Claude Code auto-loads on install.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
From a marketplace source (GitHub):
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
claude plugin marketplace add https://github.com/jgwill/coaiajs
|
|
17
|
+
claude plugin install coaiajs-langfuse@coaiajs-marketplace
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Or from a local checkout:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
claude plugin marketplace add /a/src/coaiajs/coaiajs-langfuse-claude-plugin
|
|
24
|
+
claude plugin install coaiajs-langfuse@coaiajs-marketplace
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Confirm it registered:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
claude plugin list
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Tool families
|
|
34
|
+
|
|
35
|
+
- **Structural-tension charts** — desired outcome / current reality / action steps, the core CoAIA data model.
|
|
36
|
+
- **Narrative knowledge graph** — entities, relations, and graph queries (from coaia-narrative).
|
|
37
|
+
- **PDE (Prompt Decomposition Engine)** — decompose complex prompts into actionable intent maps.
|
|
38
|
+
- **Action planning** — structural tension plans and action-step management (from coaia-planning).
|
|
39
|
+
- **Redis tash/fetch** — SET/GET shorthand against a Redis store.
|
|
40
|
+
- **Langfuse tracing** — trace, span, and observation tools for Langfuse-backed observability.
|
|
41
|
+
|
|
42
|
+
## Environment variables
|
|
43
|
+
|
|
44
|
+
The server boots with no configuration — it connects to nothing at import time. Individual tool families activate only when their own credentials are present in the environment Claude Code runs in:
|
|
45
|
+
|
|
46
|
+
| Variable | Used by |
|
|
47
|
+
| --- | --- |
|
|
48
|
+
| `REDIS_URL` | tash/fetch |
|
|
49
|
+
| `OPENAI_API_KEY` | LLM-backed tools |
|
|
50
|
+
| `LANGFUSE_PUBLIC_KEY` | Langfuse tracing |
|
|
51
|
+
| `LANGFUSE_SECRET_KEY` | Langfuse tracing |
|
|
52
|
+
| `LANGFUSE_BASE_URL` | Langfuse tracing |
|
|
53
|
+
| `GITHUB_TOKEN` | GitHub-integration tools |
|
|
54
|
+
| AWS credentials (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, etc.) | Polly audio tools |
|
|
55
|
+
|
|
56
|
+
None of these are set by the plugin itself — they are inherited from whatever shell/environment Claude Code is launched in. Set them in your shell profile, `.env`, or however you normally manage secrets for this machine.
|
|
57
|
+
|
|
58
|
+
## Versioning
|
|
59
|
+
|
|
60
|
+
This plugin tracks the published npm `coaiajs` package rather than vendoring source. `.mcp.json` calls `npx -y --package=coaiajs coaiajs-mcp`, which always resolves the latest published version at launch time. To pin a specific version, edit `.mcp.json` and change `--package=coaiajs` to `--package=coaiajs@<version>` (e.g. `coaiajs@0.3.0`).
|
package/dist/mcp/server.js
CHANGED
|
@@ -12,6 +12,7 @@ import { tash as redisTash, fetch as redisFetch } from '../src/redis.js';
|
|
|
12
12
|
import { ALL_TOOL_DEFINITIONS as NARRATIVE_TOOL_DEFINITIONS, handleToolCall as handleNarrativeTool, KnowledgeGraphManager, } from '../src/narrative/index.js';
|
|
13
13
|
import { PDE_MCP_TOOLS, handlePdeTool } from '../src/pde/index.js';
|
|
14
14
|
import { PLANNING_MCP_TOOLS, handlePlanningTool } from '../src/planning/index.js';
|
|
15
|
+
import { getPackageVersion } from '../src/version.js';
|
|
15
16
|
// Langfuse imports
|
|
16
17
|
import { addTrace, patchTraceOutput, listTraces, getTrace, formatTracesMarkdown, formatTraceTree, } from '../src/langfuse/traces.js';
|
|
17
18
|
import { addObservation, getObservation, formatObservationDisplay } from '../src/langfuse/observations.js';
|
|
@@ -22,7 +23,7 @@ import { listComments, getComment, createComment } from '../src/langfuse/comment
|
|
|
22
23
|
import { uploadAndAttachMedia, getMedia, formatMediaDisplay } from '../src/langfuse/media.js';
|
|
23
24
|
// ─── Server Info ────────────────────────────────────────────────────
|
|
24
25
|
const SERVER_NAME = 'coaiajs-mcp';
|
|
25
|
-
const SERVER_VERSION =
|
|
26
|
+
const SERVER_VERSION = getPackageVersion();
|
|
26
27
|
// ─── Parse CLI args ─────────────────────────────────────────────────
|
|
27
28
|
function parseArgs() {
|
|
28
29
|
const args = process.argv.slice(2);
|
package/dist/src/cli.js
CHANGED
|
@@ -8,6 +8,7 @@ import { readConfig } from './config.js';
|
|
|
8
8
|
import { llm as llmCall, transcribeAudio, abstractProcess } from './llm.js';
|
|
9
9
|
import { listIssues, getIssue } from './github.js';
|
|
10
10
|
import { createEnvironment, findEnvironment } from './environment.js';
|
|
11
|
+
import { getPackageVersion } from './version.js';
|
|
11
12
|
import { formatTable, formatJson, formatError, formatSuccess, truncate, formatDate, formatProgress, setColorEnabled, } from './cli-helpers.js';
|
|
12
13
|
// ---------------------------------------------------------------------------
|
|
13
14
|
// Helpers
|
|
@@ -1084,7 +1085,7 @@ async function main() {
|
|
|
1084
1085
|
const program = new Command();
|
|
1085
1086
|
program
|
|
1086
1087
|
.name('coaia')
|
|
1087
|
-
.version(
|
|
1088
|
+
.version(getPackageVersion(), '-V, --version')
|
|
1088
1089
|
.description('CoAIA unified CLI — structural tension, narrative, and DevOps tooling')
|
|
1089
1090
|
.option('--env <path>', 'Load environment file')
|
|
1090
1091
|
.option('-M, --memory-path <path>', 'JSONL memory file path')
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export { LangfuseClient, LangfuseApiError, getClient, resetClient, nowISO } from './client.js';
|
|
2
2
|
export type { IngestionEvent, LangfuseClientConfig } from './client.js';
|
|
3
|
-
export { addTrace, patchTraceOutput, listTraces, getTrace, formatTracesTable, formatTracesMarkdown, formatTraceTree } from './traces.js';
|
|
3
|
+
export { addTrace, createTrace, patchTraceOutput, listTraces, getTrace, traceView, sessionView, formatTracesTable, formatTracesMarkdown, formatTraceTree, } from './traces.js';
|
|
4
4
|
export type { TraceFilters } from './traces.js';
|
|
5
|
-
export { addObservation, getObservation, formatObservationDisplay } from './observations.js';
|
|
5
|
+
export { addObservation, addObservations, getObservation, formatObservationDisplay } from './observations.js';
|
|
6
6
|
export { listPrompts, getPrompt, createPrompt, formatPromptsTable, formatPromptDisplay } from './prompts.js';
|
|
7
7
|
export { listDatasets, getDataset, createDataset, listDatasetItems, createDatasetItem, formatDatasetsTable, formatDatasetForFinetuning, } from './datasets.js';
|
|
8
8
|
export { createScore, applyScoreToTrace, createScoreForTarget, listScores, listScoreConfigs, getScoreConfig, createScoreConfig, exportScoreConfigs, importScoreConfigs, applyScoreConfig, getBuiltInPresets, installPreset, formatScoresTable, formatScoreConfigsTable, } from './scores.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// coaiajs/src/langfuse/index.ts — Barrel export
|
|
2
2
|
export { LangfuseClient, LangfuseApiError, getClient, resetClient, nowISO } from './client.js';
|
|
3
|
-
export { addTrace, patchTraceOutput, listTraces, getTrace, formatTracesTable, formatTracesMarkdown, formatTraceTree } from './traces.js';
|
|
4
|
-
export { addObservation, getObservation, formatObservationDisplay } from './observations.js';
|
|
3
|
+
export { addTrace, createTrace, patchTraceOutput, listTraces, getTrace, traceView, sessionView, formatTracesTable, formatTracesMarkdown, formatTraceTree, } from './traces.js';
|
|
4
|
+
export { addObservation, addObservations, getObservation, formatObservationDisplay } from './observations.js';
|
|
5
5
|
export { listPrompts, getPrompt, createPrompt, formatPromptsTable, formatPromptDisplay } from './prompts.js';
|
|
6
6
|
export { listDatasets, getDataset, createDataset, listDatasetItems, createDatasetItem, formatDatasetsTable, formatDatasetForFinetuning, } from './datasets.js';
|
|
7
7
|
export { createScore, applyScoreToTrace, createScoreForTarget, listScores, listScoreConfigs, getScoreConfig, createScoreConfig, exportScoreConfigs, importScoreConfigs, applyScoreConfig, getBuiltInPresets, installPreset, formatScoresTable, formatScoreConfigsTable, } from './scores.js';
|
|
@@ -4,9 +4,12 @@ export declare function addObservation(params: {
|
|
|
4
4
|
type?: string;
|
|
5
5
|
name: string;
|
|
6
6
|
parentId?: string;
|
|
7
|
+
parentObservationId?: string;
|
|
8
|
+
input?: string;
|
|
7
9
|
inputData?: unknown;
|
|
10
|
+
output?: string;
|
|
8
11
|
outputData?: unknown;
|
|
9
|
-
metadata?: unknown;
|
|
12
|
+
metadata?: string | unknown;
|
|
10
13
|
startTime?: string;
|
|
11
14
|
endTime?: string;
|
|
12
15
|
level?: string;
|
|
@@ -14,5 +17,9 @@ export declare function addObservation(params: {
|
|
|
14
17
|
usage?: unknown;
|
|
15
18
|
}): Promise<string>;
|
|
16
19
|
export declare function getObservation(observationId: string): Promise<string>;
|
|
20
|
+
export declare function addObservations(params: {
|
|
21
|
+
traceId?: string;
|
|
22
|
+
observations?: Array<Record<string, unknown>>;
|
|
23
|
+
}): Promise<string>;
|
|
17
24
|
export declare function formatObservationDisplay(json: unknown): string;
|
|
18
25
|
//# sourceMappingURL=observations.d.ts.map
|
|
@@ -15,14 +15,14 @@ export async function addObservation(params) {
|
|
|
15
15
|
};
|
|
16
16
|
if (params.name)
|
|
17
17
|
body.name = params.name;
|
|
18
|
-
if (params.inputData)
|
|
19
|
-
body.input = params.inputData;
|
|
20
|
-
if (params.outputData)
|
|
21
|
-
body.output = params.outputData;
|
|
18
|
+
if (params.inputData ?? params.input)
|
|
19
|
+
body.input = parseJsonOption(params.inputData ?? params.input);
|
|
20
|
+
if (params.outputData ?? params.output)
|
|
21
|
+
body.output = parseJsonOption(params.outputData ?? params.output);
|
|
22
22
|
if (params.metadata)
|
|
23
|
-
body.metadata = params.metadata;
|
|
24
|
-
if (params.parentId)
|
|
25
|
-
body.parentObservationId = params.parentId;
|
|
23
|
+
body.metadata = parseJsonOption(params.metadata);
|
|
24
|
+
if (params.parentId ?? params.parentObservationId)
|
|
25
|
+
body.parentObservationId = params.parentId ?? params.parentObservationId;
|
|
26
26
|
if (params.endTime)
|
|
27
27
|
body.endTime = params.endTime;
|
|
28
28
|
if (params.model)
|
|
@@ -49,6 +49,28 @@ export async function getObservation(observationId) {
|
|
|
49
49
|
const result = await client.request('GET', `/api/public/observations/${observationId}`);
|
|
50
50
|
return JSON.stringify(result, null, 2);
|
|
51
51
|
}
|
|
52
|
+
function parseJsonOption(value) {
|
|
53
|
+
if (typeof value !== 'string')
|
|
54
|
+
return value;
|
|
55
|
+
try {
|
|
56
|
+
return JSON.parse(value);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return value;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export async function addObservations(params) {
|
|
63
|
+
const observations = params.observations ?? [];
|
|
64
|
+
const results = [];
|
|
65
|
+
for (const observation of observations) {
|
|
66
|
+
const traceId = String(observation.traceId ?? params.traceId ?? '');
|
|
67
|
+
const name = String(observation.name ?? 'Observation');
|
|
68
|
+
if (!traceId)
|
|
69
|
+
throw new Error('traceId is required for every observation');
|
|
70
|
+
results.push(JSON.parse(await addObservation({ ...observation, traceId, name })));
|
|
71
|
+
}
|
|
72
|
+
return JSON.stringify({ success: true, count: results.length, observations: results }, null, 2);
|
|
73
|
+
}
|
|
52
74
|
// ─── Formatters ─────────────────────────────────────────────────────
|
|
53
75
|
const TYPE_GLYPHS = {
|
|
54
76
|
SPAN: '🔗',
|
|
@@ -21,9 +21,27 @@ export declare function addTrace(params: {
|
|
|
21
21
|
outputData?: unknown;
|
|
22
22
|
metadata?: unknown;
|
|
23
23
|
}): Promise<string>;
|
|
24
|
-
export declare function patchTraceOutput(
|
|
24
|
+
export declare function patchTraceOutput(traceIdOrParams: string | {
|
|
25
|
+
traceId?: string;
|
|
26
|
+
output?: string;
|
|
27
|
+
outputData?: unknown;
|
|
28
|
+
}, outputData?: unknown): Promise<string>;
|
|
29
|
+
export declare function createTrace(params: {
|
|
30
|
+
traceId?: string;
|
|
31
|
+
id?: string;
|
|
32
|
+
userId?: string;
|
|
33
|
+
sessionId?: string;
|
|
34
|
+
name?: string;
|
|
35
|
+
input?: string;
|
|
36
|
+
inputData?: unknown;
|
|
37
|
+
output?: string;
|
|
38
|
+
outputData?: unknown;
|
|
39
|
+
metadata?: string | unknown;
|
|
40
|
+
}): Promise<string>;
|
|
25
41
|
export declare function listTraces(filters: TraceFilters): Promise<string>;
|
|
26
42
|
export declare function getTrace(traceId: string): Promise<string>;
|
|
43
|
+
export declare function traceView(traceId: string): Promise<string>;
|
|
44
|
+
export declare function sessionView(sessionId: string): Promise<string>;
|
|
27
45
|
export declare function formatTracesTable(json: unknown): string;
|
|
28
46
|
export declare function formatTraceTree(json: unknown): string;
|
|
29
47
|
export declare function formatTracesMarkdown(json: unknown): string;
|
|
@@ -35,13 +35,19 @@ export async function addTrace(params) {
|
|
|
35
35
|
message: `Trace ${traceId} created`,
|
|
36
36
|
}, null, 2);
|
|
37
37
|
}
|
|
38
|
-
export async function patchTraceOutput(
|
|
38
|
+
export async function patchTraceOutput(traceIdOrParams, outputData) {
|
|
39
|
+
const traceId = typeof traceIdOrParams === 'string' ? traceIdOrParams : traceIdOrParams.traceId;
|
|
40
|
+
if (!traceId)
|
|
41
|
+
throw new Error('traceId is required');
|
|
42
|
+
const output = typeof traceIdOrParams === 'string'
|
|
43
|
+
? outputData
|
|
44
|
+
: parseJsonOption(traceIdOrParams.outputData ?? traceIdOrParams.output);
|
|
39
45
|
const client = getClient();
|
|
40
46
|
const now = nowISO();
|
|
41
47
|
const body = {
|
|
42
48
|
id: traceId,
|
|
43
49
|
timestamp: now,
|
|
44
|
-
output
|
|
50
|
+
output,
|
|
45
51
|
};
|
|
46
52
|
const eventId = `${traceId}-patch-${uuidv4().slice(0, 8)}`;
|
|
47
53
|
const event = {
|
|
@@ -57,6 +63,27 @@ export async function patchTraceOutput(traceId, outputData) {
|
|
|
57
63
|
message: `Trace output patched for ${traceId}`,
|
|
58
64
|
}, null, 2);
|
|
59
65
|
}
|
|
66
|
+
function parseJsonOption(value) {
|
|
67
|
+
if (typeof value !== 'string')
|
|
68
|
+
return value;
|
|
69
|
+
try {
|
|
70
|
+
return JSON.parse(value);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return value;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
export async function createTrace(params) {
|
|
77
|
+
return addTrace({
|
|
78
|
+
traceId: params.traceId ?? params.id,
|
|
79
|
+
userId: params.userId,
|
|
80
|
+
sessionId: params.sessionId,
|
|
81
|
+
name: params.name,
|
|
82
|
+
inputData: parseJsonOption(params.inputData ?? params.input),
|
|
83
|
+
outputData: parseJsonOption(params.outputData ?? params.output),
|
|
84
|
+
metadata: parseJsonOption(params.metadata),
|
|
85
|
+
});
|
|
86
|
+
}
|
|
60
87
|
export async function listTraces(filters) {
|
|
61
88
|
const client = getClient();
|
|
62
89
|
const params = new URLSearchParams();
|
|
@@ -111,6 +138,14 @@ export async function getTrace(traceId) {
|
|
|
111
138
|
}
|
|
112
139
|
return JSON.stringify(trace, null, 2);
|
|
113
140
|
}
|
|
141
|
+
export async function traceView(traceId) {
|
|
142
|
+
const raw = await getTrace(traceId);
|
|
143
|
+
return formatTraceTree(raw);
|
|
144
|
+
}
|
|
145
|
+
export async function sessionView(sessionId) {
|
|
146
|
+
const raw = await listTraces({ sessionId, limit: 20, orderBy: 'timestamp.desc' });
|
|
147
|
+
return formatTracesMarkdown(raw);
|
|
148
|
+
}
|
|
114
149
|
// ─── Formatters ─────────────────────────────────────────────────────
|
|
115
150
|
export function formatTracesTable(json) {
|
|
116
151
|
try {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// coaiajs/src/version.ts — single source of truth for the runtime version.
|
|
2
|
+
// Reads package.json at runtime so the CLI banner, the MCP handshake, and the
|
|
3
|
+
// published package can never drift apart again.
|
|
4
|
+
import { readFileSync } from 'node:fs';
|
|
5
|
+
import { dirname, join } from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
const PACKAGE_NAME = 'coaiajs';
|
|
8
|
+
let cached;
|
|
9
|
+
/** Resolved version of the installed `coaiajs` package. */
|
|
10
|
+
export function getPackageVersion() {
|
|
11
|
+
if (cached)
|
|
12
|
+
return cached;
|
|
13
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
// dist/src/version.js -> package root is two levels up.
|
|
15
|
+
// src/version.ts (ts-node/tsx) -> package root is one level up.
|
|
16
|
+
const candidates = [join(here, '..', '..', 'package.json'), join(here, '..', 'package.json')];
|
|
17
|
+
for (const candidate of candidates) {
|
|
18
|
+
let raw;
|
|
19
|
+
try {
|
|
20
|
+
raw = readFileSync(candidate, 'utf8');
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
continue; // not at this depth; try the next candidate
|
|
24
|
+
}
|
|
25
|
+
const pkg = JSON.parse(raw);
|
|
26
|
+
if (pkg.name === PACKAGE_NAME && pkg.version) {
|
|
27
|
+
cached = pkg.version;
|
|
28
|
+
return cached;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
throw new Error(`Unable to resolve ${PACKAGE_NAME} version: no package.json found near ${here}`);
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=version.js.map
|
package/mcp/server.ts
CHANGED
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
import { PDE_MCP_TOOLS, handlePdeTool } from '../src/pde/index.js';
|
|
29
29
|
import { PLANNING_MCP_TOOLS, handlePlanningTool } from '../src/planning/index.js';
|
|
30
30
|
import type { McpToolResult } from '../src/types.js';
|
|
31
|
+
import { getPackageVersion } from '../src/version.js';
|
|
31
32
|
|
|
32
33
|
// Langfuse imports
|
|
33
34
|
import {
|
|
@@ -46,7 +47,7 @@ import { uploadAndAttachMedia, getMedia, formatMediaDisplay } from '../src/langf
|
|
|
46
47
|
// ─── Server Info ────────────────────────────────────────────────────
|
|
47
48
|
|
|
48
49
|
const SERVER_NAME = 'coaiajs-mcp';
|
|
49
|
-
const SERVER_VERSION =
|
|
50
|
+
const SERVER_VERSION = getPackageVersion();
|
|
50
51
|
|
|
51
52
|
// ─── Parse CLI args ─────────────────────────────────────────────────
|
|
52
53
|
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "coaiajs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "CoAIA unified TypeScript monorepo — CLI, MCP server, and library consolidating coaia-narrative, coaia-pde, coaia-planning, and coaiapy patterns into one package.",
|
|
6
6
|
"bin": {
|
|
7
|
-
"coaia": "
|
|
8
|
-
"coaiajs-mcp": "
|
|
7
|
+
"coaia": "dist/src/cli.js",
|
|
8
|
+
"coaiajs-mcp": "dist/mcp/server.js"
|
|
9
9
|
},
|
|
10
10
|
"engines": {
|
|
11
11
|
"node": ">=20.0.0"
|
package/src/cli.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { readConfig, getConfig } from './config.js';
|
|
|
9
9
|
import { llm as llmCall, transcribeAudio, abstractProcess } from './llm.js';
|
|
10
10
|
import { listIssues, getIssue } from './github.js';
|
|
11
11
|
import { createEnvironment, findEnvironment } from './environment.js';
|
|
12
|
+
import { getPackageVersion } from './version.js';
|
|
12
13
|
import {
|
|
13
14
|
formatTable, formatJson, formatError, formatSuccess,
|
|
14
15
|
truncate, formatDate, formatProgress, setColorEnabled,
|
|
@@ -1221,7 +1222,7 @@ async function main(): Promise<void> {
|
|
|
1221
1222
|
|
|
1222
1223
|
program
|
|
1223
1224
|
.name('coaia')
|
|
1224
|
-
.version(
|
|
1225
|
+
.version(getPackageVersion(), '-V, --version')
|
|
1225
1226
|
.description('CoAIA unified CLI — structural tension, narrative, and DevOps tooling')
|
|
1226
1227
|
.option('--env <path>', 'Load environment file')
|
|
1227
1228
|
.option('-M, --memory-path <path>', 'JSONL memory file path')
|
package/src/langfuse/index.ts
CHANGED
|
@@ -3,10 +3,14 @@
|
|
|
3
3
|
export { LangfuseClient, LangfuseApiError, getClient, resetClient, nowISO } from './client.js';
|
|
4
4
|
export type { IngestionEvent, LangfuseClientConfig } from './client.js';
|
|
5
5
|
|
|
6
|
-
export {
|
|
6
|
+
export {
|
|
7
|
+
addTrace, createTrace, patchTraceOutput,
|
|
8
|
+
listTraces, getTrace, traceView, sessionView,
|
|
9
|
+
formatTracesTable, formatTracesMarkdown, formatTraceTree,
|
|
10
|
+
} from './traces.js';
|
|
7
11
|
export type { TraceFilters } from './traces.js';
|
|
8
12
|
|
|
9
|
-
export { addObservation, getObservation, formatObservationDisplay } from './observations.js';
|
|
13
|
+
export { addObservation, addObservations, getObservation, formatObservationDisplay } from './observations.js';
|
|
10
14
|
|
|
11
15
|
export { listPrompts, getPrompt, createPrompt, formatPromptsTable, formatPromptDisplay } from './prompts.js';
|
|
12
16
|
|
|
@@ -11,9 +11,12 @@ export async function addObservation(params: {
|
|
|
11
11
|
type?: string;
|
|
12
12
|
name: string;
|
|
13
13
|
parentId?: string;
|
|
14
|
+
parentObservationId?: string;
|
|
15
|
+
input?: string;
|
|
14
16
|
inputData?: unknown;
|
|
17
|
+
output?: string;
|
|
15
18
|
outputData?: unknown;
|
|
16
|
-
metadata?: unknown;
|
|
19
|
+
metadata?: string | unknown;
|
|
17
20
|
startTime?: string;
|
|
18
21
|
endTime?: string;
|
|
19
22
|
level?: string;
|
|
@@ -33,10 +36,10 @@ export async function addObservation(params: {
|
|
|
33
36
|
};
|
|
34
37
|
|
|
35
38
|
if (params.name) body.name = params.name;
|
|
36
|
-
if (params.inputData) body.input = params.inputData;
|
|
37
|
-
if (params.outputData) body.output = params.outputData;
|
|
38
|
-
if (params.metadata) body.metadata = params.metadata;
|
|
39
|
-
if (params.parentId) body.parentObservationId = params.parentId;
|
|
39
|
+
if (params.inputData ?? params.input) body.input = parseJsonOption(params.inputData ?? params.input);
|
|
40
|
+
if (params.outputData ?? params.output) body.output = parseJsonOption(params.outputData ?? params.output);
|
|
41
|
+
if (params.metadata) body.metadata = parseJsonOption(params.metadata);
|
|
42
|
+
if (params.parentId ?? params.parentObservationId) body.parentObservationId = params.parentId ?? params.parentObservationId;
|
|
40
43
|
if (params.endTime) body.endTime = params.endTime;
|
|
41
44
|
if (params.model) body.model = params.model;
|
|
42
45
|
if (params.usage) body.usage = params.usage;
|
|
@@ -65,6 +68,27 @@ export async function getObservation(observationId: string): Promise<string> {
|
|
|
65
68
|
return JSON.stringify(result, null, 2);
|
|
66
69
|
}
|
|
67
70
|
|
|
71
|
+
function parseJsonOption(value: unknown): unknown {
|
|
72
|
+
if (typeof value !== 'string') return value;
|
|
73
|
+
try {
|
|
74
|
+
return JSON.parse(value) as unknown;
|
|
75
|
+
} catch {
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export async function addObservations(params: { traceId?: string; observations?: Array<Record<string, unknown>> }): Promise<string> {
|
|
81
|
+
const observations = params.observations ?? [];
|
|
82
|
+
const results: unknown[] = [];
|
|
83
|
+
for (const observation of observations) {
|
|
84
|
+
const traceId = String(observation.traceId ?? params.traceId ?? '');
|
|
85
|
+
const name = String(observation.name ?? 'Observation');
|
|
86
|
+
if (!traceId) throw new Error('traceId is required for every observation');
|
|
87
|
+
results.push(JSON.parse(await addObservation({ ...observation, traceId, name })) as unknown);
|
|
88
|
+
}
|
|
89
|
+
return JSON.stringify({ success: true, count: results.length, observations: results }, null, 2);
|
|
90
|
+
}
|
|
91
|
+
|
|
68
92
|
// ─── Formatters ─────────────────────────────────────────────────────
|
|
69
93
|
|
|
70
94
|
const TYPE_GLYPHS: Record<string, string> = {
|
package/src/langfuse/traces.ts
CHANGED
|
@@ -61,14 +61,23 @@ export async function addTrace(params: {
|
|
|
61
61
|
}, null, 2);
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
export async function patchTraceOutput(
|
|
64
|
+
export async function patchTraceOutput(
|
|
65
|
+
traceIdOrParams: string | { traceId?: string; output?: string; outputData?: unknown },
|
|
66
|
+
outputData?: unknown,
|
|
67
|
+
): Promise<string> {
|
|
68
|
+
const traceId = typeof traceIdOrParams === 'string' ? traceIdOrParams : traceIdOrParams.traceId;
|
|
69
|
+
if (!traceId) throw new Error('traceId is required');
|
|
70
|
+
const output = typeof traceIdOrParams === 'string'
|
|
71
|
+
? outputData
|
|
72
|
+
: parseJsonOption(traceIdOrParams.outputData ?? traceIdOrParams.output);
|
|
73
|
+
|
|
65
74
|
const client = getClient();
|
|
66
75
|
const now = nowISO();
|
|
67
76
|
|
|
68
77
|
const body: Record<string, unknown> = {
|
|
69
78
|
id: traceId,
|
|
70
79
|
timestamp: now,
|
|
71
|
-
output
|
|
80
|
+
output,
|
|
72
81
|
};
|
|
73
82
|
|
|
74
83
|
const eventId = `${traceId}-patch-${uuidv4().slice(0, 8)}`;
|
|
@@ -88,6 +97,38 @@ export async function patchTraceOutput(traceId: string, outputData: unknown): Pr
|
|
|
88
97
|
}, null, 2);
|
|
89
98
|
}
|
|
90
99
|
|
|
100
|
+
function parseJsonOption(value: unknown): unknown {
|
|
101
|
+
if (typeof value !== 'string') return value;
|
|
102
|
+
try {
|
|
103
|
+
return JSON.parse(value) as unknown;
|
|
104
|
+
} catch {
|
|
105
|
+
return value;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export async function createTrace(params: {
|
|
110
|
+
traceId?: string;
|
|
111
|
+
id?: string;
|
|
112
|
+
userId?: string;
|
|
113
|
+
sessionId?: string;
|
|
114
|
+
name?: string;
|
|
115
|
+
input?: string;
|
|
116
|
+
inputData?: unknown;
|
|
117
|
+
output?: string;
|
|
118
|
+
outputData?: unknown;
|
|
119
|
+
metadata?: string | unknown;
|
|
120
|
+
}): Promise<string> {
|
|
121
|
+
return addTrace({
|
|
122
|
+
traceId: params.traceId ?? params.id,
|
|
123
|
+
userId: params.userId,
|
|
124
|
+
sessionId: params.sessionId,
|
|
125
|
+
name: params.name,
|
|
126
|
+
inputData: parseJsonOption(params.inputData ?? params.input),
|
|
127
|
+
outputData: parseJsonOption(params.outputData ?? params.output),
|
|
128
|
+
metadata: parseJsonOption(params.metadata),
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
91
132
|
export async function listTraces(filters: TraceFilters): Promise<string> {
|
|
92
133
|
const client = getClient();
|
|
93
134
|
const params = new URLSearchParams();
|
|
@@ -141,6 +182,16 @@ export async function getTrace(traceId: string): Promise<string> {
|
|
|
141
182
|
return JSON.stringify(trace, null, 2);
|
|
142
183
|
}
|
|
143
184
|
|
|
185
|
+
export async function traceView(traceId: string): Promise<string> {
|
|
186
|
+
const raw = await getTrace(traceId);
|
|
187
|
+
return formatTraceTree(raw);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export async function sessionView(sessionId: string): Promise<string> {
|
|
191
|
+
const raw = await listTraces({ sessionId, limit: 20, orderBy: 'timestamp.desc' });
|
|
192
|
+
return formatTracesMarkdown(raw);
|
|
193
|
+
}
|
|
194
|
+
|
|
144
195
|
// ─── Formatters ─────────────────────────────────────────────────────
|
|
145
196
|
|
|
146
197
|
export function formatTracesTable(json: unknown): string {
|
package/src/version.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// coaiajs/src/version.ts — single source of truth for the runtime version.
|
|
2
|
+
// Reads package.json at runtime so the CLI banner, the MCP handshake, and the
|
|
3
|
+
// published package can never drift apart again.
|
|
4
|
+
|
|
5
|
+
import { readFileSync } from 'node:fs';
|
|
6
|
+
import { dirname, join } from 'node:path';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
|
|
9
|
+
const PACKAGE_NAME = 'coaiajs';
|
|
10
|
+
|
|
11
|
+
let cached: string | undefined;
|
|
12
|
+
|
|
13
|
+
/** Resolved version of the installed `coaiajs` package. */
|
|
14
|
+
export function getPackageVersion(): string {
|
|
15
|
+
if (cached) return cached;
|
|
16
|
+
|
|
17
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
18
|
+
// dist/src/version.js -> package root is two levels up.
|
|
19
|
+
// src/version.ts (ts-node/tsx) -> package root is one level up.
|
|
20
|
+
const candidates = [join(here, '..', '..', 'package.json'), join(here, '..', 'package.json')];
|
|
21
|
+
|
|
22
|
+
for (const candidate of candidates) {
|
|
23
|
+
let raw: string;
|
|
24
|
+
try {
|
|
25
|
+
raw = readFileSync(candidate, 'utf8');
|
|
26
|
+
} catch {
|
|
27
|
+
continue; // not at this depth; try the next candidate
|
|
28
|
+
}
|
|
29
|
+
const pkg = JSON.parse(raw) as { name?: string; version?: string };
|
|
30
|
+
if (pkg.name === PACKAGE_NAME && pkg.version) {
|
|
31
|
+
cached = pkg.version;
|
|
32
|
+
return cached;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
throw new Error(
|
|
37
|
+
`Unable to resolve ${PACKAGE_NAME} version: no package.json found near ${here}`,
|
|
38
|
+
);
|
|
39
|
+
}
|