@promptbook/cli 0.113.0-0 → 0.113.0-2
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 -17
- package/agents/default/developer.book +3 -0
- package/apps/agents-server/src/app/admin/task-manager/TaskManagerClient.tsx +3 -3
- package/apps/agents-server/src/app/admin/task-manager/TaskManagerTaskRow.tsx +11 -2
- package/apps/agents-server/src/app/admin/task-manager/TaskManagerTasksCard.tsx +5 -5
- package/apps/agents-server/src/app/api/page-preview/input/route.ts +161 -0
- package/apps/agents-server/src/app/api/page-preview/stream/route.ts +81 -0
- package/apps/agents-server/src/components/Header/HeaderHomepageLink.tsx +1 -1
- package/apps/agents-server/src/constants/chatVisualMode.ts +1 -1
- package/apps/agents-server/src/constants/themeMode.ts +1 -1
- package/apps/agents-server/src/database/migrations/2026-05-2600-default-theme.sql +2 -2
- package/apps/agents-server/src/utils/chatTasksAdmin.ts +4 -1
- package/apps/agents-server/src/utils/createPagePreviewBrowserStream.ts +179 -0
- package/apps/agents-server/src/utils/getAdminChatTasksResponse/mapVpsSelfUpdateJobToAdminChatTask.ts +84 -0
- package/apps/agents-server/src/utils/getAdminChatTasksResponse.ts +221 -5
- package/apps/agents-server/src/utils/pagePreviewBrowserSessions.ts +234 -0
- package/apps/agents-server/src/utils/vpsSelfUpdate.ts +12 -0
- package/esm/index.es.js +26 -5
- package/esm/index.es.js.map +1 -1
- package/esm/src/book-components/Chat/Chat/CitationIframePreview.d.ts +2 -2
- package/esm/src/book-components/Chat/Chat/CitationIframePreview.test.d.ts +2 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/book-components/Chat/Chat/Chat.module.css +37 -0
- package/src/book-components/Chat/Chat/CitationIframePreview.tsx +138 -11
- package/src/book-components/Chat/Chat/createProgressCardChecklistMarkdown.ts +1 -8
- package/src/cli/promptbookCli.ts +28 -3
- package/src/other/templates/getTemplatesPipelineCollection.ts +750 -812
- package/src/version.ts +2 -2
- package/src/versions.txt +2 -0
- package/umd/index.umd.js +26 -5
- package/umd/index.umd.js.map +1 -1
- package/umd/src/book-components/Chat/Chat/CitationIframePreview.d.ts +2 -2
- package/umd/src/book-components/Chat/Chat/CitationIframePreview.test.d.ts +2 -0
- package/umd/src/version.d.ts +1 -1
|
@@ -9,8 +9,8 @@ export type CitationIframePreviewProps = {
|
|
|
9
9
|
};
|
|
10
10
|
/**
|
|
11
11
|
* Renders a citation URL preview as an iframe when the target page allows embedding,
|
|
12
|
-
* or falls back to a server-side
|
|
13
|
-
* does not (e.g. X-Frame-Options: DENY / SAMEORIGIN).
|
|
12
|
+
* or falls back to a live server-side browser stream with an "Open in new tab" link
|
|
13
|
+
* when it does not (e.g. X-Frame-Options: DENY / SAMEORIGIN).
|
|
14
14
|
*
|
|
15
15
|
* Embedding capability is determined by `GET /api/page-preview/check?url=<url>`.
|
|
16
16
|
* If that endpoint is unavailable the component falls back to the iframe directly.
|
package/esm/src/version.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export declare const BOOK_LANGUAGE_VERSION: string_semantic_version;
|
|
|
15
15
|
export declare const PROMPTBOOK_ENGINE_VERSION: string_promptbook_version;
|
|
16
16
|
/**
|
|
17
17
|
* Represents the version string of the Promptbook engine.
|
|
18
|
-
* It follows semantic versioning (e.g., `0.
|
|
18
|
+
* It follows semantic versioning (e.g., `0.113.0-1`).
|
|
19
19
|
*
|
|
20
20
|
* @generated
|
|
21
21
|
*/
|
package/package.json
CHANGED
|
@@ -3356,6 +3356,43 @@
|
|
|
3356
3356
|
text-decoration: underline;
|
|
3357
3357
|
}
|
|
3358
3358
|
|
|
3359
|
+
.citationBrowserStreamFallback {
|
|
3360
|
+
width: 100%;
|
|
3361
|
+
position: relative;
|
|
3362
|
+
display: flex;
|
|
3363
|
+
flex-direction: column;
|
|
3364
|
+
}
|
|
3365
|
+
|
|
3366
|
+
.citationBrowserStreamImage {
|
|
3367
|
+
width: 100%;
|
|
3368
|
+
max-height: 60vh;
|
|
3369
|
+
min-height: 400px;
|
|
3370
|
+
object-fit: cover;
|
|
3371
|
+
object-position: top;
|
|
3372
|
+
display: block;
|
|
3373
|
+
cursor: crosshair;
|
|
3374
|
+
user-select: none;
|
|
3375
|
+
touch-action: none;
|
|
3376
|
+
}
|
|
3377
|
+
|
|
3378
|
+
.citationBrowserStreamLink {
|
|
3379
|
+
display: block;
|
|
3380
|
+
text-align: center;
|
|
3381
|
+
padding: 10px 16px;
|
|
3382
|
+
background: #f0f0f0;
|
|
3383
|
+
color: #333;
|
|
3384
|
+
font-size: 0.9em;
|
|
3385
|
+
font-weight: 500;
|
|
3386
|
+
text-decoration: none;
|
|
3387
|
+
border-top: 1px solid #ddd;
|
|
3388
|
+
transition: background 0.15s;
|
|
3389
|
+
}
|
|
3390
|
+
|
|
3391
|
+
.citationBrowserStreamLink:hover {
|
|
3392
|
+
background: #e0e0e0;
|
|
3393
|
+
text-decoration: underline;
|
|
3394
|
+
}
|
|
3395
|
+
|
|
3359
3396
|
.citationMetadata {
|
|
3360
3397
|
background: #f8f8f8;
|
|
3361
3398
|
padding: 16px;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { useEffect, useState } from 'react';
|
|
3
|
+
import { useEffect, useMemo, useState, type MouseEvent, type WheelEvent } from 'react';
|
|
4
4
|
import styles from './Chat.module.css';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -18,12 +18,36 @@ export type CitationIframePreviewProps = {
|
|
|
18
18
|
*
|
|
19
19
|
* @private type of `<CitationIframePreview/>`
|
|
20
20
|
*/
|
|
21
|
-
type EmbedStatus = 'loading' | 'embed' | '
|
|
21
|
+
type EmbedStatus = 'loading' | 'embed' | 'browser-stream';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Prefix shared with the Agents Server page-preview stream route.
|
|
25
|
+
*
|
|
26
|
+
* @private component constant of `<CitationIframePreview/>`
|
|
27
|
+
*/
|
|
28
|
+
const BROWSER_PREVIEW_SESSION_ID_PREFIX = 'page-preview-';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Fallback suffix length used when `crypto.randomUUID` is unavailable.
|
|
32
|
+
*
|
|
33
|
+
* @private component constant of `<CitationIframePreview/>`
|
|
34
|
+
*/
|
|
35
|
+
const BROWSER_PREVIEW_RANDOM_SUFFIX_LENGTH = 24;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Pointer ratio resolved from one browser preview interaction.
|
|
39
|
+
*
|
|
40
|
+
* @private type of `<CitationIframePreview/>`
|
|
41
|
+
*/
|
|
42
|
+
type BrowserPreviewPointerRatio = {
|
|
43
|
+
readonly xRatio: number;
|
|
44
|
+
readonly yRatio: number;
|
|
45
|
+
};
|
|
22
46
|
|
|
23
47
|
/**
|
|
24
48
|
* Renders a citation URL preview as an iframe when the target page allows embedding,
|
|
25
|
-
* or falls back to a server-side
|
|
26
|
-
* does not (e.g. X-Frame-Options: DENY / SAMEORIGIN).
|
|
49
|
+
* or falls back to a live server-side browser stream with an "Open in new tab" link
|
|
50
|
+
* when it does not (e.g. X-Frame-Options: DENY / SAMEORIGIN).
|
|
27
51
|
*
|
|
28
52
|
* Embedding capability is determined by `GET /api/page-preview/check?url=<url>`.
|
|
29
53
|
* If that endpoint is unavailable the component falls back to the iframe directly.
|
|
@@ -32,6 +56,7 @@ type EmbedStatus = 'loading' | 'embed' | 'screenshot';
|
|
|
32
56
|
*/
|
|
33
57
|
export function CitationIframePreview({ src, title }: CitationIframePreviewProps) {
|
|
34
58
|
const [status, setStatus] = useState<EmbedStatus>('loading');
|
|
59
|
+
const browserPreviewSessionId = useMemo(() => createBrowserPreviewSessionId(), [src]);
|
|
35
60
|
|
|
36
61
|
useEffect(() => {
|
|
37
62
|
let cancelled = false;
|
|
@@ -40,7 +65,7 @@ export function CitationIframePreview({ src, title }: CitationIframePreviewProps
|
|
|
40
65
|
.then((response) => response.json())
|
|
41
66
|
.then((data: { canEmbed: boolean }) => {
|
|
42
67
|
if (!cancelled) {
|
|
43
|
-
setStatus(data.canEmbed ? 'embed' : '
|
|
68
|
+
setStatus(data.canEmbed ? 'embed' : 'browser-stream');
|
|
44
69
|
}
|
|
45
70
|
})
|
|
46
71
|
.catch(() => {
|
|
@@ -59,15 +84,45 @@ export function CitationIframePreview({ src, title }: CitationIframePreviewProps
|
|
|
59
84
|
return <div className={styles.citationIframeLoading}>Loading preview…</div>;
|
|
60
85
|
}
|
|
61
86
|
|
|
62
|
-
if (status === '
|
|
87
|
+
if (status === 'browser-stream') {
|
|
63
88
|
return (
|
|
64
|
-
<div className={styles.
|
|
89
|
+
<div className={styles.citationBrowserStreamFallback}>
|
|
65
90
|
<img
|
|
66
|
-
src={`/api/page-preview/
|
|
67
|
-
|
|
68
|
-
|
|
91
|
+
src={`/api/page-preview/stream?url=${encodeURIComponent(src)}&sessionId=${encodeURIComponent(
|
|
92
|
+
browserPreviewSessionId,
|
|
93
|
+
)}`}
|
|
94
|
+
alt={`Live browser preview of ${title}`}
|
|
95
|
+
className={styles.citationBrowserStreamImage}
|
|
96
|
+
draggable={false}
|
|
97
|
+
onClick={(event) => {
|
|
98
|
+
const pointerRatio = resolveBrowserPreviewPointerRatio(event);
|
|
99
|
+
if (!pointerRatio) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
sendBrowserPreviewInput({
|
|
104
|
+
sessionId: browserPreviewSessionId,
|
|
105
|
+
type: 'click',
|
|
106
|
+
...pointerRatio,
|
|
107
|
+
});
|
|
108
|
+
}}
|
|
109
|
+
onWheel={(event) => {
|
|
110
|
+
event.preventDefault();
|
|
111
|
+
const pointerRatio = resolveBrowserPreviewPointerRatio(event);
|
|
112
|
+
if (!pointerRatio) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
sendBrowserPreviewInput({
|
|
117
|
+
sessionId: browserPreviewSessionId,
|
|
118
|
+
type: 'wheel',
|
|
119
|
+
deltaX: event.deltaX,
|
|
120
|
+
deltaY: event.deltaY,
|
|
121
|
+
...pointerRatio,
|
|
122
|
+
});
|
|
123
|
+
}}
|
|
69
124
|
/>
|
|
70
|
-
<a href={src} target="_blank" rel="noopener noreferrer" className={styles.
|
|
125
|
+
<a href={src} target="_blank" rel="noopener noreferrer" className={styles.citationBrowserStreamLink}>
|
|
71
126
|
Open in new tab ↗
|
|
72
127
|
</a>
|
|
73
128
|
</div>
|
|
@@ -76,3 +131,75 @@ export function CitationIframePreview({ src, title }: CitationIframePreviewProps
|
|
|
76
131
|
|
|
77
132
|
return <iframe src={src} className={styles.citationIframe} title={title} />;
|
|
78
133
|
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Creates one client-side browser preview session id.
|
|
137
|
+
*
|
|
138
|
+
* @returns Session id accepted by Agents Server page-preview stream routes.
|
|
139
|
+
*/
|
|
140
|
+
function createBrowserPreviewSessionId(): string {
|
|
141
|
+
const randomId =
|
|
142
|
+
globalThis.crypto && 'randomUUID' in globalThis.crypto
|
|
143
|
+
? globalThis.crypto.randomUUID()
|
|
144
|
+
: createFallbackBrowserPreviewSessionSuffix();
|
|
145
|
+
|
|
146
|
+
return `${BROWSER_PREVIEW_SESSION_ID_PREFIX}${randomId}`.toLowerCase();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Creates a sufficiently long fallback session suffix when Web Crypto UUIDs are unavailable.
|
|
151
|
+
*
|
|
152
|
+
* @returns Lowercase random suffix.
|
|
153
|
+
*/
|
|
154
|
+
function createFallbackBrowserPreviewSessionSuffix(): string {
|
|
155
|
+
let suffix = '';
|
|
156
|
+
|
|
157
|
+
while (suffix.length < BROWSER_PREVIEW_RANDOM_SUFFIX_LENGTH) {
|
|
158
|
+
suffix += Math.random().toString(36).slice(2);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return suffix.slice(0, BROWSER_PREVIEW_RANDOM_SUFFIX_LENGTH);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Resolves pointer coordinates as ratios inside the streamed preview image.
|
|
166
|
+
*
|
|
167
|
+
* @param event - Mouse or wheel event fired inside the live preview image.
|
|
168
|
+
* @returns Pointer ratio or `null` when the image has no measurable size.
|
|
169
|
+
*/
|
|
170
|
+
function resolveBrowserPreviewPointerRatio(
|
|
171
|
+
event: MouseEvent<HTMLImageElement> | WheelEvent<HTMLImageElement>,
|
|
172
|
+
): BrowserPreviewPointerRatio | null {
|
|
173
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
174
|
+
if (rect.width <= 0 || rect.height <= 0) {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
xRatio: (event.clientX - rect.left) / rect.width,
|
|
180
|
+
yRatio: (event.clientY - rect.top) / rect.height,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Sends one browser-preview interaction to the Agents Server stream session.
|
|
186
|
+
*
|
|
187
|
+
* @param payload - Browser-preview input payload.
|
|
188
|
+
*/
|
|
189
|
+
function sendBrowserPreviewInput(payload: {
|
|
190
|
+
readonly sessionId: string;
|
|
191
|
+
readonly type: 'click' | 'wheel';
|
|
192
|
+
readonly xRatio: number;
|
|
193
|
+
readonly yRatio: number;
|
|
194
|
+
readonly deltaX?: number;
|
|
195
|
+
readonly deltaY?: number;
|
|
196
|
+
}): void {
|
|
197
|
+
void fetch('/api/page-preview/input', {
|
|
198
|
+
method: 'POST',
|
|
199
|
+
headers: {
|
|
200
|
+
'Content-Type': 'application/json',
|
|
201
|
+
},
|
|
202
|
+
body: JSON.stringify(payload),
|
|
203
|
+
keepalive: true,
|
|
204
|
+
}).catch(() => undefined);
|
|
205
|
+
}
|
|
@@ -14,13 +14,6 @@ const PENDING_PROGRESS_MARKER_HTML = '<span data-chat-progress-marker="pending"
|
|
|
14
14
|
*/
|
|
15
15
|
const COMPLETED_PROGRESS_MARKER_HTML = '<span data-chat-progress-marker="completed" aria-hidden="true"></span>';
|
|
16
16
|
|
|
17
|
-
/**
|
|
18
|
-
* Human-facing label shown for "now" progress updates.
|
|
19
|
-
*
|
|
20
|
-
* @private internal helper of `<ChatMessageItem/>`
|
|
21
|
-
*/
|
|
22
|
-
const PROGRESS_NOW_LABEL = "What I'm Doing Now";
|
|
23
|
-
|
|
24
17
|
/**
|
|
25
18
|
* Human-facing label shown for "next" progress updates.
|
|
26
19
|
*
|
|
@@ -85,7 +78,7 @@ function createProgressCardMarkdownSections(progressCard: NonNullable<ChatMessag
|
|
|
85
78
|
}
|
|
86
79
|
|
|
87
80
|
if (normalizedNow) {
|
|
88
|
-
markdownSections.push(
|
|
81
|
+
markdownSections.push(normalizedNow);
|
|
89
82
|
}
|
|
90
83
|
|
|
91
84
|
const itemLines: Array<string> = [];
|
package/src/cli/promptbookCli.ts
CHANGED
|
@@ -48,6 +48,13 @@ const DEPRECATED_TOP_LEVEL_COMMAND_MESSAGES: Readonly<Record<string, string>> =
|
|
|
48
48
|
'start-pipelines-server': OLD_PIPELINE_SYSTEM_DEPRECATION_MESSAGE,
|
|
49
49
|
};
|
|
50
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Raw top-level CLI arguments that print the Promptbook version.
|
|
53
|
+
*
|
|
54
|
+
* @private internal constant of `promptbookCli`
|
|
55
|
+
*/
|
|
56
|
+
const VERSION_OPTION_ARGUMENTS: ReadonlySet<string> = new Set(['-v', '--version']);
|
|
57
|
+
|
|
51
58
|
/**
|
|
52
59
|
* Runs CLI utilities of Promptbook package
|
|
53
60
|
*
|
|
@@ -65,8 +72,15 @@ export async function promptbookCli(): Promise<void> {
|
|
|
65
72
|
);
|
|
66
73
|
}
|
|
67
74
|
|
|
68
|
-
const
|
|
69
|
-
const
|
|
75
|
+
const commandLineArguments = process.argv.slice(2);
|
|
76
|
+
const isVersionRequested = isTopLevelVersionRequested(commandLineArguments);
|
|
77
|
+
|
|
78
|
+
if (isVersionRequested) {
|
|
79
|
+
console.info(PROMPTBOOK_ENGINE_VERSION);
|
|
80
|
+
return process.exit(0);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const isVerbose = commandLineArguments.some((argument) => argument === '--verbose' || argument === '-v');
|
|
70
84
|
// <- TODO: Can be this be done with commander before the commander commands are initialized?
|
|
71
85
|
if (isVerbose) {
|
|
72
86
|
console.info(
|
|
@@ -104,7 +118,7 @@ export async function promptbookCli(): Promise<void> {
|
|
|
104
118
|
// TODO: [🧠] Should it be here or not> $addGlobalOptionsToCommand(program);
|
|
105
119
|
program.commands.forEach($addGlobalOptionsToCommand);
|
|
106
120
|
|
|
107
|
-
if (
|
|
121
|
+
if (commandLineArguments.length === 0) {
|
|
108
122
|
program.outputHelp();
|
|
109
123
|
return process.exit(0);
|
|
110
124
|
}
|
|
@@ -112,6 +126,17 @@ export async function promptbookCli(): Promise<void> {
|
|
|
112
126
|
program.parse(process.argv);
|
|
113
127
|
}
|
|
114
128
|
|
|
129
|
+
/**
|
|
130
|
+
* Checks whether the invocation asks for the root Promptbook CLI version.
|
|
131
|
+
*
|
|
132
|
+
* @private internal utility of `promptbookCli`
|
|
133
|
+
*/
|
|
134
|
+
function isTopLevelVersionRequested(commandLineArguments: ReadonlyArray<string>): boolean {
|
|
135
|
+
const firstCommandLineArgument = commandLineArguments[0];
|
|
136
|
+
|
|
137
|
+
return firstCommandLineArgument !== undefined && VERSION_OPTION_ARGUMENTS.has(firstCommandLineArgument);
|
|
138
|
+
}
|
|
139
|
+
|
|
115
140
|
/**
|
|
116
141
|
* Adds one deprecation notice to each configured top-level legacy command.
|
|
117
142
|
*/
|