@nlabs/reaktor 1.16.0 → 1.18.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 +186 -0
- package/docs/ASSISTANT.md +138 -0
- package/docs/GENERATION.md +29 -2
- package/docs/NATIVE_PUSH.md +56 -0
- package/lib/actions/alfredFaq.d.ts +80 -0
- package/lib/actions/alfredFaq.js +206 -0
- package/lib/actions/contentGeneration.d.ts +4 -1
- package/lib/actions/contentGeneration.js +83 -27
- package/lib/actions/contentGenerationErrors.js +1 -1
- package/lib/actions/conversations.d.ts +1 -1
- package/lib/actions/conversations.js +19 -9
- package/lib/actions/crud.js +26 -1
- package/lib/actions/index.d.ts +2 -0
- package/lib/actions/index.js +3 -1
- package/lib/actions/messages.js +23 -7
- package/lib/actions/phoneSupport.d.ts +18 -0
- package/lib/actions/phoneSupport.js +170 -0
- package/lib/actions/users.js +57 -4
- package/lib/assistant/core.d.ts +53 -0
- package/lib/assistant/core.js +123 -0
- package/lib/assistant/faq.d.ts +26 -0
- package/lib/assistant/faq.js +238 -0
- package/lib/assistant/faqCore.d.ts +23 -0
- package/lib/assistant/faqCore.js +20 -0
- package/lib/assistant/index.d.ts +7 -0
- package/lib/assistant/index.js +5 -0
- package/lib/assistant/service.d.ts +35 -0
- package/lib/assistant/service.js +201 -0
- package/lib/config.js +3 -2
- package/lib/durableChat/conversations.d.ts +62 -0
- package/lib/durableChat/conversations.js +729 -0
- package/lib/durableChat/errors.d.ts +6 -0
- package/lib/durableChat/errors.js +11 -0
- package/lib/durableChat/events.d.ts +22 -0
- package/lib/durableChat/events.js +50 -0
- package/lib/durableChat/index.d.ts +8 -0
- package/lib/durableChat/index.js +10 -0
- package/lib/durableChat/membership.d.ts +24 -0
- package/lib/durableChat/membership.js +85 -0
- package/lib/durableChat/messageTypes.d.ts +76 -0
- package/lib/durableChat/messageTypes.js +3 -0
- package/lib/durableChat/messages.d.ts +16 -0
- package/lib/durableChat/messages.js +257 -0
- package/lib/durableChat/transaction.d.ts +10 -0
- package/lib/durableChat/transaction.js +53 -0
- package/lib/durableChat/types.d.ts +81 -0
- package/lib/durableChat/types.js +3 -0
- package/lib/index.d.ts +4 -4
- package/lib/index.js +5 -3
- package/lib/lambdas/actions/websockets.js +4 -4
- package/lib/nativePush/graphql.d.ts +14 -0
- package/lib/nativePush/graphql.js +105 -0
- package/lib/nativePush/index.d.ts +7 -0
- package/lib/nativePush/index.js +9 -0
- package/lib/nativePush/migrations.d.ts +2 -0
- package/lib/nativePush/migrations.js +36 -0
- package/lib/nativePush/nativePushContract.fixture.d.ts +22 -0
- package/lib/nativePush/nativePushContract.fixture.js +27 -0
- package/lib/nativePush/payload.d.ts +2 -0
- package/lib/nativePush/payload.js +106 -0
- package/lib/nativePush/repository.d.ts +9 -0
- package/lib/nativePush/repository.js +120 -0
- package/lib/nativePush/service.d.ts +2 -0
- package/lib/nativePush/service.js +110 -0
- package/lib/nativePush/snsProvider.d.ts +17 -0
- package/lib/nativePush/snsProvider.js +165 -0
- package/lib/nativePush/types.d.ts +89 -0
- package/lib/nativePush/types.js +3 -0
- package/lib/organizations/accountLifecycle.d.ts +7 -0
- package/lib/organizations/accountLifecycle.js +106 -0
- package/lib/organizations/authorization.d.ts +9 -0
- package/lib/organizations/authorization.js +40 -0
- package/lib/organizations/billing.d.ts +38 -0
- package/lib/organizations/billing.js +277 -0
- package/lib/organizations/billingProvider.d.ts +4 -0
- package/lib/organizations/billingProvider.js +287 -0
- package/lib/organizations/billingUpdates.d.ts +9 -0
- package/lib/organizations/billingUpdates.js +388 -0
- package/lib/organizations/index.d.ts +10 -0
- package/lib/organizations/index.js +12 -0
- package/lib/organizations/mail.d.ts +10 -0
- package/lib/organizations/mail.js +60 -0
- package/lib/organizations/memberDirectory.d.ts +15 -0
- package/lib/organizations/memberDirectory.js +28 -0
- package/lib/organizations/membership.d.ts +19 -0
- package/lib/organizations/membership.js +248 -0
- package/lib/organizations/passwordRecovery.d.ts +9 -0
- package/lib/organizations/passwordRecovery.js +50 -0
- package/lib/organizations/plans.d.ts +6 -0
- package/lib/organizations/plans.js +40 -0
- package/lib/organizations/providerPagination.d.ts +6 -0
- package/lib/organizations/providerPagination.js +23 -0
- package/lib/organizations/reconciliation.d.ts +11 -0
- package/lib/organizations/reconciliation.js +400 -0
- package/lib/organizations/signup.d.ts +25 -0
- package/lib/organizations/signup.js +169 -0
- package/lib/organizations/store.d.ts +25 -0
- package/lib/organizations/store.js +167 -0
- package/lib/organizations/types.d.ts +138 -0
- package/lib/organizations/types.js +3 -0
- package/lib/organizations/verification.d.ts +3 -0
- package/lib/organizations/verification.js +51 -0
- package/package.json +16 -3
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { aql } from 'arangojs';
|
|
3
|
+
import { useDb } from '../utils/arangodbUtils.js';
|
|
4
|
+
const hash = (value)=>createHash('sha256').update(value).digest('hex');
|
|
5
|
+
const products = new Set([
|
|
6
|
+
'alfred',
|
|
7
|
+
'nitrogen',
|
|
8
|
+
'nitrogen-labs',
|
|
9
|
+
'nitrogen-studios',
|
|
10
|
+
'reaktor',
|
|
11
|
+
'gothamui',
|
|
12
|
+
'lanternui',
|
|
13
|
+
'metropolisjs',
|
|
14
|
+
'arkhamjs',
|
|
15
|
+
'lex',
|
|
16
|
+
'torchone',
|
|
17
|
+
'pulsify',
|
|
18
|
+
'phantaze',
|
|
19
|
+
'reactorbox'
|
|
20
|
+
]);
|
|
21
|
+
const safeText = (value, max)=>typeof value === 'string' && value.trim().length >= 8 && value.length <= max && !/[@<>]|\b(?:sk_|AKIA)|(?:\d[\s()-]*){7}/i.test(value);
|
|
22
|
+
const vectorValid = (value)=>Array.isArray(value) && value.length === 256 && value.every((n)=>typeof n === 'number' && Number.isFinite(n)) && value.some((n)=>n !== 0);
|
|
23
|
+
const sourceValid = (source)=>{
|
|
24
|
+
try {
|
|
25
|
+
const url = new URL(source.url);
|
|
26
|
+
return typeof source.title === 'string' && source.title.length <= 200 && url.protocol === 'https:' && !url.username && !url.password && !url.search && [
|
|
27
|
+
'nitrogenx.co',
|
|
28
|
+
'www.nitrogenx.co',
|
|
29
|
+
'reaktor.io',
|
|
30
|
+
'torch.one',
|
|
31
|
+
'pulsify.com',
|
|
32
|
+
'phantaze.com',
|
|
33
|
+
'reactorbox.com',
|
|
34
|
+
...[
|
|
35
|
+
'alfred',
|
|
36
|
+
'reaktor',
|
|
37
|
+
'gothamui',
|
|
38
|
+
'lanternui',
|
|
39
|
+
'metropolisjs',
|
|
40
|
+
'arkhamjs',
|
|
41
|
+
'lex'
|
|
42
|
+
].map((name)=>`${name}.nitrogenx.co`)
|
|
43
|
+
].includes(url.hostname);
|
|
44
|
+
} catch {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
export const validateFaqInput = (value)=>{
|
|
49
|
+
const v = value;
|
|
50
|
+
if (!v || !safeText(v.question, 500) || !products.has(v.product) || ![
|
|
51
|
+
'website',
|
|
52
|
+
'phone'
|
|
53
|
+
].includes(v.channel) || !/^[a-f0-9]{64}$/.test(v.eventId) || !vectorValid(v.embedding) || !Number.isSafeInteger(v.revision) || v.revision < 0 || typeof v.topicId !== 'string' || v.topicId && !/^topic-[a-f0-9]{64}$/.test(v.topicId)) throw new Error('invalid_faq_input');
|
|
54
|
+
return {
|
|
55
|
+
channel: v.channel,
|
|
56
|
+
embedding: v.embedding,
|
|
57
|
+
eventId: v.eventId,
|
|
58
|
+
product: v.product,
|
|
59
|
+
question: v.question.trim(),
|
|
60
|
+
revision: v.revision,
|
|
61
|
+
topicId: v.topicId
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
export const publicFaq = (topics, now)=>topics.filter((topic)=>topic.appId === 'nitrogenx' && topic.kind === 'topic' && topic.weight >= 3 && safeText(topic.answer, 2500) && (topic.answerExpires || 0) > now && topic.sources?.length && topic.sources.every(sourceValid)).sort((a, b)=>b.weight - a.weight || b.lastAsked - a.lastAsked || a._key.localeCompare(b._key)).slice(0, 15).map(({ _key, answer, question, sources })=>({
|
|
65
|
+
answer,
|
|
66
|
+
id: _key,
|
|
67
|
+
question,
|
|
68
|
+
sources
|
|
69
|
+
}));
|
|
70
|
+
const cosine = (a, b)=>{
|
|
71
|
+
if (!vectorValid(b)) return -1;
|
|
72
|
+
return a.reduce((sum, n, i)=>sum + n * b[i], 0) / Math.sqrt(a.reduce((sum, n)=>sum + n * n, 0) * b.reduce((sum, n)=>sum + n * n, 0));
|
|
73
|
+
};
|
|
74
|
+
export const faqAction = async (context, operation, value = {})=>{
|
|
75
|
+
const db = useDb(context.databaseName);
|
|
76
|
+
const collection = db.collection('alfredFaq');
|
|
77
|
+
if (!await collection.exists()) {
|
|
78
|
+
try {
|
|
79
|
+
await collection.create();
|
|
80
|
+
} catch (error) {
|
|
81
|
+
if (!await collection.exists()) throw error;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
await collection.ensureIndex({
|
|
85
|
+
fields: [
|
|
86
|
+
'appId',
|
|
87
|
+
'kind',
|
|
88
|
+
'product'
|
|
89
|
+
],
|
|
90
|
+
type: 'persistent'
|
|
91
|
+
});
|
|
92
|
+
const input = value;
|
|
93
|
+
if (operation === 'list' || operation === 'refresh-list') {
|
|
94
|
+
const topics = await db.query(aql`FOR t IN alfredFaq FILTER t.appId == 'nitrogenx' AND t.kind == 'topic' AND t.weight >= 3 SORT t.weight DESC, t.lastAsked DESC, t._key ASC RETURN t`).then((cursor)=>cursor.all());
|
|
95
|
+
return operation === 'list' ? {
|
|
96
|
+
items: publicFaq(topics.filter((topic)=>topic.sourceRevision === input.sourceRevision), Date.now())
|
|
97
|
+
} : {
|
|
98
|
+
items: topics
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
if (operation === 'refresh') {
|
|
102
|
+
if (typeof input.topicId !== 'string' || !/^topic-[a-f0-9]{64}$/.test(input.topicId)) throw new Error('invalid_faq_input');
|
|
103
|
+
const valid = safeText(input.answer, 2500) && Array.isArray(input.sources) && input.sources.length > 0 && input.sources.length <= 3 && input.sources.every(sourceValid) && typeof input.answerExpires === 'number' && input.answerExpires > Date.now() && input.answerExpires <= Date.now() + 14 * 86400000;
|
|
104
|
+
await db.query(aql`FOR t IN alfredFaq FILTER t._key == ${input.topicId} AND t.appId == 'nitrogenx' AND t.kind == 'topic' UPDATE t WITH ${valid ? {
|
|
105
|
+
answer: input.answer,
|
|
106
|
+
answerExpires: input.answerExpires,
|
|
107
|
+
refreshAfter: Date.now() + 12 * 3600000,
|
|
108
|
+
sourceRevision: input.sourceRevision,
|
|
109
|
+
sources: input.sources
|
|
110
|
+
} : {
|
|
111
|
+
answer: null,
|
|
112
|
+
answerExpires: 0,
|
|
113
|
+
refreshAfter: Date.now() + 12 * 3600000,
|
|
114
|
+
sourceRevision: input.sourceRevision,
|
|
115
|
+
sources: []
|
|
116
|
+
}} IN alfredFaq`);
|
|
117
|
+
return {
|
|
118
|
+
ok: true
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
if (operation !== 'record' && operation !== 'candidates') throw new Error('invalid_faq_input');
|
|
122
|
+
const event = validateFaqInput(value);
|
|
123
|
+
const metaKey = `catalog-${event.product}`;
|
|
124
|
+
const tx = await db.beginTransaction({
|
|
125
|
+
exclusive: [
|
|
126
|
+
'alfredFaq'
|
|
127
|
+
]
|
|
128
|
+
}, {
|
|
129
|
+
lockTimeout: 10
|
|
130
|
+
});
|
|
131
|
+
const next = async (query)=>tx.step(()=>db.query(query)).then((cursor)=>cursor.next());
|
|
132
|
+
try {
|
|
133
|
+
if (operation === 'candidates') {
|
|
134
|
+
const meta = await next(aql`RETURN DOCUMENT('alfredFaq', ${metaKey})`);
|
|
135
|
+
const topics = await tx.step(()=>db.query(aql`FOR t IN alfredFaq FILTER t.appId == 'nitrogenx' AND t.kind == 'topic' AND t.product == ${event.product} RETURN t`)).then((cursor)=>cursor.all());
|
|
136
|
+
await tx.commit();
|
|
137
|
+
return {
|
|
138
|
+
candidates: topics.map((topic)=>({
|
|
139
|
+
id: topic._key,
|
|
140
|
+
question: topic.question,
|
|
141
|
+
score: cosine(event.embedding, topic.embedding || [])
|
|
142
|
+
})).filter((topic)=>topic.score >= 0.55).sort((a, b)=>b.score - a.score).slice(0, 8),
|
|
143
|
+
revision: meta?.revision || 0
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
const key = `question-${event.eventId}`;
|
|
147
|
+
const existing = await next(aql`RETURN DOCUMENT('alfredFaq', ${key})`);
|
|
148
|
+
if (existing) {
|
|
149
|
+
await tx.commit();
|
|
150
|
+
return {
|
|
151
|
+
duplicate: true,
|
|
152
|
+
topicId: existing.topicId
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
const meta = await next(aql`RETURN DOCUMENT('alfredFaq', ${metaKey})`);
|
|
156
|
+
if ((meta?.revision || 0) !== event.revision) throw new Error('faq_revision_conflict');
|
|
157
|
+
const topicId = event.topicId || `topic-${hash(`${event.product}:${event.question.toLowerCase()}`)}`;
|
|
158
|
+
const timestamp = Date.now();
|
|
159
|
+
if (event.topicId) {
|
|
160
|
+
const topic = await next(aql`RETURN DOCUMENT('alfredFaq', ${topicId})`);
|
|
161
|
+
if (!topic || topic.appId !== 'nitrogenx' || topic.product !== event.product || topic.kind !== 'topic') throw new Error('invalid_faq_input');
|
|
162
|
+
}
|
|
163
|
+
await next(aql`UPSERT {_key: ${topicId}} INSERT ${{
|
|
164
|
+
_key: topicId,
|
|
165
|
+
answerExpires: 0,
|
|
166
|
+
appId: 'nitrogenx',
|
|
167
|
+
embedding: event.embedding,
|
|
168
|
+
embeddingModel: 'amazon.titan-embed-text-v2:0/256',
|
|
169
|
+
firstAsked: timestamp,
|
|
170
|
+
kind: 'topic',
|
|
171
|
+
lastAsked: timestamp,
|
|
172
|
+
phoneCount: event.channel === 'phone' ? 1 : 0,
|
|
173
|
+
product: event.product,
|
|
174
|
+
question: event.question,
|
|
175
|
+
websiteCount: event.channel === 'website' ? 1 : 0,
|
|
176
|
+
weight: 1
|
|
177
|
+
}} UPDATE {lastAsked: ${timestamp}, weight: OLD.weight + 1, phoneCount: OLD.phoneCount + ${event.channel === 'phone' ? 1 : 0}, websiteCount: OLD.websiteCount + ${event.channel === 'website' ? 1 : 0}} IN alfredFaq`);
|
|
178
|
+
await next(aql`INSERT ${{
|
|
179
|
+
_key: key,
|
|
180
|
+
appId: 'nitrogenx',
|
|
181
|
+
channel: event.channel,
|
|
182
|
+
classifierVersion: 1,
|
|
183
|
+
created: timestamp,
|
|
184
|
+
kind: 'question',
|
|
185
|
+
product: event.product,
|
|
186
|
+
question: event.question,
|
|
187
|
+
topicId
|
|
188
|
+
}} IN alfredFaq`);
|
|
189
|
+
await next(aql`UPSERT {_key: ${metaKey}} INSERT ${{
|
|
190
|
+
_key: metaKey,
|
|
191
|
+
appId: 'nitrogenx',
|
|
192
|
+
kind: 'catalog',
|
|
193
|
+
revision: event.revision + 1
|
|
194
|
+
}} UPDATE {revision: ${event.revision + 1}} IN alfredFaq`);
|
|
195
|
+
await tx.commit();
|
|
196
|
+
return {
|
|
197
|
+
duplicate: false,
|
|
198
|
+
topicId
|
|
199
|
+
};
|
|
200
|
+
} catch (error) {
|
|
201
|
+
await tx.abort();
|
|
202
|
+
throw error;
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9uaXRyb2c3L0RldmVsb3BtZW50L3JlYWt0b3IvcGFja2FnZXMvcmVha3Rvci9zcmMvYWN0aW9ucy9hbGZyZWRGYXEudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtjcmVhdGVIYXNofSBmcm9tICdub2RlOmNyeXB0byc7XG5pbXBvcnQge2FxbH0gZnJvbSAnYXJhbmdvanMnO1xuaW1wb3J0IHt1c2VEYn0gZnJvbSAnLi4vdXRpbHMvYXJhbmdvZGJVdGlscy5qcyc7XG5pbXBvcnQgdHlwZSB7QXBpQ29udGV4dH0gZnJvbSAnLi4vdHlwZXMvYXV0aC50eXBlcy5qcyc7XG5cbmludGVyZmFjZSBGYXFTb3VyY2Uge3RpdGxlOiBzdHJpbmc7IHVybDogc3RyaW5nfVxuaW50ZXJmYWNlIFRvcGljIHsgX2tleTogc3RyaW5nOyBhbnN3ZXI/OiBzdHJpbmc7IGFuc3dlckV4cGlyZXM/OiBudW1iZXI7IGFwcElkOiBzdHJpbmc7IGVtYmVkZGluZz86IG51bWJlcltdOyBraW5kOiBzdHJpbmc7IGxhc3RBc2tlZDogbnVtYmVyOyBwcm9kdWN0Pzogc3RyaW5nOyBxdWVzdGlvbjogc3RyaW5nOyBzb3VyY2VzPzogRmFxU291cmNlW107IHdlaWdodDogbnVtYmVyfVxuaW50ZXJmYWNlIEZhcUlucHV0IHtjaGFubmVsOiAnd2Vic2l0ZScgfCAncGhvbmUnOyBlbWJlZGRpbmc6IG51bWJlcltdOyBldmVudElkOiBzdHJpbmc7IHByb2R1Y3Q6IHN0cmluZzsgcXVlc3Rpb246IHN0cmluZzsgcmV2aXNpb246IG51bWJlcjsgdG9waWNJZDogc3RyaW5nfVxuY29uc3QgaGFzaCA9ICh2YWx1ZTogc3RyaW5nKTogc3RyaW5nID0+IGNyZWF0ZUhhc2goJ3NoYTI1NicpLnVwZGF0ZSh2YWx1ZSkuZGlnZXN0KCdoZXgnKTtcbmNvbnN0IHByb2R1Y3RzID0gbmV3IFNldChbJ2FsZnJlZCcsICduaXRyb2dlbicsICduaXRyb2dlbi1sYWJzJywgJ25pdHJvZ2VuLXN0dWRpb3MnLCAncmVha3RvcicsICdnb3RoYW11aScsICdsYW50ZXJudWknLCAnbWV0cm9wb2xpc2pzJywgJ2Fya2hhbWpzJywgJ2xleCcsICd0b3JjaG9uZScsICdwdWxzaWZ5JywgJ3BoYW50YXplJywgJ3JlYWN0b3Jib3gnXSk7XG5jb25zdCBzYWZlVGV4dCA9ICh2YWx1ZTogdW5rbm93biwgbWF4OiBudW1iZXIpOiB2YWx1ZSBpcyBzdHJpbmcgPT4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyAmJiB2YWx1ZS50cmltKCkubGVuZ3RoID49IDggJiYgdmFsdWUubGVuZ3RoIDw9IG1heCAmJiAhL1tAPD5dfFxcYig/OnNrX3xBS0lBKXwoPzpcXGRbXFxzKCktXSopezd9L2kudGVzdCh2YWx1ZSk7XG5jb25zdCB2ZWN0b3JWYWxpZCA9ICh2YWx1ZTogdW5rbm93bik6IHZhbHVlIGlzIG51bWJlcltdID0+IEFycmF5LmlzQXJyYXkodmFsdWUpICYmIHZhbHVlLmxlbmd0aCA9PT0gMjU2ICYmIHZhbHVlLmV2ZXJ5KChuKSA9PiB0eXBlb2YgbiA9PT0gJ251bWJlcicgJiYgTnVtYmVyLmlzRmluaXRlKG4pKSAmJiB2YWx1ZS5zb21lKChuKSA9PiBuICE9PSAwKTtcbmNvbnN0IHNvdXJjZVZhbGlkID0gKHNvdXJjZTogRmFxU291cmNlKTogYm9vbGVhbiA9PiB7XG4gIHRyeSB7Y29uc3QgdXJsID0gbmV3IFVSTChzb3VyY2UudXJsKTsgcmV0dXJuIHR5cGVvZiBzb3VyY2UudGl0bGUgPT09ICdzdHJpbmcnICYmIHNvdXJjZS50aXRsZS5sZW5ndGggPD0gMjAwICYmIHVybC5wcm90b2NvbCA9PT0gJ2h0dHBzOicgJiYgIXVybC51c2VybmFtZSAmJiAhdXJsLnBhc3N3b3JkICYmICF1cmwuc2VhcmNoICYmIFsnbml0cm9nZW54LmNvJywgJ3d3dy5uaXRyb2dlbnguY28nLCAncmVha3Rvci5pbycsICd0b3JjaC5vbmUnLCAncHVsc2lmeS5jb20nLCAncGhhbnRhemUuY29tJywgJ3JlYWN0b3Jib3guY29tJywgLi4uWydhbGZyZWQnLCAncmVha3RvcicsICdnb3RoYW11aScsICdsYW50ZXJudWknLCAnbWV0cm9wb2xpc2pzJywgJ2Fya2hhbWpzJywgJ2xleCddLm1hcCgobmFtZSkgPT4gYCR7bmFtZX0ubml0cm9nZW54LmNvYCldLmluY2x1ZGVzKHVybC5ob3N0bmFtZSk7fSBjYXRjaCB7cmV0dXJuIGZhbHNlO31cbn07XG5leHBvcnQgY29uc3QgdmFsaWRhdGVGYXFJbnB1dCA9ICh2YWx1ZTogdW5rbm93bik6IEZhcUlucHV0ID0+IHtcbiAgY29uc3QgdiA9IHZhbHVlIGFzIEZhcUlucHV0O1xuICBpZighdiB8fCAhc2FmZVRleHQodi5xdWVzdGlvbiwgNTAwKSB8fCAhcHJvZHVjdHMuaGFzKHYucHJvZHVjdCkgfHwgIVsnd2Vic2l0ZScsICdwaG9uZSddLmluY2x1ZGVzKHYuY2hhbm5lbCkgfHwgIS9eW2EtZjAtOV17NjR9JC8udGVzdCh2LmV2ZW50SWQpIHx8ICF2ZWN0b3JWYWxpZCh2LmVtYmVkZGluZykgfHwgIU51bWJlci5pc1NhZmVJbnRlZ2VyKHYucmV2aXNpb24pIHx8IHYucmV2aXNpb24gPCAwIHx8IHR5cGVvZiB2LnRvcGljSWQgIT09ICdzdHJpbmcnIHx8ICh2LnRvcGljSWQgJiYgIS9edG9waWMtW2EtZjAtOV17NjR9JC8udGVzdCh2LnRvcGljSWQpKSkgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkX2ZhcV9pbnB1dCcpO1xuICByZXR1cm4ge2NoYW5uZWw6IHYuY2hhbm5lbCwgZW1iZWRkaW5nOiB2LmVtYmVkZGluZywgZXZlbnRJZDogdi5ldmVudElkLCBwcm9kdWN0OiB2LnByb2R1Y3QsIHF1ZXN0aW9uOiB2LnF1ZXN0aW9uLnRyaW0oKSwgcmV2aXNpb246IHYucmV2aXNpb24sIHRvcGljSWQ6IHYudG9waWNJZH07XG59O1xuZXhwb3J0IGNvbnN0IHB1YmxpY0ZhcSA9ICh0b3BpY3M6IFRvcGljW10sIG5vdzogbnVtYmVyKSA9PiB0b3BpY3MuZmlsdGVyKCh0b3BpYykgPT4gdG9waWMuYXBwSWQgPT09ICduaXRyb2dlbngnICYmIHRvcGljLmtpbmQgPT09ICd0b3BpYycgJiYgdG9waWMud2VpZ2h0ID49IDMgJiYgc2FmZVRleHQodG9waWMuYW5zd2VyLCAyNTAwKSAmJiAodG9waWMuYW5zd2VyRXhwaXJlcyB8fCAwKSA+IG5vdyAmJiB0b3BpYy5zb3VyY2VzPy5sZW5ndGggJiYgdG9waWMuc291cmNlcy5ldmVyeShzb3VyY2VWYWxpZCkpLnNvcnQoKGEsIGIpID0+IGIud2VpZ2h0IC0gYS53ZWlnaHQgfHwgYi5sYXN0QXNrZWQgLSBhLmxhc3RBc2tlZCB8fCBhLl9rZXkubG9jYWxlQ29tcGFyZShiLl9rZXkpKS5zbGljZSgwLCAxNSkubWFwKCh7X2tleSwgYW5zd2VyLCBxdWVzdGlvbiwgc291cmNlc30pID0+ICh7YW5zd2VyLCBpZDogX2tleSwgcXVlc3Rpb24sIHNvdXJjZXN9KSk7XG5jb25zdCBjb3NpbmUgPSAoYTogbnVtYmVyW10sIGI6IG51bWJlcltdKTogbnVtYmVyID0+IHtcbiAgaWYoIXZlY3RvclZhbGlkKGIpKSByZXR1cm4gLTE7XG4gIHJldHVybiBhLnJlZHVjZSgoc3VtLCBuLCBpKSA9PiBzdW0gKyBuICogYltpXSwgMCkgLyBNYXRoLnNxcnQoYS5yZWR1Y2UoKHN1bSwgbikgPT4gc3VtICsgbiAqIG4sIDApICogYi5yZWR1Y2UoKHN1bSwgbikgPT4gc3VtICsgbiAqIG4sIDApKTtcbn07XG5leHBvcnQgY29uc3QgZmFxQWN0aW9uID0gYXN5bmMgKGNvbnRleHQ6IEFwaUNvbnRleHQsIG9wZXJhdGlvbjogc3RyaW5nLCB2YWx1ZTogdW5rbm93biA9IHt9KSA9PiB7XG4gIGNvbnN0IGRiID0gdXNlRGIoY29udGV4dC5kYXRhYmFzZU5hbWUpO1xuICBjb25zdCBjb2xsZWN0aW9uID0gZGIuY29sbGVjdGlvbignYWxmcmVkRmFxJyk7XG4gIGlmKCFhd2FpdCBjb2xsZWN0aW9uLmV4aXN0cygpKSB7dHJ5IHthd2FpdCBjb2xsZWN0aW9uLmNyZWF0ZSgpO30gY2F0Y2goZXJyb3IpIHtpZighYXdhaXQgY29sbGVjdGlvbi5leGlzdHMoKSkgdGhyb3cgZXJyb3I7fX1cbiAgYXdhaXQgY29sbGVjdGlvbi5lbnN1cmVJbmRleCh7ZmllbGRzOiBbJ2FwcElkJywgJ2tpbmQnLCAncHJvZHVjdCddLCB0eXBlOiAncGVyc2lzdGVudCd9KTtcbiAgY29uc3QgaW5wdXQgPSB2YWx1ZSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgaWYob3BlcmF0aW9uID09PSAnbGlzdCcgfHwgb3BlcmF0aW9uID09PSAncmVmcmVzaC1saXN0Jykge1xuICAgIGNvbnN0IHRvcGljcyA9IGF3YWl0IGRiLnF1ZXJ5KGFxbGBGT1IgdCBJTiBhbGZyZWRGYXEgRklMVEVSIHQuYXBwSWQgPT0gJ25pdHJvZ2VueCcgQU5EIHQua2luZCA9PSAndG9waWMnIEFORCB0LndlaWdodCA+PSAzIFNPUlQgdC53ZWlnaHQgREVTQywgdC5sYXN0QXNrZWQgREVTQywgdC5fa2V5IEFTQyBSRVRVUk4gdGApLnRoZW4oKGN1cnNvcikgPT4gY3Vyc29yLmFsbCgpKSBhcyBUb3BpY1tdO1xuICAgIHJldHVybiBvcGVyYXRpb24gPT09ICdsaXN0JyA/IHtpdGVtczogcHVibGljRmFxKHRvcGljcy5maWx0ZXIoKHRvcGljKSA9PiAodG9waWMgYXMgVG9waWMgJiB7c291cmNlUmV2aXNpb24/OiBzdHJpbmd9KS5zb3VyY2VSZXZpc2lvbiA9PT0gaW5wdXQuc291cmNlUmV2aXNpb24pLCBEYXRlLm5vdygpKX0gOiB7aXRlbXM6IHRvcGljc307XG4gIH1cbiAgaWYob3BlcmF0aW9uID09PSAncmVmcmVzaCcpIHtcbiAgICBpZih0eXBlb2YgaW5wdXQudG9waWNJZCAhPT0gJ3N0cmluZycgfHwgIS9edG9waWMtW2EtZjAtOV17NjR9JC8udGVzdChpbnB1dC50b3BpY0lkKSkgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkX2ZhcV9pbnB1dCcpO1xuICAgIGNvbnN0IHZhbGlkID0gc2FmZVRleHQoaW5wdXQuYW5zd2VyLCAyNTAwKSAmJiBBcnJheS5pc0FycmF5KGlucHV0LnNvdXJjZXMpICYmIGlucHV0LnNvdXJjZXMubGVuZ3RoID4gMCAmJiBpbnB1dC5zb3VyY2VzLmxlbmd0aCA8PSAzICYmIGlucHV0LnNvdXJjZXMuZXZlcnkoc291cmNlVmFsaWQpICYmIHR5cGVvZiBpbnB1dC5hbnN3ZXJFeHBpcmVzID09PSAnbnVtYmVyJyAmJiBpbnB1dC5hbnN3ZXJFeHBpcmVzID4gRGF0ZS5ub3coKSAmJiBpbnB1dC5hbnN3ZXJFeHBpcmVzIDw9IERhdGUubm93KCkgKyAxNCAqIDg2NDAwMDAwO1xuICAgIGF3YWl0IGRiLnF1ZXJ5KGFxbGBGT1IgdCBJTiBhbGZyZWRGYXEgRklMVEVSIHQuX2tleSA9PSAke2lucHV0LnRvcGljSWR9IEFORCB0LmFwcElkID09ICduaXRyb2dlbngnIEFORCB0LmtpbmQgPT0gJ3RvcGljJyBVUERBVEUgdCBXSVRIICR7dmFsaWQgPyB7YW5zd2VyOiBpbnB1dC5hbnN3ZXIsIGFuc3dlckV4cGlyZXM6IGlucHV0LmFuc3dlckV4cGlyZXMsIHJlZnJlc2hBZnRlcjogRGF0ZS5ub3coKSArIDEyICogMzYwMDAwMCwgc291cmNlUmV2aXNpb246IGlucHV0LnNvdXJjZVJldmlzaW9uLCBzb3VyY2VzOiBpbnB1dC5zb3VyY2VzfSA6IHthbnN3ZXI6IG51bGwsIGFuc3dlckV4cGlyZXM6IDAsIHJlZnJlc2hBZnRlcjogRGF0ZS5ub3coKSArIDEyICogMzYwMDAwMCwgc291cmNlUmV2aXNpb246IGlucHV0LnNvdXJjZVJldmlzaW9uLCBzb3VyY2VzOiBbXX19IElOIGFsZnJlZEZhcWApO1xuICAgIHJldHVybiB7b2s6IHRydWV9O1xuICB9XG4gIGlmKG9wZXJhdGlvbiAhPT0gJ3JlY29yZCcgJiYgb3BlcmF0aW9uICE9PSAnY2FuZGlkYXRlcycpIHRocm93IG5ldyBFcnJvcignaW52YWxpZF9mYXFfaW5wdXQnKTtcbiAgY29uc3QgZXZlbnQgPSB2YWxpZGF0ZUZhcUlucHV0KHZhbHVlKTtcbiAgY29uc3QgbWV0YUtleSA9IGBjYXRhbG9nLSR7ZXZlbnQucHJvZHVjdH1gO1xuICBjb25zdCB0eCA9IGF3YWl0IGRiLmJlZ2luVHJhbnNhY3Rpb24oe2V4Y2x1c2l2ZTogWydhbGZyZWRGYXEnXX0sIHtsb2NrVGltZW91dDogMTB9KTtcbiAgY29uc3QgbmV4dCA9IGFzeW5jIChxdWVyeTogUmV0dXJuVHlwZTx0eXBlb2YgYXFsPikgPT4gdHguc3RlcCgoKSA9PiBkYi5xdWVyeShxdWVyeSkpLnRoZW4oKGN1cnNvcikgPT4gY3Vyc29yLm5leHQoKSBhcyBQcm9taXNlPHthcHBJZD86IHN0cmluZzsga2luZD86IHN0cmluZzsgcHJvZHVjdD86IHN0cmluZzsgcmV2aXNpb24/OiBudW1iZXI7IHRvcGljSWQ/OiBzdHJpbmd9IHwgbnVsbD4pO1xuICB0cnkge1xuICAgIGlmKG9wZXJhdGlvbiA9PT0gJ2NhbmRpZGF0ZXMnKSB7XG4gICAgICBjb25zdCBtZXRhID0gYXdhaXQgbmV4dChhcWxgUkVUVVJOIERPQ1VNRU5UKCdhbGZyZWRGYXEnLCAke21ldGFLZXl9KWApO1xuICAgICAgY29uc3QgdG9waWNzID0gYXdhaXQgdHguc3RlcCgoKSA9PiBkYi5xdWVyeShhcWxgRk9SIHQgSU4gYWxmcmVkRmFxIEZJTFRFUiB0LmFwcElkID09ICduaXRyb2dlbngnIEFORCB0LmtpbmQgPT0gJ3RvcGljJyBBTkQgdC5wcm9kdWN0ID09ICR7ZXZlbnQucHJvZHVjdH0gUkVUVVJOIHRgKSkudGhlbigoY3Vyc29yKSA9PiBjdXJzb3IuYWxsKCkpIGFzIFRvcGljW107XG4gICAgICBhd2FpdCB0eC5jb21taXQoKTtcbiAgICAgIHJldHVybiB7Y2FuZGlkYXRlczogdG9waWNzLm1hcCgodG9waWMpID0+ICh7aWQ6IHRvcGljLl9rZXksIHF1ZXN0aW9uOiB0b3BpYy5xdWVzdGlvbiwgc2NvcmU6IGNvc2luZShldmVudC5lbWJlZGRpbmcsIHRvcGljLmVtYmVkZGluZyB8fCBbXSl9KSkuZmlsdGVyKCh0b3BpYykgPT4gdG9waWMuc2NvcmUgPj0gMC41NSkuc29ydCgoYSwgYikgPT4gYi5zY29yZSAtIGEuc2NvcmUpLnNsaWNlKDAsIDgpLCByZXZpc2lvbjogbWV0YT8ucmV2aXNpb24gfHwgMH07XG4gICAgfVxuICAgIGNvbnN0IGtleSA9IGBxdWVzdGlvbi0ke2V2ZW50LmV2ZW50SWR9YDtcbiAgICBjb25zdCBleGlzdGluZyA9IGF3YWl0IG5leHQoYXFsYFJFVFVSTiBET0NVTUVOVCgnYWxmcmVkRmFxJywgJHtrZXl9KWApO1xuICAgIGlmKGV4aXN0aW5nKSB7YXdhaXQgdHguY29tbWl0KCk7IHJldHVybiB7ZHVwbGljYXRlOiB0cnVlLCB0b3BpY0lkOiBleGlzdGluZy50b3BpY0lkfTt9XG4gICAgY29uc3QgbWV0YSA9IGF3YWl0IG5leHQoYXFsYFJFVFVSTiBET0NVTUVOVCgnYWxmcmVkRmFxJywgJHttZXRhS2V5fSlgKTtcbiAgICBpZigobWV0YT8ucmV2aXNpb24gfHwgMCkgIT09IGV2ZW50LnJldmlzaW9uKSB0aHJvdyBuZXcgRXJyb3IoJ2ZhcV9yZXZpc2lvbl9jb25mbGljdCcpO1xuICAgIGNvbnN0IHRvcGljSWQgPSBldmVudC50b3BpY0lkIHx8IGB0b3BpYy0ke2hhc2goYCR7ZXZlbnQucHJvZHVjdH06JHtldmVudC5xdWVzdGlvbi50b0xvd2VyQ2FzZSgpfWApfWA7XG4gICAgY29uc3QgdGltZXN0YW1wID0gRGF0ZS5ub3coKTtcbiAgICBpZihldmVudC50b3BpY0lkKSB7XG4gICAgICBjb25zdCB0b3BpYyA9IGF3YWl0IG5leHQoYXFsYFJFVFVSTiBET0NVTUVOVCgnYWxmcmVkRmFxJywgJHt0b3BpY0lkfSlgKTtcbiAgICAgIGlmKCF0b3BpYyB8fCB0b3BpYy5hcHBJZCAhPT0gJ25pdHJvZ2VueCcgfHwgdG9waWMucHJvZHVjdCAhPT0gZXZlbnQucHJvZHVjdCB8fCB0b3BpYy5raW5kICE9PSAndG9waWMnKSB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWRfZmFxX2lucHV0Jyk7XG4gICAgfVxuICAgIGF3YWl0IG5leHQoYXFsYFVQU0VSVCB7X2tleTogJHt0b3BpY0lkfX0gSU5TRVJUICR7e19rZXk6IHRvcGljSWQsIGFuc3dlckV4cGlyZXM6IDAsIGFwcElkOiAnbml0cm9nZW54JywgZW1iZWRkaW5nOiBldmVudC5lbWJlZGRpbmcsIGVtYmVkZGluZ01vZGVsOiAnYW1hem9uLnRpdGFuLWVtYmVkLXRleHQtdjI6MC8yNTYnLCBmaXJzdEFza2VkOiB0aW1lc3RhbXAsIGtpbmQ6ICd0b3BpYycsIGxhc3RBc2tlZDogdGltZXN0YW1wLCBwaG9uZUNvdW50OiBldmVudC5jaGFubmVsID09PSAncGhvbmUnID8gMSA6IDAsIHByb2R1Y3Q6IGV2ZW50LnByb2R1Y3QsIHF1ZXN0aW9uOiBldmVudC5xdWVzdGlvbiwgd2Vic2l0ZUNvdW50OiBldmVudC5jaGFubmVsID09PSAnd2Vic2l0ZScgPyAxIDogMCwgd2VpZ2h0OiAxfX0gVVBEQVRFIHtsYXN0QXNrZWQ6ICR7dGltZXN0YW1wfSwgd2VpZ2h0OiBPTEQud2VpZ2h0ICsgMSwgcGhvbmVDb3VudDogT0xELnBob25lQ291bnQgKyAke2V2ZW50LmNoYW5uZWwgPT09ICdwaG9uZScgPyAxIDogMH0sIHdlYnNpdGVDb3VudDogT0xELndlYnNpdGVDb3VudCArICR7ZXZlbnQuY2hhbm5lbCA9PT0gJ3dlYnNpdGUnID8gMSA6IDB9fSBJTiBhbGZyZWRGYXFgKTtcbiAgICBhd2FpdCBuZXh0KGFxbGBJTlNFUlQgJHt7X2tleToga2V5LCBhcHBJZDogJ25pdHJvZ2VueCcsIGNoYW5uZWw6IGV2ZW50LmNoYW5uZWwsIGNsYXNzaWZpZXJWZXJzaW9uOiAxLCBjcmVhdGVkOiB0aW1lc3RhbXAsIGtpbmQ6ICdxdWVzdGlvbicsIHByb2R1Y3Q6IGV2ZW50LnByb2R1Y3QsIHF1ZXN0aW9uOiBldmVudC5xdWVzdGlvbiwgdG9waWNJZH19IElOIGFsZnJlZEZhcWApO1xuICAgIGF3YWl0IG5leHQoYXFsYFVQU0VSVCB7X2tleTogJHttZXRhS2V5fX0gSU5TRVJUICR7e19rZXk6IG1ldGFLZXksIGFwcElkOiAnbml0cm9nZW54Jywga2luZDogJ2NhdGFsb2cnLCByZXZpc2lvbjogZXZlbnQucmV2aXNpb24gKyAxfX0gVVBEQVRFIHtyZXZpc2lvbjogJHtldmVudC5yZXZpc2lvbiArIDF9fSBJTiBhbGZyZWRGYXFgKTtcbiAgICBhd2FpdCB0eC5jb21taXQoKTtcbiAgICByZXR1cm4ge2R1cGxpY2F0ZTogZmFsc2UsIHRvcGljSWR9O1xuICB9IGNhdGNoKGVycm9yKSB7YXdhaXQgdHguYWJvcnQoKTsgdGhyb3cgZXJyb3I7fVxufTtcbiJdLCJuYW1lcyI6WyJjcmVhdGVIYXNoIiwiYXFsIiwidXNlRGIiLCJoYXNoIiwidmFsdWUiLCJ1cGRhdGUiLCJkaWdlc3QiLCJwcm9kdWN0cyIsIlNldCIsInNhZmVUZXh0IiwibWF4IiwidHJpbSIsImxlbmd0aCIsInRlc3QiLCJ2ZWN0b3JWYWxpZCIsIkFycmF5IiwiaXNBcnJheSIsImV2ZXJ5IiwibiIsIk51bWJlciIsImlzRmluaXRlIiwic29tZSIsInNvdXJjZVZhbGlkIiwic291cmNlIiwidXJsIiwiVVJMIiwidGl0bGUiLCJwcm90b2NvbCIsInVzZXJuYW1lIiwicGFzc3dvcmQiLCJzZWFyY2giLCJtYXAiLCJuYW1lIiwiaW5jbHVkZXMiLCJob3N0bmFtZSIsInZhbGlkYXRlRmFxSW5wdXQiLCJ2IiwicXVlc3Rpb24iLCJoYXMiLCJwcm9kdWN0IiwiY2hhbm5lbCIsImV2ZW50SWQiLCJlbWJlZGRpbmciLCJpc1NhZmVJbnRlZ2VyIiwicmV2aXNpb24iLCJ0b3BpY0lkIiwiRXJyb3IiLCJwdWJsaWNGYXEiLCJ0b3BpY3MiLCJub3ciLCJmaWx0ZXIiLCJ0b3BpYyIsImFwcElkIiwia2luZCIsIndlaWdodCIsImFuc3dlciIsImFuc3dlckV4cGlyZXMiLCJzb3VyY2VzIiwic29ydCIsImEiLCJiIiwibGFzdEFza2VkIiwiX2tleSIsImxvY2FsZUNvbXBhcmUiLCJzbGljZSIsImlkIiwiY29zaW5lIiwicmVkdWNlIiwic3VtIiwiaSIsIk1hdGgiLCJzcXJ0IiwiZmFxQWN0aW9uIiwiY29udGV4dCIsIm9wZXJhdGlvbiIsImRiIiwiZGF0YWJhc2VOYW1lIiwiY29sbGVjdGlvbiIsImV4aXN0cyIsImNyZWF0ZSIsImVycm9yIiwiZW5zdXJlSW5kZXgiLCJmaWVsZHMiLCJ0eXBlIiwiaW5wdXQiLCJxdWVyeSIsInRoZW4iLCJjdXJzb3IiLCJhbGwiLCJpdGVtcyIsInNvdXJjZVJldmlzaW9uIiwiRGF0ZSIsInZhbGlkIiwicmVmcmVzaEFmdGVyIiwib2siLCJldmVudCIsIm1ldGFLZXkiLCJ0eCIsImJlZ2luVHJhbnNhY3Rpb24iLCJleGNsdXNpdmUiLCJsb2NrVGltZW91dCIsIm5leHQiLCJzdGVwIiwibWV0YSIsImNvbW1pdCIsImNhbmRpZGF0ZXMiLCJzY29yZSIsImtleSIsImV4aXN0aW5nIiwiZHVwbGljYXRlIiwidG9Mb3dlckNhc2UiLCJ0aW1lc3RhbXAiLCJlbWJlZGRpbmdNb2RlbCIsImZpcnN0QXNrZWQiLCJwaG9uZUNvdW50Iiwid2Vic2l0ZUNvdW50IiwiY2xhc3NpZmllclZlcnNpb24iLCJjcmVhdGVkIiwiYWJvcnQiXSwibWFwcGluZ3MiOiJBQUFBLFNBQVFBLFVBQVUsUUFBTyxjQUFjO0FBQ3ZDLFNBQVFDLEdBQUcsUUFBTyxXQUFXO0FBQzdCLFNBQVFDLEtBQUssUUFBTyw0QkFBNEI7QUFNaEQsTUFBTUMsT0FBTyxDQUFDQyxRQUEwQkosV0FBVyxVQUFVSyxNQUFNLENBQUNELE9BQU9FLE1BQU0sQ0FBQztBQUNsRixNQUFNQyxXQUFXLElBQUlDLElBQUk7SUFBQztJQUFVO0lBQVk7SUFBaUI7SUFBb0I7SUFBVztJQUFZO0lBQWE7SUFBZ0I7SUFBWTtJQUFPO0lBQVk7SUFBVztJQUFZO0NBQWE7QUFDNU0sTUFBTUMsV0FBVyxDQUFDTCxPQUFnQk0sTUFBaUMsT0FBT04sVUFBVSxZQUFZQSxNQUFNTyxJQUFJLEdBQUdDLE1BQU0sSUFBSSxLQUFLUixNQUFNUSxNQUFNLElBQUlGLE9BQU8sQ0FBQywwQ0FBMENHLElBQUksQ0FBQ1Q7QUFDbk0sTUFBTVUsY0FBYyxDQUFDVixRQUFzQ1csTUFBTUMsT0FBTyxDQUFDWixVQUFVQSxNQUFNUSxNQUFNLEtBQUssT0FBT1IsTUFBTWEsS0FBSyxDQUFDLENBQUNDLElBQU0sT0FBT0EsTUFBTSxZQUFZQyxPQUFPQyxRQUFRLENBQUNGLE9BQU9kLE1BQU1pQixJQUFJLENBQUMsQ0FBQ0gsSUFBTUEsTUFBTTtBQUN0TSxNQUFNSSxjQUFjLENBQUNDO0lBQ25CLElBQUk7UUFBQyxNQUFNQyxNQUFNLElBQUlDLElBQUlGLE9BQU9DLEdBQUc7UUFBRyxPQUFPLE9BQU9ELE9BQU9HLEtBQUssS0FBSyxZQUFZSCxPQUFPRyxLQUFLLENBQUNkLE1BQU0sSUFBSSxPQUFPWSxJQUFJRyxRQUFRLEtBQUssWUFBWSxDQUFDSCxJQUFJSSxRQUFRLElBQUksQ0FBQ0osSUFBSUssUUFBUSxJQUFJLENBQUNMLElBQUlNLE1BQU0sSUFBSTtZQUFDO1lBQWdCO1lBQW9CO1lBQWM7WUFBYTtZQUFlO1lBQWdCO2VBQXFCO2dCQUFDO2dCQUFVO2dCQUFXO2dCQUFZO2dCQUFhO2dCQUFnQjtnQkFBWTthQUFNLENBQUNDLEdBQUcsQ0FBQyxDQUFDQyxPQUFTLEdBQUdBLEtBQUssYUFBYSxDQUFDO1NBQUUsQ0FBQ0MsUUFBUSxDQUFDVCxJQUFJVSxRQUFRO0lBQUUsRUFBRSxPQUFNO1FBQUMsT0FBTztJQUFNO0FBQ3pkO0FBQ0EsT0FBTyxNQUFNQyxtQkFBbUIsQ0FBQy9CO0lBQy9CLE1BQU1nQyxJQUFJaEM7SUFDVixJQUFHLENBQUNnQyxLQUFLLENBQUMzQixTQUFTMkIsRUFBRUMsUUFBUSxFQUFFLFFBQVEsQ0FBQzlCLFNBQVMrQixHQUFHLENBQUNGLEVBQUVHLE9BQU8sS0FBSyxDQUFDO1FBQUM7UUFBVztLQUFRLENBQUNOLFFBQVEsQ0FBQ0csRUFBRUksT0FBTyxLQUFLLENBQUMsaUJBQWlCM0IsSUFBSSxDQUFDdUIsRUFBRUssT0FBTyxLQUFLLENBQUMzQixZQUFZc0IsRUFBRU0sU0FBUyxLQUFLLENBQUN2QixPQUFPd0IsYUFBYSxDQUFDUCxFQUFFUSxRQUFRLEtBQUtSLEVBQUVRLFFBQVEsR0FBRyxLQUFLLE9BQU9SLEVBQUVTLE9BQU8sS0FBSyxZQUFhVCxFQUFFUyxPQUFPLElBQUksQ0FBQyx1QkFBdUJoQyxJQUFJLENBQUN1QixFQUFFUyxPQUFPLEdBQUksTUFBTSxJQUFJQyxNQUFNO0lBQ2xWLE9BQU87UUFBQ04sU0FBU0osRUFBRUksT0FBTztRQUFFRSxXQUFXTixFQUFFTSxTQUFTO1FBQUVELFNBQVNMLEVBQUVLLE9BQU87UUFBRUYsU0FBU0gsRUFBRUcsT0FBTztRQUFFRixVQUFVRCxFQUFFQyxRQUFRLENBQUMxQixJQUFJO1FBQUlpQyxVQUFVUixFQUFFUSxRQUFRO1FBQUVDLFNBQVNULEVBQUVTLE9BQU87SUFBQTtBQUNuSyxFQUFFO0FBQ0YsT0FBTyxNQUFNRSxZQUFZLENBQUNDLFFBQWlCQyxNQUFnQkQsT0FBT0UsTUFBTSxDQUFDLENBQUNDLFFBQVVBLE1BQU1DLEtBQUssS0FBSyxlQUFlRCxNQUFNRSxJQUFJLEtBQUssV0FBV0YsTUFBTUcsTUFBTSxJQUFJLEtBQUs3QyxTQUFTMEMsTUFBTUksTUFBTSxFQUFFLFNBQVMsQUFBQ0osQ0FBQUEsTUFBTUssYUFBYSxJQUFJLENBQUEsSUFBS1AsT0FBT0UsTUFBTU0sT0FBTyxFQUFFN0MsVUFBVXVDLE1BQU1NLE9BQU8sQ0FBQ3hDLEtBQUssQ0FBQ0ssY0FBY29DLElBQUksQ0FBQyxDQUFDQyxHQUFHQyxJQUFNQSxFQUFFTixNQUFNLEdBQUdLLEVBQUVMLE1BQU0sSUFBSU0sRUFBRUMsU0FBUyxHQUFHRixFQUFFRSxTQUFTLElBQUlGLEVBQUVHLElBQUksQ0FBQ0MsYUFBYSxDQUFDSCxFQUFFRSxJQUFJLEdBQUdFLEtBQUssQ0FBQyxHQUFHLElBQUlqQyxHQUFHLENBQUMsQ0FBQyxFQUFDK0IsSUFBSSxFQUFFUCxNQUFNLEVBQUVsQixRQUFRLEVBQUVvQixPQUFPLEVBQUMsR0FBTSxDQUFBO1lBQUNGO1lBQVFVLElBQUlIO1lBQU16QjtZQUFVb0I7UUFBTyxDQUFBLEdBQUk7QUFDbmUsTUFBTVMsU0FBUyxDQUFDUCxHQUFhQztJQUMzQixJQUFHLENBQUM5QyxZQUFZOEMsSUFBSSxPQUFPLENBQUM7SUFDNUIsT0FBT0QsRUFBRVEsTUFBTSxDQUFDLENBQUNDLEtBQUtsRCxHQUFHbUQsSUFBTUQsTUFBTWxELElBQUkwQyxDQUFDLENBQUNTLEVBQUUsRUFBRSxLQUFLQyxLQUFLQyxJQUFJLENBQUNaLEVBQUVRLE1BQU0sQ0FBQyxDQUFDQyxLQUFLbEQsSUFBTWtELE1BQU1sRCxJQUFJQSxHQUFHLEtBQUswQyxFQUFFTyxNQUFNLENBQUMsQ0FBQ0MsS0FBS2xELElBQU1rRCxNQUFNbEQsSUFBSUEsR0FBRztBQUN6STtBQUNBLE9BQU8sTUFBTXNELFlBQVksT0FBT0MsU0FBcUJDLFdBQW1CdEUsUUFBaUIsQ0FBQyxDQUFDO0lBQ3pGLE1BQU11RSxLQUFLekUsTUFBTXVFLFFBQVFHLFlBQVk7SUFDckMsTUFBTUMsYUFBYUYsR0FBR0UsVUFBVSxDQUFDO0lBQ2pDLElBQUcsQ0FBQyxNQUFNQSxXQUFXQyxNQUFNLElBQUk7UUFBQyxJQUFJO1lBQUMsTUFBTUQsV0FBV0UsTUFBTTtRQUFHLEVBQUUsT0FBTUMsT0FBTztZQUFDLElBQUcsQ0FBQyxNQUFNSCxXQUFXQyxNQUFNLElBQUksTUFBTUU7UUFBTTtJQUFDO0lBQzNILE1BQU1ILFdBQVdJLFdBQVcsQ0FBQztRQUFDQyxRQUFRO1lBQUM7WUFBUztZQUFRO1NBQVU7UUFBRUMsTUFBTTtJQUFZO0lBQ3RGLE1BQU1DLFFBQVFoRjtJQUNkLElBQUdzRSxjQUFjLFVBQVVBLGNBQWMsZ0JBQWdCO1FBQ3ZELE1BQU0xQixTQUFTLE1BQU0yQixHQUFHVSxLQUFLLENBQUNwRixHQUFHLENBQUMsa0pBQWtKLENBQUMsRUFBRXFGLElBQUksQ0FBQyxDQUFDQyxTQUFXQSxPQUFPQyxHQUFHO1FBQ2xOLE9BQU9kLGNBQWMsU0FBUztZQUFDZSxPQUFPMUMsVUFBVUMsT0FBT0UsTUFBTSxDQUFDLENBQUNDLFFBQVUsQUFBQ0EsTUFBNEN1QyxjQUFjLEtBQUtOLE1BQU1NLGNBQWMsR0FBR0MsS0FBSzFDLEdBQUc7UUFBRyxJQUFJO1lBQUN3QyxPQUFPekM7UUFBTTtJQUMvTDtJQUNBLElBQUcwQixjQUFjLFdBQVc7UUFDMUIsSUFBRyxPQUFPVSxNQUFNdkMsT0FBTyxLQUFLLFlBQVksQ0FBQyx1QkFBdUJoQyxJQUFJLENBQUN1RSxNQUFNdkMsT0FBTyxHQUFHLE1BQU0sSUFBSUMsTUFBTTtRQUNyRyxNQUFNOEMsUUFBUW5GLFNBQVMyRSxNQUFNN0IsTUFBTSxFQUFFLFNBQVN4QyxNQUFNQyxPQUFPLENBQUNvRSxNQUFNM0IsT0FBTyxLQUFLMkIsTUFBTTNCLE9BQU8sQ0FBQzdDLE1BQU0sR0FBRyxLQUFLd0UsTUFBTTNCLE9BQU8sQ0FBQzdDLE1BQU0sSUFBSSxLQUFLd0UsTUFBTTNCLE9BQU8sQ0FBQ3hDLEtBQUssQ0FBQ0ssZ0JBQWdCLE9BQU84RCxNQUFNNUIsYUFBYSxLQUFLLFlBQVk0QixNQUFNNUIsYUFBYSxHQUFHbUMsS0FBSzFDLEdBQUcsTUFBTW1DLE1BQU01QixhQUFhLElBQUltQyxLQUFLMUMsR0FBRyxLQUFLLEtBQUs7UUFDblMsTUFBTTBCLEdBQUdVLEtBQUssQ0FBQ3BGLEdBQUcsQ0FBQyxvQ0FBb0MsRUFBRW1GLE1BQU12QyxPQUFPLENBQUMsZ0VBQWdFLEVBQUUrQyxRQUFRO1lBQUNyQyxRQUFRNkIsTUFBTTdCLE1BQU07WUFBRUMsZUFBZTRCLE1BQU01QixhQUFhO1lBQUVxQyxjQUFjRixLQUFLMUMsR0FBRyxLQUFLLEtBQUs7WUFBU3lDLGdCQUFnQk4sTUFBTU0sY0FBYztZQUFFakMsU0FBUzJCLE1BQU0zQixPQUFPO1FBQUEsSUFBSTtZQUFDRixRQUFRO1lBQU1DLGVBQWU7WUFBR3FDLGNBQWNGLEtBQUsxQyxHQUFHLEtBQUssS0FBSztZQUFTeUMsZ0JBQWdCTixNQUFNTSxjQUFjO1lBQUVqQyxTQUFTLEVBQUU7UUFBQSxFQUFFLGFBQWEsQ0FBQztRQUNoYyxPQUFPO1lBQUNxQyxJQUFJO1FBQUk7SUFDbEI7SUFDQSxJQUFHcEIsY0FBYyxZQUFZQSxjQUFjLGNBQWMsTUFBTSxJQUFJNUIsTUFBTTtJQUN6RSxNQUFNaUQsUUFBUTVELGlCQUFpQi9CO0lBQy9CLE1BQU00RixVQUFVLENBQUMsUUFBUSxFQUFFRCxNQUFNeEQsT0FBTyxFQUFFO0lBQzFDLE1BQU0wRCxLQUFLLE1BQU10QixHQUFHdUIsZ0JBQWdCLENBQUM7UUFBQ0MsV0FBVztZQUFDO1NBQVk7SUFBQSxHQUFHO1FBQUNDLGFBQWE7SUFBRTtJQUNqRixNQUFNQyxPQUFPLE9BQU9oQixRQUFrQ1ksR0FBR0ssSUFBSSxDQUFDLElBQU0zQixHQUFHVSxLQUFLLENBQUNBLFFBQVFDLElBQUksQ0FBQyxDQUFDQyxTQUFXQSxPQUFPYyxJQUFJO0lBQ2pILElBQUk7UUFDRixJQUFHM0IsY0FBYyxjQUFjO1lBQzdCLE1BQU02QixPQUFPLE1BQU1GLEtBQUtwRyxHQUFHLENBQUMsNkJBQTZCLEVBQUUrRixRQUFRLENBQUMsQ0FBQztZQUNyRSxNQUFNaEQsU0FBUyxNQUFNaUQsR0FBR0ssSUFBSSxDQUFDLElBQU0zQixHQUFHVSxLQUFLLENBQUNwRixHQUFHLENBQUMsd0ZBQXdGLEVBQUU4RixNQUFNeEQsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHK0MsSUFBSSxDQUFDLENBQUNDLFNBQVdBLE9BQU9DLEdBQUc7WUFDaE0sTUFBTVMsR0FBR08sTUFBTTtZQUNmLE9BQU87Z0JBQUNDLFlBQVl6RCxPQUFPakIsR0FBRyxDQUFDLENBQUNvQixRQUFXLENBQUE7d0JBQUNjLElBQUlkLE1BQU1XLElBQUk7d0JBQUV6QixVQUFVYyxNQUFNZCxRQUFRO3dCQUFFcUUsT0FBT3hDLE9BQU82QixNQUFNckQsU0FBUyxFQUFFUyxNQUFNVCxTQUFTLElBQUksRUFBRTtvQkFBQyxDQUFBLEdBQUlRLE1BQU0sQ0FBQyxDQUFDQyxRQUFVQSxNQUFNdUQsS0FBSyxJQUFJLE1BQU1oRCxJQUFJLENBQUMsQ0FBQ0MsR0FBR0MsSUFBTUEsRUFBRThDLEtBQUssR0FBRy9DLEVBQUUrQyxLQUFLLEVBQUUxQyxLQUFLLENBQUMsR0FBRztnQkFBSXBCLFVBQVUyRCxNQUFNM0QsWUFBWTtZQUFDO1FBQ3BRO1FBQ0EsTUFBTStELE1BQU0sQ0FBQyxTQUFTLEVBQUVaLE1BQU10RCxPQUFPLEVBQUU7UUFDdkMsTUFBTW1FLFdBQVcsTUFBTVAsS0FBS3BHLEdBQUcsQ0FBQyw2QkFBNkIsRUFBRTBHLElBQUksQ0FBQyxDQUFDO1FBQ3JFLElBQUdDLFVBQVU7WUFBQyxNQUFNWCxHQUFHTyxNQUFNO1lBQUksT0FBTztnQkFBQ0ssV0FBVztnQkFBTWhFLFNBQVMrRCxTQUFTL0QsT0FBTztZQUFBO1FBQUU7UUFDckYsTUFBTTBELE9BQU8sTUFBTUYsS0FBS3BHLEdBQUcsQ0FBQyw2QkFBNkIsRUFBRStGLFFBQVEsQ0FBQyxDQUFDO1FBQ3JFLElBQUcsQUFBQ08sQ0FBQUEsTUFBTTNELFlBQVksQ0FBQSxNQUFPbUQsTUFBTW5ELFFBQVEsRUFBRSxNQUFNLElBQUlFLE1BQU07UUFDN0QsTUFBTUQsVUFBVWtELE1BQU1sRCxPQUFPLElBQUksQ0FBQyxNQUFNLEVBQUUxQyxLQUFLLEdBQUc0RixNQUFNeEQsT0FBTyxDQUFDLENBQUMsRUFBRXdELE1BQU0xRCxRQUFRLENBQUN5RSxXQUFXLElBQUksR0FBRztRQUNwRyxNQUFNQyxZQUFZcEIsS0FBSzFDLEdBQUc7UUFDMUIsSUFBRzhDLE1BQU1sRCxPQUFPLEVBQUU7WUFDaEIsTUFBTU0sUUFBUSxNQUFNa0QsS0FBS3BHLEdBQUcsQ0FBQyw2QkFBNkIsRUFBRTRDLFFBQVEsQ0FBQyxDQUFDO1lBQ3RFLElBQUcsQ0FBQ00sU0FBU0EsTUFBTUMsS0FBSyxLQUFLLGVBQWVELE1BQU1aLE9BQU8sS0FBS3dELE1BQU14RCxPQUFPLElBQUlZLE1BQU1FLElBQUksS0FBSyxTQUFTLE1BQU0sSUFBSVAsTUFBTTtRQUN6SDtRQUNBLE1BQU11RCxLQUFLcEcsR0FBRyxDQUFDLGNBQWMsRUFBRTRDLFFBQVEsU0FBUyxFQUFFO1lBQUNpQixNQUFNakI7WUFBU1csZUFBZTtZQUFHSixPQUFPO1lBQWFWLFdBQVdxRCxNQUFNckQsU0FBUztZQUFFc0UsZ0JBQWdCO1lBQW9DQyxZQUFZRjtZQUFXMUQsTUFBTTtZQUFTUSxXQUFXa0Q7WUFBV0csWUFBWW5CLE1BQU12RCxPQUFPLEtBQUssVUFBVSxJQUFJO1lBQUdELFNBQVN3RCxNQUFNeEQsT0FBTztZQUFFRixVQUFVMEQsTUFBTTFELFFBQVE7WUFBRThFLGNBQWNwQixNQUFNdkQsT0FBTyxLQUFLLFlBQVksSUFBSTtZQUFHYyxRQUFRO1FBQUMsRUFBRSxvQkFBb0IsRUFBRXlELFVBQVUsdURBQXVELEVBQUVoQixNQUFNdkQsT0FBTyxLQUFLLFVBQVUsSUFBSSxFQUFFLG1DQUFtQyxFQUFFdUQsTUFBTXZELE9BQU8sS0FBSyxZQUFZLElBQUksRUFBRSxjQUFjLENBQUM7UUFDdG1CLE1BQU02RCxLQUFLcEcsR0FBRyxDQUFDLE9BQU8sRUFBRTtZQUFDNkQsTUFBTTZDO1lBQUt2RCxPQUFPO1lBQWFaLFNBQVN1RCxNQUFNdkQsT0FBTztZQUFFNEUsbUJBQW1CO1lBQUdDLFNBQVNOO1lBQVcxRCxNQUFNO1lBQVlkLFNBQVN3RCxNQUFNeEQsT0FBTztZQUFFRixVQUFVMEQsTUFBTTFELFFBQVE7WUFBRVE7UUFBTyxFQUFFLGFBQWEsQ0FBQztRQUNyTixNQUFNd0QsS0FBS3BHLEdBQUcsQ0FBQyxjQUFjLEVBQUUrRixRQUFRLFNBQVMsRUFBRTtZQUFDbEMsTUFBTWtDO1lBQVM1QyxPQUFPO1lBQWFDLE1BQU07WUFBV1QsVUFBVW1ELE1BQU1uRCxRQUFRLEdBQUc7UUFBQyxFQUFFLG1CQUFtQixFQUFFbUQsTUFBTW5ELFFBQVEsR0FBRyxFQUFFLGNBQWMsQ0FBQztRQUM1TCxNQUFNcUQsR0FBR08sTUFBTTtRQUNmLE9BQU87WUFBQ0ssV0FBVztZQUFPaEU7UUFBTztJQUNuQyxFQUFFLE9BQU1tQyxPQUFPO1FBQUMsTUFBTWlCLEdBQUdxQixLQUFLO1FBQUksTUFBTXRDO0lBQU07QUFDaEQsRUFBRSJ9
|
|
@@ -5,6 +5,8 @@ export interface ContentGenerationConfig {
|
|
|
5
5
|
geminiImageModel?: string;
|
|
6
6
|
geminiKey?: string;
|
|
7
7
|
geminiModel?: string;
|
|
8
|
+
grokKey?: string;
|
|
9
|
+
grokModel?: string;
|
|
8
10
|
ollama?: {
|
|
9
11
|
endpoint: string;
|
|
10
12
|
protocol: 'generate' | 'chat' | 'openai-chat';
|
|
@@ -44,8 +46,9 @@ export interface ContentGenerationInput {
|
|
|
44
46
|
messages?: ContentGenerationMessage[];
|
|
45
47
|
modality?: 'image' | 'text';
|
|
46
48
|
model?: string;
|
|
49
|
+
outputTextMode?: 'preserve' | 'trim';
|
|
47
50
|
prompt?: string;
|
|
48
|
-
provider: 'claude' | 'gemini' | 'ollama' | 'openai';
|
|
51
|
+
provider: 'claude' | 'gemini' | 'grok' | 'ollama' | 'openai';
|
|
49
52
|
reasoningEffort?: ContentGenerationReasoningEffort;
|
|
50
53
|
responseFormat?: ContentGenerationResponseFormat;
|
|
51
54
|
search?: boolean;
|