comfy-pr 0.2.26 → 1.0.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 (100) hide show
  1. package/README.md +258 -157
  2. package/bot/IdleWaiter.ts +31 -0
  3. package/bot/RestartManager.spec.ts +163 -0
  4. package/bot/RestartManager.ts +190 -0
  5. package/bot/WorkingTasksManager.spec.ts +154 -0
  6. package/bot/cli.ts +1171 -0
  7. package/bot/codesearch-ai-wip.ts +351 -0
  8. package/bot/error-collector.ts +133 -0
  9. package/bot/index.ts +14 -0
  10. package/bot/restart-example.ts +99 -0
  11. package/bot/slack-bolt.ts +688 -0
  12. package/bot/slack-bot.ts +1575 -0
  13. package/bot/state.ts +19 -0
  14. package/bot/templateLoader.test.ts +84 -0
  15. package/bot/templateLoader.ts +92 -0
  16. package/next.config.ts +26 -0
  17. package/package.json +161 -41
  18. package/post-summary.ts +44 -0
  19. package/src/Authors.ts +2 -2
  20. package/src/CMNodes.ts +3 -3
  21. package/src/CNRepos.ts +30 -7
  22. package/src/CRNodes.ts +11 -9
  23. package/src/CRPulls.ts +3 -0
  24. package/src/EmailTasks.ts +27 -9
  25. package/src/FORK_OWNER.ts +3 -1
  26. package/src/FollowRules.ts +3 -3
  27. package/src/GithubIssueComments.ts +1 -1
  28. package/src/Totals.ts +9 -8
  29. package/src/WorkerInstances.ts +31 -8
  30. package/src/addCommentAction.ts +19 -11
  31. package/src/analyzePullsStatus.ts +39 -17
  32. package/src/analyzeTotals.ts +19 -11
  33. package/src/bypassRepos.ts +6 -5
  34. package/src/checkPRsFailures.ts +13 -8
  35. package/src/cli.test.ts +2 -0
  36. package/src/cli.ts +1 -1
  37. package/src/constants.ts +2 -0
  38. package/src/createComfyRegistryPRsFromCandidates.ts +20 -12
  39. package/src/createComfyRegistryPullRequests.ts +35 -10
  40. package/src/createGithubForkForRepo.ts +36 -11
  41. package/src/createGithubPullRequest.ts +83 -33
  42. package/src/createIssueComment.ts +4 -4
  43. package/src/fetchComfyRegistryNodes.ts +34 -4
  44. package/src/fetchCurrentGeoInfo.ts +3 -1
  45. package/src/fetchRelatedPullWithComments.ts +1 -1
  46. package/src/fetchRepoDescriptionMap.ts +1 -4
  47. package/src/followRuleSchema.ts +10 -4
  48. package/src/getBranchWorkingDir.ts +3 -7
  49. package/src/getRepoWorkingDir.ts +2 -3
  50. package/src/gh.spec.ts +571 -0
  51. package/src/ghData.ts +13 -0
  52. package/src/ghPageFlow.ts +33 -0
  53. package/src/ghSubscriber.ts +76 -0
  54. package/src/ghUser.ts +28 -4
  55. package/src/index.ts +13 -4
  56. package/src/initializeFollowRules.ts +11 -4
  57. package/src/logger.spec.ts +95 -0
  58. package/src/logger.ts +46 -0
  59. package/src/makeGpl3LicenseBranch.ts +66 -0
  60. package/src/makePublishBranch.ts +21 -15
  61. package/src/makeTomlBranch.ts +48 -14
  62. package/src/makeUpdateTomlLicenseBranch.ts +40 -44
  63. package/src/matchRelatedPulls.ts +9 -4
  64. package/src/normalizeGithubUrl.spec.ts +131 -0
  65. package/src/normalizeGithubUrl.ts +64 -0
  66. package/src/parseIssueUrl.spec.ts +95 -0
  67. package/src/parseIssueUrl.ts +17 -3
  68. package/src/parseOwnerRepo.spec.ts +147 -0
  69. package/src/parseOwnerRepo.ts +8 -5
  70. package/src/parsePullsState.ts +2 -2
  71. package/src/parseTitleBodyOfMarkdown.ts +1 -1
  72. package/src/pickRepoInfo.ts +37 -0
  73. package/src/postSlackMessage.ts +5 -1
  74. package/src/preload.ts +30 -27
  75. package/src/readTemplateTitle.ts +1 -3
  76. package/src/sendEmailAction.ts +14 -10
  77. package/src/sendGmail.ts +3 -3
  78. package/src/updateAuthorsForGithub.ts +53 -35
  79. package/src/updateAuthorsFromCNRepo.ts +12 -5
  80. package/src/updateCMNodesDuplicationWarnings.ts +14 -9
  81. package/src/updateCMRepos.ts +1 -1
  82. package/src/updateCNRepos.ts +14 -14
  83. package/src/updateCNReposCRPullsComments.ts +7 -5
  84. package/src/updateCNReposInfo.ts +49 -40
  85. package/src/updateCNReposPRCandidate.ts +3 -3
  86. package/src/updateCNReposPulls.ts +9 -5
  87. package/src/updateCNReposPullsDashboard.ts +11 -9
  88. package/src/updateCNReposRelatedPulls.ts +3 -3
  89. package/src/updateCRNodes.ts +24 -5
  90. package/src/updateCRRepos.ts +1 -1
  91. package/src/updateComfyTotals.ts +7 -5
  92. package/src/updateFollowRuleSet.ts +17 -9
  93. package/src/updateOutdatedPullsTemplates.ts +61 -48
  94. package/src/updateSlackMessages.ts +8 -4
  95. package/tailwind.config.ts +7 -1
  96. package/next-env.d.ts +0 -5
  97. package/src/GIT_USEREMAIL.ts +0 -5
  98. package/src/GIT_USERNAME.ts +0 -9
  99. package/src/clone_modify_push_Branches.ts +0 -21
  100. package/src/tomlFillDescription.ts +0 -17
package/bot/state.ts ADDED
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Shared state management for ComfyPR Bot
3
+ * Exports SlackBotState for use across bot modules
4
+ */
5
+
6
+ import { Keyv } from "keyv";
7
+ import KeyvMongodbStore from "keyv-mongodb-store";
8
+ import KeyvNedbStore from "keyv-nedb-store";
9
+ import KeyvNest from "keyv-nest";
10
+ import { db } from "@/src/db";
11
+
12
+ export const SlackBotState = new Keyv(
13
+ KeyvNest(
14
+ new Map(),
15
+ new KeyvNedbStore("./.cache/ComfyPRBotState.jsonl"),
16
+ new KeyvMongodbStore(db.collection("ComfyPRBotState")),
17
+ ),
18
+ { namespace: "", serialize: undefined, deserialize: undefined },
19
+ );
@@ -0,0 +1,84 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { replaceTemplateSlots, loadClaudeMd, loadSkills, loadSkill } from "./templateLoader";
3
+
4
+ describe("Template Loader", () => {
5
+ test("replaceTemplateSlots - basic replacement", () => {
6
+ const template = "Hello ${NAME}, welcome to ${PLACE}!";
7
+ const slots = {
8
+ NAME: "Alice",
9
+ PLACE: "Wonderland",
10
+ };
11
+ const result = replaceTemplateSlots(template, slots);
12
+ expect(result).toBe("Hello Alice, welcome to Wonderland!");
13
+ });
14
+
15
+ test("replaceTemplateSlots - throws on unreplaced slots", () => {
16
+ const template = "Hello ${NAME}, welcome to ${PLACE}!";
17
+ const slots = {
18
+ NAME: "Alice",
19
+ // Missing PLACE
20
+ };
21
+ expect(() => replaceTemplateSlots(template, slots)).toThrow(/unreplaced slots/i);
22
+ });
23
+
24
+ test("replaceTemplateSlots - handles multiple occurrences", () => {
25
+ const template = "${VAR} ${VAR} ${VAR}";
26
+ const slots = { VAR: "test" };
27
+ const result = replaceTemplateSlots(template, slots);
28
+ expect(result).toBe("test test test");
29
+ });
30
+
31
+ test("loadClaudeMd - loads and replaces slots", () => {
32
+ const slots = {
33
+ EVENT_CHANNEL: "C123",
34
+ QUICK_RESPOND_MSG_TS: "1234567890.123456",
35
+ USERNAME: "testuser",
36
+ NEARBY_MESSAGES_YAML: "[]",
37
+ EVENT_TEXT_JSON: '"test message"',
38
+ USER_INTENT: "test intent",
39
+ MY_RESPONSE_MESSAGE_JSON: '"test response"',
40
+ EVENT_THREAD_TS: "1234567890.123456",
41
+ };
42
+ const result = loadClaudeMd(slots);
43
+ expect(result).toContain("ComfyPR-Bot");
44
+ expect(result).toContain("C123");
45
+ // Note: USERNAME and USER_INTENT slots are not used in the current CLAUDE.md template
46
+ expect(result).not.toContain("${");
47
+ });
48
+
49
+ test("loadSkills - loads all skills", () => {
50
+ const slots = {
51
+ EVENT_CHANNEL: "C123",
52
+ QUICK_RESPOND_MSG_TS: "1234567890.123456",
53
+ EVENT_THREAD_TS: "1234567890.123456",
54
+ };
55
+ const skills = loadSkills(slots);
56
+ expect(Object.keys(skills).length).toBeGreaterThan(0);
57
+ expect(skills["slack-messaging"]).toBeDefined();
58
+ expect(skills["slack-file-sharing"]).toBeDefined();
59
+ expect(skills["github-pr-bot"]).toBeDefined();
60
+ expect(skills["slack-messaging"]).toContain("C123");
61
+ expect(skills["slack-messaging"]).not.toContain("${");
62
+ });
63
+
64
+ test("loadSkill - loads specific skill", () => {
65
+ const slots = {
66
+ EVENT_CHANNEL: "C123",
67
+ QUICK_RESPOND_MSG_TS: "1234567890.123456",
68
+ EVENT_THREAD_TS: "1234567890.123456",
69
+ };
70
+ const skill = loadSkill("slack-messaging", slots);
71
+ expect(skill).toContain("Slack Thread Messaging");
72
+ expect(skill).toContain("C123");
73
+ expect(skill).not.toContain("${");
74
+ });
75
+
76
+ test("loadSkill - throws on missing skill", () => {
77
+ const slots = {
78
+ EVENT_CHANNEL: "C123",
79
+ QUICK_RESPOND_MSG_TS: "1234567890.123456",
80
+ EVENT_THREAD_TS: "1234567890.123456",
81
+ };
82
+ expect(() => loadSkill("nonexistent-skill", slots)).toThrow();
83
+ });
84
+ });
@@ -0,0 +1,92 @@
1
+ import { readFileSync, readdirSync } from "fs";
2
+ import { join } from "path";
3
+ import DIE from "@snomiao/die";
4
+
5
+ /**
6
+ * Template slot values interface
7
+ */
8
+ export interface TemplateSlots {
9
+ [key: string]: string;
10
+ }
11
+
12
+ /**
13
+ * Load and replace template slots in a string
14
+ * @param template - Template string with ${SLOT_NAME} placeholders
15
+ * @param slots - Object mapping slot names to values
16
+ * @returns Processed template string
17
+ * @throws Error if unknown slots are unreplaced
18
+ */
19
+ export function replaceTemplateSlots(template: string, slots: TemplateSlots): string {
20
+ let result = template;
21
+
22
+ // Replace all slots
23
+ for (const [key, value] of Object.entries(slots)) {
24
+ const placeholder = `\${${key}}`;
25
+ result = result.replaceAll(placeholder, value);
26
+ }
27
+
28
+ // Check for unreplaced slots
29
+ const unreplacedSlots = result.match(/\$\{[A-Z_][A-Z0-9_]*\}/g);
30
+ if (unreplacedSlots && unreplacedSlots.length > 0) {
31
+ DIE(
32
+ `Template contains unreplaced slots: ${unreplacedSlots.join(", ")}\n` +
33
+ `Available slots: ${Object.keys(slots).join(", ")}\n` +
34
+ `Template preview: ${result.slice(0, 200)}...`,
35
+ );
36
+ }
37
+
38
+ return result;
39
+ }
40
+
41
+ /**
42
+ * Load CLAUDE.md template from .bot/CLAUDE.md
43
+ * @param slots - Template slot values
44
+ * @returns Processed CLAUDE.md content
45
+ */
46
+ export function loadClaudeMd(slots: TemplateSlots): string {
47
+ const templatePath = join(import.meta.dir, "../.bot/CLAUDE.md");
48
+ const template = readFileSync(templatePath, "utf-8");
49
+ return replaceTemplateSlots(template, slots);
50
+ }
51
+
52
+ /**
53
+ * Load all skill templates from .bot/skills/
54
+ * @param slots - Template slot values
55
+ * @returns Object mapping skill names to processed skill content
56
+ */
57
+ export function loadSkills(slots: TemplateSlots): Record<string, string> {
58
+ const skillsDir = join(import.meta.dir, "../.bot/skills");
59
+ const skillDirs = readdirSync(skillsDir, { withFileTypes: true })
60
+ .filter((dirent) => dirent.isDirectory())
61
+ .map((dirent) => dirent.name);
62
+
63
+ const skills: Record<string, string> = {};
64
+
65
+ for (const skillName of skillDirs) {
66
+ const skillPath = join(skillsDir, skillName, "SKILL.md");
67
+ try {
68
+ const template = readFileSync(skillPath, "utf-8");
69
+ skills[skillName] = replaceTemplateSlots(template, slots);
70
+ } catch (error: unknown) {
71
+ DIE(`Failed to load skill '${skillName}' from ${skillPath}: ${(error as Error).message}`);
72
+ }
73
+ }
74
+
75
+ return skills;
76
+ }
77
+
78
+ /**
79
+ * Load a specific skill template
80
+ * @param skillName - Name of the skill (directory name in .bot/skills/)
81
+ * @param slots - Template slot values
82
+ * @returns Processed skill content
83
+ */
84
+ export function loadSkill(skillName: string, slots: TemplateSlots): string {
85
+ const skillPath = join(import.meta.dir, "../.bot/skills", skillName, "SKILL.md");
86
+ try {
87
+ const template = readFileSync(skillPath, "utf-8");
88
+ return replaceTemplateSlots(template, slots);
89
+ } catch (error: unknown) {
90
+ DIE(`Failed to load skill '${skillName}' from ${skillPath}: ${(error as Error).message}`);
91
+ }
92
+ }
package/next.config.ts ADDED
@@ -0,0 +1,26 @@
1
+ import type { NextConfig } from "next";
2
+
3
+ const nextConfig: NextConfig = {
4
+ output: "standalone",
5
+ typescript: {
6
+ // Skip type checking during build - handled by pre-commit hook
7
+ ignoreBuildErrors: true,
8
+ },
9
+ eslint: {
10
+ // Skip ESLint during build - handled by pre-commit hook with oxlint
11
+ ignoreDuringBuilds: true,
12
+ },
13
+ webpack: (config, { isServer }) => {
14
+ if (!isServer) {
15
+ config.resolve.fallback = {
16
+ ...config.resolve.fallback,
17
+ fs: false,
18
+ net: false,
19
+ tls: false,
20
+ };
21
+ }
22
+ return config;
23
+ },
24
+ };
25
+
26
+ export default nextConfig;
package/package.json CHANGED
@@ -1,135 +1,255 @@
1
1
  {
2
2
  "name": "comfy-pr",
3
- "version": "0.2.26",
4
- "description": "Make PRs that publishes ComfyUI Custom Nodes to [ComfyUI Registry]( https://www.comfyregistry.org/ ).",
3
+ "version": "1.0.1",
4
+ "description": "Make PRs that publishes ComfyUI Custom Nodes to [ComfyUI Registry]( https://registry.comfy.org/ ).",
5
5
  "keywords": [],
6
6
  "license": "ISC",
7
7
  "author": "snomiao <snomiao@gmail.com>",
8
- "type": "module",
9
- "exports": {
10
- "import": "./src/index.ts",
11
- "types": "./src/index.ts"
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/Comfy-Org/Comfy-PR"
12
11
  },
13
- "main": "index.ts",
14
- "module": "index.ts",
15
- "types": "./src/index.ts",
16
12
  "bin": {
17
- "comfy-pr": "./src/cli.ts"
13
+ "comfy-pr": "./src/cli.ts",
14
+ "pr-bot": "./bot/cli.ts",
15
+ "prbot": "./bot/cli.ts"
18
16
  },
17
+ "workspaces": [
18
+ "packages/*"
19
+ ],
19
20
  "files": [
20
21
  "*.ts"
21
22
  ],
23
+ "type": "module",
24
+ "main": "index.ts",
25
+ "module": "index.ts",
26
+ "types": "./src/index.ts",
27
+ "exports": {
28
+ "types": "./src/index.ts",
29
+ "import": "./src/index.ts"
30
+ },
22
31
  "scripts": {
23
32
  "_postinstall": "bun ./src/muteInstances.ts",
24
- "vercel:dev": "vercel dev",
25
- "vercel:build": "vercel build",
26
33
  "build": "next build",
27
34
  "build:worker": "bun build . --define 'import.meta.main=false' --define 'import.meta.env.IS_BUNDLE=true' --target=bun > dist/index.js",
28
35
  "predev": "bun i",
29
36
  "dev": "next dev",
37
+ "dev:bot": "bun --watch ./bot/index.ts",
30
38
  "dev:tsc": "tsc -w",
31
- "lint": "next lint",
39
+ "gh-service": "bun run/index.ts",
40
+ "check": "tsgo && oxlint && oxfmt",
41
+ "typecheck": "tsgo",
42
+ "lint": "oxlint --fix",
43
+ "fmt": "oxfmt",
44
+ "prepare": "husky",
45
+ "preview:pyproject": "bun scripts/preview-pyproject-minimal.ts",
46
+ "preview:pyproject-repo": "bun scripts/preview-pyproject-toml.ts",
47
+ "db:setup-indexes": "bun scripts/setup-performance-indexes.ts",
32
48
  "prerelease": "bun run build && bun run test && vercel --prod",
33
- "release": "bunx standard-version && npm publish",
49
+ "release": "npx semantic-release",
34
50
  "start": "next start",
35
- "test": "bun test"
51
+ "test": "bun test",
52
+ "test:watch": "bun test --watch",
53
+ "vercel:build": "vercel build",
54
+ "vercel:dev": "vercel dev"
36
55
  },
37
56
  "dependencies": {
57
+ "@ai-sdk/anthropic": "^3.0.23",
58
+ "@ai-sdk/openai": "^3.0.19",
38
59
  "@auth/mongodb-adapter": "^3.4.2",
39
60
  "@ctrl/mac-address": "^3.0.3",
61
+ "@google/generative-ai": "^0.24.1",
62
+ "@hookform/resolvers": "^5.1.1",
40
63
  "@kbox-labs/react-echarts": "^1.2.0",
64
+ "@keyv/mongo": "^3.0.5",
65
+ "@keyv/sqlite": "^4.0.5",
41
66
  "@monaco-editor/react": "^4.6.0",
42
- "@slack/web-api": "^7.3.1",
43
- "@snomiao/die": "^1.2.3",
44
- "@trpc/server": "^10.45.2",
45
- "@types/d3": "^7.4.3",
46
- "@types/file-saver": "^2.0.7",
47
- "@types/git-diff": "^2.0.7",
48
- "@types/jest": "^29.5.12",
49
- "@types/markdown-it": "^14.1.2",
50
- "@types/open": "^6.2.1",
67
+ "@notionhq/client": "^5.4.0",
68
+ "@octokit/plugin-retry": "^8.0.3",
69
+ "@octokit/plugin-throttling": "^11.0.3",
70
+ "@radix-ui/react-dialog": "^1.1.15",
71
+ "@radix-ui/react-slot": "^1.2.3",
72
+ "@slack/bolt": "^4.6.0",
73
+ "@slack/socket-mode": "^2.0.5",
74
+ "@slack/web-api": "^7.13.0",
75
+ "@snomiao/die": "^1.7.0",
76
+ "@snomiao/keyv-sqlite": "^5.1.2",
77
+ "@sourcegraph/amp": "^0.0.1769026071-gf9f5b8",
78
+ "@tanstack/react-query": "^5",
79
+ "@tanstack/react-query-devtools": "^5",
80
+ "@trpc/client": "^11",
81
+ "@trpc/next": "^11",
82
+ "@trpc/react-query": "^11",
83
+ "@trpc/server": "^11",
84
+ "@types/ink": "^2.0.3",
85
+ "@types/ms": "^2.1.0",
86
+ "@types/parse-github-url": "^1.0.3",
87
+ "@types/sha256": "^0.2.2",
88
+ "ai": "^6.0.49",
89
+ "async-sema": "^3.1.1",
51
90
  "bun": "^1.1.21",
91
+ "chalk": "^5.6.2",
52
92
  "class-variance-authority": "^0.7.0",
53
93
  "clsx": "^2.1.1",
94
+ "comparing": "^1.3.1",
95
+ "concurrent-lock": "^1.0.7",
54
96
  "d3": "^7.9.0",
55
97
  "daisyui": "^4.12.10",
98
+ "date-fns": "^4.1.0",
99
+ "defer-close": "^1.1.0",
56
100
  "dotenv": "^16.4.5",
57
101
  "enhanced-ms": "^3.0.0",
102
+ "execa": "^9.6.1",
103
+ "faker": "^6.6.6",
104
+ "fast-diff": "^1.3.0",
58
105
  "file-saver": "^2.0.5",
59
106
  "flat": "^6.0.1",
107
+ "from-node-stream": "^0.1.2",
60
108
  "git-diff": "^2.0.6",
61
109
  "globby": "^14.0.2",
62
110
  "google-auth-library": "^9.12.0",
63
111
  "googleapis": "^140.0.1",
64
112
  "googleapis-common": "^7.2.0",
113
+ "hot-memo": "^1.1.1",
114
+ "hot-resource": "^1.2.1",
115
+ "ink": "^6.0.1",
116
+ "is-ci": "^4.1.0",
117
+ "is-hotkey-esm": "^1.0.0",
65
118
  "js-yaml": "^4.1.0",
66
- "json-stable-stringify": "^1.1.1",
67
- "keyv": "^4.5.4",
119
+ "json-stable-stringify": "^1.3.0",
120
+ "json5": "^2.2.3",
121
+ "keyv": "^5.5.5",
122
+ "keyv-cache-proxy": "^0.2.0",
68
123
  "keyv-cached-with": "^0.0.13",
124
+ "keyv-mongodb-store": "^0.0.3",
125
+ "keyv-nedb-store": "^0.0.10",
126
+ "keyv-nest": "^0.0.7",
69
127
  "lodash-es": "^4.17.21",
70
- "lucide-react": "^0.408.0",
128
+ "lucide-react": "^0.544.0",
71
129
  "mail-mime-builder": "^0.1.0",
72
130
  "markdown-it": "^14.1.0",
73
131
  "md5": "^2.3.0",
74
132
  "minimist": "^1.2.8",
75
133
  "monaco-editor": "^0.50.0",
76
- "mongodb": "^6.8.0",
134
+ "mongodb": "^7.0.0",
135
+ "ms": "^2.1.3",
77
136
  "next-auth": "^5.0.0-beta.20",
78
137
  "nodemailer": "^6.9.14",
79
- "octokit": "^4.0.2",
138
+ "octokit": "^5.0.5",
80
139
  "open": "^10.1.0",
81
140
  "openai": "^4.53.2",
141
+ "p-limit": "^7.2.0",
82
142
  "p-map": "^7.0.2",
143
+ "p-props": "^6.0.0",
144
+ "parse-github-url": "^1.0.3",
83
145
  "peek-log": "^0.0.8",
84
146
  "polyfill-text-decoder-stream": "^0.0.9",
85
147
  "polyfill-text-encoder-stream": "^0.0.8",
148
+ "prettier": "^3.7.4",
86
149
  "pretty-ms": "^9.1.0",
87
150
  "promise-all-properties": "^4.0.4",
88
151
  "rambda": "^9.2.1",
152
+ "random-word-slugs": "^0.1.7",
89
153
  "react-api-doc": "^0.0.9",
154
+ "react-diff-view": "^3.3.1",
155
+ "react-diff-viewer": "^3.1.1",
90
156
  "react-hook-form": "^7.52.1",
91
157
  "react-hot-toast": "^2.4.1",
158
+ "react-i18next": "^15.6.0",
159
+ "react-icons": "^5.5.0",
160
+ "react-intersection-observer": "^9.16.0",
92
161
  "react-markdown": "^9.0.1",
93
- "sflow": "^1.16.17",
94
- "snoflow": "^1.9.1",
162
+ "remark-gfm": "^4.0.0",
163
+ "sflow": "^1.27.0",
164
+ "sha256": "^0.2.0",
95
165
  "sparse-bitfield": "^3.0.3",
166
+ "swr": "^2.3.4",
96
167
  "tailwind-merge": "^2.4.0",
97
168
  "tailwindcss-animate": "^1.0.7",
169
+ "terminal-link": "^5.0.0",
170
+ "terminal-render": "^1.2.2",
98
171
  "toml": "^3.0.0",
99
172
  "trpc-openapi": "^1.2.0",
173
+ "trpc-to-openapi": "^2.3.2",
100
174
  "ts-pattern": "^5.2.0",
101
175
  "unwind-array": "^1.1.4",
102
- "use-swr-component": "^0.0.5",
176
+ "url-regex-safe": "^4.0.0",
177
+ "use-async-effect": "^2.2.7",
178
+ "use-swr-component": "^0.0.7",
103
179
  "vercel": "^34.4.0",
180
+ "winston": "^3.17.0",
104
181
  "yaml": "^2.5.0",
105
- "zod": "^3.23.8",
106
- "zx": "^8.1.4"
182
+ "zod": "^4.3.2",
183
+ "zod-deep-partial": "^1.0.0",
184
+ "zx": "^8.5.3"
107
185
  },
108
186
  "devDependencies": {
187
+ "@jest/globals": "^30.1.2",
188
+ "@next/bundle-analyzer": "^15.1.5",
189
+ "@octokit/webhooks-types": "^7.6.1",
190
+ "@semantic-release/changelog": "^6.0.3",
191
+ "@semantic-release/commit-analyzer": "^13.0.1",
192
+ "@semantic-release/git": "^10.0.1",
193
+ "@semantic-release/github": "^12.0.6",
194
+ "@semantic-release/npm": "^13.1.5",
195
+ "@semantic-release/release-notes-generator": "^14.1.0",
109
196
  "@types/bun": "^1.1.6",
197
+ "@types/d3": "^7.4.3",
198
+ "@types/file-saver": "^2.0.7",
199
+ "@types/git-diff": "^2.0.7",
200
+ "@types/jest": "^29.5.12",
110
201
  "@types/js-yaml": "^4.0.9",
111
202
  "@types/json-stable-stringify": "^1.0.36",
112
203
  "@types/lodash-es": "^4.17.12",
204
+ "@types/markdown-it": "^14.1.2",
113
205
  "@types/md5": "^2.3.5",
114
206
  "@types/minimist": "^1.2.5",
115
207
  "@types/node": "^20.14.13",
116
208
  "@types/nodemailer": "^6.4.15",
117
- "@types/react": "^18.3.3",
118
- "@types/react-dom": "^18.3.0",
119
- "eslint": "^8.57.0",
120
- "eslint-config-next": "14.2.4",
121
- "next": "^14.2.5",
209
+ "@types/open": "^6.2.1",
210
+ "@types/react": "19.0.4",
211
+ "@types/react-dom": "19.0.2",
212
+ "@types/url-regex-safe": "^1.0.2",
213
+ "@typescript/native-preview": "^7.0.0-dev.20260113.1",
214
+ "and": "^0.0.3",
215
+ "husky": "^9.1.7",
216
+ "lint-staged": "^16.1.2",
217
+ "msw": "^2.11.6",
218
+ "next": "15.4.10",
219
+ "oxfmt": "^0.24.0",
220
+ "oxlint": "^1.41.0",
122
221
  "postcss": "^8.4.40",
123
222
  "prettier-plugin-organize-imports": "^3.2.4",
124
223
  "prettier-plugin-packagejson": "^2.5.1",
125
- "react": "^18.3.1",
126
- "react-dom": "^18.3.1",
224
+ "push": "^0.1.1",
225
+ "react": "19.0.0",
226
+ "react-dom": "19.0.0",
227
+ "semantic-release": "^25.0.3",
228
+ "string-replace-loader": "^3.2.0",
127
229
  "tailwindcss": "^3.4.7",
230
+ "then": "^0.0.1",
128
231
  "ts-toolbelt": "^9.6.0",
232
+ "type-fest": "^4.41.0",
129
233
  "typescript": "^5.5.4"
130
234
  },
131
235
  "peerDependencies": {
132
236
  "typescript": "^5.4.5"
133
237
  },
238
+ "overrides": {
239
+ "@types/react": "19.0.4",
240
+ "@types/react-dom": "19.0.2"
241
+ },
242
+ "lint-staged": {
243
+ "*.{js,jsx,ts,tsx}": [
244
+ "oxlint --fix",
245
+ "oxfmt --write"
246
+ ],
247
+ "*.{json,css,md,yaml,yml,html}": [
248
+ "oxfmt --write"
249
+ ]
250
+ },
251
+ "patchedDependencies": {
252
+ "trpc-to-openapi@2.3.2": "patches/trpc-to-openapi@2.3.2.patch"
253
+ },
134
254
  "title": "Comfy-PR"
135
255
  }
@@ -0,0 +1,44 @@
1
+ import { slack } from "@/lib";
2
+
3
+ async function postSummary() {
4
+ const message = `✅ *Files uploaded successfully!*
5
+
6
+ I've uploaded all 4 analysis documents for <https://github.com/Comfy-Org/ComfyUI_frontend/pull/7738|PR #7738>:
7
+
8
+ 📄 *PR_ANALYSIS.md* - Detailed breakdown of issues (command errors, Node version, doc consolidation)
9
+ 📄 *PR_7738_REVIEW_SUMMARY.md* - Complete review with exact fixes and commit message
10
+ 📄 *TROUBLESHOOTING_UPDATED.md* - Corrected version ready to use (all fixes applied)
11
+ 📄 *CHANGES_SUMMARY.md* - Quick reference for modifications
12
+
13
+ *Key Fixes Applied:*
14
+ • Fixed test command: \`pnpm test:unit --no-cache\`
15
+ • Fixed Node version format: \`v24\` (not v24.x)
16
+ • Fixed port configuration advice for Nx/Vite
17
+ • Updated timestamp to 2026-01-14
18
+ • Added cross-references to browser_tests README
19
+ • Fixed markdown linting (MD031)
20
+
21
+ *Next Steps:*
22
+ The TROUBLESHOOTING_UPDATED.md file is ready to replace the current version in the PR. I can create a new commit with these fixes using the \`prbot pr\` command if needed!
23
+
24
+ All changes address the feedback from @cbyrne and automated review tools.`;
25
+
26
+ try {
27
+ const result = await slack.chat.postMessage({
28
+ channel: "C09EM82R2HL",
29
+ thread_ts: "1768466981.470589",
30
+ text: message,
31
+ mrkdwn: true,
32
+ });
33
+
34
+ if (result.ok) {
35
+ console.log("✅ Summary message posted");
36
+ } else {
37
+ console.error("❌ Failed:", result.error);
38
+ }
39
+ } catch (error: unknown) {
40
+ console.error("❌ Error:", (error as Error).message);
41
+ }
42
+ }
43
+
44
+ postSummary();
package/src/Authors.ts CHANGED
@@ -31,11 +31,11 @@ export type Author = {
31
31
  };
32
32
 
33
33
  export const Authors = db.collection<Author>("Authors");
34
- await Authors.createIndex("githubId");
35
- await Authors.createIndex("email");
36
34
  export const GithubUsers = db.collection<{ username: string } & GHUser>("GithubUsers");
37
35
 
38
36
  if (import.meta.main) {
37
+ await Authors.createIndex("githubId");
38
+ await Authors.createIndex("email");
39
39
  // collect github id from cn repos
40
40
  await updateAuthors();
41
41
  console.log("done");
package/src/CMNodes.ts CHANGED
@@ -3,7 +3,7 @@ import md5 from "md5";
3
3
  import type { ObjectId } from "mongodb";
4
4
  import { db } from "./db";
5
5
  import { fetchCMNodes } from "./fetchCMNodes";
6
- import { type SlackMsg } from "./slack/SlackMsgs";
6
+ import { type SlackMsg } from "@/lib/slack/SlackMsgs";
7
7
  import { updateCMNodesDuplicationWarnings } from "./updateCMNodesDuplicationWarnings";
8
8
 
9
9
  // Raw version maybe duplicated with id or reference
@@ -15,7 +15,7 @@ export type CMNode = CMNodeRaw & {
15
15
  };
16
16
  };
17
17
  export const CMNodes = db.collection<CMNode>("CMNodes");
18
- await CMNodes.createIndex({ mtime: -1 });
18
+ await CMNodes.createIndex({ mtime: -1 }).catch(() => {});
19
19
  await CMNodes.createIndex({ hash: 1 }, { unique: true }).catch(() => {});
20
20
 
21
21
  if (import.meta.main) {
@@ -31,7 +31,7 @@ if (import.meta.main) {
31
31
  }
32
32
  export async function updateCMNodes() {
33
33
  const nodes = await fetchCMNodesWithHash();
34
- console.log("CMNodes updating (" + nodes.length + " nodes)");
34
+ console.log(`CMNodes updating (${nodes.length} nodes)`);
35
35
 
36
36
  // updating nodes
37
37
  const updateResult = await CMNodes.bulkWrite(