@pulse-editor/cli 0.1.1-beta.3 → 0.1.1-beta.31

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 (45) hide show
  1. package/dist/app.js +2 -1
  2. package/dist/cli.js +1 -0
  3. package/dist/components/commands/build.js +18 -33
  4. package/dist/components/commands/create.js +38 -12
  5. package/dist/components/commands/dev.js +36 -4
  6. package/dist/components/commands/help.js +2 -1
  7. package/dist/components/commands/preview.js +51 -7
  8. package/dist/components/commands/publish.js +23 -37
  9. package/dist/components/commands/{preview copy.d.ts → upgrade.d.ts} +1 -1
  10. package/dist/components/commands/upgrade.js +53 -0
  11. package/dist/lib/backend/publish-app.d.ts +1 -0
  12. package/dist/lib/backend/publish-app.js +27 -0
  13. package/dist/lib/cli-flags.d.ts +14 -0
  14. package/dist/lib/cli-flags.js +14 -0
  15. package/dist/lib/execa-utils/clean.js +1 -1
  16. package/dist/lib/execa-utils/deps.js +10 -1
  17. package/dist/lib/manual.js +52 -0
  18. package/dist/lib/server/express.js +33 -18
  19. package/dist/lib/server/preview/backend/load-remote.cjs +33 -23
  20. package/dist/lib/server/preview/frontend/index.html +11 -11
  21. package/dist/lib/webpack/compile.d.ts +2 -0
  22. package/dist/lib/webpack/compile.js +28 -0
  23. package/dist/lib/webpack/dist/pregistered-actions.d.ts +2 -0
  24. package/dist/lib/webpack/dist/pulse.config.d.ts +7 -0
  25. package/dist/lib/webpack/dist/src/lib/agents/code-modifier-agent.d.ts +2 -0
  26. package/dist/lib/webpack/dist/src/lib/agents/vibe-coding-agent.d.ts +3 -0
  27. package/dist/lib/webpack/dist/src/lib/mcp/utils.d.ts +3 -0
  28. package/dist/lib/webpack/dist/src/lib/streaming/message-stream-controller.d.ts +10 -0
  29. package/dist/lib/webpack/dist/src/lib/types.d.ts +58 -0
  30. package/dist/lib/webpack/dist/src/server-function/generate-code/v1/generate.d.ts +5 -0
  31. package/dist/lib/webpack/dist/src/server-function/generate-code/v2/generate.d.ts +1 -0
  32. package/dist/lib/webpack/tsconfig.server.json +19 -0
  33. package/dist/lib/webpack/webpack.config.d.ts +2 -0
  34. package/dist/lib/webpack/webpack.config.js +527 -0
  35. package/package.json +29 -15
  36. package/readme.md +35 -1
  37. package/dist/components/commands/preview copy.js +0 -14
  38. package/dist/components/commands/start copy.d.ts +0 -5
  39. package/dist/components/commands/start copy.js +0 -14
  40. package/dist/lib/deps.d.ts +0 -1
  41. package/dist/lib/deps.js +0 -5
  42. package/dist/lib/node_module_bin.d.ts +0 -1
  43. package/dist/lib/node_module_bin.js +0 -7
  44. package/dist/lib/server/preview/backend/index.d.ts +0 -1
  45. package/dist/lib/server/preview/backend/index.js +0 -23
@@ -29,4 +29,18 @@ export const flags = defineFlags({
29
29
  type: 'string',
30
30
  shortFlag: 't',
31
31
  },
32
+ beta: {
33
+ type: 'boolean',
34
+ },
35
+ build: {
36
+ type: 'boolean',
37
+ default: true,
38
+ },
39
+ path: {
40
+ type: 'string',
41
+ shortFlag: 'p',
42
+ },
43
+ displayName: {
44
+ type: 'string',
45
+ },
32
46
  });
@@ -5,5 +5,5 @@ export async function cleanDist() {
5
5
  await execa(`${getDepsBinPath('rimraf')} dist`, {
6
6
  shell: true,
7
7
  });
8
- console.log('✅ Cleaned dist directory.');
8
+ console.log('✅ Cleaned dist directory.');
9
9
  }
@@ -1,5 +1,14 @@
1
+ import fs from 'fs';
1
2
  // Get deps bin at node_modules/@pulse-editor/cli/node_modules
2
3
  export function getDepsBinPath(name) {
3
4
  const workingDir = process.cwd();
4
- return `${workingDir}/node_modules/@pulse-editor/cli/node_modules/.bin/${process.platform === 'win32' ? `${name}.cmd` : name}`;
5
+ // Check if the package is installed in the node_modules, if yes, just return "npx <name>"
6
+ if (fs.existsSync(`${workingDir}/node_modules/${name}`)) {
7
+ return `npx ${name}`;
8
+ }
9
+ // Check if the package exists in node_modules/@pulse-editor/cli/node_modules
10
+ else if (fs.existsSync(`${workingDir}/node_modules/@pulse-editor/cli/node_modules/${name}`)) {
11
+ return `${workingDir}/node_modules/@pulse-editor/cli/node_modules/.bin/${process.platform === 'win32' ? `${name}.cmd` : name}`;
12
+ }
13
+ throw new Error(`Dependency ${name} not found.`);
5
14
  }
@@ -1,5 +1,6 @@
1
1
  const help = `\
2
2
  help [command] Show help for a command.
3
+
3
4
  `;
4
5
  const chat = `\
5
6
  chat [message] (WIP) Chat with the Pulse Editor AI assistant.
@@ -22,9 +23,14 @@ const login = `\
22
23
  `;
23
24
  const logout = `\
24
25
  logout Logout from the Pulse Editor Platform.
26
+
25
27
  `;
26
28
  const publish = `\
27
29
  publish Publish Pulse Editor Extension in current directory to the Pulse Editor Platform.
30
+ Flags:
31
+ --noBuild
32
+ Skip the build step before publishing.
33
+
28
34
  `;
29
35
  const create = `\
30
36
  create Create a new Pulse App using the starter template.
@@ -38,6 +44,46 @@ const create = `\
38
44
  --visibility, -v [visibility]
39
45
  The visibility of the new project. Options are private,
40
46
  public, and unlisted.
47
+ --path, -p [path]
48
+ The path where to create the new project. Defaults to
49
+ the name of the project in the current working directory.
50
+
51
+ `;
52
+ const preview = `\
53
+ preview Build the Pulse App in development mode and
54
+ start a preview server accessible via browser
55
+ with live reloading.
56
+
57
+ `;
58
+ const dev = `\
59
+ dev Build the Pulse App in development mode and
60
+ start a local development server for Pulse Editor
61
+ to load the app from, with live reloading.
62
+
63
+ `;
64
+ const build = `\
65
+ build Build the Pulse App for production deployment.
66
+ Flags:
67
+ --target, -t [target]
68
+ The build target. Options are 'client', 'server', or
69
+ unspecified (both client and server).
70
+
71
+ `;
72
+ const start = `\
73
+ start Build the Pulse App in production mode and
74
+ start a local server for Pulse Editor to load the app from.
75
+
76
+ `;
77
+ const clean = `\
78
+ clean Clean the dist/ directory.
79
+
80
+ `;
81
+ const upgrade = `\
82
+ upgrade Upgrade Pulse Editor CLI and related packages to the latest version.
83
+ Flags:
84
+ --beta
85
+ Upgrade to the latest beta version.
86
+
41
87
  `;
42
88
  export const commandsManual = {
43
89
  help,
@@ -46,4 +92,10 @@ export const commandsManual = {
46
92
  logout,
47
93
  publish,
48
94
  create,
95
+ preview,
96
+ dev,
97
+ build,
98
+ start,
99
+ clean,
100
+ upgrade,
49
101
  };
@@ -16,7 +16,7 @@ dotenv.config({
16
16
  quiet: true,
17
17
  });
18
18
  const isPreview = process.env?.['PREVIEW'];
19
- const isDev = process.env?.['NODE_ENV'];
19
+ const isDev = process.env?.['NODE_ENV'] === 'development';
20
20
  const workspaceId = process.env?.['WORKSPACE_ID'];
21
21
  const pulseConfig = await readConfigFile();
22
22
  if (isDev || isPreview) {
@@ -65,19 +65,34 @@ app.all(/^\/server-function\/(.*)/, async (req, res) => {
65
65
  });
66
66
  const dir = path.resolve('node_modules/@pulse-editor/cli/dist/lib/server/preview/backend/load-remote.cjs');
67
67
  const fileUrl = pathToFileURL(dir).href;
68
- const { loadAndCall } = await import(fileUrl);
69
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
70
- const response = await loadAndCall(func, request, pulseConfig.id, 'http://localhost:3030', pulseConfig.version);
71
- const streamPipeline = promisify(pipeline);
72
- // If loadAndCall returns a Response (Fetch API Response)
73
- if (response.body) {
74
- // Convert WHATWG stream to Node.js stream
75
- const nodeStream = Readable.fromWeb(response.body);
76
- // Pipe it directly to Express
77
- await streamPipeline(nodeStream, res);
68
+ const { loadFunc, loadPrice } = await import(fileUrl);
69
+ const price = await loadPrice(func, pulseConfig.id, 'http://localhost:3030', pulseConfig.version);
70
+ if (price) {
71
+ // Make func name and price bold in console
72
+ console.log(`🏃 Running function \x1b[1m${func}\x1b[0m, credits consumed: \x1b[1m${price}\x1b[0m`);
78
73
  }
79
74
  else {
80
- res.end();
75
+ console.log(`🏃 Running function \x1b[1m${func}\x1b[0m.`);
76
+ }
77
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
78
+ const loadedFunc = await loadFunc(func, pulseConfig.id, 'http://localhost:3030', pulseConfig.version);
79
+ const response = await loadedFunc(request);
80
+ const streamPipeline = promisify(pipeline);
81
+ if (response) {
82
+ // 1️⃣ Set status code
83
+ res.status(response.status);
84
+ // 2️⃣ Copy headers
85
+ response.headers.forEach((value, key) => {
86
+ res.setHeader(key, value);
87
+ });
88
+ // 3️⃣ Pipe body if present
89
+ if (response.body) {
90
+ const nodeStream = Readable.fromWeb(response.body);
91
+ await streamPipeline(nodeStream, res);
92
+ }
93
+ else {
94
+ res.end();
95
+ }
81
96
  }
82
97
  });
83
98
  if (isPreview) {
@@ -94,12 +109,12 @@ else {
94
109
  /* Production mode */
95
110
  app.use(`/${pulseConfig.id}/${pulseConfig.version}`, express.static('dist'));
96
111
  app.listen(3030, '0.0.0.0', () => {
97
- console.log(`\
98
- 🎉 Your Pulse extension \x1b[1m${pulseConfig.displayName}\x1b[0m is LIVE!
99
-
100
- ⚡️ Local: http://localhost:3030/${pulseConfig.id}/${pulseConfig.version}/
101
- ⚡️ Network: http://${getLocalNetworkIP()}:3030/${pulseConfig.id}/${pulseConfig.version}/
102
-
112
+ console.log(`\
113
+ 🎉 Your Pulse extension \x1b[1m${pulseConfig.displayName}\x1b[0m is LIVE!
114
+
115
+ ⚡️ Local: http://localhost:3030/${pulseConfig.id}/${pulseConfig.version}/
116
+ ⚡️ Network: http://${getLocalNetworkIP()}:3030/${pulseConfig.id}/${pulseConfig.version}/
117
+
103
118
  ✨ Try it out in the Pulse Editor and let the magic happen! 🚀`);
104
119
  });
105
120
  }
@@ -1,23 +1,33 @@
1
- const { createInstance } = require("@module-federation/runtime");
2
-
3
- async function loadAndCall(func, req, appId, origin, version) {
4
- // here we assign the return value of the init() function, which can be used to do some more complex
5
- // things with the module federation runtime
6
- const instance = createInstance({
7
- name: "server_function_runner",
8
- remotes: [
9
- {
10
- name: appId + "_server",
11
- entry: `${origin}/${appId}/${version}/server/remoteEntry.js`,
12
- },
13
- ],
14
- });
15
-
16
- const loadedFunc = (await instance.loadRemote(`${appId}_server/${func}`))
17
- .default;
18
-
19
- const res = await loadedFunc(req);
20
- return res;
21
- }
22
-
23
- module.exports = { loadAndCall };
1
+ const {createInstance} = require('@module-federation/runtime');
2
+
3
+ async function importRemoteModule(func, appId, origin, version) {
4
+ const instance = createInstance({
5
+ name: 'server_function_runner',
6
+ remotes: [
7
+ {
8
+ name: appId + '_server',
9
+ entry: `${origin}/${appId}/${version}/server/remoteEntry.js`,
10
+ },
11
+ ],
12
+ });
13
+
14
+ const loadedModule = await instance.loadRemote(`${appId}_server/${func}`);
15
+ return loadedModule;
16
+ }
17
+
18
+ async function loadFunc(func, appId, origin, version) {
19
+ // here we assign the return value of the init() function, which can be used to do some more complex
20
+ // things with the module federation runtime
21
+ const module = await importRemoteModule(func, appId, origin, version);
22
+ const loadedFunc = module.default;
23
+
24
+ return loadedFunc;
25
+ }
26
+
27
+ async function loadPrice(func, appId, origin, version) {
28
+ const module = await importRemoteModule(func, appId, origin, version);
29
+ const price = module._CREDIT_PER_CALL;
30
+ return price;
31
+ }
32
+
33
+ module.exports = {loadFunc, loadPrice};
@@ -1,11 +1,11 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Pulse App</title>
7
- </head>
8
- <body style="height: 100vh; width: 100vw">
9
- <div id="root" style="height: 100%; width: 100%"></div>
10
- </body>
11
- </html>
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Pulse App</title>
7
+ </head>
8
+ <body style="height: 100vh; width: 100vw">
9
+ <div id="root" style="height: 100%; width: 100%"></div>
10
+ </body>
11
+ </html>
@@ -0,0 +1,2 @@
1
+ import webpack from 'webpack';
2
+ export declare function webpackCompile(mode: 'development' | 'production' | 'preview', buildTarget?: 'client' | 'server', isWatchMode?: boolean): Promise<void | webpack.MultiCompiler>;
@@ -0,0 +1,28 @@
1
+ import webpack from 'webpack';
2
+ import { createWebpackConfig } from '../../lib/webpack/webpack.config.js';
3
+ export async function webpackCompile(mode, buildTarget, isWatchMode = false) {
4
+ const configs = await createWebpackConfig(mode === 'preview', buildTarget ?? 'both', mode === 'development'
5
+ ? 'development'
6
+ : mode === 'preview'
7
+ ? 'development'
8
+ : 'production');
9
+ const compiler = webpack(configs);
10
+ if (isWatchMode) {
11
+ compiler.watch({}, (err, stats) => {
12
+ if (err) {
13
+ console.error('❌ Webpack build failed', err);
14
+ return;
15
+ }
16
+ });
17
+ return compiler;
18
+ }
19
+ return new Promise((resolve, reject) => {
20
+ compiler.run(err => {
21
+ if (err) {
22
+ reject(err);
23
+ return;
24
+ }
25
+ resolve();
26
+ });
27
+ });
28
+ }
@@ -0,0 +1,2 @@
1
+ import { Action } from "@pulse-editor/shared-utils";
2
+ export declare const preRegisteredActions: Record<string, Action>;
@@ -0,0 +1,7 @@
1
+ import { AppConfig } from "@pulse-editor/shared-utils";
2
+ /**
3
+ * Pulse Editor Extension Config
4
+ *
5
+ */
6
+ declare const config: AppConfig;
7
+ export default config;
@@ -0,0 +1,2 @@
1
+ import { ChatPromptTemplate } from "@langchain/core/prompts";
2
+ export declare const codeModifierAgentPrompt: ChatPromptTemplate<any, any>;
@@ -0,0 +1,3 @@
1
+ import { MultiServerMCPClient } from "@langchain/mcp-adapters";
2
+ import { MessageStreamController } from "../streaming/message-stream-controller";
3
+ export declare function runVibeCoding(mcpClient: MultiServerMCPClient, userPrompt: string, controller: MessageStreamController): Promise<void>;
@@ -0,0 +1,3 @@
1
+ import { MultiServerMCPClient } from "@langchain/mcp-adapters";
2
+ export declare function writeFileToFS(mcpClient: MultiServerMCPClient, uri: string, content: string): Promise<string>;
3
+ export declare function callTerminal(mcpClient: MultiServerMCPClient, command: string): Promise<string>;
@@ -0,0 +1,10 @@
1
+ import { AgentTaskMessageData } from "../types";
2
+ export declare class MessageStreamController {
3
+ private controller;
4
+ private msgCounter;
5
+ private messages;
6
+ private timeCountMap;
7
+ constructor(controller: ReadableStreamDefaultController);
8
+ enqueueNew(data: AgentTaskMessageData, isFinal: boolean): number;
9
+ enqueueUpdate(data: AgentTaskMessageData, isFinal: boolean): void;
10
+ }
@@ -0,0 +1,58 @@
1
+ export type VibeDevFlowNode = {
2
+ id: string;
3
+ children: VibeDevFlowNode[];
4
+ };
5
+ export declare enum AgentTaskMessageType {
6
+ Creation = "creation",
7
+ Update = "update"
8
+ }
9
+ export declare enum AgentTaskMessageDataType {
10
+ Notification = "notification",
11
+ ToolCall = "toolCall",
12
+ ArtifactOutput = "artifactOutput"
13
+ }
14
+ /**
15
+ * Data associated with an AgentTaskItem.
16
+ * The fields included depend on the type of the task item.
17
+ *
18
+ * @property type - The type of the task item, defined by the AgentTaskItemType enum.
19
+ * @property title - (Optional) A brief title or summary of the task item.
20
+ * @property description - (Optional) A detailed description of the task item.
21
+ * @property toolName - (Optional) The name of the tool being called (if applicable).
22
+ * @property parameters - (Optional) A record of parameters associated with the tool call (if applicable).
23
+ * @property error - (Optional) An error message if the task item represents an error.
24
+ * @property result - (Optional) The result or output of the task item (if applicable).
25
+ */
26
+ export type AgentTaskMessageData = {
27
+ type?: AgentTaskMessageDataType;
28
+ title?: string;
29
+ description?: string;
30
+ toolName?: string;
31
+ parameters?: Record<string, unknown>;
32
+ error?: string;
33
+ result?: string;
34
+ };
35
+ /**
36
+ * Represents a single task item generated by the agent.
37
+ * Each task item can be of different types such as tool calls, notifications, or errors.
38
+ *
39
+ * @property type - The type of the task item, defined by the AgentTaskItemType enum.
40
+ * @property messageId - The unique identifier for the task item.
41
+ * This is an incremental number representing the n-th task item.
42
+ * @property data - The data associated with the task item, which varies based on the type.
43
+ * @property isFinal - (Optional) Indicates if the task item is final and no further updates are expected.
44
+ */
45
+ export type AgentTaskMessage = {
46
+ type: AgentTaskMessageType;
47
+ messageId: number;
48
+ data: AgentTaskMessageData;
49
+ isFinal?: boolean;
50
+ };
51
+ export type AgentTaskMessageUpdate = {
52
+ type: AgentTaskMessageType;
53
+ messageId: number;
54
+ updateType: "append";
55
+ delta: AgentTaskMessageData;
56
+ isFinal?: boolean;
57
+ timeUsedSec?: string;
58
+ };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * An example function to echo the body of a POST request.
3
+ * This route is accessible at /server-function/echo
4
+ */
5
+ export default function generate(req: Request): Promise<Response>;
@@ -0,0 +1 @@
1
+ export default function handler(req: Request): Promise<Response>;
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "esnext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "declaration": true,
8
+ "outDir": "dist",
9
+ },
10
+ "include": [
11
+ "../../../../../../src/server-function/**/*",
12
+ "../../../../../../pulse.config.ts",
13
+ "../../../../../../global.d.ts",
14
+ ],
15
+ "exclude": [
16
+ "../../../../../../node_modules",
17
+ "../../../../../../dist",
18
+ ]
19
+ }
@@ -0,0 +1,2 @@
1
+ import wp from 'webpack';
2
+ export declare function createWebpackConfig(isPreview: boolean, buildTarget: 'client' | 'server' | 'both', mode: 'development' | 'production'): Promise<wp.Configuration[]>;