@dyyz1993/create-agent 2.0.1 → 2.1.1

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 (60) hide show
  1. package/package.json +1 -1
  2. package/src/commands/create.ts +31 -31
  3. package/src/commands/workspace.ts +112 -105
  4. package/src/lib/copy.ts +117 -12
  5. package/templates/agent/.prettierignore +6 -0
  6. package/templates/agent/.prettierrc +9 -0
  7. package/templates/agent/commitlint.config.js +8 -0
  8. package/templates/agent/electron/main.js +46 -0
  9. package/templates/agent/electron/preload.js +5 -0
  10. package/templates/agent/electron-builder.json +40 -0
  11. package/templates/agent/eslint.config.mjs +2 -0
  12. package/templates/agent/package.json +75 -2
  13. package/templates/agent/src/mainview/App.tsx +29 -26
  14. package/templates/agent/src/mainview/components/chat/ChatPanel.tsx +88 -88
  15. package/templates/agent/src/mainview/components/file-preview/VirtualizedCodeView.tsx +105 -81
  16. package/templates/agent/src/mainview/components/search/SearchPanel.tsx +427 -378
  17. package/templates/agent/src/mainview/components/todo/TodoPanel.tsx +3 -3
  18. package/templates/agent/src/mainview/hooks/use-input-history.ts +70 -61
  19. package/templates/agent/src/mainview/lib/api-client.ts +1 -4
  20. package/templates/agent/src/mainview/main.tsx +4 -10
  21. package/templates/agent/src/mainview/stores/use-feed-store.ts +107 -107
  22. package/templates/agent/src/mainview/utils/drop-handler.ts +114 -115
  23. package/templates/agent/src/server-config.ts +1 -1
  24. package/templates/agent/src/server.ts +1 -2
  25. package/templates/agent/src/shared/handlers/chat.ts +5 -5
  26. package/templates/agent/src/shared/handlers/debug.ts +5 -1
  27. package/templates/agent/src/shared/handlers/git.ts +286 -243
  28. package/templates/agent/src/shared/http-routes.ts +1 -1
  29. package/templates/agent/src/shared/lib/bash-security.ts +43 -43
  30. package/templates/agent/tsconfig.ipc.json +5 -1
  31. package/templates/agent/tsconfig.json +3 -1
  32. package/templates/chat/package.json +3 -0
  33. package/templates/chat/src/mainview/hooks/use-input-history.ts +70 -61
  34. package/templates/chat/src/mainview/lib/api-client.ts +2 -5
  35. package/templates/chat/src/mainview/main.tsx +10 -7
  36. package/templates/chat/src/server-config.ts +1 -1
  37. package/templates/chat/src/server.ts +1 -2
  38. package/templates/chat/src/shared/handlers/chat.ts +5 -5
  39. package/templates/chat/src/shared/handlers/debug.ts +5 -1
  40. package/templates/chat/src/shared/http-routes.ts +1 -1
  41. package/templates/chat/tsconfig.ipc.json +5 -1
  42. package/templates/chat/tsconfig.json +12 -2
  43. package/templates/general/package.json +3 -0
  44. package/templates/general/src/mainview/components/file-preview/VirtualizedCodeView.tsx +101 -81
  45. package/templates/general/src/mainview/components/search/SearchPanel.tsx +429 -378
  46. package/templates/general/src/mainview/hooks/use-input-history.ts +70 -61
  47. package/templates/general/src/mainview/lib/api-client.ts +2 -5
  48. package/templates/general/src/mainview/main.tsx +10 -7
  49. package/templates/general/src/mainview/stores/use-feed-store.ts +107 -107
  50. package/templates/general/src/mainview/utils/drop-handler.ts +114 -115
  51. package/templates/general/src/server-config.ts +1 -1
  52. package/templates/general/src/server.ts +1 -2
  53. package/templates/general/src/shared/handlers/chat.ts +5 -5
  54. package/templates/general/src/shared/handlers/debug.ts +5 -1
  55. package/templates/general/src/shared/handlers/git.ts +286 -243
  56. package/templates/general/src/shared/http-routes.ts +1 -1
  57. package/templates/general/tsconfig.ipc.json +5 -1
  58. package/templates/general/tsconfig.json +12 -2
  59. package/templates/shared/components/ErrorBoundary.tsx +50 -49
  60. package/templates/shared/http-routes.ts +210 -190
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dyyz1993/create-agent",
3
- "version": "2.0.1",
3
+ "version": "2.1.1",
4
4
  "description": "Create Agent project scaffolding CLI",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,27 +1,27 @@
1
- import { resolve } from 'path';
2
- import { resolveTemplateDir, getRootDir } from '../lib/templates.js';
3
- import { copyTemplate } from '../lib/copy.js';
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
- let templateType = 'general';
7
- let customDir: string | undefined;
6
+ let templateType = "general";
7
+ let customDir: string | undefined;
8
8
 
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
- }
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
- const projectName = positional[0];
22
- const targetArg = customDir || positional[1];
23
- if (!projectName) {
24
- console.log(`
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
- process.exit(1);
37
- }
36
+ process.exit(1);
37
+ }
38
38
 
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);
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
- await copyTemplate({
45
- projectName: sanitized,
46
- templateDir,
47
- targetDir,
48
- });
44
+ await copyTemplate({
45
+ projectName: sanitized,
46
+ templateDir,
47
+ targetDir,
48
+ });
49
49
  }
@@ -1,45 +1,50 @@
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';
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 || '~', '.pi-agent', 'ports.json');
7
+ const PORT_REGISTRY = resolve(process.env.HOME || "~", ".pi-agent", "ports.json");
8
8
 
9
9
  function readRegistry(): Record<string, PortEntry> {
10
- try {
11
- return JSON.parse(readFileSync(PORT_REGISTRY, 'utf-8'));
12
- } catch {
13
- return {};
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
- return new Promise((resolve) => {
19
- const server = createServer();
20
- server.once('error', () => resolve(false));
21
- server.once('listening', () => { server.close(); resolve(true); });
22
- server.listen(port);
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(entries: Record<string, PortEntry>): Promise<{ backend: number; vite: number }> {
27
- const usedPorts = new Set<number>();
28
- for (const entry of Object.values(entries)) {
29
- usedPorts.add(entry.port);
30
- }
31
- let backend = 3100;
32
- while (usedPorts.has(backend) || !(await isPortFree(backend))) backend++;
33
- let vite = 5173;
34
- while (usedPorts.has(vite) || !(await isPortFree(vite))) vite++;
35
- return { backend, vite };
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
- const subCommand = args[0];
44
+ const subCommand = args[0];
40
45
 
41
- if (!subCommand || subCommand === '--help' || subCommand === '-h') {
42
- console.log(`
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
- return;
55
- }
56
-
57
- if (subCommand !== 'add') {
58
- console.error(`Unknown workspace subcommand: "${subCommand}"`);
59
- console.log('Usage: create-agent workspace add <name>');
60
- return;
61
- }
62
-
63
- let name = '';
64
- let baseBranch = '';
65
- const rest = args.slice(1);
66
- for (let i = 0; i < rest.length; i++) {
67
- if (rest[i] === '--base' && rest[i + 1]) {
68
- baseBranch = rest[++i];
69
- } else if (!rest[i].startsWith('--')) {
70
- name = rest[i];
71
- }
72
- }
73
-
74
- if (!name) {
75
- console.error('Error: workspace name is required');
76
- process.exit(1);
77
- }
78
-
79
- const projectRoot = process.cwd();
80
- const workspaceDir = resolve(projectRoot, '.workspace', name);
81
-
82
- if (existsSync(workspaceDir)) {
83
- console.error(`Error: workspace "${name}" already exists at ${workspaceDir}`);
84
- process.exit(1);
85
- }
86
-
87
- const branchName = `workspace/${name}`;
88
- const baseArg = baseBranch ? baseBranch : 'HEAD';
89
-
90
- console.log(`Creating workspace: ${name}`);
91
- console.log(` Branch: ${branchName}`);
92
- console.log(` Directory: .workspace/${name}`);
93
-
94
- mkdirSync(resolve(projectRoot, '.workspace'), { recursive: true });
95
-
96
- try {
97
- execSync(`git worktree add "${workspaceDir}" -b ${branchName} ${baseArg}`, {
98
- cwd: projectRoot,
99
- stdio: 'pipe',
100
- });
101
- } catch (err: unknown) {
102
- const message = err instanceof Error ? err.message : String(err);
103
- console.error(`Failed to create worktree: ${message}`);
104
- process.exit(1);
105
- }
106
-
107
- const registry = readRegistry();
108
- const ports = await findFreePorts(registry);
109
-
110
- console.log(` Backend port: ${ports.backend}`);
111
- console.log(` Vite port: ${ports.vite}`);
112
- console.log('');
113
- console.log('Installing dependencies...');
114
- try {
115
- execSync('bun install', { cwd: workspaceDir, stdio: 'pipe' });
116
- } catch {
117
- console.log('(bun install skipped)');
118
- }
119
-
120
- console.log('');
121
- console.log('Workspace created successfully!');
122
- console.log('');
123
- console.log('To start developing:');
124
- console.log(` cd .workspace/${name}`);
125
- console.log(` PORT=${ports.backend} VITE_PORT=${ports.vite} bun run dev:web`);
126
- console.log('');
127
- console.log('Or start from project root:');
128
- console.log(` PORT=${ports.backend} VITE_PORT=${ports.vite} bun run dev:web`);
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,12 @@
1
- import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync, unlinkSync } from "fs";
1
+ import {
2
+ readFileSync,
3
+ writeFileSync,
4
+ mkdirSync,
5
+ existsSync,
6
+ readdirSync,
7
+ unlinkSync,
8
+ chmodSync,
9
+ } from "fs";
2
10
  import { join, resolve } from "path";
3
11
  import { execSync } from "child_process";
4
12
 
@@ -178,6 +186,7 @@ function updatePackageJson(targetDir: string, _projectName: string): void {
178
186
  let inRpcSection = false;
179
187
  for (let i = 0; i < lines.length; i++) {
180
188
  const line = lines[i];
189
+ if (line === undefined) continue;
181
190
 
182
191
  if (line.includes("import rpcPlugin") && line.includes("@dyyz1993/eslint-plugin-rpc")) {
183
192
  continue;
@@ -265,19 +274,115 @@ export async function copyTemplate(options: CopyOptions): Promise<void> {
265
274
 
266
275
  const huskyDir = join(targetDir, ".husky");
267
276
  mkdirSync(huskyDir, { recursive: true });
268
- writeFileSync(
269
- join(huskyDir, "pre-commit"),
270
- [
271
- "#!/bin/sh",
272
- "bun run lint",
273
- 'ERRORS=$(bunx tsc --noEmit 2>&1 | grep "error TS" | grep -v "node_modules" || true)',
274
- 'if [ -n "$ERRORS" ]; then',
275
- ' echo "$ERRORS"',
276
- " exit 1",
277
- "fi",
278
- ].join("\n") + "\n"
277
+
278
+ const hook = (name: string, content: string) => {
279
+ const p = join(huskyDir, name);
280
+ writeFileSync(p, content);
281
+ chmodSync(p, 0o755);
282
+ };
283
+
284
+ hook(
285
+ "pre-commit",
286
+ `#!/bin/sh
287
+ npx lint-staged
288
+
289
+ STAGED_TS=$(git diff --cached --name-only --diff-filter=ACMR | grep -c '\\.tsx\\?$' || true)
290
+
291
+ if [ "$STAGED_TS" -gt 0 ]; then
292
+ echo "⏳ Type checking..."
293
+ bunx tsc --noEmit 2>&1 | grep "error TS" | grep -v "node_modules" && exit 1 || true
294
+ fi
295
+
296
+ echo "✅ Pre-commit checks passed"
297
+ `
298
+ );
299
+
300
+ hook(
301
+ "commit-msg",
302
+ `#!/bin/sh
303
+ npx --no -- commitlint --edit "$1"
304
+ `
305
+ );
306
+
307
+ hook(
308
+ "pre-push",
309
+ `#!/bin/sh
310
+ echo "⏳ Linting..."
311
+ bun run lint || { echo "❌ Lint failed."; exit 1; }
312
+
313
+ echo "⏳ Checking lockfile sync..."
314
+ git diff --name-only HEAD -- pnpm-lock.yaml | grep -q . && { echo "⚠️ pnpm-lock.yaml has uncommitted changes."; exit 1; }
315
+
316
+ echo "✅ Pre-push checks passed (full tests run in CI). Pushing..."
317
+ `
279
318
  );
280
319
 
320
+ hook(
321
+ "prepare-commit-msg",
322
+ `#!/bin/sh
323
+ COMMIT_MSG_FILE="$1"
324
+ COMMIT_SOURCE="$2"
325
+
326
+ if [ "$COMMIT_SOURCE" = "merge" ] || [ "$COMMIT_SOURCE" = "squash" ] || [ "$COMMIT_SOURCE" = "commit" ]; then
327
+ exit 0
328
+ fi
329
+
330
+ FIRST_LINE=$(head -n1 "$COMMIT_MSG_FILE")
331
+
332
+ if echo "$FIRST_LINE" | grep -qE '^[a-z]+(\\([^)]+\\))?:'; then
333
+ exit 0
334
+ fi
335
+
336
+ STAGED=$(git diff --cached --name-only)
337
+
338
+ if echo "$STAGED" | grep -q "^src/"; then
339
+ SCOPE="app"
340
+ elif echo "$STAGED" | grep -q "^components/"; then
341
+ SCOPE="ui"
342
+ elif echo "$STAGED" | grep -q "^server/"; then
343
+ SCOPE="server"
344
+ fi
345
+
346
+ if [ -n "$SCOPE" ]; then
347
+ sed -i.bak -E "s/^([a-z]+)(\\([^)]+\\))?:/\\1($SCOPE):/" "$COMMIT_MSG_FILE"
348
+ rm -f "\${COMMIT_MSG_FILE}.bak"
349
+ fi
350
+ `
351
+ );
352
+
353
+ hook(
354
+ "post-merge",
355
+ `#!/bin/sh
356
+ echo "⏳ Checking for dependency changes..."
357
+ CHANGED=$(git diff HEAD@{1} --name-only HEAD)
358
+
359
+ if echo "$CHANGED" | grep -q "pnpm-lock.yaml\\|package.json"; then
360
+ echo "📦 Dependencies changed, running pnpm install..."
361
+ pnpm install
362
+ fi
363
+ `
364
+ );
365
+
366
+ hook(
367
+ "post-checkout",
368
+ `#!/bin/sh
369
+ PREV_HEAD="$1"
370
+ NEW_HEAD="$2"
371
+ IS_BRANCH="$3"
372
+
373
+ if [ "$IS_BRANCH" = "1" ]; then
374
+ CHANGED=$(git diff --name-only "$PREV_HEAD" "$NEW_HEAD" 2>/dev/null)
375
+ if echo "$CHANGED" | grep -q "pnpm-lock.yaml\\|package.json"; then
376
+ echo "📦 Dependencies changed between branches, running pnpm install..."
377
+ pnpm install
378
+ fi
379
+ fi
380
+ `
381
+ );
382
+
383
+ console.log("Initializing husky...");
384
+ execSync("pnpm run prepare", { cwd: targetDir, stdio: "pipe" });
385
+
281
386
  execSync("git add -A", { cwd: targetDir, stdio: "pipe" });
282
387
 
283
388
  try {
@@ -0,0 +1,6 @@
1
+ node_modules
2
+ build
3
+ dist
4
+ dist-electron
5
+ pnpm-lock.yaml
6
+ *.min.js
@@ -0,0 +1,9 @@
1
+ {
2
+ "semi": true,
3
+ "singleQuote": true,
4
+ "trailingComma": "all",
5
+ "printWidth": 100,
6
+ "tabWidth": 2,
7
+ "arrowParens": "always",
8
+ "endOfLine": "lf"
9
+ }
@@ -0,0 +1,8 @@
1
+ export default {
2
+ extends: ['@commitlint/config-conventional'],
3
+ rules: {
4
+ 'type-enum': [2, 'always', ['feat', 'fix', 'docs', 'style', 'refactor', 'test', 'chore', 'revert', 'perf']],
5
+ 'subject-max-length': [2, 'always', 80],
6
+ 'subject-case': [0],
7
+ },
8
+ };
@@ -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,5 @@
1
+ const { contextBridge, ipcRenderer } = require('electron');
2
+
3
+ contextBridge.exposeInMainWorld('electronAPI', {
4
+ ping: () => ipcRenderer.invoke('ping'),
5
+ });
@@ -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
+ }
@@ -13,6 +13,8 @@ export default tseslint.config(
13
13
  'node_modules/**',
14
14
  'build/**',
15
15
  'dist/**',
16
+ 'dist-electron/**',
17
+ 'electron/**',
16
18
  'postcss.config.js',
17
19
  'tailwind.config.js',
18
20
  ],