summaryrefslogtreecommitdiff
path: root/backend/instance/server.ts
blob: e41f91fe88389092e09423387a70c98d171d4023 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import express from 'express';

import * as api from './api-connection.js';
import * as tools from './tools.js';
import * as notes from './notes.js';
import * as wget from './wget.js';
import * as chat from './chat.js';

const app = express();
app.use( express.json() );

var PORT = 3001;
var DOMAIN = 'http://localhost';

export function listen( port: number, domain: string ) {
  PORT = port;
  DOMAIN = domain;

  api.setStatus( { domain: `${DOMAIN}:${(port == 443 || port == 80)? '' : port}` } );

  app.listen( PORT, () => {
    console.log( `Server listening on ${DOMAIN}:${PORT}` );
  });
}

app.post( '/chat', async( req: any, res: any ) => {
  let messages: chat.Msg[] | undefined = req.body.messages;
  let options: chat.Options | undefined = req.body.options;

  if( !options || !messages )
    return res.status( 401 ).json( { status: 'error', msg: 'options not provided' } );
  if( api.status.isBusy )
    return res.status( 401 ).json( { status: 'busy', msg: 'please wait' } );

  res.header( 'Transfer-Encoding', 'chunked' );
  api.serverNotify( { isBusy: true } );
  wget.resetUseCount();
  tools.resetUseCount();

  let onChunk = ( chunk: string, isTool: boolean ) => {
    const chatStream: chat.Stream = {
      response: chunk,
      status: 'ok',
      done: false,
      tool: !!isTool
    };

    res.write( JSON.stringify( chatStream ) + '\n' );
  };

  try {
    const notelog = notes.load( options.uuid );
    const chatRes = await chat.run( messages, options, false, notelog, onChunk );
    messages.push( chatRes );
    const stream: chat.Stream = {
      status: 'ok',
      done: false,
      finalMsg: chatRes.content,
    }

    if( chatRes.toolCall ) {
      res.write( JSON.stringify( stream ) + '\n' );
      const toolRes = await tools.run( messages, options, chatRes.toolCall, notelog, onChunk );
      res.end( JSON.stringify( { status: 'ok', done: true, finalMsg: toolRes.content, title: chatRes.title } ) + "\n" );
    } else {
      res.end( JSON.stringify( { status: 'ok', done: true, finalMsg: chatRes.content, title: chatRes.title } ) + "\n" );
    }
    if( options.chatfile )
      chat.save( messages, options.chatfile );
  } catch( e: any ) {
    console.log( e );
    res.end( JSON.stringify( { status: 'error', msg: e.message } ) );
  }

  api.serverNotify( { isBusy: false } );
} );

app.post( '/generate', async( req: any, res: any ) => {
  let { prompt, suffix, options } = req.body;

  if( api.status.isBusy )
    return res.status( 401 ).json( { status: 'busy', msg: 'please wait' } );
  if( !options )
    return res.status( 401 ).json( { status: 'error', msg: 'options not provided' } );

  res.header( 'Transfer-Encoding', 'chunked' );
  api.serverNotify( { isBusy: true } );

  let onChunk = ( chunk: string ) => {
    const chatStream: chat.Stream = {
      response: chunk,
      status: 'ok',
      done: false
    };

    res.write( JSON.stringify( chatStream ) + '\n' );
  }

  try {
    const gen = await chat.generate( prompt, suffix, options, onChunk );
    const end: chat.Stream = {
      status: 'ok',
      done: true,
      finalMsg: gen
    };
    res.end( JSON.stringify( end ) );
  } catch( e: any ) {
    console.log( e );
    res.end( JSON.stringify( { status: 'error', msg: e.message } ) );
  }

  api.serverNotify( { isBusy: false } );
} );

// todo later
app.post( '/get-chat', async( _: any, res: any ) => {
  return res.status( 400 ).json( { status: 'err', msg: 'not implemented' } );
} );

// todo later
app.post( '/list-chats', async( _: any, res: any ) => {
  return res.status( 400 ).json( { status: 'err', msg: 'not implemented' } );
} );