create-openthrottle 1.1.0 → 1.3.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.
Files changed (2) hide show
  1. package/index.mjs +28 -73
  2. package/package.json +2 -3
package/index.mjs CHANGED
@@ -5,16 +5,15 @@
5
5
  // Usage: npx create-openthrottle
6
6
  //
7
7
  // Detects the project, prompts for config, generates .openthrottle.yml +
8
- // wake-sandbox.yml, creates a Daytona snapshot + volume, prints next steps.
8
+ // wake-sandbox.yml, creates a Daytona snapshot from GHCR, and prints next steps.
9
9
  // =============================================================================
10
10
 
11
- import { readFileSync, writeFileSync, existsSync, mkdirSync, copyFileSync, readdirSync, statSync } from 'node:fs';
11
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, copyFileSync } from 'node:fs';
12
12
  import { join, dirname } from 'node:path';
13
13
  import { execFileSync } from 'node:child_process';
14
14
  import { fileURLToPath } from 'node:url';
15
15
  import prompts from 'prompts';
16
16
  import { stringify } from 'yaml';
17
- import { Daytona } from '@daytonaio/sdk';
18
17
 
19
18
  const __dirname = dirname(fileURLToPath(import.meta.url));
20
19
  const cwd = process.cwd();
@@ -109,14 +108,6 @@ async function promptConfig(detected) {
109
108
  name: 'maxRounds', message: 'Max review rounds', initial: 3, min: 1, max: 10,
110
109
  },
111
110
  { type: 'text', name: 'snapshotName', message: 'Daytona snapshot name', initial: 'openthrottle' },
112
- {
113
- type: 'select', name: 'snapshotMode', message: 'Snapshot source',
114
- choices: [
115
- { title: 'Pre-built image (faster, recommended)', value: 'image' },
116
- { title: 'Build from Dockerfile (customizable)', value: 'dockerfile' },
117
- ],
118
- initial: 0,
119
- },
120
111
  ], { onCancel: () => { console.log('\nCancelled.'); process.exit(0); } });
121
112
 
122
113
  return { ...detected, ...response };
@@ -174,76 +165,40 @@ function copyWorkflow() {
174
165
  }
175
166
 
176
167
  // ---------------------------------------------------------------------------
177
- // 5 & 6. Create Daytona snapshot + volume
168
+ // 5. Create Daytona snapshot from pre-built GHCR image
178
169
  // ---------------------------------------------------------------------------
179
170
 
180
- async function setupDaytona(config) {
181
- const apiKey = process.env.DAYTONA_API_KEY;
182
- if (!apiKey) {
183
- console.error('\n Missing DAYTONA_API_KEY env var. Get one at https://daytona.io/dashboard\n');
184
- process.exit(1);
185
- }
186
-
187
- const daytona = new Daytona();
171
+ function setupDaytona(config) {
188
172
  const snapshotName = config.snapshotName || 'openthrottle';
189
- const volumeName = `openthrottle-${config.name}`;
190
-
191
- // Create snapshot from pre-built image or from Dockerfile
192
- if (config.snapshotMode === 'dockerfile') {
193
- // Copy Dockerfile + runtime scripts into user's project for customization
194
- const dockerDir = join(cwd, '.openthrottle', 'docker');
195
- mkdirSync(dockerDir, { recursive: true });
196
-
197
- const templateDir = join(__dirname, 'templates', 'docker');
198
- if (existsSync(templateDir)) {
199
- for (const file of readdirSync(templateDir, { recursive: true })) {
200
- const src = join(templateDir, file);
201
- const dest = join(dockerDir, file);
202
- const stat = statSync(src);
203
- if (stat.isDirectory()) {
204
- mkdirSync(dest, { recursive: true });
205
- } else {
206
- mkdirSync(dirname(dest), { recursive: true });
207
- copyFileSync(src, dest);
208
- }
209
- }
210
- }
211
- console.log(' ✓ Copied Dockerfile + runtime to .openthrottle/docker/');
212
- console.log(' Customize the Dockerfile, then create snapshot:');
213
- console.log(` daytona snapshot create ${snapshotName} --dockerfile .openthrottle/docker/Dockerfile --build-arg AGENT=${config.agent}`);
214
- } else {
215
- const image = `ghcr.io/openthrottle/doer-${config.agent}:node-1.0.0`;
216
- try {
217
- await daytona.snapshot.create({
218
- name: snapshotName,
219
- image,
220
- resources: { cpu: 2, memory: 4, disk: 10 },
221
- });
222
- console.log(` ✓ Created Daytona snapshot: ${snapshotName}`);
223
- } catch (err) {
224
- if (err.status === 409 || err.message?.includes('already exists')) {
225
- console.log(` ✓ Snapshot already exists: ${snapshotName}`);
226
- } else {
227
- console.error(` ✗ Failed to create snapshot: ${err.message}`);
228
- process.exit(1);
229
- }
230
- }
173
+ const image = 'ghcr.io/knoxgraeme/openthrottle:latest';
174
+
175
+ // Check daytona CLI is available
176
+ try {
177
+ execFileSync('daytona', ['--version'], { stdio: 'pipe' });
178
+ } catch {
179
+ console.log(`\n daytona CLI not found. Install it, then run:`);
180
+ console.log(` daytona snapshot create ${snapshotName} --image ${image} --cpu 2 --memory 4 --disk 10\n`);
181
+ return { snapshotName, skipped: true };
231
182
  }
232
183
 
233
- // Create volume (idempotent)
184
+ // Create snapshot from pre-built image
234
185
  try {
235
- await daytona.volume.create({ name: volumeName });
236
- console.log(` ✓ Created Daytona volume: ${volumeName}`);
186
+ execFileSync('daytona', [
187
+ 'snapshot', 'create', snapshotName,
188
+ '--image', image,
189
+ '--cpu', '2', '--memory', '4', '--disk', '10',
190
+ ], { stdio: 'inherit' });
191
+ console.log(` ✓ Created Daytona snapshot: ${snapshotName}`);
237
192
  } catch (err) {
238
- if (err.status === 409 || err.message?.includes('already exists')) {
239
- console.log(` ✓ Volume already exists: ${volumeName}`);
193
+ if (err.stderr?.toString().includes('already exists')) {
194
+ console.log(` ✓ Snapshot already exists: ${snapshotName}`);
240
195
  } else {
241
- console.error(` ✗ Failed to create volume: ${err.message}`);
242
- process.exit(1);
196
+ console.log(` ✗ Snapshot creation failed. You can create it manually:`);
197
+ console.log(` daytona snapshot create ${snapshotName} --image ${image} --cpu 2 --memory 4 --disk 10`);
243
198
  }
244
199
  }
245
200
 
246
- return { snapshotName, volumeName };
201
+ return { snapshotName };
247
202
  }
248
203
 
249
204
  // ---------------------------------------------------------------------------
@@ -323,10 +278,10 @@ async function main() {
323
278
  console.log(' ✓ Copied .github/workflows/wake-sandbox.yml');
324
279
  }
325
280
 
326
- // Steps 5 & 6: Daytona setup
327
- await setupDaytona(config);
281
+ // Step 5: Create Daytona snapshot
282
+ setupDaytona(config);
328
283
 
329
- // Step 7: Next steps
284
+ // Step 6: Next steps
330
285
  printNextSteps(config);
331
286
  }
332
287
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-openthrottle",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "Set up openthrottle in any Node.js project — agent-agnostic, config-driven.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -11,7 +11,6 @@
11
11
  "templates/"
12
12
  ],
13
13
  "dependencies": {
14
- "@daytonaio/sdk": "^0.153.0",
15
14
  "prompts": "^2.4.2",
16
15
  "yaml": "^2.4.0"
17
16
  },
@@ -21,7 +20,7 @@
21
20
  "license": "MIT",
22
21
  "repository": {
23
22
  "type": "git",
24
- "url": "https://github.com/knoxgraeme/sodaprompts"
23
+ "url": "https://github.com/knoxgraeme/openthrottle"
25
24
  },
26
25
  "keywords": [
27
26
  "openthrottle",