synthos 0.6.0 → 0.7.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.
Files changed (149) hide show
  1. package/README.md +33 -1
  2. package/default-pages/app_builder.html +40 -0
  3. package/default-pages/app_builder.json +1 -0
  4. package/default-pages/json_tools.html +89 -159
  5. package/default-pages/json_tools.json +1 -0
  6. package/default-pages/my_notes.html +33 -0
  7. package/default-pages/my_notes.json +12 -0
  8. package/default-pages/neon_asteroids.html +77 -0
  9. package/default-pages/neon_asteroids.json +12 -0
  10. package/default-pages/sidebar_builder.html +49 -0
  11. package/default-pages/sidebar_builder.json +1 -0
  12. package/default-pages/solar_explorer.html +1956 -0
  13. package/default-pages/solar_explorer.json +12 -0
  14. package/default-pages/solar_tutorial.html +476 -0
  15. package/default-pages/solar_tutorial.json +1 -0
  16. package/default-pages/two-panel_builder.html +66 -0
  17. package/default-pages/two-panel_builder.json +1 -0
  18. package/dist/connectors/index.d.ts +3 -0
  19. package/dist/connectors/index.d.ts.map +1 -0
  20. package/dist/connectors/index.js +6 -0
  21. package/dist/connectors/index.js.map +1 -0
  22. package/dist/connectors/registry.d.ts +3 -0
  23. package/dist/connectors/registry.d.ts.map +1 -0
  24. package/dist/connectors/registry.js +100 -0
  25. package/dist/connectors/registry.js.map +1 -0
  26. package/dist/connectors/types.d.ts +61 -0
  27. package/dist/connectors/types.d.ts.map +1 -0
  28. package/dist/connectors/types.js +3 -0
  29. package/dist/connectors/types.js.map +1 -0
  30. package/dist/files.d.ts +2 -0
  31. package/dist/files.d.ts.map +1 -1
  32. package/dist/files.js +12 -1
  33. package/dist/files.js.map +1 -1
  34. package/dist/init.d.ts +8 -1
  35. package/dist/init.d.ts.map +1 -1
  36. package/dist/init.js +155 -3
  37. package/dist/init.js.map +1 -1
  38. package/dist/migrations.d.ts +11 -0
  39. package/dist/migrations.d.ts.map +1 -0
  40. package/dist/migrations.js +281 -0
  41. package/dist/migrations.js.map +1 -0
  42. package/dist/models/index.d.ts +3 -0
  43. package/dist/models/index.d.ts.map +1 -0
  44. package/dist/models/index.js +10 -0
  45. package/dist/models/index.js.map +1 -0
  46. package/dist/models/providers.d.ts +7 -0
  47. package/dist/models/providers.d.ts.map +1 -0
  48. package/dist/models/providers.js +33 -0
  49. package/dist/models/providers.js.map +1 -0
  50. package/dist/models/types.d.ts +21 -0
  51. package/dist/models/types.d.ts.map +1 -0
  52. package/dist/models/types.js +3 -0
  53. package/dist/models/types.js.map +1 -0
  54. package/dist/pages.d.ts +21 -2
  55. package/dist/pages.d.ts.map +1 -1
  56. package/dist/pages.js +202 -23
  57. package/dist/pages.js.map +1 -1
  58. package/dist/scripts.js +2 -2
  59. package/dist/scripts.js.map +1 -1
  60. package/dist/service/createCompletePrompt.d.ts +3 -2
  61. package/dist/service/createCompletePrompt.d.ts.map +1 -1
  62. package/dist/service/createCompletePrompt.js +11 -16
  63. package/dist/service/createCompletePrompt.js.map +1 -1
  64. package/dist/service/debugLog.d.ts +11 -0
  65. package/dist/service/debugLog.d.ts.map +1 -0
  66. package/dist/service/debugLog.js +26 -0
  67. package/dist/service/debugLog.js.map +1 -0
  68. package/dist/service/modelInstructions.d.ts +7 -0
  69. package/dist/service/modelInstructions.d.ts.map +1 -0
  70. package/dist/service/modelInstructions.js +16 -0
  71. package/dist/service/modelInstructions.js.map +1 -0
  72. package/dist/service/requiresSettings.d.ts +2 -2
  73. package/dist/service/requiresSettings.d.ts.map +1 -1
  74. package/dist/service/requiresSettings.js.map +1 -1
  75. package/dist/service/server.d.ts.map +1 -1
  76. package/dist/service/server.js +15 -0
  77. package/dist/service/server.js.map +1 -1
  78. package/dist/service/transformPage.d.ts +81 -2
  79. package/dist/service/transformPage.d.ts.map +1 -1
  80. package/dist/service/transformPage.js +672 -82
  81. package/dist/service/transformPage.js.map +1 -1
  82. package/dist/service/useApiRoutes.d.ts.map +1 -1
  83. package/dist/service/useApiRoutes.js +579 -13
  84. package/dist/service/useApiRoutes.js.map +1 -1
  85. package/dist/service/useConnectorRoutes.d.ts +4 -0
  86. package/dist/service/useConnectorRoutes.d.ts.map +1 -0
  87. package/dist/service/useConnectorRoutes.js +389 -0
  88. package/dist/service/useConnectorRoutes.js.map +1 -0
  89. package/dist/service/useDataRoutes.d.ts.map +1 -1
  90. package/dist/service/useDataRoutes.js +83 -70
  91. package/dist/service/useDataRoutes.js.map +1 -1
  92. package/dist/service/usePageRoutes.d.ts.map +1 -1
  93. package/dist/service/usePageRoutes.js +243 -38
  94. package/dist/service/usePageRoutes.js.map +1 -1
  95. package/dist/settings.d.ts +33 -4
  96. package/dist/settings.d.ts.map +1 -1
  97. package/dist/settings.js +108 -15
  98. package/dist/settings.js.map +1 -1
  99. package/dist/synthos-cli.d.ts.map +1 -1
  100. package/dist/synthos-cli.js +11 -1
  101. package/dist/synthos-cli.js.map +1 -1
  102. package/dist/themes.d.ts +9 -0
  103. package/dist/themes.d.ts.map +1 -0
  104. package/dist/themes.js +64 -0
  105. package/dist/themes.js.map +1 -0
  106. package/package.json +5 -3
  107. package/required-pages/builder.html +74 -0
  108. package/required-pages/builder.json +1 -0
  109. package/required-pages/pages.html +169 -126
  110. package/required-pages/pages.json +1 -0
  111. package/required-pages/settings.html +812 -156
  112. package/required-pages/settings.json +1 -0
  113. package/required-pages/synthos_apis.html +272 -0
  114. package/required-pages/synthos_apis.json +1 -0
  115. package/required-pages/synthos_scripts.html +87 -0
  116. package/required-pages/synthos_scripts.json +1 -0
  117. package/src/connectors/index.ts +12 -0
  118. package/src/connectors/registry.ts +98 -0
  119. package/src/connectors/types.ts +68 -0
  120. package/src/files.ts +11 -0
  121. package/src/init.ts +151 -5
  122. package/src/migrations.ts +266 -0
  123. package/src/models/index.ts +2 -0
  124. package/src/models/providers.ts +33 -0
  125. package/src/models/types.ts +23 -0
  126. package/src/pages.ts +234 -26
  127. package/src/scripts.ts +2 -2
  128. package/src/service/createCompletePrompt.ts +14 -18
  129. package/src/service/debugLog.ts +17 -0
  130. package/src/service/modelInstructions.ts +14 -0
  131. package/src/service/requiresSettings.ts +3 -3
  132. package/src/service/server.ts +19 -2
  133. package/src/service/transformPage.ts +709 -88
  134. package/src/service/useApiRoutes.ts +632 -16
  135. package/src/service/useConnectorRoutes.ts +427 -0
  136. package/src/service/useDataRoutes.ts +87 -71
  137. package/src/service/usePageRoutes.ts +237 -44
  138. package/src/settings.ts +143 -20
  139. package/src/synthos-cli.ts +11 -1
  140. package/src/themes.ts +71 -0
  141. package/default-pages/[application].html +0 -95
  142. package/default-pages/[markdown].html +0 -271
  143. package/default-pages/[sidebar].html +0 -114
  144. package/default-pages/[split-application].html +0 -118
  145. package/default-pages/solar_system.html +0 -432
  146. package/default-pages/space_invaders.html +0 -617
  147. package/required-pages/apis.html +0 -362
  148. package/required-pages/home.html +0 -126
  149. package/required-pages/scripts.html +0 -350
package/dist/settings.js CHANGED
@@ -3,27 +3,102 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.saveSettings = exports.loadSettings = exports.hasConfiguredSettings = exports.DefaultSettings = void 0;
6
+ exports.saveSettings = exports.loadSettings = exports.hasConfiguredSettings = exports.getModelEntry = exports.DefaultSettings = void 0;
7
7
  const files_1 = require("./files");
8
8
  const path_1 = __importDefault(require("path"));
9
+ const models_1 = require("./models");
9
10
  let _settings;
10
11
  exports.DefaultSettings = {
11
- serviceApiKey: '',
12
- model: '',
13
- maxTokens: 32000,
14
- imageQuality: 'standard',
15
- instructions: '',
16
- logCompletions: false
12
+ version: 2,
13
+ theme: 'nebula-dawn',
14
+ models: [
15
+ {
16
+ use: 'builder',
17
+ provider: 'Anthropic',
18
+ configuration: { apiKey: '', model: '', maxTokens: 32000 },
19
+ imageQuality: 'standard',
20
+ instructions: '',
21
+ logCompletions: false,
22
+ },
23
+ {
24
+ use: 'chat',
25
+ provider: 'Anthropic',
26
+ configuration: { apiKey: '', model: '', maxTokens: 32000 },
27
+ imageQuality: 'standard',
28
+ instructions: '',
29
+ logCompletions: false,
30
+ },
31
+ ],
32
+ features: [],
33
+ services: {},
34
+ connectors: {}
17
35
  };
36
+ /**
37
+ * Find a model entry by its `use` field. Falls back to default if not found.
38
+ */
39
+ function getModelEntry(settings, use) {
40
+ const entry = settings.models.find(m => m.use === use);
41
+ if (entry)
42
+ return entry;
43
+ return exports.DefaultSettings.models.find(m => m.use === use);
44
+ }
45
+ exports.getModelEntry = getModelEntry;
46
+ /**
47
+ * Migrate a v1 settings object to v2 by detecting provider from model prefix
48
+ * and wrapping fields into the new configuration object.
49
+ */
50
+ function migrateV1toV2(raw) {
51
+ const v1 = raw;
52
+ const rawModel = v1.model ?? '';
53
+ // Migrate retired model names
54
+ const model = rawModel === 'claude-opus-4-5' ? 'claude-opus-4-6' : rawModel;
55
+ const detected = (0, models_1.detectProvider)(model);
56
+ const provider = detected?.name ?? 'Anthropic';
57
+ // Default chat to claude-haiku-4-5 when migrating from an Anthropic model
58
+ const chatModel = provider === 'Anthropic' ? 'claude-haiku-4-5' : model;
59
+ return {
60
+ version: 2,
61
+ theme: v1.theme ?? 'nebula-dusk',
62
+ models: [
63
+ {
64
+ use: 'builder',
65
+ provider,
66
+ configuration: {
67
+ apiKey: v1.serviceApiKey ?? '',
68
+ model,
69
+ maxTokens: v1.maxTokens ?? 32000,
70
+ },
71
+ imageQuality: v1.imageQuality ?? 'standard',
72
+ instructions: v1.instructions ?? '',
73
+ logCompletions: v1.logCompletions ?? false,
74
+ },
75
+ {
76
+ use: 'chat',
77
+ provider,
78
+ configuration: {
79
+ apiKey: v1.serviceApiKey ?? '',
80
+ model: chatModel,
81
+ maxTokens: v1.maxTokens ?? 32000,
82
+ },
83
+ imageQuality: v1.imageQuality ?? 'standard',
84
+ instructions: v1.instructions ?? '',
85
+ logCompletions: v1.logCompletions ?? false,
86
+ },
87
+ ],
88
+ features: [],
89
+ services: v1.services,
90
+ };
91
+ }
18
92
  async function hasConfiguredSettings(folder) {
19
93
  const settings = await loadSettings(folder);
20
- if (typeof settings.serviceApiKey !== 'string' || settings.serviceApiKey.length == 0) {
94
+ const builder = getModelEntry(settings, 'builder');
95
+ if (typeof builder.configuration.apiKey !== 'string' || builder.configuration.apiKey.length == 0) {
21
96
  return false;
22
97
  }
23
- if (typeof settings.model !== 'string' || settings.model.length == 0) {
98
+ if (typeof builder.configuration.model !== 'string' || builder.configuration.model.length == 0) {
24
99
  return false;
25
100
  }
26
- if (typeof settings.maxTokens !== 'number' || settings.maxTokens <= 0) {
101
+ if (typeof builder.configuration.maxTokens !== 'number' || builder.configuration.maxTokens <= 0) {
27
102
  return false;
28
103
  }
29
104
  return true;
@@ -31,24 +106,42 @@ async function hasConfiguredSettings(folder) {
31
106
  exports.hasConfiguredSettings = hasConfiguredSettings;
32
107
  async function loadSettings(folder) {
33
108
  if (_settings == undefined) {
34
- // Check for file to exist
35
109
  const filename = path_1.default.join(folder, 'settings.json');
36
110
  if (await (0, files_1.checkIfExists)(filename)) {
37
111
  try {
38
- // Load and parse file
39
- _settings = JSON.parse(await (0, files_1.loadFile)(filename));
112
+ const raw = JSON.parse(await (0, files_1.loadFile)(filename));
113
+ if (!raw.version) {
114
+ // V1 file — migrate
115
+ console.log('Migrating settings.json from v1 to v2...');
116
+ const migrated = migrateV1toV2(raw);
117
+ _settings = migrated;
118
+ await (0, files_1.saveFile)(filename, JSON.stringify(migrated, null, 4));
119
+ }
120
+ else {
121
+ _settings = raw;
122
+ }
40
123
  }
41
124
  catch {
42
125
  // Invalid JSON
43
126
  }
44
127
  }
45
128
  }
46
- // Return settings from file
47
- return { ...exports.DefaultSettings, ..._settings };
129
+ const merged = { ...exports.DefaultSettings, ..._settings, models: _settings?.models ?? exports.DefaultSettings.models };
130
+ // Auto-migrate: copy services into connectors if connectors is empty
131
+ const connectors = merged.connectors ?? {};
132
+ const services = merged.services ?? {};
133
+ if (Object.keys(connectors).length === 0 && Object.keys(services).length > 0) {
134
+ merged.connectors = { ...services };
135
+ }
136
+ return merged;
48
137
  }
49
138
  exports.loadSettings = loadSettings;
50
139
  async function saveSettings(folder, settings) {
51
140
  _settings = { ..._settings, ...settings };
141
+ if (settings.models) {
142
+ _settings.models = settings.models;
143
+ }
144
+ _settings.version = 2;
52
145
  await (0, files_1.saveFile)(path_1.default.join(folder, 'settings.json'), JSON.stringify(_settings, null, 4));
53
146
  }
54
147
  exports.saveSettings = saveSettings;
@@ -1 +1 @@
1
- {"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":";;;;;;AAAA,mCAA0D;AAC1D,gDAAwB;AAExB,IAAI,SAAsC,CAAC;AAW9B,QAAA,eAAe,GAAa;IACrC,aAAa,EAAE,EAAE;IACjB,KAAK,EAAE,EAAE;IACT,SAAS,EAAE,KAAK;IAChB,YAAY,EAAE,UAAU;IACxB,YAAY,EAAE,EAAE;IAChB,cAAc,EAAE,KAAK;CACxB,CAAC;AAEK,KAAK,UAAU,qBAAqB,CAAC,MAAc;IACtD,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,OAAO,QAAQ,CAAC,aAAa,KAAK,QAAQ,IAAI,QAAQ,CAAC,aAAa,CAAC,MAAM,IAAI,CAAC,EAAE;QAClF,OAAO,KAAK,CAAC;KAChB;IACD,IAAI,OAAO,QAAQ,CAAC,KAAK,KAAK,QAAQ,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE;QAClE,OAAO,KAAK,CAAC;KAChB;IACD,IAAI,OAAO,QAAQ,CAAC,SAAS,KAAK,QAAQ,IAAI,QAAQ,CAAC,SAAS,IAAI,CAAC,EAAE;QACnE,OAAO,KAAK,CAAC;KAChB;IAED,OAAO,IAAI,CAAC;AAChB,CAAC;AAbD,sDAaC;AAEM,KAAK,UAAU,YAAY,CAAC,MAAc;IAC7C,IAAI,SAAS,IAAI,SAAS,EAAE;QACxB,0BAA0B;QAC1B,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;QACpD,IAAI,MAAM,IAAA,qBAAa,EAAC,QAAQ,CAAC,EAAE;YAC/B,IAAI;gBACA,sBAAsB;gBACtB,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,IAAA,gBAAQ,EAAC,QAAQ,CAAC,CAAC,CAAC;aACpD;YAAC,MAAM;gBACJ,eAAe;aAClB;SACJ;KACJ;IAED,4BAA4B;IAC5B,OAAO,EAAC,GAAG,uBAAe,EAAE,GAAG,SAAS,EAAC,CAAC;AAC9C,CAAC;AAhBD,oCAgBC;AAEM,KAAK,UAAU,YAAY,CAAC,MAAc,EAAE,QAA2B;IAC1E,SAAS,GAAG,EAAC,GAAG,SAAS,EAAE,GAAG,QAAQ,EAAC,CAAC;IACxC,MAAM,IAAA,gBAAQ,EAAC,cAAI,CAAC,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC3F,CAAC;AAHD,oCAGC"}
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"synthos-cli.d.ts","sourceRoot":"","sources":["../src/synthos-cli.ts"],"names":[],"mappings":"AAOA,wBAAsB,GAAG,kBA8BxB"}
1
+ {"version":3,"file":"synthos-cli.d.ts","sourceRoot":"","sources":["../src/synthos-cli.ts"],"names":[],"mappings":"AAOA,wBAAsB,GAAG,kBAwCxB"}
@@ -23,10 +23,20 @@ async function run() {
23
23
  describe: `Include default pages when initializing a new .synthos folder.`,
24
24
  type: 'boolean',
25
25
  default: true
26
+ })
27
+ .option('debug', {
28
+ describe: `Log all server requests with timing and page update summaries.`,
29
+ type: 'boolean',
30
+ default: false
31
+ })
32
+ .option('debug-page-updates', {
33
+ describe: `Log model input/output for page transformations to the console.`,
34
+ type: 'boolean',
35
+ default: false
26
36
  })
27
37
  .demandOption([]);
28
38
  }, async (args) => {
29
- const config = (0, init_1.createConfig)();
39
+ const config = (0, init_1.createConfig)('.synthos', { debug: args.debug, debugPageUpdates: args.debugPageUpdates });
30
40
  await (0, init_1.init)(config, args.pages);
31
41
  await (0, service_1.server)(config).listen(args.port, async () => {
32
42
  console.log(`SynthOS server is running on http://localhost:${args.port}`);
@@ -1 +1 @@
1
- {"version":3,"file":"synthos-cli.js","sourceRoot":"","sources":["../src/synthos-cli.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA0B;AAC1B,2CAAwC;AACxC,uCAAmC;AACnC,iCAA4C;AAE5C,MAAM,aAAa,GAAG,IAAI,QAAQ,CAAC,WAAW,EAAE,0BAA0B,CAAC,CAAC;AAErE,KAAK,UAAU,GAAG;IACrB,MAAM,IAAA,eAAK,EAAC,IAAA,iBAAO,EAAC,OAAO,CAAC,IAAI,CAAC,CAAC;SAC7B,UAAU,CAAC,SAAS,CAAC;SACrB,OAAO,CAAC,OAAO,EAAE,4BAA4B,EAAE,CAAC,KAAK,EAAE,EAAE;QACtD,OAAO,KAAK;aACP,MAAM,CAAC,MAAM,EAAE;YACZ,QAAQ,EAAE,yBAAyB;YACnC,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,IAAI;SAChB,CAAC;aACD,MAAM,CAAC,OAAO,EAAE;YACb,QAAQ,EAAE,gEAAgE;YAC1E,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,IAAI;SAChB,CAAC;aACD,YAAY,CAAC,EAAE,CAAC,CAAC;IAC1B,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACd,MAAM,MAAM,GAAG,IAAA,mBAAY,GAAE,CAAC;QAC9B,MAAM,IAAA,WAAI,EAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/B,MAAM,IAAA,gBAAM,EAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE;YAC9C,OAAO,CAAC,GAAG,CAAC,iDAAiD,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YAE1E,6BAA6B;YAC7B,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC;YACzC,IAAI,CAAC,OAAO,CAAC,oBAAoB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;IACP,CAAC,CAAC;SACD,IAAI,EAAE;SACN,aAAa,EAAE;SACf,UAAU,EAAE,CAAC;AACtB,CAAC;AA9BD,kBA8BC"}
1
+ {"version":3,"file":"synthos-cli.js","sourceRoot":"","sources":["../src/synthos-cli.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA0B;AAC1B,2CAAwC;AACxC,uCAAmC;AACnC,iCAA4C;AAE5C,MAAM,aAAa,GAAG,IAAI,QAAQ,CAAC,WAAW,EAAE,0BAA0B,CAAC,CAAC;AAErE,KAAK,UAAU,GAAG;IACrB,MAAM,IAAA,eAAK,EAAC,IAAA,iBAAO,EAAC,OAAO,CAAC,IAAI,CAAC,CAAC;SAC7B,UAAU,CAAC,SAAS,CAAC;SACrB,OAAO,CAAC,OAAO,EAAE,4BAA4B,EAAE,CAAC,KAAK,EAAE,EAAE;QACtD,OAAO,KAAK;aACP,MAAM,CAAC,MAAM,EAAE;YACZ,QAAQ,EAAE,yBAAyB;YACnC,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,IAAI;SAChB,CAAC;aACD,MAAM,CAAC,OAAO,EAAE;YACb,QAAQ,EAAE,gEAAgE;YAC1E,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,IAAI;SAChB,CAAC;aACD,MAAM,CAAC,OAAO,EAAE;YACb,QAAQ,EAAE,gEAAgE;YAC1E,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,KAAK;SACjB,CAAC;aACD,MAAM,CAAC,oBAAoB,EAAE;YAC1B,QAAQ,EAAE,iEAAiE;YAC3E,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,KAAK;SACjB,CAAC;aACD,YAAY,CAAC,EAAE,CAAC,CAAC;IAC1B,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACd,MAAM,MAAM,GAAG,IAAA,mBAAY,EAAC,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;QACxG,MAAM,IAAA,WAAI,EAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/B,MAAM,IAAA,gBAAM,EAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE;YAC9C,OAAO,CAAC,GAAG,CAAC,iDAAiD,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YAE1E,6BAA6B;YAC7B,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC;YACzC,IAAI,CAAC,OAAO,CAAC,oBAAoB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;IACP,CAAC,CAAC;SACD,IAAI,EAAE;SACN,aAAa,EAAE;SACf,UAAU,EAAE,CAAC;AACtB,CAAC;AAxCD,kBAwCC"}
@@ -0,0 +1,9 @@
1
+ import { SynthOSConfig } from './init';
2
+ export interface ThemeInfo {
3
+ mode: 'light' | 'dark';
4
+ colors: Record<string, string>;
5
+ }
6
+ export declare function loadThemeInfo(name: string, config: SynthOSConfig): Promise<ThemeInfo | undefined>;
7
+ export declare function loadTheme(name: string, config: SynthOSConfig): Promise<string | undefined>;
8
+ export declare function listThemes(config: SynthOSConfig): Promise<string[]>;
9
+ //# sourceMappingURL=themes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"themes.d.ts","sourceRoot":"","sources":["../src/themes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAEvC,MAAM,WAAW,SAAS;IACtB,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAMD,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAevG;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAahG;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAyBzE"}
package/dist/themes.js ADDED
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.listThemes = exports.loadTheme = exports.loadThemeInfo = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ const files_1 = require("./files");
9
+ function userThemesFolder(config) {
10
+ return path_1.default.join(config.pagesFolder, 'themes');
11
+ }
12
+ async function loadThemeInfo(name, config) {
13
+ // Check user's local themes first, then fall back to package defaults
14
+ const localPath = path_1.default.join(userThemesFolder(config), `${name}.json`);
15
+ if (await (0, files_1.checkIfExists)(localPath)) {
16
+ const raw = await (0, files_1.loadFile)(localPath);
17
+ return raw ? JSON.parse(raw) : undefined;
18
+ }
19
+ const defaultPath = path_1.default.join(config.defaultThemesFolder, `${name}.json`);
20
+ if (await (0, files_1.checkIfExists)(defaultPath)) {
21
+ const raw = await (0, files_1.loadFile)(defaultPath);
22
+ return raw ? JSON.parse(raw) : undefined;
23
+ }
24
+ return undefined;
25
+ }
26
+ exports.loadThemeInfo = loadThemeInfo;
27
+ async function loadTheme(name, config) {
28
+ // Check user's local themes first, then fall back to package defaults
29
+ const localPath = path_1.default.join(userThemesFolder(config), `${name}.css`);
30
+ if (await (0, files_1.checkIfExists)(localPath)) {
31
+ return await (0, files_1.loadFile)(localPath);
32
+ }
33
+ const defaultPath = path_1.default.join(config.defaultThemesFolder, `${name}.css`);
34
+ if (await (0, files_1.checkIfExists)(defaultPath)) {
35
+ return await (0, files_1.loadFile)(defaultPath);
36
+ }
37
+ return undefined;
38
+ }
39
+ exports.loadTheme = loadTheme;
40
+ async function listThemes(config) {
41
+ const names = new Set();
42
+ // Collect from user's local themes folder
43
+ const localFolder = userThemesFolder(config);
44
+ if (await (0, files_1.checkIfExists)(localFolder)) {
45
+ const files = await (0, files_1.listFiles)(localFolder);
46
+ for (const f of files) {
47
+ if (f.endsWith('.css')) {
48
+ names.add(f.replace(/\.css$/, ''));
49
+ }
50
+ }
51
+ }
52
+ // Collect from package defaults
53
+ if (await (0, files_1.checkIfExists)(config.defaultThemesFolder)) {
54
+ const files = await (0, files_1.listFiles)(config.defaultThemesFolder);
55
+ for (const f of files) {
56
+ if (f.endsWith('.css')) {
57
+ names.add(f.replace(/\.css$/, ''));
58
+ }
59
+ }
60
+ }
61
+ return Array.from(names).sort();
62
+ }
63
+ exports.listThemes = listThemes;
64
+ //# sourceMappingURL=themes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"themes.js","sourceRoot":"","sources":["../src/themes.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "synthos",
3
3
  "author": "Steven Ickman",
4
4
  "description": "An AI powered shell experience.",
5
- "version": "0.6.0",
5
+ "version": "0.7.0",
6
6
  "license": "MIT",
7
7
  "keywords": [
8
8
  "synthos",
@@ -20,6 +20,7 @@
20
20
  "bin": "./bin/synthos.js",
21
21
  "dependencies": {
22
22
  "agentm-core": "0.7.2",
23
+ "cheerio": "^1.2.0",
23
24
  "express": "^4.19.2",
24
25
  "open": "^10.1.0",
25
26
  "openai": "^4.57.0",
@@ -28,6 +29,7 @@
28
29
  },
29
30
  "devDependencies": {
30
31
  "@types/assert": "^1.5.3",
32
+ "@types/cheerio": "^0.22.35",
31
33
  "@types/express": "^4.17.21",
32
34
  "@types/mocha": "^8.2.0",
33
35
  "@types/node": "^14.14.31",
@@ -43,8 +45,8 @@
43
45
  "build": "tsc -b",
44
46
  "clean": "rimraf dist tsconfig.tsbuildinfo node_modules",
45
47
  "start": "node ./bin/synthos.js",
46
- "test": "npm-run-all build test:mocha",
47
- "test:mocha": "nyc mocha tests"
48
+ "test": "npm run build && npm run test:mocha",
49
+ "test:mocha": "nyc ts-mocha tests/**/*.spec.ts"
48
50
  },
49
51
  "files": [
50
52
  "dist",
@@ -0,0 +1,74 @@
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</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>.idle-container{position:absolute;width:100%;height:100%;pointer-events:none;opacity:1;transition:opacity 1s ease-out}.idle-container.hidden{opacity:0}.breathing-orb{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:80px;height:80px;border-radius:50%;background:radial-gradient(circle,rgba(102,126,234,.15) 0,transparent 70%);animation:4s ease-in-out infinite breathe}.breathing-orb::before{content:'';position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:8px;height:8px;border-radius:50%;background:rgba(183,148,246,.6);box-shadow:0 0 20px rgba(183,148,246,.4);animation:4s ease-in-out infinite core-pulse}@keyframes breathe{0%,100%{width:80px;height:80px;opacity:.3}50%{width:120px;height:120px;opacity:.6}}@keyframes core-pulse{0%,100%{opacity:.4;box-shadow:0 0 20px rgba(183,148,246,.3)}50%{opacity:.8;box-shadow:0 0 30px rgba(183,148,246,.5)}}.orbit-ring{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:200px;height:200px;border:1px solid rgba(102,126,234,.1);border-radius:50%;animation:20s linear infinite orbit-rotate}.orbit-ring::after{content:'';position:absolute;top:-3px;left:50%;transform:translateX(-50%);width:6px;height:6px;background:rgba(240,147,251,.5);border-radius:50%;box-shadow:0 0 10px rgba(240,147,251,.3)}@keyframes orbit-rotate{from{transform:translate(-50%,-50%) rotate(0)}to{transform:translate(-50%,-50%) rotate(360deg)}}</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 id="page-info" src="/api/page-info.js?page=builder"></script>
12
+ </head>
13
+ <body>
14
+ <div class="chat-panel" data-locked="true">
15
+ <div class="chat-header" data-locked="true">SynthOS</div>
16
+ <div class="chat-messages" id="chatMessages" data-locked="true">
17
+ <div class="chat-message" id="defaultGreeting"><strong>SynthOS:</strong> What can I create for you? Ask "what can you do?" or "how does this work?" to learn more. Remember to save often!</div>
18
+ <div class="chat-message" id="firstRunGreeting" style="display:none;">
19
+ <p><strong>Welcome to SynthOS!</strong></p>
20
+ <p>You're all set up and ready to start creating. This is the <strong>Builder</strong> — your main workspace. Just type what you want to build into the chat and SynthOS will generate it for you as a live, interactive page.</p>
21
+ <p>You can create just about anything: dashboards, tools, games, visualizations, forms, calculators — if it can be expressed as a web page, you can build it here through conversation.</p>
22
+ <p><strong>How pages work:</strong></p>
23
+ <ul>
24
+ <li>Each creation lives on its own <strong>page</strong>. When you save, it gets a name and becomes part of your collection.</li>
25
+ <li>The <strong>Pages</strong> button (in the link bar above) takes you to the <strong>Pages Gallery</strong> where you can browse, open, and manage all your saved creations.</li>
26
+ </ul>
27
+ <p><strong>Key actions:</strong></p>
28
+ <ul>
29
+ <li><strong>Save</strong> — saves your current page. You'll be prompted for a name the first time. <em>Save often!</em> Your work only persists when you save it.</li>
30
+ <li><strong>Reset</strong> — clears the current page back to a blank slate. Useful when you want to start fresh on something new.</li>
31
+ </ul>
32
+ <p>When you're ready, we recommend trying the <a href="/solar_tutorial">Solar Tutorial</a> — it's a guided walkthrough that will show you the basics of creating with SynthOS step by step.</p>
33
+ <p>Have fun building!</p>
34
+ </div>
35
+ </div>
36
+ <div class="link-group" data-locked="true">
37
+ <a href="#" id="saveLink" data-locked="true">Save</a>
38
+ <a href="/pages" id="pagesLink" data-locked="true">Pages</a>
39
+ <a href="#" id="resetLink" data-locked="true">Reset</a>
40
+ </div>
41
+ <form action="/" method="POST" id="chatForm" data-locked="true">
42
+ <input type="text" class="chat-input" id="chatInput" name="message" placeholder="Type a message..." data-locked="true">
43
+ <button type="submit" class="chat-submit" data-locked="true">Send</button>
44
+ </form>
45
+ </div>
46
+ <div class="viewer-panel" id="viewerPanel">
47
+ <div class="idle-container" id="idleAnimation">
48
+ <div class="orbit-ring"></div>
49
+ <div class="breathing-orb"></div>
50
+ </div>
51
+ <div id="loadingOverlay" class="loading-overlay"><div class="spinner"></div></div>
52
+ </div>
53
+ <div id="instructions" style="display: none;" data-locked="true"></div>
54
+ <div id="thoughts" style="display: none;" data-locked="true"></div>
55
+ <script id="idle-animation">function hideIdleAnimation(){const idleContainer=document.getElementById("idleAnimation");idleContainer&&(idleContainer.classList.add("hidden"),setTimeout(()=>{idleContainer.style.display="none"},1e3))}function showIdleAnimation(){const idleContainer=document.getElementById("idleAnimation");idleContainer&&(idleContainer.style.display="block",setTimeout(()=>{idleContainer.classList.remove("hidden")},10))}</script>
56
+ <button class="chat-toggle" aria-label="Toggle chat panel">
57
+ <span class="chat-toggle-dots">
58
+ <span class="chat-toggle-dot"></span>
59
+ <span class="chat-toggle-dot"></span>
60
+ <span class="chat-toggle-dot"></span>
61
+ </span>
62
+ </button>
63
+ <script id="first-run-check">
64
+ (function() {
65
+ var params = new URLSearchParams(window.location.search);
66
+ if (params.get('firstRun') === 'true') {
67
+ document.getElementById('defaultGreeting').style.display = 'none';
68
+ document.getElementById('firstRunGreeting').style.display = '';
69
+ }
70
+ })();
71
+ </script>
72
+ <script id="page-helpers" src="/api/page-helpers.js?v=2" data-locked="true"></script>
73
+ <script id="page-script" src="/api/page-script.js?v=2" data-locked="true"></script>
74
+ </body></html>
@@ -0,0 +1 @@
1
+ { "title": "Builder", "categories": ["System"], "pinned": true, "showInAll": true, "pageVersion": 2, "mode": "unlockedS" }