@promptbook/cli 0.103.0-49 → 0.103.0-50
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/src/app/[agentName]/[...rest]/page.tsx +6 -1
- package/apps/agents-server/src/app/agents/[agentName]/api/chat/route.ts +21 -1
- package/apps/agents-server/src/app/agents/[agentName]/api/profile/route.ts +23 -3
- package/apps/agents-server/src/app/agents/[agentName]/page.tsx +10 -2
- package/apps/agents-server/src/app/api/agents/route.ts +34 -0
- package/apps/agents-server/src/app/page.tsx +33 -0
- package/apps/agents-server/src/database/metadataDefaults.ts +5 -0
- package/apps/agents-server/src/middleware.ts +47 -9
- package/apps/agents-server/src/utils/getFederatedAgents.ts +66 -0
- package/esm/index.es.js +1 -1
- package/esm/typings/src/_packages/components.index.d.ts +2 -0
- package/esm/typings/src/book-components/PromptbookAgent/PromptbookAgent.d.ts +20 -0
- package/esm/typings/src/llm-providers/agent/Agent.d.ts +8 -0
- package/esm/typings/src/llm-providers/agent/AgentLlmExecutionTools.d.ts +7 -0
- package/esm/typings/src/llm-providers/agent/RemoteAgent.d.ts +5 -0
- package/esm/typings/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/umd/index.umd.js +1 -1
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
import { redirect } from 'next/navigation';
|
|
1
|
+
import { notFound, redirect } from 'next/navigation';
|
|
2
2
|
|
|
3
3
|
export default async function RedirectPage({ params }: { params: Promise<{ agentName: string; rest: string[] }> }) {
|
|
4
4
|
const { agentName, rest } = await params;
|
|
5
|
+
|
|
6
|
+
if (agentName === 'agents' || agentName === 'api' || agentName.startsWith('.')) {
|
|
7
|
+
notFound();
|
|
8
|
+
}
|
|
9
|
+
|
|
5
10
|
redirect(`/agents/${agentName}/${rest.join('/')}`);
|
|
6
11
|
}
|
|
@@ -11,6 +11,17 @@ import { assertsError } from '../../../../../../../../src/errors/assertsError';
|
|
|
11
11
|
*/
|
|
12
12
|
export const maxDuration = 300;
|
|
13
13
|
|
|
14
|
+
export async function OPTIONS(request: Request) {
|
|
15
|
+
return new Response(null, {
|
|
16
|
+
status: 200,
|
|
17
|
+
headers: {
|
|
18
|
+
'Access-Control-Allow-Origin': '*',
|
|
19
|
+
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
|
|
20
|
+
'Access-Control-Allow-Headers': 'Content-Type',
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
14
25
|
export async function POST(request: Request, { params }: { params: Promise<{ agentName: string }> }) {
|
|
15
26
|
let { agentName } = await params;
|
|
16
27
|
agentName = decodeURIComponent(agentName);
|
|
@@ -110,6 +121,12 @@ export async function POST(request: Request, { params }: { params: Promise<{ age
|
|
|
110
121
|
platform,
|
|
111
122
|
});
|
|
112
123
|
|
|
124
|
+
// Note: [🐱🚀] Save the learned data
|
|
125
|
+
const newAgentSource = agent.agentSource.value;
|
|
126
|
+
if (newAgentSource !== agentSource) {
|
|
127
|
+
await collection.updateAgentSource(agentName, newAgentSource);
|
|
128
|
+
}
|
|
129
|
+
|
|
113
130
|
controller.close();
|
|
114
131
|
})
|
|
115
132
|
.catch((error) => {
|
|
@@ -120,7 +137,10 @@ export async function POST(request: Request, { params }: { params: Promise<{ age
|
|
|
120
137
|
|
|
121
138
|
return new Response(readableStream, {
|
|
122
139
|
status: 200,
|
|
123
|
-
headers: {
|
|
140
|
+
headers: {
|
|
141
|
+
'Content-Type': 'text/markdown',
|
|
142
|
+
'Access-Control-Allow-Origin': '*', // <- Note: Allow embedding on other websites
|
|
143
|
+
},
|
|
124
144
|
});
|
|
125
145
|
} catch (error) {
|
|
126
146
|
assertsError(error);
|
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
import { $provideAgentCollectionForServer } from '@/src/tools/$provideAgentCollectionForServer';
|
|
2
|
-
import { parseAgentSource } from '@promptbook-local/core';
|
|
2
|
+
import { computeAgentHash, parseAgentSource } from '@promptbook-local/core';
|
|
3
3
|
import { serializeError } from '@promptbook-local/utils';
|
|
4
4
|
import { assertsError } from '../../../../../../../../src/errors/assertsError';
|
|
5
5
|
import { keepUnused } from '../../../../../../../../src/utils/organization/keepUnused';
|
|
6
6
|
|
|
7
|
+
export async function OPTIONS(request: Request) {
|
|
8
|
+
keepUnused(request);
|
|
9
|
+
return new Response(null, {
|
|
10
|
+
status: 200,
|
|
11
|
+
headers: {
|
|
12
|
+
'Access-Control-Allow-Origin': '*',
|
|
13
|
+
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
|
|
14
|
+
'Access-Control-Allow-Headers': 'Content-Type',
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
7
19
|
export async function GET(request: Request, { params }: { params: Promise<{ agentName: string }> }) {
|
|
8
20
|
keepUnused(request /* <- Note: We dont need `request` parameter */);
|
|
9
21
|
let { agentName } = await params;
|
|
@@ -13,10 +25,15 @@ export async function GET(request: Request, { params }: { params: Promise<{ agen
|
|
|
13
25
|
const collection = await $provideAgentCollectionForServer();
|
|
14
26
|
const agentSource = await collection.getAgentSource(agentName);
|
|
15
27
|
const agentProfile = parseAgentSource(agentSource);
|
|
28
|
+
const agentHash = computeAgentHash(agentSource);
|
|
16
29
|
|
|
17
30
|
return new Response(
|
|
18
31
|
JSON.stringify(
|
|
19
|
-
|
|
32
|
+
{
|
|
33
|
+
...agentProfile,
|
|
34
|
+
agentHash,
|
|
35
|
+
parameters: [], // <- TODO: [😰] Implement parameters
|
|
36
|
+
},
|
|
20
37
|
// <- TODO: [🐱🚀] Rename `serializeError` to `errorToJson`
|
|
21
38
|
null,
|
|
22
39
|
4,
|
|
@@ -24,7 +41,10 @@ export async function GET(request: Request, { params }: { params: Promise<{ agen
|
|
|
24
41
|
),
|
|
25
42
|
{
|
|
26
43
|
status: 200,
|
|
27
|
-
headers: {
|
|
44
|
+
headers: {
|
|
45
|
+
'Content-Type': 'application/json',
|
|
46
|
+
'Access-Control-Allow-Origin': '*', // <- Note: Allow embedding on other websites
|
|
47
|
+
},
|
|
28
48
|
},
|
|
29
49
|
);
|
|
30
50
|
} catch (error) {
|
|
@@ -4,7 +4,7 @@ import { $provideAgentCollectionForServer } from '@/src/tools/$provideAgentColle
|
|
|
4
4
|
// import { BookEditor } from '@promptbook-local/components';
|
|
5
5
|
import { $provideServer } from '@/src/tools/$provideServer';
|
|
6
6
|
import { parseAgentSource } from '@promptbook-local/core';
|
|
7
|
-
import { Columns2Icon,
|
|
7
|
+
import { Columns2Icon, MessagesSquareIcon, NotebookPenIcon } from 'lucide-react';
|
|
8
8
|
import { headers } from 'next/headers';
|
|
9
9
|
import { notFound } from 'next/navigation';
|
|
10
10
|
import { Color } from '../../../../../../src/utils/color/Color';
|
|
@@ -114,6 +114,14 @@ export default async function AgentPage({ params }: { params: Promise<{ agentNam
|
|
|
114
114
|
|
|
115
115
|
<div className="flex flex-col gap-2 mt-auto">
|
|
116
116
|
<div className="flex gap-2">
|
|
117
|
+
<a
|
|
118
|
+
href={`/agents/${encodeURIComponent(agentName)}/chat`}
|
|
119
|
+
// <- TODO: [🧠] Can I append path like this on current browser URL in href?
|
|
120
|
+
className="flex-1 inline-flex items-center justify-center whitespace-nowrap bg-white hover:bg-gray-100 text-gray-800 px-4 py-2 rounded shadow font-semibold transition border border-gray-200"
|
|
121
|
+
>
|
|
122
|
+
<MessagesSquareIcon className="ml-2 w-4 h-4 mr-2" />
|
|
123
|
+
Chat
|
|
124
|
+
</a>
|
|
117
125
|
<a
|
|
118
126
|
href={`/agents/${encodeURIComponent(agentName)}/book+chat`}
|
|
119
127
|
// <- TODO: [🧠] Can I append path like this on current browser URL in href?
|
|
@@ -127,7 +135,7 @@ export default async function AgentPage({ params }: { params: Promise<{ agentNam
|
|
|
127
135
|
// <- TODO: [🧠] Can I append path like this on current browser URL in href?
|
|
128
136
|
className="flex-1 inline-flex items-center justify-center whitespace-nowrap bg-white hover:bg-gray-100 text-gray-800 px-4 py-2 rounded shadow font-semibold transition border border-gray-200"
|
|
129
137
|
>
|
|
130
|
-
<
|
|
138
|
+
<NotebookPenIcon className="ml-2 w-4 h-4 mr-2" />
|
|
131
139
|
Edit
|
|
132
140
|
</a>
|
|
133
141
|
</div>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { getMetadata } from '../../../database/getMetadata';
|
|
3
|
+
import { $provideAgentCollectionForServer } from '../../../tools/$provideAgentCollectionForServer';
|
|
4
|
+
|
|
5
|
+
export const dynamic = 'force-dynamic';
|
|
6
|
+
|
|
7
|
+
export async function GET() {
|
|
8
|
+
try {
|
|
9
|
+
const collection = await $provideAgentCollectionForServer();
|
|
10
|
+
const agents = await collection.listAgents();
|
|
11
|
+
const serverUrl = (await getMetadata('SERVER_URL')) || '';
|
|
12
|
+
const federatedServersString = (await getMetadata('FEDERATED_SERVERS')) || '';
|
|
13
|
+
const federatedServers = federatedServersString
|
|
14
|
+
.split(',')
|
|
15
|
+
.map((s) => s.trim())
|
|
16
|
+
.filter((s) => s !== '');
|
|
17
|
+
|
|
18
|
+
const agentsWithUrl = agents.map((agent) => ({
|
|
19
|
+
...agent,
|
|
20
|
+
url: `${serverUrl}/${agent.agentName}`,
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
return NextResponse.json({
|
|
24
|
+
agents: agentsWithUrl,
|
|
25
|
+
federatedServers,
|
|
26
|
+
});
|
|
27
|
+
} catch (error) {
|
|
28
|
+
console.error('Error fetching agents:', error);
|
|
29
|
+
return NextResponse.json(
|
|
30
|
+
{ error: 'Failed to fetch agents' },
|
|
31
|
+
{ status: 500 },
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -10,10 +10,12 @@ import { $sideEffect } from '../../../../src/utils/organization/$sideEffect';
|
|
|
10
10
|
import { AuthControls } from '../components/Auth/AuthControls';
|
|
11
11
|
import { UsersList } from '../components/UsersList/UsersList';
|
|
12
12
|
import VercelDeploymentCard from '../components/VercelDeploymentCard/VercelDeploymentCard';
|
|
13
|
+
import { getMetadata } from '../database/getMetadata';
|
|
13
14
|
import { getLongRunningTask } from '../deamons/longRunningTask';
|
|
14
15
|
import { $provideAgentCollectionForServer } from '../tools/$provideAgentCollectionForServer';
|
|
15
16
|
import { $provideExecutionToolsForServer } from '../tools/$provideExecutionToolsForServer';
|
|
16
17
|
import { $provideServer } from '../tools/$provideServer';
|
|
18
|
+
import { getFederatedAgents } from '../utils/getFederatedAgents';
|
|
17
19
|
import { getCurrentUser } from '../utils/getCurrentUser';
|
|
18
20
|
import { isUserAdmin } from '../utils/isUserAdmin';
|
|
19
21
|
import { AddAgentButton } from './AddAgentButton';
|
|
@@ -37,6 +39,14 @@ export default async function HomePage() {
|
|
|
37
39
|
const collection = await $provideAgentCollectionForServer();
|
|
38
40
|
const agents = await collection.listAgents();
|
|
39
41
|
|
|
42
|
+
const federatedServersString = (await getMetadata('FEDERATED_SERVERS')) || '';
|
|
43
|
+
const federatedServers = federatedServersString
|
|
44
|
+
.split(',')
|
|
45
|
+
.map((s) => s.trim())
|
|
46
|
+
.filter((s) => s !== '');
|
|
47
|
+
|
|
48
|
+
const externalAgents = await getFederatedAgents(federatedServers);
|
|
49
|
+
|
|
40
50
|
const longRunningTask = getLongRunningTask();
|
|
41
51
|
|
|
42
52
|
const executionTools = await $provideExecutionToolsForServer();
|
|
@@ -73,6 +83,29 @@ export default async function HomePage() {
|
|
|
73
83
|
</div>
|
|
74
84
|
</>
|
|
75
85
|
|
|
86
|
+
{externalAgents.length > 0 && (
|
|
87
|
+
<>
|
|
88
|
+
<h2 className="text-3xl text-gray-900 mt-16 mb-4">External Agents ({externalAgents.length})</h2>
|
|
89
|
+
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
|
90
|
+
{externalAgents.map((agent) => (
|
|
91
|
+
<Link key={agent.url} href={agent.url}>
|
|
92
|
+
<AvatarProfile
|
|
93
|
+
{...{ agent }}
|
|
94
|
+
style={
|
|
95
|
+
!agent.meta.color
|
|
96
|
+
? {}
|
|
97
|
+
: {
|
|
98
|
+
backgroundColor: `${agent.meta.color}22`, // <- TODO: Use Color object here
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
className="block p-6 bg-white rounded-lg shadow-md hover:shadow-xl transition-shadow duration-300 border border-gray-200 hover:border-blue-400"
|
|
102
|
+
/>
|
|
103
|
+
</Link>
|
|
104
|
+
))}
|
|
105
|
+
</div>
|
|
106
|
+
</>
|
|
107
|
+
)}
|
|
108
|
+
|
|
76
109
|
{isAdmin && <UsersList />}
|
|
77
110
|
|
|
78
111
|
{isAdmin && (
|
|
@@ -29,4 +29,9 @@ export const metadataDefaults = [
|
|
|
29
29
|
value: '',
|
|
30
30
|
note: 'Comma separated list of allowed IPs or CIDR ranges. If set, only clients from these IPs are allowed to access the server.',
|
|
31
31
|
},
|
|
32
|
+
{
|
|
33
|
+
key: 'FEDERATED_SERVERS',
|
|
34
|
+
value: '',
|
|
35
|
+
note: 'Comma separated list of federated servers URLs. The server will look to all federated servers and list their agents.',
|
|
36
|
+
},
|
|
32
37
|
] as const;
|
|
@@ -72,10 +72,48 @@ export async function middleware(req: NextRequest) {
|
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
const allowedIps =
|
|
75
|
+
const allowedIps =
|
|
76
|
+
allowedIpsMetadata !== null && allowedIpsMetadata !== undefined ? allowedIpsMetadata : allowedIpsEnv;
|
|
76
77
|
|
|
77
78
|
if (isIpAllowed(ip, allowedIps)) {
|
|
78
|
-
//
|
|
79
|
+
// Handle OPTIONS (preflight) requests before any redirects
|
|
80
|
+
// to avoid CORS issues ("Redirect is not allowed for a preflight request")
|
|
81
|
+
if (req.method === 'OPTIONS') {
|
|
82
|
+
return new NextResponse(null, {
|
|
83
|
+
status: 200,
|
|
84
|
+
headers: {
|
|
85
|
+
'Access-Control-Allow-Origin': '*',
|
|
86
|
+
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
|
|
87
|
+
'Access-Control-Allow-Headers': 'Content-Type',
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// 3. Redirect /:agentName/* to /agents/:agentName/*
|
|
93
|
+
// This enables accessing agents from the root path
|
|
94
|
+
const pathParts = req.nextUrl.pathname.split('/');
|
|
95
|
+
const potentialAgentName = pathParts[1];
|
|
96
|
+
|
|
97
|
+
if (
|
|
98
|
+
potentialAgentName &&
|
|
99
|
+
!['agents', 'api', '_next', 'favicon.ico'].includes(potentialAgentName) &&
|
|
100
|
+
!potentialAgentName.startsWith('.') &&
|
|
101
|
+
// Note: Other static files are excluded by the matcher configuration below
|
|
102
|
+
true
|
|
103
|
+
) {
|
|
104
|
+
const url = req.nextUrl.clone();
|
|
105
|
+
url.pathname = `/agents${req.nextUrl.pathname}`;
|
|
106
|
+
const response = NextResponse.redirect(url);
|
|
107
|
+
|
|
108
|
+
// Enable CORS for the redirect
|
|
109
|
+
response.headers.set('Access-Control-Allow-Origin', '*');
|
|
110
|
+
response.headers.set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
|
|
111
|
+
response.headers.set('Access-Control-Allow-Headers', 'Content-Type');
|
|
112
|
+
|
|
113
|
+
return response;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// 4. Custom Domain Routing
|
|
79
117
|
// If the host is not one of the configured SERVERS, try to find an agent with a matching META LINK
|
|
80
118
|
|
|
81
119
|
if (host && SERVERS && !SERVERS.some((server) => server === host)) {
|
|
@@ -94,7 +132,7 @@ export async function middleware(req: NextRequest) {
|
|
|
94
132
|
// We check all configured servers because the custom domain could point to any of them
|
|
95
133
|
// (or if they share the database, we need to check the relevant tables)
|
|
96
134
|
const serversToCheck = SERVERS;
|
|
97
|
-
|
|
135
|
+
|
|
98
136
|
// TODO: [🧠] If there are many servers, this loop might be slow. Optimize if needed.
|
|
99
137
|
for (const serverHost of serversToCheck) {
|
|
100
138
|
let serverName = serverHost;
|
|
@@ -105,11 +143,11 @@ export async function middleware(req: NextRequest) {
|
|
|
105
143
|
// Search for agent with matching META LINK
|
|
106
144
|
// agentProfile->links is an array of strings
|
|
107
145
|
// We check if it contains the host, or https://host, or http://host
|
|
108
|
-
|
|
146
|
+
|
|
109
147
|
const searchLinks = [host, `https://${host}`, `http://${host}`];
|
|
110
|
-
|
|
148
|
+
|
|
111
149
|
// Construct OR filter: agentProfile.cs.{"links":["link1"]},agentProfile.cs.{"links":["link2"]},...
|
|
112
|
-
const orFilter = searchLinks.map(link => `agentProfile.cs.{"links":["${link}"]}`).join(',');
|
|
150
|
+
const orFilter = searchLinks.map((link) => `agentProfile.cs.{"links":["${link}"]}`).join(',');
|
|
113
151
|
|
|
114
152
|
try {
|
|
115
153
|
const { data } = await supabase
|
|
@@ -123,7 +161,7 @@ export async function middleware(req: NextRequest) {
|
|
|
123
161
|
// Found the agent!
|
|
124
162
|
const url = req.nextUrl.clone();
|
|
125
163
|
url.pathname = `/${data.agentName}`;
|
|
126
|
-
|
|
164
|
+
|
|
127
165
|
// Pass the server context to the app via header
|
|
128
166
|
const requestHeaders = new Headers(req.headers);
|
|
129
167
|
requestHeaders.set('x-promptbook-server', serverHost);
|
|
@@ -135,8 +173,8 @@ export async function middleware(req: NextRequest) {
|
|
|
135
173
|
});
|
|
136
174
|
}
|
|
137
175
|
} catch (error) {
|
|
138
|
-
|
|
139
|
-
|
|
176
|
+
// Ignore error (e.g. table not found, or agent not found) and continue to next server
|
|
177
|
+
// console.error(`Error checking server ${serverHost} for custom domain ${host}:`, error);
|
|
140
178
|
}
|
|
141
179
|
}
|
|
142
180
|
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { AgentCollection } from '@promptbook-local/types';
|
|
2
|
+
|
|
3
|
+
type Agent = Awaited<ReturnType<AgentCollection['listAgents']>>[number];
|
|
4
|
+
|
|
5
|
+
type AgentWithUrl = Agent & {
|
|
6
|
+
url: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
type AgentsApiResponse = {
|
|
10
|
+
agents: AgentWithUrl[];
|
|
11
|
+
federatedServers: string[];
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Fetches agents from federated servers recursively
|
|
16
|
+
*/
|
|
17
|
+
export async function getFederatedAgents(initialServers: string[]): Promise<AgentWithUrl[]> {
|
|
18
|
+
const visited = new Set<string>();
|
|
19
|
+
const queue = [...initialServers];
|
|
20
|
+
const externalAgentsMap = new Map<string, AgentWithUrl>();
|
|
21
|
+
const MAX_SERVERS = 20;
|
|
22
|
+
|
|
23
|
+
while (queue.length > 0 && visited.size < MAX_SERVERS) {
|
|
24
|
+
const serverUrl = queue.shift();
|
|
25
|
+
if (!serverUrl) continue;
|
|
26
|
+
|
|
27
|
+
const normalizedUrl = serverUrl.trim().replace(/\/$/, '');
|
|
28
|
+
if (visited.has(normalizedUrl)) continue;
|
|
29
|
+
visited.add(normalizedUrl);
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
// TODO: [🧠] Should we use some shorter timeout?
|
|
33
|
+
const response = await fetch(`${normalizedUrl}/api/agents`, {
|
|
34
|
+
next: { revalidate: 600 } // Cache for 10 minutes
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
if (!response.ok) {
|
|
38
|
+
console.warn(`Failed to fetch agents from ${normalizedUrl}: ${response.status} ${response.statusText}`);
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const data: AgentsApiResponse = await response.json();
|
|
43
|
+
|
|
44
|
+
if (data.agents && Array.isArray(data.agents)) {
|
|
45
|
+
for (const agent of data.agents) {
|
|
46
|
+
if (agent.url && !externalAgentsMap.has(agent.url)) {
|
|
47
|
+
externalAgentsMap.set(agent.url, agent);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (data.federatedServers && Array.isArray(data.federatedServers)) {
|
|
53
|
+
for (const server of data.federatedServers) {
|
|
54
|
+
const normalizedServer = server.trim().replace(/\/$/, '');
|
|
55
|
+
if (!visited.has(normalizedServer) && normalizedServer !== '') {
|
|
56
|
+
queue.push(normalizedServer);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
} catch (error) {
|
|
61
|
+
console.error(`Error fetching agents from ${normalizedUrl}:`, error);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return Array.from(externalAgentsMap.values());
|
|
66
|
+
}
|
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-50';
|
|
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
|
|
@@ -51,6 +51,7 @@ import { ResetIcon } from '../book-components/icons/ResetIcon';
|
|
|
51
51
|
import { SaveIcon } from '../book-components/icons/SaveIcon';
|
|
52
52
|
import { SendIcon } from '../book-components/icons/SendIcon';
|
|
53
53
|
import { TemplateIcon } from '../book-components/icons/TemplateIcon';
|
|
54
|
+
import { PromptbookAgent } from '../book-components/PromptbookAgent/PromptbookAgent';
|
|
54
55
|
import { BrandedQrCode } from '../book-components/Qr/BrandedQrCode';
|
|
55
56
|
import { GenericQrCode } from '../book-components/Qr/GenericQrCode';
|
|
56
57
|
import { PromptbookQrCode } from '../book-components/Qr/PromptbookQrCode';
|
|
@@ -109,6 +110,7 @@ export { ResetIcon };
|
|
|
109
110
|
export { SaveIcon };
|
|
110
111
|
export { SendIcon };
|
|
111
112
|
export { TemplateIcon };
|
|
113
|
+
export { PromptbookAgent };
|
|
112
114
|
export { BrandedQrCode };
|
|
113
115
|
export { GenericQrCode };
|
|
114
116
|
export { PromptbookQrCode };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import './PromptbookAgent.css';
|
|
2
|
+
type PromptbookAgentProps = {
|
|
3
|
+
/**
|
|
4
|
+
* URL of the agent to connect to
|
|
5
|
+
*
|
|
6
|
+
* @example "http://s6.ptbk.io/benjamin-white"
|
|
7
|
+
*/
|
|
8
|
+
agentUrl: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Renders a floating agent button that opens a chat window with the remote agent.
|
|
12
|
+
*
|
|
13
|
+
* @public exported from `@promptbook/components`
|
|
14
|
+
*/
|
|
15
|
+
export declare function PromptbookAgent(props: PromptbookAgentProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export {};
|
|
17
|
+
/**
|
|
18
|
+
* TODO: !!! Load the full branding
|
|
19
|
+
* TODO: !!! <promptbook-agent> element
|
|
20
|
+
*/
|
|
@@ -2,6 +2,8 @@ import { BehaviorSubject } from 'rxjs';
|
|
|
2
2
|
import type { AgentBasicInformation, BookParameter } from '../../book-2.0/agent-source/AgentBasicInformation';
|
|
3
3
|
import type { string_book } from '../../book-2.0/agent-source/string_book';
|
|
4
4
|
import type { LlmExecutionTools } from '../../execution/LlmExecutionTools';
|
|
5
|
+
import type { ChatPromptResult } from '../../execution/PromptResult';
|
|
6
|
+
import type { Prompt } from '../../types/Prompt';
|
|
5
7
|
import type { string_agent_hash, string_agent_name, string_agent_url, string_url_image } from '../../types/typeAliases';
|
|
6
8
|
import { AgentLlmExecutionTools } from './AgentLlmExecutionTools';
|
|
7
9
|
import type { AgentOptions } from './AgentOptions';
|
|
@@ -55,6 +57,12 @@ export declare class Agent extends AgentLlmExecutionTools implements LlmExecutio
|
|
|
55
57
|
get parameters(): BookParameter[];
|
|
56
58
|
readonly agentSource: BehaviorSubject<string_book>;
|
|
57
59
|
constructor(options: AgentOptions);
|
|
60
|
+
/**
|
|
61
|
+
* Calls the chat model with agent-specific system prompt and requirements with streaming
|
|
62
|
+
*
|
|
63
|
+
* Note: This method also implements the learning mechanism
|
|
64
|
+
*/
|
|
65
|
+
callChatModelStream(prompt: Prompt, onProgress: (chunk: ChatPromptResult) => void): Promise<ChatPromptResult>;
|
|
58
66
|
}
|
|
59
67
|
/**
|
|
60
68
|
* TODO: [🧠][😰]Agent is not working with the parameters, should it be?
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Promisable } from 'type-fest';
|
|
2
|
+
import type { string_book } from '../../book-2.0/agent-source/string_book';
|
|
2
3
|
import type { ChatParticipant } from '../../book-components/Chat/types/ChatParticipant';
|
|
3
4
|
import type { AvailableModel } from '../../execution/AvailableModel';
|
|
4
5
|
import type { LlmExecutionTools } from '../../execution/LlmExecutionTools';
|
|
@@ -40,6 +41,12 @@ export declare class AgentLlmExecutionTools implements LlmExecutionTools {
|
|
|
40
41
|
* @param agentSource The agent source string that defines the agent's behavior
|
|
41
42
|
*/
|
|
42
43
|
constructor(options: CreateAgentLlmExecutionToolsOptions);
|
|
44
|
+
/**
|
|
45
|
+
* Updates the agent source and clears the cache
|
|
46
|
+
*
|
|
47
|
+
* @param agentSource The new agent source string
|
|
48
|
+
*/
|
|
49
|
+
protected updateAgentSource(agentSource: string_book): void;
|
|
43
50
|
/**
|
|
44
51
|
* Get cached or parse agent information
|
|
45
52
|
*/
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ChatPromptResult } from '../../execution/PromptResult';
|
|
2
2
|
import type { Prompt } from '../../types/Prompt';
|
|
3
|
+
import type { string_agent_hash, string_agent_name } from '../../types/typeAliases';
|
|
3
4
|
import { Agent } from './Agent';
|
|
4
5
|
import type { RemoteAgentOptions } from './RemoteAgentOptions';
|
|
5
6
|
/**
|
|
@@ -20,7 +21,11 @@ export declare class RemoteAgent extends Agent {
|
|
|
20
21
|
* The source of the agent
|
|
21
22
|
*/
|
|
22
23
|
private agentUrl;
|
|
24
|
+
private _remoteAgentName;
|
|
25
|
+
private _remoteAgentHash;
|
|
23
26
|
private constructor();
|
|
27
|
+
get agentName(): string_agent_name;
|
|
28
|
+
get agentHash(): string_agent_hash;
|
|
24
29
|
/**
|
|
25
30
|
* Calls the agent on agents remote server
|
|
26
31
|
*/
|
|
@@ -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.103.0-
|
|
18
|
+
* It follows semantic versioning (e.g., `0.103.0-49`).
|
|
19
19
|
*
|
|
20
20
|
* @generated
|
|
21
21
|
*/
|
package/package.json
CHANGED
package/umd/index.umd.js
CHANGED
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
* @generated
|
|
57
57
|
* @see https://github.com/webgptorg/promptbook
|
|
58
58
|
*/
|
|
59
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.103.0-
|
|
59
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.103.0-50';
|
|
60
60
|
/**
|
|
61
61
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
62
62
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|