fix: make quantifier lazy to not span multiple JSON blocks, tests + docs

old-agentic-v1^2
Philipp Burckhardt 2023-06-14 23:30:16 -04:00 zatwierdzone przez Travis Fischer
rodzic 5b510116e4
commit 07138c9ca7
2 zmienionych plików z 88 dodań i 11 usunięć

Wyświetl plik

@ -2,18 +2,39 @@ import { customAlphabet, urlAlphabet } from 'nanoid'
import * as types from './types'
/**
* Extracts the first JSON object string from a given string.
*
* @param text - string from which to extract the JSON object
* @returns extracted JSON object string, or `undefined` if no JSON object is found
*/
export function extractJSONObjectFromString(text: string): string | undefined {
return text.match(/\{(.|\n)*\}/gm)?.[0]
}
/**
* Extracts the first JSON array string from a given string.
*
* @param text - string from which to extract the JSON array
* @returns extracted JSON array string, or `undefined` if no JSON array is found
*/
export function extractJSONArrayFromString(text: string): string | undefined {
return text.match(/\[(.|\n)*\]/gm)?.[0]
}
/**
* Pauses the execution of a function for a specified time.
*
* @param ms - number of milliseconds to pause
* @returns promise that resolves after the specified number of milliseconds
*/
export function sleep(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms))
}
/**
* A default ID generator function that uses a custom alphabet based on URL safe symbols.
*/
export const defaultIDGeneratorFn: types.IDGeneratorFunction =
customAlphabet(urlAlphabet)
@ -23,28 +44,27 @@ export function isValidTaskIdentifier(id: string): boolean {
}
/**
* Chunk a string into an array of strings of a given length
* Chunks a string into an array of chunks.
*
* @param text - string to chunk
* @param length - maximum length of each chunk
* @returns array of strings
* @param maxLength - maximum length of each chunk
* @returns array of chunks
*/
export const chunkString = (text: string, length: number) => {
export const chunkString = (text: string, maxLength: number) => {
const words = text.split(' ')
const chunks: string[] = []
let chunk = ''
for (const word of words) {
if (word.length > length) {
if (word.length > maxLength) {
// Truncate the word if it's too long and indicate that it was truncated:
chunks.push(word.substring(0, length - 3) + '...')
}
if ((chunk + word).length > length) {
chunks.push(word.substring(0, maxLength - 3) + '...')
} else if ((chunk + word + 1).length > maxLength) {
// +1 accounts for the space between words
chunks.push(chunk.trim())
chunk = word
} else {
chunk += ' ' + word
chunk += (chunk ? ' ' : '') + word
}
}

59
test/utils.test.ts vendored
Wyświetl plik

@ -1,6 +1,13 @@
import test from 'ava'
import { isValidTaskIdentifier } from '@/utils'
import {
chunkString,
defaultIDGeneratorFn,
extractJSONArrayFromString,
extractJSONObjectFromString,
isValidTaskIdentifier,
sleep
} from '@/utils'
test('isValidTaskIdentifier - valid', async (t) => {
t.true(isValidTaskIdentifier('foo'))
@ -18,3 +25,53 @@ test('isValidTaskIdentifier - invalid', async (t) => {
t.false(isValidTaskIdentifier('x'.repeat(65)))
t.false(isValidTaskIdentifier('-foo'))
})
test('extractJSONObjectFromString should extract first JSON object from string', (t) => {
const jsonString = '{"name":"John"} Some other text {"name":"Doe"}'
const result = extractJSONObjectFromString(jsonString)
t.is(result, '{"name":"John"}')
})
test('extractJSONArrayFromString should extract first JSON array from string', (t) => {
const jsonString = '[1,2,3] Some other text [4,5,6]'
const result = extractJSONArrayFromString(jsonString)
t.is(result, '[1,2,3]')
})
test('extractJSONObjectFromString should return undefined if no JSON object is found', (t) => {
const jsonString = 'Some text'
const result = extractJSONObjectFromString(jsonString)
t.is(result, undefined)
})
test('extractJSONArrayFromString should return undefined if no JSON array is found', (t) => {
const jsonString = 'Some text'
const result = extractJSONArrayFromString(jsonString)
t.is(result, undefined)
})
test('sleep should delay execution', async (t) => {
const start = Date.now()
await sleep(1000) // for example, 1000ms / 1sec
const end = Date.now()
t.true(end - start >= 1000)
})
test('defaultIDGeneratorFn should generate URL-safe string', (t) => {
const result = defaultIDGeneratorFn()
// Check if generated string matches URL-safe characters:
t.regex(result, /^[A-Za-z0-9\-_]+$/)
})
test('chunkString should split string into chunks', (t) => {
const text = 'Hello, this is a test string for chunkString function.'
const chunks = chunkString(text, 12)
t.deepEqual(chunks, [
'Hello, this',
'is a test',
'string for',
'chunkString',
'function.'
])
})