@sprucelabs/sprucebot-llm 14.3.3 → 15.0.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/README.md +1 -1
- package/build/.spruce/errors/errors.types.d.ts +11 -0
- package/build/.spruce/errors/options.types.d.ts +4 -1
- package/build/.spruce/errors/sprucebotLlm/stateUpdateFailed.schema.d.ts +3 -0
- package/build/.spruce/errors/sprucebotLlm/stateUpdateFailed.schema.js +11 -0
- package/build/bots/TurnRequest.js +14 -4
- package/build/bots/adapters/{OpenAiMessageBuilder.d.ts → MessageBuilder.d.ts} +3 -2
- package/build/bots/adapters/{OpenAiMessageBuilder.js → MessageBuilder.js} +13 -4
- package/build/bots/adapters/MessageSender.js +2 -2
- package/build/errors/SpruceError.js +3 -0
- package/build/errors/stateUpdateFailed.builder.d.ts +6 -0
- package/build/errors/stateUpdateFailed.builder.js +8 -0
- package/build/esm/.spruce/errors/errors.types.d.ts +11 -0
- package/build/esm/.spruce/errors/options.types.d.ts +4 -1
- package/build/esm/bots/TurnRequest.js +14 -4
- package/build/esm/bots/adapters/{OpenAiMessageBuilder.d.ts → MessageBuilder.d.ts} +3 -2
- package/build/esm/bots/adapters/{OpenAiMessageBuilder.js → MessageBuilder.js} +10 -4
- package/build/esm/bots/adapters/MessageSender.js +2 -2
- package/build/esm/errors/SpruceError.js +3 -0
- package/build/esm/errors/stateUpdateFailed.builder.d.ts +6 -0
- package/build/esm/errors/stateUpdateFailed.builder.js +6 -0
- package/build/esm/llm.types.d.ts +11 -0
- package/build/esm/parsingResponses/ResponseParserFactory.d.ts +10 -0
- package/build/esm/parsingResponses/ResponseParserFactory.js +21 -0
- package/build/esm/parsingResponses/ResponseParserV1.d.ts +12 -0
- package/build/esm/parsingResponses/{ResponseParser.js → ResponseParserV1.js} +14 -33
- package/build/esm/parsingResponses/ResponseParserV2.d.ts +7 -0
- package/build/esm/parsingResponses/ResponseParserV2.js +73 -0
- package/build/esm/parsingResponses/validateAndNormalizeCallbackOptions.d.ts +2 -0
- package/build/esm/parsingResponses/validateAndNormalizeCallbackOptions.js +26 -0
- package/build/llm.types.d.ts +11 -0
- package/build/parsingResponses/ResponseParserFactory.d.ts +10 -0
- package/build/parsingResponses/ResponseParserFactory.js +26 -0
- package/build/parsingResponses/ResponseParserV1.d.ts +12 -0
- package/build/parsingResponses/{ResponseParser.js → ResponseParserV1.js} +14 -21
- package/build/parsingResponses/ResponseParserV2.d.ts +7 -0
- package/build/parsingResponses/ResponseParserV2.js +66 -0
- package/build/parsingResponses/validateAndNormalizeCallbackOptions.d.ts +2 -0
- package/build/parsingResponses/validateAndNormalizeCallbackOptions.js +18 -0
- package/package.json +15 -15
- package/build/esm/parsingResponses/ResponseParser.d.ts +0 -18
- package/build/parsingResponses/ResponseParser.d.ts +0 -18
package/README.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import { default as SchemaEntity } from '@sprucelabs/schema';
|
|
2
2
|
import * as SpruceSchema from '@sprucelabs/schema';
|
|
3
|
+
export declare namespace SpruceErrors.SprucebotLlm {
|
|
4
|
+
interface StateUpdateFailed {
|
|
5
|
+
}
|
|
6
|
+
interface StateUpdateFailedSchema extends SpruceSchema.Schema {
|
|
7
|
+
id: 'stateUpdateFailed';
|
|
8
|
+
namespace: 'SprucebotLlm';
|
|
9
|
+
name: 'State Update Failed';
|
|
10
|
+
fields: {};
|
|
11
|
+
}
|
|
12
|
+
type StateUpdateFailedEntity = SchemaEntity<SpruceErrors.SprucebotLlm.StateUpdateFailedSchema>;
|
|
13
|
+
}
|
|
3
14
|
export declare namespace SpruceErrors.SprucebotLlm {
|
|
4
15
|
interface NoBotInstanceSet {
|
|
5
16
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { SpruceErrors } from "./errors.types";
|
|
2
2
|
import { ErrorOptions as ISpruceErrorOptions } from "@sprucelabs/error";
|
|
3
|
+
export interface StateUpdateFailedErrorOptions extends SpruceErrors.SprucebotLlm.StateUpdateFailed, ISpruceErrorOptions {
|
|
4
|
+
code: 'STATE_UPDATE_FAILED';
|
|
5
|
+
}
|
|
3
6
|
export interface NoBotInstanceSetErrorOptions extends SpruceErrors.SprucebotLlm.NoBotInstanceSet, ISpruceErrorOptions {
|
|
4
7
|
code: 'NO_BOT_INSTANCE_SET';
|
|
5
8
|
}
|
|
@@ -12,5 +15,5 @@ export interface InvalidCallbackErrorOptions extends SpruceErrors.SprucebotLlm.I
|
|
|
12
15
|
export interface CallbackErrorErrorOptions extends SpruceErrors.SprucebotLlm.CallbackError, ISpruceErrorOptions {
|
|
13
16
|
code: 'CALLBACK_ERROR';
|
|
14
17
|
}
|
|
15
|
-
type ErrorOptions = NoBotInstanceSetErrorOptions | InvalidLlmAdapterErrorOptions | InvalidCallbackErrorOptions | CallbackErrorErrorOptions;
|
|
18
|
+
type ErrorOptions = StateUpdateFailedErrorOptions | NoBotInstanceSetErrorOptions | InvalidLlmAdapterErrorOptions | InvalidCallbackErrorOptions | CallbackErrorErrorOptions;
|
|
16
19
|
export default ErrorOptions;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const schema_1 = require("@sprucelabs/schema");
|
|
4
|
+
const stateUpdateFailedSchema = {
|
|
5
|
+
id: 'stateUpdateFailed',
|
|
6
|
+
namespace: 'SprucebotLlm',
|
|
7
|
+
name: 'State Update Failed',
|
|
8
|
+
fields: {}
|
|
9
|
+
};
|
|
10
|
+
schema_1.SchemaRegistry.getInstance().trackSchema(stateUpdateFailedSchema);
|
|
11
|
+
exports.default = stateUpdateFailedSchema;
|
|
@@ -3,7 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const
|
|
6
|
+
const SpruceError_1 = __importDefault(require("../errors/SpruceError"));
|
|
7
|
+
const ResponseParserFactory_1 = __importDefault(require("../parsingResponses/ResponseParserFactory"));
|
|
7
8
|
class TurnRequest {
|
|
8
9
|
constructor(options) {
|
|
9
10
|
this.isCancelled = false;
|
|
@@ -35,7 +36,16 @@ class TurnRequest {
|
|
|
35
36
|
isDone = parsed.isDone;
|
|
36
37
|
state = parsed.state;
|
|
37
38
|
callbackResults = parsed.callbackResults;
|
|
38
|
-
|
|
39
|
+
try {
|
|
40
|
+
await this.optionallyUpdateState(state);
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
throw new SpruceError_1.default({
|
|
44
|
+
code: 'STATE_UPDATE_FAILED',
|
|
45
|
+
friendlyMessage: `Updating state failed with error: ${err.message}`,
|
|
46
|
+
originalError: err,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
39
49
|
}
|
|
40
50
|
catch (err) {
|
|
41
51
|
this.trackMessage({
|
|
@@ -44,7 +54,7 @@ class TurnRequest {
|
|
|
44
54
|
});
|
|
45
55
|
if (err.options?.code === 'INVALID_CALLBACK' ||
|
|
46
56
|
err.options?.code === 'CALLBACK_ERROR' ||
|
|
47
|
-
err.options?.code === '
|
|
57
|
+
err.options?.code === 'STATE_UPDATE_FAILED') {
|
|
48
58
|
return this.sendMessage({ from: 'Api', message: `Error: ${err.message}` }, cb);
|
|
49
59
|
}
|
|
50
60
|
throw err;
|
|
@@ -82,7 +92,7 @@ class TurnRequest {
|
|
|
82
92
|
: undefined);
|
|
83
93
|
}
|
|
84
94
|
async parseResponse(response, callbacks) {
|
|
85
|
-
const parser =
|
|
95
|
+
const parser = ResponseParserFactory_1.default.getInstance();
|
|
86
96
|
const parsed = await parser.parse(response, callbacks);
|
|
87
97
|
return parsed;
|
|
88
98
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { ChatCompletionMessageParam } from 'openai/resources';
|
|
2
2
|
import { SprucebotLlmBot } from '../../llm.types';
|
|
3
|
-
export default class
|
|
3
|
+
export default class MessageBuilder {
|
|
4
4
|
private bot;
|
|
5
5
|
private memoryLimit;
|
|
6
6
|
protected constructor(bot: SprucebotLlmBot, options?: BuildMessageOptions);
|
|
7
|
-
static Builder(bot: SprucebotLlmBot, options?: BuildMessageOptions):
|
|
7
|
+
static Builder(bot: SprucebotLlmBot, options?: BuildMessageOptions): MessageBuilder;
|
|
8
|
+
private get parser();
|
|
8
9
|
buildMessages(): ChatCompletionMessageParam[];
|
|
9
10
|
private buildChatHistoryMessages;
|
|
10
11
|
private mapMessageToCompletion;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const ResponseParserFactory_1 = __importDefault(require("../../parsingResponses/ResponseParserFactory"));
|
|
3
7
|
const templates_1 = require("../templates");
|
|
4
|
-
class
|
|
8
|
+
class MessageBuilder {
|
|
5
9
|
constructor(bot, options) {
|
|
6
10
|
const { memoryLimit } = options ?? {};
|
|
7
11
|
this.bot = bot;
|
|
@@ -12,6 +16,9 @@ class OpenAiMessageBuilder {
|
|
|
12
16
|
static Builder(bot, options) {
|
|
13
17
|
return new this(bot, options);
|
|
14
18
|
}
|
|
19
|
+
get parser() {
|
|
20
|
+
return ResponseParserFactory_1.default.getInstance();
|
|
21
|
+
}
|
|
15
22
|
buildMessages() {
|
|
16
23
|
const values = this.bot.serialize();
|
|
17
24
|
const allMessages = [
|
|
@@ -132,6 +139,8 @@ class OpenAiMessageBuilder {
|
|
|
132
139
|
<Parameter${param.isRequired ? ' required="true"' : ''}>
|
|
133
140
|
<Name>${param.name}</Name>
|
|
134
141
|
<Type>${param.type}</Type>
|
|
142
|
+
${param.isArray ? '<IsArray>true</IsArray>' : ''}
|
|
143
|
+
${'minArrayLength' in param ? `<MinArrayLength>${param.minArrayLength}</MinArrayLength>` : ''}
|
|
135
144
|
${param.description ? `<Description>${param.description}</Description>` : ''}${parameterChoices}
|
|
136
145
|
</Parameter>`;
|
|
137
146
|
}
|
|
@@ -144,7 +153,7 @@ class OpenAiMessageBuilder {
|
|
|
144
153
|
const api = `<APIReference>\n\n${descriptions.join('\n\n')}</APIReference>`;
|
|
145
154
|
return {
|
|
146
155
|
role: 'system',
|
|
147
|
-
content: `You have an API available to you to lookup answers. When you need the response of the function call to proceed, you can call a function using a custom markup we created
|
|
156
|
+
content: `You have an API available to you to lookup answers. When you need the response of the function call to proceed, you can call a function using a custom markup we created: ${this.parser.getFunctionCallInstructions()}. The API is as follows (in xml format):\n\n${api}`,
|
|
148
157
|
};
|
|
149
158
|
}
|
|
150
159
|
buildPleaseKeepInMindMessage(pleaseKeepInMindThat) {
|
|
@@ -156,7 +165,7 @@ class OpenAiMessageBuilder {
|
|
|
156
165
|
buildStateMessage(state) {
|
|
157
166
|
return {
|
|
158
167
|
role: 'system',
|
|
159
|
-
content: `The current state of this conversation is:\n\n${JSON.stringify(state)}. As the
|
|
168
|
+
content: `The current state of this conversation is:\n\n${JSON.stringify(state)}. As the conversation progresses and you need to update state, follow these instructions: ${this.parser.getStateUpdateInstructions()}`,
|
|
160
169
|
};
|
|
161
170
|
}
|
|
162
171
|
buildYourJobMessage(yourJob) {
|
|
@@ -178,4 +187,4 @@ class OpenAiMessageBuilder {
|
|
|
178
187
|
};
|
|
179
188
|
}
|
|
180
189
|
}
|
|
181
|
-
exports.default =
|
|
190
|
+
exports.default = MessageBuilder;
|
|
@@ -5,8 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const sdk_1 = require("@anthropic-ai/sdk");
|
|
7
7
|
const openai_1 = require("openai");
|
|
8
|
+
const MessageBuilder_1 = __importDefault(require("./MessageBuilder"));
|
|
8
9
|
const OpenAiAdapter_1 = require("./OpenAiAdapter");
|
|
9
|
-
const OpenAiMessageBuilder_1 = __importDefault(require("./OpenAiMessageBuilder"));
|
|
10
10
|
class MessageSenderImpl {
|
|
11
11
|
constructor(send, log) {
|
|
12
12
|
this.log = log;
|
|
@@ -17,7 +17,7 @@ class MessageSenderImpl {
|
|
|
17
17
|
}
|
|
18
18
|
async sendMessage(bot, options) {
|
|
19
19
|
const { memoryLimit, ...rest } = options;
|
|
20
|
-
const messageBuilder =
|
|
20
|
+
const messageBuilder = MessageBuilder_1.default.Builder(bot, {
|
|
21
21
|
memoryLimit,
|
|
22
22
|
});
|
|
23
23
|
const messages = messageBuilder.buildMessages();
|
|
@@ -42,6 +42,9 @@ ${options.validCallbacks.map((name, idx) => `${idx + 1}: ${name}`).join('\n')}`;
|
|
|
42
42
|
case 'INVALID_LLM_ADAPTER':
|
|
43
43
|
message = `SPRUCE_LLM_ADAPTER=${options.adapter} is not a valid adapter. Please set SPRUCE_LLM_ADAPTER to a valid adapter (OpenAi, Anthropic, Ollama) and try again.`;
|
|
44
44
|
break;
|
|
45
|
+
case 'STATE_UPDATE_FAILED':
|
|
46
|
+
message = 'A State Update Failed just happened!';
|
|
47
|
+
break;
|
|
45
48
|
default:
|
|
46
49
|
message = super.friendlyMessage();
|
|
47
50
|
}
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import { default as SchemaEntity } from '@sprucelabs/schema';
|
|
2
2
|
import * as SpruceSchema from '@sprucelabs/schema';
|
|
3
|
+
export declare namespace SpruceErrors.SprucebotLlm {
|
|
4
|
+
interface StateUpdateFailed {
|
|
5
|
+
}
|
|
6
|
+
interface StateUpdateFailedSchema extends SpruceSchema.Schema {
|
|
7
|
+
id: 'stateUpdateFailed';
|
|
8
|
+
namespace: 'SprucebotLlm';
|
|
9
|
+
name: 'State Update Failed';
|
|
10
|
+
fields: {};
|
|
11
|
+
}
|
|
12
|
+
type StateUpdateFailedEntity = SchemaEntity<SpruceErrors.SprucebotLlm.StateUpdateFailedSchema>;
|
|
13
|
+
}
|
|
3
14
|
export declare namespace SpruceErrors.SprucebotLlm {
|
|
4
15
|
interface NoBotInstanceSet {
|
|
5
16
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { SpruceErrors } from "./errors.types";
|
|
2
2
|
import { ErrorOptions as ISpruceErrorOptions } from "@sprucelabs/error";
|
|
3
|
+
export interface StateUpdateFailedErrorOptions extends SpruceErrors.SprucebotLlm.StateUpdateFailed, ISpruceErrorOptions {
|
|
4
|
+
code: 'STATE_UPDATE_FAILED';
|
|
5
|
+
}
|
|
3
6
|
export interface NoBotInstanceSetErrorOptions extends SpruceErrors.SprucebotLlm.NoBotInstanceSet, ISpruceErrorOptions {
|
|
4
7
|
code: 'NO_BOT_INSTANCE_SET';
|
|
5
8
|
}
|
|
@@ -12,5 +15,5 @@ export interface InvalidCallbackErrorOptions extends SpruceErrors.SprucebotLlm.I
|
|
|
12
15
|
export interface CallbackErrorErrorOptions extends SpruceErrors.SprucebotLlm.CallbackError, ISpruceErrorOptions {
|
|
13
16
|
code: 'CALLBACK_ERROR';
|
|
14
17
|
}
|
|
15
|
-
type ErrorOptions = NoBotInstanceSetErrorOptions | InvalidLlmAdapterErrorOptions | InvalidCallbackErrorOptions | CallbackErrorErrorOptions;
|
|
18
|
+
type ErrorOptions = StateUpdateFailedErrorOptions | NoBotInstanceSetErrorOptions | InvalidLlmAdapterErrorOptions | InvalidCallbackErrorOptions | CallbackErrorErrorOptions;
|
|
16
19
|
export default ErrorOptions;
|
|
@@ -7,7 +7,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import
|
|
10
|
+
import SpruceError from '../errors/SpruceError.js';
|
|
11
|
+
import ResponseParserFactory from '../parsingResponses/ResponseParserFactory.js';
|
|
11
12
|
export default class TurnRequest {
|
|
12
13
|
constructor(options) {
|
|
13
14
|
this.isCancelled = false;
|
|
@@ -41,7 +42,16 @@ export default class TurnRequest {
|
|
|
41
42
|
isDone = parsed.isDone;
|
|
42
43
|
state = parsed.state;
|
|
43
44
|
callbackResults = parsed.callbackResults;
|
|
44
|
-
|
|
45
|
+
try {
|
|
46
|
+
yield this.optionallyUpdateState(state);
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
throw new SpruceError({
|
|
50
|
+
code: 'STATE_UPDATE_FAILED',
|
|
51
|
+
friendlyMessage: `Updating state failed with error: ${err.message}`,
|
|
52
|
+
originalError: err,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
45
55
|
}
|
|
46
56
|
catch (err) {
|
|
47
57
|
this.trackMessage({
|
|
@@ -50,7 +60,7 @@ export default class TurnRequest {
|
|
|
50
60
|
});
|
|
51
61
|
if (((_c = err.options) === null || _c === void 0 ? void 0 : _c.code) === 'INVALID_CALLBACK' ||
|
|
52
62
|
((_d = err.options) === null || _d === void 0 ? void 0 : _d.code) === 'CALLBACK_ERROR' ||
|
|
53
|
-
((_e = err.options) === null || _e === void 0 ? void 0 : _e.code) === '
|
|
63
|
+
((_e = err.options) === null || _e === void 0 ? void 0 : _e.code) === 'STATE_UPDATE_FAILED') {
|
|
54
64
|
return this.sendMessage({ from: 'Api', message: `Error: ${err.message}` }, cb);
|
|
55
65
|
}
|
|
56
66
|
throw err;
|
|
@@ -92,7 +102,7 @@ export default class TurnRequest {
|
|
|
92
102
|
}
|
|
93
103
|
parseResponse(response, callbacks) {
|
|
94
104
|
return __awaiter(this, void 0, void 0, function* () {
|
|
95
|
-
const parser =
|
|
105
|
+
const parser = ResponseParserFactory.getInstance();
|
|
96
106
|
const parsed = yield parser.parse(response, callbacks);
|
|
97
107
|
return parsed;
|
|
98
108
|
});
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { ChatCompletionMessageParam } from 'openai/resources';
|
|
2
2
|
import { SprucebotLlmBot } from '../../llm.types';
|
|
3
|
-
export default class
|
|
3
|
+
export default class MessageBuilder {
|
|
4
4
|
private bot;
|
|
5
5
|
private memoryLimit;
|
|
6
6
|
protected constructor(bot: SprucebotLlmBot, options?: BuildMessageOptions);
|
|
7
|
-
static Builder(bot: SprucebotLlmBot, options?: BuildMessageOptions):
|
|
7
|
+
static Builder(bot: SprucebotLlmBot, options?: BuildMessageOptions): MessageBuilder;
|
|
8
|
+
private get parser();
|
|
8
9
|
buildMessages(): ChatCompletionMessageParam[];
|
|
9
10
|
private buildChatHistoryMessages;
|
|
10
11
|
private mapMessageToCompletion;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import ResponseParserFactory from '../../parsingResponses/ResponseParserFactory.js';
|
|
2
|
+
import { DONE_TOKEN } from '../templates.js';
|
|
3
|
+
export default class MessageBuilder {
|
|
3
4
|
constructor(bot, options) {
|
|
4
5
|
var _a;
|
|
5
6
|
const { memoryLimit } = options !== null && options !== void 0 ? options : {};
|
|
@@ -10,6 +11,9 @@ export default class OpenAiMessageBuilder {
|
|
|
10
11
|
static Builder(bot, options) {
|
|
11
12
|
return new this(bot, options);
|
|
12
13
|
}
|
|
14
|
+
get parser() {
|
|
15
|
+
return ResponseParserFactory.getInstance();
|
|
16
|
+
}
|
|
13
17
|
buildMessages() {
|
|
14
18
|
const values = this.bot.serialize();
|
|
15
19
|
const allMessages = [
|
|
@@ -131,6 +135,8 @@ export default class OpenAiMessageBuilder {
|
|
|
131
135
|
<Parameter${param.isRequired ? ' required="true"' : ''}>
|
|
132
136
|
<Name>${param.name}</Name>
|
|
133
137
|
<Type>${param.type}</Type>
|
|
138
|
+
${param.isArray ? '<IsArray>true</IsArray>' : ''}
|
|
139
|
+
${'minArrayLength' in param ? `<MinArrayLength>${param.minArrayLength}</MinArrayLength>` : ''}
|
|
134
140
|
${param.description ? `<Description>${param.description}</Description>` : ''}${parameterChoices}
|
|
135
141
|
</Parameter>`;
|
|
136
142
|
}
|
|
@@ -143,7 +149,7 @@ export default class OpenAiMessageBuilder {
|
|
|
143
149
|
const api = `<APIReference>\n\n${descriptions.join('\n\n')}</APIReference>`;
|
|
144
150
|
return {
|
|
145
151
|
role: 'system',
|
|
146
|
-
content: `You have an API available to you to lookup answers. When you need the response of the function call to proceed, you can call a function using a custom markup we created
|
|
152
|
+
content: `You have an API available to you to lookup answers. When you need the response of the function call to proceed, you can call a function using a custom markup we created: ${this.parser.getFunctionCallInstructions()}. The API is as follows (in xml format):\n\n${api}`,
|
|
147
153
|
};
|
|
148
154
|
}
|
|
149
155
|
buildPleaseKeepInMindMessage(pleaseKeepInMindThat) {
|
|
@@ -155,7 +161,7 @@ export default class OpenAiMessageBuilder {
|
|
|
155
161
|
buildStateMessage(state) {
|
|
156
162
|
return {
|
|
157
163
|
role: 'system',
|
|
158
|
-
content: `The current state of this conversation is:\n\n${JSON.stringify(state)}. As the
|
|
164
|
+
content: `The current state of this conversation is:\n\n${JSON.stringify(state)}. As the conversation progresses and you need to update state, follow these instructions: ${this.parser.getStateUpdateInstructions()}`,
|
|
159
165
|
};
|
|
160
166
|
}
|
|
161
167
|
buildYourJobMessage(yourJob) {
|
|
@@ -20,8 +20,8 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
20
20
|
};
|
|
21
21
|
import { APIUserAbortError as AnthropicAbortError } from '@anthropic-ai/sdk';
|
|
22
22
|
import { APIUserAbortError } from 'openai';
|
|
23
|
+
import MessageBuilder from './MessageBuilder.js';
|
|
23
24
|
import { MESSAGE_RESPONSE_ERROR_MESSAGE } from './OpenAiAdapter.js';
|
|
24
|
-
import OpenAiMessageBuilder from './OpenAiMessageBuilder.js';
|
|
25
25
|
class MessageSenderImpl {
|
|
26
26
|
constructor(send, log) {
|
|
27
27
|
this.log = log;
|
|
@@ -35,7 +35,7 @@ class MessageSenderImpl {
|
|
|
35
35
|
return __awaiter(this, void 0, void 0, function* () {
|
|
36
36
|
var _a, _b, _c, _d;
|
|
37
37
|
const { memoryLimit } = options, rest = __rest(options, ["memoryLimit"]);
|
|
38
|
-
const messageBuilder =
|
|
38
|
+
const messageBuilder = MessageBuilder.Builder(bot, {
|
|
39
39
|
memoryLimit,
|
|
40
40
|
});
|
|
41
41
|
const messages = messageBuilder.buildMessages();
|
|
@@ -37,6 +37,9 @@ ${options.validCallbacks.map((name, idx) => `${idx + 1}: ${name}`).join('\n')}`;
|
|
|
37
37
|
case 'INVALID_LLM_ADAPTER':
|
|
38
38
|
message = `SPRUCE_LLM_ADAPTER=${options.adapter} is not a valid adapter. Please set SPRUCE_LLM_ADAPTER to a valid adapter (OpenAi, Anthropic, Ollama) and try again.`;
|
|
39
39
|
break;
|
|
40
|
+
case 'STATE_UPDATE_FAILED':
|
|
41
|
+
message = 'A State Update Failed just happened!';
|
|
42
|
+
break;
|
|
40
43
|
default:
|
|
41
44
|
message = super.friendlyMessage();
|
|
42
45
|
}
|
package/build/esm/llm.types.d.ts
CHANGED
|
@@ -103,3 +103,14 @@ export interface SendMessageWithImage {
|
|
|
103
103
|
imageBase64: string;
|
|
104
104
|
}
|
|
105
105
|
export type LllmReasoningEffort = ReasoningEffort;
|
|
106
|
+
export interface ResponseParser {
|
|
107
|
+
parse(response: string, callbacks?: LlmCallbackMap): Promise<ParsedResponse>;
|
|
108
|
+
getStateUpdateInstructions(): string;
|
|
109
|
+
getFunctionCallInstructions(): string;
|
|
110
|
+
}
|
|
111
|
+
export interface ParsedResponse {
|
|
112
|
+
isDone: boolean;
|
|
113
|
+
state?: Record<string, any>;
|
|
114
|
+
message: string;
|
|
115
|
+
callbackResults?: SendMessage;
|
|
116
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ResponseParser } from '../llm.types';
|
|
2
|
+
export default class ResponseParserFactory {
|
|
3
|
+
private static instance;
|
|
4
|
+
private static _version;
|
|
5
|
+
static set version(version: ParserVersion);
|
|
6
|
+
static get version(): ParserVersion;
|
|
7
|
+
static setInstance(parser: ResponseParser): void;
|
|
8
|
+
static getInstance(): ResponseParser;
|
|
9
|
+
}
|
|
10
|
+
export type ParserVersion = 'v1' | 'v2';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import ResponseParserV1 from './ResponseParserV1.js';
|
|
2
|
+
import ResponseParserV2 from './ResponseParserV2.js';
|
|
3
|
+
class ResponseParserFactory {
|
|
4
|
+
static set version(version) {
|
|
5
|
+
this._version = version;
|
|
6
|
+
this.instance =
|
|
7
|
+
version === 'v1' ? new ResponseParserV1() : new ResponseParserV2();
|
|
8
|
+
}
|
|
9
|
+
static get version() {
|
|
10
|
+
return this._version;
|
|
11
|
+
}
|
|
12
|
+
static setInstance(parser) {
|
|
13
|
+
this.instance = parser;
|
|
14
|
+
}
|
|
15
|
+
static getInstance() {
|
|
16
|
+
return this.instance;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
ResponseParserFactory.instance = new ResponseParserV2();
|
|
20
|
+
ResponseParserFactory._version = 'v2';
|
|
21
|
+
export default ResponseParserFactory;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { LlmCallbackMap, ParsedResponse, ResponseParser } from '../llm.types';
|
|
2
|
+
export default class ResponseParserV1 implements ResponseParser {
|
|
3
|
+
parse(response: string, callbacks?: LlmCallbackMap): Promise<ParsedResponse>;
|
|
4
|
+
private validateAndNormalizeCallbackOptions;
|
|
5
|
+
private findFirstBadCallback;
|
|
6
|
+
private invokeCallbackAndDropInLegacyResults;
|
|
7
|
+
private doesIncludeDoneToken;
|
|
8
|
+
private parseState;
|
|
9
|
+
private assertAtMostOneCallback;
|
|
10
|
+
getStateUpdateInstructions(): string;
|
|
11
|
+
getFunctionCallInstructions(): string;
|
|
12
|
+
}
|
|
@@ -7,31 +7,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
11
|
-
var t = {};
|
|
12
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
13
|
-
t[p] = s[p];
|
|
14
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
15
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
16
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
17
|
-
t[p[i]] = s[p[i]];
|
|
18
|
-
}
|
|
19
|
-
return t;
|
|
20
|
-
};
|
|
21
|
-
import { normalizeSchemaValues, validateSchemaValues, } from '@sprucelabs/schema';
|
|
22
10
|
import { DONE_TOKEN, STATE_BOUNDARY } from '../bots/templates.js';
|
|
23
11
|
import SpruceError from '../errors/SpruceError.js';
|
|
24
12
|
import renderPlaceholder from './renderPlaceholder.js';
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
this.instance = parser;
|
|
28
|
-
}
|
|
29
|
-
static getInstance() {
|
|
30
|
-
return this.instance;
|
|
31
|
-
}
|
|
13
|
+
import validateAndNormalizeCallbackOptions from './validateAndNormalizeCallbackOptions.js';
|
|
14
|
+
export default class ResponseParserV1 {
|
|
32
15
|
parse(response, callbacks) {
|
|
33
16
|
return __awaiter(this, void 0, void 0, function* () {
|
|
34
|
-
var _a;
|
|
35
17
|
let message = response.replace(DONE_TOKEN, '').trim();
|
|
36
18
|
let state;
|
|
37
19
|
let callbackResults;
|
|
@@ -68,17 +50,7 @@ class ResponseParser {
|
|
|
68
50
|
try {
|
|
69
51
|
const callback = callbacks === null || callbacks === void 0 ? void 0 : callbacks[key];
|
|
70
52
|
if (data) {
|
|
71
|
-
|
|
72
|
-
id: 'validationSchema',
|
|
73
|
-
fields: {},
|
|
74
|
-
};
|
|
75
|
-
((_a = callback === null || callback === void 0 ? void 0 : callback.parameters) !== null && _a !== void 0 ? _a : []).forEach((param) => {
|
|
76
|
-
const { name } = param, rest = __rest(param, ["name"]);
|
|
77
|
-
schema.fields[name] =
|
|
78
|
-
rest;
|
|
79
|
-
});
|
|
80
|
-
validateSchemaValues(schema, data);
|
|
81
|
-
data = normalizeSchemaValues(schema, data);
|
|
53
|
+
data = this.validateAndNormalizeCallbackOptions(callback, data);
|
|
82
54
|
}
|
|
83
55
|
callbackResults = yield (callback === null || callback === void 0 ? void 0 : callback.cb(data));
|
|
84
56
|
message = message.replace(xmlCallMatches[0], '').trim();
|
|
@@ -113,6 +85,11 @@ class ResponseParser {
|
|
|
113
85
|
};
|
|
114
86
|
});
|
|
115
87
|
}
|
|
88
|
+
validateAndNormalizeCallbackOptions(callback, options) {
|
|
89
|
+
var _a;
|
|
90
|
+
options = validateAndNormalizeCallbackOptions((_a = callback === null || callback === void 0 ? void 0 : callback.parameters) !== null && _a !== void 0 ? _a : [], options);
|
|
91
|
+
return options;
|
|
92
|
+
}
|
|
116
93
|
findFirstBadCallback(message) {
|
|
117
94
|
const simpleMatches = message.match(new RegExp(`<<(.*)\/?>>`, 'g'));
|
|
118
95
|
const extraJsonMatches = message.match(new RegExp(`<<.*?>>(.*?)<<\/.*?>>`, 'gs'));
|
|
@@ -145,6 +122,10 @@ class ResponseParser {
|
|
|
145
122
|
});
|
|
146
123
|
}
|
|
147
124
|
}
|
|
125
|
+
getStateUpdateInstructions() {
|
|
126
|
+
return `Send updates to me in json format (something it can JSON.parse()) at the end of each response (it's not meant for reading, but for parsing, so don't call it out, but send it as we progress), surrounded by the State Boundary (${STATE_BOUNDARY}), like this:\n\n${STATE_BOUNDARY} { "fieldName": "fieldValue" } ${STATE_BOUNDARY}`;
|
|
127
|
+
}
|
|
128
|
+
getFunctionCallInstructions() {
|
|
129
|
+
return `A function call looks like this: <<FunctionName/>>. The API will respond with the results and then you can continue the conversation with your new knowledge. If the api call has parameters, call it like this: <<FunctionName>>{{parametersJsonEncoded}}<</FunctionName>>. Make sure to json encode the data and drop it between the function tags. Note: You can only make one API call at a time`;
|
|
130
|
+
}
|
|
148
131
|
}
|
|
149
|
-
ResponseParser.instance = new ResponseParser();
|
|
150
|
-
export default ResponseParser;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ResponseParser, LlmCallbackMap, ParsedResponse } from '../llm.types';
|
|
2
|
+
export default class ResponseParserV2 implements ResponseParser {
|
|
3
|
+
parse(response: string, callbacks?: LlmCallbackMap): Promise<ParsedResponse>;
|
|
4
|
+
private invokeCallbacks;
|
|
5
|
+
getStateUpdateInstructions(): string;
|
|
6
|
+
getFunctionCallInstructions(): string;
|
|
7
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { DONE_TOKEN } from '../bots/templates.js';
|
|
11
|
+
import validateAndNormalizeCallbackOptions from './validateAndNormalizeCallbackOptions.js';
|
|
12
|
+
export default class ResponseParserV2 {
|
|
13
|
+
parse(response, callbacks) {
|
|
14
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
15
|
+
let message = response.replace(DONE_TOKEN, '').trim();
|
|
16
|
+
let state = undefined;
|
|
17
|
+
let callbackResults = undefined;
|
|
18
|
+
const hasCallbacks = message.includes('@callback');
|
|
19
|
+
if (hasCallbacks) {
|
|
20
|
+
callbackResults = yield this.invokeCallbacks(message, callbacks);
|
|
21
|
+
}
|
|
22
|
+
const hasState = response.includes('@updateState');
|
|
23
|
+
if (hasState) {
|
|
24
|
+
const stateMatch = message.match(/@updateState\s+({[\s\S]*?})\n?/);
|
|
25
|
+
if (stateMatch && stateMatch[1]) {
|
|
26
|
+
state = JSON.parse(stateMatch[1]);
|
|
27
|
+
message = message.replace(stateMatch[0], '').trim();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
isDone: response.includes(DONE_TOKEN),
|
|
32
|
+
message,
|
|
33
|
+
callbackResults,
|
|
34
|
+
state,
|
|
35
|
+
};
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
invokeCallbacks(message, callbacks) {
|
|
39
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
40
|
+
let callbackResults = '';
|
|
41
|
+
const matches = [...message.matchAll(/^@callback\s+({.*})$/gm)];
|
|
42
|
+
for (const match of matches) {
|
|
43
|
+
const callbackData = match && match[1] ? JSON.parse(match[1]) : null;
|
|
44
|
+
const { name, options } = callbackData || {};
|
|
45
|
+
try {
|
|
46
|
+
const callback = callbacks === null || callbacks === void 0 ? void 0 : callbacks[name];
|
|
47
|
+
if (callback === null || callback === void 0 ? void 0 : callback.parameters) {
|
|
48
|
+
validateAndNormalizeCallbackOptions(callback.parameters, options);
|
|
49
|
+
}
|
|
50
|
+
const results = yield (callback === null || callback === void 0 ? void 0 : callback.cb(options));
|
|
51
|
+
callbackResults += `@results ${JSON.stringify({
|
|
52
|
+
name,
|
|
53
|
+
results,
|
|
54
|
+
})}\n`;
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
callbackResults += `@results ${JSON.stringify({
|
|
58
|
+
name,
|
|
59
|
+
error: err,
|
|
60
|
+
})}\n`;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
callbackResults = callbackResults.trim();
|
|
64
|
+
return callbackResults;
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
getStateUpdateInstructions() {
|
|
68
|
+
return 'Updating state works similar to all function calls. Use the following syntax:\n@updateState { "updates": "here" }\n. Make sure to json encode only the fields you want to change. You can update state once and do it at the end of any messages you send.';
|
|
69
|
+
}
|
|
70
|
+
getFunctionCallInstructions() {
|
|
71
|
+
return `A function call is done using the following syntax:\n@callback { "name": "callbackName", "options": {} }\nMake sure to json encode the options and include the name of the callback you want to call. You can call as many callbacks as you want in a single response by including multiple @callback lines.`;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import { validateSchemaValues, normalizeSchemaValues, } from '@sprucelabs/schema';
|
|
13
|
+
export default function validateAndNormalizeCallbackOptions(parameters, options) {
|
|
14
|
+
const schema = {
|
|
15
|
+
id: 'validationSchema',
|
|
16
|
+
fields: {},
|
|
17
|
+
};
|
|
18
|
+
(parameters !== null && parameters !== void 0 ? parameters : []).forEach((param) => {
|
|
19
|
+
const { name } = param, rest = __rest(param, ["name"]);
|
|
20
|
+
schema.fields[name] =
|
|
21
|
+
rest;
|
|
22
|
+
});
|
|
23
|
+
validateSchemaValues(schema, options);
|
|
24
|
+
options = normalizeSchemaValues(schema, options);
|
|
25
|
+
return options;
|
|
26
|
+
}
|
package/build/llm.types.d.ts
CHANGED
|
@@ -103,3 +103,14 @@ export interface SendMessageWithImage {
|
|
|
103
103
|
imageBase64: string;
|
|
104
104
|
}
|
|
105
105
|
export type LllmReasoningEffort = ReasoningEffort;
|
|
106
|
+
export interface ResponseParser {
|
|
107
|
+
parse(response: string, callbacks?: LlmCallbackMap): Promise<ParsedResponse>;
|
|
108
|
+
getStateUpdateInstructions(): string;
|
|
109
|
+
getFunctionCallInstructions(): string;
|
|
110
|
+
}
|
|
111
|
+
export interface ParsedResponse {
|
|
112
|
+
isDone: boolean;
|
|
113
|
+
state?: Record<string, any>;
|
|
114
|
+
message: string;
|
|
115
|
+
callbackResults?: SendMessage;
|
|
116
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ResponseParser } from '../llm.types';
|
|
2
|
+
export default class ResponseParserFactory {
|
|
3
|
+
private static instance;
|
|
4
|
+
private static _version;
|
|
5
|
+
static set version(version: ParserVersion);
|
|
6
|
+
static get version(): ParserVersion;
|
|
7
|
+
static setInstance(parser: ResponseParser): void;
|
|
8
|
+
static getInstance(): ResponseParser;
|
|
9
|
+
}
|
|
10
|
+
export type ParserVersion = 'v1' | 'v2';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const ResponseParserV1_1 = __importDefault(require("./ResponseParserV1"));
|
|
7
|
+
const ResponseParserV2_1 = __importDefault(require("./ResponseParserV2"));
|
|
8
|
+
class ResponseParserFactory {
|
|
9
|
+
static set version(version) {
|
|
10
|
+
this._version = version;
|
|
11
|
+
this.instance =
|
|
12
|
+
version === 'v1' ? new ResponseParserV1_1.default() : new ResponseParserV2_1.default();
|
|
13
|
+
}
|
|
14
|
+
static get version() {
|
|
15
|
+
return this._version;
|
|
16
|
+
}
|
|
17
|
+
static setInstance(parser) {
|
|
18
|
+
this.instance = parser;
|
|
19
|
+
}
|
|
20
|
+
static getInstance() {
|
|
21
|
+
return this.instance;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
ResponseParserFactory.instance = new ResponseParserV2_1.default();
|
|
25
|
+
ResponseParserFactory._version = 'v2';
|
|
26
|
+
exports.default = ResponseParserFactory;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { LlmCallbackMap, ParsedResponse, ResponseParser } from '../llm.types';
|
|
2
|
+
export default class ResponseParserV1 implements ResponseParser {
|
|
3
|
+
parse(response: string, callbacks?: LlmCallbackMap): Promise<ParsedResponse>;
|
|
4
|
+
private validateAndNormalizeCallbackOptions;
|
|
5
|
+
private findFirstBadCallback;
|
|
6
|
+
private invokeCallbackAndDropInLegacyResults;
|
|
7
|
+
private doesIncludeDoneToken;
|
|
8
|
+
private parseState;
|
|
9
|
+
private assertAtMostOneCallback;
|
|
10
|
+
getStateUpdateInstructions(): string;
|
|
11
|
+
getFunctionCallInstructions(): string;
|
|
12
|
+
}
|
|
@@ -3,17 +3,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const schema_1 = require("@sprucelabs/schema");
|
|
7
6
|
const templates_1 = require("../bots/templates");
|
|
8
7
|
const SpruceError_1 = __importDefault(require("../errors/SpruceError"));
|
|
9
8
|
const renderPlaceholder_1 = __importDefault(require("./renderPlaceholder"));
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
this.instance = parser;
|
|
13
|
-
}
|
|
14
|
-
static getInstance() {
|
|
15
|
-
return this.instance;
|
|
16
|
-
}
|
|
9
|
+
const validateAndNormalizeCallbackOptions_1 = __importDefault(require("./validateAndNormalizeCallbackOptions"));
|
|
10
|
+
class ResponseParserV1 {
|
|
17
11
|
async parse(response, callbacks) {
|
|
18
12
|
let message = response.replace(templates_1.DONE_TOKEN, '').trim();
|
|
19
13
|
let state;
|
|
@@ -51,17 +45,7 @@ class ResponseParser {
|
|
|
51
45
|
try {
|
|
52
46
|
const callback = callbacks?.[key];
|
|
53
47
|
if (data) {
|
|
54
|
-
|
|
55
|
-
id: 'validationSchema',
|
|
56
|
-
fields: {},
|
|
57
|
-
};
|
|
58
|
-
(callback?.parameters ?? []).forEach((param) => {
|
|
59
|
-
const { name, ...rest } = param;
|
|
60
|
-
schema.fields[name] =
|
|
61
|
-
rest;
|
|
62
|
-
});
|
|
63
|
-
(0, schema_1.validateSchemaValues)(schema, data);
|
|
64
|
-
data = (0, schema_1.normalizeSchemaValues)(schema, data);
|
|
48
|
+
data = this.validateAndNormalizeCallbackOptions(callback, data);
|
|
65
49
|
}
|
|
66
50
|
callbackResults = await callback?.cb(data);
|
|
67
51
|
message = message.replace(xmlCallMatches[0], '').trim();
|
|
@@ -95,6 +79,10 @@ class ResponseParser {
|
|
|
95
79
|
callbackResults: callbackResults ?? undefined,
|
|
96
80
|
};
|
|
97
81
|
}
|
|
82
|
+
validateAndNormalizeCallbackOptions(callback, options) {
|
|
83
|
+
options = (0, validateAndNormalizeCallbackOptions_1.default)(callback?.parameters ?? [], options);
|
|
84
|
+
return options;
|
|
85
|
+
}
|
|
98
86
|
findFirstBadCallback(message) {
|
|
99
87
|
const simpleMatches = message.match(new RegExp(`<<(.*)\/?>>`, 'g'));
|
|
100
88
|
const extraJsonMatches = message.match(new RegExp(`<<.*?>>(.*?)<<\/.*?>>`, 'gs'));
|
|
@@ -124,6 +112,11 @@ class ResponseParser {
|
|
|
124
112
|
});
|
|
125
113
|
}
|
|
126
114
|
}
|
|
115
|
+
getStateUpdateInstructions() {
|
|
116
|
+
return `Send updates to me in json format (something it can JSON.parse()) at the end of each response (it's not meant for reading, but for parsing, so don't call it out, but send it as we progress), surrounded by the State Boundary (${templates_1.STATE_BOUNDARY}), like this:\n\n${templates_1.STATE_BOUNDARY} { "fieldName": "fieldValue" } ${templates_1.STATE_BOUNDARY}`;
|
|
117
|
+
}
|
|
118
|
+
getFunctionCallInstructions() {
|
|
119
|
+
return `A function call looks like this: <<FunctionName/>>. The API will respond with the results and then you can continue the conversation with your new knowledge. If the api call has parameters, call it like this: <<FunctionName>>{{parametersJsonEncoded}}<</FunctionName>>. Make sure to json encode the data and drop it between the function tags. Note: You can only make one API call at a time`;
|
|
120
|
+
}
|
|
127
121
|
}
|
|
128
|
-
|
|
129
|
-
exports.default = ResponseParser;
|
|
122
|
+
exports.default = ResponseParserV1;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ResponseParser, LlmCallbackMap, ParsedResponse } from '../llm.types';
|
|
2
|
+
export default class ResponseParserV2 implements ResponseParser {
|
|
3
|
+
parse(response: string, callbacks?: LlmCallbackMap): Promise<ParsedResponse>;
|
|
4
|
+
private invokeCallbacks;
|
|
5
|
+
getStateUpdateInstructions(): string;
|
|
6
|
+
getFunctionCallInstructions(): string;
|
|
7
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const templates_1 = require("../bots/templates");
|
|
7
|
+
const validateAndNormalizeCallbackOptions_1 = __importDefault(require("./validateAndNormalizeCallbackOptions"));
|
|
8
|
+
class ResponseParserV2 {
|
|
9
|
+
async parse(response, callbacks) {
|
|
10
|
+
let message = response.replace(templates_1.DONE_TOKEN, '').trim();
|
|
11
|
+
let state = undefined;
|
|
12
|
+
let callbackResults = undefined;
|
|
13
|
+
const hasCallbacks = message.includes('@callback');
|
|
14
|
+
if (hasCallbacks) {
|
|
15
|
+
callbackResults = await this.invokeCallbacks(message, callbacks);
|
|
16
|
+
}
|
|
17
|
+
const hasState = response.includes('@updateState');
|
|
18
|
+
if (hasState) {
|
|
19
|
+
const stateMatch = message.match(/@updateState\s+({[\s\S]*?})\n?/);
|
|
20
|
+
if (stateMatch && stateMatch[1]) {
|
|
21
|
+
state = JSON.parse(stateMatch[1]);
|
|
22
|
+
message = message.replace(stateMatch[0], '').trim();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
isDone: response.includes(templates_1.DONE_TOKEN),
|
|
27
|
+
message,
|
|
28
|
+
callbackResults,
|
|
29
|
+
state,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
async invokeCallbacks(message, callbacks) {
|
|
33
|
+
let callbackResults = '';
|
|
34
|
+
const matches = [...message.matchAll(/^@callback\s+({.*})$/gm)];
|
|
35
|
+
for (const match of matches) {
|
|
36
|
+
const callbackData = match && match[1] ? JSON.parse(match[1]) : null;
|
|
37
|
+
const { name, options } = callbackData || {};
|
|
38
|
+
try {
|
|
39
|
+
const callback = callbacks?.[name];
|
|
40
|
+
if (callback?.parameters) {
|
|
41
|
+
(0, validateAndNormalizeCallbackOptions_1.default)(callback.parameters, options);
|
|
42
|
+
}
|
|
43
|
+
const results = await callback?.cb(options);
|
|
44
|
+
callbackResults += `@results ${JSON.stringify({
|
|
45
|
+
name,
|
|
46
|
+
results,
|
|
47
|
+
})}\n`;
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
callbackResults += `@results ${JSON.stringify({
|
|
51
|
+
name,
|
|
52
|
+
error: err,
|
|
53
|
+
})}\n`;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
callbackResults = callbackResults.trim();
|
|
57
|
+
return callbackResults;
|
|
58
|
+
}
|
|
59
|
+
getStateUpdateInstructions() {
|
|
60
|
+
return 'Updating state works similar to all function calls. Use the following syntax:\n@updateState { "updates": "here" }\n. Make sure to json encode only the fields you want to change. You can update state once and do it at the end of any messages you send.';
|
|
61
|
+
}
|
|
62
|
+
getFunctionCallInstructions() {
|
|
63
|
+
return `A function call is done using the following syntax:\n@callback { "name": "callbackName", "options": {} }\nMake sure to json encode the options and include the name of the callback you want to call. You can call as many callbacks as you want in a single response by including multiple @callback lines.`;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
exports.default = ResponseParserV2;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = validateAndNormalizeCallbackOptions;
|
|
4
|
+
const schema_1 = require("@sprucelabs/schema");
|
|
5
|
+
function validateAndNormalizeCallbackOptions(parameters, options) {
|
|
6
|
+
const schema = {
|
|
7
|
+
id: 'validationSchema',
|
|
8
|
+
fields: {},
|
|
9
|
+
};
|
|
10
|
+
(parameters ?? []).forEach((param) => {
|
|
11
|
+
const { name, ...rest } = param;
|
|
12
|
+
schema.fields[name] =
|
|
13
|
+
rest;
|
|
14
|
+
});
|
|
15
|
+
(0, schema_1.validateSchemaValues)(schema, options);
|
|
16
|
+
options = (0, schema_1.normalizeSchemaValues)(schema, options);
|
|
17
|
+
return options;
|
|
18
|
+
}
|
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"eta"
|
|
9
9
|
]
|
|
10
10
|
},
|
|
11
|
-
"version": "
|
|
11
|
+
"version": "15.0.0",
|
|
12
12
|
"files": [
|
|
13
13
|
"build"
|
|
14
14
|
],
|
|
@@ -67,32 +67,32 @@
|
|
|
67
67
|
"dependencies": {
|
|
68
68
|
"@anthropic-ai/sdk": "^0.78.0",
|
|
69
69
|
"@sprucelabs/error": "^8.1.12",
|
|
70
|
-
"@sprucelabs/mercury-event-emitter": "^46.1.
|
|
71
|
-
"@sprucelabs/mercury-types": "^49.1.
|
|
72
|
-
"@sprucelabs/schema": "^
|
|
73
|
-
"@sprucelabs/spruce-skill-utils": "^34.0.
|
|
70
|
+
"@sprucelabs/mercury-event-emitter": "^46.1.11",
|
|
71
|
+
"@sprucelabs/mercury-types": "^49.1.13",
|
|
72
|
+
"@sprucelabs/schema": "^34.0.0",
|
|
73
|
+
"@sprucelabs/spruce-skill-utils": "^34.0.19",
|
|
74
74
|
"eta": "3.5.0",
|
|
75
|
-
"openai": "^6.
|
|
75
|
+
"openai": "^6.27.0"
|
|
76
76
|
},
|
|
77
77
|
"resolutions": {
|
|
78
78
|
"eta": "3.5.0"
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
|
-
"@regressionproof/cli": "^0.9.
|
|
82
|
-
"@regressionproof/jest-reporter": "^0.9.
|
|
83
|
-
"@sprucelabs/esm-postbuild": "^9.0.
|
|
84
|
-
"@sprucelabs/jest-json-reporter": "^10.0.
|
|
85
|
-
"@sprucelabs/resolve-path-aliases": "^4.0.
|
|
81
|
+
"@regressionproof/cli": "^0.9.4",
|
|
82
|
+
"@regressionproof/jest-reporter": "^0.9.4",
|
|
83
|
+
"@sprucelabs/esm-postbuild": "^9.0.21",
|
|
84
|
+
"@sprucelabs/jest-json-reporter": "^10.0.29",
|
|
85
|
+
"@sprucelabs/resolve-path-aliases": "^4.0.21",
|
|
86
86
|
"@sprucelabs/semantic-release": "^6.0.0",
|
|
87
87
|
"@sprucelabs/test": "^11.1.6",
|
|
88
88
|
"@sprucelabs/test-utils": "^7.2.15",
|
|
89
|
-
"@types/node": "^25.
|
|
89
|
+
"@types/node": "^25.4.0",
|
|
90
90
|
"chokidar-cli": "^3.0.0",
|
|
91
91
|
"dotenv": "^17.3.1",
|
|
92
|
-
"eslint": "^10.0.
|
|
92
|
+
"eslint": "^10.0.3",
|
|
93
93
|
"eslint-config-spruce": "^11.2.35",
|
|
94
|
-
"jest": "^30.
|
|
95
|
-
"jest-circus": "^30.
|
|
94
|
+
"jest": "^30.3.0",
|
|
95
|
+
"jest-circus": "^30.3.0",
|
|
96
96
|
"prettier": "^3.8.1",
|
|
97
97
|
"ts-node": "^10.9.2",
|
|
98
98
|
"tsc-watch": "^7.2.0",
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { LlmCallbackMap, SendMessage } from '../llm.types';
|
|
2
|
-
export default class ResponseParser {
|
|
3
|
-
private static instance;
|
|
4
|
-
static setInstance(parser: ResponseParser): void;
|
|
5
|
-
static getInstance(): ResponseParser;
|
|
6
|
-
parse(response: string, callbacks?: LlmCallbackMap): Promise<ParsedResponse>;
|
|
7
|
-
private findFirstBadCallback;
|
|
8
|
-
private invokeCallbackAndDropInLegacyResults;
|
|
9
|
-
private doesIncludeDoneToken;
|
|
10
|
-
private parseState;
|
|
11
|
-
private assertAtMostOneCallback;
|
|
12
|
-
}
|
|
13
|
-
export interface ParsedResponse {
|
|
14
|
-
isDone: boolean;
|
|
15
|
-
state?: Record<string, any>;
|
|
16
|
-
message: string;
|
|
17
|
-
callbackResults?: SendMessage;
|
|
18
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { LlmCallbackMap, SendMessage } from '../llm.types';
|
|
2
|
-
export default class ResponseParser {
|
|
3
|
-
private static instance;
|
|
4
|
-
static setInstance(parser: ResponseParser): void;
|
|
5
|
-
static getInstance(): ResponseParser;
|
|
6
|
-
parse(response: string, callbacks?: LlmCallbackMap): Promise<ParsedResponse>;
|
|
7
|
-
private findFirstBadCallback;
|
|
8
|
-
private invokeCallbackAndDropInLegacyResults;
|
|
9
|
-
private doesIncludeDoneToken;
|
|
10
|
-
private parseState;
|
|
11
|
-
private assertAtMostOneCallback;
|
|
12
|
-
}
|
|
13
|
-
export interface ParsedResponse {
|
|
14
|
-
isDone: boolean;
|
|
15
|
-
state?: Record<string, any>;
|
|
16
|
-
message: string;
|
|
17
|
-
callbackResults?: SendMessage;
|
|
18
|
-
}
|