Skip to content

Commit b3d84bc

Browse files
Merge pull request #1 from rustic-ai/002-setup-a-documentation
setup documentation
2 parents 0bc000c + 2e98dcd commit b3d84bc

65 files changed

Lines changed: 16277 additions & 431 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/docs-deploy.yml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
name: Deploy Documentation
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths: ['docs/**', '.github/workflows/docs-deploy.yml']
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
pages: write
12+
id-token: write
13+
14+
concurrency:
15+
group: pages
16+
cancel-in-progress: false
17+
18+
jobs:
19+
build:
20+
runs-on: ubuntu-latest
21+
steps:
22+
- name: Checkout
23+
uses: actions/checkout@v4
24+
25+
- name: Setup Node.js
26+
uses: actions/setup-node@v4
27+
with:
28+
node-version: '18'
29+
cache: 'pnpm'
30+
31+
- name: Install pnpm
32+
uses: pnpm/action-setup@v2
33+
with:
34+
version: 8
35+
36+
- name: Install dependencies
37+
run: pnpm install --frozen-lockfile
38+
39+
- name: Build documentation
40+
run: |
41+
cd docs
42+
pnpm build
43+
44+
- name: Setup Pages
45+
uses: actions/configure-pages@v4
46+
47+
- name: Upload artifact
48+
uses: actions/upload-pages-artifact@v2
49+
with:
50+
path: './docs/dist'
51+
52+
deploy:
53+
environment:
54+
name: github-pages
55+
url: ${{ steps.deployment.outputs.page_url }}
56+
runs-on: ubuntu-latest
57+
needs: build
58+
steps:
59+
- name: Deploy to GitHub Pages
60+
id: deployment
61+
uses: actions/deploy-pages@v3

README.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,46 @@ A comprehensive web-based debugging tool for RusticAI's Redis messaging system.
1313
- **Thread View**: Track message threads and conversations
1414
- **Developer Presence**: See which developers are currently monitoring
1515

16+
## Screenshots
17+
18+
<div align="center">
19+
20+
### Dashboard - Guild Overview
21+
![Dashboard View](docs/src/assets/screenshots/dashboard-guilds.png)
22+
*Monitor all active guilds with real-time metrics and message rates*
23+
24+
### Debug Views
25+
26+
<table>
27+
<tr>
28+
<td width="50%">
29+
30+
#### List View
31+
![List View](docs/src/assets/screenshots/debug-list-view.png)
32+
*Chronological message list with filtering*
33+
34+
</td>
35+
<td width="50%">
36+
37+
#### Thread View
38+
![Thread View](docs/src/assets/screenshots/debug-thread-view.png)
39+
*Messages grouped by conversation threads*
40+
41+
</td>
42+
</tr>
43+
<tr>
44+
<td colspan="2">
45+
46+
#### Graph View
47+
![Graph View](docs/src/assets/screenshots/debug-graph-view.png)
48+
*Interactive visualization of message flows between agents*
49+
50+
</td>
51+
</tr>
52+
</table>
53+
54+
</div>
55+
1656
## Architecture
1757

1858
This is a monorepo project using PNPM workspaces:

backend/src/api/routes/messages.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { FastifyPluginAsync } from 'fastify';
2-
import type { ApiResponse, PaginatedResponse, Message, MessageStatus } from '@rustic-debug/types';
2+
import type { ApiResponse, PaginatedResponse, Message, ProcessStatus } from '@rustic-debug/types';
33
import { MessageHistoryService } from '../../services/messageHistory/index.js';
44
import { GuildDiscoveryService } from '../../services/guildDiscovery.js';
55
import { validateMessageId } from '../../utils/gemstoneId.js';
@@ -86,7 +86,7 @@ export const topicMessageRoutes: FastifyPluginAsync = async (fastify) => {
8686
}
8787

8888
// Parse status array
89-
const statusArray = status ? status.split(',') as MessageStatus[] : undefined;
89+
const statusArray = status ? status.split(',') as ProcessStatus[] : undefined;
9090

9191
try {
9292
const result = await messageService.getTopicMessages(guildId, topicName, {

backend/src/models/message.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,12 @@ export class MessageModel {
6464
const min = timeRange?.start?.getTime() || '-inf';
6565
const max = timeRange?.end?.getTime() || '+inf';
6666

67+
// Build the full topic key (guildId:topicName in RusticAI)
68+
const topicKey = guildId ? `${guildId}:${topicName}` : topicName;
69+
6770
// The sorted set contains full JSON messages
6871
const rawMessages = await redis.zrangebyscore(
69-
topicName,
72+
topicKey,
7073
min,
7174
max
7275
);

backend/src/services/export.ts

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -71,25 +71,34 @@ export class ExportService {
7171
): Promise<Buffer> {
7272
const exportData = messages.map(message => {
7373
const base: any = {
74-
id: message.id.id,
75-
guildId: message.guildId,
76-
topicName: message.topicName,
77-
timestamp: message.metadata.timestamp.toISOString(),
78-
status: message.status.current,
74+
id: message.id,
75+
timestamp: new Date(message.timestamp).toISOString(),
76+
format: message.format,
77+
topics: message.topics,
78+
sender: message.sender,
7979
payload: message.payload,
80+
is_error_message: message.is_error_message,
81+
process_status: message.process_status,
8082
};
81-
83+
8284
if (options.includeMetadata) {
83-
base.metadata = message.metadata;
85+
base.priority = message.priority;
86+
base.recipient_list = message.recipient_list;
87+
base.thread = message.thread;
88+
base.in_response_to = message.in_response_to;
89+
base.conversation_id = message.conversation_id;
90+
base.ttl = message.ttl;
8491
}
85-
92+
8693
if (options.includeRouting) {
87-
base.routing = message.routing;
94+
base.routing_slip = message.routing_slip;
95+
base.forward_header = message.forward_header;
96+
base.message_history = message.message_history;
8897
}
89-
98+
9099
return base;
91100
});
92-
101+
93102
return Buffer.from(JSON.stringify(exportData, null, 2));
94103
}
95104

@@ -120,31 +129,31 @@ export class ExportService {
120129
const rows = [headers.join(',')];
121130

122131
for (const message of messages) {
123-
const payloadStr = JSON.stringify(message.payload.content);
132+
const payloadStr = JSON.stringify(message.payload);
124133
const row = [
125-
message.id.id,
126-
message.guildId,
127-
message.topicName,
128-
message.metadata.timestamp.toISOString(),
129-
message.status.current,
130-
message.metadata.sourceAgent,
131-
message.metadata.targetAgent || '',
132-
message.payload.type,
134+
message.id.toString(),
135+
typeof message.topics === 'string' ? message.topics : message.topics.join(';'),
136+
message.topic_published_to || '',
137+
new Date(message.timestamp).toISOString(),
138+
message.process_status || (message.is_error_message ? 'error' : 'completed'),
139+
message.sender.name || message.sender.id || 'unknown',
140+
message.recipient_list?.map(r => r.name || r.id).join(';') || '',
141+
message.format,
133142
payloadStr.length.toString(),
134143
];
135-
144+
136145
if (options.includeMetadata) {
137146
row.push(
138-
message.metadata.priority.toString(),
139-
message.metadata.retryCount.toString(),
140-
message.metadata.ttl?.toString() || ''
147+
message.priority.toString(),
148+
message.thread?.length.toString() || '0',
149+
message.ttl?.toString() || ''
141150
);
142151
}
143-
152+
144153
if (options.includeRouting) {
145154
row.push(
146-
message.routing.hops.length.toString(),
147-
message.routing.destination || ''
155+
message.message_history?.length.toString() || '0',
156+
message.forward_header?.on_behalf_of?.name || ''
148157
);
149158
}
150159

backend/src/services/messageHistory/ordering.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,19 @@ export class MessageOrdering {
88
orderMessages(messages: Message[]): Message[] {
99
return messages.sort((a, b) => {
1010
// First sort by timestamp
11-
const timeDiff = a.metadata.timestamp.getTime() - b.metadata.timestamp.getTime();
11+
const timeDiff = a.timestamp - b.timestamp;
1212
if (timeDiff !== 0) {
1313
return timeDiff;
1414
}
15-
15+
1616
// Same timestamp - sort by priority (higher priority first)
17-
const priorityDiff = b.metadata.priority - a.metadata.priority;
17+
const priorityDiff = b.priority - a.priority;
1818
if (priorityDiff !== 0) {
1919
return priorityDiff;
2020
}
21-
22-
// Same timestamp and priority - use GemstoneID counter for stable ordering
23-
return a.id.counter - b.id.counter;
21+
22+
// Same timestamp and priority - use message ID for stable ordering
23+
return a.id - b.id;
2424
});
2525
}
2626

@@ -34,19 +34,19 @@ export class MessageOrdering {
3434
const rootMessages: Message[] = [];
3535

3636
for (const message of messages) {
37-
if (message.parentMessageId) {
38-
const siblings = childrenMap.get(message.parentMessageId) || [];
37+
// Use in_response_to field to determine parent
38+
if (message.in_response_to) {
39+
const parentId = message.in_response_to.toString();
40+
const siblings = childrenMap.get(parentId) || [];
3941
siblings.push(message);
40-
childrenMap.set(message.parentMessageId, siblings);
42+
childrenMap.set(parentId, siblings);
4143
} else {
4244
rootMessages.push(message);
4345
}
4446
}
4547

4648
// Sort root messages by timestamp
47-
rootMessages.sort((a, b) =>
48-
a.metadata.timestamp.getTime() - b.metadata.timestamp.getTime()
49-
);
49+
rootMessages.sort((a, b) => a.timestamp - b.timestamp);
5050

5151
// Build ordered list with depth-first traversal
5252
const ordered: Message[] = [];
@@ -57,9 +57,9 @@ export class MessageOrdering {
5757
ordered.push(message);
5858

5959
// Add children recursively
60-
const children = childrenMap.get(message.id.id) || [];
60+
const children = childrenMap.get(message.id.toString()) || [];
6161
children
62-
.sort((a, b) => a.metadata.timestamp.getTime() - b.metadata.timestamp.getTime())
62+
.sort((a, b) => a.timestamp - b.timestamp)
6363
.forEach(child => addMessageAndChildren(child, depth + 1));
6464
};
6565

@@ -79,7 +79,7 @@ export class MessageOrdering {
7979
const buckets = new Map<number, Message[]>();
8080

8181
for (const message of messages) {
82-
const timestamp = message.metadata.timestamp.getTime();
82+
const timestamp = message.timestamp;
8383
const bucket = Math.floor(timestamp / bucketSizeMs) * bucketSizeMs;
8484

8585
const bucketMessages = buckets.get(bucket) || [];

0 commit comments

Comments
 (0)