@leeoohoo/ui-apps-devkit 0.1.1 → 0.1.3

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 (62) hide show
  1. package/README.md +84 -76
  2. package/bin/chatos-uiapp.js +3 -4
  3. package/package.json +28 -25
  4. package/src/cli.js +53 -53
  5. package/src/commands/dev.js +14 -14
  6. package/src/commands/init.js +143 -142
  7. package/src/commands/install.js +56 -55
  8. package/src/commands/pack.js +72 -72
  9. package/src/commands/validate.js +113 -113
  10. package/src/lib/args.js +49 -49
  11. package/src/lib/config.js +29 -29
  12. package/src/lib/fs.js +78 -78
  13. package/src/lib/path-boundary.js +16 -16
  14. package/src/lib/plugin.js +45 -45
  15. package/src/lib/state-constants.js +2 -0
  16. package/src/lib/template.js +172 -172
  17. package/src/sandbox/server.js +2302 -1200
  18. package/templates/basic/README.md +80 -77
  19. package/templates/basic/chatos.config.json +5 -5
  20. package/templates/basic/docs/CHATOS_UI_APPS_AI_CONTRIBUTIONS.md +178 -178
  21. package/templates/basic/docs/CHATOS_UI_APPS_BACKEND_PROTOCOL.md +75 -74
  22. package/templates/basic/docs/CHATOS_UI_APPS_HOST_API.md +136 -136
  23. package/templates/basic/docs/CHATOS_UI_APPS_OVERVIEW.md +115 -113
  24. package/templates/basic/docs/CHATOS_UI_APPS_PLUGIN_MANIFEST.md +225 -224
  25. package/templates/basic/docs/CHATOS_UI_APPS_STYLE_GUIDE.md +95 -95
  26. package/templates/basic/docs/CHATOS_UI_APPS_TROUBLESHOOTING.md +45 -45
  27. package/templates/basic/docs/CHATOS_UI_PROMPTS_PROTOCOL.md +392 -392
  28. package/templates/basic/plugin/apps/app/compact.mjs +41 -41
  29. package/templates/basic/plugin/apps/app/index.mjs +287 -287
  30. package/templates/basic/plugin/apps/app/mcp-prompt.en.md +7 -7
  31. package/templates/basic/plugin/apps/app/mcp-prompt.zh.md +7 -7
  32. package/templates/basic/plugin/apps/app/mcp-server.mjs +15 -15
  33. package/templates/basic/plugin/backend/index.mjs +37 -37
  34. package/templates/basic/template.json +7 -7
  35. package/templates/notepad/README.md +61 -58
  36. package/templates/notepad/chatos.config.json +4 -4
  37. package/templates/notepad/docs/CHATOS_UI_APPS_AI_CONTRIBUTIONS.md +178 -178
  38. package/templates/notepad/docs/CHATOS_UI_APPS_BACKEND_PROTOCOL.md +75 -74
  39. package/templates/notepad/docs/CHATOS_UI_APPS_HOST_API.md +136 -136
  40. package/templates/notepad/docs/CHATOS_UI_APPS_OVERVIEW.md +115 -113
  41. package/templates/notepad/docs/CHATOS_UI_APPS_PLUGIN_MANIFEST.md +225 -224
  42. package/templates/notepad/docs/CHATOS_UI_APPS_STYLE_GUIDE.md +95 -95
  43. package/templates/notepad/docs/CHATOS_UI_APPS_TROUBLESHOOTING.md +45 -45
  44. package/templates/notepad/docs/CHATOS_UI_PROMPTS_PROTOCOL.md +392 -392
  45. package/templates/notepad/plugin/apps/app/api.mjs +30 -30
  46. package/templates/notepad/plugin/apps/app/compact.mjs +41 -41
  47. package/templates/notepad/plugin/apps/app/dom.mjs +14 -14
  48. package/templates/notepad/plugin/apps/app/ds-tree.mjs +35 -35
  49. package/templates/notepad/plugin/apps/app/index.mjs +1056 -1056
  50. package/templates/notepad/plugin/apps/app/layers.mjs +338 -338
  51. package/templates/notepad/plugin/apps/app/markdown.mjs +120 -120
  52. package/templates/notepad/plugin/apps/app/mcp-prompt.en.md +22 -22
  53. package/templates/notepad/plugin/apps/app/mcp-prompt.zh.md +22 -22
  54. package/templates/notepad/plugin/apps/app/mcp-server.mjs +207 -200
  55. package/templates/notepad/plugin/apps/app/styles.mjs +355 -355
  56. package/templates/notepad/plugin/apps/app/tags.mjs +21 -21
  57. package/templates/notepad/plugin/apps/app/ui.mjs +280 -280
  58. package/templates/notepad/plugin/backend/index.mjs +99 -99
  59. package/templates/notepad/plugin/plugin.json +23 -23
  60. package/templates/notepad/plugin/shared/notepad-paths.mjs +80 -62
  61. package/templates/notepad/plugin/shared/notepad-store.mjs +765 -765
  62. package/templates/notepad/template.json +8 -8
@@ -0,0 +1,2 @@
1
+ export const STATE_ROOT_DIRNAME = '.deepseek_cli';
2
+ export const COMPAT_STATE_ROOT_DIRNAME = '.chatos';
@@ -1,172 +1,172 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import { fileURLToPath } from 'url';
4
-
5
- import { copyDir, ensureDir, isDirectory, isFile, readJson, writeJson, writeText } from './fs.js';
6
-
7
- function packageRoot() {
8
- // src/lib/template.js -> src -> package root
9
- const here = path.dirname(fileURLToPath(import.meta.url));
10
- return path.resolve(here, '..', '..');
11
- }
12
-
13
- export function getTemplateDir(name) {
14
- const root = packageRoot();
15
- const dir = path.join(root, 'templates', name);
16
- if (!isDirectory(dir)) throw new Error(`template not found: ${name}`);
17
- return dir;
18
- }
19
-
20
- function readSelfPackage() {
21
- const root = packageRoot();
22
- const pkgPath = path.join(root, 'package.json');
23
- if (!isFile(pkgPath)) return { name: '@leeoohoo/ui-apps-devkit', version: '0.1.0' };
24
- try {
25
- const pkg = readJson(pkgPath);
26
- return pkg && typeof pkg === 'object' ? pkg : { name: '@leeoohoo/ui-apps-devkit', version: '0.1.0' };
27
- } catch {
28
- return { name: '@leeoohoo/ui-apps-devkit', version: '0.1.0' };
29
- }
30
- }
31
-
32
- export function readTemplateMeta(name) {
33
- const dir = getTemplateDir(name);
34
- const metaPath = path.join(dir, 'template.json');
35
- if (!isFile(metaPath)) return { name, description: '', defaults: null };
36
- try {
37
- const meta = readJson(metaPath);
38
- return {
39
- name,
40
- description: typeof meta?.description === 'string' ? meta.description.trim() : '',
41
- defaults: meta?.defaults && typeof meta.defaults === 'object' ? meta.defaults : null,
42
- };
43
- } catch {
44
- return { name, description: '', defaults: null };
45
- }
46
- }
47
-
48
- export function listTemplates() {
49
- const root = packageRoot();
50
- const templatesDir = path.join(root, 'templates');
51
- let entries = [];
52
- try {
53
- entries = fs.readdirSync(templatesDir, { withFileTypes: true });
54
- } catch {
55
- return [];
56
- }
57
-
58
- const out = [];
59
- for (const ent of entries) {
60
- if (!ent?.isDirectory?.()) continue;
61
- const name = String(ent.name || '').trim();
62
- if (!name || name.startsWith('.')) continue;
63
- if (!isDirectory(path.join(templatesDir, name))) continue;
64
- out.push(readTemplateMeta(name));
65
- }
66
- out.sort((a, b) => a.name.localeCompare(b.name));
67
- return out;
68
- }
69
-
70
- export function copyTemplate({ templateName, destDir }) {
71
- const srcDir = getTemplateDir(templateName);
72
- ensureDir(destDir);
73
-
74
- copyDir(srcDir, destDir, {
75
- filter: (src) => {
76
- const base = path.basename(src);
77
- if (base === 'node_modules') return false;
78
- if (base === '.DS_Store') return false;
79
- return true;
80
- },
81
- });
82
- }
83
-
84
- export function writeScaffoldManifest({ destPluginDir, pluginId, pluginName, version, appId, withBackend = true }) {
85
- const manifest = {
86
- manifestVersion: 1,
87
- id: pluginId,
88
- name: pluginName,
89
- version: version || '0.1.0',
90
- description: 'A ChatOS UI Apps plugin.',
91
- ...(withBackend ? { backend: { entry: 'backend/index.mjs' } } : {}),
92
- apps: [
93
- {
94
- id: appId,
95
- name: 'My App',
96
- description: 'A ChatOS module app.',
97
- entry: {
98
- type: 'module',
99
- path: `apps/${appId}/index.mjs`,
100
- compact: { type: 'module', path: `apps/${appId}/compact.mjs` },
101
- },
102
- ai: {
103
- // Keep the default scaffold dependency-free: prompt is safe, MCP server is opt-in.
104
- mcpPrompt: {
105
- title: 'My App · MCP Prompt',
106
- zh: `apps/${appId}/mcp-prompt.zh.md`,
107
- en: `apps/${appId}/mcp-prompt.en.md`,
108
- },
109
- },
110
- },
111
- ],
112
- };
113
-
114
- writeJson(path.join(destPluginDir, 'plugin.json'), manifest);
115
- return manifest;
116
- }
117
-
118
- export function writeScaffoldPackageJson({ destDir, projectName }) {
119
- const selfPkg = readSelfPackage();
120
- const devkitName = typeof selfPkg?.name === 'string' && selfPkg.name.trim() ? selfPkg.name.trim() : '@leeoohoo/ui-apps-devkit';
121
- const devkitVersion = typeof selfPkg?.version === 'string' && selfPkg.version.trim() ? selfPkg.version.trim() : '0.1.0';
122
- const devkitRange = `^${devkitVersion}`;
123
-
124
- const baseScripts = {
125
- dev: 'chatos-uiapp dev',
126
- validate: 'chatos-uiapp validate',
127
- pack: 'chatos-uiapp pack',
128
- 'install:chatos': 'chatos-uiapp install --host-app chatos',
129
- };
130
-
131
- const pkgPath = path.join(destDir, 'package.json');
132
- const existing = isFile(pkgPath) ? readJson(pkgPath) : {};
133
- const pkg = existing && typeof existing === 'object' ? existing : {};
134
-
135
- pkg.name = projectName;
136
- pkg.private = true;
137
- pkg.type = 'module';
138
-
139
- pkg.scripts = pkg.scripts && typeof pkg.scripts === 'object' ? pkg.scripts : {};
140
- for (const [key, value] of Object.entries(baseScripts)) {
141
- if (!pkg.scripts[key]) pkg.scripts[key] = value;
142
- }
143
-
144
- pkg.devDependencies = pkg.devDependencies && typeof pkg.devDependencies === 'object' ? pkg.devDependencies : {};
145
- if (!pkg.devDependencies[devkitName]) {
146
- pkg.devDependencies[devkitName] = devkitRange;
147
- }
148
-
149
- writeJson(pkgPath, pkg);
150
- return pkg;
151
- }
152
-
153
- export function writeScaffoldConfig({ destDir, pluginDir = 'plugin', appId = '' }) {
154
- const cfgPath = path.join(destDir, 'chatos.config.json');
155
- const existing = isFile(cfgPath) ? readJson(cfgPath) : {};
156
- const cfg = existing && typeof existing === 'object' ? existing : {};
157
- cfg.pluginDir = pluginDir;
158
- cfg.appId = appId;
159
- writeJson(cfgPath, cfg);
160
- return cfg;
161
- }
162
-
163
- export function maybeReplaceTokensInFile(filePath, replacements) {
164
- const raw = fs.readFileSync(filePath, 'utf8');
165
- let next = raw;
166
- for (const [key, value] of Object.entries(replacements || {})) {
167
- next = next.split(key).join(String(value));
168
- }
169
- if (next !== raw) {
170
- writeText(filePath, next);
171
- }
172
- }
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { fileURLToPath } from 'url';
4
+
5
+ import { copyDir, ensureDir, isDirectory, isFile, readJson, writeJson, writeText } from './fs.js';
6
+
7
+ function packageRoot() {
8
+ // src/lib/template.js -> src -> package root
9
+ const here = path.dirname(fileURLToPath(import.meta.url));
10
+ return path.resolve(here, '..', '..');
11
+ }
12
+
13
+ export function getTemplateDir(name) {
14
+ const root = packageRoot();
15
+ const dir = path.join(root, 'templates', name);
16
+ if (!isDirectory(dir)) throw new Error(`template not found: ${name}`);
17
+ return dir;
18
+ }
19
+
20
+ function readSelfPackage() {
21
+ const root = packageRoot();
22
+ const pkgPath = path.join(root, 'package.json');
23
+ if (!isFile(pkgPath)) return { name: '@leeoohoo/ui-apps-devkit', version: '0.1.0' };
24
+ try {
25
+ const pkg = readJson(pkgPath);
26
+ return pkg && typeof pkg === 'object' ? pkg : { name: '@leeoohoo/ui-apps-devkit', version: '0.1.0' };
27
+ } catch {
28
+ return { name: '@leeoohoo/ui-apps-devkit', version: '0.1.0' };
29
+ }
30
+ }
31
+
32
+ export function readTemplateMeta(name) {
33
+ const dir = getTemplateDir(name);
34
+ const metaPath = path.join(dir, 'template.json');
35
+ if (!isFile(metaPath)) return { name, description: '', defaults: null };
36
+ try {
37
+ const meta = readJson(metaPath);
38
+ return {
39
+ name,
40
+ description: typeof meta?.description === 'string' ? meta.description.trim() : '',
41
+ defaults: meta?.defaults && typeof meta.defaults === 'object' ? meta.defaults : null,
42
+ };
43
+ } catch {
44
+ return { name, description: '', defaults: null };
45
+ }
46
+ }
47
+
48
+ export function listTemplates() {
49
+ const root = packageRoot();
50
+ const templatesDir = path.join(root, 'templates');
51
+ let entries = [];
52
+ try {
53
+ entries = fs.readdirSync(templatesDir, { withFileTypes: true });
54
+ } catch {
55
+ return [];
56
+ }
57
+
58
+ const out = [];
59
+ for (const ent of entries) {
60
+ if (!ent?.isDirectory?.()) continue;
61
+ const name = String(ent.name || '').trim();
62
+ if (!name || name.startsWith('.')) continue;
63
+ if (!isDirectory(path.join(templatesDir, name))) continue;
64
+ out.push(readTemplateMeta(name));
65
+ }
66
+ out.sort((a, b) => a.name.localeCompare(b.name));
67
+ return out;
68
+ }
69
+
70
+ export function copyTemplate({ templateName, destDir }) {
71
+ const srcDir = getTemplateDir(templateName);
72
+ ensureDir(destDir);
73
+
74
+ copyDir(srcDir, destDir, {
75
+ filter: (src) => {
76
+ const base = path.basename(src);
77
+ if (base === 'node_modules') return false;
78
+ if (base === '.DS_Store') return false;
79
+ return true;
80
+ },
81
+ });
82
+ }
83
+
84
+ export function writeScaffoldManifest({ destPluginDir, pluginId, pluginName, version, appId, withBackend = true }) {
85
+ const manifest = {
86
+ manifestVersion: 1,
87
+ id: pluginId,
88
+ name: pluginName,
89
+ version: version || '0.1.0',
90
+ description: 'A ChatOS UI Apps plugin.',
91
+ ...(withBackend ? { backend: { entry: 'backend/index.mjs' } } : {}),
92
+ apps: [
93
+ {
94
+ id: appId,
95
+ name: 'My App',
96
+ description: 'A ChatOS module app.',
97
+ entry: {
98
+ type: 'module',
99
+ path: `apps/${appId}/index.mjs`,
100
+ compact: { type: 'module', path: `apps/${appId}/compact.mjs` },
101
+ },
102
+ ai: {
103
+ // Keep the default scaffold dependency-free: prompt is safe, MCP server is opt-in.
104
+ mcpPrompt: {
105
+ title: 'My App · MCP Prompt',
106
+ zh: `apps/${appId}/mcp-prompt.zh.md`,
107
+ en: `apps/${appId}/mcp-prompt.en.md`,
108
+ },
109
+ },
110
+ },
111
+ ],
112
+ };
113
+
114
+ writeJson(path.join(destPluginDir, 'plugin.json'), manifest);
115
+ return manifest;
116
+ }
117
+
118
+ export function writeScaffoldPackageJson({ destDir, projectName }) {
119
+ const selfPkg = readSelfPackage();
120
+ const devkitName = typeof selfPkg?.name === 'string' && selfPkg.name.trim() ? selfPkg.name.trim() : '@leeoohoo/ui-apps-devkit';
121
+ const devkitVersion = typeof selfPkg?.version === 'string' && selfPkg.version.trim() ? selfPkg.version.trim() : '0.1.0';
122
+ const devkitRange = `^${devkitVersion}`;
123
+
124
+ const baseScripts = {
125
+ dev: 'chatos-uiapp dev',
126
+ validate: 'chatos-uiapp validate',
127
+ pack: 'chatos-uiapp pack',
128
+ 'install:chatos': 'chatos-uiapp install --host-app chatos',
129
+ };
130
+
131
+ const pkgPath = path.join(destDir, 'package.json');
132
+ const existing = isFile(pkgPath) ? readJson(pkgPath) : {};
133
+ const pkg = existing && typeof existing === 'object' ? existing : {};
134
+
135
+ pkg.name = projectName;
136
+ pkg.private = true;
137
+ pkg.type = 'module';
138
+
139
+ pkg.scripts = pkg.scripts && typeof pkg.scripts === 'object' ? pkg.scripts : {};
140
+ for (const [key, value] of Object.entries(baseScripts)) {
141
+ if (!pkg.scripts[key]) pkg.scripts[key] = value;
142
+ }
143
+
144
+ pkg.devDependencies = pkg.devDependencies && typeof pkg.devDependencies === 'object' ? pkg.devDependencies : {};
145
+ if (!pkg.devDependencies[devkitName]) {
146
+ pkg.devDependencies[devkitName] = devkitRange;
147
+ }
148
+
149
+ writeJson(pkgPath, pkg);
150
+ return pkg;
151
+ }
152
+
153
+ export function writeScaffoldConfig({ destDir, pluginDir = 'plugin', appId = '' }) {
154
+ const cfgPath = path.join(destDir, 'chatos.config.json');
155
+ const existing = isFile(cfgPath) ? readJson(cfgPath) : {};
156
+ const cfg = existing && typeof existing === 'object' ? existing : {};
157
+ cfg.pluginDir = pluginDir;
158
+ cfg.appId = appId;
159
+ writeJson(cfgPath, cfg);
160
+ return cfg;
161
+ }
162
+
163
+ export function maybeReplaceTokensInFile(filePath, replacements) {
164
+ const raw = fs.readFileSync(filePath, 'utf8');
165
+ let next = raw;
166
+ for (const [key, value] of Object.entries(replacements || {})) {
167
+ next = next.split(key).join(String(value));
168
+ }
169
+ if (next !== raw) {
170
+ writeText(filePath, next);
171
+ }
172
+ }