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
@@ -0,0 +1,281 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.postProcessV2 = exports.migratePage = void 0;
27
+ const cheerio = __importStar(require("cheerio"));
28
+ const transformPage_1 = require("./service/transformPage");
29
+ /**
30
+ * Registry of migration functions: fromVersion -> transform.
31
+ * Each function transforms page HTML from version N to version N+1.
32
+ */
33
+ const migrations = {
34
+ 1: migrateV1toV2,
35
+ };
36
+ /**
37
+ * Migrate a page's HTML from one version to another by applying
38
+ * sequential migration steps.
39
+ */
40
+ async function migratePage(html, fromVersion, toVersion, completePrompt) {
41
+ let current = html;
42
+ for (let v = fromVersion; v < toVersion; v++) {
43
+ const migrate = migrations[v];
44
+ if (!migrate) {
45
+ throw new Error(`No migration defined for version ${v} -> ${v + 1}`);
46
+ }
47
+ current = await migrate(current, completePrompt);
48
+ }
49
+ return current;
50
+ }
51
+ exports.migratePage = migratePage;
52
+ /** CSS classes that belong to the shared theme and must NOT appear in page-specific <style> blocks. */
53
+ const SHARED_CSS_SELECTORS = [
54
+ '*',
55
+ 'body',
56
+ '.chat-panel',
57
+ '.chat-header',
58
+ '.chat-messages',
59
+ '.chat-message',
60
+ '.chat-message p',
61
+ '.chat-message strong',
62
+ '.chat-message pre',
63
+ '.chat-message code',
64
+ '.chat-message a',
65
+ '.link-group',
66
+ '.link-group a',
67
+ 'form',
68
+ '.chat-input',
69
+ '.chat-submit',
70
+ '.loading-overlay',
71
+ '.spinner',
72
+ '.viewer-panel',
73
+ '#loadingOverlay',
74
+ '.chat-submit:disabled',
75
+ '.chat-input:disabled',
76
+ ];
77
+ const V1_TO_V2_SYSTEM_PROMPT = `You are a code migration tool. You convert SynthOS v1 pages to v2 format.
78
+
79
+ ## Rules — What to REMOVE
80
+
81
+ 1. **Shared CSS rules** — Remove CSS rules that match these selectors **exactly** (they are now in theme.css):
82
+ \`*\`, \`body\`, \`.chat-panel\`, \`.chat-header\`, \`.chat-messages\`, \`.chat-message\` (and descendants like \`.chat-message p\`, \`.chat-message strong\`, \`.chat-message pre\`, \`.chat-message code\`, \`.chat-message a\`), \`.link-group\`, \`.link-group a\`, \`form\`, \`.chat-input\`, \`.chat-submit\`, \`.loading-overlay\`, \`.spinner\`, \`.viewer-panel\`, \`#loadingOverlay\`, \`.chat-submit:disabled\`, \`.chat-input:disabled\`
83
+ Also remove any \`@keyframes spin\` and scrollbar pseudo-element rules (\`::-webkit-scrollbar\`, \`::-webkit-scrollbar-track\`, \`::-webkit-scrollbar-thumb\`).
84
+ **Important:** Only remove rules matching these selectors exactly. Do NOT remove pseudo-element variants (\`.viewer-panel::before\`, \`.viewer-panel::after\`), pseudo-class variants (\`.chat-input:focus\`, \`.chat-submit:hover\`), or any other compound selectors that extend the shared selectors — those are page-specific styles and must be preserved. Also preserve any \`@keyframes\` referenced by page-specific rules (e.g. if a page has \`.viewer-panel::before\` using a custom animation, keep that \`@keyframes\`).
85
+
86
+ 2. **Shared inline JS** — Remove these specific code blocks from \`<script>\` tags:
87
+ - \`document.getElementById('chatInput').focus()\` line
88
+ - \`chatForm\` submit event listener (the one with setTimeout and loading overlay)
89
+ - \`saveLink\` click handler
90
+ - \`resetLink\` click handler
91
+ - \`window.onload\` that ONLY scrolls chatMessages (keep other onload logic!)
92
+ - Chat panel toggle IIFE (references \`synthos-chat-collapsed\`)
93
+ - Focus management IIFE (references \`stopImmediatePropagation\`)
94
+ - \`// Basic chat functionality\` comment
95
+
96
+ 3. **Empty \`<script>\` tags** — If a script block becomes empty after stripping, remove it entirely.
97
+
98
+ ## Rules — What to ADD
99
+
100
+ 1. In \`<head>\`, add these two lines right after the \`<title>\` tag (if not already present):
101
+ \`\`\`
102
+ <script src="/api/theme-info.js"></script>
103
+ <link rel="stylesheet" href="/api/theme.css">
104
+ \`\`\`
105
+
106
+ ## Rules — What to TRANSFORM
107
+
108
+ ### Data/Table API migration
109
+ The data API changed from global tables to **page-scoped** tables:
110
+ - Old: \`/api/data/:table\` → New: \`/api/data/:page/:table\`
111
+ - Old: \`/api/data/:table/:id\` → New: \`/api/data/:page/:table/:id\`
112
+ - Tables are now stored as sub-folders of each page's folder.
113
+ - **Raw fetch() calls** must be updated: e.g. \`fetch('/api/data/notes')\` → \`fetch('/api/data/' + pageName + '/notes')\`
114
+ - **synthos.data.\* helpers** handle this automatically — they read the current page name from \`window.pageInfo.name\`. Prefer converting raw fetch data calls to use the helpers instead:
115
+ - \`fetch('/api/data/notes')\` → \`synthos.data.list('notes')\`
116
+ - \`fetch('/api/data/notes/' + id)\` → \`synthos.data.get('notes', id)\`
117
+ - \`fetch('/api/data/notes', { method: 'POST', ... })\` → \`synthos.data.save('notes', row)\`
118
+ - \`fetch('/api/data/notes/' + id, { method: 'DELETE' })\` → \`synthos.data.remove('notes', id)\`
119
+
120
+ ### Color variables
121
+ Replace hardcoded Nebula Dusk colors with CSS variables in **page-specific** CSS only:
122
+ | Hardcoded | CSS Variable |
123
+ |-----------|-------------|
124
+ | \`#667eea\` | \`var(--accent-primary)\` |
125
+ | \`#764ba2\` | \`var(--accent-secondary)\` |
126
+ | \`#f093fb\` | \`var(--accent-tertiary)\` |
127
+ | \`#b794f6\` | \`var(--text-secondary)\` |
128
+ | \`#e0e0e0\` | \`var(--text-primary)\` |
129
+ | \`rgba(138, 43, 226, 0.3)\` or similar purple rgba | \`var(--border-color)\` or \`var(--accent-glow)\` (use border-color for borders, accent-glow for shadows) |
130
+ | \`#1a1a2e\` | \`var(--bg-primary)\` |
131
+ | \`#16213e\` | \`var(--bg-secondary)\` |
132
+ | \`#0f0f23\` | \`var(--bg-tertiary)\` |
133
+
134
+ For gradients using these colors (e.g. \`linear-gradient(135deg, #667eea, #764ba2)\`), replace with \`linear-gradient(135deg, var(--accent-primary), var(--accent-secondary))\`.
135
+
136
+ ## Rules — What to PRESERVE (do NOT modify)
137
+
138
+ - ALL viewer-panel HTML content (games, presentations, tools, etc.)
139
+ - ALL page-specific JavaScript (game logic, presentation logic, keyboard handlers, etc.)
140
+ - ALL page-specific CSS (game styles, presentation styles, layout rules for non-shared classes)
141
+ - Chat message history in \`.chat-messages\`
142
+ - \`<div id="thoughts">\` content
143
+ - External CDN script tags (\`<script src="...">\`)
144
+ - The two-panel layout structure (chat-panel + viewer-panel)
145
+ - The \`<div id="loadingOverlay" class="loading-overlay"><div class="spinner"></div></div>\` element
146
+ - The chat form, link-group, chat-header elements (structure only, their CSS is handled by theme)
147
+
148
+ ## V2 page structure example
149
+
150
+ \`\`\`html
151
+ <!DOCTYPE html>
152
+ <html lang="en">
153
+ <head>
154
+ <meta charset="UTF-8">
155
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
156
+ <title>SynthOS - Page Title</title>
157
+ <script src="/api/theme-info.js"></script>
158
+ <link rel="stylesheet" href="/api/theme.css">
159
+ <style>
160
+ /* Only page-specific styles here — no shared chat/layout CSS */
161
+ .my-custom-element {
162
+ color: var(--text-primary);
163
+ background: var(--bg-secondary);
164
+ }
165
+ </style>
166
+ <!-- external CDN scripts if needed -->
167
+ </head>
168
+ <body>
169
+ <div class="chat-panel">
170
+ <div class="chat-header">SynthOS</div>
171
+ <div class="chat-messages" id="chatMessages">
172
+ <!-- chat messages preserved -->
173
+ </div>
174
+ <div class="link-group">
175
+ <a href="#" id="saveLink">Save</a>
176
+ <a href="/pages" id="pagesLink">Pages</a>
177
+ <a href="#" id="resetLink">Reset</a>
178
+ </div>
179
+ <form action="/" method="POST" id="chatForm">
180
+ <input type="text" class="chat-input" id="chatInput" name="message" placeholder="Type a message...">
181
+ <button type="submit" class="chat-submit">Send</button>
182
+ </form>
183
+ </div>
184
+ <div class="viewer-panel" id="viewerPanel">
185
+ <!-- page content preserved -->
186
+ <div id="loadingOverlay" class="loading-overlay"><div class="spinner"></div></div>
187
+ </div>
188
+ <div id="thoughts" style="display: none;">...</div>
189
+ <script>
190
+ // Only page-specific JS here — no shared chat handlers
191
+ </script>
192
+ </body>
193
+ </html>
194
+ \`\`\`
195
+
196
+ ## Output format
197
+
198
+ Return ONLY the complete migrated HTML. No markdown fences, no explanation, no commentary. Just the raw HTML starting with \`<!DOCTYPE html>\`.`;
199
+ /**
200
+ * v1 -> v2: LLM-based migration that strips shared code and adds theme support.
201
+ * Post-processes with cheerio to verify critical elements are present.
202
+ */
203
+ async function migrateV1toV2(html, completePrompt) {
204
+ const system = { role: 'system', content: V1_TO_V2_SYSTEM_PROMPT };
205
+ const prompt = { role: 'user', content: `Convert this v1 page to v2 format:\n\n${html}` };
206
+ const result = await completePrompt({ prompt, system, maxTokens: 16000 });
207
+ if (!result.completed || !result.value) {
208
+ throw new Error('LLM migration failed: ' + (result.error?.message ?? 'no response'));
209
+ }
210
+ // Strip markdown fencing if present
211
+ let migrated = result.value.trim();
212
+ if (migrated.startsWith('```')) {
213
+ migrated = migrated.replace(/^```(?:html)?\s*\n?/, '').replace(/\n?```\s*$/, '');
214
+ }
215
+ // Post-process with cheerio to verify and fix critical elements
216
+ migrated = postProcessV2(migrated);
217
+ return migrated;
218
+ }
219
+ /**
220
+ * Cheerio-based post-processing to verify the LLM output meets v2 requirements.
221
+ */
222
+ function postProcessV2(html) {
223
+ const $ = cheerio.load(html, { decodeEntities: false });
224
+ // Ensure theme-info.js is in <head>
225
+ if ($('script[src="/api/theme-info.js"]').length === 0) {
226
+ const titleEl = $('title');
227
+ if (titleEl.length > 0) {
228
+ titleEl.after('\n<script src="/api/theme-info.js"></script>');
229
+ }
230
+ else {
231
+ $('head').prepend('<script src="/api/theme-info.js"></script>\n');
232
+ }
233
+ }
234
+ // Ensure theme.css is in <head>
235
+ if ($('link[href="/api/theme.css"]').length === 0) {
236
+ const themeScript = $('script[src="/api/theme-info.js"]');
237
+ if (themeScript.length > 0) {
238
+ themeScript.after('\n<link rel="stylesheet" href="/api/theme.css">');
239
+ }
240
+ else {
241
+ $('head').append('<link rel="stylesheet" href="/api/theme.css">\n');
242
+ }
243
+ }
244
+ // Remove leftover shared CSS selectors from <style> blocks
245
+ $('style').each(function (_, el) {
246
+ let css = $(el).html() ?? '';
247
+ for (const selector of SHARED_CSS_SELECTORS) {
248
+ // Escape special regex chars in selector
249
+ const escaped = selector.replace(/[.*+?^${}()|[\]\\#]/g, '\\$&');
250
+ // Match the full rule block: selector { ... }
251
+ const pattern = new RegExp(`(?:^|\\n)\\s*${escaped}\\s*\\{[^}]*\\}`, 'g');
252
+ css = css.replace(pattern, '');
253
+ }
254
+ // Remove @keyframes spin
255
+ css = css.replace(/@keyframes\s+spin\s*\{[^}]*(?:\{[^}]*\}[^}]*)*\}/g, '');
256
+ // Remove scrollbar pseudo-element rules
257
+ css = css.replace(/(?:^|\n)\s*(?:\*|body|)::-webkit-scrollbar(?:-(?:track|thumb))?\s*\{[^}]*\}/g, '');
258
+ $(el).html(css);
259
+ });
260
+ // Remove empty <style> blocks
261
+ $('style').each(function (_, el) {
262
+ const content = ($(el).html() ?? '').trim();
263
+ if (content === '') {
264
+ $(el).remove();
265
+ }
266
+ });
267
+ // Remove empty <script> blocks (no src)
268
+ $('script').each(function (_, el) {
269
+ const src = $(el).attr('src');
270
+ if (src)
271
+ return;
272
+ const code = ($(el).html() ?? '').trim();
273
+ if (code === '') {
274
+ $(el).remove();
275
+ }
276
+ });
277
+ // Remove duplicate inline scripts that share overlapping declarations
278
+ return (0, transformPage_1.deduplicateInlineScripts)($.html());
279
+ }
280
+ exports.postProcessV2 = postProcessV2;
281
+ //# sourceMappingURL=migrations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrations.js","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { ProviderName, ProviderConfig, ModelEntry, Provider } from './types';
2
+ export { AnthropicProvider, OpenAIProvider, PROVIDERS, getProvider, detectProvider } from './providers';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/models/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,SAAS,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectProvider = exports.getProvider = exports.PROVIDERS = exports.OpenAIProvider = exports.AnthropicProvider = void 0;
4
+ var providers_1 = require("./providers");
5
+ Object.defineProperty(exports, "AnthropicProvider", { enumerable: true, get: function () { return providers_1.AnthropicProvider; } });
6
+ Object.defineProperty(exports, "OpenAIProvider", { enumerable: true, get: function () { return providers_1.OpenAIProvider; } });
7
+ Object.defineProperty(exports, "PROVIDERS", { enumerable: true, get: function () { return providers_1.PROVIDERS; } });
8
+ Object.defineProperty(exports, "getProvider", { enumerable: true, get: function () { return providers_1.getProvider; } });
9
+ Object.defineProperty(exports, "detectProvider", { enumerable: true, get: function () { return providers_1.detectProvider; } });
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/models/index.ts"],"names":[],"mappings":";;;AACA,yCAAwG;AAA/F,8GAAA,iBAAiB,OAAA;AAAE,2GAAA,cAAc,OAAA;AAAE,sGAAA,SAAS,OAAA;AAAE,wGAAA,WAAW,OAAA;AAAE,2GAAA,cAAc,OAAA"}
@@ -0,0 +1,7 @@
1
+ import { Provider, ProviderName } from './types';
2
+ export declare const AnthropicProvider: Provider;
3
+ export declare const OpenAIProvider: Provider;
4
+ export declare const PROVIDERS: Provider[];
5
+ export declare function getProvider(name: ProviderName): Provider;
6
+ export declare function detectProvider(model: string): Provider | undefined;
7
+ //# sourceMappingURL=providers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../src/models/providers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEjD,eAAO,MAAM,iBAAiB,EAAE,QAO/B,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,QAO5B,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,QAAQ,EAAwC,CAAC;AAEzE,wBAAgB,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,QAAQ,CAMxD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAElE"}
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectProvider = exports.getProvider = exports.PROVIDERS = exports.OpenAIProvider = exports.AnthropicProvider = void 0;
4
+ exports.AnthropicProvider = {
5
+ name: 'Anthropic',
6
+ builderModels: ['claude-opus-4-6', 'claude-sonnet-4-5'],
7
+ chatModels: ['claude-haiku-4-5', 'claude-sonnet-4-5'],
8
+ detectModel(model) {
9
+ return model.startsWith('claude-');
10
+ }
11
+ };
12
+ exports.OpenAIProvider = {
13
+ name: 'OpenAI',
14
+ builderModels: ['gpt-5.2', 'gpt-5.2-codex'],
15
+ chatModels: ['gpt-5-nano', 'gpt-5-mini', 'gpt-4.1'],
16
+ detectModel(model) {
17
+ return model.startsWith('gpt-') || model.startsWith('GPT-');
18
+ }
19
+ };
20
+ exports.PROVIDERS = [exports.AnthropicProvider, exports.OpenAIProvider];
21
+ function getProvider(name) {
22
+ const provider = exports.PROVIDERS.find(p => p.name === name);
23
+ if (!provider) {
24
+ throw new Error(`Unknown provider: ${name}`);
25
+ }
26
+ return provider;
27
+ }
28
+ exports.getProvider = getProvider;
29
+ function detectProvider(model) {
30
+ return exports.PROVIDERS.find(p => p.detectModel(model));
31
+ }
32
+ exports.detectProvider = detectProvider;
33
+ //# sourceMappingURL=providers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.js","sourceRoot":"","sources":["../../src/models/providers.ts"],"names":[],"mappings":";;;AAEa,QAAA,iBAAiB,GAAa;IACvC,IAAI,EAAE,WAAW;IACjB,aAAa,EAAE,CAAC,iBAAiB,EAAE,mBAAmB,CAAC;IACvD,UAAU,EAAE,CAAC,kBAAkB,EAAE,mBAAmB,CAAC;IACrD,WAAW,CAAC,KAAa;QACrB,OAAO,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACvC,CAAC;CACJ,CAAC;AAEW,QAAA,cAAc,GAAa;IACpC,IAAI,EAAE,QAAQ;IACd,aAAa,EAAE,CAAC,SAAS,EAAE,eAAe,CAAC;IAC3C,UAAU,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,SAAS,CAAC;IACnD,WAAW,CAAC,KAAa;QACrB,OAAO,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAChE,CAAC;CACJ,CAAC;AAEW,QAAA,SAAS,GAAe,CAAC,yBAAiB,EAAE,sBAAc,CAAC,CAAC;AAEzE,SAAgB,WAAW,CAAC,IAAkB;IAC1C,MAAM,QAAQ,GAAG,iBAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACtD,IAAI,CAAC,QAAQ,EAAE;QACX,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,EAAE,CAAC,CAAC;KAChD;IACD,OAAO,QAAQ,CAAC;AACpB,CAAC;AAND,kCAMC;AAED,SAAgB,cAAc,CAAC,KAAa;IACxC,OAAO,iBAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;AACrD,CAAC;AAFD,wCAEC"}
@@ -0,0 +1,21 @@
1
+ export type ProviderName = 'Anthropic' | 'OpenAI';
2
+ export interface ProviderConfig {
3
+ apiKey: string;
4
+ model: string;
5
+ maxTokens: number;
6
+ }
7
+ export interface ModelEntry {
8
+ use: 'builder' | 'chat';
9
+ provider: ProviderName;
10
+ configuration: ProviderConfig;
11
+ imageQuality: 'standard' | 'hd';
12
+ instructions?: string;
13
+ logCompletions?: boolean;
14
+ }
15
+ export interface Provider {
16
+ name: ProviderName;
17
+ builderModels: string[];
18
+ chatModels: string[];
19
+ detectModel(model: string): boolean;
20
+ }
21
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/models/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,QAAQ,CAAC;AAElD,MAAM,WAAW,cAAc;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACvB,GAAG,EAAE,SAAS,GAAG,MAAM,CAAC;IACxB,QAAQ,EAAE,YAAY,CAAC;IACvB,aAAa,EAAE,cAAc,CAAC;IAC9B,YAAY,EAAE,UAAU,GAAG,IAAI,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,QAAQ;IACrB,IAAI,EAAE,YAAY,CAAC;IACnB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CACvC"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/models/types.ts"],"names":[],"mappings":""}
package/dist/pages.d.ts CHANGED
@@ -1,6 +1,25 @@
1
- export declare function listPages(pagesFolder: string, fallbackPagesFolder: string): Promise<string[]>;
1
+ export declare const REQUIRED_PAGES: string[];
2
+ export declare const PAGE_VERSION = 2;
3
+ export interface PageInfo {
4
+ name: string;
5
+ title: string;
6
+ categories: string[];
7
+ pinned: boolean;
8
+ showInAll: boolean;
9
+ createdDate: string;
10
+ lastModified: string;
11
+ pageVersion: number;
12
+ mode: 'unlocked' | 'locked';
13
+ }
14
+ export type PageMetadata = Omit<PageInfo, 'name'>;
15
+ export declare function loadPageMetadata(pagesFolder: string, name: string, fallbackFolder?: string): Promise<PageMetadata | undefined>;
16
+ export declare function parseMetadata(parsed: Record<string, unknown>): PageMetadata;
17
+ export declare function savePageMetadata(pagesFolder: string, name: string, metadata: PageMetadata): Promise<void>;
18
+ export declare function listPages(pagesFolder: string, fallbackPagesFolder: string): Promise<PageInfo[]>;
2
19
  export declare function loadPageState(pagesFolder: string, name: string, reset: boolean): Promise<string | undefined>;
3
20
  export declare function normalizePageName(name: string | undefined): string | undefined;
4
- export declare function savePageState(pagesFolder: string, name: string, content: string): Promise<void>;
21
+ export declare function savePageState(pagesFolder: string, name: string, content: string, title?: string, categories?: string[]): Promise<void>;
5
22
  export declare function updatePageState(name: string, content: string): void;
23
+ export declare function deletePage(pagesFolder: string, name: string): Promise<void>;
24
+ export declare function copyPage(pagesFolder: string, sourceName: string, targetName: string, title: string, categories: string[], requiredPagesFolder: string): Promise<void>;
6
25
  //# sourceMappingURL=pages.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../src/pages.ts"],"names":[],"mappings":"AAMA,wBAAsB,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAoBnG;AAED,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAC,SAAS,CAAC,CAahH;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAC,SAAS,GAAG,MAAM,GAAC,SAAS,CAE1E;AAED,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrG;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAEnE"}
1
+ {"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../src/pages.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,cAAc,UAAsD,CAAC;AAElF,eAAO,MAAM,YAAY,IAAI,CAAC;AAE9B,MAAM,WAAW,QAAQ;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,UAAU,GAAG,QAAQ,CAAC;CAC/B;AAED,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AAElD,wBAAsB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CA4BpI;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,YAAY,CAY3E;AAED,wBAAsB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAI/G;AAaD,wBAAsB,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAuErG;AAED,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAC,SAAS,CAAC,CAgBhH;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAC,SAAS,GAAG,MAAM,GAAC,SAAS,CAE1E;AAED,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsB5I;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAEnE;AAED,wBAAsB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAejF;AAED,wBAAsB,QAAQ,CAC1B,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAAE,EACpB,mBAAmB,EAAE,MAAM,GAC5B,OAAO,CAAC,IAAI,CAAC,CA8Bf"}