@promptbook/cli 0.103.0-48 → 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/README.md +1 -1
- package/apps/agents-server/TODO.txt +6 -5
- package/apps/agents-server/config.ts +130 -0
- package/apps/agents-server/next.config.ts +1 -1
- package/apps/agents-server/public/fonts/OpenMoji-black-glyf.woff2 +0 -0
- package/apps/agents-server/public/fonts/download-font.js +22 -0
- package/apps/agents-server/src/app/[agentName]/[...rest]/page.tsx +11 -0
- package/apps/agents-server/src/app/[agentName]/page.tsx +1 -0
- package/apps/agents-server/src/app/actions.ts +37 -2
- package/apps/agents-server/src/app/agents/[agentName]/AgentChatWrapper.tsx +68 -0
- package/apps/agents-server/src/app/agents/[agentName]/AgentQrCode.tsx +55 -0
- package/apps/agents-server/src/app/agents/[agentName]/AgentUrlCopy.tsx +4 -5
- package/apps/agents-server/src/app/agents/[agentName]/CopyField.tsx +44 -0
- package/apps/agents-server/src/app/agents/[agentName]/api/book/route.ts +8 -8
- package/apps/agents-server/src/app/agents/[agentName]/api/chat/route.ts +121 -25
- package/apps/agents-server/src/app/agents/[agentName]/api/feedback/route.ts +54 -0
- package/apps/agents-server/src/app/agents/[agentName]/api/modelRequirements/route.ts +6 -6
- package/apps/agents-server/src/app/agents/[agentName]/api/modelRequirements/systemMessage/route.ts +3 -3
- package/apps/agents-server/src/app/agents/[agentName]/api/profile/route.ts +29 -10
- package/apps/agents-server/src/app/agents/[agentName]/book/BookEditorWrapper.tsx +4 -5
- package/apps/agents-server/src/app/agents/[agentName]/book/page.tsx +9 -2
- package/apps/agents-server/src/app/agents/[agentName]/book+chat/AgentBookAndChat.tsx +23 -0
- package/apps/agents-server/src/app/agents/[agentName]/book+chat/{AgentBookAndChatComponent.tsx → AgentBookAndChatComponent.tsx.todo} +4 -4
- package/apps/agents-server/src/app/agents/[agentName]/book+chat/page.tsx +28 -17
- package/apps/agents-server/src/app/agents/[agentName]/book+chat/page.tsx.todo +21 -0
- package/apps/agents-server/src/app/agents/[agentName]/chat/AgentChatWrapper.tsx +34 -4
- package/apps/agents-server/src/app/agents/[agentName]/chat/page.tsx +4 -1
- package/apps/agents-server/src/app/agents/[agentName]/generateAgentMetadata.ts +42 -0
- package/apps/agents-server/src/app/agents/[agentName]/page.tsx +117 -106
- package/apps/agents-server/src/app/agents/page.tsx +1 -1
- package/apps/agents-server/src/app/api/agents/route.ts +34 -0
- package/apps/agents-server/src/app/api/auth/login/route.ts +65 -0
- package/apps/agents-server/src/app/api/auth/logout/route.ts +7 -0
- package/apps/agents-server/src/app/api/metadata/route.ts +116 -0
- package/apps/agents-server/src/app/api/upload/route.ts +7 -3
- package/apps/agents-server/src/app/api/users/[username]/route.ts +75 -0
- package/apps/agents-server/src/app/api/users/route.ts +71 -0
- package/apps/agents-server/src/app/globals.css +35 -1
- package/apps/agents-server/src/app/layout.tsx +43 -23
- package/apps/agents-server/src/app/metadata/MetadataClient.tsx +271 -0
- package/apps/agents-server/src/app/metadata/page.tsx +13 -0
- package/apps/agents-server/src/app/not-found.tsx +5 -0
- package/apps/agents-server/src/app/page.tsx +117 -46
- package/apps/agents-server/src/components/Auth/AuthControls.tsx +123 -0
- package/apps/agents-server/src/components/ErrorPage/ErrorPage.tsx +33 -0
- package/apps/agents-server/src/components/ForbiddenPage/ForbiddenPage.tsx +15 -0
- package/apps/agents-server/src/components/Header/Header.tsx +146 -0
- package/apps/agents-server/src/components/LayoutWrapper/LayoutWrapper.tsx +27 -0
- package/apps/agents-server/src/components/LoginDialog/LoginDialog.tsx +40 -0
- package/apps/agents-server/src/components/LoginForm/LoginForm.tsx +109 -0
- package/apps/agents-server/src/components/NotFoundPage/NotFoundPage.tsx +17 -0
- package/apps/agents-server/src/components/UsersList/UsersList.tsx +190 -0
- package/apps/agents-server/src/components/VercelDeploymentCard/VercelDeploymentCard.tsx +60 -0
- package/apps/agents-server/src/database/$getTableName.ts +18 -0
- package/apps/agents-server/src/database/$provideSupabase.ts +2 -2
- package/apps/agents-server/src/database/$provideSupabaseForServer.ts +3 -3
- package/apps/agents-server/src/database/getMetadata.ts +31 -0
- package/apps/agents-server/src/database/metadataDefaults.ts +37 -0
- package/apps/agents-server/src/database/schema.sql +81 -33
- package/apps/agents-server/src/database/schema.ts +35 -1
- package/apps/agents-server/src/middleware.ts +200 -0
- package/apps/agents-server/src/tools/$provideAgentCollectionForServer.ts +11 -7
- package/apps/agents-server/src/tools/$provideCdnForServer.ts +1 -1
- package/apps/agents-server/src/tools/$provideExecutionToolsForServer.ts +11 -13
- package/apps/agents-server/src/tools/$provideOpenAiAssistantExecutionToolsForServer.ts +7 -7
- package/apps/agents-server/src/tools/$provideServer.ts +39 -0
- package/apps/agents-server/src/utils/auth.ts +33 -0
- package/apps/agents-server/src/utils/cdn/utils/nameToSubfolderPath.ts +1 -1
- package/apps/agents-server/src/utils/getCurrentUser.ts +32 -0
- package/apps/agents-server/src/utils/getFederatedAgents.ts +66 -0
- package/apps/agents-server/src/utils/isIpAllowed.ts +101 -0
- package/apps/agents-server/src/utils/isUserAdmin.ts +31 -0
- package/apps/agents-server/src/utils/session.ts +50 -0
- package/apps/agents-server/tailwind.config.ts +2 -0
- package/esm/index.es.js +147 -31
- package/esm/index.es.js.map +1 -1
- package/esm/typings/servers.d.ts +1 -0
- package/esm/typings/src/_packages/components.index.d.ts +2 -0
- package/esm/typings/src/_packages/types.index.d.ts +2 -0
- package/esm/typings/src/_packages/utils.index.d.ts +2 -0
- package/esm/typings/src/book-2.0/agent-source/AgentBasicInformation.d.ts +12 -2
- package/esm/typings/src/book-components/PromptbookAgent/PromptbookAgent.d.ts +20 -0
- package/esm/typings/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabase.d.ts +14 -8
- package/esm/typings/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabaseOptions.d.ts +10 -0
- package/esm/typings/src/commitments/MESSAGE/InitialMessageCommitmentDefinition.d.ts +28 -0
- package/esm/typings/src/commitments/index.d.ts +2 -1
- package/esm/typings/src/config.d.ts +1 -0
- package/esm/typings/src/errors/DatabaseError.d.ts +2 -2
- package/esm/typings/src/errors/WrappedError.d.ts +2 -2
- package/esm/typings/src/execution/ExecutionTask.d.ts +2 -2
- package/esm/typings/src/execution/LlmExecutionTools.d.ts +6 -1
- package/esm/typings/src/llm-providers/_common/register/$provideLlmToolsForWizardOrCli.d.ts +2 -2
- package/esm/typings/src/llm-providers/agent/Agent.d.ts +19 -3
- package/esm/typings/src/llm-providers/agent/AgentLlmExecutionTools.d.ts +13 -1
- package/esm/typings/src/llm-providers/agent/RemoteAgent.d.ts +11 -2
- package/esm/typings/src/llm-providers/openai/OpenAiAssistantExecutionTools.d.ts +6 -1
- package/esm/typings/src/remote-server/startAgentServer.d.ts +2 -2
- package/esm/typings/src/utils/color/Color.d.ts +7 -0
- package/esm/typings/src/utils/color/Color.test.d.ts +1 -0
- package/esm/typings/src/utils/environment/$getGlobalScope.d.ts +2 -2
- package/esm/typings/src/utils/misc/computeHash.d.ts +11 -0
- package/esm/typings/src/utils/misc/computeHash.test.d.ts +1 -0
- package/esm/typings/src/utils/organization/$sideEffect.d.ts +2 -2
- package/esm/typings/src/utils/organization/$side_effect.d.ts +2 -2
- package/esm/typings/src/utils/organization/TODO_USE.d.ts +2 -2
- package/esm/typings/src/utils/organization/keepUnused.d.ts +2 -2
- package/esm/typings/src/utils/organization/preserve.d.ts +3 -3
- package/esm/typings/src/utils/organization/really_any.d.ts +7 -0
- package/esm/typings/src/utils/serialization/asSerializable.d.ts +2 -2
- package/esm/typings/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/umd/index.umd.js +147 -31
- package/umd/index.umd.js.map +1 -1
- package/apps/agents-server/config.ts.todo +0 -38
|
@@ -1,15 +1,34 @@
|
|
|
1
|
+
import { $getTableName } from '@/src/database/$getTableName';
|
|
2
|
+
import { $provideSupabaseForServer } from '@/src/database/$provideSupabaseForServer';
|
|
1
3
|
import { $provideAgentCollectionForServer } from '@/src/tools/$provideAgentCollectionForServer';
|
|
2
4
|
import { $provideOpenAiAssistantExecutionToolsForServer } from '@/src/tools/$provideOpenAiAssistantExecutionToolsForServer';
|
|
3
|
-
import { Agent } from '@promptbook-local/core';
|
|
4
|
-
import { serializeError } from '@promptbook-local/utils';
|
|
5
|
+
import { Agent, computeAgentHash, PROMPTBOOK_ENGINE_VERSION } from '@promptbook-local/core';
|
|
6
|
+
import { computeHash, serializeError } from '@promptbook-local/utils';
|
|
5
7
|
import { assertsError } from '../../../../../../../../src/errors/assertsError';
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Allow long-running streams: set to platform maximum (seconds)
|
|
11
|
+
*/
|
|
12
|
+
export const maxDuration = 300;
|
|
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
|
+
|
|
25
|
+
export async function POST(request: Request, { params }: { params: Promise<{ agentName: string }> }) {
|
|
8
26
|
let { agentName } = await params;
|
|
9
27
|
agentName = decodeURIComponent(agentName);
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
|
|
28
|
+
|
|
29
|
+
const body = await request.json();
|
|
30
|
+
const { message = 'Tell me more about yourself.', thread } = body;
|
|
31
|
+
// <- TODO: [🐱🚀] To configuration DEFAULT_INITIAL_HIDDEN_MESSAGE
|
|
13
32
|
|
|
14
33
|
try {
|
|
15
34
|
const collection = await $provideAgentCollectionForServer();
|
|
@@ -17,7 +36,7 @@ export async function GET(request: Request, { params }: { params: Promise<{ agen
|
|
|
17
36
|
const openAiAssistantExecutionTools = await $provideOpenAiAssistantExecutionToolsForServer();
|
|
18
37
|
const agentSource = await collection.getAgentSource(agentName);
|
|
19
38
|
const agent = new Agent({
|
|
20
|
-
isVerbose: true, // <- TODO:
|
|
39
|
+
isVerbose: true, // <- TODO: [🐱🚀] From environment variable
|
|
21
40
|
executionTools: {
|
|
22
41
|
// [▶️] ...executionTools,
|
|
23
42
|
llm: openAiAssistantExecutionTools, // Note: Providing the OpenAI Assistant LLM tools to the Agent to be able to create its own Assistants GPTs
|
|
@@ -25,20 +44,103 @@ export async function GET(request: Request, { params }: { params: Promise<{ agen
|
|
|
25
44
|
agentSource,
|
|
26
45
|
});
|
|
27
46
|
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
47
|
+
const agentHash = computeAgentHash(agentSource);
|
|
48
|
+
const userAgent = request.headers.get('user-agent');
|
|
49
|
+
const ip =
|
|
50
|
+
request.headers.get('x-forwarded-for') ||
|
|
51
|
+
request.headers.get('x-real-ip') ||
|
|
52
|
+
request.headers.get('x-client-ip');
|
|
53
|
+
|
|
54
|
+
// Note: Capture language and platform information
|
|
55
|
+
const language = request.headers.get('accept-language');
|
|
56
|
+
// Simple platform extraction from userAgent parentheses content (e.g., Windows NT 10.0; Win64; x64)
|
|
57
|
+
const platform = userAgent ? userAgent.match(/\(([^)]+)\)/)?.[1] : undefined; // <- TODO: [🧠] Improve platform parsing
|
|
58
|
+
|
|
59
|
+
// Note: Identify the user message
|
|
60
|
+
const userMessageContent = {
|
|
61
|
+
role: 'USER',
|
|
34
62
|
content: message,
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// Record the user message
|
|
66
|
+
const supabase = $provideSupabaseForServer();
|
|
67
|
+
await supabase.from(await $getTableName('ChatHistory')).insert({
|
|
68
|
+
createdAt: new Date().toISOString(),
|
|
69
|
+
messageHash: computeHash(userMessageContent),
|
|
70
|
+
previousMessageHash: null, // <- TODO: [🧠] How to handle previous message hash?
|
|
71
|
+
agentName,
|
|
72
|
+
agentHash,
|
|
73
|
+
message: userMessageContent,
|
|
74
|
+
promptbookEngineVersion: PROMPTBOOK_ENGINE_VERSION,
|
|
75
|
+
url: request.url,
|
|
76
|
+
ip,
|
|
77
|
+
userAgent,
|
|
78
|
+
language,
|
|
79
|
+
platform,
|
|
35
80
|
});
|
|
36
81
|
|
|
37
|
-
|
|
82
|
+
const encoder = new TextEncoder();
|
|
83
|
+
const readableStream = new ReadableStream({
|
|
84
|
+
start(controller) {
|
|
85
|
+
agent.callChatModelStream!(
|
|
86
|
+
{
|
|
87
|
+
title: `Chat with agent ${
|
|
88
|
+
agentName /* <- TODO: [🕛] There should be `agentFullname` not `agentName` */
|
|
89
|
+
}`,
|
|
90
|
+
parameters: {},
|
|
91
|
+
modelRequirements: {
|
|
92
|
+
modelVariant: 'CHAT',
|
|
93
|
+
},
|
|
94
|
+
content: message,
|
|
95
|
+
thread,
|
|
96
|
+
},
|
|
97
|
+
(chunk) => {
|
|
98
|
+
controller.enqueue(encoder.encode(chunk.content));
|
|
99
|
+
},
|
|
100
|
+
)
|
|
101
|
+
.then(async (response) => {
|
|
102
|
+
// Note: Identify the agent message
|
|
103
|
+
const agentMessageContent = {
|
|
104
|
+
role: 'MODEL',
|
|
105
|
+
content: response.content,
|
|
106
|
+
};
|
|
38
107
|
|
|
39
|
-
|
|
108
|
+
// Record the agent message
|
|
109
|
+
await supabase.from(await $getTableName('ChatHistory')).insert({
|
|
110
|
+
createdAt: new Date().toISOString(),
|
|
111
|
+
messageHash: computeHash(agentMessageContent),
|
|
112
|
+
previousMessageHash: computeHash(userMessageContent),
|
|
113
|
+
agentName,
|
|
114
|
+
agentHash,
|
|
115
|
+
message: agentMessageContent,
|
|
116
|
+
promptbookEngineVersion: PROMPTBOOK_ENGINE_VERSION,
|
|
117
|
+
url: request.url,
|
|
118
|
+
ip,
|
|
119
|
+
userAgent,
|
|
120
|
+
language,
|
|
121
|
+
platform,
|
|
122
|
+
});
|
|
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
|
+
|
|
130
|
+
controller.close();
|
|
131
|
+
})
|
|
132
|
+
.catch((error) => {
|
|
133
|
+
controller.error(error);
|
|
134
|
+
});
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
return new Response(readableStream, {
|
|
40
139
|
status: 200,
|
|
41
|
-
headers: {
|
|
140
|
+
headers: {
|
|
141
|
+
'Content-Type': 'text/markdown',
|
|
142
|
+
'Access-Control-Allow-Origin': '*', // <- Note: Allow embedding on other websites
|
|
143
|
+
},
|
|
42
144
|
});
|
|
43
145
|
} catch (error) {
|
|
44
146
|
assertsError(error);
|
|
@@ -48,21 +150,15 @@ export async function GET(request: Request, { params }: { params: Promise<{ agen
|
|
|
48
150
|
return new Response(
|
|
49
151
|
JSON.stringify(
|
|
50
152
|
serializeError(error),
|
|
51
|
-
// <- TODO:
|
|
153
|
+
// <- TODO: [🐱🚀] Rename `serializeError` to `errorToJson`
|
|
52
154
|
null,
|
|
53
155
|
4,
|
|
54
|
-
// <- TODO:
|
|
156
|
+
// <- TODO: [🐱🚀] Allow to configure pretty print for agent server
|
|
55
157
|
),
|
|
56
158
|
{
|
|
57
|
-
status: 400, // <- TODO:
|
|
159
|
+
status: 400, // <- TODO: [🐱🚀] Make `errorToHttpStatusCode`
|
|
58
160
|
headers: { 'Content-Type': 'application/json' },
|
|
59
161
|
},
|
|
60
162
|
);
|
|
61
163
|
}
|
|
62
164
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* TODO: !!!!!! Record conversations to `ChatHistory`
|
|
67
|
-
* TODO: !!!!!! Make api endpoint for feedback on agent responses `/apps/agents-server/src/app/agents/[agentName]/api/feedback/route.ts` and record to `ChatFeedback`
|
|
68
|
-
*/
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { $provideSupabaseForServer } from '@/src/database/$provideSupabaseForServer';
|
|
2
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
3
|
+
import { PROMPTBOOK_ENGINE_VERSION } from '../../../../../../../../src/version';
|
|
4
|
+
import { $getTableName } from '../../../../../database/$getTableName';
|
|
5
|
+
|
|
6
|
+
type FeedbackRequest = {
|
|
7
|
+
agentHash: string;
|
|
8
|
+
rating?: string;
|
|
9
|
+
textRating?: string;
|
|
10
|
+
chatThread?: string;
|
|
11
|
+
userNote?: string;
|
|
12
|
+
expectedAnswer?: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export async function POST(request: NextRequest, { params }: { params: Promise<{ agentName: string }> }) {
|
|
16
|
+
try {
|
|
17
|
+
const { agentName } = await params;
|
|
18
|
+
const body = (await request.json()) as FeedbackRequest;
|
|
19
|
+
const { agentHash, rating, textRating, chatThread, userNote, expectedAnswer } = body;
|
|
20
|
+
|
|
21
|
+
if (!agentHash) {
|
|
22
|
+
return NextResponse.json({ message: 'Missing agentHash' }, { status: 400 });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const supabase = $provideSupabaseForServer();
|
|
26
|
+
|
|
27
|
+
const { error } = await supabase.from(await $getTableName('ChatFeedback')).insert({
|
|
28
|
+
createdAt: new Date().toISOString(),
|
|
29
|
+
agentName,
|
|
30
|
+
agentHash,
|
|
31
|
+
rating,
|
|
32
|
+
textRating,
|
|
33
|
+
chatThread,
|
|
34
|
+
userNote,
|
|
35
|
+
expectedAnswer,
|
|
36
|
+
promptbookEngineVersion: PROMPTBOOK_ENGINE_VERSION,
|
|
37
|
+
// Telemetry fields can be populated here if available in headers
|
|
38
|
+
// For now we leave them null or let Supabase handle default if any (though schema has them nullable)
|
|
39
|
+
url: request.headers.get('referer') || undefined,
|
|
40
|
+
userAgent: request.headers.get('user-agent') || undefined,
|
|
41
|
+
ip: request.headers.get('x-forwarded-for') || undefined,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
if (error) {
|
|
45
|
+
console.error('Error inserting feedback:', error);
|
|
46
|
+
return NextResponse.json({ message: 'Failed to save feedback' }, { status: 500 });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return NextResponse.json({ message: 'Feedback saved' }, { status: 201 });
|
|
50
|
+
} catch (error) {
|
|
51
|
+
console.error('Unexpected error in feedback route:', error);
|
|
52
|
+
return NextResponse.json({ message: 'Internal server error' }, { status: 500 });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -17,10 +17,10 @@ export async function GET(request: Request, { params }: { params: Promise<{ agen
|
|
|
17
17
|
return new Response(
|
|
18
18
|
JSON.stringify(
|
|
19
19
|
modelRequirements,
|
|
20
|
-
// <- TODO:
|
|
20
|
+
// <- TODO: [🐱🚀] Rename `serializeError` to `errorToJson`
|
|
21
21
|
null,
|
|
22
22
|
4,
|
|
23
|
-
// <- TODO:
|
|
23
|
+
// <- TODO: [🐱🚀] Allow to configure pretty print for agent server
|
|
24
24
|
),
|
|
25
25
|
{
|
|
26
26
|
status: 200,
|
|
@@ -35,13 +35,13 @@ export async function GET(request: Request, { params }: { params: Promise<{ agen
|
|
|
35
35
|
return new Response(
|
|
36
36
|
JSON.stringify(
|
|
37
37
|
serializeError(error),
|
|
38
|
-
// <- TODO:
|
|
38
|
+
// <- TODO: [🐱🚀] Rename `serializeError` to `errorToJson`
|
|
39
39
|
null,
|
|
40
40
|
4,
|
|
41
|
-
// <- TODO:
|
|
41
|
+
// <- TODO: [🐱🚀] Allow to configure pretty print for agent server
|
|
42
42
|
),
|
|
43
43
|
{
|
|
44
|
-
status: 400, // <- TODO:
|
|
44
|
+
status: 400, // <- TODO: [🐱🚀] Make `errorToHttpStatusCode`
|
|
45
45
|
headers: { 'Content-Type': 'application/json' },
|
|
46
46
|
},
|
|
47
47
|
);
|
|
@@ -50,4 +50,4 @@ export async function GET(request: Request, { params }: { params: Promise<{ agen
|
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
52
|
* TODO: [🍞] DRY - Make some common utility for API on one agent
|
|
53
|
-
*/
|
|
53
|
+
*/
|
package/apps/agents-server/src/app/agents/[agentName]/api/modelRequirements/systemMessage/route.ts
CHANGED
|
@@ -27,13 +27,13 @@ export async function GET(request: Request, { params }: { params: Promise<{ agen
|
|
|
27
27
|
return new Response(
|
|
28
28
|
JSON.stringify(
|
|
29
29
|
serializeError(error),
|
|
30
|
-
// <- TODO:
|
|
30
|
+
// <- TODO: [🐱🚀] Rename `serializeError` to `errorToJson`
|
|
31
31
|
null,
|
|
32
32
|
4,
|
|
33
|
-
// <- TODO:
|
|
33
|
+
// <- TODO: [🐱🚀] Allow to configure pretty print for agent server
|
|
34
34
|
),
|
|
35
35
|
{
|
|
36
|
-
status: 400, // <- TODO:
|
|
36
|
+
status: 400, // <- TODO: [🐱🚀] Make `errorToHttpStatusCode`
|
|
37
37
|
headers: { 'Content-Type': 'application/json' },
|
|
38
38
|
},
|
|
39
39
|
);
|
|
@@ -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,18 +25,26 @@ 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
|
-
|
|
20
|
-
|
|
32
|
+
{
|
|
33
|
+
...agentProfile,
|
|
34
|
+
agentHash,
|
|
35
|
+
parameters: [], // <- TODO: [😰] Implement parameters
|
|
36
|
+
},
|
|
37
|
+
// <- TODO: [🐱🚀] Rename `serializeError` to `errorToJson`
|
|
21
38
|
null,
|
|
22
39
|
4,
|
|
23
|
-
// <- TODO:
|
|
40
|
+
// <- TODO: [🐱🚀] Allow to configure pretty print for agent server
|
|
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) {
|
|
@@ -35,20 +55,19 @@ export async function GET(request: Request, { params }: { params: Promise<{ agen
|
|
|
35
55
|
return new Response(
|
|
36
56
|
JSON.stringify(
|
|
37
57
|
serializeError(error),
|
|
38
|
-
// <- TODO:
|
|
58
|
+
// <- TODO: [🐱🚀] Rename `serializeError` to `errorToJson`
|
|
39
59
|
null,
|
|
40
60
|
4,
|
|
41
|
-
// <- TODO:
|
|
61
|
+
// <- TODO: [🐱🚀] Allow to configure pretty print for agent server
|
|
42
62
|
),
|
|
43
63
|
{
|
|
44
|
-
status: 400, // <- TODO:
|
|
64
|
+
status: 400, // <- TODO: [🐱🚀] Make `errorToHttpStatusCode`
|
|
45
65
|
headers: { 'Content-Type': 'application/json' },
|
|
46
66
|
},
|
|
47
67
|
);
|
|
48
68
|
}
|
|
49
69
|
}
|
|
50
70
|
|
|
51
|
-
|
|
52
71
|
/**
|
|
53
72
|
* TODO: [🍞] DRY - Make some common utility for API on one agent
|
|
54
|
-
*/
|
|
73
|
+
*/
|
|
@@ -9,7 +9,7 @@ type BookEditorWrapperProps = {
|
|
|
9
9
|
initialAgentSource: string_book;
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
// TODO:
|
|
12
|
+
// TODO: [🐱🚀] Rename to BookEditorSavingWrapper
|
|
13
13
|
|
|
14
14
|
export function BookEditorWrapper({ agentName, initialAgentSource }: BookEditorWrapperProps) {
|
|
15
15
|
const [agentSource, setAgentSource] = useState<string_book>(initialAgentSource);
|
|
@@ -126,15 +126,14 @@ export function BookEditorWrapper({ agentName, initialAgentSource }: BookEditorW
|
|
|
126
126
|
|
|
127
127
|
return shortFileUrl;
|
|
128
128
|
}}
|
|
129
|
-
// <- TODO: !!!! Create two-state solution for `<BookEditor onFileUpload={...} />`
|
|
130
129
|
/>
|
|
131
130
|
</div>
|
|
132
131
|
);
|
|
133
132
|
}
|
|
134
133
|
|
|
135
134
|
/**
|
|
135
|
+
* TODO: Prompt: Use `import { debounce } from '@promptbook-local/utils';` instead of custom debounce implementation
|
|
136
136
|
* TODO: [🚗] Transfer the saving logic to `<BookEditor/>` be aware of CRDT / yjs approach to be implementable in future
|
|
137
|
-
*
|
|
138
|
-
* TODO:
|
|
139
|
-
* TODO: !!! Show save status indicator
|
|
137
|
+
* TODO: [🐱🚀] Add error handling and retry logic
|
|
138
|
+
* TODO: [🐱🚀] Show save status indicator
|
|
140
139
|
*/
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
|
|
3
|
+
import { ForbiddenPage } from '@/src/components/ForbiddenPage/ForbiddenPage';
|
|
3
4
|
import { $provideAgentCollectionForServer } from '@/src/tools/$provideAgentCollectionForServer';
|
|
5
|
+
import { isUserAdmin } from '@/src/utils/isUserAdmin';
|
|
4
6
|
import { headers } from 'next/headers';
|
|
5
7
|
import { $sideEffect } from '../../../../../../../src/utils/organization/$sideEffect';
|
|
6
8
|
import { BookEditorWrapper } from './BookEditorWrapper';
|
|
@@ -8,15 +10,20 @@ import { BookEditorWrapper } from './BookEditorWrapper';
|
|
|
8
10
|
export default async function AgentBookPage({ params }: { params: Promise<{ agentName: string }> }) {
|
|
9
11
|
$sideEffect(headers());
|
|
10
12
|
|
|
13
|
+
if (!(await isUserAdmin())) {
|
|
14
|
+
/* <- TODO: [👹] Here should be user permissions */
|
|
15
|
+
return <ForbiddenPage />;
|
|
16
|
+
}
|
|
17
|
+
|
|
11
18
|
let { agentName } = await params;
|
|
12
19
|
agentName = decodeURIComponent(agentName);
|
|
13
20
|
const collection = await $provideAgentCollectionForServer();
|
|
14
21
|
const agentSource = await collection.getAgentSource(decodeURIComponent(agentName));
|
|
15
22
|
|
|
16
23
|
return (
|
|
17
|
-
<
|
|
24
|
+
<div className={`w-screen h-[calc(100vh-60px)]`}>
|
|
18
25
|
<BookEditorWrapper agentName={agentName} initialAgentSource={agentSource} />
|
|
19
|
-
</
|
|
26
|
+
</div>
|
|
20
27
|
);
|
|
21
28
|
}
|
|
22
29
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { ResizablePanelsAuto } from '@common/components/ResizablePanelsAuto/ResizablePanelsAuto';
|
|
4
|
+
import { string_agent_url, string_book } from '@promptbook-local/types';
|
|
5
|
+
import { BookEditorWrapper } from '../book/BookEditorWrapper';
|
|
6
|
+
import { AgentChatWrapper } from '../AgentChatWrapper';
|
|
7
|
+
|
|
8
|
+
type AgentBookAndChatProps = {
|
|
9
|
+
agentName: string;
|
|
10
|
+
initialAgentSource: string_book;
|
|
11
|
+
agentUrl: string_agent_url;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export function AgentBookAndChat(props: AgentBookAndChatProps) {
|
|
15
|
+
const { agentName, initialAgentSource, agentUrl } = props;
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<ResizablePanelsAuto name={`agent-book-and-chat-${agentName}`} className="w-full h-full">
|
|
19
|
+
<BookEditorWrapper agentName={agentName} initialAgentSource={initialAgentSource} />
|
|
20
|
+
<AgentChatWrapper agentUrl={agentUrl} />
|
|
21
|
+
</ResizablePanelsAuto>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -16,7 +16,7 @@ export function AgentBookAndChatComponent() {
|
|
|
16
16
|
|
|
17
17
|
const [agentSource, setAgentSource] = useStateInLocalStorage<string_book>(
|
|
18
18
|
'marigold-agentSource-1',
|
|
19
|
-
// TODO:
|
|
19
|
+
// TODO: [🐱🚀] Uplad image to ptbk.io CDN
|
|
20
20
|
() => book`
|
|
21
21
|
Marigold
|
|
22
22
|
|
|
@@ -53,7 +53,7 @@ export function AgentBookAndChatComponent() {
|
|
|
53
53
|
|
|
54
54
|
const agent = useMemo(() => {
|
|
55
55
|
/*/
|
|
56
|
-
// TODO:
|
|
56
|
+
// TODO: [🐱🚀] Try working with `RemoteLlmExecutionTools`
|
|
57
57
|
const llm = new RemoteLlmExecutionTools({
|
|
58
58
|
remoteServerUrl: 'https://promptbook.s5.ptbk.io/',
|
|
59
59
|
identification: {
|
|
@@ -66,7 +66,7 @@ export function AgentBookAndChatComponent() {
|
|
|
66
66
|
/**/
|
|
67
67
|
const llm = new OpenAiAssistantExecutionTools({
|
|
68
68
|
dangerouslyAllowBrowser: true,
|
|
69
|
-
isCreatingNewAssistantsAllowed: true, // <- TODO:
|
|
69
|
+
isCreatingNewAssistantsAllowed: true, // <- TODO: [🐱🚀] Test without whether warning is shown
|
|
70
70
|
apiKey,
|
|
71
71
|
assistantId: 'asst_xI94Elk27nssnwAUkG2Cmok8', // <- TODO: [🧠] Make dynamic
|
|
72
72
|
isVerbose: true,
|
|
@@ -155,6 +155,6 @@ export function AgentBookAndChatComponent() {
|
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
/**
|
|
158
|
-
* TODO:
|
|
158
|
+
* TODO: [🐱🚀] Make self-learning book createAgentLlmExecutionTools, use bidirectional agentSource
|
|
159
159
|
* TODO: [🚗] Components and pages here should be just tiny UI wraper around proper agent logic and conponents
|
|
160
160
|
*/
|
|
@@ -1,21 +1,32 @@
|
|
|
1
|
-
'use
|
|
1
|
+
'use server';
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import { ForbiddenPage } from '@/src/components/ForbiddenPage/ForbiddenPage';
|
|
4
|
+
import { $provideAgentCollectionForServer } from '@/src/tools/$provideAgentCollectionForServer';
|
|
5
|
+
import { isUserAdmin } from '@/src/utils/isUserAdmin';
|
|
6
|
+
import { headers } from 'next/headers';
|
|
7
|
+
import { $sideEffect } from '../../../../../../../src/utils/organization/$sideEffect';
|
|
8
|
+
import { generateAgentMetadata } from '../generateAgentMetadata';
|
|
9
|
+
import { AgentBookAndChat } from './AgentBookAndChat';
|
|
4
10
|
|
|
5
|
-
const
|
|
6
|
-
() => import('./AgentBookAndChatComponent').then((module) => module.AgentBookAndChatComponent),
|
|
7
|
-
{
|
|
8
|
-
ssr: false,
|
|
9
|
-
},
|
|
10
|
-
);
|
|
11
|
+
export const generateMetadata = generateAgentMetadata;
|
|
11
12
|
|
|
12
|
-
export default function AgentBookAndChatPage() {
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
export default async function AgentBookAndChatPage({ params }: { params: Promise<{ agentName: string }> }) {
|
|
14
|
+
$sideEffect(headers());
|
|
15
|
+
|
|
16
|
+
if (!(await isUserAdmin())) {
|
|
17
|
+
/* <- TODO: [👹] Here should be user permissions */
|
|
18
|
+
return <ForbiddenPage />;
|
|
19
|
+
}
|
|
15
20
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
let { agentName } = await params;
|
|
22
|
+
agentName = decodeURIComponent(agentName);
|
|
23
|
+
const collection = await $provideAgentCollectionForServer();
|
|
24
|
+
const agentSource = await collection.getAgentSource(agentName);
|
|
25
|
+
const agentUrl = `/agents/${agentName}`;
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<div className={`w-screen h-[calc(100vh-60px)]`}>
|
|
29
|
+
<AgentBookAndChat agentName={agentName} initialAgentSource={agentSource} agentUrl={agentUrl} />
|
|
30
|
+
</div>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import dynamic from 'next/dynamic';
|
|
4
|
+
|
|
5
|
+
const SelfLearningBook = dynamic(
|
|
6
|
+
() => import('./AgentBookAndChatComponent').then((module) => module.AgentBookAndChatComponent),
|
|
7
|
+
{
|
|
8
|
+
ssr: false,
|
|
9
|
+
},
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
export default function AgentBookAndChatPage() {
|
|
13
|
+
return <SelfLearningBook />;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* TODO: [🐱🚀] Private / public / open agents
|
|
18
|
+
* TODO: [🐱🚀] Allow http://localhost:4440/agents/agent-123.book to download the agent book file
|
|
19
|
+
* TODO: [🐱🚀] BOOK_MIME_TYPE in config
|
|
20
|
+
* TODO: [🚗] Components and pages here should be just tiny UI wraper around proper agent logic and conponents
|
|
21
|
+
*/
|
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
import { usePromise } from '@common/hooks/usePromise';
|
|
4
4
|
import { AgentChat } from '@promptbook-local/components';
|
|
5
5
|
import { RemoteAgent } from '@promptbook-local/core';
|
|
6
|
-
import { useMemo } from 'react';
|
|
6
|
+
import { useCallback, useMemo } from 'react';
|
|
7
7
|
import { string_agent_url } from '../../../../../../../src/types/typeAliases';
|
|
8
8
|
|
|
9
9
|
type AgentChatWrapperProps = {
|
|
10
10
|
agentUrl: string_agent_url;
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
-
// TODO:
|
|
13
|
+
// TODO: [🐱🚀] Rename to AgentChatSomethingWrapper
|
|
14
14
|
|
|
15
15
|
export function AgentChatWrapper(props: AgentChatWrapperProps) {
|
|
16
16
|
const { agentUrl } = props;
|
|
@@ -26,11 +26,41 @@ export function AgentChatWrapper(props: AgentChatWrapperProps) {
|
|
|
26
26
|
|
|
27
27
|
const { value: agent } = usePromise(agentPromise, [agentPromise]);
|
|
28
28
|
|
|
29
|
+
const handleFeedback = useCallback(
|
|
30
|
+
async (feedback: {
|
|
31
|
+
rating: number;
|
|
32
|
+
textRating?: string;
|
|
33
|
+
chatThread?: string;
|
|
34
|
+
userNote?: string;
|
|
35
|
+
expectedAnswer?: string | null;
|
|
36
|
+
}) => {
|
|
37
|
+
if (!agent) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
await fetch(`${agentUrl}/api/feedback`, {
|
|
42
|
+
method: 'POST',
|
|
43
|
+
headers: {
|
|
44
|
+
'Content-Type': 'application/json',
|
|
45
|
+
},
|
|
46
|
+
body: JSON.stringify({
|
|
47
|
+
rating: feedback.rating.toString(),
|
|
48
|
+
textRating: feedback.textRating,
|
|
49
|
+
chatThread: feedback.chatThread,
|
|
50
|
+
userNote: feedback.textRating, // Mapping textRating to userNote as well if needed, or just textRating
|
|
51
|
+
expectedAnswer: feedback.expectedAnswer,
|
|
52
|
+
agentHash: agent.agentHash,
|
|
53
|
+
}),
|
|
54
|
+
});
|
|
55
|
+
},
|
|
56
|
+
[agent, agentUrl],
|
|
57
|
+
);
|
|
58
|
+
|
|
29
59
|
if (!agent) {
|
|
30
|
-
return <>{/* <- TODO:
|
|
60
|
+
return <>{/* <- TODO: [🐱🚀] <PromptbookLoading /> */}</>;
|
|
31
61
|
}
|
|
32
62
|
|
|
33
|
-
return <AgentChat className={`w-full h-full`} agent={agent} />;
|
|
63
|
+
return <AgentChat className={`w-full h-full`} agent={agent} onFeedback={handleFeedback} />;
|
|
34
64
|
}
|
|
35
65
|
|
|
36
66
|
/**
|
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import { headers } from 'next/headers';
|
|
4
4
|
import { $sideEffect } from '../../../../../../../src/utils/organization/$sideEffect';
|
|
5
|
-
import {
|
|
5
|
+
import { generateAgentMetadata } from '../generateAgentMetadata';
|
|
6
|
+
import { AgentChatWrapper } from '../AgentChatWrapper';
|
|
7
|
+
|
|
8
|
+
export const generateMetadata = generateAgentMetadata;
|
|
6
9
|
|
|
7
10
|
export default async function AgentChatPage({ params }: { params: Promise<{ agentName: string }> }) {
|
|
8
11
|
$sideEffect(headers());
|