@openbuilder/cli 0.31.11

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 (78) hide show
  1. package/README.md +1053 -0
  2. package/bin/openbuilder.js +31 -0
  3. package/dist/chunks/Banner-D4tqKfzA.js +113 -0
  4. package/dist/chunks/Banner-D4tqKfzA.js.map +1 -0
  5. package/dist/chunks/auto-update-Dj3lWPWO.js +350 -0
  6. package/dist/chunks/auto-update-Dj3lWPWO.js.map +1 -0
  7. package/dist/chunks/build-D0qYqIq0.js +116 -0
  8. package/dist/chunks/build-D0qYqIq0.js.map +1 -0
  9. package/dist/chunks/cleanup-qVTsA3tk.js +141 -0
  10. package/dist/chunks/cleanup-qVTsA3tk.js.map +1 -0
  11. package/dist/chunks/cli-error-BjQwvWtK.js +140 -0
  12. package/dist/chunks/cli-error-BjQwvWtK.js.map +1 -0
  13. package/dist/chunks/config-BGP1jZJ4.js +167 -0
  14. package/dist/chunks/config-BGP1jZJ4.js.map +1 -0
  15. package/dist/chunks/config-manager-BkbjtN-H.js +133 -0
  16. package/dist/chunks/config-manager-BkbjtN-H.js.map +1 -0
  17. package/dist/chunks/database-BvAbD4sP.js +68 -0
  18. package/dist/chunks/database-BvAbD4sP.js.map +1 -0
  19. package/dist/chunks/database-setup-BYjIRAmT.js +253 -0
  20. package/dist/chunks/database-setup-BYjIRAmT.js.map +1 -0
  21. package/dist/chunks/exports-ij9sv4UM.js +7793 -0
  22. package/dist/chunks/exports-ij9sv4UM.js.map +1 -0
  23. package/dist/chunks/init-CZoN6soU.js +468 -0
  24. package/dist/chunks/init-CZoN6soU.js.map +1 -0
  25. package/dist/chunks/init-tui-BNzk_7Yx.js +1127 -0
  26. package/dist/chunks/init-tui-BNzk_7Yx.js.map +1 -0
  27. package/dist/chunks/logger-ZpJi7chw.js +38 -0
  28. package/dist/chunks/logger-ZpJi7chw.js.map +1 -0
  29. package/dist/chunks/main-tui-Cq1hLCx-.js +644 -0
  30. package/dist/chunks/main-tui-Cq1hLCx-.js.map +1 -0
  31. package/dist/chunks/manager-CvGX9qqe.js +1161 -0
  32. package/dist/chunks/manager-CvGX9qqe.js.map +1 -0
  33. package/dist/chunks/port-allocator-BRFzgH9b.js +749 -0
  34. package/dist/chunks/port-allocator-BRFzgH9b.js.map +1 -0
  35. package/dist/chunks/process-killer-CaUL7Kpl.js +87 -0
  36. package/dist/chunks/process-killer-CaUL7Kpl.js.map +1 -0
  37. package/dist/chunks/prompts-1QbE_bRr.js +128 -0
  38. package/dist/chunks/prompts-1QbE_bRr.js.map +1 -0
  39. package/dist/chunks/repo-cloner-CpOQjFSo.js +219 -0
  40. package/dist/chunks/repo-cloner-CpOQjFSo.js.map +1 -0
  41. package/dist/chunks/repo-detector-B_oj696o.js +66 -0
  42. package/dist/chunks/repo-detector-B_oj696o.js.map +1 -0
  43. package/dist/chunks/run-D23hg4xy.js +630 -0
  44. package/dist/chunks/run-D23hg4xy.js.map +1 -0
  45. package/dist/chunks/runner-logger-instance-nDWv2h2T.js +899 -0
  46. package/dist/chunks/runner-logger-instance-nDWv2h2T.js.map +1 -0
  47. package/dist/chunks/spinner-BJL9zWAJ.js +53 -0
  48. package/dist/chunks/spinner-BJL9zWAJ.js.map +1 -0
  49. package/dist/chunks/start-BygPCbvw.js +1708 -0
  50. package/dist/chunks/start-BygPCbvw.js.map +1 -0
  51. package/dist/chunks/start-traditional-uoLZXdxm.js +255 -0
  52. package/dist/chunks/start-traditional-uoLZXdxm.js.map +1 -0
  53. package/dist/chunks/status-cS8YwtUx.js +97 -0
  54. package/dist/chunks/status-cS8YwtUx.js.map +1 -0
  55. package/dist/chunks/theme-DhorI2Hb.js +44 -0
  56. package/dist/chunks/theme-DhorI2Hb.js.map +1 -0
  57. package/dist/chunks/upgrade-CT6w0lKp.js +323 -0
  58. package/dist/chunks/upgrade-CT6w0lKp.js.map +1 -0
  59. package/dist/chunks/useBuildState-CdBSu9y_.js +331 -0
  60. package/dist/chunks/useBuildState-CdBSu9y_.js.map +1 -0
  61. package/dist/cli/index.js +694 -0
  62. package/dist/cli/index.js.map +1 -0
  63. package/dist/index.js +14358 -0
  64. package/dist/index.js.map +1 -0
  65. package/dist/instrument.js +64226 -0
  66. package/dist/instrument.js.map +1 -0
  67. package/dist/templates.json +295 -0
  68. package/package.json +98 -0
  69. package/scripts/install-vendor-deps.js +34 -0
  70. package/scripts/install-vendor.js +167 -0
  71. package/scripts/prepare-release.js +71 -0
  72. package/templates/config.template.json +18 -0
  73. package/templates.json +295 -0
  74. package/vendor/ai-sdk-provider-claude-code-LOCAL.tgz +0 -0
  75. package/vendor/sentry-core-LOCAL.tgz +0 -0
  76. package/vendor/sentry-nextjs-LOCAL.tgz +0 -0
  77. package/vendor/sentry-node-LOCAL.tgz +0 -0
  78. package/vendor/sentry-node-core-LOCAL.tgz +0 -0
@@ -0,0 +1,295 @@
1
+ {
2
+ "version": "1.0.0",
3
+ "templates": [
4
+ {
5
+ "id": "react-vite",
6
+ "name": "React + Vite",
7
+ "description": "Simple, fast React app with Vite - perfect for basic projects and prototypes",
8
+ "repository": "github:codyde/template-reactvite",
9
+ "branch": "main",
10
+
11
+ "selection": {
12
+ "keywords": [
13
+ "simple",
14
+ "basic",
15
+ "quick",
16
+ "prototype",
17
+ "demo",
18
+ "app",
19
+ "website",
20
+ "page",
21
+ "ui",
22
+ "interface",
23
+ "component",
24
+ "react",
25
+ "vite",
26
+ "frontend"
27
+ ],
28
+ "useCases": [
29
+ "Simple single-page applications and UIs",
30
+ "Quick prototypes and demos",
31
+ "Basic web apps without backend complexity",
32
+ "Learning projects and tutorials",
33
+ "Component libraries and design systems",
34
+ "Client-side only applications",
35
+ "Default choice for straightforward projects"
36
+ ],
37
+ "examples": [
38
+ "Build a todo app",
39
+ "Create a calculator",
40
+ "Make a weather app",
41
+ "Build a simple dashboard",
42
+ "Create a landing page",
43
+ "Build a basic form"
44
+ ]
45
+ },
46
+
47
+ "tech": {
48
+ "framework": "vite",
49
+ "version": "5.x",
50
+ "language": "typescript",
51
+ "styling": "tailwind",
52
+ "packageManager": "pnpm",
53
+ "nodeVersion": ">=20.0.0"
54
+ },
55
+
56
+ "setup": {
57
+ "defaultPort": 5173,
58
+ "installCommand": "pnpm install",
59
+ "devCommand": "pnpm dev",
60
+ "buildCommand": "pnpm build"
61
+ },
62
+
63
+ "ai": {
64
+ "systemPromptAddition": "This is a simple React + Vite project - the default for basic applications.\n\n**Key Patterns:**\n- Pure client-side React application\n- No backend or API needed\n- Fast development with Vite HMR\n- TypeScript for type safety\n- Tailwind CSS for styling\n\n**Directory Structure:**\n- src/ - React components and logic\n- src/components/ - Reusable components\n- src/App.tsx - Main application component\n\n**When to use:**\n- Simple UIs without server-side logic\n- Prototypes and demos\n- Learning projects\n- Any basic React application\n\n**When NOT to use:**\n- Need authentication or database (use Next.js)\n- Need static site generation (use Astro)",
65
+
66
+ "includedFeatures": [
67
+ "React 18 with TypeScript",
68
+ "Vite 5 with fast HMR",
69
+ "Tailwind CSS configured",
70
+ "ESLint and TypeScript setup",
71
+ "Example components and routing",
72
+ "Clean project structure"
73
+ ]
74
+ }
75
+ },
76
+
77
+ {
78
+ "id": "nextjs-fullstack",
79
+ "name": "Next.js Full-Stack",
80
+ "description": "Modern full-stack with App Router, TypeScript, Tailwind, and shadcn/ui",
81
+ "repository": "github:codyde/template-nextjs",
82
+ "branch": "main",
83
+
84
+ "selection": {
85
+ "keywords": [
86
+ "nextjs",
87
+ "next.js",
88
+ "next",
89
+ "full-stack",
90
+ "fullstack",
91
+ "ssr",
92
+ "server-side",
93
+ "app router",
94
+ "react server components",
95
+ "tailwind",
96
+ "shadcn",
97
+ "typescript",
98
+ "authentication",
99
+ "auth",
100
+ "database",
101
+ "api",
102
+ "dashboard",
103
+ "admin",
104
+ "saas"
105
+ ],
106
+ "useCases": [
107
+ "Full-stack web applications with server and client rendering",
108
+ "SaaS products requiring authentication and APIs",
109
+ "Dynamic websites with database integration",
110
+ "Dashboard applications with real-time data",
111
+ "E-commerce platforms",
112
+ "Admin panels and management tools",
113
+ "Applications requiring SEO optimization"
114
+ ],
115
+ "examples": [
116
+ "Build a todo app with authentication",
117
+ "Create an analytics dashboard",
118
+ "Make a blog with CMS",
119
+ "Build a SaaS landing page with pricing",
120
+ "Create an e-commerce product catalog",
121
+ "Build an admin panel with user management"
122
+ ]
123
+ },
124
+
125
+ "tech": {
126
+ "framework": "next",
127
+ "version": "15.x",
128
+ "language": "typescript",
129
+ "styling": "tailwind",
130
+ "uiLibrary": "shadcn",
131
+ "packageManager": "pnpm",
132
+ "nodeVersion": ">=20.0.0"
133
+ },
134
+
135
+ "setup": {
136
+ "defaultPort": 3001,
137
+ "installCommand": "pnpm install",
138
+ "devCommand": "pnpm dev",
139
+ "buildCommand": "pnpm build"
140
+ },
141
+
142
+ "ai": {
143
+ "systemPromptAddition": "This is a Next.js 15 App Router project.\n\n**Key Patterns:**\n- Use Server Components by default (no 'use client' needed)\n- Add 'use client' ONLY when needed (useState, useEffect, event handlers)\n- API routes: app/api/[route]/route.ts with export async function GET/POST\n- Use TypeScript import type for type-only imports\n- Tailwind for styling with utility classes\n- shadcn/ui components are pre-installed in components/ui/\n\n**Directory Structure:**\n- app/ - App Router pages and layouts\n- components/ - Shared React components\n- lib/ - Utilities, types, helpers\n\n**After template is downloaded:**\n1. Install dependencies: cd {projectName} && pnpm install\n2. Components are ready to use: import { Button } from '@/components/ui/button'\n3. Create new pages in app/ directory",
144
+
145
+ "includedFeatures": [
146
+ "Pre-configured TypeScript with strict mode",
147
+ "Tailwind CSS with custom config",
148
+ "shadcn/ui components (Button, Card, Input, Select, etc.)",
149
+ "Example API route at /api/example",
150
+ "Root layout with metadata and fonts",
151
+ "Sample homepage with working components",
152
+ "ESLint and Prettier configured"
153
+ ]
154
+ }
155
+ },
156
+
157
+ {
158
+ "id": "template_tanstackstart",
159
+ "name": "TanStack Start (Blank)",
160
+ "description": "Minimal TanStack Start + React + Tailwind scaffold for full-stack applications. Provides TanStack Router/Query wiring without opinionated auth or database layers.",
161
+ "repository": "github:codyde/template-tanstackstart",
162
+ "branch": "main",
163
+
164
+ "selection": {
165
+ "keywords": [
166
+ "tanstack",
167
+ "tanstack start",
168
+ "start",
169
+ "router",
170
+ "tanstack router",
171
+ "tanstack query",
172
+ "full-stack",
173
+ "react 19",
174
+ "tailwind",
175
+ "ssr",
176
+ "server actions"
177
+ ],
178
+ "useCases": [
179
+ "Teams standardizing on TanStack Start for new full-stack builds",
180
+ "Projects that need file-based routing with TanStack Router and server-side loaders",
181
+ "React 19 applications targeting modern SSR/edge runtimes",
182
+ "Internal tools that will layer in auth, data, and APIs incrementally",
183
+ "Proof-of-concept apps exploring the TanStack Start workflow"
184
+ ],
185
+ "examples": [
186
+ "Kick off a TanStack Start full-stack project with custom backend",
187
+ "Prototype a dashboard using TanStack Router and Query",
188
+ "Create a React 19 + Tailwind admin shell with server-rendered routes",
189
+ "Start a multi-step workflow using TanStack Start loaders/actions",
190
+ "Experiment with TanStack Start SSR on a blank canvas"
191
+ ]
192
+ },
193
+
194
+ "tech": {
195
+ "framework": "tanstack",
196
+ "version": "start",
197
+ "language": "typescript",
198
+ "styling": "tailwind",
199
+ "packageManager": "pnpm",
200
+ "nodeVersion": ">=20.10.0"
201
+ },
202
+
203
+ "setup": {
204
+ "defaultPort": 3000,
205
+ "installCommand": "pnpm install",
206
+ "devCommand": "pnpm dev",
207
+ "buildCommand": "pnpm build"
208
+ },
209
+
210
+ "ai": {
211
+ "systemPromptAddition": "This is a TanStack Start project built on React 19 with TanStack Router, TanStack Query, and Tailwind CSS. It is intentionally minimal so you can layer in auth, database, and domain logic.\n\n**Key Patterns:**\n- Define routes, loaders, and actions in `app/routes/` using TanStack Start conventions\n- Use TanStack Query for client data fetching; prefer server loaders for initial data\n- Tailwind CSS is preconfigured for styling; bring your own component library if needed\n- The template ships without auth/database; you are expected to scaffold these as part of the build\n\n**Directory Structure:**\n- app/routes/ - File-based routes with loaders/actions\n- app/components/ - Shared UI components\n- app/lib/ - Utilities/helpers you create\n\n**When to use:**\n- You want a clean TanStack Start foundation without extra opinions\n- Building full-stack React apps that will add custom data/auth layers\n- Exploring TanStack Router/Query workflows end-to-end\n\n**When NOT to use:**\n- Prefer an opinionated Next.js App Router experience\n- Need a static-only marketing site (use Astro)\n- Want a minimal SPA without SSR (use React + Vite)",
212
+
213
+ "includedFeatures": [
214
+ "TanStack Router file-based routing scaffold",
215
+ "TanStack Query integration hooked into React 19 defaults",
216
+ "Tailwind CSS configured out of the box",
217
+ "pnpm workspace setup with Vite dev tooling",
218
+ "Ready-to-extend server actions and loaders"
219
+ ]
220
+ }
221
+ },
222
+
223
+ {
224
+ "id": "astro-static",
225
+ "name": "Astro Static Site",
226
+ "description": "Fast static site with optional React islands for interactivity",
227
+ "repository": "github:codyde/template-astro",
228
+ "branch": "main",
229
+
230
+ "selection": {
231
+ "keywords": [
232
+ "astro",
233
+ "static",
234
+ "ssg",
235
+ "blog",
236
+ "content",
237
+ "markdown",
238
+ "documentation",
239
+ "docs",
240
+ "landing",
241
+ "landing-page",
242
+ "portfolio",
243
+ "seo",
244
+ "performance",
245
+ "marketing"
246
+ ],
247
+ "useCases": [
248
+ "Static websites and landing pages",
249
+ "Blogs and content-heavy sites",
250
+ "Documentation sites and guides",
251
+ "Portfolio and showcase websites",
252
+ "Marketing pages requiring excellent SEO",
253
+ "Sites prioritizing performance and load times"
254
+ ],
255
+ "examples": [
256
+ "Build a personal blog with posts",
257
+ "Create a documentation site",
258
+ "Make a portfolio website",
259
+ "Build a company landing page",
260
+ "Create a marketing site with blog"
261
+ ]
262
+ },
263
+
264
+ "tech": {
265
+ "framework": "astro",
266
+ "version": "5.x",
267
+ "language": "typescript",
268
+ "styling": "tailwind",
269
+ "packageManager": "pnpm",
270
+ "nodeVersion": ">=20.0.0"
271
+ },
272
+
273
+ "setup": {
274
+ "defaultPort": 4321,
275
+ "installCommand": "pnpm install",
276
+ "devCommand": "pnpm dev",
277
+ "buildCommand": "pnpm build"
278
+ },
279
+
280
+ "ai": {
281
+ "systemPromptAddition": "This is an Astro static site generator project.\n\n**Key Patterns:**\n- Pages are .astro files with --- frontmatter at the top\n- File-based routing in src/pages/ (index.astro = homepage)\n- Use layouts in src/layouts/ for consistent page structure\n- Add React islands for interactivity: <Component client:load />\n- Content collections for blog posts/docs in src/content/\n\n**CRITICAL: Code Snippet Handling for Deployments:**\n- ALWAYS use <code set:html={'TheCode'} /> to properly fence code snippets\n- This prevents code from breaking during deployment builds\n- Never use regular <code>{code}</code> for multi-line or complex code snippets\n- Example: <code set:html={'const x = 1;\\nconst y = 2;'} />\n\n**Example .astro page:**\n```astro\n---\nimport Layout from '../layouts/Layout.astro'\nconst title = 'My Page'\n---\n<Layout title={title}>\n <h1>{title}</h1>\n <p>Static content, ultra fast!</p>\n</Layout>\n```\n\n**For interactivity, use React islands:**\n```astro\n---\nimport Counter from '../components/Counter.tsx'\n---\n<Counter client:load />\n```",
282
+
283
+ "includedFeatures": [
284
+ "Astro 5.x with TypeScript configured",
285
+ "Tailwind CSS with Astro integration",
286
+ "Example pages (index, about, blog)",
287
+ "Layout component with metadata",
288
+ "Content collections setup for blog",
289
+ "Sample blog posts in Markdown",
290
+ "React integration for islands"
291
+ ]
292
+ }
293
+ }
294
+ ]
295
+ }
package/package.json ADDED
@@ -0,0 +1,98 @@
1
+ {
2
+ "name": "@openbuilder/cli",
3
+ "version": "0.31.11",
4
+ "description": "OpenBuilder CLI - AI-powered app builder",
5
+ "private": false,
6
+ "type": "module",
7
+ "main": "dist/index.js",
8
+ "bin": {
9
+ "openbuilder-cli": "./bin/openbuilder.js",
10
+ "openbuilder": "./bin/openbuilder.js"
11
+ },
12
+ "files": [
13
+ "bin/",
14
+ "dist/",
15
+ "templates/",
16
+ "vendor/*.tgz",
17
+ "scripts/",
18
+ "templates.json",
19
+ ".npmrc"
20
+ ],
21
+ "engines": {
22
+ "node": ">=18.0.0"
23
+ },
24
+ "keywords": [
25
+ "openbuilder",
26
+ "runner",
27
+ "cli",
28
+ "ai",
29
+ "build",
30
+ "claude"
31
+ ],
32
+ "author": "Cody De Arkland",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "https://github.com/codyde/openbuilder.git",
36
+ "directory": "apps/runner"
37
+ },
38
+ "bugs": {
39
+ "url": "https://github.com/codyde/openbuilder/issues"
40
+ },
41
+ "homepage": "https://github.com/codyde/openbuilder#readme",
42
+ "preferGlobal": true,
43
+ "scripts": {
44
+ "postinstall": "node scripts/install-vendor.js",
45
+ "dev": "RUNNER_WS_URL=ws://localhost:3000/ws/runner tsx --import ./src/instrument.ts src/index.ts",
46
+ "dev:cli": "tsx --import ./src/instrument.ts src/cli/index.ts",
47
+ "build": "rollup -c && cp templates.json dist/",
48
+ "build:tsc": "tsc -p tsconfig.json",
49
+ "start": "RUNNER_WS_URL=ws://localhost:3000/ws/runner node --import ./dist/instrument.js dist/index.js",
50
+ "cli": "node --import ./dist/instrument.js dist/cli/index.js"
51
+ },
52
+ "dependencies": {
53
+ "@ai-sdk/openai": "^2.0.53",
54
+ "@anthropic-ai/claude-agent-sdk": "^0.2.12",
55
+ "@clack/prompts": "^0.11.0",
56
+ "@openai/codex-sdk": "^0.53.0",
57
+ "@sentry/core": "^10.17.0",
58
+ "@sentry/nextjs": "^10.17.0",
59
+ "@sentry/node": "^10.17.0",
60
+ "@sentry/node-core": "^10.17.0",
61
+ "ai": "^5.0.79",
62
+ "ai-sdk-provider-claude-code": "^2.1.0",
63
+ "chalk": "^5.6.2",
64
+ "commander": "^14.0.1",
65
+ "conf": "^15.0.2",
66
+ "dotenv": "^16.4.5",
67
+ "drizzle-orm": "^0.44.5",
68
+ "express": "^5.1.0",
69
+ "http-proxy": "^1.18.1",
70
+ "ink": "^6.3.1",
71
+ "ink-select-input": "^6.2.0",
72
+ "ink-spinner": "^5.0.0",
73
+ "ink-text-input": "^6.0.0",
74
+ "inquirer": "^12.9.6",
75
+ "jsonc-parser": "^3.3.1",
76
+ "ora": "^9.0.0",
77
+ "pg": "^8.13.1",
78
+ "picocolors": "^1.1.1",
79
+ "react": "19.1.0",
80
+ "simple-git": "^3.28.0",
81
+ "ws": "^8.18.0",
82
+ "zod": "^4.0.0"
83
+ },
84
+ "devDependencies": {
85
+ "@rollup/plugin-commonjs": "^28.0.0",
86
+ "@rollup/plugin-json": "^6.1.0",
87
+ "@rollup/plugin-node-resolve": "^16.0.0",
88
+ "@rollup/plugin-typescript": "^12.1.0",
89
+ "@types/express": "^4.17.21",
90
+ "@types/http-proxy": "^1.17.16",
91
+ "@types/node": "^20",
92
+ "@types/react": "^19",
93
+ "@types/ws": "^8.5.10",
94
+ "rollup": "^4.28.0",
95
+ "tsx": "^4.19.1",
96
+ "typescript": "^5.6.3"
97
+ }
98
+ }
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env node
2
+ import { execFileSync } from 'node:child_process';
3
+ import { existsSync } from 'node:fs';
4
+ import path from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = path.dirname(__filename);
9
+
10
+ const packageRoot = path.join(__dirname, '..');
11
+ const nodeModules = path.join(packageRoot, 'node_modules');
12
+
13
+ if (!existsSync(nodeModules)) {
14
+ process.exit(0);
15
+ }
16
+
17
+ try {
18
+ execFileSync(
19
+ 'node',
20
+ ['-e', "require('node:module').createRequire(require('node:url').pathToFileURL(process.cwd() + '/node_modules/@sentry/node/package.json')).resolve('@opentelemetry/sdk-trace-base')"],
21
+ { cwd: packageRoot, stdio: 'pipe' },
22
+ );
23
+ } catch (error) {
24
+ console.log('Installing @opentelemetry/sdk-trace-base via pnpm...');
25
+ try {
26
+ execFileSync('pnpm', ['install', '@opentelemetry/sdk-trace-base@^2.1.0'], {
27
+ cwd: packageRoot,
28
+ stdio: 'inherit',
29
+ });
30
+ } catch (installError) {
31
+ console.warn('Warning: Failed to install @opentelemetry/sdk-trace-base automatically. Please install it manually.');
32
+ console.warn(installError instanceof Error ? installError.message : String(installError));
33
+ }
34
+ }
@@ -0,0 +1,167 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Install vendor-patched Sentry packages that ship with the CLI bundle.
4
+ * We unpack the tarballs that live in ./vendor into node_modules/@sentry/*
5
+ * so the CLI always runs with the patched builds even when installed offline.
6
+ */
7
+ import { execFileSync } from 'node:child_process';
8
+ import { existsSync, mkdirSync, rmSync, lstatSync, readlinkSync, readdirSync } from 'node:fs';
9
+ import path from 'node:path';
10
+ import { fileURLToPath } from 'node:url';
11
+
12
+ const __filename = fileURLToPath(import.meta.url);
13
+ const __dirname = path.dirname(__filename);
14
+ const packageRoot = path.join(__dirname, '..');
15
+ const vendorDir = path.join(packageRoot, 'vendor');
16
+
17
+ // Detect the correct node_modules location for both npm and pnpm
18
+ // The vendor packages MUST be installed in the same node_modules tree as the CLI
19
+ // to ensure proper Node.js module resolution. npm may create empty placeholder directories
20
+ // in nested node_modules, so we need to install there to override them.
21
+ function findNodeModules() {
22
+ // Local node_modules inside the package (npm style for bundled deps)
23
+ const localNodeModules = path.join(packageRoot, 'node_modules');
24
+
25
+ // Parent node_modules (pnpm global style: @openbuilder/cli -> @openbuilder -> node_modules)
26
+ const parentNodeModules = path.join(packageRoot, '..', '..');
27
+
28
+ // Always prefer local node_modules if it exists - this ensures vendor packages
29
+ // are in the same resolution tree as the CLI package
30
+ if (existsSync(localNodeModules)) {
31
+ return localNodeModules;
32
+ }
33
+
34
+ // Fall back to parent for pnpm global installs where there's no local node_modules
35
+ if (existsSync(path.join(parentNodeModules, '@openbuilder')) ||
36
+ existsSync(path.join(parentNodeModules, '@sentry'))) {
37
+ return parentNodeModules;
38
+ }
39
+
40
+ // Default to local (will be created)
41
+ return localNodeModules;
42
+ }
43
+
44
+ const nodeModules = findNodeModules();
45
+
46
+ const packages = [
47
+ { name: 'core', tarball: 'sentry-core-LOCAL.tgz', scope: '@sentry' },
48
+ { name: 'node', tarball: 'sentry-node-LOCAL.tgz', scope: '@sentry' },
49
+ { name: 'node-core', tarball: 'sentry-node-core-LOCAL.tgz', scope: '@sentry' },
50
+ { name: 'nextjs', tarball: 'sentry-nextjs-LOCAL.tgz', scope: '@sentry' },
51
+ { name: 'ai-sdk-provider-claude-code', tarball: 'ai-sdk-provider-claude-code-LOCAL.tgz', scope: '' }, // No scope for this package
52
+ ];
53
+
54
+ // Silent mode by default, only show output if VERBOSE env var is set
55
+ const isVerbose = process.env.VERBOSE === '1' || process.env.VERBOSE === 'true';
56
+ const log = isVerbose ? console.log : () => {};
57
+
58
+ log('Installing vendor Sentry packages...');
59
+ log(` Vendor directory: ${vendorDir}`);
60
+ log(` Target node_modules: ${nodeModules}`);
61
+
62
+ if (!existsSync(vendorDir)) {
63
+ log('No vendor directory found, skipping...');
64
+ process.exit(0);
65
+ }
66
+
67
+ const missing = packages.filter(
68
+ ({ tarball }) => !existsSync(path.join(vendorDir, tarball)),
69
+ );
70
+
71
+ if (missing.length) {
72
+ log(
73
+ `Vendor tarballs not found for: ${missing
74
+ .map(({ tarball }) => tarball)
75
+ .join(', ')}, skipping...`,
76
+ );
77
+ process.exit(0);
78
+ }
79
+
80
+ try {
81
+ mkdirSync(nodeModules, { recursive: true });
82
+ mkdirSync(path.join(nodeModules, '@sentry'), { recursive: true });
83
+
84
+ for (const { name, tarball, scope } of packages) {
85
+ const source = path.join(vendorDir, tarball);
86
+ const destination = scope
87
+ ? path.join(nodeModules, scope, name)
88
+ : path.join(nodeModules, name);
89
+ const extractTarget = resolveExtractionTarget(destination);
90
+
91
+ execFileSync(
92
+ 'tar',
93
+ ['-xzf', source, '--strip-components', '1', '-C', extractTarget],
94
+ { stdio: 'pipe' },
95
+ );
96
+
97
+ log(` ✓ ${scope ? `${scope}/${name}` : name}`);
98
+ }
99
+
100
+ // Ensure jsonc-parser is available for ai-sdk-provider-claude-code
101
+ // This is needed because the vendored package imports it but in global installs
102
+ // with pnpm, the dependency hoisting doesn't always work correctly
103
+ const aiSdkProviderDir = path.join(nodeModules, 'ai-sdk-provider-claude-code');
104
+
105
+ if (existsSync(aiSdkProviderDir)) {
106
+ try {
107
+ // Try to find jsonc-parser in various locations
108
+ let jsoncParserSource = path.join(nodeModules, 'jsonc-parser');
109
+
110
+ // If not found directly, try to find it in the pnpm store (for global installs)
111
+ if (!existsSync(jsoncParserSource)) {
112
+ // In pnpm global installs, node_modules is at .pnpm/<package>@<version>/node_modules
113
+ // The store is at .pnpm/ level, so we need to go up: node_modules -> <package> -> .pnpm
114
+ const pnpmStoreDir = path.join(nodeModules, '..', '..');
115
+
116
+ if (existsSync(pnpmStoreDir)) {
117
+ const entries = readdirSync(pnpmStoreDir);
118
+ const jsoncParserEntry = entries.find((entry) => entry.startsWith('jsonc-parser@'));
119
+
120
+ if (jsoncParserEntry) {
121
+ jsoncParserSource = path.join(pnpmStoreDir, jsoncParserEntry, 'node_modules', 'jsonc-parser');
122
+ }
123
+ }
124
+ }
125
+
126
+ if (existsSync(jsoncParserSource)) {
127
+ const jsoncParserDest = path.join(aiSdkProviderDir, 'node_modules', 'jsonc-parser');
128
+
129
+ mkdirSync(path.join(aiSdkProviderDir, 'node_modules'), { recursive: true });
130
+
131
+ // Remove existing symlink/directory if it exists
132
+ rmSync(jsoncParserDest, { recursive: true, force: true });
133
+
134
+ // Create symlink to jsonc-parser
135
+ execFileSync('ln', ['-s', jsoncParserSource, jsoncParserDest], { stdio: 'pipe' });
136
+
137
+ log(` ✓ Linked jsonc-parser for ai-sdk-provider-claude-code`);
138
+ } else {
139
+ log(` ⚠ jsonc-parser not found, skipping symlink`);
140
+ }
141
+ } catch (error) {
142
+ // Non-fatal error, log and continue
143
+ log(` ⚠ Could not link jsonc-parser: ${error instanceof Error ? error.message : String(error)}`);
144
+ }
145
+ }
146
+
147
+ log('✓ Vendor packages installed successfully');
148
+ } catch (error) {
149
+ console.warn('Warning: Could not install vendor packages, using published versions');
150
+ console.warn(error instanceof Error ? error.message : String(error));
151
+ }
152
+
153
+ function resolveExtractionTarget(destination) {
154
+ try {
155
+ const stat = lstatSync(destination);
156
+ if (stat.isSymbolicLink()) {
157
+ const linkTarget = readlinkSync(destination);
158
+ return path.resolve(path.dirname(destination), linkTarget);
159
+ }
160
+ } catch (error) {
161
+ // Path does not exist yet.
162
+ }
163
+
164
+ rmSync(destination, { recursive: true, force: true });
165
+ mkdirSync(destination, { recursive: true });
166
+ return destination;
167
+ }
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Prepare package.json for publishing
4
+ *
5
+ * This script:
6
+ * 1. Replaces file: dependencies with npm versions (for Sentry/vendor packages)
7
+ * 2. REMOVES @openbuilder/agent-core from dependencies (it's bundled by tsup)
8
+ *
9
+ * The vendor files are still included, and postinstall will replace npm versions with vendor versions
10
+ */
11
+ import { readFileSync, writeFileSync } from 'fs';
12
+ import { join, dirname } from 'path';
13
+ import { fileURLToPath } from 'url';
14
+
15
+ const __filename = fileURLToPath(import.meta.url);
16
+ const __dirname = dirname(__filename);
17
+ const packageJsonPath = join(__dirname, '../package.json');
18
+
19
+ console.log('Preparing package.json for release...');
20
+ console.log('');
21
+
22
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
23
+
24
+ // Replace file: dependencies with npm versions
25
+ const replacements = {
26
+ '@sentry/core': '^10.17.0',
27
+ '@sentry/node': '^10.17.0',
28
+ '@sentry/node-core': '^10.17.0',
29
+ '@sentry/nextjs': '^10.17.0',
30
+ 'ai-sdk-provider-claude-code': '^2.1.0', // Use npm version, postinstall will replace with vendor
31
+ };
32
+
33
+ let modified = false;
34
+
35
+ for (const [pkg, version] of Object.entries(replacements)) {
36
+ if (packageJson.dependencies[pkg] && packageJson.dependencies[pkg].startsWith('file:')) {
37
+ console.log(` Replacing ${pkg}: ${packageJson.dependencies[pkg]} → ${version}`);
38
+ packageJson.dependencies[pkg] = version;
39
+ modified = true;
40
+ }
41
+ }
42
+
43
+ // REMOVE workspace dependencies - they're bundled into dist/ by rollup
44
+ // This eliminates npm 404 errors since these packages don't exist on npm
45
+ const workspaceDeps = ['@openbuilder/agent-core', '@openbuilder/opencode-client'];
46
+ for (const dep of workspaceDeps) {
47
+ if (packageJson.dependencies[dep]) {
48
+ console.log(` Removing ${dep} (bundled by rollup)`);
49
+ delete packageJson.dependencies[dep];
50
+ modified = true;
51
+ }
52
+ }
53
+
54
+ // Remove bundledDependencies if it exists (no longer needed)
55
+ if (packageJson.bundledDependencies) {
56
+ console.log(` Removing bundledDependencies (agent-core is inlined, not bundled)`);
57
+ delete packageJson.bundledDependencies;
58
+ modified = true;
59
+ }
60
+
61
+ if (modified) {
62
+ writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n', 'utf-8');
63
+ console.log('');
64
+ console.log('✓ package.json updated for release');
65
+ console.log('');
66
+ console.log('Note: This modifies package.json. After publishing, run:');
67
+ console.log(' git checkout apps/runner/package.json');
68
+ console.log(' to restore workspace:* dependency for local development');
69
+ } else {
70
+ console.log('✓ package.json already prepared for release');
71
+ }