wingbot 3.73.15 → 3.74.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,14 +3,13 @@ name: Push
3
3
  on:
4
4
  push:
5
5
  branches:
6
- - master
7
- - production
6
+ - "**"
7
+
8
8
  permissions:
9
9
  contents: write
10
10
  jobs:
11
-
12
- test-and-build-gatsby:
13
- name: test-and-deploy-documentation
11
+ test:
12
+ name: test
14
13
  runs-on: ubuntu-latest
15
14
 
16
15
  strategy:
@@ -18,79 +17,105 @@ jobs:
18
17
  node-version: [20.x]
19
18
 
20
19
  steps:
21
-
22
20
  - name: Checkout
23
- uses: actions/checkout@v2
21
+ uses: actions/checkout@v4
24
22
 
25
23
  - name: Node.js ${{ matrix.node-version }} setup
26
- uses: actions/setup-node@v3
24
+ uses: actions/setup-node@v4
27
25
  with:
28
26
  node-version: ${{ matrix.node-version }}
29
- cache: 'npm'
27
+ cache: "npm"
28
+ registry-url: https://npm.pkg.github.com
29
+ scope: "@wingbotai"
30
30
 
31
31
  - name: Npm install
32
- run: npm install && cd documentation && npm install --legacy-peer-deps && cd ..
32
+ run: npm i
33
+ env:
34
+ NODE_AUTH_TOKEN: ${{ secrets.WINGBOT_PCKG_READ_PAT }}
33
35
 
34
36
  - name: Test
35
37
  run: npm run test
36
38
 
37
- - name: Rewrite gatsby confing inside smoothdoc
38
- run: cp documentation/smooth-doc-gatsby-config.js documentation/node_modules/smooth-doc/gatsby-config.js
39
-
40
- - name: Generate mdx documentation files
41
- run: node bin/makeApiDoc
42
-
43
- - name: Build documentation website with gatsby
44
- run: cd documentation && npm run build
45
-
46
- - name: Deploy documentation to github pages
47
- uses: JamesIves/github-pages-deploy-action@v4
48
- with:
49
- folder: documentation/public # The folder the action should deploy.
50
-
51
- # deploy:
52
- # name: deploy
39
+ # build-docs:
40
+ # name: build docs
53
41
  # needs: test
54
42
  # runs-on: ubuntu-latest
55
43
 
44
+ # if: github.ref != 'refs/heads/master'
45
+
56
46
  # strategy:
57
47
  # matrix:
58
- # node-version: [12.x]
48
+ # node-version: [20.x]
59
49
 
60
50
  # steps:
51
+ # - name: Checkout
52
+ # uses: actions/checkout@v4
53
+
54
+ # - name: Node.js ${{ matrix.node-version }} setup
55
+ # uses: actions/setup-node@v4
56
+ # with:
57
+ # node-version: ${{ matrix.node-version }}
58
+ # cache: "npm"
59
+ # registry-url: https://npm.pkg.github.com
60
+ # scope: '@wingbotai'
61
61
 
62
- # - name: Set ENV to staging
63
- # if: github.ref == 'refs/heads/master'
64
- # run: echo "WB_ENV=staging" >> $GITHUB_ENV
62
+ # - name: Npm install
63
+ # run: npm i
64
+ # env:
65
+ # NODE_AUTH_TOKEN: ${{ secrets.WINGBOT_PCKG_READ_PAT }}
66
+
67
+ # - name: Npm install docs
68
+ # run: cd documentation && npm install --legacy-peer-deps && cd ..
69
+
70
+ # - name: Rewrite gatsby confing inside smoothdoc
71
+ # run: cp documentation/smooth-doc-gatsby-config.js documentation/node_modules/smooth-doc/gatsby-config.js
72
+
73
+ # - name: Generate mdx documentation files
74
+ # run: node bin/makeApiDoc
75
+
76
+ # - name: Build documentation website with gatsby
77
+ # run: cd documentation && npm run build
78
+
79
+ # build-and-deploy-docs:
80
+ # name: build and deploy docs
81
+ # runs-on: ubuntu-latest
65
82
 
66
- # - name: Set ENV to production
67
- # if: github.ref == 'refs/heads/production'
68
- # run: echo "WB_ENV=production" >> $GITHUB_ENV
83
+ # if: github.ref == 'refs/heads/master'
69
84
 
85
+ # strategy:
86
+ # matrix:
87
+ # node-version: [20.x]
88
+
89
+ # steps:
70
90
  # - name: Checkout
71
- # uses: actions/checkout@v2
91
+ # uses: actions/checkout@v4
72
92
 
73
93
  # - name: Node.js ${{ matrix.node-version }} setup
74
- # uses: actions/setup-node@v2
94
+ # uses: actions/setup-node@v4
75
95
  # with:
76
96
  # node-version: ${{ matrix.node-version }}
77
- # cache: 'npm'
97
+ # cache: "npm"
98
+ # registry-url: https://npm.pkg.github.com
99
+ # scope: '@wingbotai'
78
100
 
79
101
  # - name: Npm install
80
- # run: npm ci
102
+ # run: npm i
103
+ # env:
104
+ # NODE_AUTH_TOKEN: ${{ secrets.WINGBOT_PCKG_READ_PAT }}
81
105
 
82
- # - name: AWS setup
83
- # uses: aws-actions/configure-aws-credentials@v1
84
- # with:
85
- # aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
86
- # aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
87
- # aws-region: eu-central-1
106
+ # - name: Npm install docs
107
+ # run: cd documentation && npm install --legacy-peer-deps && cd ..
108
+
109
+ # - name: Rewrite gatsby confing inside smoothdoc
110
+ # run: cp documentation/smooth-doc-gatsby-config.js documentation/node_modules/smooth-doc/gatsby-config.js
88
111
 
89
- # - name: Serverless install
90
- # run: sudo npm i -g serverless@2.x
112
+ # - name: Generate mdx documentation files
113
+ # run: node bin/makeApiDoc
91
114
 
92
- # - name: Build
93
- # run: npm run build:${{ env.WB_ENV }}
115
+ # - name: Build documentation website with gatsby
116
+ # run: cd documentation && npm run build
94
117
 
95
- # - name: Deploy to the ${{ env.WB_ENV }}
96
- # run: sls deploy -s ${{ env.WB_ENV }}
118
+ # - name: Deploy documentation to github pages
119
+ # uses: JamesIves/github-pages-deploy-action@v4
120
+ # with:
121
+ # folder: documentation/public # The folder the action should deploy.
package/index.js CHANGED
@@ -66,6 +66,9 @@ const { fuzzy } = require('./src/fuzzy');
66
66
  const prepareFuzzyIndex = require('./src/fuzzy/prepareFuzzyIndex');
67
67
  const factoryFuzzySearch = require('./src/fuzzy/factoryFuzzySearch');
68
68
  const LLM = require('./src/LLM');
69
+ const LLMSession = require('./src/LLMSession');
70
+ const LLMTool = require('./src/LLMTool');
71
+ const LLMType = require('./src/LLMType');
69
72
 
70
73
  module.exports = {
71
74
 
@@ -156,5 +159,8 @@ module.exports = {
156
159
  textBodyFromTranscript,
157
160
  transcriptFromHistory,
158
161
 
159
- LLM
162
+ LLM,
163
+ LLMSession,
164
+ LLMTool,
165
+ LLMType
160
166
  };
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "wingbot",
3
- "version": "3.73.15",
3
+ "version": "3.74.1",
4
4
  "description": "Enterprise Messaging Bot Conversation Engine",
5
5
  "main": "index.js",
6
6
  "type": "commonjs",
7
7
  "scripts": {
8
+ "start": "node --trace-uncaught --stack-trace-limit=50 ./chat/www.js",
8
9
  "tsd:update": "jsdoc -t ./node_modules/tsd-jsdoc/dist/ -r ./src",
9
10
  "doc:gql": "graphql-markdown ./src/graphApi/schema.gql > doc/api/graphqlSchema.md",
10
11
  "doc": "npm run doc:gql && node ./bin/makeApiDoc.js && cpy ./CHANGELOG.md ./doc && gitbook install ./doc && gitbook build ./doc && rimraf -rf ./docs && rimraf --rf ./doc/CHANGELOG.md && move-cli ./doc/_book ./docs",
@@ -38,6 +39,7 @@
38
39
  "homepage": "https://github.com/wingbot.ai/wingbot#readme",
39
40
  "devDependencies": {
40
41
  "@types/mocha": "^10.0.10",
42
+ "@wingbotai/wingbot-ai-orchestrator": "^2.13.3",
41
43
  "cpy-cli": "^5.0.0",
42
44
  "eslint": "^8.56.0",
43
45
  "eslint-config-airbnb": "^19.0.4",
@@ -46,9 +48,12 @@
46
48
  "eslint-plugin-jsx-a11y": "^6.8.0",
47
49
  "eslint-plugin-mocha": "^10.2.0",
48
50
  "eslint-plugin-react": "^7.33.2",
51
+ "express": "^4.22.1",
49
52
  "graphql-markdown": "^7.0.0",
53
+ "js-yaml": "^4.1.1",
50
54
  "jsdoc-to-markdown": "^8.0.0",
51
55
  "mocha": "^10.2.0",
56
+ "mongodb-memory-server": "^11.0.1",
52
57
  "nyc": "^15.1.0",
53
58
  "rimraf": "^5.0.5",
54
59
  "sinon": "^17.0.1"
@@ -395,7 +395,12 @@ class BuildRouter extends Router {
395
395
  if (!snapshot) {
396
396
  snapshot = await this.loadBot();
397
397
  }
398
- this.buildWithSnapshot(snapshot.blocks);
398
+ this.buildWithSnapshot(
399
+ snapshot.blocks,
400
+ undefined,
401
+ undefined,
402
+ snapshot.deployedConfiguration
403
+ );
399
404
  } catch (e) {
400
405
  if (this._configTs > 0 && !snapshot) {
401
406
  // mute
@@ -437,7 +442,12 @@ class BuildRouter extends Router {
437
442
  // wait for running request
438
443
  await Promise.all(this._runningReqs);
439
444
 
440
- this.buildWithSnapshot(snapshot.blocks, snapshot.timestamp, snapshot.lastmod);
445
+ this.buildWithSnapshot(
446
+ snapshot.blocks,
447
+ snapshot.timestamp,
448
+ snapshot.lastmod,
449
+ snapshot.deployedConfiguration
450
+ );
441
451
  } catch (e) {
442
452
  await configStorage.invalidateConfig();
443
453
  throw e;
@@ -528,9 +538,20 @@ class BuildRouter extends Router {
528
538
  blocks.forEach((b) => this._validateBlock(b, action));
529
539
  }
530
540
 
531
- buildWithSnapshot (blocks, setConfigTimestamp = Number.MAX_SAFE_INTEGER, lastmod = '-') {
541
+ buildWithSnapshot (blocks, setConfigTimestamp = Number.MAX_SAFE_INTEGER, lastmod = '-', deployedConfiguration = null) {
532
542
  this._validateBlocks(blocks);
533
543
 
544
+ if (deployedConfiguration && typeof deployedConfiguration === 'object') {
545
+ if (this._configuration instanceof Promise) {
546
+ this._configuration = this._configuration
547
+ .then((c) => Object.assign(c || /** @type {C} */ ({}), deployedConfiguration));
548
+ } else {
549
+ const cfg = this._configuration || /** @type {C} */ ({});
550
+ Object.assign(cfg, deployedConfiguration);
551
+ this._configuration = cfg;
552
+ }
553
+ }
554
+
534
555
  Object.assign(this._resolvedContext, {
535
556
  blocks,
536
557
  nestedBlocksByStaticId: null
package/src/ChatGpt.js CHANGED
@@ -14,6 +14,8 @@ const LLM = require('./LLM');
14
14
  /** @typedef {import('./Responder').QuickReply} QuickReply */
15
15
  /** @typedef {import('./LLM').LLMMessage} LLMMessage */
16
16
  /** @typedef {import('./LLM').LLMProviderOptions} LLMProviderOptions */
17
+ /** @typedef {import('./LLMSession').ToolFunction} ToolFunction */
18
+ /** @typedef {import('./LLMSession').JsonSchemaProp} SimpleJsonSchema */
17
19
 
18
20
  /**
19
21
  * @typedef {object} Transcript
@@ -33,15 +35,26 @@ const LLM = require('./LLM');
33
35
 
34
36
  /** @typedef {'gpt-3.5-turbo'|'gpt-4'|'gpt-4-32k'|'gpt-3.5-turbo-16k'|string} ChatGPTModel */
35
37
 
38
+ /**
39
+ * @typedef {object} ForcedFn
40
+ * @prop {'function'|string} type
41
+ * @prop {string} name
42
+ */
43
+
36
44
  /**
37
45
  * @typedef {object} DefaultRequestOptions
38
46
  * @prop {ChatGPTModel} [model]
39
- * @prop {'node'|'low'|'medium'|'high'} [reasoningEffort]
47
+ * @prop {'none'|'low'|'medium'|'high'} [reasoningEffort]
40
48
  * @prop {number} [presencePenalty=0.0]
41
49
  * @prop {number} [requestTokens]
42
50
  * @prop {number} [tokensLimit]
43
51
  * @prop {number} [temperature=1.0]
44
52
  * @prop {number} [transcriptLength=-5]
53
+ * @prop {boolean} [parallelToolCalls]
54
+ * @prop {'auto'|'required'|ForcedFn|string} [toolChoice]
55
+ * @prop {'none'|'low'|'medium'|'high'|string} [reasoningEffort]
56
+ * @prop {'low'|'medium'|'high'|string} [verbosity]
57
+ * @prop {'text'|SimpleJsonSchema} [responseFormat]
45
58
  */
46
59
 
47
60
  /**
@@ -59,6 +72,7 @@ const LLM = require('./LLM');
59
72
  * @typedef {object} Message
60
73
  * @prop {'system'|'user'|'assistant'|string} role
61
74
  * @prop {string} content
75
+ * @prop {GptToolCall[]} [tool_calls]
62
76
  */
63
77
 
64
78
  /**
@@ -66,7 +80,6 @@ const LLM = require('./LLM');
66
80
  * @prop {'stop'|'length'|'tool_calls'|'content_filter'|null} finish_reason
67
81
  * @prop {number} index
68
82
  * @prop {Message} message
69
- * @prop {GptToolCall[]} [tool_calls]
70
83
  */
71
84
 
72
85
  /**
@@ -188,7 +201,7 @@ class ChatGpt {
188
201
 
189
202
  this._defaultUser = defaultUser;
190
203
 
191
- /** @type {Required<DefaultRequestOptions>} */
204
+ /** @type {DefaultRequestOptions} */
192
205
  this._options = {
193
206
  requestTokens: null,
194
207
  tokensLimit: null,
@@ -255,20 +268,23 @@ class ChatGpt {
255
268
  /**
256
269
  * @param {LLMMessage[]} prompt
257
270
  * @param {LLMProviderOptions} [options]
271
+ * @param {ToolFunction[]} [tools=[]]
258
272
  * @returns {Promise<LLMMessage>}
259
273
  */
260
- async requestChat (prompt, options) {
261
- const choice = await this._request(prompt, options);
274
+ async requestChat (prompt, options, tools = []) {
275
+ const choice = await this._request(prompt, options, tools);
262
276
 
263
- const { finish_reason: finishReason, message, tool_calls: toolCalls = [] } = choice;
277
+ const { finish_reason: finishReason, message } = choice;
264
278
 
265
279
  return {
266
280
  finishReason,
267
- toolCalls: toolCalls.map(({ id, function: { name, arguments: args } }) => ({
268
- id,
269
- name,
270
- args
271
- })),
281
+ toolCalls: (message.tool_calls || [])
282
+ .map(({ id, type, function: { name, arguments: args } }) => ({
283
+ id,
284
+ type,
285
+ name,
286
+ args
287
+ })),
272
288
  ...message
273
289
  };
274
290
  }
@@ -276,11 +292,11 @@ class ChatGpt {
276
292
  /**
277
293
  *
278
294
  * @param {LLMMessage[]} chat
279
- * @param {RequestOptions} requestOptions
280
- * @param {string} user
295
+ * @param {LLMProviderOptions} requestOptions
296
+ * @param {ToolFunction[]} [tools=[]]
281
297
  * @returns {Promise<ChatGPTChoice>}
282
298
  */
283
- async _request (chat, requestOptions, user = null) {
299
+ async _request (chat, requestOptions, tools = []) {
284
300
  const {
285
301
  requestTokens,
286
302
  tokensLimit,
@@ -288,13 +304,40 @@ class ChatGpt {
288
304
  presencePenalty,
289
305
  temperature,
290
306
  reasoningEffort,
291
- functions = []
307
+ functions = [],
308
+ toolChoice,
309
+ parallelToolCalls,
310
+ verbosity,
311
+ responseFormat
292
312
  } = {
293
313
  ...this._options,
294
314
  ...requestOptions
295
315
  };
296
316
 
297
- let messages = chat;
317
+ let messages = chat.map((msg) => {
318
+ const { toolCallId, toolCalls, ...rest } = msg;
319
+ if (toolCalls) {
320
+ return {
321
+ ...rest,
322
+ tool_calls: toolCalls.map((tc) => ({
323
+ id: tc.id,
324
+ type: tc.type || 'function',
325
+ function: {
326
+ name: tc.name,
327
+ arguments: tc.args
328
+ }
329
+ }))
330
+ };
331
+ }
332
+ if (toolCallId) {
333
+ return {
334
+ tool_call_id: toolCallId,
335
+ ...rest
336
+ };
337
+ }
338
+
339
+ return msg;
340
+ });
298
341
 
299
342
  let body;
300
343
  try {
@@ -304,7 +347,7 @@ class ChatGpt {
304
347
  if (m.role === LLM.ROLE_USER) {
305
348
  lastUserIndex = i;
306
349
  }
307
- return (m.content ? 0 : m.content.length) + total;
350
+ return (m.content ? m.content.length : 0) + total;
308
351
  }, 0);
309
352
 
310
353
  if (tokensLimit !== null && totalTokens > tokensLimit) {
@@ -321,22 +364,66 @@ class ChatGpt {
321
364
  });
322
365
  }
323
366
 
367
+ let rf;
368
+
369
+ if (typeof responseFormat === 'object' && responseFormat) {
370
+ const { name = 'output', ...schema } = responseFormat;
371
+ rf = {
372
+ type: 'json_schema',
373
+ json_schema: {
374
+ name,
375
+ schema
376
+ }
377
+ };
378
+ } else if (typeof responseFormat === 'string') {
379
+ rf = { type: responseFormat };
380
+ }
381
+
382
+ let tc;
383
+
384
+ if (typeof toolChoice === 'string') {
385
+ tc = toolChoice;
386
+ } else if (typeof toolChoice === 'object' && toolChoice) {
387
+ tc = {
388
+ type: toolChoice.type || 'function',
389
+ function: {
390
+ name: toolChoice.name
391
+ }
392
+ };
393
+ }
394
+
324
395
  body = {
325
396
  model,
326
397
  frequency_penalty: 0,
327
398
  presence_penalty: presencePenalty,
328
- ...(requestTokens ? { max_completion_tokens: requestTokens } : {}),
399
+ ...(requestTokens ? {
400
+ max_completion_tokens: requestTokens
401
+ } : {}),
329
402
  ...(reasoningEffort ? {
330
403
  reasoning: { effort: reasoningEffort }
331
404
  } : {}),
405
+ ...(typeof parallelToolCalls === 'boolean' ? {
406
+ parallel_tool_calls: parallelToolCalls
407
+ } : {}),
408
+ ...(rf ? {
409
+ response_format: rf
410
+ } : {}),
411
+ ...(tc ? {
412
+ tool_choice: tc
413
+ } : {}),
414
+ ...(verbosity ? {
415
+ verbosity
416
+ } : {}),
332
417
  temperature,
333
- messages
418
+ messages,
419
+ tools: tools.map((tool) => ({
420
+ type: 'function',
421
+ function: tool
422
+ }))
423
+ // prompt_cache_key
424
+ // prompt_cache_retention in-memory" or "24h"
334
425
  };
335
426
 
336
- if (user) {
337
- Object.assign(body, { user });
338
- }
339
-
340
427
  if (functions.length) {
341
428
  Object.assign(body, { functions });
342
429
  }
@@ -387,10 +474,9 @@ class ChatGpt {
387
474
  * @param {string} [system]
388
475
  * @param {Transcript[]} [transcript]
389
476
  * @param {RequestOptions} [requestOptions]
390
- * @param {string|Request} [user]
391
477
  * @returns {Promise<ChatGPTChoice>}
392
478
  */
393
- async request (content, system = null, transcript = [], requestOptions = {}, user = null) {
479
+ async request (content, system = null, transcript = [], requestOptions = {}) {
394
480
 
395
481
  /** @type {Message[]} */
396
482
  const messages = [
@@ -399,16 +485,7 @@ class ChatGpt {
399
485
  { role: 'user', content }
400
486
  ];
401
487
 
402
- let useUser;
403
- if (typeof user === 'string') {
404
- useUser = user;
405
- } else if (user) {
406
- useUser = `${user.pageId}|${user.senderId}`;
407
- } else if (this._defaultUser) {
408
- useUser = this._defaultUser;
409
- }
410
-
411
- return this._request(messages, requestOptions, useUser);
488
+ return this._request(messages, requestOptions);
412
489
  }
413
490
 
414
491
  /**