@promptbook/cli 0.112.0-93 → 0.112.0-96
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/apps/agents-server/next.config.ts +8 -1
- package/apps/agents-server/playwright.config.ts +2 -0
- package/apps/agents-server/src/app/admin/_components/AdminConfigurationShell.tsx +13 -7
- package/apps/agents-server/src/app/admin/code-runners/CodeRunnersClient.tsx +225 -0
- package/apps/agents-server/src/app/admin/code-runners/page.tsx +14 -0
- package/apps/agents-server/src/app/admin/database/DatabaseAdminClient.tsx +38 -0
- package/apps/agents-server/src/app/admin/database/DatabaseAdminStudioSurface.tsx +42 -0
- package/apps/agents-server/src/app/admin/database/page.tsx +33 -0
- package/apps/agents-server/src/app/admin/environment/EnvironmentVariablesClient.tsx +259 -0
- package/apps/agents-server/src/app/admin/environment/page.tsx +21 -0
- package/apps/agents-server/src/app/admin/logs/LogsClient.tsx +78 -0
- package/apps/agents-server/src/app/admin/logs/page.tsx +14 -0
- package/apps/agents-server/src/app/admin/servers/ServersClient.tsx +64 -33
- package/apps/agents-server/src/app/admin/servers/ServersRegistryApi.ts +5 -0
- package/apps/agents-server/src/app/admin/servers/ServersRegistryTable.tsx +15 -2
- package/apps/agents-server/src/app/admin/servers/page.tsx +3 -3
- package/apps/agents-server/src/app/admin/servers/useServersRegistryState.ts +12 -2
- package/apps/agents-server/src/app/api/admin/code-runners/route.ts +104 -0
- package/apps/agents-server/src/app/api/admin/database/studio/route.ts +113 -0
- package/apps/agents-server/src/app/api/admin/environment/route.ts +65 -0
- package/apps/agents-server/src/app/api/admin/logs/route.ts +24 -0
- package/apps/agents-server/src/app/api/admin/servers/[serverId]/route.ts +79 -3
- package/apps/agents-server/src/app/api/admin/servers/route.ts +36 -1
- package/apps/agents-server/src/app/layout.tsx +1 -0
- package/apps/agents-server/src/app/page.tsx +101 -1
- package/apps/agents-server/src/components/Header/buildHeaderSystemMenuItems.ts +27 -4
- package/apps/agents-server/src/database/$provideClientSql.ts +2 -6
- package/apps/agents-server/src/database/$provideDatabaseAdminExecutor.ts +273 -0
- package/apps/agents-server/src/database/resolvePostgresConnectionString.ts +26 -0
- package/apps/agents-server/src/database/sqlite/$provideAgentsServerSqliteDatabase.ts +83 -0
- package/apps/agents-server/src/database/sqlite/$provideLocalSqliteSupabase.ts +20 -71
- package/apps/agents-server/src/languages/ServerTranslationKeys.ts +5 -0
- package/apps/agents-server/src/languages/translations/czech.yaml +5 -0
- package/apps/agents-server/src/languages/translations/english.yaml +5 -0
- package/apps/agents-server/src/tools/$provideServer.ts +27 -0
- package/apps/agents-server/src/utils/serverRegistry.ts +20 -1
- package/apps/agents-server/src/utils/session.ts +123 -2
- package/apps/agents-server/src/utils/vpsConfiguration.ts +550 -0
- package/esm/index.es.js +1 -1
- package/esm/index.es.js.map +1 -1
- package/esm/src/book-components/Chat/utils/renderMarkdown.test.d.ts +1 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +3 -1
- package/src/book-components/Chat/MarkdownContent/MarkdownContent.tsx +9 -398
- package/src/book-components/Chat/utils/renderMarkdown.ts +323 -8
- package/src/other/templates/getTemplatesPipelineCollection.ts +712 -829
- package/src/version.ts +2 -2
- package/src/versions.txt +2 -0
- package/umd/index.umd.js +1 -1
- package/umd/index.umd.js.map +1 -1
- package/umd/src/book-components/Chat/utils/renderMarkdown.test.d.ts +1 -0
- package/umd/src/version.d.ts +1 -1
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import createDOMPurify, {
|
|
2
|
+
type Config as DomPurifyConfig,
|
|
3
|
+
type DOMPurify as DomPurifyInstance,
|
|
4
|
+
type UponSanitizeAttributeHookEvent as DomPurifyUponSanitizeAttributeHookEvent,
|
|
5
|
+
type WindowLike as DomPurifyWindowLike,
|
|
6
|
+
} from 'dompurify';
|
|
1
7
|
import katex from 'katex';
|
|
2
8
|
import { Converter as ShowdownConverter } from 'showdown';
|
|
3
9
|
import type { string_html, string_markdown } from '../../../types/string_markdown';
|
|
@@ -19,6 +25,182 @@ const KATEX_STYLESHEET_ID = 'katex-css';
|
|
|
19
25
|
*/
|
|
20
26
|
const KATEX_STYLESHEET_URL = 'https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css';
|
|
21
27
|
|
|
28
|
+
/**
|
|
29
|
+
* Explicit allowlist of HTML tags that may survive markdown rendering.
|
|
30
|
+
*
|
|
31
|
+
* @private utility of `renderMarkdown`
|
|
32
|
+
*/
|
|
33
|
+
const MARKDOWN_SANITIZER_ALLOWED_TAGS = [
|
|
34
|
+
'a',
|
|
35
|
+
'annotation',
|
|
36
|
+
'b',
|
|
37
|
+
'blockquote',
|
|
38
|
+
'br',
|
|
39
|
+
'code',
|
|
40
|
+
'del',
|
|
41
|
+
'details',
|
|
42
|
+
'div',
|
|
43
|
+
'em',
|
|
44
|
+
'h1',
|
|
45
|
+
'h2',
|
|
46
|
+
'h3',
|
|
47
|
+
'h4',
|
|
48
|
+
'h5',
|
|
49
|
+
'h6',
|
|
50
|
+
'hr',
|
|
51
|
+
'i',
|
|
52
|
+
'img',
|
|
53
|
+
'input',
|
|
54
|
+
'li',
|
|
55
|
+
'math',
|
|
56
|
+
'menclose',
|
|
57
|
+
'mfrac',
|
|
58
|
+
'mi',
|
|
59
|
+
'mn',
|
|
60
|
+
'mo',
|
|
61
|
+
'mover',
|
|
62
|
+
'mpadded',
|
|
63
|
+
'mphantom',
|
|
64
|
+
'mroot',
|
|
65
|
+
'mrow',
|
|
66
|
+
'msqrt',
|
|
67
|
+
'mspace',
|
|
68
|
+
'msub',
|
|
69
|
+
'msubsup',
|
|
70
|
+
'msup',
|
|
71
|
+
'mstyle',
|
|
72
|
+
'mtable',
|
|
73
|
+
'mtd',
|
|
74
|
+
'mtext',
|
|
75
|
+
'mtr',
|
|
76
|
+
'munder',
|
|
77
|
+
'munderover',
|
|
78
|
+
'ol',
|
|
79
|
+
'p',
|
|
80
|
+
'pre',
|
|
81
|
+
's',
|
|
82
|
+
'semantics',
|
|
83
|
+
'span',
|
|
84
|
+
'strong',
|
|
85
|
+
'sub',
|
|
86
|
+
'summary',
|
|
87
|
+
'sup',
|
|
88
|
+
'table',
|
|
89
|
+
'tbody',
|
|
90
|
+
'td',
|
|
91
|
+
'tfoot',
|
|
92
|
+
'th',
|
|
93
|
+
'thead',
|
|
94
|
+
'tr',
|
|
95
|
+
'u',
|
|
96
|
+
'ul',
|
|
97
|
+
] as const;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Explicit allowlist of HTML attributes that may survive markdown rendering.
|
|
101
|
+
*
|
|
102
|
+
* @private utility of `renderMarkdown`
|
|
103
|
+
*/
|
|
104
|
+
const MARKDOWN_SANITIZER_ALLOWED_ATTRIBUTES = [
|
|
105
|
+
'alt',
|
|
106
|
+
'aria-hidden',
|
|
107
|
+
'checked',
|
|
108
|
+
'class',
|
|
109
|
+
'colspan',
|
|
110
|
+
'data-citation-footnote',
|
|
111
|
+
'data-chat-progress-marker',
|
|
112
|
+
'disabled',
|
|
113
|
+
'encoding',
|
|
114
|
+
'height',
|
|
115
|
+
'href',
|
|
116
|
+
'id',
|
|
117
|
+
'open',
|
|
118
|
+
'rel',
|
|
119
|
+
'rowspan',
|
|
120
|
+
'src',
|
|
121
|
+
'start',
|
|
122
|
+
'stretchy',
|
|
123
|
+
'style',
|
|
124
|
+
'target',
|
|
125
|
+
'title',
|
|
126
|
+
'type',
|
|
127
|
+
'width',
|
|
128
|
+
'xmlns',
|
|
129
|
+
] as const;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Attributes that may contain external URLs and therefore need protocol validation.
|
|
133
|
+
*
|
|
134
|
+
* @private utility of `renderMarkdown`
|
|
135
|
+
*/
|
|
136
|
+
const MARKDOWN_SANITIZER_URL_ATTRIBUTES = ['href', 'src'] as const;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* URL protocols that remain allowed after markdown sanitization.
|
|
140
|
+
*
|
|
141
|
+
* @private utility of `renderMarkdown`
|
|
142
|
+
*/
|
|
143
|
+
const MARKDOWN_SANITIZER_ALLOWED_PROTOCOLS = new Set(['http', 'https', 'mailto', 'tel']);
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Internal `data-*` attributes that Promptbook injects into rendered markdown and must survive sanitization.
|
|
147
|
+
*
|
|
148
|
+
* @private utility of `renderMarkdown`
|
|
149
|
+
*/
|
|
150
|
+
const MARKDOWN_SANITIZER_ALLOWED_DATA_ATTRIBUTES = new Set(['data-citation-footnote', 'data-chat-progress-marker']);
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Highest ASCII control character code that should be stripped from sanitized URLs.
|
|
154
|
+
*
|
|
155
|
+
* @private utility of `renderMarkdown`
|
|
156
|
+
*/
|
|
157
|
+
const MAX_ASCII_CONTROL_CHARACTER_CODE = 32;
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* ASCII delete character code that should be stripped from sanitized URLs.
|
|
161
|
+
*
|
|
162
|
+
* @private utility of `renderMarkdown`
|
|
163
|
+
*/
|
|
164
|
+
const ASCII_DELETE_CHARACTER_CODE = 127;
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* DOMPurify configuration used for markdown rendering and export sanitization.
|
|
168
|
+
*
|
|
169
|
+
* @private utility of `renderMarkdown`
|
|
170
|
+
*/
|
|
171
|
+
const MARKDOWN_SANITIZER_CONFIG: DomPurifyConfig = {
|
|
172
|
+
ALLOWED_TAGS: [...MARKDOWN_SANITIZER_ALLOWED_TAGS],
|
|
173
|
+
ALLOWED_ATTR: [...MARKDOWN_SANITIZER_ALLOWED_ATTRIBUTES],
|
|
174
|
+
ALLOW_ARIA_ATTR: true,
|
|
175
|
+
ALLOW_DATA_ATTR: false,
|
|
176
|
+
USE_PROFILES: {
|
|
177
|
+
html: true,
|
|
178
|
+
mathMl: true,
|
|
179
|
+
svg: false,
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Shared browser-side DOMPurify instance.
|
|
185
|
+
*
|
|
186
|
+
* @private utility of `renderMarkdown`
|
|
187
|
+
*/
|
|
188
|
+
let browserMarkdownSanitizer: DomPurifyInstance | null = null;
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Shared server-side DOMPurify instance.
|
|
192
|
+
*
|
|
193
|
+
* @private utility of `renderMarkdown`
|
|
194
|
+
*/
|
|
195
|
+
let serverMarkdownSanitizer: DomPurifyInstance | null = null;
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Shared JSDOM window backing the server-side DOMPurify instance.
|
|
199
|
+
*
|
|
200
|
+
* @private utility of `renderMarkdown`
|
|
201
|
+
*/
|
|
202
|
+
let serverMarkdownSanitizerWindow: DomPurifyWindowLike | null = null;
|
|
203
|
+
|
|
22
204
|
/**
|
|
23
205
|
* Pattern matching CODE FENCE.
|
|
24
206
|
*/
|
|
@@ -119,6 +301,144 @@ type MaskedDetailsBlocksResult = {
|
|
|
119
301
|
restore: (value: string_html) => string_html;
|
|
120
302
|
};
|
|
121
303
|
|
|
304
|
+
/**
|
|
305
|
+
* Removes whitespace and control characters that can obscure a URL protocol.
|
|
306
|
+
*
|
|
307
|
+
* @private utility of `renderMarkdown`
|
|
308
|
+
*/
|
|
309
|
+
function normalizeSanitizedUrlValue(value: string): string {
|
|
310
|
+
return Array.from(value.trim())
|
|
311
|
+
.filter((character) => {
|
|
312
|
+
const characterCode = character.charCodeAt(0);
|
|
313
|
+
|
|
314
|
+
return (
|
|
315
|
+
characterCode > MAX_ASCII_CONTROL_CHARACTER_CODE && characterCode !== ASCII_DELETE_CHARACTER_CODE
|
|
316
|
+
);
|
|
317
|
+
})
|
|
318
|
+
.join('');
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Returns whether a sanitized URL attribute still uses an allowed protocol.
|
|
323
|
+
*
|
|
324
|
+
* @private utility of `renderMarkdown`
|
|
325
|
+
*/
|
|
326
|
+
function isAllowedSanitizedUrl(value: string): boolean {
|
|
327
|
+
const normalizedValue = normalizeSanitizedUrlValue(value);
|
|
328
|
+
|
|
329
|
+
if (normalizedValue === '') {
|
|
330
|
+
return true;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if (
|
|
334
|
+
normalizedValue.startsWith('#') ||
|
|
335
|
+
normalizedValue.startsWith('/') ||
|
|
336
|
+
normalizedValue.startsWith('./') ||
|
|
337
|
+
normalizedValue.startsWith('../') ||
|
|
338
|
+
normalizedValue.startsWith('?') ||
|
|
339
|
+
normalizedValue.startsWith('//')
|
|
340
|
+
) {
|
|
341
|
+
return true;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const schemeMatch = normalizedValue.match(/^([a-z][a-z0-9+.-]*):/i);
|
|
345
|
+
if (!schemeMatch) {
|
|
346
|
+
return true;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return MARKDOWN_SANITIZER_ALLOWED_PROTOCOLS.has(schemeMatch[1]!.toLowerCase());
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Applies the shared post-attribute sanitization rules to a DOMPurify instance.
|
|
354
|
+
*
|
|
355
|
+
* @private utility of `renderMarkdown`
|
|
356
|
+
*/
|
|
357
|
+
function registerMarkdownSanitizerHooks(markdownSanitizer: DomPurifyInstance): void {
|
|
358
|
+
markdownSanitizer.addHook(
|
|
359
|
+
'uponSanitizeAttribute',
|
|
360
|
+
(_currentNode: Element, hookEvent: DomPurifyUponSanitizeAttributeHookEvent) => {
|
|
361
|
+
if (MARKDOWN_SANITIZER_ALLOWED_DATA_ATTRIBUTES.has(hookEvent.attrName)) {
|
|
362
|
+
hookEvent.forceKeepAttr = true;
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
);
|
|
366
|
+
|
|
367
|
+
markdownSanitizer.addHook('afterSanitizeAttributes', (currentNode: Node) => {
|
|
368
|
+
if (!currentNode || currentNode.nodeType !== 1) {
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
const currentElement = currentNode as Element;
|
|
373
|
+
|
|
374
|
+
for (const attributeName of MARKDOWN_SANITIZER_URL_ATTRIBUTES) {
|
|
375
|
+
const attributeValue = currentElement.getAttribute(attributeName);
|
|
376
|
+
|
|
377
|
+
if (attributeValue && !isAllowedSanitizedUrl(attributeValue)) {
|
|
378
|
+
currentElement.removeAttribute(attributeName);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
if (currentElement.tagName === 'A' && currentElement.getAttribute('target') === '_blank') {
|
|
383
|
+
currentElement.setAttribute('rel', 'noopener noreferrer');
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Creates a DOMPurify instance configured for Promptbook markdown output.
|
|
390
|
+
*
|
|
391
|
+
* @private utility of `renderMarkdown`
|
|
392
|
+
*/
|
|
393
|
+
function createMarkdownSanitizer(sanitizerWindow: DomPurifyWindowLike): DomPurifyInstance {
|
|
394
|
+
const markdownSanitizer = createDOMPurify(sanitizerWindow);
|
|
395
|
+
|
|
396
|
+
registerMarkdownSanitizerHooks(markdownSanitizer);
|
|
397
|
+
|
|
398
|
+
return markdownSanitizer;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Lazily creates the JSDOM window used by server-side markdown sanitization.
|
|
403
|
+
*
|
|
404
|
+
* @private utility of `renderMarkdown`
|
|
405
|
+
*/
|
|
406
|
+
function getServerMarkdownSanitizerWindow(): DomPurifyWindowLike {
|
|
407
|
+
if (!serverMarkdownSanitizerWindow) {
|
|
408
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
409
|
+
const { JSDOM } = require('jsdom') as typeof import('jsdom');
|
|
410
|
+
serverMarkdownSanitizerWindow = new JSDOM('').window as unknown as DomPurifyWindowLike;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
return serverMarkdownSanitizerWindow;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Returns the shared DOMPurify instance appropriate for the current runtime.
|
|
418
|
+
*
|
|
419
|
+
* @private utility of `renderMarkdown`
|
|
420
|
+
*/
|
|
421
|
+
function getMarkdownSanitizer(): DomPurifyInstance {
|
|
422
|
+
if (typeof window !== 'undefined') {
|
|
423
|
+
browserMarkdownSanitizer ??= createMarkdownSanitizer(window as unknown as DomPurifyWindowLike);
|
|
424
|
+
|
|
425
|
+
return browserMarkdownSanitizer;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
serverMarkdownSanitizer ??= createMarkdownSanitizer(getServerMarkdownSanitizerWindow());
|
|
429
|
+
|
|
430
|
+
return serverMarkdownSanitizer;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* Sanitizes rendered markdown HTML with the shared Promptbook allowlist.
|
|
435
|
+
*
|
|
436
|
+
* @private utility of `renderMarkdown`
|
|
437
|
+
*/
|
|
438
|
+
function sanitizeRenderedMarkdownHtml(html: string_html): string_html {
|
|
439
|
+
return getMarkdownSanitizer().sanitize(html, MARKDOWN_SANITIZER_CONFIG) as string_html;
|
|
440
|
+
}
|
|
441
|
+
|
|
122
442
|
/**
|
|
123
443
|
* Normalizes markdown sublists so they render correctly under ordered list items.
|
|
124
444
|
*
|
|
@@ -447,14 +767,9 @@ export function renderMarkdown(markdown: string_markdown, options?: RenderMarkdo
|
|
|
447
767
|
registerKatexStylesheet(html);
|
|
448
768
|
|
|
449
769
|
const restoredHtml = restoreDetails(html);
|
|
450
|
-
const sanitizedHtml = restoredHtml
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
.replace(/\s+javascript:/gi, '')
|
|
454
|
-
.replace(/\s+data:/gi, '')
|
|
455
|
-
.replace(/\s+vbscript:/gi, '');
|
|
456
|
-
|
|
457
|
-
return sanitizedHtml as string_html;
|
|
770
|
+
const sanitizedHtml = sanitizeRenderedMarkdownHtml(restoredHtml);
|
|
771
|
+
|
|
772
|
+
return sanitizedHtml;
|
|
458
773
|
} catch (error) {
|
|
459
774
|
console.error('Error rendering markdown:', error);
|
|
460
775
|
return escapeHtml(markdown);
|