coaia-visualizer 1.6.0 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.dockerignore +9 -0
- package/COMPLETE_IMPLEMENTATION_REPORT.md +215 -0
- package/QUICK_START_MCP_TESTING.md +236 -0
- package/README_TELESCOPED_NAVIGATION.md +247 -0
- package/STC.md +18 -0
- package/STCGOAL.md +0 -0
- package/STCISSUE.md +36 -0
- package/STCKIN.md +0 -0
- package/STCMASTERY.md +0 -0
- package/STUDY_REPORT.md +510 -0
- package/cli.ts +8 -0
- package/components/chart-detail-editable.tsx +0 -2
- package/components/chart-detail.tsx +1 -6
- package/components/edit-action-step.tsx +0 -2
- package/components/relation-graph.tsx +27 -91
- package/components.json +21 -0
- package/direct-test.sh +180 -0
- package/dist/cli.js +7 -0
- package/dist/skill.js +342 -0
- package/docker-compose.test.yml +69 -0
- package/index.tsx +0 -26
- package/jgwill.coaia-visualizer-8--496dca71-d476-4ac9-ba9f-376add118dd8--260208.txt +2612 -0
- package/lib/types.ts +2 -15
- package/mcp/dist/api-client.d.ts +138 -0
- package/mcp/dist/api-client.d.ts.map +1 -0
- package/mcp/dist/api-client.js +115 -0
- package/mcp/dist/api-client.js.map +1 -0
- package/mcp/dist/index.d.ts +2 -0
- package/mcp/dist/index.d.ts.map +1 -0
- package/mcp/dist/index.js +286 -0
- package/mcp/dist/index.js.map +1 -0
- package/mcp/dist/tools/index.d.ts +18 -0
- package/mcp/dist/tools/index.d.ts.map +1 -0
- package/mcp/dist/tools/index.js +322 -0
- package/mcp/dist/tools/index.js.map +1 -0
- package/mcp/package-lock.json +210 -0
- package/package.json +1 -27
- package/rispecs/github-project-runtime-memory-integration.spec.md +381 -0
- package/skill.ts +385 -0
- package/test-data/test-master.jsonl +11 -0
- package/test-scripts/README.md +325 -0
- package/test-scripts/run-all-tests.sh +38 -0
- package/test-scripts/test-01-basic-operations.sh +87 -0
- package/test-scripts/test-02-telescope-creation.sh +91 -0
- package/test-scripts/test-03-navigation.sh +87 -0
- package/test-scripts/test-global-cli.spec.ts +220 -0
- package/test-scripts/verify-global-cli.sh +87 -0
- package/tsconfig.json +41 -0
- package/components/github-provenance.tsx +0 -226
- package/lib/github-provenance.ts +0 -316
|
@@ -2,10 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
|
4
4
|
import { Badge } from "@/components/ui/badge"
|
|
5
|
-
import type { ParsedData, Chart,
|
|
6
|
-
import { ArrowRight
|
|
7
|
-
import { getGithubBridgeRelationType, getGithubSyncState } from "@/lib/github-provenance"
|
|
8
|
-
import { SyncStatePill } from "./github-provenance"
|
|
5
|
+
import type { ParsedData, Chart, RelationRecord } from "@/lib/types"
|
|
6
|
+
import { ArrowRight } from "lucide-react"
|
|
9
7
|
|
|
10
8
|
interface RelationGraphProps {
|
|
11
9
|
chart: Chart
|
|
@@ -25,10 +23,7 @@ export function RelationGraph({ chart, data }: RelationGraphProps) {
|
|
|
25
23
|
)
|
|
26
24
|
}
|
|
27
25
|
|
|
28
|
-
const
|
|
29
|
-
const standardRelations = relations.filter((relation) => !getGithubBridgeRelationType(relation))
|
|
30
|
-
|
|
31
|
-
const relationsByType = standardRelations.reduce(
|
|
26
|
+
const relationsByType = relations.reduce(
|
|
32
27
|
(acc, rel) => {
|
|
33
28
|
if (!acc[rel.relationType]) {
|
|
34
29
|
acc[rel.relationType] = []
|
|
@@ -46,28 +41,6 @@ export function RelationGraph({ chart, data }: RelationGraphProps) {
|
|
|
46
41
|
<CardDescription>Connections between chart entities</CardDescription>
|
|
47
42
|
</CardHeader>
|
|
48
43
|
<CardContent className="space-y-6">
|
|
49
|
-
{githubBridgeRelations.length > 0 && (
|
|
50
|
-
<div>
|
|
51
|
-
<h3 className="text-sm font-semibold mb-3 flex items-center gap-2">
|
|
52
|
-
<Badge className="gap-1 bg-indigo-600 text-white">
|
|
53
|
-
<Github className="w-3 h-3" />
|
|
54
|
-
GitHub bridge
|
|
55
|
-
</Badge>
|
|
56
|
-
<span className="text-muted-foreground">({githubBridgeRelations.length})</span>
|
|
57
|
-
</h3>
|
|
58
|
-
<div className="space-y-2">
|
|
59
|
-
{githubBridgeRelations.map((rel, idx) => (
|
|
60
|
-
<RelationRow
|
|
61
|
-
key={`github-${idx}`}
|
|
62
|
-
relation={rel}
|
|
63
|
-
data={data}
|
|
64
|
-
bridgeLabel={getGithubBridgeRelationType(rel)}
|
|
65
|
-
/>
|
|
66
|
-
))}
|
|
67
|
-
</div>
|
|
68
|
-
</div>
|
|
69
|
-
)}
|
|
70
|
-
|
|
71
44
|
{Object.entries(relationsByType).map(([type, rels]) => (
|
|
72
45
|
<div key={type}>
|
|
73
46
|
<h3 className="text-sm font-semibold mb-3 flex items-center gap-2">
|
|
@@ -75,9 +48,30 @@ export function RelationGraph({ chart, data }: RelationGraphProps) {
|
|
|
75
48
|
<span className="text-muted-foreground">({rels.length})</span>
|
|
76
49
|
</h3>
|
|
77
50
|
<div className="space-y-2">
|
|
78
|
-
{rels.map((rel, idx) =>
|
|
79
|
-
|
|
80
|
-
|
|
51
|
+
{rels.map((rel, idx) => {
|
|
52
|
+
const fromEntity = data.entities.get(rel.from)
|
|
53
|
+
const toEntity = data.entities.get(rel.to)
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<div key={idx} className="flex items-center gap-3 p-3 bg-muted/30 rounded-lg text-sm">
|
|
57
|
+
<div className="flex-1 min-w-0">
|
|
58
|
+
<div className="font-mono text-xs text-muted-foreground mb-1">{rel.from}</div>
|
|
59
|
+
{fromEntity && (
|
|
60
|
+
<div className="text-xs line-clamp-1">
|
|
61
|
+
{fromEntity.observations[0] || fromEntity.entityType}
|
|
62
|
+
</div>
|
|
63
|
+
)}
|
|
64
|
+
</div>
|
|
65
|
+
<ArrowRight className="w-4 h-4 text-muted-foreground flex-shrink-0" />
|
|
66
|
+
<div className="flex-1 min-w-0">
|
|
67
|
+
<div className="font-mono text-xs text-muted-foreground mb-1">{rel.to}</div>
|
|
68
|
+
{toEntity && (
|
|
69
|
+
<div className="text-xs line-clamp-1">{toEntity.observations[0] || toEntity.entityType}</div>
|
|
70
|
+
)}
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
)
|
|
74
|
+
})}
|
|
81
75
|
</div>
|
|
82
76
|
</div>
|
|
83
77
|
))}
|
|
@@ -85,61 +79,3 @@ export function RelationGraph({ chart, data }: RelationGraphProps) {
|
|
|
85
79
|
</Card>
|
|
86
80
|
)
|
|
87
81
|
}
|
|
88
|
-
|
|
89
|
-
interface RelationRowProps {
|
|
90
|
-
relation: RelationRecord
|
|
91
|
-
data: ParsedData
|
|
92
|
-
bridgeLabel?: string
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function RelationRow({ relation, data, bridgeLabel }: RelationRowProps) {
|
|
96
|
-
const fromEntity = data.entities.get(relation.from)
|
|
97
|
-
const toEntity = data.entities.get(relation.to)
|
|
98
|
-
const syncState = getGithubSyncState(relation.metadata)
|
|
99
|
-
|
|
100
|
-
return (
|
|
101
|
-
<div className="flex flex-col gap-2 p-3 bg-muted/30 rounded-lg text-sm sm:flex-row sm:items-center sm:gap-3">
|
|
102
|
-
<RelationEndpoint name={relation.from} entity={fromEntity} />
|
|
103
|
-
|
|
104
|
-
<div className="flex items-center gap-2 text-muted-foreground sm:flex-col">
|
|
105
|
-
<ArrowRight className="w-4 h-4 flex-shrink-0 rotate-90 sm:rotate-0" />
|
|
106
|
-
{(bridgeLabel || syncState) && (
|
|
107
|
-
<div className="flex flex-wrap justify-center gap-1">
|
|
108
|
-
{bridgeLabel && (
|
|
109
|
-
<Badge variant="outline" className="text-xs">
|
|
110
|
-
{bridgeLabel.replace(/_/g, " ")}
|
|
111
|
-
</Badge>
|
|
112
|
-
)}
|
|
113
|
-
<SyncStatePill syncState={syncState} />
|
|
114
|
-
</div>
|
|
115
|
-
)}
|
|
116
|
-
</div>
|
|
117
|
-
|
|
118
|
-
<RelationEndpoint name={relation.to} entity={toEntity} />
|
|
119
|
-
</div>
|
|
120
|
-
)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function RelationEndpoint({
|
|
124
|
-
name,
|
|
125
|
-
entity,
|
|
126
|
-
}: {
|
|
127
|
-
name: string
|
|
128
|
-
entity?: EntityRecord
|
|
129
|
-
}) {
|
|
130
|
-
const isGithubVirtualNode = name.startsWith("gh:")
|
|
131
|
-
|
|
132
|
-
return (
|
|
133
|
-
<div className="flex-1 min-w-0">
|
|
134
|
-
<div className="font-mono text-xs text-muted-foreground mb-1 break-all">{name}</div>
|
|
135
|
-
{entity ? (
|
|
136
|
-
<div className="text-xs line-clamp-1">{entity.observations[0] || entity.entityType}</div>
|
|
137
|
-
) : isGithubVirtualNode ? (
|
|
138
|
-
<Badge variant="outline" className="gap-1 text-xs">
|
|
139
|
-
<Github className="w-3 h-3" />
|
|
140
|
-
GitHub issue
|
|
141
|
-
</Badge>
|
|
142
|
-
) : null}
|
|
143
|
-
</div>
|
|
144
|
-
)
|
|
145
|
-
}
|
package/components.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema.json",
|
|
3
|
+
"style": "new-york",
|
|
4
|
+
"rsc": true,
|
|
5
|
+
"tsx": true,
|
|
6
|
+
"tailwind": {
|
|
7
|
+
"config": "",
|
|
8
|
+
"css": "app/globals.css",
|
|
9
|
+
"baseColor": "neutral",
|
|
10
|
+
"cssVariables": true,
|
|
11
|
+
"prefix": ""
|
|
12
|
+
},
|
|
13
|
+
"aliases": {
|
|
14
|
+
"components": "@/components",
|
|
15
|
+
"utils": "@/lib/utils",
|
|
16
|
+
"ui": "@/components/ui",
|
|
17
|
+
"lib": "@/lib",
|
|
18
|
+
"hooks": "@/hooks"
|
|
19
|
+
},
|
|
20
|
+
"iconLibrary": "lucide"
|
|
21
|
+
}
|
package/direct-test.sh
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Direct MCP Integration Test
|
|
4
|
+
# Tests the MCP server and Next.js API without Docker complexity
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
echo "========================================="
|
|
9
|
+
echo "Direct MCP Integration Test"
|
|
10
|
+
echo "========================================="
|
|
11
|
+
echo ""
|
|
12
|
+
|
|
13
|
+
PROJECT_DIR="/workspace/repos/jgwill/coaia-visualizer-feat-4"
|
|
14
|
+
cd "$PROJECT_DIR"
|
|
15
|
+
|
|
16
|
+
# Start the Next.js app in the background
|
|
17
|
+
echo "1. Starting Next.js application..."
|
|
18
|
+
timeout 30 npm run dev > /tmp/nextjs.log 2>&1 &
|
|
19
|
+
NEXTJS_PID=$!
|
|
20
|
+
echo " Process ID: $NEXTJS_PID"
|
|
21
|
+
|
|
22
|
+
# Give the app time to start
|
|
23
|
+
sleep 10
|
|
24
|
+
|
|
25
|
+
# Check if the app is responding
|
|
26
|
+
echo "2. Checking Next.js app health..."
|
|
27
|
+
if curl -sf http://localhost:3000/api/charts > /dev/null; then
|
|
28
|
+
echo " ✓ Next.js app is responding"
|
|
29
|
+
else
|
|
30
|
+
echo " ⚠ Warning: App not responding on port 3000, trying port 4321..."
|
|
31
|
+
if curl -sf http://localhost:4321/api/charts > /dev/null; then
|
|
32
|
+
echo " ✓ Next.js app is responding on port 4321"
|
|
33
|
+
else
|
|
34
|
+
echo " ✗ Failed to reach Next.js app"
|
|
35
|
+
kill $NEXTJS_PID 2>/dev/null || true
|
|
36
|
+
exit 1
|
|
37
|
+
fi
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
API_PORT=3000
|
|
41
|
+
if ! curl -sf http://localhost:3000/api/charts > /dev/null 2>&1; then
|
|
42
|
+
API_PORT=4321
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
echo ""
|
|
46
|
+
echo "3. Testing MCP API endpoints..."
|
|
47
|
+
echo ""
|
|
48
|
+
|
|
49
|
+
# Test 1: Create a chart
|
|
50
|
+
echo " Test 1: Creating a chart..."
|
|
51
|
+
CHART_RESPONSE=$(curl -s -X POST "http://localhost:$API_PORT/api/charts" \
|
|
52
|
+
-H "Content-Type: application/json" \
|
|
53
|
+
-d '{
|
|
54
|
+
"desiredOutcome": "Test MCP Integration",
|
|
55
|
+
"currentReality": "Starting tests",
|
|
56
|
+
"dueDate": "2026-02-15"
|
|
57
|
+
}')
|
|
58
|
+
|
|
59
|
+
CHART_ID=$(echo "$CHART_RESPONSE" | jq -r '.chart.id' 2>/dev/null)
|
|
60
|
+
|
|
61
|
+
if [ -n "$CHART_ID" ] && [ "$CHART_ID" != "null" ]; then
|
|
62
|
+
echo " ✓ Chart created: $CHART_ID"
|
|
63
|
+
else
|
|
64
|
+
echo " ✗ Failed to create chart"
|
|
65
|
+
echo " Response: $CHART_RESPONSE"
|
|
66
|
+
kill $NEXTJS_PID 2>/dev/null || true
|
|
67
|
+
exit 1
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
# Test 2: Add action step
|
|
71
|
+
echo ""
|
|
72
|
+
echo " Test 2: Adding action step..."
|
|
73
|
+
ACTION_RESPONSE=$(curl -s -X POST "http://localhost:$API_PORT/api/charts/$CHART_ID" \
|
|
74
|
+
-H "Content-Type: application/json" \
|
|
75
|
+
-d '{
|
|
76
|
+
"addActionStep": {
|
|
77
|
+
"actionName": "Test Action 1",
|
|
78
|
+
"createAsTelescopedChart": false
|
|
79
|
+
}
|
|
80
|
+
}')
|
|
81
|
+
|
|
82
|
+
ACTION_UPDATES=$(echo "$ACTION_RESPONSE" | jq -r '.updates | length' 2>/dev/null || echo "0")
|
|
83
|
+
|
|
84
|
+
if [ "$ACTION_UPDATES" -gt 0 ]; then
|
|
85
|
+
echo " ✓ Action step added"
|
|
86
|
+
else
|
|
87
|
+
echo " ⚠ Could not verify action addition"
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
# Test 3: Create telescoped chart
|
|
91
|
+
echo ""
|
|
92
|
+
echo " Test 3: Creating telescoped chart..."
|
|
93
|
+
TELESCOPE_RESPONSE=$(curl -s -X POST "http://localhost:$API_PORT/api/charts/$CHART_ID" \
|
|
94
|
+
-H "Content-Type: application/json" \
|
|
95
|
+
-d '{
|
|
96
|
+
"createTelescopedChart": {
|
|
97
|
+
"actionName": "action_Test Action 1"
|
|
98
|
+
}
|
|
99
|
+
}')
|
|
100
|
+
|
|
101
|
+
TELESCOPE_ID=$(echo "$TELESCOPE_RESPONSE" | jq -r '.chart.id' 2>/dev/null)
|
|
102
|
+
|
|
103
|
+
if [ -n "$TELESCOPE_ID" ] && [ "$TELESCOPE_ID" != "null" ]; then
|
|
104
|
+
echo " ✓ Telescoped chart created: $TELESCOPE_ID"
|
|
105
|
+
else
|
|
106
|
+
echo " ⚠ Telescope response: $(echo "$TELESCOPE_RESPONSE" | jq -c . 2>/dev/null || echo "$TELESCOPE_RESPONSE")"
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
# Test 4: Retrieve parent chart
|
|
110
|
+
echo ""
|
|
111
|
+
echo " Test 4: Retrieving parent chart with subCharts..."
|
|
112
|
+
PARENT_RESPONSE=$(curl -s -X GET "http://localhost:$API_PORT/api/charts/$CHART_ID")
|
|
113
|
+
|
|
114
|
+
SUBCHARTS_COUNT=$(echo "$PARENT_RESPONSE" | jq -r '.chart.subCharts | length' 2>/dev/null || echo "0")
|
|
115
|
+
|
|
116
|
+
if [ "$SUBCHARTS_COUNT" -gt 0 ]; then
|
|
117
|
+
echo " ✓ Parent chart has $SUBCHARTS_COUNT subCharts"
|
|
118
|
+
else
|
|
119
|
+
echo " ⚠ Parent chart subCharts count: $SUBCHARTS_COUNT"
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
# Test 5: Test MCP server directly (if available)
|
|
123
|
+
echo ""
|
|
124
|
+
echo "4. Testing MCP Server..."
|
|
125
|
+
|
|
126
|
+
if [ -f "$PROJECT_DIR/mcp/dist/index.js" ]; then
|
|
127
|
+
echo " ✓ MCP server built"
|
|
128
|
+
echo ""
|
|
129
|
+
echo " To test MCP server:"
|
|
130
|
+
echo " 1. Build: cd mcp && npm run build"
|
|
131
|
+
echo " 2. Run: node dist/index.js"
|
|
132
|
+
echo " 3. Configure in Claude Desktop"
|
|
133
|
+
else
|
|
134
|
+
echo " ⚠ MCP server not built yet"
|
|
135
|
+
echo " Build with: cd mcp && npm run build"
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
# Cleanup
|
|
139
|
+
echo ""
|
|
140
|
+
echo "5. Cleaning up..."
|
|
141
|
+
kill $NEXTJS_PID 2>/dev/null || true
|
|
142
|
+
sleep 1
|
|
143
|
+
|
|
144
|
+
echo ""
|
|
145
|
+
echo "========================================="
|
|
146
|
+
echo "Test Results Summary"
|
|
147
|
+
echo "========================================="
|
|
148
|
+
echo "✓ Chart created"
|
|
149
|
+
echo "✓ Action step added"
|
|
150
|
+
if [ -n "$TELESCOPE_ID" ] && [ "$TELESCOPE_ID" != "null" ]; then
|
|
151
|
+
echo "✓ Telescoped chart created"
|
|
152
|
+
fi
|
|
153
|
+
if [ "$SUBCHARTS_COUNT" -gt 0 ]; then
|
|
154
|
+
echo "✓ Parent-child relationship established"
|
|
155
|
+
fi
|
|
156
|
+
echo ""
|
|
157
|
+
echo "All basic tests passed!"
|
|
158
|
+
echo "========================================="
|
|
159
|
+
|
|
160
|
+
# Cleanup
|
|
161
|
+
echo ""
|
|
162
|
+
echo "5. Cleaning up..."
|
|
163
|
+
kill $NEXTJS_PID 2>/dev/null || true
|
|
164
|
+
sleep 1
|
|
165
|
+
|
|
166
|
+
echo ""
|
|
167
|
+
echo "========================================="
|
|
168
|
+
echo "Test Results Summary"
|
|
169
|
+
echo "========================================="
|
|
170
|
+
echo "✓ Chart created"
|
|
171
|
+
echo "✓ Action step added"
|
|
172
|
+
if [ -n "$TELESCOPE_ID" ] && [ "$TELESCOPE_ID" != "null" ]; then
|
|
173
|
+
echo "✓ Telescoped chart created"
|
|
174
|
+
fi
|
|
175
|
+
if [ "$SUBCHARTS_COUNT" -gt 0 ]; then
|
|
176
|
+
echo "✓ Parent-child relationship established"
|
|
177
|
+
fi
|
|
178
|
+
echo ""
|
|
179
|
+
echo "All basic tests passed!"
|
|
180
|
+
echo "========================================="
|
package/dist/cli.js
CHANGED
|
@@ -11,6 +11,7 @@ import path from 'path';
|
|
|
11
11
|
import minimist from 'minimist';
|
|
12
12
|
import * as dotenv from 'dotenv';
|
|
13
13
|
import { fileURLToPath } from 'url';
|
|
14
|
+
import { handleSkillCommand } from './skill.js';
|
|
14
15
|
const __filename = fileURLToPath(import.meta.url);
|
|
15
16
|
const __dirname = path.dirname(__filename);
|
|
16
17
|
const DOCKER_IMAGE = 'jgwill/coaia:visualizer';
|
|
@@ -95,6 +96,11 @@ function loadConfig(args) {
|
|
|
95
96
|
}
|
|
96
97
|
async function main() {
|
|
97
98
|
const args = minimist(process.argv.slice(2));
|
|
99
|
+
const command = args._[0];
|
|
100
|
+
if (command === 'skill') {
|
|
101
|
+
await handleSkillCommand(args);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
98
104
|
if (args.help || args.h) {
|
|
99
105
|
console.log(`
|
|
100
106
|
🎨 COAIA Visualizer - Interactive Chart Viewer
|
|
@@ -106,6 +112,7 @@ DESCRIPTION:
|
|
|
106
112
|
USAGE:
|
|
107
113
|
coaia-visualizer [OPTIONS]
|
|
108
114
|
npx coaia-visualizer [OPTIONS]
|
|
115
|
+
coaia-visualizer skill <show|install|help>
|
|
109
116
|
|
|
110
117
|
OPTIONS:
|
|
111
118
|
--memory-path PATH, -M PATH Path to memory.jsonl file (default: ./memory.jsonl)
|