synthos 0.10.0 → 0.11.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 +5 -5
- package/default-pages/elevenlabs_effects_studio/chat-history.json +1 -0
- package/default-pages/elevenlabs_effects_studio/page.html +1345 -1363
- package/default-pages/elevenlabs_effects_studio/page.json +13 -11
- package/default-pages/elevenlabs_voice_studio/chat-history.json +1 -0
- package/default-pages/elevenlabs_voice_studio/page.html +782 -801
- package/default-pages/elevenlabs_voice_studio/page.json +13 -11
- package/default-pages/json_tools/chat-history.json +1 -0
- package/default-pages/json_tools/page.html +70 -90
- package/default-pages/json_tools/page.json +12 -10
- package/default-pages/my_notes/chat-history.json +1 -0
- package/default-pages/my_notes/page.html +115 -131
- package/default-pages/my_notes/page.json +14 -12
- package/default-pages/neon_asteroids/chat-history.json +1 -0
- package/default-pages/neon_asteroids/page.html +1777 -1803
- package/default-pages/neon_asteroids/page.json +14 -12
- package/default-pages/oregon_trail/chat-history.json +1 -0
- package/default-pages/oregon_trail/page.html +290 -307
- package/default-pages/oregon_trail/page.json +14 -12
- package/default-pages/solar_explorer/chat-history.json +1 -0
- package/default-pages/solar_explorer/page.html +1929 -1951
- package/default-pages/solar_explorer/page.json +14 -12
- package/default-pages/solar_tutorial/chat-history.json +1 -0
- package/default-pages/solar_tutorial/page.html +464 -478
- package/default-pages/solar_tutorial/page.json +12 -10
- package/default-pages/us_map/chat-history.json +1 -0
- package/default-pages/us_map/page.html +170 -193
- package/default-pages/us_map/page.json +14 -12
- package/default-pages/us_map/page.light.png +0 -0
- package/default-pages/us_map_1850/chat-history.json +1 -0
- package/default-pages/us_map_1850/page.html +302 -326
- package/default-pages/us_map_1850/page.json +14 -12
- package/default-pages/western_cities_1850/chat-history.json +1 -0
- package/default-pages/western_cities_1850/page.html +503 -527
- package/default-pages/western_cities_1850/page.json +14 -12
- package/default-themes/aurora-dawn.v3.css +15 -14
- package/default-themes/aurora-dusk.v3.css +26 -26
- package/default-themes/cosmos-dawn.v3.css +15 -14
- package/default-themes/cosmos-dusk.v3.css +26 -26
- package/default-themes/elemental-dawn.v3.css +200 -0
- package/default-themes/nebula-dawn.v3.css +15 -14
- package/default-themes/nebula-dusk.v3.css +24 -24
- package/default-themes/solar-flare-dawn.v3.css +15 -14
- package/default-themes/solar-flare-dusk.v3.css +26 -26
- package/dist/builders/anthropic.d.ts +26 -2
- package/dist/builders/anthropic.d.ts.map +1 -1
- package/dist/builders/anthropic.js +132 -31
- package/dist/builders/anthropic.js.map +1 -1
- package/dist/builders/claudecode.d.ts +13 -0
- package/dist/builders/claudecode.d.ts.map +1 -0
- package/dist/builders/claudecode.js +253 -0
- package/dist/builders/claudecode.js.map +1 -0
- package/dist/builders/index.d.ts +2 -1
- package/dist/builders/index.d.ts.map +1 -1
- package/dist/builders/index.js +8 -1
- package/dist/builders/index.js.map +1 -1
- package/dist/builders/openai.js +2 -1
- package/dist/builders/openai.js.map +1 -1
- package/dist/builders/types.d.ts +31 -7
- package/dist/builders/types.d.ts.map +1 -1
- package/dist/builders/types.js +60 -28
- package/dist/builders/types.js.map +1 -1
- package/dist/connectors/types.d.ts +8 -0
- package/dist/connectors/types.d.ts.map +1 -1
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +13 -6
- package/dist/init.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +161 -14
- package/dist/migrations.js.map +1 -1
- package/dist/models/anthropic.d.ts +1 -0
- package/dist/models/anthropic.d.ts.map +1 -1
- package/dist/models/anthropic.js +129 -29
- package/dist/models/anthropic.js.map +1 -1
- package/dist/models/chainOfThought.d.ts.map +1 -1
- package/dist/models/chainOfThought.js +32 -19
- package/dist/models/chainOfThought.js.map +1 -1
- package/dist/models/index.d.ts +2 -2
- 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/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 +15 -1
- package/dist/models/types.d.ts.map +1 -1
- package/dist/models/types.js.map +1 -1
- package/dist/pages.d.ts +57 -8
- package/dist/pages.d.ts.map +1 -1
- package/dist/pages.js +258 -45
- package/dist/pages.js.map +1 -1
- package/dist/service/createCompletePrompt.d.ts.map +1 -1
- package/dist/service/createCompletePrompt.js +5 -0
- package/dist/service/createCompletePrompt.js.map +1 -1
- package/dist/service/mediaCache.d.ts +36 -0
- package/dist/service/mediaCache.d.ts.map +1 -0
- package/dist/service/mediaCache.js +182 -0
- package/dist/service/mediaCache.js.map +1 -0
- package/dist/service/pageValidator.d.ts +25 -0
- package/dist/service/pageValidator.d.ts.map +1 -0
- package/dist/service/pageValidator.js +315 -0
- package/dist/service/pageValidator.js.map +1 -0
- package/dist/service/server.d.ts.map +1 -1
- package/dist/service/server.js +4 -0
- package/dist/service/server.js.map +1 -1
- package/dist/service/sharedTableSchema.d.ts +73 -0
- package/dist/service/sharedTableSchema.d.ts.map +1 -0
- package/dist/service/sharedTableSchema.js +206 -0
- package/dist/service/sharedTableSchema.js.map +1 -0
- package/dist/service/transformPage.d.ts +49 -11
- package/dist/service/transformPage.d.ts.map +1 -1
- package/dist/service/transformPage.js +354 -241
- package/dist/service/transformPage.js.map +1 -1
- package/dist/service/useApiRoutes.d.ts.map +1 -1
- package/dist/service/useApiRoutes.js +288 -34
- package/dist/service/useApiRoutes.js.map +1 -1
- package/dist/service/useConnectorRoutes.d.ts.map +1 -1
- package/dist/service/useConnectorRoutes.js +170 -32
- package/dist/service/useConnectorRoutes.js.map +1 -1
- package/dist/service/useDataRoutes.d.ts.map +1 -1
- package/dist/service/useDataRoutes.js +59 -2
- package/dist/service/useDataRoutes.js.map +1 -1
- package/dist/service/useExtractRoutes.d.ts +4 -0
- package/dist/service/useExtractRoutes.d.ts.map +1 -0
- package/dist/service/useExtractRoutes.js +304 -0
- package/dist/service/useExtractRoutes.js.map +1 -0
- package/dist/service/usePageRoutes.d.ts +17 -0
- package/dist/service/usePageRoutes.d.ts.map +1 -1
- package/dist/service/usePageRoutes.js +1385 -483
- package/dist/service/usePageRoutes.js.map +1 -1
- package/dist/service/useSharedDataRoutes.d.ts.map +1 -1
- package/dist/service/useSharedDataRoutes.js +54 -2
- package/dist/service/useSharedDataRoutes.js.map +1 -1
- package/dist/settings.d.ts +27 -0
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +40 -1
- package/dist/settings.js.map +1 -1
- package/dist/themes.d.ts +0 -5
- package/dist/themes.d.ts.map +1 -1
- package/dist/themes.js +3 -95
- package/dist/themes.js.map +1 -1
- package/migration-rules/v2-to-v3.md +277 -119
- package/package.json +5 -1
- package/{default-pages/application → required-pages/_shell}/page.html +56 -42
- package/required-pages/_shell/page.json +14 -0
- package/required-pages/_starters/page.html +534 -0
- package/required-pages/_starters/page.json +12 -0
- package/required-pages/builder/page.html +353 -43
- package/required-pages/builder/page.json +12 -10
- package/required-pages/pages/page.html +697 -924
- package/required-pages/pages/page.json +12 -10
- package/required-pages/settings/page.html +1879 -1753
- package/required-pages/settings/page.json +12 -10
- package/required-pages/synthos_apis/page.html +834 -845
- package/required-pages/synthos_apis/page.json +12 -10
- package/required-pages/synthos_scripts/page.html +74 -88
- package/required-pages/synthos_scripts/page.json +12 -10
- package/scripts/append-instructions.py +90 -0
- package/scripts/audit-instructions.py +76 -0
- package/scripts/cleanup-shell-markup.mjs +112 -0
- package/service-connectors/buffer/connector.json +46 -0
- package/service-connectors/canva/connector.json +67 -0
- package/service-connectors/elevenlabs/connector.json +1 -1
- package/src/builders/anthropic.ts +155 -30
- package/src/builders/claudecode.ts +310 -0
- package/src/builders/index.ts +7 -1
- package/src/builders/openai.ts +2 -1
- package/src/builders/types.ts +93 -32
- package/src/connectors/types.ts +8 -0
- package/src/init.ts +13 -7
- package/src/migrations.ts +187 -16
- package/src/models/anthropic.ts +140 -30
- package/src/models/chainOfThought.ts +33 -18
- package/src/models/index.ts +2 -2
- package/src/models/providers.ts +12 -3
- package/src/models/types.ts +21 -1
- package/src/pages.ts +271 -35
- package/src/service/createCompletePrompt.ts +6 -0
- package/src/service/mediaCache.ts +206 -0
- package/src/service/pageValidator.ts +337 -0
- package/src/service/server.ts +4 -0
- package/src/service/sharedTableSchema.ts +236 -0
- package/src/service/transformPage.ts +370 -260
- package/src/service/useApiRoutes.ts +282 -32
- package/src/service/useConnectorRoutes.ts +189 -34
- package/src/service/useDataRoutes.ts +198 -116
- package/src/service/useExtractRoutes.ts +331 -0
- package/src/service/usePageRoutes.ts +1411 -394
- package/src/service/useSharedDataRoutes.ts +184 -109
- package/src/settings.ts +65 -0
- package/src/themes.ts +78 -180
- package/starters/blank_starter/chat-history.json +1 -0
- package/starters/blank_starter/page.dark.png +0 -0
- package/starters/blank_starter/page.html +47 -0
- package/starters/blank_starter/page.json +13 -0
- package/starters/blank_starter/page.light.png +0 -0
- package/starters/calculator_starter/chat-history.json +1 -0
- package/starters/calculator_starter/page.dark.png +0 -0
- package/starters/calculator_starter/page.html +232 -0
- package/starters/calculator_starter/page.json +13 -0
- package/starters/calculator_starter/page.light.png +0 -0
- package/starters/calendar_starter/chat-history.json +1 -0
- package/starters/calendar_starter/page.dark.png +0 -0
- package/starters/calendar_starter/page.html +495 -0
- package/starters/calendar_starter/page.json +13 -0
- package/starters/calendar_starter/page.light.png +0 -0
- package/starters/chat_starter/chat-history.json +1 -0
- package/starters/chat_starter/page.dark.png +0 -0
- package/starters/chat_starter/page.html +351 -0
- package/starters/chat_starter/page.json +13 -0
- package/starters/chat_starter/page.light.png +0 -0
- package/starters/checklist_starter/chat-history.json +1 -0
- package/starters/checklist_starter/page.dark.png +0 -0
- package/starters/checklist_starter/page.html +437 -0
- package/starters/checklist_starter/page.json +13 -0
- package/starters/checklist_starter/page.light.png +0 -0
- package/starters/dashboard_starter/chat-history.json +1 -0
- package/starters/dashboard_starter/page.dark.png +0 -0
- package/starters/dashboard_starter/page.html +195 -0
- package/starters/dashboard_starter/page.json +13 -0
- package/starters/dashboard_starter/page.light.png +0 -0
- package/starters/form_starter/chat-history.json +1 -0
- package/starters/form_starter/page.dark.png +0 -0
- package/starters/form_starter/page.html +313 -0
- package/starters/form_starter/page.json +13 -0
- package/starters/form_starter/page.light.png +0 -0
- package/starters/gallery_starter/chat-history.json +1 -0
- package/starters/gallery_starter/page.dark.png +0 -0
- package/starters/gallery_starter/page.html +418 -0
- package/starters/gallery_starter/page.json +13 -0
- package/starters/gallery_starter/page.light.png +0 -0
- package/starters/generator_starter/chat-history.json +1 -0
- package/starters/generator_starter/page.dark.png +0 -0
- package/starters/generator_starter/page.html +261 -0
- package/starters/generator_starter/page.json +13 -0
- package/starters/generator_starter/page.light.png +0 -0
- package/starters/index.html +538 -0
- package/starters/kanban_starter/chat-history.json +1 -0
- package/starters/kanban_starter/page.dark.png +0 -0
- package/starters/kanban_starter/page.html +432 -0
- package/starters/kanban_starter/page.json +13 -0
- package/starters/kanban_starter/page.light.png +0 -0
- package/starters/presentation_builder/chat-history.json +1 -0
- package/starters/presentation_builder/page.dark.png +0 -0
- package/starters/presentation_builder/page.html +970 -0
- package/starters/presentation_builder/page.json +15 -0
- package/starters/presentation_builder/page.light.png +0 -0
- package/starters/presentation_builder/presentation_voice/voice_config.json +9 -0
- package/starters/pulse_starter/chat-history.json +1 -0
- package/starters/pulse_starter/page.dark.png +0 -0
- package/starters/pulse_starter/page.html +698 -0
- package/starters/pulse_starter/page.json +13 -0
- package/starters/pulse_starter/page.light.png +0 -0
- package/starters/quiz_starter/chat-history.json +1 -0
- package/starters/quiz_starter/page.dark.png +0 -0
- package/starters/quiz_starter/page.html +292 -0
- package/starters/quiz_starter/page.json +13 -0
- package/starters/quiz_starter/page.light.png +0 -0
- package/starters/reference_starter/chat-history.json +1 -0
- package/starters/reference_starter/page.dark.png +0 -0
- package/starters/reference_starter/page.html +250 -0
- package/starters/reference_starter/page.json +13 -0
- package/starters/reference_starter/page.light.png +0 -0
- package/starters/retro_game_starter/chat-history.json +1 -0
- package/starters/retro_game_starter/page.dark.png +0 -0
- package/{default-pages → starters}/retro_game_starter/page.html +1281 -1308
- package/starters/retro_game_starter/page.json +15 -0
- package/starters/retro_game_starter/page.light.png +0 -0
- package/starters/roster_starter/chat-history.json +1 -0
- package/starters/roster_starter/page.dark.png +0 -0
- package/starters/roster_starter/page.html +600 -0
- package/starters/roster_starter/page.json +13 -0
- package/starters/roster_starter/page.light.png +0 -0
- package/starters/server.js +182 -0
- package/starters/start.cmd +1 -0
- package/starters/timeline_starter/chat-history.json +1 -0
- package/starters/timeline_starter/page.dark.png +0 -0
- package/starters/timeline_starter/page.html +446 -0
- package/starters/timeline_starter/page.json +13 -0
- package/starters/timeline_starter/page.light.png +0 -0
- package/starters/tutorial_starter/chat-history.json +1 -0
- package/starters/tutorial_starter/page.dark.png +0 -0
- package/starters/tutorial_starter/page.html +283 -0
- package/starters/tutorial_starter/page.json +13 -0
- package/starters/tutorial_starter/page.light.png +0 -0
- package/static-files/agent.v3.js +122 -0
- package/static-files/connector.v3.js +48 -0
- package/static-files/extract.v3.js +188 -0
- package/static-files/helpers.v3.js +50 -6
- package/static-files/page-bridge.js +114 -0
- package/static-files/page.v3.js +1292 -1290
- package/static-files/script.v3.js +32 -0
- package/static-files/server.v3.js +89 -0
- package/static-files/shell-bridge.v3.js +174 -0
- package/static-files/shell-modals.v3.js +521 -0
- package/static-files/{shell.css → shell.v3.css} +271 -22
- package/static-files/shell.v3.js +1865 -0
- package/static-files/storage.v3.js +176 -0
- package/tests/anthropic.spec.ts +42 -7
- package/tests/builders.spec.ts +72 -4
- package/tests/pageValidator.spec.ts +548 -0
- package/tests/profiles.spec.ts +122 -0
- package/tests/providers.spec.ts +1 -1
- package/tests/sharedTableSchema.spec.ts +242 -0
- package/tests/transformPage.spec.ts +62 -81
- package/default-pages/application/page.json +0 -10
- package/default-pages/retro_game_starter/page.json +0 -12
- package/default-pages/sidebar_page/page.html +0 -51
- package/default-pages/sidebar_page/page.json +0 -10
- package/default-pages/two-panel_page/page.html +0 -68
- package/default-pages/two-panel_page/page.json +0 -10
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
{
|
|
2
|
-
"title": "SynthOS APIs",
|
|
3
|
-
"categories": [
|
|
4
|
-
"System"
|
|
5
|
-
],
|
|
6
|
-
"pinned": false,
|
|
7
|
-
"showInAll": false,
|
|
8
|
-
"pageVersion": 3,
|
|
9
|
-
"mode": "locked"
|
|
10
|
-
|
|
1
|
+
{
|
|
2
|
+
"title": "SynthOS APIs",
|
|
3
|
+
"categories": [
|
|
4
|
+
"System"
|
|
5
|
+
],
|
|
6
|
+
"pinned": false,
|
|
7
|
+
"showInAll": false,
|
|
8
|
+
"pageVersion": 3,
|
|
9
|
+
"mode": "locked",
|
|
10
|
+
"greeting": "",
|
|
11
|
+
"firstRunGreeting": ""
|
|
12
|
+
}
|
|
@@ -1,89 +1,75 @@
|
|
|
1
|
-
<!DOCTYPE html><html lang="en"><head>
|
|
2
|
-
<meta charset="UTF-8">
|
|
3
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
4
|
-
<title>SynthOS - Scripts</title>
|
|
5
|
-
<script id="theme-info" src="/api/theme-info.js" data-locked="true"></script>
|
|
6
|
-
<link id="theme-css" rel="stylesheet" href="/api/theme.css" data-locked="true">
|
|
7
|
-
<style>.application-title{font-size:22px;font-weight:700;min-height:var(--header-min-height);padding:var(--header-padding-vertical) var(--header-padding-horizontal);line-height:var(--header-line-height);display:flex;align-items:center;justify-content:center;box-sizing:border-box;background:linear-gradient(135deg,var(--
|
|
8
|
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.9.0/d3.min.js"></script>
|
|
9
|
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/14.1.1/marked.min.js"></script>
|
|
10
|
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/mermaid/11.1.0/mermaid.min.js"></script>
|
|
11
|
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
|
|
12
|
-
<script id="page-info" src="/api/page-info.js?page=scripts"></script>
|
|
13
|
-
</head>
|
|
14
|
-
<body>
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
<
|
|
19
|
-
<div class="
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
<button class="
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
<
|
|
56
|
-
<p>
|
|
57
|
-
|
|
58
|
-
<
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
<
|
|
62
|
-
|
|
63
|
-
<
|
|
64
|
-
<p>
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
<p>The Description field allows you to provide a brief explanation of what SynthOS can use your script for.</p>
|
|
76
|
-
|
|
77
|
-
<h3>Defining Variables</h3>
|
|
78
|
-
<p>Use the Variables field to specify any input parameters your script expects. Format it as a JSON object, e.g., { city: string, days?: number }. This helps SynthOS know what inputs it needs to provide when running your script.</p>
|
|
79
|
-
</div>
|
|
80
|
-
</div>
|
|
81
|
-
</div>
|
|
82
|
-
<div id="loadingOverlay" class="loading-overlay"><div class="spinner"></div></div>
|
|
83
|
-
</div>
|
|
84
|
-
<div id="instructions" style="display: none;" data-locked="true"></div>
|
|
85
|
-
<div id="thoughts" style="display: none;" data-locked="true"></div>
|
|
86
|
-
<script id="script-editor">const scriptList=document.getElementById("scriptList"),scriptId=document.getElementById("scriptId"),scriptType=document.getElementById("scriptType"),scriptCommand=document.getElementById("scriptCommand"),scriptDescription=document.getElementById("scriptDescription"),scriptVariables=document.getElementById("scriptVariables"),addScriptBtn=document.querySelector(".add-script-btn"),saveScriptBtn=document.querySelector(".save-script-btn"),deleteScriptBtn=document.querySelector(".delete-script-btn"),placeholderMessage=document.getElementById("placeholderMessage"),commandError=document.getElementById("commandError");let isNewScript=!1;function showScriptDetails(){placeholderMessage.style.display="none",scriptId.style.display="block",scriptType.style.display="block",scriptCommand.style.display="block",scriptDescription.style.display="block",scriptVariables.style.display="block",saveScriptBtn.style.display="block",deleteScriptBtn.style.display=isNewScript?"none":"block"}function hideScriptDetails(){placeholderMessage.style.display="block",scriptId.style.display="none",scriptType.style.display="none",scriptCommand.style.display="none",scriptDescription.style.display="none",scriptVariables.style.display="none",saveScriptBtn.style.display="none",deleteScriptBtn.style.display="none",commandError.style.display="none"}function formatId(id){return id.toLowerCase().replace(/\s+/g,"-")}function loadScripts(){fetch("/api/data/scripts/scripts").then(response=>response.json()).then(scripts=>{scriptList.innerHTML="",scripts.forEach(script=>{const li=document.createElement("li");li.textContent=script.id,li.dataset.id=script.id,li.dataset.type=script.type,li.dataset.command=script.command,li.dataset.description=script.description||"",li.dataset.variables=script.variables||"",scriptList.appendChild(li)})}).catch(error=>console.error("Error loading scripts:",error))}function saveScript(script){fetch("/api/data/scripts/scripts").then(response=>response.json()).then(scripts=>{scripts.find(s=>s.id===script.id)&&isNewScript?confirm("A script with this ID already exists. Do you want to overwrite it?")&&performSave(script):performSave(script)}).catch(error=>console.error("Error checking existing scripts:",error))}function performSave(script){fetch("/api/data/scripts/scripts",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(script)}).then(response=>response.json()).then(savedScript=>{loadScripts(),isNewScript=!1,setTimeout(()=>{const newScriptElement=document.querySelector(`[data-id="${savedScript.id}"]`);newScriptElement&&newScriptElement.click()},100)}).catch(error=>console.error("Error saving script:",error))}function deleteScript(id){confirm("Are you sure you want to delete this script?")&&fetch(`/api/data/scripts/scripts/${id}`,{method:"DELETE"}).then(response=>response.json()).then(result=>{result.success?(loadScripts(),hideScriptDetails()):console.error("Failed to delete script.")}).catch(error=>console.error("Error deleting script:",error))}scriptList.addEventListener("click",e=>{"LI"===e.target.tagName&&(document.querySelectorAll(".script-list li").forEach(li=>li.classList.remove("active")),e.target.classList.add("active"),showScriptDetails(),scriptId.value=e.target.dataset.id,scriptType.value=e.target.dataset.type||"command",scriptCommand.value=e.target.dataset.command||"",scriptDescription.value=e.target.dataset.description||"",scriptVariables.value=e.target.dataset.variables||"",commandError.style.display="none",isNewScript=!1,deleteScriptBtn.style.display="block")}),addScriptBtn.addEventListener("click",()=>{const newId=formatId(`script-${Date.now()}`);showScriptDetails(),scriptId.value=newId,scriptType.value="command",scriptCommand.value="",scriptDescription.value="",scriptVariables.value="",commandError.style.display="none",document.querySelectorAll(".script-list li").forEach(li=>li.classList.remove("active")),isNewScript=!0,deleteScriptBtn.style.display="none"}),saveScriptBtn.addEventListener("click",()=>{scriptCommand.value.trim()?saveScript({id:formatId(scriptId.value),type:scriptType.value,command:scriptCommand.value,description:scriptDescription.value.trim()||void 0,variables:scriptVariables.value.trim()||void 0}):commandError.style.display="block"}),deleteScriptBtn.addEventListener("click",()=>{const id=scriptId.value;id&&deleteScript(id)}),scriptId.addEventListener("input",e=>{e.target.value=formatId(e.target.value)}),scriptCommand.addEventListener("input",()=>{commandError.style.display="none"}),loadScripts(),hideScriptDetails();</script>
|
|
87
|
-
<script id="page-helpers" src="/api/page-helpers.js?v=3" data-locked="true"></script>
|
|
88
|
-
<script id="page-script" src="/api/page-script.js?v=3" data-locked="true"></script>
|
|
1
|
+
<!DOCTYPE html><html lang="en"><head>
|
|
2
|
+
<meta charset="UTF-8">
|
|
3
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
4
|
+
<title>SynthOS - Scripts</title>
|
|
5
|
+
<script id="theme-info" src="/api/theme-info.js" data-locked="true"></script>
|
|
6
|
+
<link id="theme-css" rel="stylesheet" href="/api/theme.css" data-locked="true">
|
|
7
|
+
<style>.application-title{font-size:22px;font-weight:700;min-height:var(--header-min-height);padding:var(--header-padding-vertical) var(--header-padding-horizontal);line-height:var(--header-line-height);display:flex;align-items:center;justify-content:center;box-sizing:border-box;background:linear-gradient(135deg,var(--themePrimary),var(--themeDark));color:#fff;border-radius:12px;width:100%;max-width:800px;box-shadow:0 6px 25px var(--themeLighter);position:relative;z-index:1}.application-content{font-size:14px;color:var(--bodySubtext);padding:15px 0;flex-grow:1;width:100%;max-width:800px;position:relative;z-index:1;overflow-y:auto;display:flex;gap:20px}.script-list{width:200px;flex-shrink:0}.script-list ul{list-style:none;background:rgba(15,15,35,.6);border-radius:10px;border:1px solid var(--bodyDivider);overflow:hidden;margin-bottom:10px;max-height:300px;overflow-y:auto}.script-list li{padding:12px 15px;cursor:pointer;transition:.3s;border-bottom:1px solid var(--bodyDivider);color:var(--bodySubtext)}.script-list li:last-child{border-bottom:none}.script-list li:hover{background:linear-gradient(135deg,rgba(102,126,234,.2) 0,rgba(118,75,162,.2) 100%);color:var(--themeTertiary)}.script-list li.active{background:linear-gradient(135deg,rgba(102,126,234,.3) 0,rgba(118,75,162,.3) 100%);color:var(--themeTertiary);box-shadow:inset 0 0 15px var(--themeLighter)}.add-script-btn,.delete-script-btn,.save-script-btn{width:100%;padding:12px 18px;border:none;border-radius:10px;background:linear-gradient(135deg,var(--themePrimary) 0,var(--themeDark) 100%);color:#fff;cursor:pointer;transition:.3s;font-weight:500;font-size:13px;box-shadow:0 3px 15px var(--themeLighter);margin-bottom:8px}.add-script-btn:hover,.save-script-btn:hover{transform:translateY(-2px);box-shadow:0 5px 20px rgba(102,126,234,.5)}.delete-script-btn{background:linear-gradient(135deg,#e74c3c 0,#c0392b 100%);box-shadow:0 3px 15px rgba(231,76,60,.3)}.delete-script-btn:hover{box-shadow:0 5px 20px rgba(231,76,60,.5);transform:translateY(-2px)}.script-detail{flex-grow:1;background:rgba(15,15,35,.6);border-radius:10px;border:1px solid var(--bodyDivider);padding:20px}.script-detail input,.script-detail select{width:100%;padding:12px 15px;margin-bottom:12px;border-radius:8px;border:1px solid var(--bodyDivider);background:rgba(15,15,35,.8);color:var(--bodyText);font-size:13px;transition:.3s}.script-detail input:focus,.script-detail select:focus{outline:0;border-color:var(--bodySubtext);box-shadow:0 0 15px var(--themeLighter)}.script-detail select{cursor:pointer}.script-detail select option{background:var(--defaultStateBackground);color:var(--bodyText)}.placeholder-message{color:var(--bodySubtext);text-align:center;padding:40px 20px;line-height:1.6}.error-message{display:none;color:#e74c3c;font-size:12px;margin-bottom:12px;padding:8px 12px;background:rgba(231,76,60,.1);border-radius:6px;border:1px solid rgba(231,76,60,.3)}.instructions{margin-top:20px;padding:15px;background:linear-gradient(135deg,rgba(102,126,234,.1) 0,rgba(118,75,162,.1) 100%);border-radius:10px;border:1px solid var(--bodyDivider)}.instructions h3{color:var(--themeTertiary);margin:15px 0 8px;font-size:14px}.instructions h3:first-child{margin-top:0}.instructions p{color:var(--bodySubtext);font-size:12px;line-height:1.6;margin-bottom:8px}.instructions code{background:rgba(138,43,226,.3);padding:2px 6px;border-radius:4px;font-family:'Courier New',Courier,monospace;color:var(--themeTertiary);border:1px solid rgba(240,147,251,.3);font-size:11px}.light-mode .script-detail,.light-mode .script-list ul{background:rgba(255,255,255,.6)}.light-mode .script-detail input,.light-mode .script-detail select{background:rgba(255,255,255,.8);box-shadow:inset 0 2px 10px rgba(118,75,162,.05)}</style>
|
|
8
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.9.0/d3.min.js"></script>
|
|
9
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/14.1.1/marked.min.js"></script>
|
|
10
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/mermaid/11.1.0/mermaid.min.js"></script>
|
|
11
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
|
|
12
|
+
<script id="page-info" src="/api/page-info.js?page=scripts"></script>
|
|
13
|
+
</head>
|
|
14
|
+
<body>
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
<div class="viewer-panel" id="viewerPanel">
|
|
18
|
+
<div class="application-title">Script Editor</div>
|
|
19
|
+
<div class="application-content">
|
|
20
|
+
<div class="script-list">
|
|
21
|
+
<ul id="scriptList">
|
|
22
|
+
<!-- Scripts will be loaded here -->
|
|
23
|
+
</ul>
|
|
24
|
+
<button class="add-script-btn">Add New Script</button>
|
|
25
|
+
</div>
|
|
26
|
+
<div class="script-detail">
|
|
27
|
+
<div id="placeholderMessage" class="placeholder-message">
|
|
28
|
+
Select an existing script to edit or add a new one using the "Add New Script" button.
|
|
29
|
+
</div>
|
|
30
|
+
<input type="text" id="scriptId" placeholder="Script ID" value="" style="display: none;">
|
|
31
|
+
<select id="scriptType" style="display: none;">
|
|
32
|
+
<option value="command">Command</option>
|
|
33
|
+
</select>
|
|
34
|
+
<input type="text" id="scriptCommand" placeholder="Script Command" style="display: none;">
|
|
35
|
+
<input type="text" id="scriptDescription" placeholder="Usage Description (optional)" style="display: none;">
|
|
36
|
+
<input type="text" id="scriptVariables" placeholder="Variables (optional, e.g., { city: string })" style="display: none;">
|
|
37
|
+
<div id="commandError" class="error-message">Script Command is required.</div>
|
|
38
|
+
<button class="save-script-btn" style="display: none;">Save Changes</button>
|
|
39
|
+
<button class="delete-script-btn" style="display: none;">Delete Script</button>
|
|
40
|
+
<div class="instructions">
|
|
41
|
+
<h3>Understanding SynthOS Scripts</h3>
|
|
42
|
+
<p>Scripts in SynthOS are powerful tools that allow you to define custom terminal commands for various tasks. When SynthOS executes a script, it runs the command and captures the console output, which is then returned for further processing or analysis.</p>
|
|
43
|
+
|
|
44
|
+
<h3>Creating Effective Scripts</h3>
|
|
45
|
+
<p>When writing a script, you can use any valid terminal command. For added flexibility, you can include {{variable}} placeholders, which SynthOS will replace with actual values during execution.</p>
|
|
46
|
+
|
|
47
|
+
<h3>Example: Weather Forecast Script</h3>
|
|
48
|
+
<p>Here's an example of an interesting script that SynthOS could use:</p>
|
|
49
|
+
<p><code>curl wttr.in/{{city}}?format=3</code></p>
|
|
50
|
+
<p>This script fetches a concise weather forecast for a specified city. SynthOS can call this script with different city names to get up-to-date weather information.</p>
|
|
51
|
+
|
|
52
|
+
<h3>Tips for Script Writing</h3>
|
|
53
|
+
<p>1. Keep commands concise and focused on a single task.</p>
|
|
54
|
+
<p>2. Use variables for dynamic inputs to make scripts more versatile.</p>
|
|
55
|
+
<p>3. Consider potential errors and how to handle them.</p>
|
|
56
|
+
<p>4. Test your scripts thoroughly to ensure they work as expected.</p>
|
|
57
|
+
<p>5. Provide a clear and concise usage description to help others understand how to use your script.</p>
|
|
58
|
+
<p>6. Define the expected variables in the Variables field to document the script's requirements.</p>
|
|
59
|
+
|
|
60
|
+
<h3>Using the Description Field</h3>
|
|
61
|
+
<p>The Description field allows you to provide a brief explanation of what SynthOS can use your script for.</p>
|
|
62
|
+
|
|
63
|
+
<h3>Defining Variables</h3>
|
|
64
|
+
<p>Use the Variables field to specify any input parameters your script expects. Format it as a JSON object, e.g., { city: string, days?: number }. This helps SynthOS know what inputs it needs to provide when running your script.</p>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
</div>
|
|
70
|
+
<div id="instructions" style="display: none;" data-locked="true"></div>
|
|
71
|
+
<div id="thoughts" style="display: none;" data-locked="true"></div>
|
|
72
|
+
<script id="script-editor">const scriptList=document.getElementById("scriptList"),scriptId=document.getElementById("scriptId"),scriptType=document.getElementById("scriptType"),scriptCommand=document.getElementById("scriptCommand"),scriptDescription=document.getElementById("scriptDescription"),scriptVariables=document.getElementById("scriptVariables"),addScriptBtn=document.querySelector(".add-script-btn"),saveScriptBtn=document.querySelector(".save-script-btn"),deleteScriptBtn=document.querySelector(".delete-script-btn"),placeholderMessage=document.getElementById("placeholderMessage"),commandError=document.getElementById("commandError");let isNewScript=!1;function showScriptDetails(){placeholderMessage.style.display="none",scriptId.style.display="block",scriptType.style.display="block",scriptCommand.style.display="block",scriptDescription.style.display="block",scriptVariables.style.display="block",saveScriptBtn.style.display="block",deleteScriptBtn.style.display=isNewScript?"none":"block"}function hideScriptDetails(){placeholderMessage.style.display="block",scriptId.style.display="none",scriptType.style.display="none",scriptCommand.style.display="none",scriptDescription.style.display="none",scriptVariables.style.display="none",saveScriptBtn.style.display="none",deleteScriptBtn.style.display="none",commandError.style.display="none"}function formatId(id){return id.toLowerCase().replace(/\s+/g,"-")}function loadScripts(){fetch("/api/data/scripts/scripts").then(response=>response.json()).then(scripts=>{scriptList.innerHTML="",scripts.forEach(script=>{const li=document.createElement("li");li.textContent=script.id,li.dataset.id=script.id,li.dataset.type=script.type,li.dataset.command=script.command,li.dataset.description=script.description||"",li.dataset.variables=script.variables||"",scriptList.appendChild(li)})}).catch(error=>console.error("Error loading scripts:",error))}function saveScript(script){fetch("/api/data/scripts/scripts").then(response=>response.json()).then(scripts=>{scripts.find(s=>s.id===script.id)&&isNewScript?confirm("A script with this ID already exists. Do you want to overwrite it?")&&performSave(script):performSave(script)}).catch(error=>console.error("Error checking existing scripts:",error))}function performSave(script){fetch("/api/data/scripts/scripts",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(script)}).then(response=>response.json()).then(savedScript=>{loadScripts(),isNewScript=!1,setTimeout(()=>{const newScriptElement=document.querySelector(`[data-id="${savedScript.id}"]`);newScriptElement&&newScriptElement.click()},100)}).catch(error=>console.error("Error saving script:",error))}function deleteScript(id){confirm("Are you sure you want to delete this script?")&&fetch(`/api/data/scripts/scripts/${id}`,{method:"DELETE"}).then(response=>response.json()).then(result=>{result.success?(loadScripts(),hideScriptDetails()):console.error("Failed to delete script.")}).catch(error=>console.error("Error deleting script:",error))}scriptList.addEventListener("click",e=>{"LI"===e.target.tagName&&(document.querySelectorAll(".script-list li").forEach(li=>li.classList.remove("active")),e.target.classList.add("active"),showScriptDetails(),scriptId.value=e.target.dataset.id,scriptType.value=e.target.dataset.type||"command",scriptCommand.value=e.target.dataset.command||"",scriptDescription.value=e.target.dataset.description||"",scriptVariables.value=e.target.dataset.variables||"",commandError.style.display="none",isNewScript=!1,deleteScriptBtn.style.display="block")}),addScriptBtn.addEventListener("click",()=>{const newId=formatId(`script-${Date.now()}`);showScriptDetails(),scriptId.value=newId,scriptType.value="command",scriptCommand.value="",scriptDescription.value="",scriptVariables.value="",commandError.style.display="none",document.querySelectorAll(".script-list li").forEach(li=>li.classList.remove("active")),isNewScript=!0,deleteScriptBtn.style.display="none"}),saveScriptBtn.addEventListener("click",()=>{scriptCommand.value.trim()?saveScript({id:formatId(scriptId.value),type:scriptType.value,command:scriptCommand.value,description:scriptDescription.value.trim()||void 0,variables:scriptVariables.value.trim()||void 0}):commandError.style.display="block"}),deleteScriptBtn.addEventListener("click",()=>{const id=scriptId.value;id&&deleteScript(id)}),scriptId.addEventListener("input",e=>{e.target.value=formatId(e.target.value)}),scriptCommand.addEventListener("input",()=>{commandError.style.display="none"}),loadScripts(),hideScriptDetails();</script>
|
|
73
|
+
<script id="page-helpers" src="/api/page-helpers.js?v=3" data-locked="true"></script>
|
|
74
|
+
<script id="page-script" src="/api/page-script.js?v=3" data-locked="true"></script>
|
|
89
75
|
</body></html>
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
{
|
|
2
|
-
"title": "SynthOS Scripts",
|
|
3
|
-
"categories": [
|
|
4
|
-
"System"
|
|
5
|
-
],
|
|
6
|
-
"pinned": false,
|
|
7
|
-
"showInAll": false,
|
|
8
|
-
"pageVersion": 3,
|
|
9
|
-
"mode": "locked"
|
|
10
|
-
|
|
1
|
+
{
|
|
2
|
+
"title": "SynthOS Scripts",
|
|
3
|
+
"categories": [
|
|
4
|
+
"System"
|
|
5
|
+
],
|
|
6
|
+
"pinned": false,
|
|
7
|
+
"showInAll": false,
|
|
8
|
+
"pageVersion": 3,
|
|
9
|
+
"mode": "locked",
|
|
10
|
+
"greeting": "",
|
|
11
|
+
"firstRunGreeting": ""
|
|
12
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""One-shot: append the theme-tokens instruction to every starter's instructions div.
|
|
2
|
+
|
|
3
|
+
Excludes retro_game_starter. Edits the same starter in all 3 locations:
|
|
4
|
+
default-pages/<name>/page.html
|
|
5
|
+
.synthos/pages/<name>/page.html
|
|
6
|
+
starters/<name>/page.html
|
|
7
|
+
"""
|
|
8
|
+
import os
|
|
9
|
+
import re
|
|
10
|
+
import sys
|
|
11
|
+
|
|
12
|
+
STARTERS = [
|
|
13
|
+
"blank_starter",
|
|
14
|
+
"calculator_starter",
|
|
15
|
+
"calendar_starter",
|
|
16
|
+
"chat_starter",
|
|
17
|
+
"checklist_starter",
|
|
18
|
+
"dashboard_starter",
|
|
19
|
+
"form_starter",
|
|
20
|
+
"gallery_starter",
|
|
21
|
+
"generator_starter",
|
|
22
|
+
"kanban_starter",
|
|
23
|
+
"presentation_builder",
|
|
24
|
+
"pulse_starter",
|
|
25
|
+
"quiz_starter",
|
|
26
|
+
"reference_starter",
|
|
27
|
+
"roster_starter",
|
|
28
|
+
"timeline_starter",
|
|
29
|
+
"tutorial_starter",
|
|
30
|
+
]
|
|
31
|
+
LOCATIONS = ["default-pages", ".synthos/pages", "starters"]
|
|
32
|
+
APPEND_TEXT = " Use theme tokens (avoid the natural pallet) unless the user requests an alternative color."
|
|
33
|
+
|
|
34
|
+
# Match opening tag of the instructions div, then non-greedy capture up to its closing </div>.
|
|
35
|
+
INSTRUCTIONS_RE = re.compile(
|
|
36
|
+
r'(<div id="instructions"[^>]*>)(.*?)(</div>)',
|
|
37
|
+
re.DOTALL,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
def update(path: str) -> str:
|
|
41
|
+
with open(path, "r", encoding="utf-8") as f:
|
|
42
|
+
original = f.read()
|
|
43
|
+
|
|
44
|
+
matched = []
|
|
45
|
+
|
|
46
|
+
def replace(m):
|
|
47
|
+
opening, body, closing = m.group(1), m.group(2), m.group(3)
|
|
48
|
+
if APPEND_TEXT.strip() in body:
|
|
49
|
+
matched.append("skip-already-present")
|
|
50
|
+
return m.group(0)
|
|
51
|
+
# Preserve trailing whitespace/newlines before </div>.
|
|
52
|
+
trailing_ws = re.search(r"\s*$", body).group(0)
|
|
53
|
+
body_trimmed = body[: len(body) - len(trailing_ws)]
|
|
54
|
+
new_body = body_trimmed + APPEND_TEXT + trailing_ws
|
|
55
|
+
matched.append("ok")
|
|
56
|
+
return opening + new_body + closing
|
|
57
|
+
|
|
58
|
+
updated, count = INSTRUCTIONS_RE.subn(replace, original, count=1)
|
|
59
|
+
if count == 0:
|
|
60
|
+
return "no-match"
|
|
61
|
+
if matched and matched[0] == "skip-already-present":
|
|
62
|
+
return "already"
|
|
63
|
+
if updated != original:
|
|
64
|
+
with open(path, "w", encoding="utf-8", newline="") as f:
|
|
65
|
+
f.write(updated)
|
|
66
|
+
return "updated"
|
|
67
|
+
return "noop"
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def main():
|
|
71
|
+
root = os.path.abspath(os.path.dirname(__file__) + "/..")
|
|
72
|
+
results = []
|
|
73
|
+
for starter in STARTERS:
|
|
74
|
+
for loc in LOCATIONS:
|
|
75
|
+
p = os.path.join(root, loc, starter, "page.html")
|
|
76
|
+
if not os.path.exists(p):
|
|
77
|
+
results.append((p, "missing"))
|
|
78
|
+
continue
|
|
79
|
+
results.append((p, update(p)))
|
|
80
|
+
by_status = {}
|
|
81
|
+
for path, status in results:
|
|
82
|
+
by_status.setdefault(status, []).append(path)
|
|
83
|
+
for status, paths in by_status.items():
|
|
84
|
+
print(f"[{status}] {len(paths)}")
|
|
85
|
+
for p in paths:
|
|
86
|
+
print(f" {p}")
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
if __name__ == "__main__":
|
|
90
|
+
main()
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""Audit: for each starter page, find where the instructions div ACTUALLY closes
|
|
2
|
+
(handling nested </div> tags) and verify the appended text sits right before that close.
|
|
3
|
+
"""
|
|
4
|
+
import os, re
|
|
5
|
+
|
|
6
|
+
STARTERS = [
|
|
7
|
+
"blank_starter", "calculator_starter", "calendar_starter", "chat_starter",
|
|
8
|
+
"checklist_starter", "dashboard_starter", "form_starter", "gallery_starter",
|
|
9
|
+
"generator_starter", "kanban_starter", "presentation_builder", "pulse_starter",
|
|
10
|
+
"quiz_starter", "reference_starter", "roster_starter", "timeline_starter",
|
|
11
|
+
"tutorial_starter",
|
|
12
|
+
]
|
|
13
|
+
LOCATIONS = ["default-pages", ".synthos/pages", "starters"]
|
|
14
|
+
APPEND_TEXT = "Use theme tokens (avoid the natural pallet) unless the user requests an alternative color."
|
|
15
|
+
|
|
16
|
+
OPEN_RE = re.compile(r'<div\b[^>]*>', re.IGNORECASE)
|
|
17
|
+
CLOSE_RE = re.compile(r'</div\s*>', re.IGNORECASE)
|
|
18
|
+
INSTR_OPEN = re.compile(r'<div id="instructions"[^>]*>', re.IGNORECASE)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def find_instructions_close(text: str) -> int | None:
|
|
22
|
+
"""Return index of the </div> that actually closes the instructions div,
|
|
23
|
+
matching nested <div> tags correctly. Returns -1 if not found."""
|
|
24
|
+
m = INSTR_OPEN.search(text)
|
|
25
|
+
if not m:
|
|
26
|
+
return None
|
|
27
|
+
pos = m.end()
|
|
28
|
+
depth = 1
|
|
29
|
+
while pos < len(text) and depth > 0:
|
|
30
|
+
next_open = OPEN_RE.search(text, pos)
|
|
31
|
+
next_close = CLOSE_RE.search(text, pos)
|
|
32
|
+
if not next_close:
|
|
33
|
+
return -1
|
|
34
|
+
if next_open and next_open.start() < next_close.start():
|
|
35
|
+
depth += 1
|
|
36
|
+
pos = next_open.end()
|
|
37
|
+
else:
|
|
38
|
+
depth -= 1
|
|
39
|
+
if depth == 0:
|
|
40
|
+
return next_close.start()
|
|
41
|
+
pos = next_close.end()
|
|
42
|
+
return -1
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def main():
|
|
46
|
+
root = os.path.abspath(os.path.dirname(__file__) + "/..")
|
|
47
|
+
bad = []
|
|
48
|
+
for starter in STARTERS:
|
|
49
|
+
for loc in LOCATIONS:
|
|
50
|
+
p = os.path.join(root, loc, starter, "page.html")
|
|
51
|
+
if not os.path.exists(p):
|
|
52
|
+
continue
|
|
53
|
+
with open(p, "r", encoding="utf-8") as f:
|
|
54
|
+
text = f.read()
|
|
55
|
+
close_idx = find_instructions_close(text)
|
|
56
|
+
if close_idx is None or close_idx < 0:
|
|
57
|
+
bad.append((p, "no-close-found"))
|
|
58
|
+
continue
|
|
59
|
+
# Look back ~200 chars before the close for the appended text.
|
|
60
|
+
window = text[max(0, close_idx - 250):close_idx]
|
|
61
|
+
if APPEND_TEXT not in window:
|
|
62
|
+
# Find ALL occurrences of the phrase and report their offsets vs the real close.
|
|
63
|
+
phrase_at = []
|
|
64
|
+
for m in re.finditer(re.escape(APPEND_TEXT), text):
|
|
65
|
+
phrase_at.append(m.start())
|
|
66
|
+
bad.append((p, f"phrase-not-immediately-before-close (close@{close_idx}, phrase@{phrase_at})"))
|
|
67
|
+
if not bad:
|
|
68
|
+
print("OK — every file has the phrase immediately before the actual instructions-div close.")
|
|
69
|
+
else:
|
|
70
|
+
print(f"BAD — {len(bad)} files need fixing:")
|
|
71
|
+
for p, reason in bad:
|
|
72
|
+
print(f" {p} :: {reason}")
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
if __name__ == "__main__":
|
|
76
|
+
main()
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cleanup script: removes embedded shell markup from page HTML files.
|
|
3
|
+
*
|
|
4
|
+
* Removes:
|
|
5
|
+
* - .shell-toolbar div
|
|
6
|
+
* - .chat-panel div
|
|
7
|
+
* - #loadingOverlay div
|
|
8
|
+
* - script#page-helpers
|
|
9
|
+
* - script#page-script
|
|
10
|
+
*
|
|
11
|
+
* Usage: node scripts/cleanup-shell-markup.mjs [--dry-run]
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { load } from 'cheerio';
|
|
15
|
+
import { readFileSync, writeFileSync, existsSync } from 'fs';
|
|
16
|
+
import { resolve, join } from 'path';
|
|
17
|
+
import { fileURLToPath } from 'url';
|
|
18
|
+
|
|
19
|
+
const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
|
20
|
+
const root = resolve(__dirname, '..');
|
|
21
|
+
const dryRun = process.argv.includes('--dry-run');
|
|
22
|
+
|
|
23
|
+
// Collect all page.html files from default-pages and .synthos/pages
|
|
24
|
+
const dirs = [
|
|
25
|
+
join(root, 'default-pages'),
|
|
26
|
+
join(root, '.synthos', 'pages'),
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
let totalFiles = 0;
|
|
30
|
+
let modifiedFiles = 0;
|
|
31
|
+
let skippedFiles = 0;
|
|
32
|
+
|
|
33
|
+
for (const baseDir of dirs) {
|
|
34
|
+
if (!existsSync(baseDir)) continue;
|
|
35
|
+
|
|
36
|
+
const entries = (await import('fs')).readdirSync(baseDir, { withFileTypes: true });
|
|
37
|
+
|
|
38
|
+
for (const entry of entries) {
|
|
39
|
+
if (!entry.isDirectory()) continue;
|
|
40
|
+
|
|
41
|
+
const pageFile = join(baseDir, entry.name, 'page.html');
|
|
42
|
+
if (!existsSync(pageFile)) continue;
|
|
43
|
+
|
|
44
|
+
totalFiles++;
|
|
45
|
+
|
|
46
|
+
const original = readFileSync(pageFile, 'utf-8');
|
|
47
|
+
const $ = load(original, { decodeEntities: false, xml: false });
|
|
48
|
+
|
|
49
|
+
let changed = false;
|
|
50
|
+
|
|
51
|
+
// Remove .shell-toolbar
|
|
52
|
+
const toolbar = $('.shell-toolbar');
|
|
53
|
+
if (toolbar.length) {
|
|
54
|
+
toolbar.remove();
|
|
55
|
+
changed = true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Remove .chat-panel
|
|
59
|
+
const chatPanel = $('.chat-panel');
|
|
60
|
+
if (chatPanel.length) {
|
|
61
|
+
chatPanel.remove();
|
|
62
|
+
changed = true;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Remove #loadingOverlay
|
|
66
|
+
const loadingOverlay = $('#loadingOverlay');
|
|
67
|
+
if (loadingOverlay.length) {
|
|
68
|
+
loadingOverlay.remove();
|
|
69
|
+
changed = true;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Remove script#page-helpers
|
|
73
|
+
const pageHelpers = $('script#page-helpers');
|
|
74
|
+
if (pageHelpers.length) {
|
|
75
|
+
pageHelpers.remove();
|
|
76
|
+
changed = true;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Remove script#page-script
|
|
80
|
+
const pageScript = $('script#page-script');
|
|
81
|
+
if (pageScript.length) {
|
|
82
|
+
pageScript.remove();
|
|
83
|
+
changed = true;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (!changed) {
|
|
87
|
+
skippedFiles++;
|
|
88
|
+
console.log(` SKIP ${pageFile.replace(root, '.')} (already clean)`);
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Get the updated HTML
|
|
93
|
+
let result = $.html();
|
|
94
|
+
|
|
95
|
+
// Clean up blank lines left by removals (collapse 3+ newlines to 2)
|
|
96
|
+
result = result.replace(/\n{3,}/g, '\n\n');
|
|
97
|
+
|
|
98
|
+
// Clean up leading whitespace-only lines inside <body>
|
|
99
|
+
result = result.replace(/<body>\s*\n\s*\n/, '<body>\n');
|
|
100
|
+
|
|
101
|
+
if (dryRun) {
|
|
102
|
+
console.log(` WOULD ${pageFile.replace(root, '.')}`);
|
|
103
|
+
} else {
|
|
104
|
+
writeFileSync(pageFile, result, 'utf-8');
|
|
105
|
+
console.log(` CLEAN ${pageFile.replace(root, '.')}`);
|
|
106
|
+
}
|
|
107
|
+
modifiedFiles++;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
console.log(`\nDone. ${totalFiles} files scanned, ${modifiedFiles} modified, ${skippedFiles} already clean.`);
|
|
112
|
+
if (dryRun) console.log('(dry run — no files were written)');
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "buffer",
|
|
3
|
+
"name": "Buffer",
|
|
4
|
+
"category": "Social",
|
|
5
|
+
"description": "Schedule and publish posts to social channels (X, Instagram, LinkedIn, Facebook, Threads, Bluesky, YouTube, Pinterest, Mastodon, Google Business) and manage content ideas via the Buffer GraphQL API.",
|
|
6
|
+
"baseUrl": "https://api.buffer.com",
|
|
7
|
+
"authStrategy": "bearer",
|
|
8
|
+
"authKey": "Authorization",
|
|
9
|
+
"fields": [
|
|
10
|
+
{ "name": "apiKey", "label": "API Key", "type": "password" }
|
|
11
|
+
],
|
|
12
|
+
"hints": [
|
|
13
|
+
"GraphQL API — single endpoint. Always POST to path \"/\" (the base URL itself) with body: { query: \"...\", variables: { ... } }.",
|
|
14
|
+
"Every response is HTTP 200. Check `errors` array for system errors (UNAUTHORIZED, NOT_FOUND, RATE_LIMIT_EXCEEDED, etc.) and check the typed response shape for mutation errors.",
|
|
15
|
+
"Typical flow: 1) get organizationId from account, 2) list channels for that org, 3) create posts on a channel or ideas on the org.",
|
|
16
|
+
"Get account + organizations:",
|
|
17
|
+
" query { account { id email organizations { id name } } }",
|
|
18
|
+
"List channels for an organization:",
|
|
19
|
+
" query($orgId: String!) { channels(input: { organizationId: $orgId }) { id name service } }",
|
|
20
|
+
" `service` is the platform: twitter, instagram, facebook, linkedin, threads, bluesky, youtube, pinterest, mastodon, googlebusiness.",
|
|
21
|
+
"Create a post (add to queue):",
|
|
22
|
+
" mutation($input: CreatePostInput!) { createPost(input: $input) { ... on PostActionSuccess { post { id text dueAt } } ... on MutationError { message } } }",
|
|
23
|
+
" variables: { input: { text: \"...\", channelId: \"<id>\", schedulingType: automatic, mode: addToQueue } }",
|
|
24
|
+
"Create a post at a specific time: set mode: customScheduled and dueAt: \"2026-03-10T15:00:00.000Z\" (ISO 8601 UTC).",
|
|
25
|
+
"Post immediately: set mode: now.",
|
|
26
|
+
"ALWAYS include `... on MutationError { message }` as a catch-all in every mutation — covers current and future error types.",
|
|
27
|
+
"Posts are per-channel: to publish to multiple channels, send one createPost mutation per channelId.",
|
|
28
|
+
"List queued/sent posts (cursor pagination):",
|
|
29
|
+
" query($orgId: String!, $after: String) { posts(first: 20, after: $after, input: { organizationId: $orgId, filter: { status: [scheduled], channelIds: [\"<id>\"] } }) { edges { node { id text status dueAt channelId } } pageInfo { hasNextPage endCursor } } }",
|
|
30
|
+
" Pass `endCursor` from the previous response as `after` to fetch the next page. Cursors are opaque — do not parse them.",
|
|
31
|
+
"Create an idea (org-level draft, no channel yet):",
|
|
32
|
+
" mutation($input: IdeaCreationInput!) { createIdea(input: $input) { ... on Idea { id content { title text } } ... on MutationError { message } } }",
|
|
33
|
+
"Rate limits: 100 requests / 15 minutes per client; 2000 / 15 minutes account-wide. On RATE_LIMIT_EXCEEDED check extensions.retryAfter (seconds) before retrying.",
|
|
34
|
+
"Query limits: max complexity 175,000 points, max depth 25, max 30 aliases, max 50 directives, max 15,000 tokens — keep queries flat and request only the fields you need.",
|
|
35
|
+
"IMPORTANT: Do NOT include the API key in body or query params — the proxy attaches the Authorization: Bearer header automatically."
|
|
36
|
+
],
|
|
37
|
+
"onboarding": {
|
|
38
|
+
"url": "https://publish.buffer.com/settings/api",
|
|
39
|
+
"steps": [
|
|
40
|
+
"Log in to your Buffer account at buffer.com",
|
|
41
|
+
"Go to publish.buffer.com/settings/api",
|
|
42
|
+
"Create a new API key",
|
|
43
|
+
"Copy the key"
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
}
|