synthos 0.7.2 → 0.8.0
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 +215 -65
- package/default-pages/application.json +1 -0
- package/default-pages/json_tools.json +1 -1
- package/default-pages/oregon_trail.html +321 -0
- package/default-pages/oregon_trail.json +12 -0
- package/default-pages/sidebar_page.json +1 -0
- package/default-pages/solar_explorer.html +10 -18
- package/default-pages/solar_explorer.json +2 -2
- package/default-pages/two-panel_page.json +1 -0
- package/default-pages/us_map.html +192 -0
- package/default-pages/us_map.json +12 -0
- package/default-pages/us_map_1850.html +325 -0
- package/default-pages/us_map_1850.json +12 -0
- package/default-pages/western_cities_1850.html +526 -0
- package/default-pages/western_cities_1850.json +12 -0
- package/default-themes/{nebula-dawn.css → nebula-dawn.v2.css} +24 -0
- package/default-themes/{nebula-dusk.css → nebula-dusk.v2.css} +24 -0
- package/dist/agents/a2a/a2aProvider.d.ts +3 -0
- package/dist/agents/a2a/a2aProvider.d.ts.map +1 -0
- package/dist/agents/a2a/a2aProvider.js +126 -0
- package/dist/agents/a2a/a2aProvider.js.map +1 -0
- package/dist/agents/discovery.d.ts +30 -0
- package/dist/agents/discovery.d.ts.map +1 -0
- package/dist/agents/discovery.js +52 -0
- package/dist/agents/discovery.js.map +1 -0
- package/dist/agents/index.d.ts +7 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +19 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/openclaw/gatewayManager.d.ts +113 -0
- package/dist/agents/openclaw/gatewayManager.d.ts.map +1 -0
- package/dist/agents/openclaw/gatewayManager.js +470 -0
- package/dist/agents/openclaw/gatewayManager.js.map +1 -0
- package/dist/agents/openclaw/openclawProvider.d.ts +3 -0
- package/dist/agents/openclaw/openclawProvider.d.ts.map +1 -0
- package/dist/agents/openclaw/openclawProvider.js +239 -0
- package/dist/agents/openclaw/openclawProvider.js.map +1 -0
- package/dist/agents/openclaw/sshTunnelManager.d.ts +23 -0
- package/dist/agents/openclaw/sshTunnelManager.d.ts.map +1 -0
- package/dist/agents/openclaw/sshTunnelManager.js +340 -0
- package/dist/agents/openclaw/sshTunnelManager.js.map +1 -0
- package/dist/agents/types.d.ts +64 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/types.js +6 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/connectors/airtable/connector.json +27 -0
- package/dist/connectors/alpha-vantage/connector.json +26 -0
- package/dist/connectors/brave-search/connector.json +26 -0
- package/dist/connectors/cloudinary/connector.json +27 -0
- package/dist/connectors/deepl/connector.json +28 -0
- package/dist/connectors/elevenlabs/connector.json +30 -0
- package/dist/connectors/giphy/connector.json +27 -0
- package/dist/connectors/github/connector.json +29 -0
- package/dist/connectors/huggingface/connector.json +27 -0
- package/dist/connectors/imgur/connector.json +29 -0
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.d.ts.map +1 -1
- package/dist/connectors/instagram/connector.json +43 -0
- package/dist/connectors/jira/connector.json +28 -0
- package/dist/connectors/mapbox/connector.json +26 -0
- package/dist/connectors/nasa/connector.json +27 -0
- package/dist/connectors/newsapi/connector.json +27 -0
- package/dist/connectors/notion/connector.json +28 -0
- package/dist/connectors/open-exchange-rates/connector.json +27 -0
- package/dist/connectors/openweathermap/connector.json +26 -0
- package/dist/connectors/pexels/connector.json +27 -0
- package/dist/connectors/registry.d.ts.map +1 -1
- package/dist/connectors/registry.js +42 -96
- package/dist/connectors/registry.js.map +1 -1
- package/dist/connectors/resend/connector.json +29 -0
- package/dist/connectors/rss2json/connector.json +27 -0
- package/dist/connectors/sendgrid/connector.json +27 -0
- package/dist/connectors/spoonacular/connector.json +28 -0
- package/dist/connectors/stability-ai/connector.json +27 -0
- package/dist/connectors/twilio/connector.json +28 -0
- package/dist/connectors/types.d.ts +23 -0
- package/dist/connectors/types.d.ts.map +1 -1
- package/dist/connectors/unsplash/connector.json +27 -0
- package/dist/connectors/wolfram-alpha/connector.json +26 -0
- package/dist/connectors/youtube-data/connector.json +30 -0
- package/dist/files.d.ts +1 -0
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +16 -1
- package/dist/files.js.map +1 -1
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +28 -0
- package/dist/init.js.map +1 -1
- package/dist/migrations.d.ts +3 -2
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +122 -138
- package/dist/migrations.js.map +1 -1
- package/dist/models/anthropic.d.ts +22 -0
- package/dist/models/anthropic.d.ts.map +1 -0
- package/dist/models/anthropic.js +76 -0
- package/dist/models/anthropic.js.map +1 -0
- package/dist/models/chainOfThought.d.ts +12 -0
- package/dist/models/chainOfThought.d.ts.map +1 -0
- package/dist/models/chainOfThought.js +45 -0
- package/dist/models/chainOfThought.js.map +1 -0
- package/dist/models/fireworksai.d.ts +30 -0
- package/dist/models/fireworksai.d.ts.map +1 -0
- package/dist/models/fireworksai.js +133 -0
- package/dist/models/fireworksai.js.map +1 -0
- package/dist/models/index.d.ts +7 -1
- package/dist/models/index.d.ts.map +1 -1
- package/dist/models/index.js +19 -1
- package/dist/models/index.js.map +1 -1
- package/dist/models/logCompletePrompt.d.ts +3 -0
- package/dist/models/logCompletePrompt.d.ts.map +1 -0
- package/dist/models/logCompletePrompt.js +23 -0
- package/dist/models/logCompletePrompt.js.map +1 -0
- package/dist/models/openai.d.ts +24 -0
- package/dist/models/openai.d.ts.map +1 -0
- package/dist/models/openai.js +80 -0
- package/dist/models/openai.js.map +1 -0
- package/dist/models/providers.d.ts +1 -0
- package/dist/models/providers.d.ts.map +1 -1
- package/dist/models/providers.js +12 -4
- package/dist/models/providers.js.map +1 -1
- package/dist/models/types.d.ts +34 -2
- package/dist/models/types.d.ts.map +1 -1
- package/dist/models/types.js +16 -0
- package/dist/models/types.js.map +1 -1
- package/dist/models/utils.d.ts +6 -0
- package/dist/models/utils.d.ts.map +1 -0
- package/dist/models/utils.js +21 -0
- package/dist/models/utils.js.map +1 -0
- package/dist/scripts.d.ts +2 -1
- package/dist/scripts.d.ts.map +1 -1
- package/dist/scripts.js +4 -3
- package/dist/scripts.js.map +1 -1
- package/dist/service/createCompletePrompt.d.ts +1 -1
- package/dist/service/createCompletePrompt.d.ts.map +1 -1
- package/dist/service/createCompletePrompt.js +9 -6
- package/dist/service/createCompletePrompt.js.map +1 -1
- package/dist/service/generateImage.d.ts +1 -1
- package/dist/service/generateImage.d.ts.map +1 -1
- package/dist/service/generateImage.js +3 -3
- package/dist/service/generateImage.js.map +1 -1
- package/dist/service/server.d.ts.map +1 -1
- package/dist/service/server.js +3 -0
- package/dist/service/server.js.map +1 -1
- package/dist/service/transformPage.d.ts +4 -2
- package/dist/service/transformPage.d.ts.map +1 -1
- package/dist/service/transformPage.js +74 -6
- package/dist/service/transformPage.js.map +1 -1
- package/dist/service/useAgentRoutes.d.ts +4 -0
- package/dist/service/useAgentRoutes.d.ts.map +1 -0
- package/dist/service/useAgentRoutes.js +389 -0
- package/dist/service/useAgentRoutes.js.map +1 -0
- package/dist/service/useApiRoutes.d.ts.map +1 -1
- package/dist/service/useApiRoutes.js +157 -16
- package/dist/service/useApiRoutes.js.map +1 -1
- package/dist/service/useConnectorRoutes.d.ts.map +1 -1
- package/dist/service/useConnectorRoutes.js +14 -3
- package/dist/service/useConnectorRoutes.js.map +1 -1
- package/dist/service/useGatewayRoutes.d.ts +4 -0
- package/dist/service/useGatewayRoutes.d.ts.map +1 -0
- package/dist/service/useGatewayRoutes.js +168 -0
- package/dist/service/useGatewayRoutes.js.map +1 -0
- package/dist/service/usePageRoutes.d.ts.map +1 -1
- package/dist/service/usePageRoutes.js +16 -5
- package/dist/service/usePageRoutes.js.map +1 -1
- package/dist/settings.d.ts +2 -1
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +4 -8
- package/dist/settings.js.map +1 -1
- package/dist/themes.d.ts +14 -0
- package/dist/themes.d.ts.map +1 -1
- package/dist/themes.js +86 -13
- package/dist/themes.js.map +1 -1
- package/package.json +8 -5
- package/page-scripts/helpers-v2.js +101 -0
- package/page-scripts/page-v2.js +47 -6
- package/required-pages/builder.html +1 -27
- package/required-pages/pages.html +745 -22
- package/required-pages/settings.html +819 -21
- package/required-pages/synthos_apis.html +56 -1
- package/src/agents/a2a/a2aProvider.ts +110 -0
- package/src/agents/discovery.ts +74 -0
- package/src/agents/index.ts +6 -0
- package/src/agents/openclaw/gatewayManager.ts +559 -0
- package/src/agents/openclaw/openclawProvider.ts +261 -0
- package/src/agents/openclaw/sshTunnelManager.ts +385 -0
- package/src/agents/types.ts +82 -0
- package/src/connectors/airtable/connector.json +27 -0
- package/src/connectors/alpha-vantage/connector.json +26 -0
- package/src/connectors/brave-search/connector.json +26 -0
- package/src/connectors/cloudinary/connector.json +27 -0
- package/src/connectors/deepl/connector.json +28 -0
- package/src/connectors/elevenlabs/connector.json +30 -0
- package/src/connectors/giphy/connector.json +27 -0
- package/src/connectors/github/connector.json +29 -0
- package/src/connectors/huggingface/connector.json +27 -0
- package/src/connectors/imgur/connector.json +29 -0
- package/src/connectors/index.ts +2 -0
- package/src/connectors/instagram/connector.json +43 -0
- package/src/connectors/jira/connector.json +28 -0
- package/src/connectors/mapbox/connector.json +26 -0
- package/src/connectors/nasa/connector.json +27 -0
- package/src/connectors/newsapi/connector.json +27 -0
- package/src/connectors/notion/connector.json +28 -0
- package/src/connectors/open-exchange-rates/connector.json +27 -0
- package/src/connectors/openweathermap/connector.json +26 -0
- package/src/connectors/pexels/connector.json +27 -0
- package/src/connectors/registry.ts +21 -97
- package/src/connectors/resend/connector.json +29 -0
- package/src/connectors/rss2json/connector.json +27 -0
- package/src/connectors/sendgrid/connector.json +27 -0
- package/src/connectors/spoonacular/connector.json +28 -0
- package/src/connectors/stability-ai/connector.json +27 -0
- package/src/connectors/twilio/connector.json +28 -0
- package/src/connectors/types.ts +25 -0
- package/src/connectors/unsplash/connector.json +27 -0
- package/src/connectors/wolfram-alpha/connector.json +26 -0
- package/src/connectors/youtube-data/connector.json +30 -0
- package/src/files.ts +14 -0
- package/src/init.ts +27 -0
- package/src/migrations.ts +121 -138
- package/src/models/anthropic.ts +89 -0
- package/src/models/chainOfThought.ts +56 -0
- package/src/models/fireworksai.ts +136 -0
- package/src/models/index.ts +7 -1
- package/src/models/logCompletePrompt.ts +25 -0
- package/src/models/openai.ts +90 -0
- package/src/models/providers.ts +12 -3
- package/src/models/types.ts +67 -2
- package/src/models/utils.ts +16 -0
- package/src/scripts.ts +2 -2
- package/src/service/createCompletePrompt.ts +3 -1
- package/src/service/generateImage.ts +2 -2
- package/src/service/server.ts +4 -0
- package/src/service/transformPage.ts +81 -8
- package/src/service/useAgentRoutes.ts +423 -0
- package/src/service/useApiRoutes.ts +173 -18
- package/src/service/useConnectorRoutes.ts +14 -3
- package/src/service/usePageRoutes.ts +20 -6
- package/src/settings.ts +6 -10
- package/src/themes.ts +84 -12
- package/tests/anthropic.spec.ts +84 -0
- package/tests/chainOfThought.spec.ts +108 -0
- package/tests/ensureScripts.spec.ts +82 -0
- package/tests/files.spec.ts +233 -0
- package/tests/fireworksai.spec.ts +92 -0
- package/tests/logCompletePrompt.spec.ts +74 -0
- package/tests/migrations.spec.ts +79 -1
- package/tests/openai.spec.ts +71 -0
- package/tests/pages.spec.ts +226 -1
- package/tests/providers.spec.ts +144 -0
- package/tests/scripts.spec.ts +209 -0
- package/tests/transformPage.spec.ts +517 -0
- package/tests/types.spec.ts +23 -0
- package/default-pages/app_builder.json +0 -1
- package/default-pages/sidebar_builder.json +0 -1
- package/default-pages/two-panel_builder.json +0 -1
- package/images/home.png +0 -0
- package/images/page-management.png +0 -0
- package/images/settings.png +0 -0
- package/images/synthos-square.png +0 -0
- /package/default-pages/{app_builder.html → application.html} +0 -0
- /package/default-pages/{sidebar_builder.html → sidebar_page.html} +0 -0
- /package/default-pages/{two-panel_builder.html → two-panel_page.html} +0 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import OpenAI from 'openai';
|
|
2
|
+
import { AgentCompletion, completePrompt, PromptCompletionArgs, RequestError } from './types';
|
|
3
|
+
|
|
4
|
+
export interface OpenaiArgs {
|
|
5
|
+
apiKey: string;
|
|
6
|
+
model: string;
|
|
7
|
+
baseURL?: string;
|
|
8
|
+
organization?: string;
|
|
9
|
+
project?: string;
|
|
10
|
+
temperature?: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Build the input messages and text format config for an OpenAI Responses API request.
|
|
15
|
+
* Pure function — no SDK dependency.
|
|
16
|
+
*/
|
|
17
|
+
export function buildOpenAIRequest(args: PromptCompletionArgs): {
|
|
18
|
+
input: { role: string; content: string }[];
|
|
19
|
+
text?: { format: any };
|
|
20
|
+
} {
|
|
21
|
+
const input: { role: string; content: string }[] = [];
|
|
22
|
+
if (args.history) {
|
|
23
|
+
for (const msg of args.history) {
|
|
24
|
+
input.push({ role: msg.role, content: msg.content });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
input.push({ role: 'user', content: args.prompt.content });
|
|
28
|
+
|
|
29
|
+
if (args.jsonMode || args.jsonSchema) {
|
|
30
|
+
const inputText = input.map(m => m.content).join(' ');
|
|
31
|
+
if (!/json/i.test(inputText)) {
|
|
32
|
+
const last = input[input.length - 1];
|
|
33
|
+
if (last) {
|
|
34
|
+
last.content += '\nReturn JSON.';
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let text: { format: any } | undefined;
|
|
40
|
+
if (args.jsonSchema) {
|
|
41
|
+
text = {
|
|
42
|
+
format: {
|
|
43
|
+
type: 'json_schema',
|
|
44
|
+
name: 'response',
|
|
45
|
+
strict: true,
|
|
46
|
+
schema: args.jsonSchema,
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
} else if (args.jsonMode) {
|
|
50
|
+
text = {
|
|
51
|
+
format: { type: 'json_object' },
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return { input, text };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function openai(args: OpenaiArgs): completePrompt {
|
|
59
|
+
const { apiKey, model, baseURL, organization, project } = args;
|
|
60
|
+
|
|
61
|
+
const client = new OpenAI({ apiKey, baseURL, organization, project });
|
|
62
|
+
|
|
63
|
+
return async (completionArgs: PromptCompletionArgs): Promise<AgentCompletion<string>> => {
|
|
64
|
+
const { input, text } = buildOpenAIRequest(completionArgs);
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
const response = await client.responses.create({
|
|
68
|
+
model,
|
|
69
|
+
instructions: completionArgs.system?.content,
|
|
70
|
+
input: input as OpenAI.Responses.ResponseInputItem[],
|
|
71
|
+
...(text ? { text } : {}),
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const output = response.output_text;
|
|
75
|
+
if (output === undefined || output === null) {
|
|
76
|
+
return { completed: false, error: new Error('No response output returned') };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return { completed: true, value: output };
|
|
80
|
+
} catch (err: unknown) {
|
|
81
|
+
let error: Error;
|
|
82
|
+
if (err instanceof OpenAI.APIError && (err as any).status !== undefined) {
|
|
83
|
+
error = new RequestError(err.message, (err as any).status, err.name ?? 'APIError');
|
|
84
|
+
} else {
|
|
85
|
+
error = err as Error;
|
|
86
|
+
}
|
|
87
|
+
return { completed: false, error };
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|
package/src/models/providers.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { Provider, ProviderName } from './types';
|
|
|
3
3
|
export const AnthropicProvider: Provider = {
|
|
4
4
|
name: 'Anthropic',
|
|
5
5
|
builderModels: ['claude-opus-4-6', 'claude-sonnet-4-5'],
|
|
6
|
-
chatModels: ['claude-
|
|
6
|
+
chatModels: ['claude-sonnet-4-5','claude-haiku-4-5'],
|
|
7
7
|
detectModel(model: string): boolean {
|
|
8
8
|
return model.startsWith('claude-');
|
|
9
9
|
}
|
|
@@ -14,11 +14,20 @@ export const OpenAIProvider: Provider = {
|
|
|
14
14
|
builderModels: ['gpt-5.2', 'gpt-5.2-codex'],
|
|
15
15
|
chatModels: ['gpt-5-nano', 'gpt-5-mini', 'gpt-4.1'],
|
|
16
16
|
detectModel(model: string): boolean {
|
|
17
|
-
return model.startsWith('gpt-')
|
|
17
|
+
return model.startsWith('gpt-');
|
|
18
18
|
}
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
-
export const
|
|
21
|
+
export const FireworksAIProvider: Provider = {
|
|
22
|
+
name: 'FireworksAI',
|
|
23
|
+
builderModels: ['fireworks-glm-5'],
|
|
24
|
+
chatModels: ['fireworks-minimax-m2p5', 'fireworks-kimi-k2p5', 'fireworks-glm-5'],
|
|
25
|
+
detectModel(model: string): boolean {
|
|
26
|
+
return model.startsWith('fireworks-');
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const PROVIDERS: Provider[] = [AnthropicProvider, OpenAIProvider, FireworksAIProvider];
|
|
22
31
|
|
|
23
32
|
export function getProvider(name: ProviderName): Provider {
|
|
24
33
|
const provider = PROVIDERS.find(p => p.name === name);
|
package/src/models/types.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Provider types
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
export type ProviderName = 'Anthropic' | 'OpenAI' | 'FireworksAI';
|
|
2
6
|
|
|
3
7
|
export interface ProviderConfig {
|
|
4
8
|
apiKey: string;
|
|
5
9
|
model: string;
|
|
6
|
-
maxTokens: number;
|
|
7
10
|
}
|
|
8
11
|
|
|
9
12
|
export interface ModelEntry {
|
|
@@ -21,3 +24,65 @@ export interface Provider {
|
|
|
21
24
|
chatModels: string[];
|
|
22
25
|
detectModel(model: string): boolean;
|
|
23
26
|
}
|
|
27
|
+
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// Messages
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
|
|
32
|
+
export interface Message {
|
|
33
|
+
role: string;
|
|
34
|
+
content: string;
|
|
35
|
+
name?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface SystemMessage extends Message {
|
|
39
|
+
role: 'system';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface UserMessage extends Message {
|
|
43
|
+
role: 'user';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
// Completions
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
|
|
50
|
+
export interface AgentCompletion<TValue> {
|
|
51
|
+
completed: boolean;
|
|
52
|
+
value?: TValue;
|
|
53
|
+
error?: Error;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface PromptCompletionArgs {
|
|
57
|
+
prompt: UserMessage;
|
|
58
|
+
system?: SystemMessage;
|
|
59
|
+
history?: Message[];
|
|
60
|
+
temperature?: number;
|
|
61
|
+
jsonMode?: boolean;
|
|
62
|
+
/** JSON schema for structured output. When provided, the model is asked to return JSON conforming to this schema. */
|
|
63
|
+
jsonSchema?: Record<string, unknown>;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export type completePrompt<TValue = string> = (args: PromptCompletionArgs) => Promise<AgentCompletion<TValue>>;
|
|
67
|
+
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
// Agent args
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
|
|
72
|
+
export interface AgentArgs {
|
|
73
|
+
completePrompt: completePrompt<any>;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
// Errors
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
|
|
80
|
+
export class RequestError extends Error {
|
|
81
|
+
readonly status: number;
|
|
82
|
+
|
|
83
|
+
constructor(message: string, status: number, name?: string) {
|
|
84
|
+
super(message);
|
|
85
|
+
this.status = status;
|
|
86
|
+
this.name = name ?? 'RequestError';
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert any value to a string suitable for template substitution.
|
|
3
|
+
* Replaces double quotes and line feeds with spaces.
|
|
4
|
+
*/
|
|
5
|
+
export function variableToString(variable: any): string {
|
|
6
|
+
if (variable === null || variable === undefined) {
|
|
7
|
+
return '';
|
|
8
|
+
}
|
|
9
|
+
if (typeof variable === 'string') {
|
|
10
|
+
return variable;
|
|
11
|
+
}
|
|
12
|
+
if (typeof variable === 'object') {
|
|
13
|
+
return JSON.stringify(variable);
|
|
14
|
+
}
|
|
15
|
+
return variable.toString();
|
|
16
|
+
}
|
package/src/scripts.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AgentCompletion, variableToString } from '
|
|
1
|
+
import { AgentCompletion, variableToString } from './models';
|
|
2
2
|
import { spawn } from 'child_process';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { loadFile, listFiles, checkIfExists } from './files';
|
|
@@ -122,7 +122,7 @@ function spawnProcess(command: string, args: string[]): Promise<ExecuteScriptRes
|
|
|
122
122
|
});
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
function composeArguments(template: string, variables: Record<string, any>): string {
|
|
125
|
+
export function composeArguments(template: string, variables: Record<string, any>): string {
|
|
126
126
|
return template.replace(/{{\s*([^}\s]+)\s*}}/g, (match, name) => {
|
|
127
127
|
// Convert the variable to a string and replace double quotes and line feeds with spaces
|
|
128
128
|
return variableToString(variables[name]);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {anthropic, completePrompt, logCompletePrompt, openai} from '
|
|
1
|
+
import { anthropic, completePrompt, fireworksai, logCompletePrompt, openai } from '../models';
|
|
2
2
|
import { getModelEntry, loadSettings } from '../settings';
|
|
3
3
|
import { PROVIDERS } from '../models';
|
|
4
4
|
|
|
@@ -22,6 +22,8 @@ export async function createCompletePrompt(pagesFolder: string, use: 'builder' |
|
|
|
22
22
|
const apiKey = entry.configuration.apiKey;
|
|
23
23
|
if (entry.provider === 'Anthropic') {
|
|
24
24
|
modelInstance = anthropic({apiKey, model});
|
|
25
|
+
} else if (entry.provider === 'FireworksAI') {
|
|
26
|
+
modelInstance = fireworksai({apiKey, model});
|
|
25
27
|
} else {
|
|
26
28
|
modelInstance = openai({apiKey, model});
|
|
27
29
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import OpenAI from "openai";
|
|
2
|
-
import { AgentCompletion, RequestError } from "
|
|
2
|
+
import { AgentCompletion, RequestError } from "../models";
|
|
3
3
|
import { loadFile } from "../files";
|
|
4
4
|
import path from "path";
|
|
5
5
|
|
|
@@ -81,7 +81,7 @@ export async function generateImage(args: OpenaiGenerateImageArgs): Promise<Agen
|
|
|
81
81
|
style
|
|
82
82
|
});
|
|
83
83
|
|
|
84
|
-
if (response.data.length > 0 && response.data[0].b64_json !== undefined) {
|
|
84
|
+
if (response.data && response.data.length > 0 && response.data[0].b64_json !== undefined) {
|
|
85
85
|
const url = `data:image/png;base64,${response.data[0].b64_json}`
|
|
86
86
|
return { completed: true, value: { url } };
|
|
87
87
|
} else {
|
package/src/service/server.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { useApiRoutes } from './useApiRoutes';
|
|
|
4
4
|
import { SynthOSConfig } from '../init';
|
|
5
5
|
import { useDataRoutes } from './useDataRoutes';
|
|
6
6
|
import { useConnectorRoutes } from './useConnectorRoutes';
|
|
7
|
+
import { useAgentRoutes } from './useAgentRoutes';
|
|
7
8
|
import { cyan, yellow, formatTime } from './debugLog';
|
|
8
9
|
|
|
9
10
|
export function server(config: SynthOSConfig): Application {
|
|
@@ -36,6 +37,9 @@ export function server(config: SynthOSConfig): Application {
|
|
|
36
37
|
// Connector routes
|
|
37
38
|
useConnectorRoutes(config, app);
|
|
38
39
|
|
|
40
|
+
// Agent routes
|
|
41
|
+
useAgentRoutes(config, app);
|
|
42
|
+
|
|
39
43
|
// Data routes
|
|
40
44
|
useDataRoutes(config, app);
|
|
41
45
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { AgentArgs, AgentCompletion, SystemMessage, UserMessage } from "
|
|
1
|
+
import { AgentArgs, AgentCompletion, SystemMessage, UserMessage } from "../models";
|
|
2
2
|
import { listScripts } from "../scripts";
|
|
3
3
|
import * as cheerio from "cheerio";
|
|
4
4
|
import { ThemeInfo } from "../themes";
|
|
5
5
|
import { CONNECTOR_REGISTRY, ConnectorsConfig, ConnectorOAuthConfig } from "../connectors";
|
|
6
|
+
import { AgentConfig } from "../agents";
|
|
6
7
|
|
|
7
8
|
// ---------------------------------------------------------------------------
|
|
8
9
|
// Types
|
|
@@ -12,7 +13,6 @@ export interface TransformPageArgs extends AgentArgs {
|
|
|
12
13
|
pagesFolder: string;
|
|
13
14
|
pageState: string;
|
|
14
15
|
message: string;
|
|
15
|
-
maxTokens: number;
|
|
16
16
|
instructions?: string;
|
|
17
17
|
/** Provider-specific formatting instructions injected into the prompt. */
|
|
18
18
|
modelInstructions?: string;
|
|
@@ -22,6 +22,8 @@ export interface TransformPageArgs extends AgentArgs {
|
|
|
22
22
|
mode?: 'unlocked' | 'locked';
|
|
23
23
|
/** User's configured connectors (from settings). */
|
|
24
24
|
configuredConnectors?: ConnectorsConfig;
|
|
25
|
+
/** User's configured A2A agents (from settings). */
|
|
26
|
+
configuredAgents?: AgentConfig[];
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
export type ChangeOp =
|
|
@@ -53,7 +55,7 @@ export interface TransformPageResult {
|
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
export async function transformPage(args: TransformPageArgs): Promise<AgentCompletion<TransformPageResult>> {
|
|
56
|
-
const { pagesFolder, pageState, message,
|
|
58
|
+
const { pagesFolder, pageState, message, completePrompt } = args;
|
|
57
59
|
|
|
58
60
|
// 1. Assign data-node-id to every element
|
|
59
61
|
const { html: annotatedHtml } = assignNodeIds(pageState);
|
|
@@ -71,7 +73,7 @@ export async function transformPage(args: TransformPageArgs): Promise<AgentCompl
|
|
|
71
73
|
const colorList = Object.entries(colors)
|
|
72
74
|
.map(([name, value]) => ` --${name}: ${value}`)
|
|
73
75
|
.join('\n');
|
|
74
|
-
themeBlock += `Mode: ${mode}\nCSS custom properties (use instead of hardcoded values):\n${colorList}\n\nShared shell classes (pre-styled by theme, do not redefine):\n .chat-panel — Left sidebar container (30% width)\n .chat-header — Chat panel title bar\n .chat-messages — Scrollable message container\n .chat-message — Individual message wrapper\n .link-group — Navigation links row (Save, Pages, Reset)\n .chat-input — Message text input\n .chat-submit — Send button\n .viewer-panel — Right content area (70% width)\n .loading-overlay — Full-screen loading overlay\n .spinner — Animated loading spinner\n\nPage title bars: To align with the chat header, apply these styles:\n min-height: var(--header-min-height);\n padding: var(--header-padding-vertical) var(--header-padding-horizontal);\n line-height: var(--header-line-height);\n display: flex; align-items: center; justify-content: center; box-sizing: border-box;\n\nFull-viewer mode: For games, animations, or full-screen content, add class "full-viewer" to the viewer-panel element to remove its padding.\n\nChat panel behaviours (auto-injected via page script — do NOT recreate in page code):\n The server injects page-v2.js after transformation. It provides:\n - Form submit handler: sets action to window.location.pathname, shows #loadingOverlay, disables inputs\n - Save/Reset link handlers (#saveLink, #resetLink)\n - Chat scroll to bottom (#chatMessages)\n - Chat toggle button (.chat-toggle) — created dynamically if not in markup\n - .chat-input-wrapper — wraps #chatInput with a brainstorm icon button\n - Brainstorm modal (#brainstormModal) — LLM-powered brainstorm UI, created dynamically\n - Focus management — keeps keyboard input directed to #chatInput\n\n Do NOT:\n - Create your own form submit handler, toggle button, or input wrapper\n - Modify or replace .chat-panel, .chat-header, .link-group, #chatForm, or .chat-toggle\n - INSERT new <script> blocks that duplicate existing ones — when fixing JavaScript, UPDATE or REPLACE the existing script's nodeId instead. Always give inline scripts a unique id attribute.\n - Set the form action attribute (page-v2.js sets it dynamically)\n - Include these CSS rules (in the theme): #loadingOverlay position, .chat-submit:disabled, .chat-input:disabled\n\n To add chat messages: use insert with parentId of #chatMessages and position "append".\n #chatMessages is the only unlocked element inside .chat-panel.\n\nThe <html> element has class "${mode}-mode". Always add .light-mode CSS overrides for any page-specific styles so the page works in both light and dark themes, unless the user has explicitly requested a very specific color scheme.`;
|
|
76
|
+
themeBlock += `Mode: ${mode}\nCSS custom properties (use instead of hardcoded values):\n${colorList}\n\nShared shell classes (pre-styled by theme, do not redefine):\n .chat-panel — Left sidebar container (30% width)\n .chat-header — Chat panel title bar\n .chat-messages — Scrollable message container\n .chat-message — Individual message wrapper\n .link-group — Navigation links row (Save, Pages, Reset)\n .chat-input — Message text input\n .chat-submit — Send button\n .viewer-panel — Right content area (70% width)\n .loading-overlay — Full-screen loading overlay\n .spinner — Animated loading spinner\n .modal-overlay — Full-screen modal backdrop (position:fixed, z-index:2000, backdrop-filter:blur). Add class "show" to display.\n .modal-content — Centered modal container\n .modal-header — Gradient header bar\n .modal-body — Modal content area\n .modal-footer — Bottom action bar (flex, space-between)\n .modal-footer-right — Right-aligned button group\n\nModals and popups: ALWAYS use the theme\'s .modal-overlay class for any modal or popup overlay. Do NOT create custom overlay classes with position:fixed and z-index. Structure:\n <div class="modal-overlay" id="myModal">\n <div class="modal-content">\n <div class="modal-header">Title</div>\n <div class="modal-body">Content</div>\n <div class="modal-footer"><div class="modal-footer-right"><button>OK</button></div></div>\n </div>\n </div>\nShow/hide by toggling the "show" class: el.classList.add(\'show\') / el.classList.remove(\'show\'). This ensures correct z-index layering above the chat toggle and other UI elements.\n\nPage title bars: To align with the chat header, apply these styles:\n min-height: var(--header-min-height);\n padding: var(--header-padding-vertical) var(--header-padding-horizontal);\n line-height: var(--header-line-height);\n display: flex; align-items: center; justify-content: center; box-sizing: border-box;\n\nFull-viewer mode: For games, animations, or full-screen content, add class "full-viewer" to the viewer-panel element to remove its padding.\n\nChat panel behaviours (auto-injected via page script — do NOT recreate in page code):\n The server injects page-v2.js after transformation. It provides:\n - Form submit handler: sets action to window.location.pathname, shows #loadingOverlay, disables inputs\n - Save/Reset link handlers (#saveLink, #resetLink)\n - Chat scroll to bottom (#chatMessages)\n - Chat toggle button (.chat-toggle) — created dynamically if not in markup\n - .chat-input-wrapper — wraps #chatInput with a brainstorm icon button\n - Brainstorm modal (#brainstormModal) — LLM-powered brainstorm UI, created dynamically\n - Focus management — keeps keyboard input directed to #chatInput\n\n Do NOT:\n - Create your own form submit handler, toggle button, or input wrapper\n - Modify or replace .chat-panel, .chat-header, .link-group, #chatForm, or .chat-toggle\n - INSERT new <script> blocks that duplicate existing ones — when fixing JavaScript, UPDATE or REPLACE the existing script's nodeId instead. Always give inline scripts a unique id attribute.\n - Set the form action attribute (page-v2.js sets it dynamically)\n - Include these CSS rules (in the theme): #loadingOverlay position, .chat-submit:disabled, .chat-input:disabled\n\n To add chat messages: use insert with parentId of #chatMessages and position "append".\n #chatMessages is the only unlocked element inside .chat-panel.\n\nThe <html> element has class "${mode}-mode". Always add .light-mode CSS overrides for any page-specific styles so the page works in both light and dark themes, unless the user has explicitly requested a very specific color scheme.`;
|
|
75
77
|
}
|
|
76
78
|
|
|
77
79
|
// Build configured-connectors block
|
|
@@ -103,7 +105,26 @@ export async function transformPage(args: TransformPageArgs): Promise<AgentCompl
|
|
|
103
105
|
}
|
|
104
106
|
}
|
|
105
107
|
|
|
106
|
-
|
|
108
|
+
// Build configured-agents block (only enabled agents)
|
|
109
|
+
let agentsBlock = '';
|
|
110
|
+
const enabledAgents = (args.configuredAgents ?? []).filter(a => a.enabled);
|
|
111
|
+
if (enabledAgents.length > 0) {
|
|
112
|
+
const agentBlocks = enabledAgents.map(a => {
|
|
113
|
+
let block = `- ${a.name} (id: "${a.id}", provider: ${a.provider})`;
|
|
114
|
+
block += `\n Description: ${a.description}`;
|
|
115
|
+
if (a.capabilities?.streaming) {
|
|
116
|
+
block += `\n Supports streaming: yes`;
|
|
117
|
+
}
|
|
118
|
+
if (a.skills && a.skills.length > 0) {
|
|
119
|
+
const skillList = a.skills.map(s => ` - ${s.name}: ${s.description}`).join('\n');
|
|
120
|
+
block += `\n Skills:\n${skillList}`;
|
|
121
|
+
}
|
|
122
|
+
return block;
|
|
123
|
+
});
|
|
124
|
+
agentsBlock = `<CONFIGURED_AGENTS>\nThe user has configured these agents:\n\n${agentBlocks.join('\n\n')}\n\n${AGENT_API_REFERENCE}`;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const systemMessage = [currentPage, serverAPIs, serverScripts, connectorsBlock, agentsBlock, themeBlock, messageFormat].filter(s => s).join('\n\n');
|
|
107
128
|
const system: SystemMessage = {
|
|
108
129
|
role: 'system',
|
|
109
130
|
content: systemMessage
|
|
@@ -118,7 +139,7 @@ export async function transformPage(args: TransformPageArgs): Promise<AgentCompl
|
|
|
118
139
|
};
|
|
119
140
|
|
|
120
141
|
// 3. Call model
|
|
121
|
-
const result = await completePrompt({ prompt, system
|
|
142
|
+
const result = await completePrompt({ prompt, system });
|
|
122
143
|
if (!result.completed) {
|
|
123
144
|
return { completed: false, error: result.error };
|
|
124
145
|
}
|
|
@@ -153,8 +174,7 @@ export async function transformPage(args: TransformPageArgs): Promise<AgentCompl
|
|
|
153
174
|
content: repairUSER_MESSAGE
|
|
154
175
|
};
|
|
155
176
|
|
|
156
|
-
const
|
|
157
|
-
const repairResult = await completePrompt({ prompt: repairPrompt, system: repairSystem, maxTokens: repairMaxTokens });
|
|
177
|
+
const repairResult = await completePrompt({ prompt: repairPrompt, system: repairSystem });
|
|
158
178
|
|
|
159
179
|
if (repairResult.completed) {
|
|
160
180
|
const repairChanges = parseChangeList(repairResult.value);
|
|
@@ -650,6 +670,40 @@ Return ONLY the JSON array. Example:
|
|
|
650
670
|
{ "op": "insert", "parentId": "3", "position": "append", "html": "<div class=\\"msg\\">New message</div>" }
|
|
651
671
|
]`;
|
|
652
672
|
|
|
673
|
+
const AGENT_API_REFERENCE =
|
|
674
|
+
`## Agent API
|
|
675
|
+
|
|
676
|
+
Check availability first (required):
|
|
677
|
+
const agents = await synthos.agents.list({ enabled: true });
|
|
678
|
+
|
|
679
|
+
Send a message (returns full response):
|
|
680
|
+
const result = await synthos.agents.send(agentId, message);
|
|
681
|
+
// result: { kind: 'message', text: 'response text', raw: {...} }
|
|
682
|
+
|
|
683
|
+
Send with file/image attachments:
|
|
684
|
+
const result = await synthos.agents.send(agentId, message, [
|
|
685
|
+
{ fileName: 'photo.jpg', mimeType: 'image/jpeg', content: '<base64-string>' }
|
|
686
|
+
]);
|
|
687
|
+
|
|
688
|
+
Stream a response (token-by-token deltas):
|
|
689
|
+
const handle = synthos.agents.sendStream(agentId, message, function(event) {
|
|
690
|
+
switch (event.kind) {
|
|
691
|
+
case 'text': // event.data = text delta string — append to output
|
|
692
|
+
case 'status': // event.data = status info object
|
|
693
|
+
case 'done': // stream complete — stop processing
|
|
694
|
+
case 'error': // event.data = error message string
|
|
695
|
+
}
|
|
696
|
+
});
|
|
697
|
+
handle.close(); // call to abort the stream early
|
|
698
|
+
|
|
699
|
+
Stream with attachments:
|
|
700
|
+
synthos.agents.sendStream(agentId, message, onEvent, [
|
|
701
|
+
{ fileName: 'doc.pdf', mimeType: 'application/pdf', content: '<base64>' }
|
|
702
|
+
]);
|
|
703
|
+
|
|
704
|
+
IMPORTANT: Always check synthos.agents.list({ enabled: true }) before calling an agent.
|
|
705
|
+
If no agents are configured, show the user a link to Settings > Agents (/settings?tab=agents).`;
|
|
706
|
+
|
|
653
707
|
const serverAPIs =
|
|
654
708
|
`<SERVER_APIS>
|
|
655
709
|
GET /api/data/:page/:table
|
|
@@ -708,6 +762,20 @@ description: Search the web using Brave Search (must be enabled in Settings > Co
|
|
|
708
762
|
request: { query: string, count?: number, country?: string, freshness?: string }
|
|
709
763
|
response: { results: [{ title: string, url: string, description: string }] }
|
|
710
764
|
|
|
765
|
+
GET /api/agents
|
|
766
|
+
description: List configured agents (A2A and OpenClaw). Supports ?enabled=true and ?provider=a2a|openclaw filters.
|
|
767
|
+
response: [{ id: string, name: string, description: string, url: string, enabled: boolean, provider: 'a2a'|'openclaw', capabilities?: object }]
|
|
768
|
+
|
|
769
|
+
POST /api/agents/:id/send
|
|
770
|
+
description: Send a text message to an agent (works for both A2A and OpenClaw protocols) and receive a normalized response
|
|
771
|
+
request: { message: string, attachments?: [{ fileName: string, mimeType: string, content: string }] }
|
|
772
|
+
response: { kind: 'message'|'task', text?: string, raw: object }
|
|
773
|
+
|
|
774
|
+
POST /api/agents/:id/stream
|
|
775
|
+
description: Send a message and receive a streaming SSE response (text/event-stream). Each event is JSON: { kind: 'text'|'status'|'artifact'|'done'|'error', data: any }
|
|
776
|
+
request: { message: string, attachments?: [{ fileName: string, mimeType: string, content: string }] }
|
|
777
|
+
response: SSE stream
|
|
778
|
+
|
|
711
779
|
GET /api/connectors
|
|
712
780
|
description: List available connectors (REST API proxies). Supports ?category=X and ?id=X filters.
|
|
713
781
|
response: [{ id: string, name: string, category: string, configured: boolean }]
|
|
@@ -736,6 +804,11 @@ PAGE HELPERS (available globally as window.synthos):
|
|
|
736
804
|
synthos.search.web(query, opts?) — POST /api/search/web (opts: { count?, country?, freshness? })
|
|
737
805
|
synthos.connectors.call(connector, method, path, opts?) — POST /api/connectors (proxy call; opts: { headers?, body?, query? })
|
|
738
806
|
synthos.connectors.list(opts?) — GET /api/connectors (opts: { category?, id? })
|
|
807
|
+
synthos.agents.list(opts?) — GET /api/agents (returns configured agents; opts: { enabled?, provider? }; returns [{ id, name, description, url, enabled, provider, capabilities }])
|
|
808
|
+
synthos.agents.send(agentId, message, attachments?) — POST /api/agents/:id/send (sends a text message to any agent, returns normalized { kind, text, raw }; attachments: [{ fileName, mimeType, content }])
|
|
809
|
+
synthos.agents.sendStream(agentId, message, onEvent, attachments?) — POST /api/agents/:id/stream (SSE streaming; onEvent receives { kind, data }; returns { close() } handle; attachments: [{ fileName, mimeType, content }])
|
|
810
|
+
synthos.agents.isEnabled(agentId) — checks if an agent is enabled (returns Promise<boolean>)
|
|
811
|
+
synthos.agents.getCapabilities(agentId) — returns agent capabilities object (streaming, skills, etc.)
|
|
739
812
|
All methods return Promises. Prefer these helpers over raw fetch().`;
|
|
740
813
|
|
|
741
814
|
const repairUSER_MESSAGE =
|