Skip to content

Commit

Permalink
Merge branch 'main' into timer-implement
Browse files Browse the repository at this point in the history
  • Loading branch information
jwafu authored Dec 24, 2023
2 parents 720933b + bd1e4ca commit c06e1ea
Show file tree
Hide file tree
Showing 8 changed files with 465 additions and 57 deletions.
37 changes: 37 additions & 0 deletions .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Build and Test

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: 14

- name: Install dependencies
run: npm install

- name: Create test directory
run: mkdir test

- name: Create test file
run: echo "This is a test" > test/test.js

- name: Build project
run: npm run build -- --include=test

- name: Run tests
run: npm test
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "testing-sdk",
"version": "1.0.0",
"name": "pieces-os-client-example-ts",
"version": "1.1.0",
"main": "src/index.tsx",
"scripts": {
"dev": "ts-node src/index.tsx",
Expand All @@ -9,7 +9,7 @@
"build": "react-scripts build"
},
"dependencies": {
"@pieces.app/pieces-os-client": "^1.0.0",
"@pieces.app/pieces-os-client": "1.2.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "^5.0.1",
Expand Down
46 changes: 24 additions & 22 deletions src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import * as Pieces from "@pieces.app/pieces-os-client";
import {Application} from "@pieces.app/pieces-os-client";
import {DataTextInput, DeleteAssetButton, RenameAssetInput} from './components/TextInput';
import {Header} from './components/Header'
import {CopilotChat} from './components/Copilot'
import {connect} from './utils/Connect'
import CopilotStreamController from "./controllers/copilotStreamController";

// types
type LocalAsset = {
Expand All @@ -15,7 +17,7 @@ type LocalAsset = {

//=============================[GLOBALS]================================//
let full_context: JSON;
let applicationData: Application;
export var applicationData: Application;
let _indicator: HTMLElement;
let snippetList: Array<LocalAsset>;

Expand All @@ -36,6 +38,7 @@ export function App(): React.JSX.Element {

useEffect(() => {
refreshSnippetList();
CopilotStreamController.getInstance();
}, []);

const clearArray = () => {
Expand Down Expand Up @@ -81,18 +84,6 @@ export function App(): React.JSX.Element {
display: "flex",
boxShadow: '-4px 4px 5px rgba(0,0,0, 0.2)',
}}>
{/* (6) here we can take this div and give it a min height, so that even when the list is not filled with snippets,
the refresh button is still located towards the bottom of the column.
to match our new header, we can go ahead and start adjusting some of the colors here before moving on to
make some final tweaks to the components.
a. added a background color to the main view container directly one level above ^^
b. add the light shadow to the container as well from the component file for the /component/header.tsx
c. add some minimal padding to the container for you snippets that contains the array.map
d. add a title to this side - 'Saved Snippets' from your design
*/}
<div style={{minHeight: '100%', display: "flex", flexDirection: "column", justifyContent: 'space-between'}}>

<div style={{display: 'flex', flexDirection: 'row', alignItems: 'center'}}>
Expand Down Expand Up @@ -152,9 +143,6 @@ export function App(): React.JSX.Element {
</div>

))}

{/* (5) @jordan-pieces moved the refresh button up higher in this file and placed it inside the same column div as the snippet list.
this will create the more side by side look that you were going for in your design example */}
</div>

</div>
Expand All @@ -166,6 +154,22 @@ export function App(): React.JSX.Element {
</div>
</div>

{/* this is the copilot container. the copilot logic is inside the /components/Copilot.tsx */}
<div style={{
border: '2px solid black',
backgroundColor: '#0e1111',
height: '600px',
minWidth: '1175px',
maxWidth: '1175px',
padding: '20px',
borderRadius: '9px',
display: "flex",
boxShadow: '-4px 4px 5px rgba(0,0,0, 0.2)',
marginTop: '20px'
}}>
<CopilotChat />
</div>


</div>
)
Expand All @@ -183,15 +187,13 @@ connect().then(__ => {
_indicator = document.getElementById("indicator");

// conditional for the response back on application.
//
// (1) first @jordan-pieces came in here and added this turing statement here inside a new
// if statement. this is an upgrade in comparison to the previous if statement that would not check to
// see if the _indicator itself is added to the DOM yet.
// TODO: add some better error handling components and log - abstract the connect to its own file as well.
if (_indicator != null) {
__ != undefined ? _indicator.style.backgroundColor = "green" : _indicator.style.backgroundColor = "red";
}
//agrim implemented - Upon connecting to the Pieces OS, there is a need to enhance the user experience by implementing a timer
//that automatically hides the "You're Connected" text and shrinks the button after a certain duration

// @agrim implemented - Upon connecting to the Pieces OS, there is a need to enhance the user experience by implementing a timer
// that automatically hides the "You're Connected" text and shrinks the button after a certain duration
let time = 3000;
setTimeout(() => {
if (_indicator != null) {
Expand Down
198 changes: 198 additions & 0 deletions src/app/components/Copilot.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
import * as React from 'react'
import {useEffect, useState} from 'react'
import * as Pieces from "@pieces.app/pieces-os-client";
import {ConversationTypeEnum, SeededConversation} from "@pieces.app/pieces-os-client";


import { applicationData } from "../App";
import CopilotStreamController from '../controllers/copilotStreamController';


let GlobalConversationID: string;


// going to use get all conversations with a few extra steps to store the current conversations locally.
export function createNewConversation() {

// logs --> CREATING CONVERSATION
console.log('Begin creating conversation...')

// to create a new conversation, you need to first pass in a seeded conversation in the request body.
// the only mandatory parameter is the ConversationTypeEnum.Copilot value.
let seededConversation: SeededConversation = { type: ConversationTypeEnum.Copilot, name: "Demo Seeded Conversation" }

console.log('Conversation seeded')
console.log('Passing over the new conversation with name: ' + seededConversation.name)

// creates new conversation, .then is for confirmation on creation.
// note the usage of transfereables here to expose the full conversation data and give access to the id and other
// conversation values.
new Pieces.ConversationsApi().conversationsCreateSpecificConversationRaw({transferables: true, seededConversation}).then((_c) => {
console.log('Conversation created! : Here is the response:');
console.log(_c);

// check and ensure the response back is clean.
if (_c.raw.ok == true && _c.raw.status == 200) {
console.log('CLEAN RESPONSE BACK.')
_c.value().then(_conversation => {
console.log('Returning new conversation values.');
// console.log('ID | ' + _conversation.id);
// console.log('NAME | ' + _conversation.name);
// console.log('CREATED | ' + _conversation.created.readable);
// console.log('ID: ' + _conversation.);

// Set the conversation variable here for the local file:
GlobalConversationID = _conversation.id;
})
}
})
}


// You can use this here to set and send a conversation message.
// function sendConversationMessage(prompt: string, conversationID: string = GlobalConversationID){
// // 1. seed a message
// // 2. get the conversation id from somewhere - likely the createNewConversation above ^^
// // 3. send the new message over
// // 4. use the message contents in the (not yet created) message stream/list
// // console.log(prompt);
// // console.log(conversationID);
//
// askQuestion({query: prompt, relevant: ''}).then((r) => {
// return r.result;
// }).then((value) => {
//
// // TODO: need to collect all of the iterable answers here for the viewer.
// // TODO: i believe this is near the implementation of the stream.
// // let _answers = value.answers.iterable;
// // let's store the new answers globally for this file:
// // GlobalConversationAnswers = [..._answers];
// })
// }

export async function askQuestion({
query,
relevant,
}: {
query: string;
relevant: string;
}) {
// TODO: need to get instance here - current config is stored in app.tsx (maybe not actually)
// const config = ConnectorSingleton.getInstance();
const params: Pieces.QGPTQuestionInput = {
query,
relevant: {
iterable: [
{
seed: {
type: Pieces.SeedTypeEnum.Asset,
asset: {
application: applicationData,
format: {
fragment: {
string: {
raw: relevant,
},
},
},
},
},
},
],
},
};
// const result = await Pieces.QGPTApi.question({qGPTQuestionInput: params});
const result = new Pieces.QGPTApi().question({qGPTQuestionInput: params});
return {result, query};
}

export function CopilotChat(): React.JSX.Element {
const [chatSelected, setChatSelected] = useState('-- no chat selected --');
const [chatInputData, setData] = useState('');
const [message, setMessage] = useState<string>('');

// handles the data changes on the chat input.
const handleCopilotChatInputChange = (event: { target: { value: React.SetStateAction<string>; }; }) => {
setData(event.target.value);
};

// for setting the initial copilot chat that takes place on page load.
useEffect(() => {
const getInitialChat = async () => {
let _name: string;

await new Pieces.ConversationsApi().conversationsSnapshot({}).then(output => {
_name = output.iterable.at(0).name;
GlobalConversationID = output.iterable.at(0).id;
return output.iterable.at(0).name
});
setChatSelected(_name);
};
getInitialChat();
}, []);

return (
<div style={{ width: '-webkit-fill-available'}}>
<div style={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap'}}>
<div style={{ display: 'inherit', flexDirection: 'inherit', alignItems: 'inherit' }}>
<h1 style={{color: 'White'}}>Copilot Chat</h1>

{/* TODO: configure for selecting a conversation */}
{/*<button onClick={createNewConversation}> Get all Conversations</button>*/}

<button style={{maxWidth: 'fit-content',
height: 'fit-content',
marginLeft: '10px',
backgroundColor: "black",
border: '1px solid white',
borderRadius: '5px',
padding: '8px 24px',
color: 'white',
flexWrap: 'nowrap',
cursor: 'pointer',
fontSize: '12px'}} onClick={createNewConversation}>Create Fresh Conversation</button>
</div>

<div style={{width: '500px', maxHeight: '50px', display: "inherit", flexWrap: 'inherit', alignItems: 'inherit', justifyContent: 'center'}}>
{/* TODO: great candidate for a class here on these two buttons and their coming styles. */}
<button style={{maxHeight: '25px', minWidth: '60px'}}>back</button>
{/* TODO: attach the data here for the currently selected copilot chat */}
<p style={{ margin: '0px 15px', color: "white"}}> {chatSelected} </p>
<button style={{maxHeight: '25px', minWidth: '60px'}}>forward</button>
</div>
</div>
<div style={{border: '2px solid white', height: '80%', backgroundColor: 'rgba(0,0,0,0.6)', borderRadius: '15px', marginBottom: '10px', display: 'flex', position: 'relative'}}>
{/* top layer is the text box that always stays on top of the chat bar */}
<div style={{
zIndex: '10',
border: '2px solid transparent',
width: '-webkit-fill-available',
position: "absolute",
bottom: 0,
height: '50px',
borderBottomLeftRadius: '10px',
borderBottomRightRadius: '10px',
backgroundColor: "white",
display: 'inherit'
}}>
<textarea placeholder={"Type your prompt here..."} style={{
width: '99.5%',
height: '90%',
borderBottomLeftRadius: '10px',
borderBottomRightRadius: '10px',
border: 'none',
resize: 'none'
}} value={chatInputData} onChange={handleCopilotChatInputChange}></textarea>
<button onClick={() => CopilotStreamController.getInstance().askQGPT({query: chatInputData, setMessage})} style={{maxHeight: '25px', minWidth: '60px', alignSelf: 'center', marginBottom: '5px', marginRight: '5px', marginLeft: '10px'}}>Ask</button>
</div>
{/* this is the bottom container that is where the messages go. */}
<div style={{ overflow: "hidden", zIndex: 1, width: '-webkit-fill-available', position: "absolute", height: '100%', borderRadius: '10px', display: 'flex', justifyContent: 'center' }}>
<div style={{ border: '2px solid transparent', width: '70%'}}>
<p style={{ color: "white"}} >{message}</p>
</div>
</div>

</div>
</div>
)
}
21 changes: 3 additions & 18 deletions src/app/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,10 @@
import * as React from 'react'
import { Indicator } from "./Indicator"

// (3) Here you can see some of the html structure that you were writing in the index.html file. Inside the
// return (
// <ALL-HTML-IN-HERE>
// )
// you can see that this acts like a html file and can be used as a location to
// write html or reference other React.JSX.Element(s). So we can start by adding your styling here for the header.
//
// a. you did not include any styling for the header for the \website\wave.png image that you added. so instead I am
// going to remove the headerImg for now and instead change the background color of the Header element itself.
// b. going to add some styling to the header text to change the color, so we can see it, and add some horizontal
// padding to the header container.
// c. we will top it off by adding some rounding and shadow to the header container.
// d. while we are here i would love to add some margin below the header as well to let it breathe.
// e. added a few styles here to the text and a little tagline.
//
// Now lets head over to the <Indicator /> component to get the text in there that you wanted in /components/Indicator.tsx
//

// this is the header element with its children:

// Header element with connection indicator nested inside, shows if pieces os is running.
// We don't support logic for detecting the offline status but will be adding it soon!
export function Header(): React.JSX.Element {
return (
<div style={{ display: 'flex', flexDirection: "row", justifyContent: 'space-between', alignItems: 'center', backgroundColor: 'black', padding: '0px 10px', marginBottom: '1rem', boxShadow: '-4px 4px 5px rgba(0,0,0, 0.2)', borderRadius: '10px', minWidth: '1200px', maxWidth: '1200px'}}>
Expand Down
Loading

0 comments on commit c06e1ea

Please sign in to comment.