@wabot-dev/framework 0.1.0-beta.12 → 0.1.0-beta.13
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/dist/src/ai/claude/ClaudeChatBotAdapter.js +115 -0
- package/dist/src/core/Entity.js +2 -2
- package/dist/src/index.d.ts +11 -2
- package/dist/src/index.js +2 -1
- package/dist/src/node_modules/@anthropic-ai/sdk/_vendor/partial-json-parser/parser.js +221 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/client.js +540 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/core/api-promise.js +74 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/core/error.js +100 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/core/pagination.js +119 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/core/resource.js +8 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/core/streaming.js +283 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/internal/constants.js +16 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/internal/decoders/jsonl.js +37 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/internal/decoders/line.js +110 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/internal/detect-platform.js +159 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/internal/errors.js +37 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/internal/headers.js +71 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/internal/parse.js +53 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/internal/request-options.js +11 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/internal/shims.js +86 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/internal/to-file.js +94 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/internal/tslib.js +14 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/internal/uploads.js +113 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/internal/utils/bytes.js +27 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/internal/utils/env.js +19 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/internal/utils/log.js +82 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/internal/utils/path.js +76 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/internal/utils/sleep.js +4 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/internal/utils/uuid.js +16 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/internal/utils/values.js +48 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/lib/BetaMessageStream.js +588 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/lib/MessageStream.js +582 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/resources/beta/beta.js +19 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/resources/beta/files.js +120 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/resources/beta/messages/batches.js +202 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/resources/beta/messages/messages.js +85 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/resources/beta/models.js +58 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/resources/completions.js +21 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/resources/messages/batches.js +151 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/resources/messages/messages.js +71 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/resources/models.js +43 -0
- package/dist/src/node_modules/@anthropic-ai/sdk/version.js +3 -0
- package/package.json +2 -1
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { __decorate, __metadata } from 'tslib';
|
|
2
|
+
import { injectable } from '../../injection/index.js';
|
|
3
|
+
import { Anthropic } from '../../node_modules/@anthropic-ai/sdk/client.js';
|
|
4
|
+
import '../../node_modules/@anthropic-ai/sdk/core/api-promise.js';
|
|
5
|
+
import '../../node_modules/@anthropic-ai/sdk/core/pagination.js';
|
|
6
|
+
import 'uuid';
|
|
7
|
+
import '../../chatbot/metadata/ChatBotMetadataStore.js';
|
|
8
|
+
import '../../chatbot/ChatBot.js';
|
|
9
|
+
import { ChatBotAdapter } from '../../chatbot/ChatBotAdapter.js';
|
|
10
|
+
import 'reflect-metadata';
|
|
11
|
+
import '../../mindset/metadata/MindsetMetadataStore.js';
|
|
12
|
+
import { MindsetOperator } from '../../mindset/MindsetOperator.js';
|
|
13
|
+
import { Logger } from '../../logger/Logger.js';
|
|
14
|
+
|
|
15
|
+
let ClaudeChatBotAdapter = class ClaudeChatBotAdapter extends ChatBotAdapter {
|
|
16
|
+
anthropic;
|
|
17
|
+
model;
|
|
18
|
+
logger = new Logger('wabot:claude-chat-bot-adapter');
|
|
19
|
+
constructor(mindset) {
|
|
20
|
+
super(mindset);
|
|
21
|
+
const apiKey = process.env.CLAUDE_API_KEY;
|
|
22
|
+
if (!apiKey) {
|
|
23
|
+
throw new Error(`CLAUDE_API_KEY env variable is required`);
|
|
24
|
+
}
|
|
25
|
+
const model = process.env.CLAUDE_CHAT_MODEL;
|
|
26
|
+
if (!model) {
|
|
27
|
+
throw new Error(`CLAUDE_CHAT_MODEL env variable is required`);
|
|
28
|
+
}
|
|
29
|
+
this.anthropic = new Anthropic({ apiKey });
|
|
30
|
+
this.model = model;
|
|
31
|
+
}
|
|
32
|
+
async generateNextChatItem(chatItems) {
|
|
33
|
+
const systemPrompt = await this.systemPrompt();
|
|
34
|
+
const tools = (await this.mindset.allFunctionsDescriptors()).map((fn) => {
|
|
35
|
+
return {
|
|
36
|
+
name: fn.name,
|
|
37
|
+
description: fn.description,
|
|
38
|
+
input_schema: {
|
|
39
|
+
...fn.parameters,
|
|
40
|
+
type: 'object'
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
const messages = this.mapChatItems(chatItems);
|
|
45
|
+
const request = {
|
|
46
|
+
model: this.model,
|
|
47
|
+
max_tokens: 4096,
|
|
48
|
+
system: systemPrompt,
|
|
49
|
+
messages,
|
|
50
|
+
tools: tools.length > 0 ? tools : undefined,
|
|
51
|
+
};
|
|
52
|
+
this.logger.debug(`Call Claude API with Request: ${JSON.stringify(request)}`);
|
|
53
|
+
const response = await this.anthropic.messages.create(request);
|
|
54
|
+
let newChatItem;
|
|
55
|
+
const content = response.content[0];
|
|
56
|
+
if (content.type === 'text') {
|
|
57
|
+
newChatItem = await this.buildBotMessageItem(content.text);
|
|
58
|
+
}
|
|
59
|
+
else if (content.type === 'tool_use') {
|
|
60
|
+
newChatItem = await this.buildFunctionCallItem(content.id, content.name, JSON.stringify(content.input));
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
throw new Error('Not supported Claude Response');
|
|
64
|
+
}
|
|
65
|
+
return newChatItem;
|
|
66
|
+
}
|
|
67
|
+
mapChatItems(chatItems) {
|
|
68
|
+
const messages = [];
|
|
69
|
+
for (const item of chatItems) {
|
|
70
|
+
const itemData = item.getData();
|
|
71
|
+
if (itemData.type === 'CONNECTION_MESSAGE') {
|
|
72
|
+
if (!itemData.content.text) {
|
|
73
|
+
throw new Error('User message content is empty');
|
|
74
|
+
}
|
|
75
|
+
messages.push({ role: 'user', content: itemData.content.text });
|
|
76
|
+
}
|
|
77
|
+
else if (itemData.type === 'BOT_MESSAGE') {
|
|
78
|
+
if (!itemData.content.text) {
|
|
79
|
+
throw new Error('Assistant message content is empty');
|
|
80
|
+
}
|
|
81
|
+
messages.push({ role: 'assistant', content: itemData.content.text });
|
|
82
|
+
}
|
|
83
|
+
else if (itemData.type === 'FUNCTION_CALL') {
|
|
84
|
+
messages.push({
|
|
85
|
+
role: 'assistant',
|
|
86
|
+
content: [
|
|
87
|
+
{
|
|
88
|
+
type: 'tool_use',
|
|
89
|
+
id: itemData.content.id,
|
|
90
|
+
name: itemData.content.name,
|
|
91
|
+
input: JSON.parse(itemData.content.arguments || '{}')
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
});
|
|
95
|
+
messages.push({
|
|
96
|
+
role: 'user',
|
|
97
|
+
content: [
|
|
98
|
+
{
|
|
99
|
+
type: 'tool_result',
|
|
100
|
+
tool_use_id: itemData.content.id,
|
|
101
|
+
content: itemData.content.result || 'No result'
|
|
102
|
+
}
|
|
103
|
+
]
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return messages;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
ClaudeChatBotAdapter = __decorate([
|
|
111
|
+
injectable(),
|
|
112
|
+
__metadata("design:paramtypes", [MindsetOperator])
|
|
113
|
+
], ClaudeChatBotAdapter);
|
|
114
|
+
|
|
115
|
+
export { ClaudeChatBotAdapter };
|
package/dist/src/core/Entity.js
CHANGED
package/dist/src/index.d.ts
CHANGED
|
@@ -64,7 +64,7 @@ interface IPersistentData extends IEntityData {
|
|
|
64
64
|
/**
|
|
65
65
|
* @deprecated Should use Entity
|
|
66
66
|
*/
|
|
67
|
-
declare class
|
|
67
|
+
declare class Persistent<D extends IPersistentData> extends Entity<D> {
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
type IChatType = 'PRIVATE' | 'GROUP';
|
|
@@ -400,6 +400,15 @@ declare class OpenaiChatBotAdapter extends ChatBotAdapter {
|
|
|
400
400
|
private mapChatItems;
|
|
401
401
|
}
|
|
402
402
|
|
|
403
|
+
declare class ClaudeChatBotAdapter extends ChatBotAdapter {
|
|
404
|
+
private anthropic;
|
|
405
|
+
private model;
|
|
406
|
+
private logger;
|
|
407
|
+
constructor(mindset: MindsetOperator);
|
|
408
|
+
generateNextChatItem(chatItems: ChatItem[]): Promise<ChatItem>;
|
|
409
|
+
private mapChatItems;
|
|
410
|
+
}
|
|
411
|
+
|
|
403
412
|
declare function cmd(): (target: object, propertyKey: string | symbol) => void;
|
|
404
413
|
|
|
405
414
|
declare class ChatResolver {
|
|
@@ -1179,4 +1188,4 @@ declare function validateModel<V>(value: any, info: IModelValidatorsInfo<V>): IM
|
|
|
1179
1188
|
|
|
1180
1189
|
declare function validate<V>(value: any, modelConstructor: IConstructor<V>): IModelValidationResult<V>;
|
|
1181
1190
|
|
|
1182
|
-
export { AuthenticationModule, Chat, ChatBot, ChatBotAdapter, ChatBotMetadataStore, ChatItem, ChatMemory, ChatRepository, ChatResolver, CmdChannel, Container, ControllerMetadataStore, CustomError, DeepSeekChatBotAdapter, EmailService, Entity, EnvWhatsAppRepository, ExpressProvider, HtmlModule, HttpServerProvider, type IChannelMetadata, type IChatBot, type IChatBotAdapter, type IChatBotMetadata, type IChatChannel, type IChatConnection, type IChatControllerMetadata, type IChatData, type IChatFunctionCall, type IChatItemData, type IChatItemType, type IChatMemory, type IChatMessage, type IChatRepository, type IChatType, type IConnectionChatMessage, type IConstructor, type ICrudRepository, type ICustomErrorData, type IEmailService, type IEndPointMetadata, type IEntityData, type IGetConfig, type IGetWhatsAppTemplateRequest, type IHtmlModuleOptions, type IListenWhatsAppMessageRequest, type IMessageContext, type IMessageMetadata, type IMiddlewareMetadata, type IMindset, type IMindsetDecoration, type IMindsetFunctionConfig, type IMindsetFunctionDecoration, type IMindsetFunctionMetadata, type IMindsetFunctionParamMetadata, type IMindsetIdentity, type IMindsetMetadata, type IMindsetModuleConfig, type IMindsetModuleDecoration, type IMindsetModuleMetadata, type IModelValidationError, type IModelValidationResult, type IModelValidatorsInfo, type IOtpService, type IParamConfig, type IParamDecoration, type IPersistentData, type IPgRepositoryConfig, type IPostConfig, type IPropertyValidatorInfo, type IReceivedMessage, type IReceivedMessageItem, type IRestControllerConfig, type IRestControllerMetadata, type ISendEmailRequest, type ISendWhatsAppRequest, type ISendWhatsAppTemplateRequest, type IServerConfig, type IServerProvider, type ISocketChannelConfig, type ISocketChannelReceivedMessage, type ISystemFunctionCallItem, type ISystemMessageItem, type ITelegramChannelConfig, type IUserConnection, type IUserData, type IUserRepository, type IValidateMaxOptions, type IValidateMinOptions, type IValidationError, type IValidationResult, type IValidator, type IValidatorMetadata, type IWabotEnvType, type IWhatsAppBusinessAccount, type IWhatsAppBusinessNumber, type IWhatsAppContact, type IWhatsAppData, type IWhatsAppMessage, type IWhatsAppMessageListener, type IWhatsAppRepository, type IWhatsAppSenderOptions, type IWhatsAppTemplate, type IWhatsAppTemplateComponent, type IWhatsAppTemplateMessage, type IWhatsAppTemplateParameter, type IWhatsAppTemplateResponse, type IWhatsAppWebhookPayload, type IWhatsappChannelConfig, type IchatControllerConfig, type IrunChannelProps, Logger, MINDSET_DECORATION_MINDSET, MINDSET_FUNCTION_DECORATION_FUNCTION, MINDSET_MODULE_DECORATION_MODULE, MessageContext, Mindset, MindsetMetadataStore, MindsetOperator, OpenaiChatBotAdapter, OtpService, PARAM_DECORATION_IS_OPTIONAL, PARAM_DECORATION_PARAM,
|
|
1191
|
+
export { AuthenticationModule, Chat, ChatBot, ChatBotAdapter, ChatBotMetadataStore, ChatItem, ChatMemory, ChatRepository, ChatResolver, ClaudeChatBotAdapter, CmdChannel, Container, ControllerMetadataStore, CustomError, DeepSeekChatBotAdapter, EmailService, Entity, EnvWhatsAppRepository, ExpressProvider, HtmlModule, HttpServerProvider, type IChannelMetadata, type IChatBot, type IChatBotAdapter, type IChatBotMetadata, type IChatChannel, type IChatConnection, type IChatControllerMetadata, type IChatData, type IChatFunctionCall, type IChatItemData, type IChatItemType, type IChatMemory, type IChatMessage, type IChatRepository, type IChatType, type IConnectionChatMessage, type IConstructor, type ICrudRepository, type ICustomErrorData, type IEmailService, type IEndPointMetadata, type IEntityData, type IGetConfig, type IGetWhatsAppTemplateRequest, type IHtmlModuleOptions, type IListenWhatsAppMessageRequest, type IMessageContext, type IMessageMetadata, type IMiddlewareMetadata, type IMindset, type IMindsetDecoration, type IMindsetFunctionConfig, type IMindsetFunctionDecoration, type IMindsetFunctionMetadata, type IMindsetFunctionParamMetadata, type IMindsetIdentity, type IMindsetMetadata, type IMindsetModuleConfig, type IMindsetModuleDecoration, type IMindsetModuleMetadata, type IModelValidationError, type IModelValidationResult, type IModelValidatorsInfo, type IOtpService, type IParamConfig, type IParamDecoration, type IPersistentData, type IPgRepositoryConfig, type IPostConfig, type IPropertyValidatorInfo, type IReceivedMessage, type IReceivedMessageItem, type IRestControllerConfig, type IRestControllerMetadata, type ISendEmailRequest, type ISendWhatsAppRequest, type ISendWhatsAppTemplateRequest, type IServerConfig, type IServerProvider, type ISocketChannelConfig, type ISocketChannelReceivedMessage, type ISystemFunctionCallItem, type ISystemMessageItem, type ITelegramChannelConfig, type IUserConnection, type IUserData, type IUserRepository, type IValidateMaxOptions, type IValidateMinOptions, type IValidationError, type IValidationResult, type IValidator, type IValidatorMetadata, type IWabotEnvType, type IWhatsAppBusinessAccount, type IWhatsAppBusinessNumber, type IWhatsAppContact, type IWhatsAppData, type IWhatsAppMessage, type IWhatsAppMessageListener, type IWhatsAppRepository, type IWhatsAppSenderOptions, type IWhatsAppTemplate, type IWhatsAppTemplateComponent, type IWhatsAppTemplateMessage, type IWhatsAppTemplateParameter, type IWhatsAppTemplateResponse, type IWhatsAppWebhookPayload, type IWhatsappChannelConfig, type IchatControllerConfig, type IrunChannelProps, Logger, MINDSET_DECORATION_MINDSET, MINDSET_FUNCTION_DECORATION_FUNCTION, MINDSET_MODULE_DECORATION_MODULE, MessageContext, Mindset, MindsetMetadataStore, MindsetOperator, OpenaiChatBotAdapter, OtpService, PARAM_DECORATION_IS_OPTIONAL, PARAM_DECORATION_PARAM, Persistent, PgChatMemory, PgChatRepository, PgCrudRepository, PgRepositoryBase, PgUserRepository, PgWhatsAppRepository, RamChatMemory, RamChatRepository, RamUserRepository, RegisterUserModule, RegisterUserWithEmailRequest, RestControllerMetadataStore, SendOneTimePasswordRequest, SocketChannel, SocketChannelConfig, SocketServerProvider, TelegramChannel, TelegramChannelConfig, User, UserRepository, UserResolver, ValidateOneTimePasswordRequest, ValidationMetadataStore, WabotEnv, WhatsApp, WhatsAppChannel, WhatsAppReceiver, WhatsAppReceiverByDevConnection, WhatsAppReceiverByWebHook, WhatsAppRepository, WhatsAppSender, WhatsAppSenderByCloudApi, WhatsAppSenderByDevConnection, WhatsappChannelConfig, chatBot, chatController, cmd, container, get, inject, injectable, isBoolean, isDate, isModel, isNotEmpty, isNumber, isOptional, isPresent, isString, max, middleware, min, mindset, mindsetFunction, mindsetModule, param, post, prepareChatContainer, restController, runChannel, runRestControllers, runServer, singleton, socket, telegram, validate, validateIsBoolean, validateIsDate, validateIsNotEmpty, validateIsNumber, validateIsPresent, validateIsString, validateMax, validateMin, validateModel, whatsapp };
|
package/dist/src/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { DeepSeekChatBotAdapter } from './ai/deepseek/DeepSeekChatBotAdapter.js';
|
|
2
2
|
export { OpenaiChatBotAdapter } from './ai/openia/OpenaiChatBotAdapter.js';
|
|
3
|
+
export { ClaudeChatBotAdapter } from './ai/claude/ClaudeChatBotAdapter.js';
|
|
3
4
|
export { cmd } from './channels/cmd/@cmd.js';
|
|
4
5
|
export { CmdChannel } from './channels/cmd/CmdChannel.js';
|
|
5
6
|
export { ExpressProvider } from './channels/express/ExpressProvider.js';
|
|
@@ -39,7 +40,7 @@ export { ChatItem } from './core/chat/ChatItem.js';
|
|
|
39
40
|
export { User } from './core/user/User.js';
|
|
40
41
|
export { UserRepository } from './core/user/IUserRepository.js';
|
|
41
42
|
export { MessageContext } from './core/IMessageContext.js';
|
|
42
|
-
export { Entity,
|
|
43
|
+
export { Entity, Persistent } from './core/Entity.js';
|
|
43
44
|
export { WabotEnv } from './env/WabotEnv.js';
|
|
44
45
|
export { CustomError } from './error/CustomError.js';
|
|
45
46
|
export { container, inject, injectable, singleton } from './injection/index.js';
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
const tokenize = (input) => {
|
|
2
|
+
let current = 0;
|
|
3
|
+
let tokens = [];
|
|
4
|
+
while (current < input.length) {
|
|
5
|
+
let char = input[current];
|
|
6
|
+
if (char === '\\') {
|
|
7
|
+
current++;
|
|
8
|
+
continue;
|
|
9
|
+
}
|
|
10
|
+
if (char === '{') {
|
|
11
|
+
tokens.push({
|
|
12
|
+
type: 'brace',
|
|
13
|
+
value: '{',
|
|
14
|
+
});
|
|
15
|
+
current++;
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
if (char === '}') {
|
|
19
|
+
tokens.push({
|
|
20
|
+
type: 'brace',
|
|
21
|
+
value: '}',
|
|
22
|
+
});
|
|
23
|
+
current++;
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (char === '[') {
|
|
27
|
+
tokens.push({
|
|
28
|
+
type: 'paren',
|
|
29
|
+
value: '[',
|
|
30
|
+
});
|
|
31
|
+
current++;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (char === ']') {
|
|
35
|
+
tokens.push({
|
|
36
|
+
type: 'paren',
|
|
37
|
+
value: ']',
|
|
38
|
+
});
|
|
39
|
+
current++;
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (char === ':') {
|
|
43
|
+
tokens.push({
|
|
44
|
+
type: 'separator',
|
|
45
|
+
value: ':',
|
|
46
|
+
});
|
|
47
|
+
current++;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (char === ',') {
|
|
51
|
+
tokens.push({
|
|
52
|
+
type: 'delimiter',
|
|
53
|
+
value: ',',
|
|
54
|
+
});
|
|
55
|
+
current++;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (char === '"') {
|
|
59
|
+
let value = '';
|
|
60
|
+
let danglingQuote = false;
|
|
61
|
+
char = input[++current];
|
|
62
|
+
while (char !== '"') {
|
|
63
|
+
if (current === input.length) {
|
|
64
|
+
danglingQuote = true;
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
if (char === '\\') {
|
|
68
|
+
current++;
|
|
69
|
+
if (current === input.length) {
|
|
70
|
+
danglingQuote = true;
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
value += char + input[current];
|
|
74
|
+
char = input[++current];
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
value += char;
|
|
78
|
+
char = input[++current];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
char = input[++current];
|
|
82
|
+
if (!danglingQuote) {
|
|
83
|
+
tokens.push({
|
|
84
|
+
type: 'string',
|
|
85
|
+
value,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
let WHITESPACE = /\s/;
|
|
91
|
+
if (char && WHITESPACE.test(char)) {
|
|
92
|
+
current++;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
let NUMBERS = /[0-9]/;
|
|
96
|
+
if ((char && NUMBERS.test(char)) || char === '-' || char === '.') {
|
|
97
|
+
let value = '';
|
|
98
|
+
if (char === '-') {
|
|
99
|
+
value += char;
|
|
100
|
+
char = input[++current];
|
|
101
|
+
}
|
|
102
|
+
while ((char && NUMBERS.test(char)) || char === '.') {
|
|
103
|
+
value += char;
|
|
104
|
+
char = input[++current];
|
|
105
|
+
}
|
|
106
|
+
tokens.push({
|
|
107
|
+
type: 'number',
|
|
108
|
+
value,
|
|
109
|
+
});
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
let LETTERS = /[a-z]/i;
|
|
113
|
+
if (char && LETTERS.test(char)) {
|
|
114
|
+
let value = '';
|
|
115
|
+
while (char && LETTERS.test(char)) {
|
|
116
|
+
if (current === input.length) {
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
value += char;
|
|
120
|
+
char = input[++current];
|
|
121
|
+
}
|
|
122
|
+
if (value == 'true' || value == 'false' || value === 'null') {
|
|
123
|
+
tokens.push({
|
|
124
|
+
type: 'name',
|
|
125
|
+
value,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
// unknown token, e.g. `nul` which isn't quite `null`
|
|
130
|
+
current++;
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
current++;
|
|
136
|
+
}
|
|
137
|
+
return tokens;
|
|
138
|
+
}, strip = (tokens) => {
|
|
139
|
+
if (tokens.length === 0) {
|
|
140
|
+
return tokens;
|
|
141
|
+
}
|
|
142
|
+
let lastToken = tokens[tokens.length - 1];
|
|
143
|
+
switch (lastToken.type) {
|
|
144
|
+
case 'separator':
|
|
145
|
+
tokens = tokens.slice(0, tokens.length - 1);
|
|
146
|
+
return strip(tokens);
|
|
147
|
+
case 'number':
|
|
148
|
+
let lastCharacterOfLastToken = lastToken.value[lastToken.value.length - 1];
|
|
149
|
+
if (lastCharacterOfLastToken === '.' || lastCharacterOfLastToken === '-') {
|
|
150
|
+
tokens = tokens.slice(0, tokens.length - 1);
|
|
151
|
+
return strip(tokens);
|
|
152
|
+
}
|
|
153
|
+
case 'string':
|
|
154
|
+
let tokenBeforeTheLastToken = tokens[tokens.length - 2];
|
|
155
|
+
if (tokenBeforeTheLastToken?.type === 'delimiter') {
|
|
156
|
+
tokens = tokens.slice(0, tokens.length - 1);
|
|
157
|
+
return strip(tokens);
|
|
158
|
+
}
|
|
159
|
+
else if (tokenBeforeTheLastToken?.type === 'brace' && tokenBeforeTheLastToken.value === '{') {
|
|
160
|
+
tokens = tokens.slice(0, tokens.length - 1);
|
|
161
|
+
return strip(tokens);
|
|
162
|
+
}
|
|
163
|
+
break;
|
|
164
|
+
case 'delimiter':
|
|
165
|
+
tokens = tokens.slice(0, tokens.length - 1);
|
|
166
|
+
return strip(tokens);
|
|
167
|
+
}
|
|
168
|
+
return tokens;
|
|
169
|
+
}, unstrip = (tokens) => {
|
|
170
|
+
let tail = [];
|
|
171
|
+
tokens.map((token) => {
|
|
172
|
+
if (token.type === 'brace') {
|
|
173
|
+
if (token.value === '{') {
|
|
174
|
+
tail.push('}');
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
tail.splice(tail.lastIndexOf('}'), 1);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (token.type === 'paren') {
|
|
181
|
+
if (token.value === '[') {
|
|
182
|
+
tail.push(']');
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
tail.splice(tail.lastIndexOf(']'), 1);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
if (tail.length > 0) {
|
|
190
|
+
tail.reverse().map((item) => {
|
|
191
|
+
if (item === '}') {
|
|
192
|
+
tokens.push({
|
|
193
|
+
type: 'brace',
|
|
194
|
+
value: '}',
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
else if (item === ']') {
|
|
198
|
+
tokens.push({
|
|
199
|
+
type: 'paren',
|
|
200
|
+
value: ']',
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
return tokens;
|
|
206
|
+
}, generate = (tokens) => {
|
|
207
|
+
let output = '';
|
|
208
|
+
tokens.map((token) => {
|
|
209
|
+
switch (token.type) {
|
|
210
|
+
case 'string':
|
|
211
|
+
output += '"' + token.value + '"';
|
|
212
|
+
break;
|
|
213
|
+
default:
|
|
214
|
+
output += token.value;
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
return output;
|
|
219
|
+
}, partialParse = (input) => JSON.parse(generate(unstrip(strip(tokenize(input)))));
|
|
220
|
+
|
|
221
|
+
export { partialParse };
|