client.tsx 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import React, { useEffect, useState } from "react";
  2. import type { Server } from "../src/server/server";
  3. import type { Session } from "../src/session/session";
  4. import { hc } from "hono/client";
  5. import { createInterface, Interface } from "readline";
  6. const client = hc<Server.App>(`http://localhost:16713`);
  7. const session = await client.session_create.$post().then((res) => res.json());
  8. const initial: {
  9. session: {
  10. info: {
  11. [sessionID: string]: Session.Info;
  12. };
  13. message: {
  14. [sessionID: string]: {
  15. [messageID: string]: Session.Message;
  16. };
  17. };
  18. };
  19. } = {
  20. session: {
  21. info: {
  22. [session.id]: session
  23. },
  24. message: {
  25. [session.id]: {}
  26. },
  27. },
  28. };
  29. import { render, Text, Newline, useStdout, Box } from "ink";
  30. import TextInput from "ink-text-input"
  31. function App() {
  32. const [state, setState] = useState(initial)
  33. const [input, setInput] = useState("")
  34. useEffect(() => {
  35. fetch("http://localhost:16713/event")
  36. .then(stream => {
  37. const decoder = new TextDecoder();
  38. stream.body!.pipeTo(
  39. new WritableStream({
  40. write(chunk) {
  41. const data = decoder.decode(chunk);
  42. if (data.startsWith("data: ")) {
  43. try {
  44. const event = JSON.parse(data.substring(6));
  45. switch (event.type) {
  46. case "storage.write":
  47. const splits: string[] = event.properties.key.split("/");
  48. let item = state as any;
  49. for (let i = 0; i < splits.length; i++) {
  50. const part = splits[i];
  51. if (i === splits.length - 1) {
  52. item[part] = event.properties.body;
  53. continue;
  54. }
  55. if (!item[part]) item[part] = {};
  56. item = item[part];
  57. }
  58. }
  59. setState({ ...state })
  60. } catch {
  61. }
  62. }
  63. },
  64. }),
  65. )
  66. });
  67. }, [])
  68. return (
  69. <>
  70. <Text>{session.title}</Text>
  71. {
  72. Object.values(state.session.message[session.id]).map(message => {
  73. return Object.values(message.parts).map((part, index) => {
  74. if (part.type === "text") {
  75. return <Text key={`${message.id}-${index}`}>{message.role}: {part.text}</Text>
  76. }
  77. })
  78. })
  79. }
  80. <Box gap={1} >
  81. <Text>Input:</Text>
  82. <TextInput
  83. value={input}
  84. onChange={setInput}
  85. onSubmit={() => {
  86. setInput("")
  87. client.session_chat.$post({
  88. json: {
  89. sessionID: session.id,
  90. parts: [
  91. {
  92. type: "text",
  93. text: input,
  94. },
  95. ],
  96. }
  97. })
  98. }}
  99. />
  100. </Box>
  101. </>
  102. );
  103. };
  104. console.clear();
  105. render(<App />);