Skip to content

Commit

Permalink
UI updates, processing bug fixes, notes, and testing console logs
Browse files Browse the repository at this point in the history
  • Loading branch information
jhweir committed Jan 21, 2025
1 parent 5720911 commit 801016f
Show file tree
Hide file tree
Showing 9 changed files with 224 additions and 199 deletions.
227 changes: 137 additions & 90 deletions packages/utils/src/synergy.ts

Large diffs are not rendered by default.

6 changes: 1 addition & 5 deletions views/chat-view/src/components/ChatView/ChatView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { AgentClient } from "@coasys/ad4m/lib/src/agent/AgentClient";
import { Message } from "@coasys/flux-api";
import { community } from "@coasys/flux-constants";
import { EntryType, Profile } from "@coasys/flux-types";
import { processItem, profileFormatter } from "@coasys/flux-utils";
import { profileFormatter } from "@coasys/flux-utils";
import { useEffect, useRef, useState } from "preact/hooks";
import { getPosition } from "../../utils/getPosition";
import Avatar from "../Avatar";
Expand Down Expand Up @@ -66,10 +66,6 @@ export default function ChatView({

// @ts-ignore
const message = (await repo.create({ body: html })) as any;
await processItem(perspective, source, {
baseExpression: message.id,
text,
});

if (replyMessage) {
perspective.addLinks([
Expand Down
9 changes: 4 additions & 5 deletions views/kanban-view/src/components/Entry/Entry.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { PerspectiveProxy } from "@coasys/ad4m";
import { useSubject } from "@coasys/ad4m-react-hooks";
import { processItem } from "@coasys/flux-utils";
import { useEffect, useState } from "preact/hooks";
import DisplayValue from "../DisplayValue";

Expand Down Expand Up @@ -56,10 +55,10 @@ export default function Entry({
? value.split("task://")[1]
: entry.status.split("task://")[1];
const taskText = `Task: "${task}", Status: "${status}"`;
processItem(perspective, channelId, {
baseExpression: id,
text: taskText,
});
// processItem(perspective, channelId, {
// baseExpression: id,
// text: taskText,
// });
}
});
}
Expand Down
15 changes: 1 addition & 14 deletions views/post-view/src/components/CreatePost/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import { Post as PostSubject, SubjectRepository } from "@coasys/flux-api";
import {
blobToDataURL,
dataURItoBlob,
processItem,
resizeImage,
} from "@coasys/flux-utils";
import { blobToDataURL, dataURItoBlob, resizeImage } from "@coasys/flux-utils";
import { useEffect, useMemo, useRef, useState } from "preact/hooks";
import { PostOption, postOptions } from "../../constants/options";
import FileUpload from "../FileUpload";
Expand Down Expand Up @@ -110,16 +105,8 @@ export default function CreatePost({
// if we send in null the property does not get updated
image: imageReplaced ? data.image : undefined,
});
processItem(perspective, source, {
baseExpression: postId,
text: data.title || data.body,
});
} else {
newPost = await Post.create(data);
processItem(perspective, source, {
baseExpression: newPost.id,
text: data.title || data.body,
});
}

onPublished(isEditing ? postId : newPost?.id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ export default function TimelineBlock({
}: Props) {
const {
baseExpression,
state,
groupType,
timestamp,
start,
Expand Down Expand Up @@ -240,18 +239,14 @@ export default function TimelineBlock({
<j-flex gap="400" a="center" wrap>
<Avatar did={author} showName />
</j-flex>
{state === "unprocessed" && <j-badge variant="warning">Unprocessed</j-badge>}
{!["processed", "unprocessed"].includes(state) && (
<j-badge variant="success">Processing...</j-badge>
)}
</j-flex>
<j-text
nomargin
dangerouslySetInnerHTML={{ __html: data.text }}
className={styles.itemText}
color="color-white"
/>
{selected && state === "processed" && (
{selected && (
<j-flex gap="300" wrap style={{ marginTop: 10 }}>
{topics.map((topic) => (
<button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,22 @@ $line-offset: 92px;
margin-left: $line-offset;
background-color: var(--j-color-primary-200);
}

.itemCard {
display: flex;
margin-bottom: 20px;
width: 100%;
border: 1px solid var(--j-color-ui-300);
border-radius: var(--j-border-radius);
padding: var(--j-space-400);
background-color: var(--j-color-ui-100);
}

.itemText {
p {
margin: 0;
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { useEffect, useState, useRef } from "preact/hooks";
import { closeMenu, getConversationData, groupingOptions, findItemState } from "../../utils";
import { processItem } from "@coasys/flux-utils";
import { closeMenu, getConversationData, groupingOptions } from "../../utils";
import { runProcessingCheck, getSynergyItems } from "@coasys/flux-utils";
import TimelineBlock from "../TimelineBlock";
import styles from "./TimelineColumn.module.scss";
import { getAd4mClient } from "@coasys/ad4m-connect/utils";
import Avatar from "../Avatar";

type Props = {
agent: any;
Expand All @@ -21,32 +22,28 @@ export default function TimelineColumn({
search,
}: Props) {
const [conversations, setConversations] = useState<any[]>([]);
const [processingItems, setProcessingItems] = useState<any[]>([]);
const [unprocessedItems, setUnprocessedItems] = useState<any[]>([]);
const [processing, setProcessing] = useState(false);
const [selectedItemId, setSelectedItemId] = useState<any>(null);
const [zoom, setZoom] = useState(groupingOptions[0]);
const [usingLLM, setUsingLLM] = useState(false);
const timeout = useRef<any>(null);
const totalConversationItems = useRef(0);

async function runProcessingCheckIfNewItems() {
const conversationItems = await getSynergyItems(perspective, channelId);
if (conversationItems.length > totalConversationItems.current)
runProcessingCheck(perspective, channelId);
totalConversationItems.current = conversationItems.length;
}

async function getData() {
runProcessingCheckIfNewItems();
const data = await getConversationData(perspective, channelId);
setProcessingItems(data.processingItems);
setUnprocessedItems(data.unprocessedItems);
setConversations(data.conversations);
}

async function processItems() {
setProcessing(true);
for (const item of unprocessedItems) {
// check if item still needs processing first incase someone has started
const state = await findItemState(perspective, item.baseExpression);
if (state !== "unprocessed") continue;
await processItem(perspective, channelId, item, true);
}
setProcessing(false);
}

async function checkIfUsingLLM() {
const client = await getAd4mClient();
const defaultLLM = await client.ai.getDefaultModel("LLM");
Expand Down Expand Up @@ -87,34 +84,6 @@ export default function TimelineColumn({
</j-menu-group>
</j-menu>
</j-flex>
{(processingItems.length > 0 || unprocessedItems.length > 0) && (
<j-flex a="center" gap="400">
{processingItems.length > 0 && (
<j-badge variant="success">
{processingItems.length} item
{processingItems.length > 1 ? "s" : ""} processing...
</j-badge>
)}
{unprocessedItems.length > 0 && (
<>
<j-badge variant="warning">
{unprocessedItems.length} unprocessed item
{unprocessedItems.length > 1 ? "s" : ""}
</j-badge>
{usingLLM && (
<j-button
size="sm"
onClick={processItems}
loading={processing}
disabled={processing}
>
Process
</j-button>
)}
</>
)}
</j-flex>
)}
</j-flex>
<div className={styles.timeline}>
<div className={styles.fades}>
Expand All @@ -136,6 +105,31 @@ export default function TimelineColumn({
search={search}
/>
))}
{unprocessedItems.length > 0 && (
<div style={{ marginLeft: 70 }}>
<j-text uppercase size="400" weight="800" color="primary-500">
Unprocessed Items
</j-text>
{unprocessedItems.map((item) => (
<j-flex gap="400" a="center" className={styles.itemCard}>
<j-flex gap="300" direction="column">
<j-flex gap="400" a="center">
<j-icon name={item.icon} color="ui-400" size="lg" />
<j-flex gap="400" a="center" wrap>
<Avatar did={item.author} showName />
</j-flex>
</j-flex>
<j-text
nomargin
dangerouslySetInnerHTML={{ __html: item.text }}
className={styles.itemText}
color="color-white"
/>
</j-flex>
</j-flex>
))}
</div>
)}
</div>
</div>
</div>
Expand Down
48 changes: 22 additions & 26 deletions views/synergy-demo-view/src/utils/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Conversation, ConversationSubgroup, SemanticRelationship } from "@coasys/flux-api";
import { findTopics, getSubgroupItems } from "@coasys/flux-utils";
import { findTopics, getSynergyItems, findUnprocessedItems } from "@coasys/flux-utils";
import { LinkQuery } from "@coasys/ad4m";

// constants
Expand All @@ -13,27 +13,13 @@ export function closeMenu(menuId: string) {
if (items) items.open = false;
}

export async function findItemState(perspective, itemId) {
// find the semantic relationship linking the item to its vector embedding
const relationships = await SemanticRelationship.query(perspective, { source: itemId });
const relationship = relationships.find((r: any) => !r.relevance) as any;
// if no relationship present, return unprocessed
if (!relationship) return "unprocessed";
// if a relationship is present and is linked to a vector embedding, return processed
else if (relationship.tag) return "processed";
else {
// if a relationship is present but not linked to a vector embedding, return the authors did so we know who is processing it
const links = await perspective.get(
new LinkQuery({ source: itemId, target: relationship.baseExpression })
);
return links[0].author;
}
}

export async function getConversationData(perspective, channelId, match?, setMatchIndex?) {
const processingItems = [];
const unprocessedItems = [];
const conversations = (await Conversation.query(perspective, { source: channelId })) as any;
// gather up unprocessed items
const channelItems = await getSynergyItems(perspective, channelId);
const unprocessedItems = await findUnprocessedItems(perspective, channelItems);
const conversations = (await Conversation.query(perspective, {
source: channelId,
})) as any;
// find & attach timestamp to converations
const conversationsWithTimestamps = await Promise.all(
conversations.map(
Expand All @@ -58,15 +44,25 @@ export async function getConversationData(perspective, channelId, match?, setMat
const subgroups = (await ConversationSubgroup.query(perspective, {
source: conversation.baseExpression,
})) as any;
const conversationItems = await getSynergyItems(perspective, conversation.baseExpression);
const subgroupsWithData = await Promise.all(
subgroups.map(async (subgroup, subgroupIndex) => {
if (match && subgroup.baseExpression === match.baseExpression) {
setMatchIndex(conversationIndex);
conversation.matchIndex = subgroupIndex;
}
const subgroupItems = await getSubgroupItems(perspective, subgroup.baseExpression);
subgroup.groupType = "subgroup";
subgroup.topics = await findTopics(perspective, subgroup.baseExpression);
const nextSubgroup = subgroups[subgroupIndex + 1];
const subgroupItems = conversationItems.filter(
(item) =>
// item after subgroup start
new Date(item.timestamp).getTime() > new Date(subgroup.positionTimestamp).getTime() &&
// either no subgroup after or item before next subgroup
(!nextSubgroup ||
new Date(item.timestamp).getTime() <
new Date(nextSubgroup.positionTimestamp).getTime())
);
if (subgroupItems.length) {
subgroup.start = subgroupItems[0].timestamp;
subgroup.end = subgroupItems[subgroupItems.length - 1].timestamp;
Expand All @@ -83,9 +79,6 @@ export async function getConversationData(perspective, channelId, match?, setMat
item.topics = await findTopics(perspective, item.baseExpression);
if (!subgroup.participants.find((p) => p === item.author))
subgroup.participants.push(item.author);
item.state = await findItemState(perspective, item.baseExpression);
if (item.state === "unprocessed") unprocessedItems.push(item);
else if (item.state !== "processed") processingItems.push(item);
return item;
})
);
Expand All @@ -104,7 +97,10 @@ export async function getConversationData(perspective, channelId, match?, setMat
return conversation;
})
);
return { conversations: conversationsWithData, processingItems, unprocessedItems };
return {
conversations: conversationsWithData,
unprocessedItems,
};
}

// svgs
Expand Down
15 changes: 5 additions & 10 deletions views/webrtc-view/src/components/Transcriber/Transcriber.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
import { useSubjects } from "@coasys/ad4m-react-hooks";
import { Message } from "@coasys/flux-api";
import { WebRTC } from "@coasys/flux-react-web";
import {
feedTranscription,
processItem,
startTranscription,
stopTranscription,
} from "@coasys/flux-utils";
import { feedTranscription, startTranscription, stopTranscription } from "@coasys/flux-utils";
import { useEffect, useRef, useState } from "preact/hooks";
import { v4 as uuidv4 } from "uuid";
import RecordingIcon from "../RecordingIcon/RecordingIcon";
Expand Down Expand Up @@ -119,10 +114,10 @@ export default function Transcriber({ source, perspective, webRTC }: Props) {
const message = (await messageRepo.create({
body: `<p>${fullText}</p>`,
})) as any;
processItem(perspective, source, {
baseExpression: message.id,
text: fullText,
});
// processItem(perspective, source, {
// baseExpression: message.id,
// text: fullText,
// });
}, messageTimeout * 1000);
}

Expand Down

0 comments on commit 801016f

Please sign in to comment.