@promptbook/cli 0.103.0-67 → 0.103.0-68
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/TODO.txt +1 -5
- package/apps/agents-server/package-lock.json +8 -2317
- package/apps/agents-server/package.json +0 -9
- package/apps/agents-server/src/app/agents/[agentName]/AgentOptionsMenu.tsx +34 -2
- package/apps/agents-server/src/app/agents/[agentName]/AgentProfileWrapper.tsx +4 -0
- package/apps/agents-server/src/app/humans.txt/route.ts +15 -0
- package/apps/agents-server/src/app/layout.tsx +31 -0
- package/apps/agents-server/src/app/robots.txt/route.ts +15 -0
- package/apps/agents-server/src/app/security.txt/route.ts +15 -0
- package/apps/agents-server/src/app/sitemap.xml/route.ts +37 -0
- package/apps/agents-server/src/components/DocumentationContent/DocumentationContent.tsx +19 -18
- package/apps/agents-server/src/components/Footer/Footer.tsx +13 -13
- package/apps/agents-server/src/components/Header/Header.tsx +95 -20
- package/apps/agents-server/src/components/LayoutWrapper/LayoutWrapper.tsx +3 -0
- package/apps/agents-server/src/components/_utils/generateMetaTxt.ts +28 -0
- package/apps/agents-server/src/components/_utils/headlessParam.tsx +36 -0
- package/apps/agents-server/src/middleware.ts +6 -2
- package/esm/index.es.js +191 -14
- package/esm/index.es.js.map +1 -1
- package/esm/typings/src/_packages/components.index.d.ts +2 -0
- package/esm/typings/src/_packages/types.index.d.ts +6 -0
- package/esm/typings/src/book-components/BookEditor/BookEditor.d.ts +10 -0
- package/esm/typings/src/book-components/BookEditor/BookEditorActionbar.d.ts +4 -0
- package/esm/typings/src/book-components/icons/CameraIcon.d.ts +11 -0
- package/esm/typings/src/execution/LlmExecutionTools.d.ts +5 -1
- package/esm/typings/src/execution/PromptResult.d.ts +7 -1
- package/esm/typings/src/llm-providers/ollama/OllamaExecutionTools.d.ts +4 -0
- package/esm/typings/src/llm-providers/openai/OpenAiCompatibleExecutionTools.d.ts +13 -1
- package/esm/typings/src/llm-providers/openai/OpenAiExecutionTools.d.ts +4 -0
- package/esm/typings/src/llm-providers/openai/createOpenAiCompatibleExecutionTools.d.ts +6 -6
- package/esm/typings/src/types/ModelRequirements.d.ts +13 -1
- package/esm/typings/src/types/ModelVariant.d.ts +1 -1
- package/esm/typings/src/types/Prompt.d.ts +13 -1
- package/esm/typings/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/umd/index.umd.js +191 -14
- package/umd/index.umd.js.map +1 -1
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Utility to generate content for robots.txt, security.txt, and humans.txt [DRY]
|
|
2
|
+
|
|
3
|
+
import { NEXT_PUBLIC_SITE_URL } from '@/config';
|
|
4
|
+
|
|
5
|
+
// Get base URL from environment or config
|
|
6
|
+
const baseUrl = NEXT_PUBLIC_SITE_URL?.href || process.env.PUBLIC_URL || 'https://ptbk.io';
|
|
7
|
+
|
|
8
|
+
export function generateRobotsTxt(): string {
|
|
9
|
+
return ['User-agent: *', `Sitemap: ${baseUrl}sitemap.xml`, ''].join('\n');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function generateSecurityTxt(): string {
|
|
13
|
+
// See https://securitytxt.org/ for more fields
|
|
14
|
+
return [
|
|
15
|
+
`Contact: mailto:security@ptbk.io`,
|
|
16
|
+
`Expires: ${new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toISOString().split('T')[0]}`,
|
|
17
|
+
`Canonical: ${baseUrl}security.txt`,
|
|
18
|
+
'',
|
|
19
|
+
].join('\n');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function generateHumansTxt(): string {
|
|
23
|
+
return ['/* TEAM */', 'Developer: Promptbook Team', `Site: https://ptbk.io`, `Instance: ${baseUrl}`].join('\n');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* TODO: Use `spaceTrim`
|
|
28
|
+
*/
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Utility to append ?headless param if present in current URL
|
|
2
|
+
import { usePathname, useSearchParams } from 'next/navigation';
|
|
3
|
+
import Link, { LinkProps } from 'next/link';
|
|
4
|
+
import { useMemo } from 'react';
|
|
5
|
+
|
|
6
|
+
// Returns true if ?headless is present in current search params
|
|
7
|
+
export function useIsHeadless() {
|
|
8
|
+
const searchParams = useSearchParams();
|
|
9
|
+
return searchParams.has('headless');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Appends ?headless to a given href if needed
|
|
13
|
+
export function appendHeadlessParam(href: string, isHeadless: boolean): string {
|
|
14
|
+
if (!isHeadless) return href;
|
|
15
|
+
if (href.includes('headless')) return href;
|
|
16
|
+
const hasQuery = href.includes('?');
|
|
17
|
+
return hasQuery ? `${href}&headless` : `${href}?headless`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Custom Link that preserves headless param
|
|
21
|
+
export function HeadlessLink({ href, children, ...rest }: LinkProps & { children: React.ReactNode } & React.AnchorHTMLAttributes<HTMLAnchorElement>) {
|
|
22
|
+
const isHeadless = useIsHeadless();
|
|
23
|
+
const finalHref = useMemo(() => appendHeadlessParam(String(href), isHeadless), [href, isHeadless]);
|
|
24
|
+
return (
|
|
25
|
+
<Link href={finalHref} {...rest}>
|
|
26
|
+
{children}
|
|
27
|
+
</Link>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
import { useRouter } from "next/navigation";
|
|
32
|
+
|
|
33
|
+
// Helper for router.push
|
|
34
|
+
export function pushWithHeadless(router: ReturnType<typeof useRouter>, href: string, isHeadless: boolean) {
|
|
35
|
+
router.push(appendHeadlessParam(href, isHeadless));
|
|
36
|
+
}
|
|
@@ -191,12 +191,16 @@ export async function middleware(req: NextRequest) {
|
|
|
191
191
|
'api',
|
|
192
192
|
'admin',
|
|
193
193
|
'docs',
|
|
194
|
-
'manifest.webmanifest',
|
|
195
|
-
'sw.js',
|
|
196
194
|
'test',
|
|
197
195
|
'embed',
|
|
198
196
|
'_next',
|
|
197
|
+
'manifest.webmanifest',
|
|
198
|
+
'sw.js',
|
|
199
199
|
'favicon.ico',
|
|
200
|
+
'sitemap.xml',
|
|
201
|
+
'robots.txt',
|
|
202
|
+
'security.txt',
|
|
203
|
+
'humans.txt',
|
|
200
204
|
].includes(potentialAgentName) &&
|
|
201
205
|
!potentialAgentName.startsWith('.') &&
|
|
202
206
|
// Note: Other static files are excluded by the matcher configuration below
|
package/esm/index.es.js
CHANGED
|
@@ -47,7 +47,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
|
|
|
47
47
|
* @generated
|
|
48
48
|
* @see https://github.com/webgptorg/promptbook
|
|
49
49
|
*/
|
|
50
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.103.0-
|
|
50
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.103.0-68';
|
|
51
51
|
/**
|
|
52
52
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
53
53
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -10936,7 +10936,7 @@ const jokerCommandParser = {
|
|
|
10936
10936
|
* @see {@link ModelVariant}
|
|
10937
10937
|
* @public exported from `@promptbook/core`
|
|
10938
10938
|
*/
|
|
10939
|
-
const MODEL_VARIANTS = ['COMPLETION', 'CHAT', 'EMBEDDING' /* <- TODO [🏳] */ /* <- [🤖] */];
|
|
10939
|
+
const MODEL_VARIANTS = ['COMPLETION', 'CHAT', 'IMAGE_GENERATION', 'EMBEDDING' /* <- TODO [🏳] */ /* <- [🤖] */];
|
|
10940
10940
|
|
|
10941
10941
|
/**
|
|
10942
10942
|
* Parses the model command
|
|
@@ -17575,12 +17575,18 @@ const OPENAI_MODELS = exportJson({
|
|
|
17575
17575
|
},
|
|
17576
17576
|
},
|
|
17577
17577
|
/**/
|
|
17578
|
-
|
|
17579
|
-
|
|
17580
|
-
|
|
17581
|
-
|
|
17582
|
-
|
|
17583
|
-
|
|
17578
|
+
/**/
|
|
17579
|
+
{
|
|
17580
|
+
modelVariant: 'IMAGE_GENERATION',
|
|
17581
|
+
modelTitle: 'dall-e-3',
|
|
17582
|
+
modelName: 'dall-e-3',
|
|
17583
|
+
modelDescription: 'DALL·E 3 is the latest version of the DALL·E art generation model. It understands significantly more nuance and detail than our previous systems, allowing you to easily translate your ideas into exceptionally accurate images.',
|
|
17584
|
+
pricing: {
|
|
17585
|
+
prompt: 0,
|
|
17586
|
+
output: 0.04,
|
|
17587
|
+
},
|
|
17588
|
+
},
|
|
17589
|
+
/**/
|
|
17584
17590
|
/*/
|
|
17585
17591
|
{
|
|
17586
17592
|
modelTitle: 'whisper-1',
|
|
@@ -17599,12 +17605,18 @@ const OPENAI_MODELS = exportJson({
|
|
|
17599
17605
|
},
|
|
17600
17606
|
},
|
|
17601
17607
|
/**/
|
|
17602
|
-
|
|
17603
|
-
|
|
17604
|
-
|
|
17605
|
-
|
|
17606
|
-
|
|
17607
|
-
|
|
17608
|
+
/**/
|
|
17609
|
+
{
|
|
17610
|
+
modelVariant: 'IMAGE_GENERATION',
|
|
17611
|
+
modelTitle: 'dall-e-2',
|
|
17612
|
+
modelName: 'dall-e-2',
|
|
17613
|
+
modelDescription: 'DALL·E 2 is an AI system that can create realistic images and art from a description in natural language.',
|
|
17614
|
+
pricing: {
|
|
17615
|
+
prompt: 0,
|
|
17616
|
+
output: 0.02,
|
|
17617
|
+
},
|
|
17618
|
+
},
|
|
17619
|
+
/**/
|
|
17608
17620
|
/**/
|
|
17609
17621
|
{
|
|
17610
17622
|
modelVariant: 'CHAT',
|
|
@@ -19819,6 +19831,151 @@ class OpenAiCompatibleExecutionTools {
|
|
|
19819
19831
|
return this.callEmbeddingModelWithRetry(prompt, modifiedModelRequirements, attemptStack, retriedUnsupportedParameters);
|
|
19820
19832
|
}
|
|
19821
19833
|
}
|
|
19834
|
+
/**
|
|
19835
|
+
* Calls OpenAI compatible API to use a image generation model
|
|
19836
|
+
*/
|
|
19837
|
+
async callImageGenerationModel(prompt) {
|
|
19838
|
+
// Deep clone prompt and modelRequirements to avoid mutation across calls
|
|
19839
|
+
const clonedPrompt = JSON.parse(JSON.stringify(prompt));
|
|
19840
|
+
const retriedUnsupportedParameters = new Set();
|
|
19841
|
+
return this.callImageGenerationModelWithRetry(clonedPrompt, clonedPrompt.modelRequirements, [], retriedUnsupportedParameters);
|
|
19842
|
+
}
|
|
19843
|
+
/**
|
|
19844
|
+
* Internal method that handles parameter retry for image generation model calls
|
|
19845
|
+
*/
|
|
19846
|
+
async callImageGenerationModelWithRetry(prompt, currentModelRequirements, attemptStack = [], retriedUnsupportedParameters = new Set()) {
|
|
19847
|
+
var _a, _b;
|
|
19848
|
+
if (this.options.isVerbose) {
|
|
19849
|
+
console.info(`🎨 ${this.title} callImageGenerationModel call`, { prompt, currentModelRequirements });
|
|
19850
|
+
}
|
|
19851
|
+
const { content, parameters } = prompt;
|
|
19852
|
+
const client = await this.getClient();
|
|
19853
|
+
// TODO: [☂] Use here more modelRequirements
|
|
19854
|
+
if (currentModelRequirements.modelVariant !== 'IMAGE_GENERATION') {
|
|
19855
|
+
throw new PipelineExecutionError('Use callImageGenerationModel only for IMAGE_GENERATION variant');
|
|
19856
|
+
}
|
|
19857
|
+
const modelName = currentModelRequirements.modelName || this.getDefaultImageGenerationModel().modelName;
|
|
19858
|
+
const modelSettings = {
|
|
19859
|
+
model: modelName,
|
|
19860
|
+
// size: currentModelRequirements.size,
|
|
19861
|
+
// quality: currentModelRequirements.quality,
|
|
19862
|
+
// style: currentModelRequirements.style,
|
|
19863
|
+
};
|
|
19864
|
+
const rawPromptContent = templateParameters(content, { ...parameters, modelName });
|
|
19865
|
+
const rawRequest = {
|
|
19866
|
+
...modelSettings,
|
|
19867
|
+
prompt: rawPromptContent,
|
|
19868
|
+
user: (_a = this.options.userId) === null || _a === void 0 ? void 0 : _a.toString(),
|
|
19869
|
+
response_format: 'url', // TODO: [🧠] Maybe allow b64_json
|
|
19870
|
+
};
|
|
19871
|
+
const start = $getCurrentDate();
|
|
19872
|
+
if (this.options.isVerbose) {
|
|
19873
|
+
console.info(colors.bgWhite('rawRequest'), JSON.stringify(rawRequest, null, 4));
|
|
19874
|
+
}
|
|
19875
|
+
try {
|
|
19876
|
+
const rawResponse = await this.limiter
|
|
19877
|
+
.schedule(() => this.makeRequestWithNetworkRetry(() => client.images.generate(rawRequest)))
|
|
19878
|
+
.catch((error) => {
|
|
19879
|
+
assertsError(error);
|
|
19880
|
+
if (this.options.isVerbose) {
|
|
19881
|
+
console.info(colors.bgRed('error'), error);
|
|
19882
|
+
}
|
|
19883
|
+
throw error;
|
|
19884
|
+
});
|
|
19885
|
+
if (this.options.isVerbose) {
|
|
19886
|
+
console.info(colors.bgWhite('rawResponse'), JSON.stringify(rawResponse, null, 4));
|
|
19887
|
+
}
|
|
19888
|
+
const complete = $getCurrentDate();
|
|
19889
|
+
if (!rawResponse.data[0]) {
|
|
19890
|
+
throw new PipelineExecutionError(`No choises from ${this.title}`);
|
|
19891
|
+
}
|
|
19892
|
+
if (rawResponse.data.length > 1) {
|
|
19893
|
+
throw new PipelineExecutionError(`More than one choise from ${this.title}`);
|
|
19894
|
+
}
|
|
19895
|
+
const resultContent = rawResponse.data[0].url;
|
|
19896
|
+
const modelInfo = this.HARDCODED_MODELS.find((model) => model.modelName === modelName);
|
|
19897
|
+
const price = ((_b = modelInfo === null || modelInfo === void 0 ? void 0 : modelInfo.pricing) === null || _b === void 0 ? void 0 : _b.output) ? uncertainNumber(modelInfo.pricing.output) : uncertainNumber();
|
|
19898
|
+
return exportJson({
|
|
19899
|
+
name: 'promptResult',
|
|
19900
|
+
message: `Result of \`OpenAiCompatibleExecutionTools.callImageGenerationModel\``,
|
|
19901
|
+
order: [],
|
|
19902
|
+
value: {
|
|
19903
|
+
content: resultContent,
|
|
19904
|
+
modelName: modelName,
|
|
19905
|
+
timing: {
|
|
19906
|
+
start,
|
|
19907
|
+
complete,
|
|
19908
|
+
},
|
|
19909
|
+
usage: {
|
|
19910
|
+
price,
|
|
19911
|
+
input: {
|
|
19912
|
+
tokensCount: uncertainNumber(0),
|
|
19913
|
+
...computeUsageCounts(rawPromptContent),
|
|
19914
|
+
},
|
|
19915
|
+
output: {
|
|
19916
|
+
tokensCount: uncertainNumber(0),
|
|
19917
|
+
...computeUsageCounts(''),
|
|
19918
|
+
},
|
|
19919
|
+
},
|
|
19920
|
+
rawPromptContent,
|
|
19921
|
+
rawRequest,
|
|
19922
|
+
rawResponse,
|
|
19923
|
+
},
|
|
19924
|
+
});
|
|
19925
|
+
}
|
|
19926
|
+
catch (error) {
|
|
19927
|
+
assertsError(error);
|
|
19928
|
+
if (!isUnsupportedParameterError(error)) {
|
|
19929
|
+
if (attemptStack.length > 0) {
|
|
19930
|
+
throw new PipelineExecutionError(`All attempts failed. Attempt history:\n` +
|
|
19931
|
+
attemptStack
|
|
19932
|
+
.map((a, i) => ` ${i + 1}. Model: ${a.modelName}` +
|
|
19933
|
+
(a.unsupportedParameter ? `, Stripped: ${a.unsupportedParameter}` : '') +
|
|
19934
|
+
`, Error: ${a.errorMessage}` +
|
|
19935
|
+
(a.stripped ? ' (stripped and retried)' : ''))
|
|
19936
|
+
.join('\n') +
|
|
19937
|
+
`\nFinal error: ${error.message}`);
|
|
19938
|
+
}
|
|
19939
|
+
throw error;
|
|
19940
|
+
}
|
|
19941
|
+
const unsupportedParameter = parseUnsupportedParameterError(error.message);
|
|
19942
|
+
if (!unsupportedParameter) {
|
|
19943
|
+
if (this.options.isVerbose) {
|
|
19944
|
+
console.warn(colors.bgYellow('Warning'), 'Could not parse unsupported parameter from error:', error.message);
|
|
19945
|
+
}
|
|
19946
|
+
throw error;
|
|
19947
|
+
}
|
|
19948
|
+
const retryKey = `${modelName}-${unsupportedParameter}`;
|
|
19949
|
+
if (retriedUnsupportedParameters.has(retryKey)) {
|
|
19950
|
+
attemptStack.push({
|
|
19951
|
+
modelName,
|
|
19952
|
+
unsupportedParameter,
|
|
19953
|
+
errorMessage: error.message,
|
|
19954
|
+
stripped: true,
|
|
19955
|
+
});
|
|
19956
|
+
throw new PipelineExecutionError(`All attempts failed. Attempt history:\n` +
|
|
19957
|
+
attemptStack
|
|
19958
|
+
.map((a, i) => ` ${i + 1}. Model: ${a.modelName}` +
|
|
19959
|
+
(a.unsupportedParameter ? `, Stripped: ${a.unsupportedParameter}` : '') +
|
|
19960
|
+
`, Error: ${a.errorMessage}` +
|
|
19961
|
+
(a.stripped ? ' (stripped and retried)' : ''))
|
|
19962
|
+
.join('\n') +
|
|
19963
|
+
`\nFinal error: ${error.message}`);
|
|
19964
|
+
}
|
|
19965
|
+
retriedUnsupportedParameters.add(retryKey);
|
|
19966
|
+
if (this.options.isVerbose) {
|
|
19967
|
+
console.warn(colors.bgYellow('Warning'), `Removing unsupported parameter '${unsupportedParameter}' for model '${modelName}' and retrying request`);
|
|
19968
|
+
}
|
|
19969
|
+
attemptStack.push({
|
|
19970
|
+
modelName,
|
|
19971
|
+
unsupportedParameter,
|
|
19972
|
+
errorMessage: error.message,
|
|
19973
|
+
stripped: true,
|
|
19974
|
+
});
|
|
19975
|
+
const modifiedModelRequirements = removeUnsupportedModelRequirement(currentModelRequirements, unsupportedParameter);
|
|
19976
|
+
return this.callImageGenerationModelWithRetry(prompt, modifiedModelRequirements, attemptStack, retriedUnsupportedParameters);
|
|
19977
|
+
}
|
|
19978
|
+
}
|
|
19822
19979
|
// <- Note: [🤖] callXxxModel
|
|
19823
19980
|
/**
|
|
19824
19981
|
* Get the model that should be used as default
|
|
@@ -20242,6 +20399,13 @@ class OllamaExecutionTools extends OpenAiCompatibleExecutionTools {
|
|
|
20242
20399
|
return this.getDefaultModel('text-embedding-3-large'); // <- TODO: [🧠] Pick the best default model
|
|
20243
20400
|
// <- TODO: [🛄]
|
|
20244
20401
|
}
|
|
20402
|
+
/**
|
|
20403
|
+
* Default model for image generation variant.
|
|
20404
|
+
*/
|
|
20405
|
+
getDefaultImageGenerationModel() {
|
|
20406
|
+
return this.getDefaultModel('!!!'); // <- TODO: [🧠] Pick the best default model
|
|
20407
|
+
// <- TODO: [🛄]
|
|
20408
|
+
}
|
|
20245
20409
|
}
|
|
20246
20410
|
/**
|
|
20247
20411
|
* TODO: [🛄] Some way how to re-wrap the errors from `OpenAiCompatibleExecutionTools`
|
|
@@ -20477,6 +20641,12 @@ class OpenAiExecutionTools extends OpenAiCompatibleExecutionTools {
|
|
|
20477
20641
|
getDefaultEmbeddingModel() {
|
|
20478
20642
|
return this.getDefaultModel('text-embedding-3-large');
|
|
20479
20643
|
}
|
|
20644
|
+
/**
|
|
20645
|
+
* Default model for image generation variant.
|
|
20646
|
+
*/
|
|
20647
|
+
getDefaultImageGenerationModel() {
|
|
20648
|
+
return this.getDefaultModel('dall-e-3');
|
|
20649
|
+
}
|
|
20480
20650
|
}
|
|
20481
20651
|
|
|
20482
20652
|
/**
|
|
@@ -21047,6 +21217,13 @@ class HardcodedOpenAiCompatibleExecutionTools extends OpenAiCompatibleExecutionT
|
|
|
21047
21217
|
getDefaultEmbeddingModel() {
|
|
21048
21218
|
throw new PipelineExecutionError(`${this.title} does not support EMBEDDING model variant`);
|
|
21049
21219
|
}
|
|
21220
|
+
/**
|
|
21221
|
+
* Default model for image generation variant.
|
|
21222
|
+
*/
|
|
21223
|
+
getDefaultImageGenerationModel() {
|
|
21224
|
+
return this.getDefaultModel('!!!'); // <- TODO: [🧠] Pick the best default model
|
|
21225
|
+
// <- TODO: [🛄]
|
|
21226
|
+
}
|
|
21050
21227
|
}
|
|
21051
21228
|
/**
|
|
21052
21229
|
* TODO: [🦺] Is there some way how to put `packageName` and `className` on top and function definition on bottom?
|