@caruuto/caruuto-js 0.7.0 → 0.9.0

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.
package/index.js CHANGED
@@ -1,6 +1,8 @@
1
1
  const CaruutoClient = function (caruutoUrl, caruutoApiKey, options = {}) {
2
2
  this.options = options
3
3
  this.options.caruutoUrl = caruutoUrl
4
+ .replace(/\/api\/?$/, '')
5
+ .replace(/\/$/, '')
4
6
  this.options.caruutoApiKey = caruutoApiKey
5
7
 
6
8
  this.options.version = '1'
@@ -220,21 +220,35 @@ module.exports = function (CaruutoClient, clientInstance) {
220
220
  * @param {'conversation'|'question_cache'} opts.source
221
221
  * @returns {Promise<{ id: string }>} New conversation ID
222
222
  */
223
- forkConversation: async function ({ sourceId, projectId, source = 'conversation' } = {}) {
223
+ forkConversation: async function ({
224
+ sourceId,
225
+ projectId,
226
+ source = 'conversation'
227
+ } = {}) {
224
228
  if (!sourceId) throw new Error('sourceId is required')
225
229
  if (!projectId) throw new Error('projectId is required')
226
230
 
227
231
  const url = `${this.options.caruutoUrl}/api/ai/conversations/${sourceId}/fork`
228
- const response = await doFetch(this, url, { project_id: projectId, source })
232
+ const response = await doFetch(this, url, {
233
+ project_id: projectId,
234
+ source
235
+ })
229
236
  return response.json()
230
237
  }.bind(clientInstance),
231
238
 
232
- shareConversation: async function ({ conversationId, projectId, visibility = 'public' } = {}) {
239
+ shareConversation: async function ({
240
+ conversationId,
241
+ projectId,
242
+ visibility = 'public'
243
+ } = {}) {
233
244
  if (!conversationId) throw new Error('conversationId is required')
234
245
  if (!projectId) throw new Error('projectId is required')
235
246
 
236
247
  const url = `${this.options.caruutoUrl}/api/ai/conversations/${conversationId}/share`
237
- const response = await doFetch(this, url, { project_id: projectId, visibility })
248
+ const response = await doFetch(this, url, {
249
+ project_id: projectId,
250
+ visibility
251
+ })
238
252
  return response.json()
239
253
  }.bind(clientInstance),
240
254
 
@@ -276,7 +290,11 @@ module.exports = function (CaruutoClient, clientInstance) {
276
290
  throw new Error('projectId is required')
277
291
  }
278
292
 
279
- const url = `${this.options.caruutoUrl}/api/ai/conversations/${conversationId}?project_id=${encodeURIComponent(projectId)}`
293
+ const url = `${
294
+ this.options.caruutoUrl
295
+ }/api/ai/conversations/${conversationId}?project_id=${encodeURIComponent(
296
+ projectId
297
+ )}`
280
298
  const response = await doGet(this, url)
281
299
  return response.json()
282
300
  }.bind(clientInstance),
@@ -319,6 +337,49 @@ module.exports = function (CaruutoClient, clientInstance) {
319
337
  const url = `${this.options.caruutoUrl}/api/ai/conversations/${conversationId}/turn`
320
338
  const response = await doFetch(this, url, body)
321
339
  return response.json()
340
+ }.bind(clientInstance),
341
+
342
+ /**
343
+ * Record a click on a link surfaced in an assistant response — powers the
344
+ * CTA-click and conversion panels on the analytics dashboard. Caruuto
345
+ * classifies the link as 'internal' or 'external' relative to the
346
+ * project's site_domain and persists it to ai_link_click_events.
347
+ *
348
+ * @param {Object} opts
349
+ * @param {string} opts.conversationId - The conversation the link appeared in
350
+ * @param {string} opts.projectId
351
+ * @param {string} opts.url - The full clicked URL, exactly as rendered
352
+ * @param {string} [opts.linkLabel] - The link's visible text
353
+ * @param {number} [opts.messageIndex] - Position of the assistant message clicked from
354
+ * @returns {Promise<{ ok: boolean }>}
355
+ */
356
+ trackLinkClick: async function ({
357
+ conversationId,
358
+ projectId,
359
+ url,
360
+ linkLabel,
361
+ messageIndex
362
+ } = {}) {
363
+ if (!conversationId) {
364
+ throw new Error('conversationId is required')
365
+ }
366
+
367
+ if (!projectId) {
368
+ throw new Error('projectId is required')
369
+ }
370
+
371
+ if (!url) {
372
+ throw new Error('url is required')
373
+ }
374
+
375
+ const body = { project_id: projectId, url }
376
+
377
+ if (linkLabel) body.link_label = linkLabel
378
+ if (messageIndex !== undefined) body.message_index = messageIndex
379
+
380
+ const trackUrl = `${this.options.caruutoUrl}/api/ai/conversations/${conversationId}/link-click`
381
+ const response = await doFetch(this, trackUrl, body)
382
+ return response.json()
322
383
  }.bind(clientInstance)
323
384
  }
324
385
  }
@@ -384,7 +445,9 @@ async function doGet(client, url) {
384
445
  if (data.error) {
385
446
  err.message = data.error
386
447
  }
387
- } catch (_) {}
448
+ } catch (_) {
449
+ // Ignore JSON parsing errors and use the default error message
450
+ }
388
451
 
389
452
  throw err
390
453
  }
@@ -413,7 +476,9 @@ async function doFetch(client, url, body) {
413
476
  if (data.error) {
414
477
  err.message = data.error
415
478
  }
416
- } catch (_) {}
479
+ } catch (_) {
480
+ // Ignore JSON parsing errors and use the default error message
481
+ }
417
482
 
418
483
  throw err
419
484
  }
@@ -67,7 +67,9 @@ module.exports = function (CaruutoClient) {
67
67
  if (responseData.errors) {
68
68
  err.errors = responseData.errors
69
69
  }
70
- } catch (_) {}
70
+ } catch (_) {
71
+ // Ignore JSON parsing errors and use the default error message
72
+ }
71
73
 
72
74
  return Promise.reject(err)
73
75
  }
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@caruuto/caruuto-js",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "description": "A high-level library for interacting with Caruuto",
5
5
  "exports": "./index.js",
6
6
  "scripts": {
7
- "test": "eslint --ext js,jsx . && prettier --write '**/*.{js,jsx,md,html,css}' && NODE_ENV=test mocha {test,core/test}/**/*.js",
7
+ "test": "eslint --ext js,jsx . && prettier --write '**/*.{js,jsx,md,html,css}' && NODE_ENV=test mocha test/**/*.js",
8
8
  "posttest": "./scripts/coverage.js"
9
9
  },
10
10
  "author": "Jim Lambie <jim@27.works>",
@@ -50,4 +50,4 @@
50
50
  "should": "^9.0.2",
51
51
  "sinon": "^4.5.0"
52
52
  }
53
- }
53
+ }