sujoydev99 commited on
Commit
579f597
·
1 Parent(s): b7b7936
Files changed (10) hide show
  1. .vscode/launch.json +3 -3
  2. api/index.js +465 -455
  3. cache.js +0 -1
  4. chat.html +2 -2
  5. functions.js +7 -7
  6. index.js +482 -435
  7. middleware.js +31 -1
  8. package.json +3 -0
  9. utils.js +2 -1
  10. yarn.lock +55 -2
.vscode/launch.json CHANGED
@@ -10,9 +10,9 @@
10
  "name": "Launch Server",
11
  "program": "${workspaceFolder}/index.js",
12
  "envFile": "${workspaceFolder}/.vscode/env",
13
- "env": {
14
- },
15
- "outputCapture": "std"
16
  }
17
  ]
18
  }
 
10
  "name": "Launch Server",
11
  "program": "${workspaceFolder}/index.js",
12
  "envFile": "${workspaceFolder}/.vscode/env",
13
+ "env": {},
14
+ "outputCapture": "std",
15
+ "runtimeExecutable": "/Users/sujoydev/.nvm/versions/node/v18.16.0/bin/node"
16
  }
17
  ]
18
  }
api/index.js CHANGED
@@ -161,6 +161,7 @@ const options = {
161
  */
162
 
163
  app.get(['/swagger.yaml', '/swagger.json'], (req, res) => {
 
164
  // Initialize swagger-jsdoc
165
  const swaggerSpec = swaggerJSDoc(options);
166
 
@@ -1214,433 +1215,443 @@ app.get('/', async (req, res, next) => {
1214
  }
1215
  });
1216
 
1217
- app.get('/talk', async (req, res, next) => {
1218
- try {
1219
- res.send(chatHtml);
1220
- } catch (error) {
1221
- console.error(error);
1222
- res.send('Something needs to be fixed!');
1223
- }
1224
- });
1225
 
1226
  app.post(
1227
  '/openai',
1228
  async (req, res, next) => {
1229
- const functions = [
1230
- {
1231
- "type": "function",
1232
- "function": {
1233
- "name": "getCompanyCreds",
1234
- "description": "Retrieves credentials for a specific company based on its ID.",
1235
- "parameters": {
1236
- "type": "object",
1237
- "properties": {
1238
- "company_id": {
1239
- "type": "number",
1240
- "description": "Unique identifier of the company."
1241
- }
1242
- },
1243
- "required": ["company_id"]
1244
- }
1245
- }
1246
- },
1247
- {
1248
- "type": "function",
1249
- "function": {
1250
- "name": "createUpdateCompanyCreds",
1251
- "description": "Creates or updates credentials for a company.",
1252
- "parameters": {
1253
- "type": "object",
1254
- "properties": {
1255
- "company_id": {
1256
- "type": "number",
1257
- "description": "Unique identifier of the company."
1258
- },
1259
- "clientId": {
1260
- "type": "string",
1261
- "description": "Client ID for authentication."
1262
  },
1263
- "clientSecret": {
1264
- "type": "string",
1265
- "description": "Client secret for authentication."
1266
- }
1267
- },
1268
- "required": ["company_id", "clientId", "clientSecret"]
1269
- }
1270
- }
1271
- },
1272
- {
1273
- "type": "function",
1274
- "function": {
1275
- "name": "getApplications",
1276
- "description": "Retrieves a list of applications associated with a specific company ID.",
1277
- "parameters": {
1278
- "type": "object",
1279
- "properties": {
1280
- "company_id": {
1281
- "type": "number",
1282
- "description": "Unique identifier of the company."
1283
- }
1284
- },
1285
- "required": ["company_id"]
1286
  }
1287
- }
1288
- },
1289
- {
1290
- "type": "function",
1291
- "function": {
1292
- "name": "createBrand",
1293
- "description": "Creates a new brand under a specific company.",
1294
- "parameters": {
1295
- "type": "object",
1296
- "properties": {
1297
- "company_id": {
1298
- "type": "number",
1299
- "description": "Unique identifier of the company."
1300
- },
1301
- "name": {
1302
- "type": "string",
1303
- "description": "Name of the new brand."
1304
- },
1305
- "description": {
1306
- "type": "string",
1307
- "description": "Description of the new brand."
1308
  },
1309
- "logo": {
1310
- "type": "string",
1311
- "description": "URL of the brand's logo."
1312
- }
1313
- },
1314
- "required": ["company_id", "name", "description"]
1315
  }
1316
- }
1317
- },
1318
- {
1319
- "type": "function",
1320
- "function": {
1321
- "name": "updateBrand",
1322
- "description": "Updates the details of an existing brand within a company.",
1323
- "parameters": {
1324
- "type": "object",
1325
- "properties": {
1326
- "company_id": {
1327
- "type": "number",
1328
- "description": "Unique identifier of the company."
1329
- },
1330
- "brand_id": {
1331
- "type": "string",
1332
- "description": "Unique identifier of the brand to be updated."
1333
- },
1334
- "name": {
1335
- "type": "string",
1336
- "description": "New name for the brand."
1337
- },
1338
- "description": {
1339
- "type": "string",
1340
- "description": "New description for the brand."
1341
- },
1342
- "logo": {
1343
- "type": "string",
1344
- "description": "New URL for the brand's logo."
1345
  },
1346
- },
1347
- "required": ["company_id", "brand_id", "name", "description"]
1348
- }
1349
- }
1350
- },
1351
- {
1352
- "type": "function",
1353
- "function": {
1354
- "name": "getBrands",
1355
- "description": "Retrieves a list of all brands associated with a specific company.",
1356
- "parameters": {
1357
- "type": "object",
1358
- "properties": {
1359
- "company_id": {
1360
- "type": "number",
1361
- "description": "Unique identifier of the company for which brands are being retrieved."
1362
- }
1363
- },
1364
- "required": ["company_id"]
1365
- }
1366
- }
1367
- },
1368
- {
1369
- "type": "function",
1370
- "function": {
1371
- "name": "getLocations",
1372
- "description": "Retrieves a list of all locations associated with a specific company.",
1373
- "parameters": {
1374
- "type": "object",
1375
- "properties": {
1376
- "company_id": {
1377
- "type": "number",
1378
- "description": "Unique identifier of the company for which locations are being retrieved."
1379
- }
1380
- },
1381
- "required": ["company_id"]
1382
  }
1383
- }
1384
- },
1385
- {
1386
- "type": "function",
1387
- "function": {
1388
- "name": "createLocation",
1389
- "description": "Creates a new location for a specified company.",
1390
- "parameters": {
1391
- "type": "object",
1392
- "properties": {
1393
- "company_id": {
1394
- "type": "number",
1395
- "description": "Unique identifier of the company."
1396
- },
1397
- "address1": {
1398
- "type": "string",
1399
- "description": "Primary address line of the new location."
1400
- },
1401
- "address2": {
1402
- "type": "string",
1403
- "description": "Secondary address line of the new location."
1404
- },
1405
- "pincode": {
1406
- "type": "string",
1407
- "description": "Postal code of the new location."
1408
- },
1409
- "state": {
1410
- "type": "string",
1411
- "description": "State where the new location is situated."
1412
- },
1413
- "city": {
1414
- "type": "string",
1415
- "description": "City where the new location is situated."
1416
- },
1417
- "number": {
1418
- "type": "string",
1419
- "description": "Contact number for the new location."
1420
- },
1421
- "country_code": {
1422
- "type": "string",
1423
- "description": "Country code for the contact number."
1424
- },
1425
- "gst_name": {
1426
- "type": "string",
1427
- "description": "GST registered name associated with the new location."
1428
- },
1429
- "gst_no": {
1430
- "type": "string",
1431
- "description": "GST number associated with the new location."
1432
- },
1433
- "latitude": {
1434
- "type": "number",
1435
- "description": "Latitude coordinate for the new location."
1436
  },
1437
- "longitude": {
1438
- "type": "number",
1439
- "description": "Longitude coordinate for the new location."
1440
- }
1441
- },
1442
- "required": ["company_id", "address1", "city", "state", "pincode", "country_code", "gst_name", "gst_no"]
1443
  }
1444
- }
1445
- },
1446
- {
1447
- "type": "function",
1448
- "function": {
1449
- "name": "updateLocation",
1450
- "description": "update a existing location for a specified company.",
1451
- "parameters": {
1452
- "type": "object",
1453
- "properties": {
1454
- "company_id": {
1455
- "type": "number",
1456
- "description": "Unique identifier of the company."
1457
- },
1458
- "location_id": {
1459
- "type": "number",
1460
- "description": "Unique identifier of the location."
1461
- },
1462
- "address1": {
1463
- "type": "string",
1464
- "description": "Primary address line of the new location."
1465
- },
1466
- "address2": {
1467
- "type": "string",
1468
- "description": "Secondary address line of the new location."
1469
- },
1470
- "pincode": {
1471
- "type": "string",
1472
- "description": "Postal code of the new location."
1473
- },
1474
- "state": {
1475
- "type": "string",
1476
- "description": "State where the new location is situated."
1477
- },
1478
- "city": {
1479
- "type": "string",
1480
- "description": "City where the new location is situated."
1481
- },
1482
- "number": {
1483
- "type": "string",
1484
- "description": "Contact number for the new location."
1485
- },
1486
- "country_code": {
1487
- "type": "string",
1488
- "description": "Country code for the contact number."
1489
- },
1490
- "gst_name": {
1491
- "type": "string",
1492
- "description": "GST registered name associated with the new location."
1493
- },
1494
- "gst_no": {
1495
- "type": "string",
1496
- "description": "GST number associated with the new location."
1497
- },
1498
- "latitude": {
1499
- "type": "number",
1500
- "description": "Latitude coordinate for the new location."
1501
  },
1502
- "longitude": {
1503
- "type": "number",
1504
- "description": "Longitude coordinate for the new location."
1505
- }
1506
- },
1507
- "required": ["company_id", 'brand_id', "address1", "city", "state", "pincode", "country_code", "gst_name", "gst_no"]
1508
  }
1509
- }
1510
- },
1511
- {
1512
- "type": "function",
1513
- "function": {
1514
- "name": "createProduct",
1515
- "description": "Creates a new product in the company's catalog.",
1516
- "parameters": {
1517
- "type": "object",
1518
- "properties": {
1519
- "name": {
1520
- "type": "string",
1521
- "description": "Name of the new product."
1522
- },
1523
- "company_id": {
1524
- "type": "number",
1525
- "description": "Unique identifier of the company."
1526
- },
1527
- "slug": {
1528
- "type": "string",
1529
- "description": "SEO-friendly URL segment for the product."
1530
- },
1531
- "seller_identifier": {
1532
- "type": "string",
1533
- "description": "Unique identifier for the seller of the product."
1534
- },
1535
- "brand_id": {
1536
- "type": "number",
1537
- "description": "Unique identifier of the brand associated with the product."
1538
- },
1539
- "mrp": {
1540
- "type": "number",
1541
- "description": "Maximum Retail Price of the product."
1542
  },
1543
- "selling_price": {
1544
- "type": "number",
1545
- "description": "Selling price of the product."
1546
- }
1547
- },
1548
- "required": ["name", "company_id", "slug", "seller_identifier", "brand_id"]
1549
  }
1550
- }
1551
- },
1552
- {
1553
- "type": "function",
1554
- "function": {
1555
- "name": "createInventory",
1556
- "description": "Creates a new inventory record for a specific product in a company.",
1557
- "parameters": {
1558
- "type": "object",
1559
- "properties": {
1560
- "company_id": {
1561
- "type": "number",
1562
- "description": "Unique identifier of the company."
1563
- },
1564
- "product_id": {
1565
- "type": "number",
1566
- "description": "Unique identifier of the product."
1567
- },
1568
- "seller_identifier": {
1569
- "type": "string",
1570
- "description": "Unique identifier for the seller of the product."
1571
  },
1572
- "location_id": {
1573
- "type": "number",
1574
- "description": "Unique identifier of the location where the inventory is stored."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1575
  },
1576
- "mrp": {
1577
- "type": "number",
1578
- "description": "Maximum Retail Price of the product."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1579
  },
1580
- "selling_price": {
1581
- "type": "number",
1582
- "description": "Selling price of the product."
1583
- }
1584
- },
1585
- "required": ["company_id", "product_id", "seller_identifier", "location_id"]
1586
  }
1587
- }
1588
- },
1589
- {
1590
- "type": "function",
1591
- "function": {
1592
- "name": "createApplication",
1593
- "description": "Creates a new application for a specified company.",
1594
- "parameters": {
1595
- "type": "object",
1596
- "properties": {
1597
- "company_id": {
1598
- "type": "number",
1599
- "description": "Unique identifier of the company."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1600
  },
1601
- "brand_ids": {
1602
- "type": "array",
1603
- "description": "Array of brand IDs associated with the application.",
1604
- "items": {
1605
- "type": "number"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1606
  }
1607
  },
1608
- "name": {
1609
- "type": "string",
1610
- "description": "Name of the new application."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1611
  },
1612
- "subdomain": {
1613
- "type": "string",
1614
- "description": "Subdomain for the application's URL."
1615
- }
1616
- },
1617
- "required": ["company_id", "brand_ids", "name", "subdomain"]
1618
  }
1619
  }
1620
- }
1621
- ];
 
 
 
1622
 
1623
- const messages = [{
1624
- role: 'system',
1625
- content: 'You are Jio Copilot. Introducing an all-encompassing tool, designed to seamlessly interact with TiraBeauty, JioCinema, JioMart, and JioFiber, catering to multiple facets of your digital lifestyle.\nOur JioMart integration simplifies your online shopping journey, providing a wide selection of products, from clothing and electronics to grocery items, all in one convenient location. JioMart can help to buy ingredients from recipes. Search each ingredient separately.\nWith TiraBeauty functionality, you can explore a wide array of health and beauty products, effortlessly manage your shopping cart, and share your cart selections via a QR code within the ecosystem of www.tirabeauty.com - your comprehensive ecommerce destination for beauty products and accessories.\nThe JioCinema feature takes you on an immersive streaming adventure, offering access to a diverse range of television shows, movies, sports content, and much more. Easily search and stream content to match your mood, directly from this interface.\nFinally, the JioFiber functionality empowers you to navigate through a range of lightning-fast internet and data plans from this leading broadband service provider. Explore and choose from a comprehensive list of prepaid and postpaid plans to meet your connectivity needs.\nEquip yourself with this multifunctional tool and experience a streamlined, efficient digital experience across a variety of platforms.'
1626
- }];
1627
- const session = req.jio_copilot_anonymous_session;
1628
- if (session) {
1629
- messages.push(...(await listCache.getAll(session)));
1630
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1631
 
1632
- const userMessage = { role: 'user', content: req.body.prompt };
1633
- messages.push(userMessage);
1634
- await listCache.setItems(session, userMessage);
1635
 
1636
- res.setHeader('Cache-Control', 'no-cache');
1637
- res.setHeader('Content-Type', 'text/event-stream');
1638
- // res.setHeader('Access-Control-Allow-Origin', http://);
1639
- res.setHeader('Connection', 'keep-alive');
1640
- res.flushHeaders();
1641
 
1642
- try {
1643
- // await nextStep(session, messages, skills, functions, res);
1644
  res.end();
1645
  } catch (error) {
1646
  if (error.code === 'context_length_exceeded') {
@@ -1665,66 +1676,65 @@ app.listen(port, async () => {
1665
  await fs.writeFileSync("swagger.json", JSON.stringify(swaggerSpec, null, 2), 'utf-8')
1666
  });
1667
 
1668
- // async function nextStep(session, messages, skills, functions, res) {
1669
- // const conn = new OpenAI({ apiKey: "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" });
1670
- // const streamResponse = await conn
1671
- // .chat.completions.create({
1672
- // model: 'gpt-4-1106-preview',
1673
- // messages,
1674
- // functions,
1675
- // function_call: 'auto',
1676
- // temperature: 0.5,
1677
- // stream: true
1678
- // }).catch(async err => {
1679
- // console.error(err);
1680
- // const openAIError = new Error(err.error.message);
1681
- // openAIError.code = err.error.code;
1682
- // throw openAIError;
1683
- // });
1684
 
1685
- // let finalMessage = '';
1686
- // const functionCall = { name: null, arguments: '' };
1687
 
1688
- // for await (const line of streamResponse) {
1689
- // const choice = line.choices[0];
1690
- // if (choice.delta.function_call) {
1691
- // const fc = choice.delta.function_call;
1692
- // if (fc.name) {
1693
- // // res.write(`Detected Function: ${fc.name}\n\n`);
1694
- // // res.flush();
1695
- // functionCall.name = fc.name;
1696
- // }
1697
- // if (fc.arguments) {
1698
- // functionCall.arguments += fc.arguments;
1699
- // }
1700
- // } else if (!choice.finish_reason && choice.delta.content) {
1701
- // finalMessage += choice.delta.content;
1702
- // res.write(`${choice.delta.content}`);
1703
- // res.flush();
1704
- // }
1705
- // }
1706
 
1707
- // if (!functionCall.name) {
1708
- // const assistantMessage = { role: 'assistant', content: finalMessage };
1709
- // messages.push(assistantMessage);
1710
- // await listCache.setItems(session, assistantMessage);
1711
- // return;
1712
- // }
1713
 
1714
- // const functionName = functionCall.name;
1715
- // const args = JSON.parse(functionCall.arguments);
1716
- // if (!skills[functionName]) {
1717
- // throw new Error(`No skill implemented for this function: ${functionName}`);
1718
- // }
1719
 
1720
- // // res.write(`Executing Function: ${functionName} with arguments ${JSON.stringify(args)} \n\n`);
1721
- // // res.flush();
1722
- // const skill = new skills[functionName]({ ...args, headers: { 'openai-ephemeral-user-id': session } });
1723
- // const skillRes = await skill.performAction();
1724
- // if (skillRes) {
1725
- // const functionMessage = { role: 'function', name: functionName, content: JSON.stringify(skillRes) };
1726
- // messages.push(functionMessage);
1727
- // await listCache.setItems(session, functionMessage);
1728
- // }
1729
- // return nextStep(conn, session, messages, skills, functions, res);
1730
- // }
 
161
  */
162
 
163
  app.get(['/swagger.yaml', '/swagger.json'], (req, res) => {
164
+
165
  // Initialize swagger-jsdoc
166
  const swaggerSpec = swaggerJSDoc(options);
167
 
 
1215
  }
1216
  });
1217
 
 
 
 
 
 
 
 
 
1218
 
1219
  app.post(
1220
  '/openai',
1221
  async (req, res, next) => {
1222
+ try {
1223
+ const functions = [
1224
+ {
1225
+ "type": "function",
1226
+ "function": {
1227
+ "name": "getCompanyCreds",
1228
+ "description": "Retrieves credentials for a specific company based on its ID.",
1229
+ "parameters": {
1230
+ "type": "object",
1231
+ "properties": {
1232
+ "company_id": {
1233
+ "type": "number",
1234
+ "description": "Unique identifier of the company."
1235
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1236
  },
1237
+ "required": ["company_id"]
1238
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1239
  }
1240
+ },
1241
+ {
1242
+ "type": "function",
1243
+ "function": {
1244
+ "name": "createUpdateCompanyCreds",
1245
+ "description": "Creates or updates credentials for a company.",
1246
+ "parameters": {
1247
+ "type": "object",
1248
+ "properties": {
1249
+ "company_id": {
1250
+ "type": "number",
1251
+ "description": "Unique identifier of the company."
1252
+ },
1253
+ "clientId": {
1254
+ "type": "string",
1255
+ "description": "Client ID for authentication."
1256
+ },
1257
+ "clientSecret": {
1258
+ "type": "string",
1259
+ "description": "Client secret for authentication."
1260
+ }
1261
  },
1262
+ "required": ["company_id", "clientId", "clientSecret"]
1263
+ }
 
 
 
 
1264
  }
1265
+ },
1266
+ {
1267
+ "type": "function",
1268
+ "function": {
1269
+ "name": "getApplications",
1270
+ "description": "Retrieves a list of applications associated with a specific company ID.",
1271
+ "parameters": {
1272
+ "type": "object",
1273
+ "properties": {
1274
+ "company_id": {
1275
+ "type": "number",
1276
+ "description": "Unique identifier of the company."
1277
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1278
  },
1279
+ "required": ["company_id"]
1280
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1281
  }
1282
+ },
1283
+ {
1284
+ "type": "function",
1285
+ "function": {
1286
+ "name": "createBrand",
1287
+ "description": "Creates a new brand under a specific company.",
1288
+ "parameters": {
1289
+ "type": "object",
1290
+ "properties": {
1291
+ "company_id": {
1292
+ "type": "number",
1293
+ "description": "Unique identifier of the company."
1294
+ },
1295
+ "name": {
1296
+ "type": "string",
1297
+ "description": "Name of the new brand."
1298
+ },
1299
+ "description": {
1300
+ "type": "string",
1301
+ "description": "Description of the new brand."
1302
+ },
1303
+ "logo": {
1304
+ "type": "string",
1305
+ "description": "URL of the brand's logo."
1306
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1307
  },
1308
+ "required": ["company_id", "name", "description"]
1309
+ }
 
 
 
 
1310
  }
1311
+ },
1312
+ {
1313
+ "type": "function",
1314
+ "function": {
1315
+ "name": "updateBrand",
1316
+ "description": "Updates the details of an existing brand within a company.",
1317
+ "parameters": {
1318
+ "type": "object",
1319
+ "properties": {
1320
+ "company_id": {
1321
+ "type": "number",
1322
+ "description": "Unique identifier of the company."
1323
+ },
1324
+ "brand_id": {
1325
+ "type": "string",
1326
+ "description": "Unique identifier of the brand to be updated."
1327
+ },
1328
+ "name": {
1329
+ "type": "string",
1330
+ "description": "New name for the brand."
1331
+ },
1332
+ "description": {
1333
+ "type": "string",
1334
+ "description": "New description for the brand."
1335
+ },
1336
+ "logo": {
1337
+ "type": "string",
1338
+ "description": "New URL for the brand's logo."
1339
+ },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1340
  },
1341
+ "required": ["company_id", "brand_id", "name", "description"]
1342
+ }
 
 
 
 
1343
  }
1344
+ },
1345
+ {
1346
+ "type": "function",
1347
+ "function": {
1348
+ "name": "getBrands",
1349
+ "description": "Retrieves a list of all brands associated with a specific company.",
1350
+ "parameters": {
1351
+ "type": "object",
1352
+ "properties": {
1353
+ "company_id": {
1354
+ "type": "number",
1355
+ "description": "Unique identifier of the company for which brands are being retrieved."
1356
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1357
  },
1358
+ "required": ["company_id"]
1359
+ }
 
 
 
 
1360
  }
1361
+ },
1362
+ {
1363
+ "type": "function",
1364
+ "function": {
1365
+ "name": "getLocations",
1366
+ "description": "Retrieves a list of all locations associated with a specific company.",
1367
+ "parameters": {
1368
+ "type": "object",
1369
+ "properties": {
1370
+ "company_id": {
1371
+ "type": "number",
1372
+ "description": "Unique identifier of the company for which locations are being retrieved."
1373
+ }
 
 
 
 
 
 
 
 
1374
  },
1375
+ "required": ["company_id"]
1376
+ }
1377
+ }
1378
+ },
1379
+ {
1380
+ "type": "function",
1381
+ "function": {
1382
+ "name": "createLocation",
1383
+ "description": "Creates a new location for a specified company.",
1384
+ "parameters": {
1385
+ "type": "object",
1386
+ "properties": {
1387
+ "company_id": {
1388
+ "type": "number",
1389
+ "description": "Unique identifier of the company."
1390
+ },
1391
+ "address1": {
1392
+ "type": "string",
1393
+ "description": "Primary address line of the new location."
1394
+ },
1395
+ "address2": {
1396
+ "type": "string",
1397
+ "description": "Secondary address line of the new location."
1398
+ },
1399
+ "pincode": {
1400
+ "type": "string",
1401
+ "description": "Postal code of the new location."
1402
+ },
1403
+ "state": {
1404
+ "type": "string",
1405
+ "description": "State where the new location is situated."
1406
+ },
1407
+ "city": {
1408
+ "type": "string",
1409
+ "description": "City where the new location is situated."
1410
+ },
1411
+ "number": {
1412
+ "type": "string",
1413
+ "description": "Contact number for the new location."
1414
+ },
1415
+ "country_code": {
1416
+ "type": "string",
1417
+ "description": "Country code for the contact number."
1418
+ },
1419
+ "gst_name": {
1420
+ "type": "string",
1421
+ "description": "GST registered name associated with the new location."
1422
+ },
1423
+ "gst_no": {
1424
+ "type": "string",
1425
+ "description": "GST number associated with the new location."
1426
+ },
1427
+ "latitude": {
1428
+ "type": "number",
1429
+ "description": "Latitude coordinate for the new location."
1430
+ },
1431
+ "longitude": {
1432
+ "type": "number",
1433
+ "description": "Longitude coordinate for the new location."
1434
+ }
1435
  },
1436
+ "required": ["company_id", "address1", "city", "state", "pincode", "country_code", "gst_name", "gst_no"]
1437
+ }
1438
+ }
1439
+ },
1440
+ {
1441
+ "type": "function",
1442
+ "function": {
1443
+ "name": "updateLocation",
1444
+ "description": "update a existing location for a specified company.",
1445
+ "parameters": {
1446
+ "type": "object",
1447
+ "properties": {
1448
+ "company_id": {
1449
+ "type": "number",
1450
+ "description": "Unique identifier of the company."
1451
+ },
1452
+ "location_id": {
1453
+ "type": "number",
1454
+ "description": "Unique identifier of the location."
1455
+ },
1456
+ "address1": {
1457
+ "type": "string",
1458
+ "description": "Primary address line of the new location."
1459
+ },
1460
+ "address2": {
1461
+ "type": "string",
1462
+ "description": "Secondary address line of the new location."
1463
+ },
1464
+ "pincode": {
1465
+ "type": "string",
1466
+ "description": "Postal code of the new location."
1467
+ },
1468
+ "state": {
1469
+ "type": "string",
1470
+ "description": "State where the new location is situated."
1471
+ },
1472
+ "city": {
1473
+ "type": "string",
1474
+ "description": "City where the new location is situated."
1475
+ },
1476
+ "number": {
1477
+ "type": "string",
1478
+ "description": "Contact number for the new location."
1479
+ },
1480
+ "country_code": {
1481
+ "type": "string",
1482
+ "description": "Country code for the contact number."
1483
+ },
1484
+ "gst_name": {
1485
+ "type": "string",
1486
+ "description": "GST registered name associated with the new location."
1487
+ },
1488
+ "gst_no": {
1489
+ "type": "string",
1490
+ "description": "GST number associated with the new location."
1491
+ },
1492
+ "latitude": {
1493
+ "type": "number",
1494
+ "description": "Latitude coordinate for the new location."
1495
+ },
1496
+ "longitude": {
1497
+ "type": "number",
1498
+ "description": "Longitude coordinate for the new location."
1499
+ }
1500
  },
1501
+ "required": ["company_id", 'brand_id', "address1", "city", "state", "pincode", "country_code", "gst_name", "gst_no"]
1502
+ }
 
 
 
 
1503
  }
1504
+ },
1505
+ {
1506
+ "type": "function",
1507
+ "function": {
1508
+ "name": "createProduct",
1509
+ "description": "Creates a new product in the company's catalog.",
1510
+ "parameters": {
1511
+ "type": "object",
1512
+ "properties": {
1513
+ "name": {
1514
+ "type": "string",
1515
+ "description": "Name of the new product."
1516
+ },
1517
+ "company_id": {
1518
+ "type": "number",
1519
+ "description": "Unique identifier of the company."
1520
+ },
1521
+ "slug": {
1522
+ "type": "string",
1523
+ "description": "SEO-friendly URL segment for the product."
1524
+ },
1525
+ "seller_identifier": {
1526
+ "type": "string",
1527
+ "description": "Unique identifier for the seller of the product."
1528
+ },
1529
+ "brand_id": {
1530
+ "type": "number",
1531
+ "description": "Unique identifier of the brand associated with the product."
1532
+ },
1533
+ "mrp": {
1534
+ "type": "number",
1535
+ "description": "Maximum Retail Price of the product."
1536
+ },
1537
+ "selling_price": {
1538
+ "type": "number",
1539
+ "description": "Selling price of the product."
1540
+ }
1541
  },
1542
+ "required": ["name", "company_id", "slug", "seller_identifier", "brand_id"]
1543
+ }
1544
+ }
1545
+ },
1546
+ {
1547
+ "type": "function",
1548
+ "function": {
1549
+ "name": "createInventory",
1550
+ "description": "Creates a new inventory record for a specific product in a company.",
1551
+ "parameters": {
1552
+ "type": "object",
1553
+ "properties": {
1554
+ "company_id": {
1555
+ "type": "number",
1556
+ "description": "Unique identifier of the company."
1557
+ },
1558
+ "product_id": {
1559
+ "type": "number",
1560
+ "description": "Unique identifier of the product."
1561
+ },
1562
+ "seller_identifier": {
1563
+ "type": "string",
1564
+ "description": "Unique identifier for the seller of the product."
1565
+ },
1566
+ "location_id": {
1567
+ "type": "number",
1568
+ "description": "Unique identifier of the location where the inventory is stored."
1569
+ },
1570
+ "mrp": {
1571
+ "type": "number",
1572
+ "description": "Maximum Retail Price of the product."
1573
+ },
1574
+ "selling_price": {
1575
+ "type": "number",
1576
+ "description": "Selling price of the product."
1577
  }
1578
  },
1579
+ "required": ["company_id", "product_id", "seller_identifier", "location_id"]
1580
+ }
1581
+ }
1582
+ },
1583
+ {
1584
+ "type": "function",
1585
+ "function": {
1586
+ "name": "createApplication",
1587
+ "description": "Creates a new application for a specified company.",
1588
+ "parameters": {
1589
+ "type": "object",
1590
+ "properties": {
1591
+ "company_id": {
1592
+ "type": "number",
1593
+ "description": "Unique identifier of the company."
1594
+ },
1595
+ "brand_ids": {
1596
+ "type": "array",
1597
+ "description": "Array of brand IDs associated with the application.",
1598
+ "items": {
1599
+ "type": "number"
1600
+ }
1601
+ },
1602
+ "name": {
1603
+ "type": "string",
1604
+ "description": "Name of the new application."
1605
+ },
1606
+ "subdomain": {
1607
+ "type": "string",
1608
+ "description": "Subdomain for the application's URL."
1609
+ }
1610
  },
1611
+ "required": ["company_id", "brand_ids", "name", "subdomain"]
1612
+ }
 
 
 
 
1613
  }
1614
  }
1615
+ ];
1616
+ console.log(req.body)
1617
+ const messages = [{
1618
+ role: 'system',
1619
+ content: `you are an onboarding buddy chatbot for fynd platform, you help logged in userd who have access to a company to clear their salechannels/ websites. when asking questions from the use ask one at a time, ask user for one input at a time. You must initiate the conversation
1620
 
1621
+ NOTE:
1622
+ to get started yo need to get the companyId, clientId and secret from the user. always check if the credentials exist, if not save them
1623
+ to create a sales channel you require at least one brand. fetch and show the brands
1624
+ to create a product you need a brand, department and category. fetch and show the brand, departments
1625
+ once the product is created it takes some time reflect in the db before the inventory is added
1626
+ for a product to be visible on your sales channel you must also add inventory for it
1627
+ stores, location, warehouses mean the same
1628
+
1629
+ UI Links: always give the ui link when performing actions
1630
+ company credentials create link = https://platform.fynd.com/company/{companyId}/apis/oauthclient/create
1631
+ company homepage url = https://platform.fynd.com/company/{companyId}/home
1632
+ company profile url = https://platform.fynd.com/company/{companyId}/profile
1633
+ company location url = https://platform.fynd.com/company/{companyId}/profile/edit-store/{locationId}
1634
+ company brand url = https://platform.fynd.com/company/{companyId}/profile/edit-brand/{brandId}
1635
+ company sales channels url = https://platform.fynd.com/company/{companyId}/application/{applicationId}/products
1636
+ company product listing url= https://platform.fynd.com/company/{companyId}/products/list
1637
+ company product url = https://platform.fynd.com/company/{companyId}/products/{itemId}/edit.`
1638
+ }];
1639
+ const session = req.jio_copilot_anonymous_session;
1640
+ if (session) {
1641
+ messages.push(...(await listCache.getAll(session)));
1642
+ }
1643
 
1644
+ const userMessage = { role: 'user', content: req.body.prompt };
1645
+ messages.push(userMessage);
1646
+ await listCache.setItems(session, userMessage);
1647
 
1648
+ res.setHeader('Cache-Control', 'no-cache');
1649
+ res.setHeader('Content-Type', 'text/event-stream');
1650
+ // res.setHeader('Access-Control-Allow-Origin', http://);
1651
+ res.setHeader('Connection', 'keep-alive');
1652
+ res.flushHeaders();
1653
 
1654
+ await nextStep(session, messages, skills, functions, res);
 
1655
  res.end();
1656
  } catch (error) {
1657
  if (error.code === 'context_length_exceeded') {
 
1676
  await fs.writeFileSync("swagger.json", JSON.stringify(swaggerSpec, null, 2), 'utf-8')
1677
  });
1678
 
1679
+ async function nextStep(session, messages, skills, functions, res) {
1680
+ const conn = new OpenAI({ apiKey: "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" });
1681
+ const streamResponse = await conn
1682
+ .chat.completions.create({
1683
+ model: 'gpt-4-1106-preview',
1684
+ messages,
1685
+ functions,
1686
+ function_call: 'auto',
1687
+ temperature: 0.5,
1688
+ stream: true
1689
+ }).catch(async err => {
1690
+ console.error(err);
1691
+ const openAIError = new Error(err.error.message);
1692
+ openAIError.code = err.error.code;
1693
+ throw openAIError;
1694
+ });
1695
 
1696
+ let finalMessage = '';
1697
+ const functionCall = { name: null, arguments: '' };
1698
 
1699
+ for await (const line of streamResponse) {
1700
+ const choice = line.choices[0];
1701
+ if (choice.delta.function_call) {
1702
+ const fc = choice.delta.function_call;
1703
+ if (fc.name) {
1704
+ // res.write(`Detected Function: ${fc.name}\n\n`);
1705
+ // res.flush();
1706
+ functionCall.name = fc.name;
1707
+ }
1708
+ if (fc.arguments) {
1709
+ functionCall.arguments += fc.arguments;
1710
+ }
1711
+ } else if (!choice.finish_reason && choice.delta.content) {
1712
+ finalMessage += choice.delta.content;
1713
+ res.write(`${choice.delta.content}`);
1714
+ res.flush();
1715
+ }
1716
+ }
1717
 
1718
+ if (!functionCall.name) {
1719
+ const assistantMessage = { role: 'assistant', content: finalMessage };
1720
+ messages.push(assistantMessage);
1721
+ await listCache.setItems(session, assistantMessage);
1722
+ return;
1723
+ }
1724
 
1725
+ const functionName = functionCall.name;
1726
+ const args = JSON.parse(functionCall.arguments);
1727
+ if (!skills[functionName]) {
1728
+ throw new Error(`No skill implemented for this function: ${functionName}`);
1729
+ }
1730
 
1731
+ // res.write(`Executing Function: ${functionName} with arguments ${JSON.stringify(args)} \n\n`);
1732
+ // res.flush();
1733
+ const skillRes = await skills[functionName]({ ...args, headers: { 'openai-ephemeral-user-id': session } });
1734
+ if (skillRes) {
1735
+ const functionMessage = { role: 'function', name: functionName, content: JSON.stringify(skillRes) };
1736
+ messages.push(functionMessage);
1737
+ await listCache.setItems(session, functionMessage);
1738
+ }
1739
+ return nextStep(conn, session, messages, skills, functions, res);
1740
+ }
 
cache.js CHANGED
@@ -48,7 +48,6 @@ export class RedisListCache {
48
  const namespacedKey = this.namespace + key;
49
  const items = values.map(value => JSON.stringify({
50
  ...value,
51
- createdAt: new Date().toISOString()
52
  }));
53
  await this.redis.rpush(namespacedKey, ...items);
54
  }
 
48
  const namespacedKey = this.namespace + key;
49
  const items = values.map(value => JSON.stringify({
50
  ...value,
 
51
  }));
52
  await this.redis.rpush(namespacedKey, ...items);
53
  }
chat.html CHANGED
@@ -219,7 +219,7 @@
219
  });
220
 
221
  async function loadChatHistory() {
222
- const response = await fetch("/v1/talk/history", { method: "GET" });
223
 
224
  if (!response.ok) {
225
  console.error("Failed to fetch chat history");
@@ -237,7 +237,7 @@
237
  }
238
 
239
  async function clearHistory() {
240
- const response = await fetch("/v1/talk/history", { method: "DELETE" });
241
 
242
  if (response.ok) {
243
  chatElement.replaceChildren(chatElement.firstChild);
 
219
  });
220
 
221
  async function loadChatHistory() {
222
+ const response = await fetch("/history", { method: "GET" });
223
 
224
  if (!response.ok) {
225
  console.error("Failed to fetch chat history");
 
237
  }
238
 
239
  async function clearHistory() {
240
+ const response = await fetch("/history", { method: "DELETE" });
241
 
242
  if (response.ok) {
243
  chatElement.replaceChildren(chatElement.firstChild);
functions.js CHANGED
@@ -6,7 +6,7 @@ const redis = new Redis();
6
 
7
 
8
  export const getCompanyCreds = async ({ company_id }) => {
9
- const creds = await redis.get(`${companyId}:creds`);
10
  if (!creds) {
11
  throw {
12
  message: "company creds not found"
@@ -42,7 +42,7 @@ export const createBrand = async ({ company_id, name, description, logo = "https
42
  banner: { portrait: logo, landscape: logo }
43
  }
44
  });
45
- return { message: "brand created", id: brands?.id };
46
  }
47
  export const getBrands = async ({ company_id }) => {
48
  const client = await initClient(company_id);
@@ -83,14 +83,14 @@ export const getLocations = async ({ company_id }) => {
83
  })
84
  return locations;
85
  }
86
- export const createLocation = async ({ company_id, address1, address2, pincode, state, city, number, country_code, gst_name, gst_no, latitude = 19.2762702, longitude = 72.8929, }) => {
87
  const client = await initClient(company_id);
88
  let locations = await client.companyProfile.createLocation({
89
  body: {
90
  name,
91
  display_name: name,
92
  code,
93
- company: parseInt(companyId),
94
  documents: [{
95
  type: "gst",
96
  legal_name: gst_name,
@@ -106,7 +106,7 @@ export const createLocation = async ({ company_id, address1, address2, pincode,
106
  "state": state,
107
  "latitude": latitude,
108
  "longitude": longitude,
109
- "landmark": landmark
110
  },
111
  manager: {
112
  "name": manager_name,
@@ -127,7 +127,7 @@ export const createLocation = async ({ company_id, address1, address2, pincode,
127
  }
128
  });
129
 
130
- return { message: "location added", id: locations?.id };
131
  }
132
  export const updateLocation = async ({ company_id, location_id, address1, address2, pincode, state, city, number, country_code, gst_name, gst_no, latitude = 19.2762702, longitude = 72.8929,
133
  }) => {
@@ -233,7 +233,7 @@ export const createApplication = async ({ company_id, brand_ids, name, subdomain
233
  })
234
 
235
 
236
- return { message: "location updated" };
237
  }
238
  export const createProduct = async ({ name, company_id, slug,
239
  seller_identifier,
 
6
 
7
 
8
  export const getCompanyCreds = async ({ company_id }) => {
9
+ const creds = await redis.get(`${company_id}:creds`);
10
  if (!creds) {
11
  throw {
12
  message: "company creds not found"
 
42
  banner: { portrait: logo, landscape: logo }
43
  }
44
  });
45
+ return { message: "brand created", id: brands?.uid };
46
  }
47
  export const getBrands = async ({ company_id }) => {
48
  const client = await initClient(company_id);
 
83
  })
84
  return locations;
85
  }
86
+ export const createLocation = async ({ name, company_id, address1, address2, pincode, state, city, country, number, country_code, gst_name, gst_no, latitude = 19.2762702, longitude = 72.8929, code, manager_name, email }) => {
87
  const client = await initClient(company_id);
88
  let locations = await client.companyProfile.createLocation({
89
  body: {
90
  name,
91
  display_name: name,
92
  code,
93
+ company: parseInt(company_id),
94
  documents: [{
95
  type: "gst",
96
  legal_name: gst_name,
 
106
  "state": state,
107
  "latitude": latitude,
108
  "longitude": longitude,
109
+ "landmark": ''
110
  },
111
  manager: {
112
  "name": manager_name,
 
127
  }
128
  });
129
 
130
+ return { message: "location added", id: locations?.uid };
131
  }
132
  export const updateLocation = async ({ company_id, location_id, address1, address2, pincode, state, city, number, country_code, gst_name, gst_no, latitude = 19.2762702, longitude = 72.8929,
133
  }) => {
 
233
  })
234
 
235
 
236
+ return { ...app };
237
  }
238
  export const createProduct = async ({ name, company_id, slug,
239
  seller_identifier,
index.js CHANGED
@@ -1,14 +1,44 @@
1
  import express from "express";
2
  import Redis from "ioredis";
3
  import { initClient } from './utils.js';
4
- import { errorHandler } from './middleware.js';
5
  import swaggerJSDoc from 'swagger-jsdoc';
6
  import yaml from 'js-yaml'
7
  import fs from 'fs';
8
  import { RedisListCache } from './cache.js';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  const listCache = new RedisListCache({ namespace: "fc" })
10
  const redis = new Redis();
11
-
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  const app = express();
13
  const port = process.env.PORT;
14
  app.use(express.json({}));
@@ -28,8 +58,8 @@ const options = {
28
  // Path to the API docs
29
  apis: ['./index.js'], // Adjust the path according to your file structure
30
  };
31
-
32
-
33
 
34
  /**
35
  * @swagger
@@ -489,7 +519,7 @@ app.post("/company/:companyId/brands", async (req, res, next) => {
489
  banner: { portrait: logo, landscape: logo }
490
  }
491
  });
492
- res.json({ message: "brand created", id: brands?.id })
493
  } catch (e) {
494
  next(e)
495
  }
@@ -743,7 +773,7 @@ app.post("/company/:companyId/locations", async (req, res, next) => {
743
  }
744
  });
745
 
746
- res.json({ message: "location added", id: locations?.id })
747
  } catch (e) {
748
  next(e)
749
  }
@@ -1222,407 +1252,422 @@ app.get('/talk', async (req, res, next) => {
1222
  res.send('Something needs to be fixed!');
1223
  }
1224
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1225
 
1226
  app.post(
1227
- '/openai',
1228
  async (req, res, next) => {
1229
  const functions = [
1230
  {
1231
- "type": "function",
1232
- "function": {
1233
- "name": "getCompanyCreds",
1234
- "description": "Retrieves credentials for a specific company based on its ID.",
1235
- "parameters": {
1236
- "type": "object",
1237
- "properties": {
1238
- "company_id": {
1239
- "type": "number",
1240
- "description": "Unique identifier of the company."
1241
- }
1242
- },
1243
- "required": ["company_id"]
1244
- }
1245
  }
1246
- },
1247
- {
1248
- "type": "function",
1249
- "function": {
1250
- "name": "createUpdateCompanyCreds",
1251
- "description": "Creates or updates credentials for a company.",
1252
- "parameters": {
1253
- "type": "object",
1254
- "properties": {
1255
- "company_id": {
1256
- "type": "number",
1257
- "description": "Unique identifier of the company."
1258
- },
1259
- "clientId": {
1260
- "type": "string",
1261
- "description": "Client ID for authentication."
1262
- },
1263
- "clientSecret": {
1264
- "type": "string",
1265
- "description": "Client secret for authentication."
1266
- }
1267
  },
1268
- "required": ["company_id", "clientId", "clientSecret"]
1269
- }
1270
- }
1271
- },
1272
- {
1273
- "type": "function",
1274
- "function": {
1275
- "name": "getApplications",
1276
- "description": "Retrieves a list of applications associated with a specific company ID.",
1277
- "parameters": {
1278
- "type": "object",
1279
- "properties": {
1280
- "company_id": {
1281
- "type": "number",
1282
- "description": "Unique identifier of the company."
1283
- }
1284
  },
1285
- "required": ["company_id"]
1286
- }
 
 
 
 
1287
  }
1288
- },
1289
- {
1290
- "type": "function",
1291
- "function": {
1292
- "name": "createBrand",
1293
- "description": "Creates a new brand under a specific company.",
1294
- "parameters": {
1295
- "type": "object",
1296
- "properties": {
1297
- "company_id": {
1298
- "type": "number",
1299
- "description": "Unique identifier of the company."
1300
- },
1301
- "name": {
1302
- "type": "string",
1303
- "description": "Name of the new brand."
1304
- },
1305
- "description": {
1306
- "type": "string",
1307
- "description": "Description of the new brand."
1308
- },
1309
- "logo": {
1310
- "type": "string",
1311
- "description": "URL of the brand's logo."
1312
- }
1313
- },
1314
- "required": ["company_id", "name", "description"]
1315
- }
1316
  }
1317
- },
1318
- {
1319
- "type": "function",
1320
- "function": {
1321
- "name": "updateBrand",
1322
- "description": "Updates the details of an existing brand within a company.",
1323
- "parameters": {
1324
- "type": "object",
1325
- "properties": {
1326
- "company_id": {
1327
- "type": "number",
1328
- "description": "Unique identifier of the company."
1329
- },
1330
- "brand_id": {
1331
- "type": "string",
1332
- "description": "Unique identifier of the brand to be updated."
1333
- },
1334
- "name": {
1335
- "type": "string",
1336
- "description": "New name for the brand."
1337
- },
1338
- "description": {
1339
- "type": "string",
1340
- "description": "New description for the brand."
1341
- },
1342
- "logo": {
1343
- "type": "string",
1344
- "description": "New URL for the brand's logo."
1345
- },
1346
  },
1347
- "required": ["company_id", "brand_id", "name", "description"]
1348
- }
1349
- }
1350
- },
1351
- {
1352
- "type": "function",
1353
- "function": {
1354
- "name": "getBrands",
1355
- "description": "Retrieves a list of all brands associated with a specific company.",
1356
- "parameters": {
1357
- "type": "object",
1358
- "properties": {
1359
- "company_id": {
1360
- "type": "number",
1361
- "description": "Unique identifier of the company for which brands are being retrieved."
1362
- }
1363
  },
1364
- "required": ["company_id"]
1365
- }
 
 
 
 
 
 
 
 
1366
  }
1367
- },
1368
- {
1369
- "type": "function",
1370
- "function": {
1371
- "name": "getLocations",
1372
- "description": "Retrieves a list of all locations associated with a specific company.",
1373
- "parameters": {
1374
- "type": "object",
1375
- "properties": {
1376
- "company_id": {
1377
- "type": "number",
1378
- "description": "Unique identifier of the company for which locations are being retrieved."
1379
- }
1380
  },
1381
- "required": ["company_id"]
1382
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1383
  }
1384
- },
1385
- {
1386
- "type": "function",
1387
- "function": {
1388
- "name": "createLocation",
1389
- "description": "Creates a new location for a specified company.",
1390
- "parameters": {
1391
- "type": "object",
1392
- "properties": {
1393
- "company_id": {
1394
- "type": "number",
1395
- "description": "Unique identifier of the company."
1396
- },
1397
- "address1": {
1398
- "type": "string",
1399
- "description": "Primary address line of the new location."
1400
- },
1401
- "address2": {
1402
- "type": "string",
1403
- "description": "Secondary address line of the new location."
1404
- },
1405
- "pincode": {
1406
- "type": "string",
1407
- "description": "Postal code of the new location."
1408
- },
1409
- "state": {
1410
- "type": "string",
1411
- "description": "State where the new location is situated."
1412
- },
1413
- "city": {
1414
- "type": "string",
1415
- "description": "City where the new location is situated."
1416
- },
1417
- "number": {
1418
- "type": "string",
1419
- "description": "Contact number for the new location."
1420
- },
1421
- "country_code": {
1422
- "type": "string",
1423
- "description": "Country code for the contact number."
1424
- },
1425
- "gst_name": {
1426
- "type": "string",
1427
- "description": "GST registered name associated with the new location."
1428
- },
1429
- "gst_no": {
1430
- "type": "string",
1431
- "description": "GST number associated with the new location."
1432
- },
1433
- "latitude": {
1434
- "type": "number",
1435
- "description": "Latitude coordinate for the new location."
1436
- },
1437
- "longitude": {
1438
- "type": "number",
1439
- "description": "Longitude coordinate for the new location."
1440
- }
1441
  },
1442
- "required": ["company_id", "address1", "city", "state", "pincode", "country_code", "gst_name", "gst_no"]
1443
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1444
  }
1445
- },
1446
- {
1447
- "type": "function",
1448
- "function": {
1449
- "name": "updateLocation",
1450
- "description": "update a existing location for a specified company.",
1451
- "parameters": {
1452
- "type": "object",
1453
- "properties": {
1454
- "company_id": {
1455
- "type": "number",
1456
- "description": "Unique identifier of the company."
1457
- },
1458
- "location_id": {
1459
- "type": "number",
1460
- "description": "Unique identifier of the location."
1461
- },
1462
- "address1": {
1463
- "type": "string",
1464
- "description": "Primary address line of the new location."
1465
- },
1466
- "address2": {
1467
- "type": "string",
1468
- "description": "Secondary address line of the new location."
1469
- },
1470
- "pincode": {
1471
- "type": "string",
1472
- "description": "Postal code of the new location."
1473
- },
1474
- "state": {
1475
- "type": "string",
1476
- "description": "State where the new location is situated."
1477
- },
1478
- "city": {
1479
- "type": "string",
1480
- "description": "City where the new location is situated."
1481
- },
1482
- "number": {
1483
- "type": "string",
1484
- "description": "Contact number for the new location."
1485
- },
1486
- "country_code": {
1487
- "type": "string",
1488
- "description": "Country code for the contact number."
1489
- },
1490
- "gst_name": {
1491
- "type": "string",
1492
- "description": "GST registered name associated with the new location."
1493
- },
1494
- "gst_no": {
1495
- "type": "string",
1496
- "description": "GST number associated with the new location."
1497
- },
1498
- "latitude": {
1499
- "type": "number",
1500
- "description": "Latitude coordinate for the new location."
1501
- },
1502
- "longitude": {
1503
- "type": "number",
1504
- "description": "Longitude coordinate for the new location."
1505
- }
1506
  },
1507
- "required": ["company_id", 'brand_id', "address1", "city", "state", "pincode", "country_code", "gst_name", "gst_no"]
1508
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1509
  }
1510
- },
1511
- {
1512
- "type": "function",
1513
- "function": {
1514
- "name": "createProduct",
1515
- "description": "Creates a new product in the company's catalog.",
1516
- "parameters": {
1517
- "type": "object",
1518
- "properties": {
1519
- "name": {
1520
- "type": "string",
1521
- "description": "Name of the new product."
1522
- },
1523
- "company_id": {
1524
- "type": "number",
1525
- "description": "Unique identifier of the company."
1526
- },
1527
- "slug": {
1528
- "type": "string",
1529
- "description": "SEO-friendly URL segment for the product."
1530
- },
1531
- "seller_identifier": {
1532
- "type": "string",
1533
- "description": "Unique identifier for the seller of the product."
1534
- },
1535
- "brand_id": {
1536
- "type": "number",
1537
- "description": "Unique identifier of the brand associated with the product."
1538
- },
1539
- "mrp": {
1540
- "type": "number",
1541
- "description": "Maximum Retail Price of the product."
1542
- },
1543
- "selling_price": {
1544
- "type": "number",
1545
- "description": "Selling price of the product."
1546
- }
1547
  },
1548
- "required": ["name", "company_id", "slug", "seller_identifier", "brand_id"]
1549
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1550
  }
1551
- },
1552
- {
1553
- "type": "function",
1554
- "function": {
1555
- "name": "createInventory",
1556
- "description": "Creates a new inventory record for a specific product in a company.",
1557
- "parameters": {
1558
- "type": "object",
1559
- "properties": {
1560
- "company_id": {
1561
- "type": "number",
1562
- "description": "Unique identifier of the company."
1563
- },
1564
- "product_id": {
1565
- "type": "number",
1566
- "description": "Unique identifier of the product."
1567
- },
1568
- "seller_identifier": {
1569
- "type": "string",
1570
- "description": "Unique identifier for the seller of the product."
1571
- },
1572
- "location_id": {
1573
- "type": "number",
1574
- "description": "Unique identifier of the location where the inventory is stored."
1575
- },
1576
- "mrp": {
1577
- "type": "number",
1578
- "description": "Maximum Retail Price of the product."
1579
- },
1580
- "selling_price": {
1581
- "type": "number",
1582
- "description": "Selling price of the product."
1583
- }
1584
  },
1585
- "required": ["company_id", "product_id", "seller_identifier", "location_id"]
1586
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1587
  }
1588
- },
1589
- {
1590
- "type": "function",
1591
- "function": {
1592
- "name": "createApplication",
1593
- "description": "Creates a new application for a specified company.",
1594
- "parameters": {
1595
- "type": "object",
1596
- "properties": {
1597
- "company_id": {
1598
- "type": "number",
1599
- "description": "Unique identifier of the company."
1600
- },
1601
- "brand_ids": {
1602
- "type": "array",
1603
- "description": "Array of brand IDs associated with the application.",
1604
- "items": {
1605
- "type": "number"
1606
- }
1607
- },
1608
- "name": {
1609
- "type": "string",
1610
- "description": "Name of the new application."
1611
- },
1612
- "subdomain": {
1613
- "type": "string",
1614
- "description": "Subdomain for the application's URL."
1615
  }
1616
  },
1617
- "required": ["company_id", "brand_ids", "name", "subdomain"]
1618
- }
 
 
 
 
 
 
 
 
1619
  }
1620
  }
 
1621
  ];
1622
 
1623
  const messages = [{
1624
  role: 'system',
1625
- content: 'You are Jio Copilot. Introducing an all-encompassing tool, designed to seamlessly interact with TiraBeauty, JioCinema, JioMart, and JioFiber, catering to multiple facets of your digital lifestyle.\nOur JioMart integration simplifies your online shopping journey, providing a wide selection of products, from clothing and electronics to grocery items, all in one convenient location. JioMart can help to buy ingredients from recipes. Search each ingredient separately.\nWith TiraBeauty functionality, you can explore a wide array of health and beauty products, effortlessly manage your shopping cart, and share your cart selections via a QR code within the ecosystem of www.tirabeauty.com - your comprehensive ecommerce destination for beauty products and accessories.\nThe JioCinema feature takes you on an immersive streaming adventure, offering access to a diverse range of television shows, movies, sports content, and much more. Easily search and stream content to match your mood, directly from this interface.\nFinally, the JioFiber functionality empowers you to navigate through a range of lightning-fast internet and data plans from this leading broadband service provider. Explore and choose from a comprehensive list of prepaid and postpaid plans to meet your connectivity needs.\nEquip yourself with this multifunctional tool and experience a streamlined, efficient digital experience across a variety of platforms.'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1626
  }];
1627
  const session = req.jio_copilot_anonymous_session;
1628
  if (session) {
@@ -1640,7 +1685,7 @@ app.post(
1640
  res.flushHeaders();
1641
 
1642
  try {
1643
- // await nextStep(session, messages, skills, functions, res);
1644
  res.end();
1645
  } catch (error) {
1646
  if (error.code === 'context_length_exceeded') {
@@ -1665,66 +1710,68 @@ app.listen(port, async () => {
1665
  await fs.writeFileSync("swagger.json", JSON.stringify(swaggerSpec, null, 2), 'utf-8')
1666
  });
1667
 
1668
- // async function nextStep(session, messages, skills, functions, res) {
1669
- // const conn = new OpenAI({ apiKey: "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" });
1670
- // const streamResponse = await conn
1671
- // .chat.completions.create({
1672
- // model: 'gpt-4-1106-preview',
1673
- // messages,
1674
- // functions,
1675
- // function_call: 'auto',
1676
- // temperature: 0.5,
1677
- // stream: true
1678
- // }).catch(async err => {
1679
- // console.error(err);
1680
- // const openAIError = new Error(err.error.message);
1681
- // openAIError.code = err.error.code;
1682
- // throw openAIError;
1683
- // });
1684
 
1685
- // let finalMessage = '';
1686
- // const functionCall = { name: null, arguments: '' };
1687
 
1688
- // for await (const line of streamResponse) {
1689
- // const choice = line.choices[0];
1690
- // if (choice.delta.function_call) {
1691
- // const fc = choice.delta.function_call;
1692
- // if (fc.name) {
1693
- // // res.write(`Detected Function: ${fc.name}\n\n`);
1694
- // // res.flush();
1695
- // functionCall.name = fc.name;
1696
- // }
1697
- // if (fc.arguments) {
1698
- // functionCall.arguments += fc.arguments;
1699
- // }
1700
- // } else if (!choice.finish_reason && choice.delta.content) {
1701
- // finalMessage += choice.delta.content;
1702
- // res.write(`${choice.delta.content}`);
1703
- // res.flush();
1704
- // }
1705
- // }
 
 
 
 
 
 
 
1706
 
1707
- // if (!functionCall.name) {
1708
- // const assistantMessage = { role: 'assistant', content: finalMessage };
1709
- // messages.push(assistantMessage);
1710
- // await listCache.setItems(session, assistantMessage);
1711
- // return;
1712
- // }
1713
 
1714
- // const functionName = functionCall.name;
1715
- // const args = JSON.parse(functionCall.arguments);
1716
- // if (!skills[functionName]) {
1717
- // throw new Error(`No skill implemented for this function: ${functionName}`);
1718
- // }
1719
 
1720
- // // res.write(`Executing Function: ${functionName} with arguments ${JSON.stringify(args)} \n\n`);
1721
- // // res.flush();
1722
- // const skill = new skills[functionName]({ ...args, headers: { 'openai-ephemeral-user-id': session } });
1723
- // const skillRes = await skill.performAction();
1724
- // if (skillRes) {
1725
- // const functionMessage = { role: 'function', name: functionName, content: JSON.stringify(skillRes) };
1726
- // messages.push(functionMessage);
1727
- // await listCache.setItems(session, functionMessage);
1728
- // }
1729
- // return nextStep(conn, session, messages, skills, functions, res);
1730
- // }
 
1
  import express from "express";
2
  import Redis from "ioredis";
3
  import { initClient } from './utils.js';
4
+ import { errorHandler, setJioCopilotSessionCookie } from './middleware.js';
5
  import swaggerJSDoc from 'swagger-jsdoc';
6
  import yaml from 'js-yaml'
7
  import fs from 'fs';
8
  import { RedisListCache } from './cache.js';
9
+ import {
10
+ getApplications,
11
+ createApplication,
12
+ getLocations,
13
+ createLocation,
14
+ updateLocation,
15
+ getBrands,
16
+ createBrand,
17
+ updateBrand,
18
+ createProduct,
19
+ createInventory,
20
+ getCompanyCreds,
21
+ createUpdateCompanyCreds
22
+ } from './functions.js'
23
+ import OpenAI from 'openai';
24
+ import compression from 'compression';
25
+ import cookieParser from 'cookie-parser';
26
  const listCache = new RedisListCache({ namespace: "fc" })
27
  const redis = new Redis();
28
+ const skills = {
29
+ getApplications,
30
+ createApplication,
31
+ getLocations,
32
+ createLocation,
33
+ updateLocation,
34
+ getBrands,
35
+ createBrand,
36
+ updateBrand,
37
+ createProduct,
38
+ createInventory,
39
+ getCompanyCreds,
40
+ createUpdateCompanyCreds
41
+ }
42
  const app = express();
43
  const port = process.env.PORT;
44
  app.use(express.json({}));
 
58
  // Path to the API docs
59
  apis: ['./index.js'], // Adjust the path according to your file structure
60
  };
61
+ app.use(compression())
62
+ app.use(cookieParser())
63
 
64
  /**
65
  * @swagger
 
519
  banner: { portrait: logo, landscape: logo }
520
  }
521
  });
522
+ res.json({ message: "brand created", id: brands?.uid })
523
  } catch (e) {
524
  next(e)
525
  }
 
773
  }
774
  });
775
 
776
+ res.json({ message: "location added", id: locations?.uid })
777
  } catch (e) {
778
  next(e)
779
  }
 
1252
  res.send('Something needs to be fixed!');
1253
  }
1254
  });
1255
+ app.get('/history', setJioCopilotSessionCookie, async (req, res) => {
1256
+ const session = req.jio_copilot_anonymous_session;
1257
+ let messages = [];
1258
+ if (session) {
1259
+ messages = await listCache.getAll(session);
1260
+ }
1261
+ messages = messages.filter(message => message.role === 'user' || message.role === 'assistant');
1262
+ res.json([{ role: 'assistant', content: 'Greetings! I\'m Jio Copilot, your digital aid for Jio platforms like TiraBeauty, JioCinema, JioMart, and JioFiber. Here to help with shopping, product exploration, content streaming, and internet/data plan navigation. How may I assist you today?' }, ...messages]);
1263
+ });
1264
+
1265
+ app.delete('/history', setJioCopilotSessionCookie, async (req, res) => {
1266
+ const session = req.jio_copilot_anonymous_session;
1267
+ if (session) {
1268
+ await listCache.clear(session);
1269
+ }
1270
+ res.json({ success: true });
1271
+ });
1272
 
1273
  app.post(
1274
+ '/openai', setJioCopilotSessionCookie,
1275
  async (req, res, next) => {
1276
  const functions = [
1277
  {
1278
+ "name": "getCompanyCreds",
1279
+ "description": "Retrieves credentials for a specific company based on its ID.",
1280
+ "parameters": {
1281
+ "type": "object",
1282
+ "properties": {
1283
+ "company_id": {
1284
+ "type": "number",
1285
+ "description": "Unique identifier of the company."
1286
+ }
1287
+ },
1288
+ "required": ["company_id"]
 
 
 
1289
  }
1290
+ }, {
1291
+ "name": "createUpdateCompanyCreds",
1292
+ "description": "Creates or updates credentials for a company.",
1293
+ "parameters": {
1294
+ "type": "object",
1295
+ "properties": {
1296
+ "company_id": {
1297
+ "type": "number",
1298
+ "description": "Unique identifier of the company."
 
 
 
 
 
 
 
 
 
 
 
 
1299
  },
1300
+ "clientId": {
1301
+ "type": "string",
1302
+ "description": "Client ID for authentication."
 
 
 
 
 
 
 
 
 
 
 
 
 
1303
  },
1304
+ "clientSecret": {
1305
+ "type": "string",
1306
+ "description": "Client secret for authentication."
1307
+ }
1308
+ },
1309
+ "required": ["company_id", "clientId", "clientSecret"]
1310
  }
1311
+ }, {
1312
+ "name": "getApplications",
1313
+ "description": "Retrieves a list of applications associated with a specific company ID.",
1314
+ "parameters": {
1315
+ "type": "object",
1316
+ "properties": {
1317
+ "company_id": {
1318
+ "type": "number",
1319
+ "description": "Unique identifier of the company."
1320
+ }
1321
+ },
1322
+ "required": ["company_id"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1323
  }
1324
+ }, {
1325
+ "name": "createBrand",
1326
+ "description": "Creates a new brand under a specific company.",
1327
+ "parameters": {
1328
+ "type": "object",
1329
+ "properties": {
1330
+ "company_id": {
1331
+ "type": "number",
1332
+ "description": "Unique identifier of the company."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1333
  },
1334
+ "name": {
1335
+ "type": "string",
1336
+ "description": "Name of the new brand."
 
 
 
 
 
 
 
 
 
 
 
 
 
1337
  },
1338
+ "description": {
1339
+ "type": "string",
1340
+ "description": "Description of the new brand."
1341
+ },
1342
+ "logo": {
1343
+ "type": "string",
1344
+ "description": "URL of the brand's logo."
1345
+ }
1346
+ },
1347
+ "required": ["company_id", "name", "description"]
1348
  }
1349
+ }, {
1350
+ "name": "updateBrand",
1351
+ "description": "Updates the details of an existing brand within a company.",
1352
+ "parameters": {
1353
+ "type": "object",
1354
+ "properties": {
1355
+ "company_id": {
1356
+ "type": "number",
1357
+ "description": "Unique identifier of the company."
 
 
 
 
1358
  },
1359
+ "brand_id": {
1360
+ "type": "string",
1361
+ "description": "Unique identifier of the brand to be updated."
1362
+ },
1363
+ "name": {
1364
+ "type": "string",
1365
+ "description": "New name for the brand."
1366
+ },
1367
+ "description": {
1368
+ "type": "string",
1369
+ "description": "New description for the brand."
1370
+ },
1371
+ "logo": {
1372
+ "type": "string",
1373
+ "description": "New URL for the brand's logo."
1374
+ },
1375
+ },
1376
+ "required": ["company_id", "brand_id", "name", "description"]
1377
  }
1378
+ }, {
1379
+ "name": "getBrands",
1380
+ "description": "Retrieves a list of all brands associated with a specific company.",
1381
+ "parameters": {
1382
+ "type": "object",
1383
+ "properties": {
1384
+ "company_id": {
1385
+ "type": "number",
1386
+ "description": "Unique identifier of the company for which brands are being retrieved."
1387
+ }
1388
+ },
1389
+ "required": ["company_id"]
1390
+ }
1391
+ }, {
1392
+ "name": "getLocations",
1393
+ "description": "Retrieves a list of all locations associated with a specific company.",
1394
+ "parameters": {
1395
+ "type": "object",
1396
+ "properties": {
1397
+ "company_id": {
1398
+ "type": "number",
1399
+ "description": "Unique identifier of the company for which locations are being retrieved."
1400
+ }
1401
+ },
1402
+ "required": ["company_id"]
1403
+ }
1404
+ }, {
1405
+ "name": "createLocation",
1406
+ "description": "Creates a new location for a specified company.",
1407
+ "parameters": {
1408
+ "type": "object",
1409
+ "properties": {
1410
+ "name": {
1411
+ "type": "string",
1412
+ "description": "name of the location."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1413
  },
1414
+ "code": {
1415
+ "type": "string",
1416
+ "description": "a unique code name."
1417
+ },
1418
+ "company_id": {
1419
+ "type": "number",
1420
+ "description": "Unique identifier of the company."
1421
+ },
1422
+ "address1": {
1423
+ "type": "string",
1424
+ "description": "Primary address line of the new location."
1425
+ },
1426
+ "address2": {
1427
+ "type": "string",
1428
+ "description": "Secondary address line of the new location."
1429
+ },
1430
+ "pincode": {
1431
+ "type": "number",
1432
+ "description": "Postal code of the new location."
1433
+ },
1434
+ "state": {
1435
+ "type": "string",
1436
+ "description": "State where the new location is situated."
1437
+ },
1438
+ "country": {
1439
+ "type": "string",
1440
+ "description": "State where the new location is situated."
1441
+ },
1442
+ "city": {
1443
+ "type": "string",
1444
+ "description": "City where the new location is situated."
1445
+ },
1446
+ "number": {
1447
+ "type": "string",
1448
+ "description": "Contact number for the new location. 10 digits"
1449
+ },
1450
+ "country_code": {
1451
+ "type": "string",
1452
+ "description": "Country code for the contact number eg 91"
1453
+ },
1454
+ "gst_name": {
1455
+ "type": "string",
1456
+ "description": "GST registered name associated with the new location."
1457
+ },
1458
+ "gst_no": {
1459
+ "type": "string",
1460
+ "description": "GST number associated with the new location."
1461
+ },
1462
+ "latitude": {
1463
+ "type": "number",
1464
+ "description": "Latitude coordinate for the new location."
1465
+ },
1466
+ "longitude": {
1467
+ "type": "number",
1468
+ "description": "Longitude coordinate for the new location."
1469
+ },
1470
+ "manager_name": {
1471
+ "type": "string",
1472
+ "description": "name of the store manager."
1473
+ },
1474
+ "email": {
1475
+ "type": "string",
1476
+ "description": "email of the store manager."
1477
+ }
1478
+ },
1479
+ "required": ["company_id", "address1", "city", "state", 'country', "pincode", "gst_name", "gst_no", 'manager_name', 'email', 'code', 'country_code', 'number']
1480
  }
1481
+ }, {
1482
+ "name": "updateLocation",
1483
+ "description": "update a existing location for a specified company.",
1484
+ "parameters": {
1485
+ "type": "object",
1486
+ "properties": {
1487
+ "company_id": {
1488
+ "type": "number",
1489
+ "description": "Unique identifier of the company."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1490
  },
1491
+ "location_id": {
1492
+ "type": "number",
1493
+ "description": "Unique identifier of the location."
1494
+ },
1495
+ "address1": {
1496
+ "type": "string",
1497
+ "description": "Primary address line of the new location."
1498
+ },
1499
+ "address2": {
1500
+ "type": "string",
1501
+ "description": "Secondary address line of the new location."
1502
+ },
1503
+ "pincode": {
1504
+ "type": "string",
1505
+ "description": "Postal code of the new location."
1506
+ },
1507
+ "state": {
1508
+ "type": "string",
1509
+ "description": "State where the new location is situated."
1510
+ },
1511
+ "city": {
1512
+ "type": "string",
1513
+ "description": "City where the new location is situated."
1514
+ },
1515
+ "number": {
1516
+ "type": "string",
1517
+ "description": "Contact number for the new location."
1518
+ },
1519
+ "country_code": {
1520
+ "type": "string",
1521
+ "description": "Country code for the contact number."
1522
+ },
1523
+ "gst_name": {
1524
+ "type": "string",
1525
+ "description": "GST registered name associated with the new location."
1526
+ },
1527
+ "gst_no": {
1528
+ "type": "string",
1529
+ "description": "GST number associated with the new location."
1530
+ },
1531
+ "latitude": {
1532
+ "type": "number",
1533
+ "description": "Latitude coordinate for the new location."
1534
+ },
1535
+ "longitude": {
1536
+ "type": "number",
1537
+ "description": "Longitude coordinate for the new location."
1538
+ }
1539
+ },
1540
+ "required": ["company_id", 'brand_id', "address1", "city", "state", "pincode", "country_code", "gst_name", "gst_no"]
1541
  }
1542
+ }, {
1543
+ "name": "createProduct",
1544
+ "description": "Creates a new product in the company's catalog.",
1545
+ "parameters": {
1546
+ "type": "object",
1547
+ "properties": {
1548
+ "name": {
1549
+ "type": "string",
1550
+ "description": "Name of the new product."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1551
  },
1552
+ "company_id": {
1553
+ "type": "number",
1554
+ "description": "Unique identifier of the company."
1555
+ },
1556
+ "slug": {
1557
+ "type": "string",
1558
+ "description": "SEO-friendly URL segment for the product."
1559
+ },
1560
+ "seller_identifier": {
1561
+ "type": "string",
1562
+ "description": "Unique identifier for the seller of the product."
1563
+ },
1564
+ "brand_id": {
1565
+ "type": "number",
1566
+ "description": "Unique identifier of the brand associated with the product."
1567
+ },
1568
+ "mrp": {
1569
+ "type": "number",
1570
+ "description": "Maximum Retail Price of the product."
1571
+ },
1572
+ "selling_price": {
1573
+ "type": "number",
1574
+ "description": "Selling price of the product."
1575
+ }
1576
+ },
1577
+ "required": ["name", "company_id", "slug", "seller_identifier", "brand_id"]
1578
  }
1579
+ }, {
1580
+ "name": "createInventory",
1581
+ "description": "Creates a new inventory record for a specific product in a company.",
1582
+ "parameters": {
1583
+ "type": "object",
1584
+ "properties": {
1585
+ "company_id": {
1586
+ "type": "number",
1587
+ "description": "Unique identifier of the company."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1588
  },
1589
+ "product_id": {
1590
+ "type": "number",
1591
+ "description": "Unique identifier of the product."
1592
+ },
1593
+ "seller_identifier": {
1594
+ "type": "string",
1595
+ "description": "Unique identifier for the seller of the product."
1596
+ },
1597
+ "location_id": {
1598
+ "type": "number",
1599
+ "description": "Unique identifier of the location where the inventory is stored."
1600
+ },
1601
+ "mrp": {
1602
+ "type": "number",
1603
+ "description": "Maximum Retail Price of the product."
1604
+ },
1605
+ "selling_price": {
1606
+ "type": "number",
1607
+ "description": "Selling price of the product."
1608
+ }
1609
+ },
1610
+ "required": ["company_id", "product_id", "seller_identifier", "location_id"]
1611
  }
1612
+ }, {
1613
+ "name": "createApplication",
1614
+ "description": "Creates a new application for a specified company.",
1615
+ "parameters": {
1616
+ "type": "object",
1617
+ "properties": {
1618
+ "company_id": {
1619
+ "type": "number",
1620
+ "description": "Unique identifier of the company."
1621
+ },
1622
+ "brand_ids": {
1623
+ "type": "array",
1624
+ "description": "Array of brand IDs associated with the application.",
1625
+ "items": {
1626
+ "type": "number"
 
 
 
 
 
 
 
 
 
 
 
 
1627
  }
1628
  },
1629
+ "name": {
1630
+ "type": "string",
1631
+ "description": "Name of the new application."
1632
+ },
1633
+ "subdomain": {
1634
+ "type": "string",
1635
+ "description": "Subdomain for the application's URL."
1636
+ }
1637
+ },
1638
+ "required": ["company_id", "brand_ids", "name", "subdomain"]
1639
  }
1640
  }
1641
+
1642
  ];
1643
 
1644
  const messages = [{
1645
  role: 'system',
1646
+ content: `you are an onboarding buddy chatbot for fynd platform, you help logged in userd who have access to a company to clear their salechannels/ websites, always start by asking the same. when asking questions from the use ask one at a time, ask user for one input at a time. You must initiate the conversation always.
1647
+
1648
+ NOTEs FOR YOU:
1649
+ always check if you have the credentials for a company_id
1650
+ you always show the function name and the generated JSON args when functions are called
1651
+ platform domain is platfrom.fyndx5.de
1652
+ to get started yo need to get the companyId, clientId and secret from the user. always check if the credentials exist, if not save them
1653
+ to create a sales channel you require at least one brand. fetch and show the brands
1654
+ to create a product you need a brand. fetch and show the brand
1655
+ once the product is created it takes some time reflect in the db before the inventory is added
1656
+ for a product to be visible on your sales channel you must also add inventory for it
1657
+ stores, location, warehouses mean the same,
1658
+ seller_identifier, item_code are unique indentifier of the product, both may be the same
1659
+ assume seller_identifier is a string separated by _ and in all caps always.
1660
+ assume data if possible
1661
+
1662
+ UI Links: always give the ui link when performing actions
1663
+ company credentials create link = https://platform.fyndx5.de/company/{companyId}/apis/oauthclient/create
1664
+ company homepage url = https://platform.fyndx5.de/company/{companyId}/home
1665
+ company profile url = https://platform.fyndx5.de/company/{companyId}/profile
1666
+ company location url = https://platform.fyndx5.de/company/{companyId}/profile/edit-store/{locationId}
1667
+ company brand url = https://platform.fyndx5.de/company/{companyId}/profile/edit-brand/{brandId}
1668
+ company sales channels url = https://platform.fyndx5.de/company/{companyId}/application/{applicationId}/products
1669
+ company product listing url= https://platform.fyndx5.de/company/{companyId}/products/list
1670
+ company product url = https://platform.fyndx5.de/company/{companyId}/products/{itemId}/edit.`
1671
  }];
1672
  const session = req.jio_copilot_anonymous_session;
1673
  if (session) {
 
1685
  res.flushHeaders();
1686
 
1687
  try {
1688
+ await nextStep(session, messages, skills, functions, res);
1689
  res.end();
1690
  } catch (error) {
1691
  if (error.code === 'context_length_exceeded') {
 
1710
  await fs.writeFileSync("swagger.json", JSON.stringify(swaggerSpec, null, 2), 'utf-8')
1711
  });
1712
 
1713
+ async function nextStep(session, messages, skills, functions, res) {
1714
+ const conn = new OpenAI({ apiKey: "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" });
1715
+ const streamResponse = await conn
1716
+ .chat.completions.create({
1717
+ model: 'gpt-4',
1718
+ messages,
1719
+ functions,
1720
+ function_call: 'auto',
1721
+ temperature: 0.5,
1722
+ stream: true
1723
+ }).catch(async err => {
1724
+ console.error(err);
1725
+ const openAIError = new Error(err.error.message);
1726
+ openAIError.code = err.error.code;
1727
+ throw openAIError;
1728
+ });
1729
 
1730
+ let finalMessage = '';
1731
+ const functionCall = { name: null, arguments: '' };
1732
 
1733
+ for await (const line of streamResponse) {
1734
+ const choice = line.choices[0];
1735
+ if (choice.delta.function_call) {
1736
+ const fc = choice.delta.function_call;
1737
+ if (fc.name) {
1738
+ // res.write(`Detected Function: ${fc.name}\n\n`);
1739
+ // res.flush();
1740
+ functionCall.name = fc.name;
1741
+ }
1742
+ if (fc.arguments) {
1743
+ functionCall.arguments += fc.arguments;
1744
+ }
1745
+ } else if (!choice.finish_reason && choice.delta.content) {
1746
+ finalMessage += choice.delta.content;
1747
+ res.write(`${choice.delta.content}`);
1748
+ res.flush();
1749
+ }
1750
+ }
1751
+
1752
+ if (!functionCall.name) {
1753
+ const assistantMessage = { role: 'assistant', content: finalMessage };
1754
+ messages.push(assistantMessage);
1755
+ await listCache.setItems(session, assistantMessage);
1756
+ return;
1757
+ }
1758
 
1759
+ const functionName = functionCall.name;
1760
+ const args = JSON.parse(functionCall.arguments);
1761
+ if (!skills[functionName]) {
1762
+ throw new Error(`No skill implemented for this function: ${functionName}`);
1763
+ }
 
1764
 
1765
+ // res.write(`Executing Function: ${functionName} with arguments ${JSON.stringify(args)} \n\n`);
1766
+ // res.flush();
1767
+ const skillRes = await skills[functionName]({ ...args, headers: { 'openai-ephemeral-user-id': session } }).catch(e => {
1768
+ return { message: e }
1769
+ });
1770
 
1771
+ if (skillRes) {
1772
+ const functionMessage = { role: 'function', name: functionName, content: JSON.stringify(skillRes) };
1773
+ messages.push(functionMessage);
1774
+ await listCache.setItems(session, functionMessage);
1775
+ }
1776
+ return nextStep(session, messages, skills, functions, res);
1777
+ }
 
 
 
 
middleware.js CHANGED
@@ -1,3 +1,33 @@
 
 
1
  export const errorHandler = (err, req, res, next) => {
2
  res.status(err?.code || err?.status || 500).json({ ...err, message: err?.message, });
3
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { nanoid } from 'nanoid';
2
+
3
  export const errorHandler = (err, req, res, next) => {
4
  res.status(err?.code || err?.status || 500).json({ ...err, message: err?.message, });
5
+ }
6
+
7
+ export const setJioCopilotSessionCookie = async (req, res, next = () => { }) => {
8
+ let session = req?.cookies?.['__jc_session'];
9
+ if (session && (!session.startsWith('jc-') || session.length !== 33)) {
10
+ session = null;
11
+ }
12
+ if (!session) {
13
+ session = `jc-${nanoid()}-${encodeTimestampToBase36()}`;
14
+ const validity = 7 * 24 * 3600; // 7 days
15
+ const cookieOpts = {
16
+ domain: `${'local.'}${'copilotz0.de'}`,
17
+ expires: new Date((Date.now() / 1000 + validity) * 1000),
18
+ httpOnly: true,
19
+ secure: false,
20
+ sameSite: 'Lax'
21
+ };
22
+ res.cookie('__jc_session', session, cookieOpts);
23
+ }
24
+ req.jio_copilot_anonymous_session = session;
25
+ // res.end()
26
+ next();
27
+ };
28
+
29
+ export const encodeTimestampToBase36 = (timestamp) => {
30
+ const currentTimestamp = timestamp || Date.now();
31
+ const base36Timestamp = currentTimestamp.toString(36);
32
+ return base36Timestamp;
33
+ };
package.json CHANGED
@@ -10,11 +10,14 @@
10
  },
11
  "dependencies": {
12
  "@gofynd/fdk-client-javascript": "^1.3.10-beta.1",
 
13
  "convict": "^6.2.4",
 
14
  "eslint": "^8.55.0",
15
  "express": "^4.18.2",
16
  "ioredis": "^5.3.2",
17
  "js-yaml": "^4.1.0",
 
18
  "openai": "^4.20.1",
19
  "swagger-jsdoc": "^6.2.8"
20
  }
 
10
  },
11
  "dependencies": {
12
  "@gofynd/fdk-client-javascript": "^1.3.10-beta.1",
13
+ "compression": "^1.7.4",
14
  "convict": "^6.2.4",
15
+ "cookie-parser": "^1.4.6",
16
  "eslint": "^8.55.0",
17
  "express": "^4.18.2",
18
  "ioredis": "^5.3.2",
19
  "js-yaml": "^4.1.0",
20
+ "nanoid": "^5.0.4",
21
  "openai": "^4.20.1",
22
  "swagger-jsdoc": "^6.2.8"
23
  }
utils.js CHANGED
@@ -14,7 +14,8 @@ export const initClient = async (companyId) => {
14
  apiKey: creds.clientId,
15
  apiSecret: creds.clientSecret,
16
  useAutoRenewTimer: true,
17
- domain: "https://api.fyndx5.de"
 
18
  }
19
  const platformConfig = new PlatformConfig(config)
20
  let token = await redis.get(`${companyId}:client_token`)
 
14
  apiKey: creds.clientId,
15
  apiSecret: creds.clientSecret,
16
  useAutoRenewTimer: true,
17
+ domain: "https://api.fyndx5.de",
18
+ logLevel: "DEBUG"
19
  }
20
  const platformConfig = new PlatformConfig(config)
21
  let token = await redis.get(`${companyId}:client_token`)
yarn.lock CHANGED
@@ -208,7 +208,7 @@ abort-controller@^3.0.0:
208
  dependencies:
209
  event-target-shim "^5.0.0"
210
 
211
- accepts@~1.3.8:
212
  version "1.3.8"
213
  resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
214
  integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==
@@ -314,6 +314,11 @@ brace-expansion@^1.1.7:
314
  balanced-match "^1.0.0"
315
  concat-map "0.0.1"
316
 
 
 
 
 
 
317
  bytes@3.1.2:
318
  version "3.1.2"
319
  resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
@@ -390,6 +395,26 @@ commander@^10.0.0:
390
  resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06"
391
  integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==
392
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
393
  concat-map@0.0.1:
394
  version "0.0.1"
395
  resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
@@ -415,11 +440,24 @@ convict@^6.2.4:
415
  lodash.clonedeep "^4.5.0"
416
  yargs-parser "^20.2.7"
417
 
 
 
 
 
 
 
 
 
418
  cookie-signature@1.0.6:
419
  version "1.0.6"
420
  resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
421
  integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==
422
 
 
 
 
 
 
423
  cookie@0.5.0:
424
  version "0.5.0"
425
  resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
@@ -1096,7 +1134,7 @@ methods@~1.1.2:
1096
  resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
1097
  integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==
1098
 
1099
- mime-db@1.52.0:
1100
  version "1.52.0"
1101
  resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
1102
  integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
@@ -1135,6 +1173,11 @@ ms@2.1.3, ms@^2.0.0:
1135
  resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
1136
  integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
1137
 
 
 
 
 
 
1138
  natural-compare@^1.4.0:
1139
  version "1.4.0"
1140
  resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
@@ -1169,6 +1212,11 @@ on-finished@2.4.1:
1169
  dependencies:
1170
  ee-first "1.1.1"
1171
 
 
 
 
 
 
1172
  once@^1.3.0:
1173
  version "1.4.0"
1174
  resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
@@ -1340,6 +1388,11 @@ run-parallel@^1.1.9:
1340
  dependencies:
1341
  queue-microtask "^1.2.2"
1342
 
 
 
 
 
 
1343
  safe-buffer@5.2.1:
1344
  version "5.2.1"
1345
  resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
 
208
  dependencies:
209
  event-target-shim "^5.0.0"
210
 
211
+ accepts@~1.3.5, accepts@~1.3.8:
212
  version "1.3.8"
213
  resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
214
  integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==
 
314
  balanced-match "^1.0.0"
315
  concat-map "0.0.1"
316
 
317
+ bytes@3.0.0:
318
+ version "3.0.0"
319
+ resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
320
+ integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==
321
+
322
  bytes@3.1.2:
323
  version "3.1.2"
324
  resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
 
395
  resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06"
396
  integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==
397
 
398
+ compressible@~2.0.16:
399
+ version "2.0.18"
400
+ resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba"
401
+ integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==
402
+ dependencies:
403
+ mime-db ">= 1.43.0 < 2"
404
+
405
+ compression@^1.7.4:
406
+ version "1.7.4"
407
+ resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f"
408
+ integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==
409
+ dependencies:
410
+ accepts "~1.3.5"
411
+ bytes "3.0.0"
412
+ compressible "~2.0.16"
413
+ debug "2.6.9"
414
+ on-headers "~1.0.2"
415
+ safe-buffer "5.1.2"
416
+ vary "~1.1.2"
417
+
418
  concat-map@0.0.1:
419
  version "0.0.1"
420
  resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
 
440
  lodash.clonedeep "^4.5.0"
441
  yargs-parser "^20.2.7"
442
 
443
+ cookie-parser@^1.4.6:
444
+ version "1.4.6"
445
+ resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.4.6.tgz#3ac3a7d35a7a03bbc7e365073a26074824214594"
446
+ integrity sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==
447
+ dependencies:
448
+ cookie "0.4.1"
449
+ cookie-signature "1.0.6"
450
+
451
  cookie-signature@1.0.6:
452
  version "1.0.6"
453
  resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
454
  integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==
455
 
456
+ cookie@0.4.1:
457
+ version "0.4.1"
458
+ resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1"
459
+ integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==
460
+
461
  cookie@0.5.0:
462
  version "0.5.0"
463
  resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
 
1134
  resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
1135
  integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==
1136
 
1137
+ mime-db@1.52.0, "mime-db@>= 1.43.0 < 2":
1138
  version "1.52.0"
1139
  resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
1140
  integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
 
1173
  resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
1174
  integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
1175
 
1176
+ nanoid@^5.0.4:
1177
+ version "5.0.4"
1178
+ resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-5.0.4.tgz#d2b608d8169d7da669279127615535705aa52edf"
1179
+ integrity sha512-vAjmBf13gsmhXSgBrtIclinISzFFy22WwCYoyilZlsrRXNIHSwgFQ1bEdjRwMT3aoadeIF6HMuDRlOxzfXV8ig==
1180
+
1181
  natural-compare@^1.4.0:
1182
  version "1.4.0"
1183
  resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
 
1212
  dependencies:
1213
  ee-first "1.1.1"
1214
 
1215
+ on-headers@~1.0.2:
1216
+ version "1.0.2"
1217
+ resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f"
1218
+ integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==
1219
+
1220
  once@^1.3.0:
1221
  version "1.4.0"
1222
  resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
 
1388
  dependencies:
1389
  queue-microtask "^1.2.2"
1390
 
1391
+ safe-buffer@5.1.2:
1392
+ version "5.1.2"
1393
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
1394
+ integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
1395
+
1396
  safe-buffer@5.2.1:
1397
  version "5.2.1"
1398
  resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"