@dyyz1993/create-agent 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/commands/create.ts +31 -31
- package/src/commands/workspace.ts +112 -105
- package/src/lib/copy.ts +24 -1
- package/templates/agent/electron/main.js +46 -0
- package/templates/agent/electron/preload.js +5 -0
- package/templates/agent/electron-builder.json +40 -0
- package/templates/agent/eslint.config.mjs +17 -2
- package/templates/agent/package.json +69 -3
- package/templates/agent/src/__tests__/hybrid-mode.test.ts +126 -0
- package/templates/agent/src/__tests__/server-config-security.test.ts +55 -0
- package/templates/agent/src/bun/index.ts +96 -41
- package/templates/agent/src/bun/three.d.ts +1 -0
- package/templates/agent/src/gateway/__tests__/ws-handler-token.test.ts +118 -0
- package/templates/agent/src/gateway/http-routes.ts +1 -1
- package/templates/agent/src/gateway/ws-handler.ts +84 -56
- package/templates/agent/src/mainview/App.tsx +29 -26
- package/templates/agent/src/mainview/__tests__/i18n/i18n.test.ts +1 -0
- package/templates/agent/src/mainview/__tests__/setup.ts +32 -29
- package/templates/agent/src/mainview/__tests__/theme-variables.test.ts +36 -0
- package/templates/agent/src/mainview/components/chat/ChatPanel.tsx +88 -88
- package/templates/agent/src/mainview/components/common/ErrorBoundary.tsx +1 -58
- package/templates/agent/src/mainview/components/common/LanguageSwitcher.tsx +1 -0
- package/templates/agent/src/mainview/components/common/ThemeToggle.tsx +1 -0
- package/templates/agent/src/mainview/components/feed/FeedPanel.tsx +232 -210
- package/templates/agent/src/mainview/components/file-preview/VirtualizedCodeView.tsx +105 -81
- package/templates/agent/src/mainview/components/search/SearchPanel.tsx +427 -378
- package/templates/agent/src/mainview/components/todo/TodoPanel.tsx +149 -122
- package/templates/agent/src/mainview/hooks/use-input-history.ts +70 -61
- package/templates/agent/src/mainview/lib/api-client.ts +179 -172
- package/templates/agent/src/mainview/main.tsx +4 -10
- package/templates/agent/src/mainview/stores/use-feed-store.ts +107 -107
- package/templates/agent/src/mainview/utils/drop-handler.ts +114 -115
- package/templates/agent/src/server-config.ts +34 -32
- package/templates/agent/src/server.ts +42 -54
- package/templates/agent/src/shared/handlers/__tests__/chat-concurrency.test.ts +127 -0
- package/templates/agent/src/shared/handlers/__tests__/handler-isolation.test.ts +244 -0
- package/templates/agent/src/shared/handlers/bash.ts +65 -65
- package/templates/agent/src/shared/handlers/chat.ts +189 -155
- package/templates/agent/src/shared/handlers/debug.ts +12 -0
- package/templates/agent/src/shared/handlers/feed.ts +31 -32
- package/templates/agent/src/shared/handlers/git.ts +286 -243
- package/templates/agent/src/shared/handlers/index.ts +1 -0
- package/templates/agent/src/shared/handlers/rules.ts +31 -31
- package/templates/agent/src/shared/handlers/todo.ts +31 -31
- package/templates/agent/src/shared/http-routes.ts +250 -0
- package/templates/agent/src/shared/lib/__tests__/web-server.test.ts +190 -0
- package/templates/agent/src/shared/lib/bash-security.ts +43 -43
- package/templates/agent/src/shared/lib/logger.ts +117 -95
- package/templates/agent/src/shared/lib/web-server.ts +128 -0
- package/templates/agent/src/shared/modules/debug.ts +8 -0
- package/templates/agent/src/shared/rpc-schema.ts +16 -3
- package/templates/agent/test-upload.txt +0 -0
- package/templates/agent/tsconfig.ipc.json +14 -0
- package/templates/agent/tsconfig.json +13 -3
- package/templates/chat/eslint.config.mjs +15 -2
- package/templates/chat/package.json +13 -2
- package/templates/chat/src/__tests__/hybrid-mode.test.ts +125 -0
- package/templates/chat/src/__tests__/server-config-security.test.ts +55 -0
- package/templates/chat/src/__tests__/server-config.test.ts +46 -44
- package/templates/chat/src/bun/index.ts +94 -44
- package/templates/chat/src/bun/three.d.ts +1 -0
- package/templates/chat/src/gateway/http-routes.ts +1 -1
- package/templates/chat/src/gateway/ws-handler.ts +84 -56
- package/templates/chat/src/mainview/App.tsx +6 -0
- package/templates/chat/src/mainview/__tests__/i18n/i18n.test.ts +1 -0
- package/templates/chat/src/mainview/__tests__/theme-variables.test.ts +36 -0
- package/templates/chat/src/mainview/components/common/LanguageSwitcher.tsx +1 -0
- package/templates/chat/src/mainview/components/common/ThemeToggle.tsx +1 -0
- package/templates/chat/src/mainview/hooks/use-input-history.ts +70 -61
- package/templates/chat/src/mainview/lib/api-client.ts +180 -156
- package/templates/chat/src/mainview/lib/rpc-cache.ts +84 -0
- package/templates/chat/src/mainview/main.tsx +10 -6
- package/templates/chat/src/server-config.ts +33 -31
- package/templates/chat/src/server.ts +42 -60
- package/templates/chat/src/shared/handlers/chat.ts +196 -162
- package/templates/chat/src/shared/handlers/debug.ts +12 -0
- package/templates/chat/src/shared/handlers/index.ts +1 -0
- package/templates/chat/src/shared/http-routes.ts +250 -0
- package/templates/chat/src/shared/lib/__tests__/logger.test.ts +92 -0
- package/templates/chat/src/shared/lib/logger.ts +108 -95
- package/templates/chat/src/shared/lib/web-server.ts +128 -0
- package/templates/chat/src/shared/modules/debug.ts +8 -0
- package/templates/chat/src/shared/rpc-schema.ts +3 -2
- package/templates/chat/test-upload.txt +0 -0
- package/templates/chat/tsconfig.ipc.json +14 -0
- package/templates/chat/tsconfig.json +12 -2
- package/templates/general/eslint.config.mjs +15 -2
- package/templates/general/package.json +13 -2
- package/templates/general/src/__tests__/hybrid-mode.test.ts +125 -0
- package/templates/general/src/__tests__/server-config-security.test.ts +55 -0
- package/templates/general/src/__tests__/server-config.test.ts +46 -44
- package/templates/general/src/bun/index.ts +94 -44
- package/templates/general/src/bun/three.d.ts +1 -0
- package/templates/general/src/gateway/http-routes.ts +1 -1
- package/templates/general/src/gateway/ws-handler.ts +84 -56
- package/templates/general/src/mainview/__tests__/i18n/i18n.test.ts +1 -0
- package/templates/general/src/mainview/__tests__/theme-variables.test.ts +36 -0
- package/templates/general/src/mainview/components/common/LanguageSwitcher.tsx +1 -0
- package/templates/general/src/mainview/components/common/ThemeToggle.tsx +1 -0
- package/templates/general/src/mainview/components/feed/FeedPanel.tsx +241 -219
- package/templates/general/src/mainview/components/file-preview/VirtualizedCodeView.tsx +101 -81
- package/templates/general/src/mainview/components/layout/AppLayout.tsx +6 -0
- package/templates/general/src/mainview/components/search/SearchPanel.tsx +429 -378
- package/templates/general/src/mainview/hooks/use-input-history.ts +70 -61
- package/templates/general/src/mainview/lib/api-client.ts +180 -156
- package/templates/general/src/mainview/lib/rpc-cache.ts +84 -0
- package/templates/general/src/mainview/main.tsx +10 -6
- package/templates/general/src/mainview/stores/use-feed-store.ts +107 -107
- package/templates/general/src/mainview/utils/drop-handler.ts +114 -115
- package/templates/general/src/server-config.ts +33 -31
- package/templates/general/src/server.ts +42 -60
- package/templates/general/src/shared/handlers/__tests__/chat.test.ts +165 -160
- package/templates/general/src/shared/handlers/chat.ts +189 -155
- package/templates/general/src/shared/handlers/debug.ts +12 -0
- package/templates/general/src/shared/handlers/feed.ts +38 -40
- package/templates/general/src/shared/handlers/git.ts +286 -243
- package/templates/general/src/shared/handlers/index.ts +1 -0
- package/templates/general/src/shared/http-routes.ts +250 -0
- package/templates/general/src/shared/lib/__tests__/logger.test.ts +92 -0
- package/templates/general/src/shared/lib/logger.ts +117 -95
- package/templates/general/src/shared/lib/web-server.ts +128 -0
- package/templates/general/src/shared/modules/debug.ts +8 -0
- package/templates/general/src/shared/rpc-schema.ts +12 -2
- package/templates/general/test-upload.txt +0 -0
- package/templates/general/tsconfig.ipc.json +14 -0
- package/templates/general/tsconfig.json +12 -2
- package/templates/shared/__tests__/cors-security.test.ts +165 -0
- package/templates/shared/__tests__/file-path-security.test.ts +260 -0
- package/templates/shared/__tests__/http-routes.test.ts +174 -0
- package/templates/shared/__tests__/logger.test.ts +186 -0
- package/templates/shared/components/ErrorBoundary.tsx +59 -0
- package/templates/shared/env.d.ts +11 -0
- package/templates/shared/http-routes.ts +250 -0
- package/templates/shared/logger.ts +129 -0
- package/templates/shared/test-upload.txt +0 -0
- package/templates/shared/vite-base.config.ts +92 -0
- package/templates/shared/vitest-base.config.ts +42 -0
- package/templates/agent/eslint-plugin-rpc/index.js +0 -50
- package/templates/agent/eslint-plugin-rpc/package.json +0 -6
- package/templates/agent/eslint-plugin-rpc/rules/module-file-naming.js +0 -99
- package/templates/agent/eslint-plugin-rpc/rules/no-bare-method.js +0 -78
- package/templates/agent/eslint-plugin-rpc/rules/no-direct-register.js +0 -65
- package/templates/agent/eslint-plugin-rpc/rules/no-hardcoded-strings.js +0 -69
- package/templates/agent/eslint-plugin-rpc/rules/require-api-client.js +0 -58
- package/templates/agent/eslint-plugin-rpc/rules/require-typed-register.js +0 -78
- package/templates/agent/eslint-plugin-rpc/rules/schema-merge-only.js +0 -55
- package/templates/chat/eslint-plugin-rpc/index.js +0 -50
- package/templates/chat/eslint-plugin-rpc/package.json +0 -6
- package/templates/chat/eslint-plugin-rpc/rules/module-file-naming.js +0 -99
- package/templates/chat/eslint-plugin-rpc/rules/no-bare-method.js +0 -78
- package/templates/chat/eslint-plugin-rpc/rules/no-direct-register.js +0 -65
- package/templates/chat/eslint-plugin-rpc/rules/no-hardcoded-strings.js +0 -69
- package/templates/chat/eslint-plugin-rpc/rules/require-api-client.js +0 -58
- package/templates/chat/eslint-plugin-rpc/rules/require-typed-register.js +0 -78
- package/templates/chat/eslint-plugin-rpc/rules/schema-merge-only.js +0 -55
- package/templates/general/eslint-plugin-rpc/index.js +0 -50
- package/templates/general/eslint-plugin-rpc/package.json +0 -6
- package/templates/general/eslint-plugin-rpc/rules/module-file-naming.js +0 -99
- package/templates/general/eslint-plugin-rpc/rules/no-bare-method.js +0 -78
- package/templates/general/eslint-plugin-rpc/rules/no-direct-register.js +0 -65
- package/templates/general/eslint-plugin-rpc/rules/no-hardcoded-strings.js +0 -69
- package/templates/general/eslint-plugin-rpc/rules/require-api-client.js +0 -58
- package/templates/general/eslint-plugin-rpc/rules/require-typed-register.js +0 -78
- package/templates/general/eslint-plugin-rpc/rules/schema-merge-only.js +0 -55
package/package.json
CHANGED
package/src/commands/create.ts
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import { resolve } from
|
|
2
|
-
import { resolveTemplateDir, getRootDir } from
|
|
3
|
-
import { copyTemplate } from
|
|
1
|
+
import { resolve } from "path";
|
|
2
|
+
import { resolveTemplateDir, getRootDir } from "../lib/templates.js";
|
|
3
|
+
import { copyTemplate } from "../lib/copy.js";
|
|
4
4
|
|
|
5
5
|
export async function runCreate(args: string[]): Promise<void> {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
let templateType = "general";
|
|
7
|
+
let customDir: string | undefined;
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
9
|
+
const positional: string[] = [];
|
|
10
|
+
for (let i = 0; i < args.length; i++) {
|
|
11
|
+
const arg = args[i]!;
|
|
12
|
+
if (arg === "--type" && args[i + 1]) {
|
|
13
|
+
templateType = args[++i]!;
|
|
14
|
+
} else if (arg === "--dir" && args[i + 1]) {
|
|
15
|
+
customDir = args[++i]!;
|
|
16
|
+
} else if (!arg.startsWith("--")) {
|
|
17
|
+
positional.push(arg);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
const projectName = positional[0];
|
|
22
|
+
const targetArg = customDir || positional[1];
|
|
23
|
+
if (!projectName) {
|
|
24
|
+
console.log(`
|
|
25
25
|
Usage: create-agent create <name> [--type <type>] [--dir <path>]
|
|
26
26
|
|
|
27
27
|
Options:
|
|
@@ -33,17 +33,17 @@ Examples:
|
|
|
33
33
|
create-agent create my-app --type chat
|
|
34
34
|
create-agent create my-app --dir ~/projects/my-app
|
|
35
35
|
`);
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
const sanitized = projectName.replace(/[^a-zA-Z0-9-_]/g, "-");
|
|
40
|
+
const targetDir = targetArg ? resolve(targetArg) : resolve(process.cwd(), sanitized);
|
|
41
|
+
const rootDir = getRootDir();
|
|
42
|
+
const templateDir = resolveTemplateDir(rootDir, templateType);
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
await copyTemplate({
|
|
45
|
+
projectName: sanitized,
|
|
46
|
+
templateDir,
|
|
47
|
+
targetDir,
|
|
48
|
+
});
|
|
49
49
|
}
|
|
@@ -1,45 +1,50 @@
|
|
|
1
|
-
import { resolve } from
|
|
2
|
-
import { execSync } from
|
|
3
|
-
import { existsSync, readFileSync, mkdirSync } from
|
|
4
|
-
import { createServer } from
|
|
5
|
-
import type { PortEntry } from
|
|
1
|
+
import { resolve } from "path";
|
|
2
|
+
import { execSync } from "child_process";
|
|
3
|
+
import { existsSync, readFileSync, mkdirSync } from "fs";
|
|
4
|
+
import { createServer } from "net";
|
|
5
|
+
import type { PortEntry } from "../lib/types.js";
|
|
6
6
|
|
|
7
|
-
const PORT_REGISTRY = resolve(process.env.HOME ||
|
|
7
|
+
const PORT_REGISTRY = resolve(process.env.HOME || "~", ".pi-agent", "ports.json");
|
|
8
8
|
|
|
9
9
|
function readRegistry(): Record<string, PortEntry> {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
try {
|
|
11
|
+
return JSON.parse(readFileSync(PORT_REGISTRY, "utf-8"));
|
|
12
|
+
} catch {
|
|
13
|
+
return {};
|
|
14
|
+
}
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
function isPortFree(port: number): Promise<boolean> {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
return new Promise((resolve) => {
|
|
19
|
+
const server = createServer();
|
|
20
|
+
server.once("error", () => resolve(false));
|
|
21
|
+
server.once("listening", () => {
|
|
22
|
+
server.close();
|
|
23
|
+
resolve(true);
|
|
24
|
+
});
|
|
25
|
+
server.listen(port);
|
|
26
|
+
});
|
|
24
27
|
}
|
|
25
28
|
|
|
26
|
-
async function findFreePorts(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
async function findFreePorts(
|
|
30
|
+
entries: Record<string, PortEntry>
|
|
31
|
+
): Promise<{ backend: number; vite: number }> {
|
|
32
|
+
const usedPorts = new Set<number>();
|
|
33
|
+
for (const entry of Object.values(entries)) {
|
|
34
|
+
usedPorts.add(entry.port);
|
|
35
|
+
}
|
|
36
|
+
let backend = 3100;
|
|
37
|
+
while (usedPorts.has(backend) || !(await isPortFree(backend))) backend++;
|
|
38
|
+
let vite = 5173;
|
|
39
|
+
while (usedPorts.has(vite) || !(await isPortFree(vite))) vite++;
|
|
40
|
+
return { backend, vite };
|
|
36
41
|
}
|
|
37
42
|
|
|
38
43
|
export async function runWorkspace(args: string[]): Promise<void> {
|
|
39
|
-
|
|
44
|
+
const subCommand = args[0];
|
|
40
45
|
|
|
41
|
-
|
|
42
|
-
|
|
46
|
+
if (!subCommand || subCommand === "--help" || subCommand === "-h") {
|
|
47
|
+
console.log(`
|
|
43
48
|
Usage: create-agent workspace add <name> [--base <branch>]
|
|
44
49
|
|
|
45
50
|
Creates an isolated git worktree in .workspace/<name> with its own branch and ports.
|
|
@@ -51,79 +56,81 @@ Examples:
|
|
|
51
56
|
create-agent workspace add feature-chat-ui
|
|
52
57
|
create-agent workspace add fix-login --base develop
|
|
53
58
|
`);
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (subCommand !== "add") {
|
|
63
|
+
console.error(`Unknown workspace subcommand: "${subCommand}"`);
|
|
64
|
+
console.log("Usage: create-agent workspace add <name>");
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let name = "";
|
|
69
|
+
let baseBranch = "";
|
|
70
|
+
const rest = args.slice(1);
|
|
71
|
+
for (let i = 0; i < rest.length; i++) {
|
|
72
|
+
const arg = rest[i];
|
|
73
|
+
if (arg === undefined) continue;
|
|
74
|
+
if (arg === "--base" && rest[i + 1]) {
|
|
75
|
+
baseBranch = rest[++i] as string;
|
|
76
|
+
} else if (!arg.startsWith("--")) {
|
|
77
|
+
name = arg;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!name) {
|
|
82
|
+
console.error("Error: workspace name is required");
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const projectRoot = process.cwd();
|
|
87
|
+
const workspaceDir = resolve(projectRoot, ".workspace", name);
|
|
88
|
+
|
|
89
|
+
if (existsSync(workspaceDir)) {
|
|
90
|
+
console.error(`Error: workspace "${name}" already exists at ${workspaceDir}`);
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const branchName = `workspace/${name}`;
|
|
95
|
+
const baseArg = baseBranch ? baseBranch : "HEAD";
|
|
96
|
+
|
|
97
|
+
console.log(`Creating workspace: ${name}`);
|
|
98
|
+
console.log(` Branch: ${branchName}`);
|
|
99
|
+
console.log(` Directory: .workspace/${name}`);
|
|
100
|
+
|
|
101
|
+
mkdirSync(resolve(projectRoot, ".workspace"), { recursive: true });
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
execSync(`git worktree add "${workspaceDir}" -b ${branchName} ${baseArg}`, {
|
|
105
|
+
cwd: projectRoot,
|
|
106
|
+
stdio: "pipe",
|
|
107
|
+
});
|
|
108
|
+
} catch (err: unknown) {
|
|
109
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
110
|
+
console.error(`Failed to create worktree: ${message}`);
|
|
111
|
+
process.exit(1);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const registry = readRegistry();
|
|
115
|
+
const ports = await findFreePorts(registry);
|
|
116
|
+
|
|
117
|
+
console.log(` Backend port: ${ports.backend}`);
|
|
118
|
+
console.log(` Vite port: ${ports.vite}`);
|
|
119
|
+
console.log("");
|
|
120
|
+
console.log("Installing dependencies...");
|
|
121
|
+
try {
|
|
122
|
+
execSync("bun install", { cwd: workspaceDir, stdio: "pipe" });
|
|
123
|
+
} catch {
|
|
124
|
+
console.log("(bun install skipped)");
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
console.log("");
|
|
128
|
+
console.log("Workspace created successfully!");
|
|
129
|
+
console.log("");
|
|
130
|
+
console.log("To start developing:");
|
|
131
|
+
console.log(` cd .workspace/${name}`);
|
|
132
|
+
console.log(` PORT=${ports.backend} VITE_PORT=${ports.vite} bun run dev:web`);
|
|
133
|
+
console.log("");
|
|
134
|
+
console.log("Or start from project root:");
|
|
135
|
+
console.log(` PORT=${ports.backend} VITE_PORT=${ports.vite} bun run dev:web`);
|
|
129
136
|
}
|
package/src/lib/copy.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync } from "fs";
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync, unlinkSync } from "fs";
|
|
2
2
|
import { join, resolve } from "path";
|
|
3
3
|
import { execSync } from "child_process";
|
|
4
4
|
|
|
@@ -73,6 +73,11 @@ function copySharedModules(monorepoRoot: string, targetDir: string, projectName:
|
|
|
73
73
|
const destSharedDir = join(targetDir, "shared");
|
|
74
74
|
copyAndReplace(sharedDir, destSharedDir, projectName);
|
|
75
75
|
|
|
76
|
+
for (const f of ["http-routes.ts", "logger.ts"]) {
|
|
77
|
+
const p = join(destSharedDir, f);
|
|
78
|
+
if (existsSync(p)) unlinkSync(p);
|
|
79
|
+
}
|
|
80
|
+
|
|
76
81
|
const tsconfigPath = join(targetDir, "tsconfig.json");
|
|
77
82
|
if (existsSync(tsconfigPath)) {
|
|
78
83
|
let tsconfig = readFileSync(tsconfigPath, "utf-8");
|
|
@@ -173,6 +178,7 @@ function updatePackageJson(targetDir: string, _projectName: string): void {
|
|
|
173
178
|
let inRpcSection = false;
|
|
174
179
|
for (let i = 0; i < lines.length; i++) {
|
|
175
180
|
const line = lines[i];
|
|
181
|
+
if (line === undefined) continue;
|
|
176
182
|
|
|
177
183
|
if (line.includes("import rpcPlugin") && line.includes("@dyyz1993/eslint-plugin-rpc")) {
|
|
178
184
|
continue;
|
|
@@ -224,6 +230,23 @@ export async function copyTemplate(options: CopyOptions): Promise<void> {
|
|
|
224
230
|
if (isMonorepo) {
|
|
225
231
|
copyTraeRules(localRoot, targetDir, projectName);
|
|
226
232
|
copySharedModules(localRoot, targetDir, projectName);
|
|
233
|
+
} else {
|
|
234
|
+
const publishedShared = resolve(import.meta.dir, "..", "..", "templates", "shared");
|
|
235
|
+
if (existsSync(publishedShared)) {
|
|
236
|
+
copyAndReplace(publishedShared, join(targetDir, "shared"), projectName);
|
|
237
|
+
for (const f of ["http-routes.ts", "logger.ts"]) {
|
|
238
|
+
const p = join(targetDir, "shared", f);
|
|
239
|
+
if (existsSync(p)) unlinkSync(p);
|
|
240
|
+
}
|
|
241
|
+
const tsconfigPath = join(targetDir, "tsconfig.json");
|
|
242
|
+
if (existsSync(tsconfigPath)) {
|
|
243
|
+
let tsconfig = readFileSync(tsconfigPath, "utf-8");
|
|
244
|
+
tsconfig = tsconfig.replace(/"\.\.\/shared\/\*"/g, '"./shared/*"');
|
|
245
|
+
tsconfig = tsconfig.replace(/"\.\.\/shared"/g, '"./shared"');
|
|
246
|
+
writeFileSync(tsconfigPath, tsconfig);
|
|
247
|
+
}
|
|
248
|
+
cleanSharedViteConfig(join(targetDir, "shared"));
|
|
249
|
+
}
|
|
227
250
|
}
|
|
228
251
|
cleanViteConfig(targetDir);
|
|
229
252
|
updatePackageJson(targetDir, projectName);
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const { app, BrowserWindow, ipcMain } = require('electron');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
let mainWindow;
|
|
5
|
+
|
|
6
|
+
function createWindow() {
|
|
7
|
+
mainWindow = new BrowserWindow({
|
|
8
|
+
width: 1200,
|
|
9
|
+
height: 800,
|
|
10
|
+
webPreferences: {
|
|
11
|
+
preload: path.join(__dirname, 'preload.js'),
|
|
12
|
+
nodeIntegration: false,
|
|
13
|
+
contextIsolation: true,
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
if (process.env.NODE_ENV === 'development') {
|
|
18
|
+
mainWindow.loadURL('http://localhost:5173');
|
|
19
|
+
} else {
|
|
20
|
+
mainWindow.loadFile(path.join(__dirname, '../dist/index.html'));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
mainWindow.on('closed', () => {
|
|
24
|
+
mainWindow = null;
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
app.whenReady().then(() => {
|
|
29
|
+
createWindow();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
app.on('window-all-closed', () => {
|
|
33
|
+
if (process.platform !== 'darwin') {
|
|
34
|
+
app.quit();
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
app.on('activate', () => {
|
|
39
|
+
if (BrowserWindow.getAllWindows().length === 0) {
|
|
40
|
+
createWindow();
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
ipcMain.handle('ping', async () => {
|
|
45
|
+
return 'pong';
|
|
46
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"appId": "com.piagent.app",
|
|
3
|
+
"productName": "Pi Agent",
|
|
4
|
+
"copyright": "Copyright © 2024 dyyz1993",
|
|
5
|
+
"directories": {
|
|
6
|
+
"output": "dist-electron",
|
|
7
|
+
"buildResources": "build"
|
|
8
|
+
},
|
|
9
|
+
"files": ["dist/**/*", "electron/**/*", "package.json"],
|
|
10
|
+
"mac": {
|
|
11
|
+
"category": "public.app-category.developer-tools",
|
|
12
|
+
"hardenedRuntime": true,
|
|
13
|
+
"gatekeeperAssess": false,
|
|
14
|
+
"entitlements": ["com.apple.security.cs.allow-jit"],
|
|
15
|
+
"target": [
|
|
16
|
+
{
|
|
17
|
+
"target": "dmg",
|
|
18
|
+
"arch": ["x64", "arm64"]
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
"win": {
|
|
23
|
+
"target": [
|
|
24
|
+
{
|
|
25
|
+
"target": "nsis",
|
|
26
|
+
"arch": ["x64"]
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"artifactName": "${productName}-${version}-${arch}.${ext}"
|
|
30
|
+
},
|
|
31
|
+
"linux": {
|
|
32
|
+
"target": ["AppImage", "deb"],
|
|
33
|
+
"category": "Development"
|
|
34
|
+
},
|
|
35
|
+
"publish": {
|
|
36
|
+
"provider": "github",
|
|
37
|
+
"owner": "dyyz1993",
|
|
38
|
+
"repo": "pi-agent-app"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import js from '@eslint/js';
|
|
2
2
|
import tseslint from 'typescript-eslint';
|
|
3
|
-
import rpcPlugin from '
|
|
3
|
+
import rpcPlugin from '@dyyz1993/eslint-plugin-rpc';
|
|
4
|
+
import reactHooks from 'eslint-plugin-react-hooks';
|
|
5
|
+
import reactRefresh from 'eslint-plugin-react-refresh';
|
|
6
|
+
import jsxA11y from 'eslint-plugin-jsx-a11y';
|
|
4
7
|
|
|
5
8
|
export default tseslint.config(
|
|
6
9
|
js.configs.recommended,
|
|
@@ -10,7 +13,8 @@ export default tseslint.config(
|
|
|
10
13
|
'node_modules/**',
|
|
11
14
|
'build/**',
|
|
12
15
|
'dist/**',
|
|
13
|
-
'
|
|
16
|
+
'dist-electron/**',
|
|
17
|
+
'electron/**',
|
|
14
18
|
'postcss.config.js',
|
|
15
19
|
'tailwind.config.js',
|
|
16
20
|
],
|
|
@@ -19,8 +23,19 @@ export default tseslint.config(
|
|
|
19
23
|
files: ['src/**/*.{ts,tsx}'],
|
|
20
24
|
plugins: {
|
|
21
25
|
rpc: rpcPlugin,
|
|
26
|
+
'react-hooks': reactHooks,
|
|
27
|
+
'react-refresh': reactRefresh,
|
|
28
|
+
'jsx-a11y': jsxA11y,
|
|
22
29
|
},
|
|
23
30
|
rules: {
|
|
31
|
+
...reactHooks.configs.recommended.rules,
|
|
32
|
+
'react-hooks/rules-of-hooks': 'warn',
|
|
33
|
+
'react-hooks/exhaustive-deps': 'warn',
|
|
34
|
+
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
|
|
35
|
+
...jsxA11y.configs.recommended.rules,
|
|
36
|
+
'jsx-a11y/click-events-have-key-events': 'warn',
|
|
37
|
+
'jsx-a11y/no-static-element-interactions': 'warn',
|
|
38
|
+
'jsx-a11y/no-autofocus': 'warn',
|
|
24
39
|
// TS 严格规则
|
|
25
40
|
'@typescript-eslint/no-explicit-any': 'error',
|
|
26
41
|
'@typescript-eslint/no-empty-object-type': ['error', { allowObjectTypes: 'always', allowInterfaces: 'with-single-extends' }],
|
|
@@ -2,6 +2,54 @@
|
|
|
2
2
|
"name": "pi-agent-app",
|
|
3
3
|
"version": "1.0.0",
|
|
4
4
|
"description": "Coding agent template with Bash, Rules, and Todo management",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "xuyingzhou",
|
|
7
|
+
"email": "xuyingzhou@tuzhanai.com"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/dyyz1993/pi-agent-template",
|
|
10
|
+
"main": "electron/main.js",
|
|
11
|
+
"build": {
|
|
12
|
+
"appId": "com.piagent.app",
|
|
13
|
+
"productName": "Pi Agent",
|
|
14
|
+
"directories": {
|
|
15
|
+
"output": "dist-electron"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist/**/*",
|
|
19
|
+
"electron/**/*",
|
|
20
|
+
"package.json"
|
|
21
|
+
],
|
|
22
|
+
"mac": {
|
|
23
|
+
"category": "public.app-category.developer-tools",
|
|
24
|
+
"target": [
|
|
25
|
+
{
|
|
26
|
+
"target": "dmg",
|
|
27
|
+
"arch": [
|
|
28
|
+
"x64",
|
|
29
|
+
"arm64"
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
"win": {
|
|
35
|
+
"target": [
|
|
36
|
+
{
|
|
37
|
+
"target": "nsis",
|
|
38
|
+
"arch": [
|
|
39
|
+
"x64"
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
"linux": {
|
|
45
|
+
"maintainer": "xuyingzhou <xuyingzhou@tuzhanai.com>",
|
|
46
|
+
"target": [
|
|
47
|
+
"AppImage",
|
|
48
|
+
"deb"
|
|
49
|
+
],
|
|
50
|
+
"category": "Development"
|
|
51
|
+
}
|
|
52
|
+
},
|
|
5
53
|
"scripts": {
|
|
6
54
|
"start": "vite build && electrobun dev",
|
|
7
55
|
"dev": "electrobun dev --watch",
|
|
@@ -9,6 +57,14 @@
|
|
|
9
57
|
"dev:server": "bun src/server.ts",
|
|
10
58
|
"build": "vite build",
|
|
11
59
|
"build:canary": "vite build && electrobun build --env=canary",
|
|
60
|
+
"build:mac": "vite build && electrobun build --env=canary",
|
|
61
|
+
"build:win": "vite build && electrobun build --env=canary",
|
|
62
|
+
"build:linux": "vite build && electrobun build --env=canary",
|
|
63
|
+
"electron:dev": "vite build && electron .",
|
|
64
|
+
"electron:build": "vite build && electron-builder --mac --win --linux",
|
|
65
|
+
"electron:build:mac": "vite build && electron-builder --mac",
|
|
66
|
+
"electron:build:win": "vite build && electron-builder --win",
|
|
67
|
+
"electron:build:linux": "vite build && electron-builder --linux",
|
|
12
68
|
"lint": "eslint .",
|
|
13
69
|
"lint:fix": "eslint . --fix",
|
|
14
70
|
"test": "vitest run",
|
|
@@ -19,7 +75,7 @@
|
|
|
19
75
|
"dependencies": {
|
|
20
76
|
"@dyyz1993/rpc-core": "^1.2.0",
|
|
21
77
|
"@tanstack/react-virtual": "^3.13.24",
|
|
22
|
-
"electrobun": "1.
|
|
78
|
+
"electrobun": "1.18.1",
|
|
23
79
|
"lucide-react": "^1.9.0",
|
|
24
80
|
"prism-react-renderer": "^2.4.1",
|
|
25
81
|
"react": "^18.3.1",
|
|
@@ -33,7 +89,8 @@
|
|
|
33
89
|
"zustand": "^5.0.12"
|
|
34
90
|
},
|
|
35
91
|
"devDependencies": {
|
|
36
|
-
|
|
92
|
+
"@dyyz1993/eslint-plugin-rpc": "workspace:*",
|
|
93
|
+
"@eslint/js": "^9.0.0",
|
|
37
94
|
"@testing-library/jest-dom": "^6.9.1",
|
|
38
95
|
"@testing-library/react": "^16.3.2",
|
|
39
96
|
"@testing-library/user-event": "^14.6.1",
|
|
@@ -44,7 +101,12 @@
|
|
|
44
101
|
"@vitejs/plugin-react": "^4.3.4",
|
|
45
102
|
"autoprefixer": "^10.4.20",
|
|
46
103
|
"concurrently": "^9.1.0",
|
|
104
|
+
"electron": "^42.1.0",
|
|
105
|
+
"electron-builder": "^26.8.1",
|
|
47
106
|
"eslint": "^9.0.0",
|
|
107
|
+
"eslint-plugin-jsx-a11y": "^6.10.0",
|
|
108
|
+
"eslint-plugin-react-hooks": "^5.2.0",
|
|
109
|
+
"eslint-plugin-react-refresh": "^0.4.20",
|
|
48
110
|
"happy-dom": "^20.9.0",
|
|
49
111
|
"husky": "^9.1.0",
|
|
50
112
|
"jsdom": "^29.1.1",
|
|
@@ -53,6 +115,10 @@
|
|
|
53
115
|
"typescript": "^5.7.2",
|
|
54
116
|
"typescript-eslint": "^8.0.0",
|
|
55
117
|
"vite": "^6.0.3",
|
|
56
|
-
"vitest": "^4.1.5"
|
|
118
|
+
"vitest": "^4.1.5",
|
|
119
|
+
"ws": "^8.18.0"
|
|
120
|
+
},
|
|
121
|
+
"overrides": {
|
|
122
|
+
"minimatch": "^10.0.1"
|
|
57
123
|
}
|
|
58
124
|
}
|