synthos 0.8.0 → 0.9.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 +1 -1
- package/default-pages/application/page.html +42 -0
- package/default-pages/application/page.json +10 -0
- package/default-pages/elevenlabs_effects_studio/page.html +1363 -0
- package/default-pages/elevenlabs_effects_studio/page.json +11 -0
- package/default-pages/elevenlabs_voice_studio/page.html +801 -0
- package/default-pages/elevenlabs_voice_studio/page.json +11 -0
- package/default-pages/{json_tools.html → json_tools/page.html} +13 -11
- package/default-pages/json_tools/page.json +10 -0
- package/default-pages/my_notes/notes/a1b2c3d4-e5f6-7890-abcd-ef1234567890.json +5 -0
- package/default-pages/my_notes/page.html +132 -0
- package/default-pages/{my_notes.json → my_notes/page.json} +2 -2
- package/default-pages/neon_asteroids/files/Ambient_Space.mp3 +0 -0
- package/default-pages/neon_asteroids/files/Ambient_Space2.mp3 +0 -0
- package/default-pages/neon_asteroids/files/Ambient_Space3.mp3 +0 -0
- package/default-pages/neon_asteroids/files/Asteroid_Explosion.mp3 +0 -0
- package/default-pages/neon_asteroids/files/Hyperspace_Jump.mp3 +0 -0
- package/default-pages/neon_asteroids/files/Laser_Fire.mp3 +0 -0
- package/default-pages/neon_asteroids/files/Menu_Navigate.mp3 +0 -0
- package/default-pages/neon_asteroids/files/Power_Up_Collect.mp3 +0 -0
- package/default-pages/neon_asteroids/files/Saucer_Alert.mp3 +0 -0
- package/default-pages/neon_asteroids/files/Ship_Thrust.mp3 +0 -0
- package/default-pages/neon_asteroids/files/effects.json +74 -0
- package/default-pages/neon_asteroids/page.html +1822 -0
- package/default-pages/{neon_asteroids.json → neon_asteroids/page.json} +3 -3
- package/default-pages/{oregon_trail.html → oregon_trail/page.html} +14 -12
- package/default-pages/{oregon_trail.json → oregon_trail/page.json} +2 -2
- package/default-pages/retro_game_starter/page.html +1308 -0
- package/default-pages/retro_game_starter/page.json +12 -0
- package/default-pages/{sidebar_page.html → sidebar_page/page.html} +12 -10
- package/default-pages/sidebar_page/page.json +10 -0
- package/default-pages/{solar_explorer.html → solar_explorer/page.html} +14 -11
- package/default-pages/{solar_explorer.json → solar_explorer/page.json} +2 -2
- package/default-pages/{solar_tutorial.html → solar_tutorial/page.html} +12 -10
- package/default-pages/solar_tutorial/page.json +10 -0
- package/default-pages/{two-panel_page.html → two-panel_page/page.html} +13 -11
- package/default-pages/two-panel_page/page.json +10 -0
- package/default-pages/{us_map.html → us_map/page.html} +193 -192
- package/default-pages/{us_map.json → us_map/page.json} +12 -12
- package/default-pages/{us_map_1850.html → us_map_1850/page.html} +326 -325
- package/default-pages/{us_map_1850.json → us_map_1850/page.json} +12 -12
- package/default-pages/{western_cities_1850.html → western_cities_1850/page.html} +527 -526
- package/default-pages/{western_cities_1850.json → western_cities_1850/page.json} +12 -12
- package/default-themes/aurora-dawn.json +19 -0
- package/default-themes/aurora-dawn.v3.css +198 -0
- package/default-themes/aurora-dusk.json +19 -0
- package/default-themes/aurora-dusk.v3.css +200 -0
- package/default-themes/cosmos-dawn.json +19 -0
- package/default-themes/cosmos-dawn.v3.css +198 -0
- package/default-themes/cosmos-dusk.json +19 -0
- package/default-themes/cosmos-dusk.v3.css +200 -0
- package/default-themes/high-contrast-dark.json +19 -0
- package/default-themes/high-contrast-dark.v3.css +200 -0
- package/default-themes/high-contrast-light.json +19 -0
- package/default-themes/high-contrast-light.v3.css +198 -0
- package/default-themes/nebula-dawn.v2.css +110 -0
- package/default-themes/nebula-dawn.v3.css +199 -0
- package/default-themes/nebula-dusk.v2.css +104 -0
- package/default-themes/nebula-dusk.v3.css +201 -0
- package/default-themes/solar-flare-dawn.json +19 -0
- package/default-themes/solar-flare-dawn.v3.css +198 -0
- package/default-themes/solar-flare-dusk.json +19 -0
- package/default-themes/solar-flare-dusk.v3.css +200 -0
- package/dist/agents/index.d.ts +1 -1
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +2 -1
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/openclaw/gatewayManager.d.ts +4 -0
- package/dist/agents/openclaw/gatewayManager.d.ts.map +1 -1
- package/dist/agents/openclaw/gatewayManager.js +27 -11
- package/dist/agents/openclaw/gatewayManager.js.map +1 -1
- package/dist/agents/openclaw/openclawProvider.d.ts.map +1 -1
- package/dist/agents/openclaw/openclawProvider.js +2 -4
- package/dist/agents/openclaw/openclawProvider.js.map +1 -1
- package/dist/agents/openclaw/sshTunnelManager.d.ts +2 -0
- package/dist/agents/openclaw/sshTunnelManager.d.ts.map +1 -1
- package/dist/agents/openclaw/sshTunnelManager.js +31 -12
- package/dist/agents/openclaw/sshTunnelManager.js.map +1 -1
- package/dist/builders/anthropic.d.ts +31 -0
- package/dist/builders/anthropic.d.ts.map +1 -0
- package/dist/builders/anthropic.js +227 -0
- package/dist/builders/anthropic.js.map +1 -0
- package/dist/builders/fireworksai.d.ts +9 -0
- package/dist/builders/fireworksai.d.ts.map +1 -0
- package/dist/builders/fireworksai.js +57 -0
- package/dist/builders/fireworksai.js.map +1 -0
- package/dist/builders/index.d.ts +13 -0
- package/dist/builders/index.d.ts.map +1 -0
- package/dist/builders/index.js +31 -0
- package/dist/builders/index.js.map +1 -0
- package/dist/builders/openai.d.ts +8 -0
- package/dist/builders/openai.d.ts.map +1 -0
- package/dist/builders/openai.js +87 -0
- package/dist/builders/openai.js.map +1 -0
- package/dist/builders/types.d.ts +54 -0
- package/dist/builders/types.d.ts.map +1 -0
- package/dist/builders/types.js +211 -0
- package/dist/builders/types.js.map +1 -0
- package/dist/connectors/index.d.ts.map +1 -1
- package/dist/connectors/index.js +3 -2
- package/dist/connectors/index.js.map +1 -1
- package/dist/connectors/registry.d.ts +2 -1
- package/dist/connectors/registry.d.ts.map +1 -1
- package/dist/connectors/registry.js +31 -8
- package/dist/connectors/registry.js.map +1 -1
- package/dist/customizer/Customizer.d.ts +57 -0
- package/dist/customizer/Customizer.d.ts.map +1 -0
- package/dist/customizer/Customizer.js +124 -0
- package/dist/customizer/Customizer.js.map +1 -0
- package/dist/customizer/index.d.ts.map +1 -0
- package/dist/customizer/index.js +9 -0
- package/dist/customizer/index.js.map +1 -0
- package/dist/files.d.ts +16 -0
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +60 -1
- package/dist/files.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +10 -6
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +96 -113
- package/dist/init.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +23 -10
- package/dist/migrations.js.map +1 -1
- package/dist/models/anthropic.d.ts +4 -2
- package/dist/models/anthropic.d.ts.map +1 -1
- package/dist/models/anthropic.js +33 -6
- package/dist/models/anthropic.js.map +1 -1
- package/dist/models/fireworksai.d.ts.map +1 -1
- package/dist/models/fireworksai.js +9 -1
- package/dist/models/fireworksai.js.map +1 -1
- package/dist/models/index.d.ts +1 -1
- package/dist/models/index.d.ts.map +1 -1
- package/dist/models/index.js +2 -1
- package/dist/models/index.js.map +1 -1
- package/dist/models/openai.d.ts +1 -1
- package/dist/models/openai.d.ts.map +1 -1
- package/dist/models/openai.js +24 -3
- package/dist/models/openai.js.map +1 -1
- package/dist/models/types.d.ts +20 -1
- package/dist/models/types.d.ts.map +1 -1
- package/dist/models/types.js +6 -1
- package/dist/models/types.js.map +1 -1
- package/dist/pages.d.ts +30 -7
- package/dist/pages.d.ts.map +1 -1
- package/dist/pages.js +177 -55
- package/dist/pages.js.map +1 -1
- package/dist/service/server.d.ts.map +1 -1
- package/dist/service/server.js +37 -8
- package/dist/service/server.js.map +1 -1
- package/dist/service/transformPage.d.ts +47 -20
- package/dist/service/transformPage.d.ts.map +1 -1
- package/dist/service/transformPage.js +514 -293
- package/dist/service/transformPage.js.map +1 -1
- package/dist/service/useAgentRoutes.d.ts +2 -1
- package/dist/service/useAgentRoutes.d.ts.map +1 -1
- package/dist/service/useAgentRoutes.js +5 -2
- package/dist/service/useAgentRoutes.js.map +1 -1
- package/dist/service/useApiRoutes.d.ts.map +1 -1
- package/dist/service/useApiRoutes.js +237 -136
- package/dist/service/useApiRoutes.js.map +1 -1
- package/dist/service/useConnectorRoutes.js +6 -6
- package/dist/service/useConnectorRoutes.js.map +1 -1
- package/dist/service/useFileRoutes.d.ts +4 -0
- package/dist/service/useFileRoutes.d.ts.map +1 -0
- package/dist/service/useFileRoutes.js +122 -0
- package/dist/service/useFileRoutes.js.map +1 -0
- package/dist/service/usePageRoutes.d.ts.map +1 -1
- package/dist/service/usePageRoutes.js +648 -67
- package/dist/service/usePageRoutes.js.map +1 -1
- package/dist/service/useSharedDataRoutes.d.ts +4 -0
- package/dist/service/useSharedDataRoutes.d.ts.map +1 -0
- package/dist/service/useSharedDataRoutes.js +104 -0
- package/dist/service/useSharedDataRoutes.js.map +1 -0
- package/dist/service/useSharedFileRoutes.d.ts +4 -0
- package/dist/service/useSharedFileRoutes.d.ts.map +1 -0
- package/dist/service/useSharedFileRoutes.js +121 -0
- package/dist/service/useSharedFileRoutes.js.map +1 -0
- package/dist/settings.d.ts +1 -0
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +1 -0
- package/dist/settings.js.map +1 -1
- package/dist/synthos-cli.d.ts.map +1 -1
- package/dist/synthos-cli.js +4 -3
- package/dist/synthos-cli.js.map +1 -1
- package/dist/themes.d.ts +1 -0
- package/dist/themes.d.ts.map +1 -1
- package/dist/themes.js +28 -15
- package/dist/themes.js.map +1 -1
- package/migration-rules/v1-to-v2.md +193 -0
- package/migration-rules/v2-to-v3.md +481 -0
- package/package.json +11 -10
- package/required-pages/builder/page.html +43 -0
- package/required-pages/builder/page.json +10 -0
- package/required-pages/{pages.html → pages/page.html} +238 -233
- package/required-pages/pages/page.json +10 -0
- package/required-pages/{settings.html → settings/page.html} +389 -275
- package/required-pages/settings/page.json +10 -0
- package/required-pages/synthos_apis/page.html +846 -0
- package/required-pages/synthos_apis/page.json +10 -0
- package/required-pages/{synthos_scripts.html → synthos_scripts/page.html} +13 -11
- package/required-pages/synthos_scripts/page.json +10 -0
- package/src/agents/index.ts +1 -1
- package/src/agents/openclaw/gatewayManager.ts +22 -11
- package/src/agents/openclaw/openclawProvider.ts +2 -4
- package/src/agents/openclaw/sshTunnelManager.ts +19 -11
- package/src/builders/anthropic.ts +283 -0
- package/src/builders/fireworksai.ts +59 -0
- package/src/builders/index.ts +33 -0
- package/src/builders/openai.ts +89 -0
- package/src/builders/types.ts +261 -0
- package/src/connectors/index.ts +1 -1
- package/src/connectors/registry.ts +28 -8
- package/src/customizer/Customizer.ts +151 -0
- package/src/customizer/index.ts +5 -0
- package/src/files.ts +57 -0
- package/src/index.ts +2 -1
- package/src/init.ts +137 -123
- package/src/migrations.ts +30 -10
- package/src/models/anthropic.ts +40 -10
- package/src/models/fireworksai.ts +9 -2
- package/src/models/index.ts +1 -1
- package/src/models/openai.ts +26 -6
- package/src/models/types.ts +31 -1
- package/src/pages.ts +176 -54
- package/src/service/server.ts +36 -9
- package/src/service/transformPage.ts +557 -326
- package/src/service/useAgentRoutes.ts +7 -2
- package/src/service/useApiRoutes.ts +150 -41
- package/src/service/useConnectorRoutes.ts +7 -7
- package/src/service/useFileRoutes.ts +127 -0
- package/src/service/usePageRoutes.ts +720 -73
- package/src/service/useSharedDataRoutes.ts +106 -0
- package/src/service/useSharedFileRoutes.ts +126 -0
- package/src/settings.ts +2 -0
- package/src/synthos-cli.ts +4 -3
- package/src/themes.ts +25 -14
- package/static-files/favicon.svg +12 -0
- package/static-files/fluentlm-instructions.llmd +868 -0
- package/static-files/fluentlm-instructions.md +1595 -0
- package/static-files/fluentlm.css +4844 -0
- package/static-files/fluentlm.js +3602 -0
- package/static-files/fluentlm.min.css +1 -0
- package/static-files/fluentlm.min.js +1 -0
- package/{page-scripts/helpers-v2.js → static-files/helpers.v3.js} +82 -0
- package/static-files/page.v3.js +1290 -0
- package/static-files/recommended-frameworks.llmd +81 -0
- package/static-files/recommended-frameworks.md +137 -0
- package/static-files/retro-game.js +877 -0
- package/static-files/shell.css +797 -0
- package/static-files/theme-dark.css +169 -0
- package/static-files/theme-light.css +169 -0
- package/tests/builders.spec.ts +139 -0
- package/tests/pages.spec.ts +8 -8
- package/tests/transformPage.spec.ts +299 -360
- package/default-pages/application.html +0 -40
- package/default-pages/application.json +0 -1
- package/default-pages/json_tools.json +0 -1
- package/default-pages/my_notes.html +0 -33
- package/default-pages/neon_asteroids.html +0 -77
- package/default-pages/sidebar_page.json +0 -1
- package/default-pages/solar_tutorial.json +0 -1
- package/default-pages/two-panel_page.json +0 -1
- package/dist/agents/a2a/a2aProvider.d.ts +0 -3
- package/dist/agents/discovery.d.ts +0 -30
- package/dist/agents/openclaw/openclawProvider.d.ts +0 -3
- package/dist/agents/types.d.ts +0 -64
- package/dist/connectors/index.d.ts +0 -3
- package/dist/connectors/types.d.ts +0 -84
- package/dist/index.d.ts +0 -7
- package/dist/migrations.d.ts +0 -12
- package/dist/models/chainOfThought.d.ts +0 -12
- package/dist/models/fireworksai.d.ts +0 -30
- package/dist/models/logCompletePrompt.d.ts +0 -3
- package/dist/models/providers.d.ts +0 -8
- package/dist/models/utils.d.ts +0 -6
- package/dist/scripts.d.ts +0 -15
- package/dist/service/createCompletePrompt.d.ts +0 -5
- package/dist/service/debugLog.d.ts +0 -11
- package/dist/service/generateImage.d.ts +0 -32
- package/dist/service/index.d.ts +0 -8
- package/dist/service/modelInstructions.d.ts +0 -7
- package/dist/service/requiresSettings.d.ts +0 -3
- package/dist/service/server.d.ts +0 -4
- package/dist/service/useApiRoutes.d.ts +0 -4
- package/dist/service/useConnectorRoutes.d.ts +0 -4
- package/dist/service/useDataRoutes.d.ts +0 -4
- package/dist/service/useGatewayRoutes.d.ts +0 -4
- package/dist/service/useGatewayRoutes.d.ts.map +0 -1
- package/dist/service/useGatewayRoutes.js +0 -168
- package/dist/service/useGatewayRoutes.js.map +0 -1
- package/dist/service/usePageRoutes.d.ts +0 -5
- package/dist/synthos-cli.d.ts +0 -2
- package/page-scripts/page-v2.js +0 -656
- package/required-pages/builder.html +0 -48
- package/required-pages/builder.json +0 -1
- package/required-pages/pages.json +0 -1
- package/required-pages/settings.json +0 -1
- package/required-pages/synthos_apis.html +0 -327
- package/required-pages/synthos_apis.json +0 -1
- package/required-pages/synthos_scripts.json +0 -1
- package/src/connectors/airtable/connector.json +0 -27
- package/src/connectors/alpha-vantage/connector.json +0 -26
- package/src/connectors/brave-search/connector.json +0 -26
- package/src/connectors/cloudinary/connector.json +0 -27
- package/src/connectors/deepl/connector.json +0 -28
- package/src/connectors/elevenlabs/connector.json +0 -30
- package/src/connectors/giphy/connector.json +0 -27
- package/src/connectors/github/connector.json +0 -29
- package/src/connectors/huggingface/connector.json +0 -27
- package/src/connectors/imgur/connector.json +0 -29
- package/src/connectors/instagram/connector.json +0 -43
- package/src/connectors/jira/connector.json +0 -28
- package/src/connectors/mapbox/connector.json +0 -26
- package/src/connectors/nasa/connector.json +0 -27
- package/src/connectors/newsapi/connector.json +0 -27
- package/src/connectors/notion/connector.json +0 -28
- package/src/connectors/open-exchange-rates/connector.json +0 -27
- package/src/connectors/openweathermap/connector.json +0 -26
- package/src/connectors/pexels/connector.json +0 -27
- package/src/connectors/resend/connector.json +0 -29
- package/src/connectors/rss2json/connector.json +0 -27
- package/src/connectors/sendgrid/connector.json +0 -27
- package/src/connectors/spoonacular/connector.json +0 -28
- package/src/connectors/stability-ai/connector.json +0 -27
- package/src/connectors/twilio/connector.json +0 -28
- package/src/connectors/unsplash/connector.json +0 -27
- package/src/connectors/wolfram-alpha/connector.json +0 -26
- package/src/connectors/youtube-data/connector.json +0 -30
- /package/{dist/connectors → service-connectors}/airtable/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/alpha-vantage/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/brave-search/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/cloudinary/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/deepl/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/elevenlabs/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/giphy/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/github/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/huggingface/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/imgur/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/instagram/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/jira/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/mapbox/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/nasa/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/newsapi/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/notion/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/open-exchange-rates/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/openweathermap/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/pexels/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/resend/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/rss2json/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/sendgrid/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/spoonacular/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/stability-ai/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/twilio/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/unsplash/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/wolfram-alpha/connector.json +0 -0
- /package/{dist/connectors → service-connectors}/youtube-data/connector.json +0 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { Application, Response } from 'express';
|
|
2
|
+
import { SynthOSConfig } from "../init";
|
|
3
|
+
import { checkIfExists, deleteFile, ensureFolderExists, listFiles, loadFile, saveFile } from "../files";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import { v4 } from "uuid";
|
|
6
|
+
|
|
7
|
+
export function useSharedDataRoutes(config: SynthOSConfig, app: Application): void {
|
|
8
|
+
app.get('/api/shared/data/:table', (req, res) => handleList(config, req.params.table, req.query, res));
|
|
9
|
+
app.get('/api/shared/data/:table/:id', (req, res) => handleGet(config, req.params.table, req.params.id, res));
|
|
10
|
+
app.post('/api/shared/data/:table', (req, res) => handleUpsert(config, req.params.table, req.body, res));
|
|
11
|
+
app.delete('/api/shared/data/:table/:id', (req, res) => handleDelete(config, req.params.table, req.params.id, res));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Route handlers
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
async function handleList(config: SynthOSConfig, table: string, query: Record<string, any>, res: Response): Promise<void> {
|
|
19
|
+
const folder = sharedTableFolder(config, table);
|
|
20
|
+
if (!(await checkIfExists(folder))) {
|
|
21
|
+
res.status(404).json({ error: 'table_not_found', table });
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const ids = (await listFiles(folder)).filter(f => f.endsWith('.json')).map(f => f.replace('.json', ''));
|
|
26
|
+
|
|
27
|
+
const rows: Record<string, any>[] = [];
|
|
28
|
+
for (const id of ids) {
|
|
29
|
+
const file = recordFile(folder, id);
|
|
30
|
+
try {
|
|
31
|
+
const row = JSON.parse(await loadFile(file));
|
|
32
|
+
row.id = id;
|
|
33
|
+
rows.push(row);
|
|
34
|
+
} catch (err: unknown) {
|
|
35
|
+
console.error(err);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Paginate when limit is provided
|
|
40
|
+
const limitParam = typeof query.limit === 'string' ? parseInt(query.limit, 10) : NaN;
|
|
41
|
+
if (!isNaN(limitParam) && limitParam > 0) {
|
|
42
|
+
const offset = Math.max(0, typeof query.offset === 'string' ? parseInt(query.offset, 10) || 0 : 0);
|
|
43
|
+
const items = rows.slice(offset, offset + limitParam);
|
|
44
|
+
res.json({ items, total: rows.length, offset, limit: limitParam, hasMore: offset + limitParam < rows.length });
|
|
45
|
+
} else {
|
|
46
|
+
res.json(rows);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function handleGet(config: SynthOSConfig, table: string, id: string, res: Response): Promise<void> {
|
|
51
|
+
const folder = sharedTableFolder(config, table);
|
|
52
|
+
if (!(await checkIfExists(folder))) {
|
|
53
|
+
res.status(404).json({ error: 'table_not_found', table });
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const file = recordFile(folder, id);
|
|
58
|
+
try {
|
|
59
|
+
const row = JSON.parse(await loadFile(file));
|
|
60
|
+
row.id = id;
|
|
61
|
+
res.json(row);
|
|
62
|
+
} catch (err: unknown) {
|
|
63
|
+
res.json({});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function handleUpsert(config: SynthOSConfig, table: string, body: any, res: Response): Promise<void> {
|
|
68
|
+
const id = body.id ?? v4();
|
|
69
|
+
const folder = sharedTableFolder(config, table);
|
|
70
|
+
const file = recordFile(folder, id);
|
|
71
|
+
try {
|
|
72
|
+
const row = { ...body, id };
|
|
73
|
+
await ensureFolderExists(folder);
|
|
74
|
+
await saveFile(file, JSON.stringify(row, null, 4));
|
|
75
|
+
res.json(row);
|
|
76
|
+
} catch (err: unknown) {
|
|
77
|
+
console.error(err);
|
|
78
|
+
res.status(500).send((err as Error).message);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function handleDelete(config: SynthOSConfig, table: string, id: string, res: Response): Promise<void> {
|
|
83
|
+
const folder = sharedTableFolder(config, table);
|
|
84
|
+
const file = recordFile(folder, id);
|
|
85
|
+
try {
|
|
86
|
+
if (await checkIfExists(file)) {
|
|
87
|
+
await deleteFile(file);
|
|
88
|
+
}
|
|
89
|
+
res.json({ success: true });
|
|
90
|
+
} catch (err: unknown) {
|
|
91
|
+
console.error(err);
|
|
92
|
+
res.status(500).send((err as Error).message);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
// Helpers
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
|
|
100
|
+
function sharedTableFolder(config: SynthOSConfig, table: string): string {
|
|
101
|
+
return path.join(config.pagesFolder, 'shared', table);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function recordFile(folder: string, id: string): string {
|
|
105
|
+
return path.join(folder, `${id}.json`);
|
|
106
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { Application } from 'express';
|
|
2
|
+
import express from 'express';
|
|
3
|
+
import fs from 'fs/promises';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { SynthOSConfig } from '../init';
|
|
6
|
+
import { checkIfExists, ensureFolderExists } from '../files';
|
|
7
|
+
|
|
8
|
+
export function useSharedFileRoutes(config: SynthOSConfig, app: Application): void {
|
|
9
|
+
// List files in the shared files folder
|
|
10
|
+
app.get('/api/shared/files', async (req, res) => {
|
|
11
|
+
try {
|
|
12
|
+
const folder = sharedFilesFolder(config);
|
|
13
|
+
if (!(await checkIfExists(folder))) {
|
|
14
|
+
res.json({ files: [] });
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const entries = await fs.readdir(folder);
|
|
19
|
+
const files: { name: string; size: number }[] = [];
|
|
20
|
+
for (const entry of entries) {
|
|
21
|
+
const stat = await fs.stat(path.join(folder, entry));
|
|
22
|
+
if (stat.isFile()) {
|
|
23
|
+
files.push({ name: entry, size: stat.size });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
res.json({ files });
|
|
27
|
+
} catch (err: unknown) {
|
|
28
|
+
console.error(err);
|
|
29
|
+
res.status(500).json({ error: (err as Error).message });
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Download/serve a specific shared file
|
|
34
|
+
app.get('/api/shared/files/:filename', async (req, res) => {
|
|
35
|
+
try {
|
|
36
|
+
const filePath = safeFilePath(config, req.params.filename);
|
|
37
|
+
if (!filePath) {
|
|
38
|
+
res.status(400).json({ error: 'Invalid filename' });
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (!(await checkIfExists(filePath))) {
|
|
43
|
+
res.status(404).json({ error: 'File not found' });
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
res.sendFile(filePath);
|
|
48
|
+
} catch (err: unknown) {
|
|
49
|
+
console.error(err);
|
|
50
|
+
res.status(500).json({ error: (err as Error).message });
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Upload a shared file (raw body + x-filename header)
|
|
55
|
+
app.post('/api/shared/files', express.raw({ type: '*/*', limit: '50mb' }), async (req, res) => {
|
|
56
|
+
try {
|
|
57
|
+
const filename = req.headers['x-filename'] as string | undefined;
|
|
58
|
+
if (!filename || filename.trim().length === 0) {
|
|
59
|
+
res.status(400).json({ error: 'x-filename header is required' });
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const filePath = safeFilePath(config, filename);
|
|
64
|
+
if (!filePath) {
|
|
65
|
+
res.status(400).json({ error: 'Invalid filename' });
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const folder = sharedFilesFolder(config);
|
|
70
|
+
await ensureFolderExists(folder);
|
|
71
|
+
await fs.writeFile(filePath, req.body as Buffer);
|
|
72
|
+
|
|
73
|
+
const stat = await fs.stat(filePath);
|
|
74
|
+
res.status(201).json({ name: filename, size: stat.size });
|
|
75
|
+
} catch (err: unknown) {
|
|
76
|
+
console.error(err);
|
|
77
|
+
res.status(500).json({ error: (err as Error).message });
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// Delete a shared file
|
|
82
|
+
app.delete('/api/shared/files/:filename', async (req, res) => {
|
|
83
|
+
try {
|
|
84
|
+
const filePath = safeFilePath(config, req.params.filename);
|
|
85
|
+
if (!filePath) {
|
|
86
|
+
res.status(400).json({ error: 'Invalid filename' });
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (!(await checkIfExists(filePath))) {
|
|
91
|
+
res.status(404).json({ error: 'File not found' });
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
await fs.unlink(filePath);
|
|
96
|
+
res.json({ deleted: true });
|
|
97
|
+
} catch (err: unknown) {
|
|
98
|
+
console.error(err);
|
|
99
|
+
res.status(500).json({ error: (err as Error).message });
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ---------------------------------------------------------------------------
|
|
105
|
+
// Helpers
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
|
|
108
|
+
function sharedFilesFolder(config: SynthOSConfig): string {
|
|
109
|
+
return path.join(config.pagesFolder, 'shared', 'files');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Resolve a filename inside the shared files folder with path-traversal protection.
|
|
114
|
+
* Returns the absolute path if safe, or null if the filename is invalid.
|
|
115
|
+
*/
|
|
116
|
+
function safeFilePath(config: SynthOSConfig, filename: string): string | null {
|
|
117
|
+
if (!filename || filename.includes('..') || filename.includes('/') || filename.includes('\\')) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
const folder = sharedFilesFolder(config);
|
|
121
|
+
const resolved = path.resolve(folder, filename);
|
|
122
|
+
if (!resolved.startsWith(path.resolve(folder))) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
return resolved;
|
|
126
|
+
}
|
package/src/settings.ts
CHANGED
|
@@ -39,6 +39,7 @@ export interface SettingsV2 {
|
|
|
39
39
|
services?: ServicesConfig;
|
|
40
40
|
connectors?: ServicesConfig;
|
|
41
41
|
agents?: AgentConfig[];
|
|
42
|
+
toolbarPosition?: 'left' | 'right';
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
export const DefaultSettings: SettingsV2 = {
|
|
@@ -66,6 +67,7 @@ export const DefaultSettings: SettingsV2 = {
|
|
|
66
67
|
services: {},
|
|
67
68
|
connectors: {},
|
|
68
69
|
agents: [],
|
|
70
|
+
toolbarPosition: 'left',
|
|
69
71
|
};
|
|
70
72
|
|
|
71
73
|
/**
|
package/src/synthos-cli.ts
CHANGED
|
@@ -2,6 +2,7 @@ import yargs from "yargs";
|
|
|
2
2
|
import { hideBin } from "yargs/helpers";
|
|
3
3
|
import { server } from "./service";
|
|
4
4
|
import { createConfig, init } from "./init";
|
|
5
|
+
import { customizer } from "./customizer";
|
|
5
6
|
|
|
6
7
|
const dynamicImport = new Function('specifier', `return import(specifier)`);
|
|
7
8
|
|
|
@@ -16,7 +17,7 @@ export async function run() {
|
|
|
16
17
|
default: 4242
|
|
17
18
|
})
|
|
18
19
|
.option('pages', {
|
|
19
|
-
describe: `Include default pages when initializing a new
|
|
20
|
+
describe: `Include default pages when initializing a new local folder.`,
|
|
20
21
|
type: 'boolean',
|
|
21
22
|
default: true
|
|
22
23
|
})
|
|
@@ -32,9 +33,9 @@ export async function run() {
|
|
|
32
33
|
})
|
|
33
34
|
.demandOption([]);
|
|
34
35
|
}, async (args) => {
|
|
35
|
-
const config = createConfig(
|
|
36
|
+
const config = await createConfig(customizer.localFolder, { debug: args.debug, debugPageUpdates: args.debugPageUpdates }, customizer);
|
|
36
37
|
await init(config, args.pages);
|
|
37
|
-
await server(config).listen(args.port, async () => {
|
|
38
|
+
await server(config, customizer).listen(args.port, async () => {
|
|
38
39
|
console.log(`SynthOS server is running on http://localhost:${args.port}`);
|
|
39
40
|
|
|
40
41
|
// Open using default browser
|
package/src/themes.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
|
-
import { checkIfExists, listFiles, loadFile } from './files';
|
|
2
|
+
import { checkIfExists, findFileInFolders, listFiles, listFilesFromFolders, loadFile } from './files';
|
|
3
3
|
import { SynthOSConfig } from './init';
|
|
4
4
|
|
|
5
5
|
export const THEME_VERSION = 2;
|
|
@@ -46,6 +46,16 @@ async function findThemeCssFile(folder: string, name: string): Promise<{ path: s
|
|
|
46
46
|
return best;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
export async function loadThemeVersion(name: string, config: SynthOSConfig): Promise<number> {
|
|
50
|
+
const local = await findThemeCssFile(userThemesFolder(config), name);
|
|
51
|
+
if (local) return local.version;
|
|
52
|
+
for (const folder of config.defaultThemesFolders) {
|
|
53
|
+
const def = await findThemeCssFile(folder, name);
|
|
54
|
+
if (def) return def.version;
|
|
55
|
+
}
|
|
56
|
+
return 1;
|
|
57
|
+
}
|
|
58
|
+
|
|
49
59
|
export async function loadThemeInfo(name: string, config: SynthOSConfig): Promise<ThemeInfo | undefined> {
|
|
50
60
|
// Check user's local themes first, then fall back to package defaults
|
|
51
61
|
const localPath = path.join(userThemesFolder(config), `${name}.json`);
|
|
@@ -54,8 +64,8 @@ export async function loadThemeInfo(name: string, config: SynthOSConfig): Promis
|
|
|
54
64
|
return raw ? JSON.parse(raw) : undefined;
|
|
55
65
|
}
|
|
56
66
|
|
|
57
|
-
const defaultPath =
|
|
58
|
-
if (
|
|
67
|
+
const defaultPath = await findFileInFolders(config.defaultThemesFolders, `${name}.json`);
|
|
68
|
+
if (defaultPath) {
|
|
59
69
|
const raw = await loadFile(defaultPath);
|
|
60
70
|
return raw ? JSON.parse(raw) : undefined;
|
|
61
71
|
}
|
|
@@ -70,9 +80,12 @@ export async function loadTheme(name: string, config: SynthOSConfig): Promise<st
|
|
|
70
80
|
return await loadFile(local.path);
|
|
71
81
|
}
|
|
72
82
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
83
|
+
// Search all default theme folders
|
|
84
|
+
for (const folder of config.defaultThemesFolders) {
|
|
85
|
+
const def = await findThemeCssFile(folder, name);
|
|
86
|
+
if (def) {
|
|
87
|
+
return await loadFile(def.path);
|
|
88
|
+
}
|
|
76
89
|
}
|
|
77
90
|
|
|
78
91
|
return undefined;
|
|
@@ -91,13 +104,11 @@ export async function listThemes(config: SynthOSConfig): Promise<string[]> {
|
|
|
91
104
|
}
|
|
92
105
|
}
|
|
93
106
|
|
|
94
|
-
// Collect from
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
if (parsed) names.add(parsed.name);
|
|
100
|
-
}
|
|
107
|
+
// Collect from all default theme folders
|
|
108
|
+
const defaultFiles = await listFilesFromFolders(config.defaultThemesFolders);
|
|
109
|
+
for (const f of defaultFiles) {
|
|
110
|
+
const parsed = parseThemeFilename(f);
|
|
111
|
+
if (parsed) names.add(parsed.name);
|
|
101
112
|
}
|
|
102
113
|
|
|
103
114
|
return Array.from(names).sort();
|
|
@@ -110,7 +121,7 @@ export async function getOutdatedThemes(config: SynthOSConfig): Promise<string[]
|
|
|
110
121
|
const localFolder = userThemesFolder(config);
|
|
111
122
|
if (!await checkIfExists(localFolder)) return [];
|
|
112
123
|
|
|
113
|
-
const defaultFiles = await
|
|
124
|
+
const defaultFiles = await listFilesFromFolders(config.defaultThemesFolders);
|
|
114
125
|
const localFiles = await listFiles(localFolder);
|
|
115
126
|
|
|
116
127
|
// Build maps: theme name → highest version
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="g" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
4
|
+
<stop offset="0%" stop-color="#a855f7"/>
|
|
5
|
+
<stop offset="100%" stop-color="#3b82f6"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
</defs>
|
|
8
|
+
<rect width="32" height="32" rx="7" fill="#0f0f13"/>
|
|
9
|
+
<path d="M9 11 C9 8.8 10.8 7 13 7 L20 7 C22.2 7 24 8.8 24 11 C24 13.2 22.2 15 20 15 L13 15 C10.8 15 9 16.8 9 19 C9 21.2 10.8 23 13 23 L20 23" stroke="url(#g)" stroke-width="3" stroke-linecap="round" fill="none"/>
|
|
10
|
+
<circle cx="9" cy="11" r="2" fill="#a855f7"/>
|
|
11
|
+
<circle cx="23" cy="23" r="2" fill="#3b82f6"/>
|
|
12
|
+
</svg>
|