taskdex 0.1.3 → 0.1.4
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/README.md +1 -0
- package/package.json +1 -1
- package/scripts/taskdex.mjs +40 -1
package/README.md
CHANGED
|
@@ -38,6 +38,7 @@ This will clone the repo and immediately run interactive terminal setup.
|
|
|
38
38
|
Setup now defaults to `dev-client` runtime, can build the native app (`expo run:ios` / `expo run:android`), and then starts Expo in `--dev-client` mode.
|
|
39
39
|
For iOS builds, setup asks whether to run on a real iPhone or Simulator, and supports choosing a specific iPhone device name.
|
|
40
40
|
When a `pnpm-lock.yaml` is present in `mobile`, the CLI installs mobile dependencies with pnpm automatically.
|
|
41
|
+
Setup writes runtime bridge env values into `mobile/.env.local`, sets `CODEX_CWD` for bridge agent workspace, and can pass `OPENAI_API_KEY` if provided.
|
|
41
42
|
|
|
42
43
|
For an already-cloned repo:
|
|
43
44
|
|
package/package.json
CHANGED
package/scripts/taskdex.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import crypto from 'node:crypto';
|
|
4
4
|
import { spawn } from 'node:child_process';
|
|
5
|
-
import { existsSync, readdirSync } from 'node:fs';
|
|
5
|
+
import { existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
6
6
|
import os from 'node:os';
|
|
7
7
|
import path from 'node:path';
|
|
8
8
|
import process from 'node:process';
|
|
@@ -174,6 +174,26 @@ function parseInstallChoice(input) {
|
|
|
174
174
|
throw new Error('Install choice must be Y or N.');
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
+
function upsertEnvVars(envFilePath, values) {
|
|
178
|
+
const keys = Object.keys(values);
|
|
179
|
+
const original = existsSync(envFilePath) ? readFileSync(envFilePath, 'utf8') : '';
|
|
180
|
+
const lines = original ? original.split(/\r?\n/) : [];
|
|
181
|
+
const seen = new Set();
|
|
182
|
+
const updated = lines.map((line) => {
|
|
183
|
+
const match = line.match(/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=/);
|
|
184
|
+
if (!match) return line;
|
|
185
|
+
const key = match[1];
|
|
186
|
+
if (!keys.includes(key)) return line;
|
|
187
|
+
seen.add(key);
|
|
188
|
+
return `${key}=${values[key]}`;
|
|
189
|
+
});
|
|
190
|
+
for (const key of keys) {
|
|
191
|
+
if (!seen.has(key)) updated.push(`${key}=${values[key]}`);
|
|
192
|
+
}
|
|
193
|
+
const nextContent = `${updated.filter((line) => line !== '').join('\n')}\n`;
|
|
194
|
+
writeFileSync(envFilePath, nextContent, 'utf8');
|
|
195
|
+
}
|
|
196
|
+
|
|
177
197
|
function wait(ms) {
|
|
178
198
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
179
199
|
}
|
|
@@ -192,6 +212,8 @@ async function readSetupConfig() {
|
|
|
192
212
|
let buildPlatform = process.platform === 'darwin' ? 'ios' : 'android';
|
|
193
213
|
let iosTarget = 'iphone';
|
|
194
214
|
let iosDeviceName = '';
|
|
215
|
+
const openAiApiKey = (await rl.question('OPENAI_API_KEY (optional, Enter to use current shell/Codex login): ')).trim();
|
|
216
|
+
const workspaceInput = (await rl.question('Agent workspace path [repo root]: ')).trim();
|
|
195
217
|
if (runtime === 'dev-client') {
|
|
196
218
|
const buildInput = await rl.question('Build native development client now? [Y/n]: ');
|
|
197
219
|
buildDevClient = parseInstallChoice(buildInput);
|
|
@@ -217,6 +239,8 @@ async function readSetupConfig() {
|
|
|
217
239
|
buildPlatform,
|
|
218
240
|
iosTarget,
|
|
219
241
|
iosDeviceName,
|
|
242
|
+
openAiApiKey,
|
|
243
|
+
workspaceInput,
|
|
220
244
|
installDeps: parseInstallChoice(installInput),
|
|
221
245
|
};
|
|
222
246
|
} finally {
|
|
@@ -240,12 +264,25 @@ async function runInteractiveSetup(rootDir) {
|
|
|
240
264
|
buildPlatform,
|
|
241
265
|
iosTarget,
|
|
242
266
|
iosDeviceName,
|
|
267
|
+
openAiApiKey,
|
|
268
|
+
workspaceInput,
|
|
243
269
|
installDeps,
|
|
244
270
|
} = await readSetupConfig();
|
|
245
271
|
const bridgeUrl = `ws://${getLocalIPv4()}:${port}`;
|
|
272
|
+
const workspacePath = workspaceInput ? path.resolve(workspaceInput) : rootDir;
|
|
273
|
+
|
|
274
|
+
if (!existsSync(workspacePath)) {
|
|
275
|
+
throw new Error(`Workspace path does not exist: ${workspacePath}`);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
upsertEnvVars(path.join(mobileDir, '.env.local'), {
|
|
279
|
+
EXPO_PUBLIC_BRIDGE_URL: bridgeUrl,
|
|
280
|
+
EXPO_PUBLIC_BRIDGE_API_KEY: apiKey,
|
|
281
|
+
});
|
|
246
282
|
|
|
247
283
|
console.log(`\nBridge URL: ${bridgeUrl}`);
|
|
248
284
|
console.log(`Bridge API key: ${apiKey}`);
|
|
285
|
+
console.log(`Agent workspace: ${workspacePath}`);
|
|
249
286
|
console.log(`Expo mode: ${expoMode}\n`);
|
|
250
287
|
|
|
251
288
|
if (installDeps) {
|
|
@@ -265,6 +302,8 @@ async function runInteractiveSetup(rootDir) {
|
|
|
265
302
|
...process.env,
|
|
266
303
|
PORT: String(port),
|
|
267
304
|
API_KEY: apiKey,
|
|
305
|
+
CODEX_CWD: workspacePath,
|
|
306
|
+
...(openAiApiKey ? { OPENAI_API_KEY: openAiApiKey } : {}),
|
|
268
307
|
},
|
|
269
308
|
});
|
|
270
309
|
|