episoda 0.2.33 → 0.2.34
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/dist/daemon/daemon-process.js +335 -175
- package/dist/daemon/daemon-process.js.map +1 -1
- package/dist/index.js +660 -65
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1556,15 +1556,15 @@ var require_git_executor = __commonJS({
|
|
|
1556
1556
|
try {
|
|
1557
1557
|
const { stdout: gitDir } = await execAsync2("git rev-parse --git-dir", { cwd, timeout: 5e3 });
|
|
1558
1558
|
const gitDirPath = gitDir.trim();
|
|
1559
|
-
const
|
|
1559
|
+
const fs17 = await Promise.resolve().then(() => __importStar(require("fs"))).then((m) => m.promises);
|
|
1560
1560
|
const rebaseMergePath = `${gitDirPath}/rebase-merge`;
|
|
1561
1561
|
const rebaseApplyPath = `${gitDirPath}/rebase-apply`;
|
|
1562
1562
|
try {
|
|
1563
|
-
await
|
|
1563
|
+
await fs17.access(rebaseMergePath);
|
|
1564
1564
|
inRebase = true;
|
|
1565
1565
|
} catch {
|
|
1566
1566
|
try {
|
|
1567
|
-
await
|
|
1567
|
+
await fs17.access(rebaseApplyPath);
|
|
1568
1568
|
inRebase = true;
|
|
1569
1569
|
} catch {
|
|
1570
1570
|
inRebase = false;
|
|
@@ -1618,9 +1618,9 @@ var require_git_executor = __commonJS({
|
|
|
1618
1618
|
error: validation.error || "UNKNOWN_ERROR"
|
|
1619
1619
|
};
|
|
1620
1620
|
}
|
|
1621
|
-
const
|
|
1621
|
+
const fs17 = await Promise.resolve().then(() => __importStar(require("fs"))).then((m) => m.promises);
|
|
1622
1622
|
try {
|
|
1623
|
-
await
|
|
1623
|
+
await fs17.access(command.path);
|
|
1624
1624
|
return {
|
|
1625
1625
|
success: false,
|
|
1626
1626
|
error: "WORKTREE_EXISTS",
|
|
@@ -1674,9 +1674,9 @@ var require_git_executor = __commonJS({
|
|
|
1674
1674
|
*/
|
|
1675
1675
|
async executeWorktreeRemove(command, cwd, options) {
|
|
1676
1676
|
try {
|
|
1677
|
-
const
|
|
1677
|
+
const fs17 = await Promise.resolve().then(() => __importStar(require("fs"))).then((m) => m.promises);
|
|
1678
1678
|
try {
|
|
1679
|
-
await
|
|
1679
|
+
await fs17.access(command.path);
|
|
1680
1680
|
} catch {
|
|
1681
1681
|
return {
|
|
1682
1682
|
success: false,
|
|
@@ -1829,10 +1829,10 @@ var require_git_executor = __commonJS({
|
|
|
1829
1829
|
*/
|
|
1830
1830
|
async executeCloneBare(command, options) {
|
|
1831
1831
|
try {
|
|
1832
|
-
const
|
|
1833
|
-
const
|
|
1832
|
+
const fs17 = await Promise.resolve().then(() => __importStar(require("fs"))).then((m) => m.promises);
|
|
1833
|
+
const path18 = await Promise.resolve().then(() => __importStar(require("path")));
|
|
1834
1834
|
try {
|
|
1835
|
-
await
|
|
1835
|
+
await fs17.access(command.path);
|
|
1836
1836
|
return {
|
|
1837
1837
|
success: false,
|
|
1838
1838
|
error: "BRANCH_ALREADY_EXISTS",
|
|
@@ -1841,9 +1841,9 @@ var require_git_executor = __commonJS({
|
|
|
1841
1841
|
};
|
|
1842
1842
|
} catch {
|
|
1843
1843
|
}
|
|
1844
|
-
const parentDir =
|
|
1844
|
+
const parentDir = path18.dirname(command.path);
|
|
1845
1845
|
try {
|
|
1846
|
-
await
|
|
1846
|
+
await fs17.mkdir(parentDir, { recursive: true });
|
|
1847
1847
|
} catch {
|
|
1848
1848
|
}
|
|
1849
1849
|
const { stdout, stderr } = await execAsync2(
|
|
@@ -1886,22 +1886,22 @@ var require_git_executor = __commonJS({
|
|
|
1886
1886
|
*/
|
|
1887
1887
|
async executeProjectInfo(cwd, options) {
|
|
1888
1888
|
try {
|
|
1889
|
-
const
|
|
1890
|
-
const
|
|
1889
|
+
const fs17 = await Promise.resolve().then(() => __importStar(require("fs"))).then((m) => m.promises);
|
|
1890
|
+
const path18 = await Promise.resolve().then(() => __importStar(require("path")));
|
|
1891
1891
|
let currentPath = cwd;
|
|
1892
1892
|
let projectPath = cwd;
|
|
1893
1893
|
let bareRepoPath;
|
|
1894
1894
|
for (let i = 0; i < 10; i++) {
|
|
1895
|
-
const bareDir =
|
|
1896
|
-
const episodaDir =
|
|
1895
|
+
const bareDir = path18.join(currentPath, ".bare");
|
|
1896
|
+
const episodaDir = path18.join(currentPath, ".episoda");
|
|
1897
1897
|
try {
|
|
1898
|
-
await
|
|
1899
|
-
await
|
|
1898
|
+
await fs17.access(bareDir);
|
|
1899
|
+
await fs17.access(episodaDir);
|
|
1900
1900
|
projectPath = currentPath;
|
|
1901
1901
|
bareRepoPath = bareDir;
|
|
1902
1902
|
break;
|
|
1903
1903
|
} catch {
|
|
1904
|
-
const parentPath =
|
|
1904
|
+
const parentPath = path18.dirname(currentPath);
|
|
1905
1905
|
if (parentPath === currentPath) {
|
|
1906
1906
|
break;
|
|
1907
1907
|
}
|
|
@@ -2492,34 +2492,34 @@ var require_auth = __commonJS({
|
|
|
2492
2492
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
2493
2493
|
exports2.getConfigDir = getConfigDir6;
|
|
2494
2494
|
exports2.getConfigPath = getConfigPath;
|
|
2495
|
-
exports2.loadConfig =
|
|
2495
|
+
exports2.loadConfig = loadConfig6;
|
|
2496
2496
|
exports2.saveConfig = saveConfig2;
|
|
2497
2497
|
exports2.validateToken = validateToken;
|
|
2498
|
-
var
|
|
2499
|
-
var
|
|
2500
|
-
var
|
|
2498
|
+
var fs17 = __importStar(require("fs"));
|
|
2499
|
+
var path18 = __importStar(require("path"));
|
|
2500
|
+
var os7 = __importStar(require("os"));
|
|
2501
2501
|
var child_process_1 = require("child_process");
|
|
2502
2502
|
var DEFAULT_CONFIG_FILE = "config.json";
|
|
2503
2503
|
function getConfigDir6() {
|
|
2504
|
-
return process.env.EPISODA_CONFIG_DIR ||
|
|
2504
|
+
return process.env.EPISODA_CONFIG_DIR || path18.join(os7.homedir(), ".episoda");
|
|
2505
2505
|
}
|
|
2506
2506
|
function getConfigPath(configPath) {
|
|
2507
2507
|
if (configPath) {
|
|
2508
2508
|
return configPath;
|
|
2509
2509
|
}
|
|
2510
|
-
return
|
|
2510
|
+
return path18.join(getConfigDir6(), DEFAULT_CONFIG_FILE);
|
|
2511
2511
|
}
|
|
2512
2512
|
function ensureConfigDir(configPath) {
|
|
2513
|
-
const dir =
|
|
2514
|
-
const isNew = !
|
|
2513
|
+
const dir = path18.dirname(configPath);
|
|
2514
|
+
const isNew = !fs17.existsSync(dir);
|
|
2515
2515
|
if (isNew) {
|
|
2516
|
-
|
|
2516
|
+
fs17.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
2517
2517
|
}
|
|
2518
2518
|
if (process.platform === "darwin") {
|
|
2519
|
-
const nosyncPath =
|
|
2520
|
-
if (isNew || !
|
|
2519
|
+
const nosyncPath = path18.join(dir, ".nosync");
|
|
2520
|
+
if (isNew || !fs17.existsSync(nosyncPath)) {
|
|
2521
2521
|
try {
|
|
2522
|
-
|
|
2522
|
+
fs17.writeFileSync(nosyncPath, "", { mode: 384 });
|
|
2523
2523
|
(0, child_process_1.execSync)(`xattr -w com.apple.fileprovider.ignore 1 "${dir}"`, {
|
|
2524
2524
|
stdio: "ignore",
|
|
2525
2525
|
timeout: 5e3
|
|
@@ -2529,13 +2529,13 @@ var require_auth = __commonJS({
|
|
|
2529
2529
|
}
|
|
2530
2530
|
}
|
|
2531
2531
|
}
|
|
2532
|
-
async function
|
|
2532
|
+
async function loadConfig6(configPath) {
|
|
2533
2533
|
const fullPath = getConfigPath(configPath);
|
|
2534
|
-
if (!
|
|
2534
|
+
if (!fs17.existsSync(fullPath)) {
|
|
2535
2535
|
return null;
|
|
2536
2536
|
}
|
|
2537
2537
|
try {
|
|
2538
|
-
const content =
|
|
2538
|
+
const content = fs17.readFileSync(fullPath, "utf8");
|
|
2539
2539
|
const config = JSON.parse(content);
|
|
2540
2540
|
return config;
|
|
2541
2541
|
} catch (error) {
|
|
@@ -2548,7 +2548,7 @@ var require_auth = __commonJS({
|
|
|
2548
2548
|
ensureConfigDir(fullPath);
|
|
2549
2549
|
try {
|
|
2550
2550
|
const content = JSON.stringify(config, null, 2);
|
|
2551
|
-
|
|
2551
|
+
fs17.writeFileSync(fullPath, content, { mode: 384 });
|
|
2552
2552
|
} catch (error) {
|
|
2553
2553
|
throw new Error(`Failed to save config: ${error instanceof Error ? error.message : String(error)}`);
|
|
2554
2554
|
}
|
|
@@ -2699,7 +2699,7 @@ var require_package = __commonJS({
|
|
|
2699
2699
|
"package.json"(exports2, module2) {
|
|
2700
2700
|
module2.exports = {
|
|
2701
2701
|
name: "episoda",
|
|
2702
|
-
version: "0.2.
|
|
2702
|
+
version: "0.2.33",
|
|
2703
2703
|
description: "CLI tool for Episoda local development workflow orchestration",
|
|
2704
2704
|
main: "dist/index.js",
|
|
2705
2705
|
types: "dist/index.d.ts",
|
|
@@ -5032,9 +5032,162 @@ var AgentManager = class {
|
|
|
5032
5032
|
var import_child_process9 = require("child_process");
|
|
5033
5033
|
init_port_check();
|
|
5034
5034
|
var import_core7 = __toESM(require_dist());
|
|
5035
|
-
|
|
5035
|
+
|
|
5036
|
+
// src/utils/env-cache.ts
|
|
5037
|
+
var fs10 = __toESM(require("fs"));
|
|
5038
|
+
var path11 = __toESM(require("path"));
|
|
5039
|
+
var os4 = __toESM(require("os"));
|
|
5040
|
+
|
|
5041
|
+
// src/utils/env-setup.ts
|
|
5036
5042
|
var fs9 = __toESM(require("fs"));
|
|
5037
5043
|
var path10 = __toESM(require("path"));
|
|
5044
|
+
async function fetchEnvVars(apiUrl, accessToken) {
|
|
5045
|
+
try {
|
|
5046
|
+
const url = `${apiUrl}/api/cli/env-vars`;
|
|
5047
|
+
const response = await fetch(url, {
|
|
5048
|
+
method: "GET",
|
|
5049
|
+
headers: {
|
|
5050
|
+
"Authorization": `Bearer ${accessToken}`,
|
|
5051
|
+
"Content-Type": "application/json"
|
|
5052
|
+
}
|
|
5053
|
+
});
|
|
5054
|
+
if (!response.ok) {
|
|
5055
|
+
console.warn(`[env-setup] Failed to fetch env vars: ${response.status}`);
|
|
5056
|
+
return {};
|
|
5057
|
+
}
|
|
5058
|
+
const data = await response.json();
|
|
5059
|
+
const envVars = data.env_vars || {};
|
|
5060
|
+
console.log(`[env-setup] Fetched ${Object.keys(envVars).length} env vars from server`);
|
|
5061
|
+
return envVars;
|
|
5062
|
+
} catch (error) {
|
|
5063
|
+
console.warn("[env-setup] Error fetching env vars:", error instanceof Error ? error.message : error);
|
|
5064
|
+
return {};
|
|
5065
|
+
}
|
|
5066
|
+
}
|
|
5067
|
+
function writeEnvFile(targetPath, envVars) {
|
|
5068
|
+
if (Object.keys(envVars).length === 0) {
|
|
5069
|
+
return;
|
|
5070
|
+
}
|
|
5071
|
+
const envContent = Object.entries(envVars).map(([key, value]) => {
|
|
5072
|
+
if (/[\s'"#$`\\]/.test(value) || value.includes("\n")) {
|
|
5073
|
+
const escaped = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n");
|
|
5074
|
+
return `${key}="${escaped}"`;
|
|
5075
|
+
}
|
|
5076
|
+
return `${key}=${value}`;
|
|
5077
|
+
}).join("\n") + "\n";
|
|
5078
|
+
const envPath = path10.join(targetPath, ".env");
|
|
5079
|
+
fs9.writeFileSync(envPath, envContent, { mode: 384 });
|
|
5080
|
+
console.log(`[env-setup] Wrote ${Object.keys(envVars).length} env vars to ${envPath}`);
|
|
5081
|
+
}
|
|
5082
|
+
|
|
5083
|
+
// src/utils/env-cache.ts
|
|
5084
|
+
var DEFAULT_CACHE_TTL = 60;
|
|
5085
|
+
var CACHE_DIR = path11.join(os4.homedir(), ".episoda", "cache");
|
|
5086
|
+
function getCacheFilePath(projectId) {
|
|
5087
|
+
return path11.join(CACHE_DIR, `env-vars-${projectId}.json`);
|
|
5088
|
+
}
|
|
5089
|
+
function ensureCacheDir() {
|
|
5090
|
+
if (!fs10.existsSync(CACHE_DIR)) {
|
|
5091
|
+
fs10.mkdirSync(CACHE_DIR, { recursive: true, mode: 448 });
|
|
5092
|
+
}
|
|
5093
|
+
}
|
|
5094
|
+
function readCache(projectId) {
|
|
5095
|
+
try {
|
|
5096
|
+
const cacheFile = getCacheFilePath(projectId);
|
|
5097
|
+
if (!fs10.existsSync(cacheFile)) {
|
|
5098
|
+
return null;
|
|
5099
|
+
}
|
|
5100
|
+
const content = fs10.readFileSync(cacheFile, "utf-8");
|
|
5101
|
+
const data = JSON.parse(content);
|
|
5102
|
+
if (!data.vars || typeof data.vars !== "object" || !data.fetchedAt) {
|
|
5103
|
+
return null;
|
|
5104
|
+
}
|
|
5105
|
+
return data;
|
|
5106
|
+
} catch {
|
|
5107
|
+
return null;
|
|
5108
|
+
}
|
|
5109
|
+
}
|
|
5110
|
+
function writeCache(projectId, vars) {
|
|
5111
|
+
try {
|
|
5112
|
+
ensureCacheDir();
|
|
5113
|
+
const cacheFile = getCacheFilePath(projectId);
|
|
5114
|
+
const data = {
|
|
5115
|
+
vars,
|
|
5116
|
+
fetchedAt: Date.now(),
|
|
5117
|
+
projectId
|
|
5118
|
+
};
|
|
5119
|
+
fs10.writeFileSync(cacheFile, JSON.stringify(data, null, 2), { mode: 384 });
|
|
5120
|
+
} catch (error) {
|
|
5121
|
+
console.warn("[env-cache] Failed to write cache:", error instanceof Error ? error.message : error);
|
|
5122
|
+
}
|
|
5123
|
+
}
|
|
5124
|
+
function isCacheValid(cache, ttlSeconds) {
|
|
5125
|
+
const ageMs = Date.now() - cache.fetchedAt;
|
|
5126
|
+
return ageMs < ttlSeconds * 1e3;
|
|
5127
|
+
}
|
|
5128
|
+
async function fetchEnvVarsWithCache(apiUrl, accessToken, options = {}) {
|
|
5129
|
+
const {
|
|
5130
|
+
noCache = false,
|
|
5131
|
+
cacheTtl = DEFAULT_CACHE_TTL,
|
|
5132
|
+
offline = false,
|
|
5133
|
+
projectId = "default"
|
|
5134
|
+
} = options;
|
|
5135
|
+
if (offline) {
|
|
5136
|
+
const cache = readCache(projectId);
|
|
5137
|
+
if (cache && Object.keys(cache.vars).length > 0) {
|
|
5138
|
+
return {
|
|
5139
|
+
envVars: cache.vars,
|
|
5140
|
+
fromCache: true,
|
|
5141
|
+
cacheAge: Date.now() - cache.fetchedAt
|
|
5142
|
+
};
|
|
5143
|
+
}
|
|
5144
|
+
throw new Error(
|
|
5145
|
+
"Offline mode requires cached env vars, but no cache found.\nRun without --offline first to populate the cache."
|
|
5146
|
+
);
|
|
5147
|
+
}
|
|
5148
|
+
if (!noCache) {
|
|
5149
|
+
const cache = readCache(projectId);
|
|
5150
|
+
if (cache && isCacheValid(cache, cacheTtl)) {
|
|
5151
|
+
return {
|
|
5152
|
+
envVars: cache.vars,
|
|
5153
|
+
fromCache: true,
|
|
5154
|
+
cacheAge: Date.now() - cache.fetchedAt
|
|
5155
|
+
};
|
|
5156
|
+
}
|
|
5157
|
+
}
|
|
5158
|
+
try {
|
|
5159
|
+
const envVars = await fetchEnvVars(apiUrl, accessToken);
|
|
5160
|
+
if (Object.keys(envVars).length > 0) {
|
|
5161
|
+
writeCache(projectId, envVars);
|
|
5162
|
+
}
|
|
5163
|
+
return {
|
|
5164
|
+
envVars,
|
|
5165
|
+
fromCache: false
|
|
5166
|
+
};
|
|
5167
|
+
} catch (error) {
|
|
5168
|
+
const cache = readCache(projectId);
|
|
5169
|
+
if (cache && Object.keys(cache.vars).length > 0) {
|
|
5170
|
+
const cacheAge = Date.now() - cache.fetchedAt;
|
|
5171
|
+
console.warn(
|
|
5172
|
+
`[env-cache] Failed to fetch env vars, using stale cache (${Math.round(cacheAge / 1e3)}s old)`
|
|
5173
|
+
);
|
|
5174
|
+
return {
|
|
5175
|
+
envVars: cache.vars,
|
|
5176
|
+
fromCache: true,
|
|
5177
|
+
cacheAge
|
|
5178
|
+
};
|
|
5179
|
+
}
|
|
5180
|
+
throw new Error(
|
|
5181
|
+
`Failed to fetch environment variables: ${error instanceof Error ? error.message : error}
|
|
5182
|
+
No cached values available as fallback.`
|
|
5183
|
+
);
|
|
5184
|
+
}
|
|
5185
|
+
}
|
|
5186
|
+
|
|
5187
|
+
// src/utils/dev-server.ts
|
|
5188
|
+
var import_http = __toESM(require("http"));
|
|
5189
|
+
var fs11 = __toESM(require("fs"));
|
|
5190
|
+
var path12 = __toESM(require("path"));
|
|
5038
5191
|
var MAX_RESTART_ATTEMPTS = 5;
|
|
5039
5192
|
var INITIAL_RESTART_DELAY_MS = 2e3;
|
|
5040
5193
|
var MAX_RESTART_DELAY_MS = 3e4;
|
|
@@ -5042,26 +5195,26 @@ var MAX_LOG_SIZE_BYTES = 5 * 1024 * 1024;
|
|
|
5042
5195
|
var NODE_MEMORY_LIMIT_MB = 2048;
|
|
5043
5196
|
var activeServers = /* @__PURE__ */ new Map();
|
|
5044
5197
|
function getLogsDir() {
|
|
5045
|
-
const logsDir =
|
|
5046
|
-
if (!
|
|
5047
|
-
|
|
5198
|
+
const logsDir = path12.join((0, import_core7.getConfigDir)(), "logs");
|
|
5199
|
+
if (!fs11.existsSync(logsDir)) {
|
|
5200
|
+
fs11.mkdirSync(logsDir, { recursive: true });
|
|
5048
5201
|
}
|
|
5049
5202
|
return logsDir;
|
|
5050
5203
|
}
|
|
5051
5204
|
function getLogFilePath(moduleUid) {
|
|
5052
|
-
return
|
|
5205
|
+
return path12.join(getLogsDir(), `dev-${moduleUid}.log`);
|
|
5053
5206
|
}
|
|
5054
5207
|
function rotateLogIfNeeded(logPath) {
|
|
5055
5208
|
try {
|
|
5056
|
-
if (
|
|
5057
|
-
const stats =
|
|
5209
|
+
if (fs11.existsSync(logPath)) {
|
|
5210
|
+
const stats = fs11.statSync(logPath);
|
|
5058
5211
|
if (stats.size > MAX_LOG_SIZE_BYTES) {
|
|
5059
5212
|
const backupPath = `${logPath}.1`;
|
|
5060
|
-
if (
|
|
5061
|
-
|
|
5213
|
+
if (fs11.existsSync(backupPath)) {
|
|
5214
|
+
fs11.unlinkSync(backupPath);
|
|
5062
5215
|
}
|
|
5063
|
-
|
|
5064
|
-
console.log(`[DevServer] EP932: Rotated log file for ${
|
|
5216
|
+
fs11.renameSync(logPath, backupPath);
|
|
5217
|
+
console.log(`[DevServer] EP932: Rotated log file for ${path12.basename(logPath)}`);
|
|
5065
5218
|
}
|
|
5066
5219
|
}
|
|
5067
5220
|
} catch (error) {
|
|
@@ -5074,7 +5227,7 @@ function writeToLog(logPath, line, isError = false) {
|
|
|
5074
5227
|
const prefix = isError ? "ERR" : "OUT";
|
|
5075
5228
|
const logLine = `[${timestamp}] [${prefix}] ${line}
|
|
5076
5229
|
`;
|
|
5077
|
-
|
|
5230
|
+
fs11.appendFileSync(logPath, logLine);
|
|
5078
5231
|
} catch {
|
|
5079
5232
|
}
|
|
5080
5233
|
}
|
|
@@ -5155,7 +5308,7 @@ function calculateRestartDelay(restartCount) {
|
|
|
5155
5308
|
const delay = INITIAL_RESTART_DELAY_MS * Math.pow(2, restartCount);
|
|
5156
5309
|
return Math.min(delay, MAX_RESTART_DELAY_MS);
|
|
5157
5310
|
}
|
|
5158
|
-
function spawnDevServerProcess(projectPath, port, moduleUid, logPath, customCommand) {
|
|
5311
|
+
function spawnDevServerProcess(projectPath, port, moduleUid, logPath, customCommand, injectedEnvVars) {
|
|
5159
5312
|
rotateLogIfNeeded(logPath);
|
|
5160
5313
|
const nodeOptions = process.env.NODE_OPTIONS || "";
|
|
5161
5314
|
const memoryFlag = `--max-old-space-size=${NODE_MEMORY_LIMIT_MB}`;
|
|
@@ -5163,13 +5316,19 @@ function spawnDevServerProcess(projectPath, port, moduleUid, logPath, customComm
|
|
|
5163
5316
|
const command = customCommand || "npm run dev";
|
|
5164
5317
|
const [cmd, ...args] = command.split(" ");
|
|
5165
5318
|
console.log(`[DevServer] EP959: Starting with command: ${command}`);
|
|
5319
|
+
const mergedEnv = {
|
|
5320
|
+
...process.env,
|
|
5321
|
+
...injectedEnvVars,
|
|
5322
|
+
PORT: String(port),
|
|
5323
|
+
NODE_OPTIONS: enhancedNodeOptions
|
|
5324
|
+
};
|
|
5325
|
+
const injectedCount = injectedEnvVars ? Object.keys(injectedEnvVars).length : 0;
|
|
5326
|
+
if (injectedCount > 0) {
|
|
5327
|
+
console.log(`[DevServer] EP998: Injecting ${injectedCount} env vars from database`);
|
|
5328
|
+
}
|
|
5166
5329
|
const devProcess = (0, import_child_process9.spawn)(cmd, args, {
|
|
5167
5330
|
cwd: projectPath,
|
|
5168
|
-
env:
|
|
5169
|
-
...process.env,
|
|
5170
|
-
PORT: String(port),
|
|
5171
|
-
NODE_OPTIONS: enhancedNodeOptions
|
|
5172
|
-
},
|
|
5331
|
+
env: mergedEnv,
|
|
5173
5332
|
stdio: ["ignore", "pipe", "pipe"],
|
|
5174
5333
|
detached: false,
|
|
5175
5334
|
shell: true
|
|
@@ -5219,7 +5378,7 @@ async function handleProcessExit(moduleUid, code, signal) {
|
|
|
5219
5378
|
return;
|
|
5220
5379
|
}
|
|
5221
5380
|
const logPath = serverInfo.logFile || getLogFilePath(moduleUid);
|
|
5222
|
-
const newProcess = spawnDevServerProcess(serverInfo.projectPath, serverInfo.port, moduleUid, logPath, serverInfo.customCommand);
|
|
5381
|
+
const newProcess = spawnDevServerProcess(serverInfo.projectPath, serverInfo.port, moduleUid, logPath, serverInfo.customCommand, serverInfo.injectedEnvVars);
|
|
5223
5382
|
const updatedInfo = {
|
|
5224
5383
|
...serverInfo,
|
|
5225
5384
|
process: newProcess,
|
|
@@ -5259,9 +5418,27 @@ async function startDevServer(projectPath, port = 3e3, moduleUid = "default", op
|
|
|
5259
5418
|
}
|
|
5260
5419
|
}
|
|
5261
5420
|
console.log(`[DevServer] EP932: Starting dev server for ${moduleUid} on port ${port} (auto-restart: ${autoRestart})...`);
|
|
5421
|
+
let injectedEnvVars = {};
|
|
5422
|
+
try {
|
|
5423
|
+
const config = await (0, import_core7.loadConfig)();
|
|
5424
|
+
if (config?.access_token && config?.project_id) {
|
|
5425
|
+
const apiUrl = config.api_url || "https://episoda.dev";
|
|
5426
|
+
const result = await fetchEnvVarsWithCache(apiUrl, config.access_token, {
|
|
5427
|
+
projectId: config.project_id,
|
|
5428
|
+
cacheTtl: 300
|
|
5429
|
+
// 5 minute cache for daemon
|
|
5430
|
+
});
|
|
5431
|
+
injectedEnvVars = result.envVars;
|
|
5432
|
+
console.log(`[DevServer] EP998: Loaded ${Object.keys(injectedEnvVars).length} env vars (from ${result.fromCache ? "cache" : "server"})`);
|
|
5433
|
+
} else {
|
|
5434
|
+
console.log(`[DevServer] EP998: No auth config, skipping env var injection`);
|
|
5435
|
+
}
|
|
5436
|
+
} catch (error) {
|
|
5437
|
+
console.warn(`[DevServer] EP998: Failed to fetch env vars:`, error instanceof Error ? error.message : error);
|
|
5438
|
+
}
|
|
5262
5439
|
try {
|
|
5263
5440
|
const logPath = getLogFilePath(moduleUid);
|
|
5264
|
-
const devProcess = spawnDevServerProcess(projectPath, port, moduleUid, logPath, customCommand);
|
|
5441
|
+
const devProcess = spawnDevServerProcess(projectPath, port, moduleUid, logPath, customCommand, injectedEnvVars);
|
|
5265
5442
|
const serverInfo = {
|
|
5266
5443
|
process: devProcess,
|
|
5267
5444
|
moduleUid,
|
|
@@ -5272,8 +5449,10 @@ async function startDevServer(projectPath, port = 3e3, moduleUid = "default", op
|
|
|
5272
5449
|
lastRestartAt: null,
|
|
5273
5450
|
autoRestartEnabled: autoRestart,
|
|
5274
5451
|
logFile: logPath,
|
|
5275
|
-
customCommand
|
|
5452
|
+
customCommand,
|
|
5276
5453
|
// EP959-m2: Store for restarts
|
|
5454
|
+
injectedEnvVars
|
|
5455
|
+
// EP998: Store for restarts
|
|
5277
5456
|
};
|
|
5278
5457
|
activeServers.set(moduleUid, serverInfo);
|
|
5279
5458
|
writeToLog(logPath, `Starting dev server on port ${port}`, false);
|
|
@@ -5359,8 +5538,8 @@ async function ensureDevServer(projectPath, port = 3e3, moduleUid = "default", c
|
|
|
5359
5538
|
}
|
|
5360
5539
|
|
|
5361
5540
|
// src/utils/port-detect.ts
|
|
5362
|
-
var
|
|
5363
|
-
var
|
|
5541
|
+
var fs12 = __toESM(require("fs"));
|
|
5542
|
+
var path13 = __toESM(require("path"));
|
|
5364
5543
|
var DEFAULT_PORT = 3e3;
|
|
5365
5544
|
function detectDevPort(projectPath) {
|
|
5366
5545
|
const envPort = getPortFromEnv(projectPath);
|
|
@@ -5378,15 +5557,15 @@ function detectDevPort(projectPath) {
|
|
|
5378
5557
|
}
|
|
5379
5558
|
function getPortFromEnv(projectPath) {
|
|
5380
5559
|
const envPaths = [
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5560
|
+
path13.join(projectPath, ".env"),
|
|
5561
|
+
path13.join(projectPath, ".env.local"),
|
|
5562
|
+
path13.join(projectPath, ".env.development"),
|
|
5563
|
+
path13.join(projectPath, ".env.development.local")
|
|
5385
5564
|
];
|
|
5386
5565
|
for (const envPath of envPaths) {
|
|
5387
5566
|
try {
|
|
5388
|
-
if (!
|
|
5389
|
-
const content =
|
|
5567
|
+
if (!fs12.existsSync(envPath)) continue;
|
|
5568
|
+
const content = fs12.readFileSync(envPath, "utf-8");
|
|
5390
5569
|
const lines = content.split("\n");
|
|
5391
5570
|
for (const line of lines) {
|
|
5392
5571
|
const match = line.match(/^\s*PORT\s*=\s*["']?(\d+)["']?\s*(?:#.*)?$/);
|
|
@@ -5403,10 +5582,10 @@ function getPortFromEnv(projectPath) {
|
|
|
5403
5582
|
return null;
|
|
5404
5583
|
}
|
|
5405
5584
|
function getPortFromPackageJson(projectPath) {
|
|
5406
|
-
const packageJsonPath =
|
|
5585
|
+
const packageJsonPath = path13.join(projectPath, "package.json");
|
|
5407
5586
|
try {
|
|
5408
|
-
if (!
|
|
5409
|
-
const content =
|
|
5587
|
+
if (!fs12.existsSync(packageJsonPath)) return null;
|
|
5588
|
+
const content = fs12.readFileSync(packageJsonPath, "utf-8");
|
|
5410
5589
|
const pkg = JSON.parse(content);
|
|
5411
5590
|
const devScript = pkg.scripts?.dev;
|
|
5412
5591
|
if (!devScript) return null;
|
|
@@ -5430,8 +5609,8 @@ function getPortFromPackageJson(projectPath) {
|
|
|
5430
5609
|
}
|
|
5431
5610
|
|
|
5432
5611
|
// src/daemon/worktree-manager.ts
|
|
5433
|
-
var
|
|
5434
|
-
var
|
|
5612
|
+
var fs13 = __toESM(require("fs"));
|
|
5613
|
+
var path14 = __toESM(require("path"));
|
|
5435
5614
|
var import_core8 = __toESM(require_dist());
|
|
5436
5615
|
function validateModuleUid(moduleUid) {
|
|
5437
5616
|
if (!moduleUid || typeof moduleUid !== "string" || !moduleUid.trim()) {
|
|
@@ -5455,8 +5634,8 @@ var WorktreeManager = class _WorktreeManager {
|
|
|
5455
5634
|
// ============================================================
|
|
5456
5635
|
this.lockPath = "";
|
|
5457
5636
|
this.projectRoot = projectRoot;
|
|
5458
|
-
this.bareRepoPath =
|
|
5459
|
-
this.configPath =
|
|
5637
|
+
this.bareRepoPath = path14.join(projectRoot, ".bare");
|
|
5638
|
+
this.configPath = path14.join(projectRoot, ".episoda", "config.json");
|
|
5460
5639
|
this.gitExecutor = new import_core8.GitExecutor();
|
|
5461
5640
|
}
|
|
5462
5641
|
/**
|
|
@@ -5465,10 +5644,10 @@ var WorktreeManager = class _WorktreeManager {
|
|
|
5465
5644
|
* @returns true if valid project, false otherwise
|
|
5466
5645
|
*/
|
|
5467
5646
|
async initialize() {
|
|
5468
|
-
if (!
|
|
5647
|
+
if (!fs13.existsSync(this.bareRepoPath)) {
|
|
5469
5648
|
return false;
|
|
5470
5649
|
}
|
|
5471
|
-
if (!
|
|
5650
|
+
if (!fs13.existsSync(this.configPath)) {
|
|
5472
5651
|
return false;
|
|
5473
5652
|
}
|
|
5474
5653
|
try {
|
|
@@ -5483,8 +5662,8 @@ var WorktreeManager = class _WorktreeManager {
|
|
|
5483
5662
|
*/
|
|
5484
5663
|
static async createProject(projectRoot, repoUrl, projectId, workspaceSlug, projectSlug) {
|
|
5485
5664
|
const manager = new _WorktreeManager(projectRoot);
|
|
5486
|
-
const episodaDir =
|
|
5487
|
-
|
|
5665
|
+
const episodaDir = path14.join(projectRoot, ".episoda");
|
|
5666
|
+
fs13.mkdirSync(episodaDir, { recursive: true });
|
|
5488
5667
|
const cloneResult = await manager.gitExecutor.execute({
|
|
5489
5668
|
action: "clone_bare",
|
|
5490
5669
|
url: repoUrl,
|
|
@@ -5515,7 +5694,7 @@ var WorktreeManager = class _WorktreeManager {
|
|
|
5515
5694
|
error: `Invalid module UID: "${moduleUid}" - contains disallowed characters`
|
|
5516
5695
|
};
|
|
5517
5696
|
}
|
|
5518
|
-
const worktreePath =
|
|
5697
|
+
const worktreePath = path14.join(this.projectRoot, moduleUid);
|
|
5519
5698
|
const lockAcquired = await this.acquireLock();
|
|
5520
5699
|
if (!lockAcquired) {
|
|
5521
5700
|
return {
|
|
@@ -5696,7 +5875,7 @@ var WorktreeManager = class _WorktreeManager {
|
|
|
5696
5875
|
let prunedCount = 0;
|
|
5697
5876
|
await this.updateConfigSafe((config) => {
|
|
5698
5877
|
const initialCount = config.worktrees.length;
|
|
5699
|
-
config.worktrees = config.worktrees.filter((w) =>
|
|
5878
|
+
config.worktrees = config.worktrees.filter((w) => fs13.existsSync(w.worktreePath));
|
|
5700
5879
|
prunedCount = initialCount - config.worktrees.length;
|
|
5701
5880
|
return config;
|
|
5702
5881
|
});
|
|
@@ -5777,16 +5956,16 @@ var WorktreeManager = class _WorktreeManager {
|
|
|
5777
5956
|
const retryInterval = 50;
|
|
5778
5957
|
while (Date.now() - startTime < timeoutMs) {
|
|
5779
5958
|
try {
|
|
5780
|
-
|
|
5959
|
+
fs13.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
|
|
5781
5960
|
return true;
|
|
5782
5961
|
} catch (err) {
|
|
5783
5962
|
if (err.code === "EEXIST") {
|
|
5784
5963
|
try {
|
|
5785
|
-
const stats =
|
|
5964
|
+
const stats = fs13.statSync(lockPath);
|
|
5786
5965
|
const lockAge = Date.now() - stats.mtimeMs;
|
|
5787
5966
|
if (lockAge > 3e4) {
|
|
5788
5967
|
try {
|
|
5789
|
-
const lockContent =
|
|
5968
|
+
const lockContent = fs13.readFileSync(lockPath, "utf-8").trim();
|
|
5790
5969
|
const lockPid = parseInt(lockContent, 10);
|
|
5791
5970
|
if (!isNaN(lockPid) && this.isProcessRunning(lockPid)) {
|
|
5792
5971
|
await new Promise((resolve3) => setTimeout(resolve3, retryInterval));
|
|
@@ -5795,7 +5974,7 @@ var WorktreeManager = class _WorktreeManager {
|
|
|
5795
5974
|
} catch {
|
|
5796
5975
|
}
|
|
5797
5976
|
try {
|
|
5798
|
-
|
|
5977
|
+
fs13.unlinkSync(lockPath);
|
|
5799
5978
|
} catch {
|
|
5800
5979
|
}
|
|
5801
5980
|
continue;
|
|
@@ -5816,16 +5995,16 @@ var WorktreeManager = class _WorktreeManager {
|
|
|
5816
5995
|
*/
|
|
5817
5996
|
releaseLock() {
|
|
5818
5997
|
try {
|
|
5819
|
-
|
|
5998
|
+
fs13.unlinkSync(this.getLockPath());
|
|
5820
5999
|
} catch {
|
|
5821
6000
|
}
|
|
5822
6001
|
}
|
|
5823
6002
|
readConfig() {
|
|
5824
6003
|
try {
|
|
5825
|
-
if (!
|
|
6004
|
+
if (!fs13.existsSync(this.configPath)) {
|
|
5826
6005
|
return null;
|
|
5827
6006
|
}
|
|
5828
|
-
const content =
|
|
6007
|
+
const content = fs13.readFileSync(this.configPath, "utf-8");
|
|
5829
6008
|
return JSON.parse(content);
|
|
5830
6009
|
} catch (error) {
|
|
5831
6010
|
console.error("[WorktreeManager] Failed to read config:", error);
|
|
@@ -5834,11 +6013,11 @@ var WorktreeManager = class _WorktreeManager {
|
|
|
5834
6013
|
}
|
|
5835
6014
|
writeConfig(config) {
|
|
5836
6015
|
try {
|
|
5837
|
-
const dir =
|
|
5838
|
-
if (!
|
|
5839
|
-
|
|
6016
|
+
const dir = path14.dirname(this.configPath);
|
|
6017
|
+
if (!fs13.existsSync(dir)) {
|
|
6018
|
+
fs13.mkdirSync(dir, { recursive: true });
|
|
5840
6019
|
}
|
|
5841
|
-
|
|
6020
|
+
fs13.writeFileSync(this.configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
5842
6021
|
} catch (error) {
|
|
5843
6022
|
console.error("[WorktreeManager] Failed to write config:", error);
|
|
5844
6023
|
throw error;
|
|
@@ -5919,14 +6098,14 @@ var WorktreeManager = class _WorktreeManager {
|
|
|
5919
6098
|
}
|
|
5920
6099
|
try {
|
|
5921
6100
|
for (const file of files) {
|
|
5922
|
-
const srcPath =
|
|
5923
|
-
const destPath =
|
|
5924
|
-
if (
|
|
5925
|
-
const destDir =
|
|
5926
|
-
if (!
|
|
5927
|
-
|
|
5928
|
-
}
|
|
5929
|
-
|
|
6101
|
+
const srcPath = path14.join(mainWorktree.worktreePath, file);
|
|
6102
|
+
const destPath = path14.join(worktree.worktreePath, file);
|
|
6103
|
+
if (fs13.existsSync(srcPath)) {
|
|
6104
|
+
const destDir = path14.dirname(destPath);
|
|
6105
|
+
if (!fs13.existsSync(destDir)) {
|
|
6106
|
+
fs13.mkdirSync(destDir, { recursive: true });
|
|
6107
|
+
}
|
|
6108
|
+
fs13.copyFileSync(srcPath, destPath);
|
|
5930
6109
|
console.log(`[WorktreeManager] EP964: Copied ${file} to ${moduleUid} (deprecated)`);
|
|
5931
6110
|
} else {
|
|
5932
6111
|
console.log(`[WorktreeManager] EP964: Skipped ${file} (not found in main)`);
|
|
@@ -6009,27 +6188,27 @@ var WorktreeManager = class _WorktreeManager {
|
|
|
6009
6188
|
}
|
|
6010
6189
|
};
|
|
6011
6190
|
function getEpisodaRoot() {
|
|
6012
|
-
return process.env.EPISODA_ROOT ||
|
|
6191
|
+
return process.env.EPISODA_ROOT || path14.join(require("os").homedir(), "episoda");
|
|
6013
6192
|
}
|
|
6014
6193
|
async function isWorktreeProject(projectRoot) {
|
|
6015
6194
|
const manager = new WorktreeManager(projectRoot);
|
|
6016
6195
|
return manager.initialize();
|
|
6017
6196
|
}
|
|
6018
6197
|
async function findProjectRoot(startPath) {
|
|
6019
|
-
let current =
|
|
6198
|
+
let current = path14.resolve(startPath);
|
|
6020
6199
|
const episodaRoot = getEpisodaRoot();
|
|
6021
6200
|
if (!current.startsWith(episodaRoot)) {
|
|
6022
6201
|
return null;
|
|
6023
6202
|
}
|
|
6024
6203
|
for (let i = 0; i < 10; i++) {
|
|
6025
|
-
const bareDir =
|
|
6026
|
-
const episodaDir =
|
|
6027
|
-
if (
|
|
6204
|
+
const bareDir = path14.join(current, ".bare");
|
|
6205
|
+
const episodaDir = path14.join(current, ".episoda");
|
|
6206
|
+
if (fs13.existsSync(bareDir) && fs13.existsSync(episodaDir)) {
|
|
6028
6207
|
if (await isWorktreeProject(current)) {
|
|
6029
6208
|
return current;
|
|
6030
6209
|
}
|
|
6031
6210
|
}
|
|
6032
|
-
const parent =
|
|
6211
|
+
const parent = path14.dirname(current);
|
|
6033
6212
|
if (parent === current) {
|
|
6034
6213
|
break;
|
|
6035
6214
|
}
|
|
@@ -6038,39 +6217,20 @@ async function findProjectRoot(startPath) {
|
|
|
6038
6217
|
return null;
|
|
6039
6218
|
}
|
|
6040
6219
|
|
|
6041
|
-
// src/utils/env-setup.ts
|
|
6042
|
-
var fs12 = __toESM(require("fs"));
|
|
6043
|
-
var path13 = __toESM(require("path"));
|
|
6044
|
-
function writeEnvFile(targetPath, envVars) {
|
|
6045
|
-
if (Object.keys(envVars).length === 0) {
|
|
6046
|
-
return;
|
|
6047
|
-
}
|
|
6048
|
-
const envContent = Object.entries(envVars).map(([key, value]) => {
|
|
6049
|
-
if (/[\s'"#$`\\]/.test(value) || value.includes("\n")) {
|
|
6050
|
-
const escaped = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n");
|
|
6051
|
-
return `${key}="${escaped}"`;
|
|
6052
|
-
}
|
|
6053
|
-
return `${key}=${value}`;
|
|
6054
|
-
}).join("\n") + "\n";
|
|
6055
|
-
const envPath = path13.join(targetPath, ".env");
|
|
6056
|
-
fs12.writeFileSync(envPath, envContent, { mode: 384 });
|
|
6057
|
-
console.log(`[env-setup] Wrote ${Object.keys(envVars).length} env vars to ${envPath}`);
|
|
6058
|
-
}
|
|
6059
|
-
|
|
6060
6220
|
// src/utils/worktree.ts
|
|
6061
|
-
var
|
|
6062
|
-
var
|
|
6063
|
-
var
|
|
6221
|
+
var path15 = __toESM(require("path"));
|
|
6222
|
+
var fs14 = __toESM(require("fs"));
|
|
6223
|
+
var os5 = __toESM(require("os"));
|
|
6064
6224
|
var import_core9 = __toESM(require_dist());
|
|
6065
6225
|
function getEpisodaRoot2() {
|
|
6066
|
-
return process.env.EPISODA_ROOT ||
|
|
6226
|
+
return process.env.EPISODA_ROOT || path15.join(os5.homedir(), "episoda");
|
|
6067
6227
|
}
|
|
6068
6228
|
function getWorktreeInfo(moduleUid, workspaceSlug, projectSlug) {
|
|
6069
6229
|
const root = getEpisodaRoot2();
|
|
6070
|
-
const worktreePath =
|
|
6230
|
+
const worktreePath = path15.join(root, workspaceSlug, projectSlug, moduleUid);
|
|
6071
6231
|
return {
|
|
6072
6232
|
path: worktreePath,
|
|
6073
|
-
exists:
|
|
6233
|
+
exists: fs14.existsSync(worktreePath),
|
|
6074
6234
|
moduleUid
|
|
6075
6235
|
};
|
|
6076
6236
|
}
|
|
@@ -6087,7 +6247,7 @@ async function getProjectRootPath() {
|
|
|
6087
6247
|
if (!config?.workspace_slug || !config?.project_slug) {
|
|
6088
6248
|
return null;
|
|
6089
6249
|
}
|
|
6090
|
-
return
|
|
6250
|
+
return path15.join(
|
|
6091
6251
|
getEpisodaRoot2(),
|
|
6092
6252
|
config.workspace_slug,
|
|
6093
6253
|
config.project_slug
|
|
@@ -6137,61 +6297,61 @@ function clearAllPorts() {
|
|
|
6137
6297
|
}
|
|
6138
6298
|
|
|
6139
6299
|
// src/framework-detector.ts
|
|
6140
|
-
var
|
|
6141
|
-
var
|
|
6300
|
+
var fs15 = __toESM(require("fs"));
|
|
6301
|
+
var path16 = __toESM(require("path"));
|
|
6142
6302
|
function getInstallCommand(cwd) {
|
|
6143
|
-
if (
|
|
6303
|
+
if (fs15.existsSync(path16.join(cwd, "bun.lockb"))) {
|
|
6144
6304
|
return {
|
|
6145
6305
|
command: ["bun", "install"],
|
|
6146
6306
|
description: "Installing dependencies with bun",
|
|
6147
6307
|
detectedFrom: "bun.lockb"
|
|
6148
6308
|
};
|
|
6149
6309
|
}
|
|
6150
|
-
if (
|
|
6310
|
+
if (fs15.existsSync(path16.join(cwd, "pnpm-lock.yaml"))) {
|
|
6151
6311
|
return {
|
|
6152
6312
|
command: ["pnpm", "install"],
|
|
6153
6313
|
description: "Installing dependencies with pnpm",
|
|
6154
6314
|
detectedFrom: "pnpm-lock.yaml"
|
|
6155
6315
|
};
|
|
6156
6316
|
}
|
|
6157
|
-
if (
|
|
6317
|
+
if (fs15.existsSync(path16.join(cwd, "yarn.lock"))) {
|
|
6158
6318
|
return {
|
|
6159
6319
|
command: ["yarn", "install"],
|
|
6160
6320
|
description: "Installing dependencies with yarn",
|
|
6161
6321
|
detectedFrom: "yarn.lock"
|
|
6162
6322
|
};
|
|
6163
6323
|
}
|
|
6164
|
-
if (
|
|
6324
|
+
if (fs15.existsSync(path16.join(cwd, "package-lock.json"))) {
|
|
6165
6325
|
return {
|
|
6166
6326
|
command: ["npm", "ci"],
|
|
6167
6327
|
description: "Installing dependencies with npm ci",
|
|
6168
6328
|
detectedFrom: "package-lock.json"
|
|
6169
6329
|
};
|
|
6170
6330
|
}
|
|
6171
|
-
if (
|
|
6331
|
+
if (fs15.existsSync(path16.join(cwd, "package.json"))) {
|
|
6172
6332
|
return {
|
|
6173
6333
|
command: ["npm", "install"],
|
|
6174
6334
|
description: "Installing dependencies with npm",
|
|
6175
6335
|
detectedFrom: "package.json"
|
|
6176
6336
|
};
|
|
6177
6337
|
}
|
|
6178
|
-
if (
|
|
6338
|
+
if (fs15.existsSync(path16.join(cwd, "Pipfile.lock")) || fs15.existsSync(path16.join(cwd, "Pipfile"))) {
|
|
6179
6339
|
return {
|
|
6180
6340
|
command: ["pipenv", "install"],
|
|
6181
6341
|
description: "Installing dependencies with pipenv",
|
|
6182
|
-
detectedFrom:
|
|
6342
|
+
detectedFrom: fs15.existsSync(path16.join(cwd, "Pipfile.lock")) ? "Pipfile.lock" : "Pipfile"
|
|
6183
6343
|
};
|
|
6184
6344
|
}
|
|
6185
|
-
if (
|
|
6345
|
+
if (fs15.existsSync(path16.join(cwd, "poetry.lock"))) {
|
|
6186
6346
|
return {
|
|
6187
6347
|
command: ["poetry", "install"],
|
|
6188
6348
|
description: "Installing dependencies with poetry",
|
|
6189
6349
|
detectedFrom: "poetry.lock"
|
|
6190
6350
|
};
|
|
6191
6351
|
}
|
|
6192
|
-
if (
|
|
6193
|
-
const pyprojectPath =
|
|
6194
|
-
const content =
|
|
6352
|
+
if (fs15.existsSync(path16.join(cwd, "pyproject.toml"))) {
|
|
6353
|
+
const pyprojectPath = path16.join(cwd, "pyproject.toml");
|
|
6354
|
+
const content = fs15.readFileSync(pyprojectPath, "utf-8");
|
|
6195
6355
|
if (content.includes("[tool.poetry]")) {
|
|
6196
6356
|
return {
|
|
6197
6357
|
command: ["poetry", "install"],
|
|
@@ -6200,41 +6360,41 @@ function getInstallCommand(cwd) {
|
|
|
6200
6360
|
};
|
|
6201
6361
|
}
|
|
6202
6362
|
}
|
|
6203
|
-
if (
|
|
6363
|
+
if (fs15.existsSync(path16.join(cwd, "requirements.txt"))) {
|
|
6204
6364
|
return {
|
|
6205
6365
|
command: ["pip", "install", "-r", "requirements.txt"],
|
|
6206
6366
|
description: "Installing dependencies with pip",
|
|
6207
6367
|
detectedFrom: "requirements.txt"
|
|
6208
6368
|
};
|
|
6209
6369
|
}
|
|
6210
|
-
if (
|
|
6370
|
+
if (fs15.existsSync(path16.join(cwd, "Gemfile.lock")) || fs15.existsSync(path16.join(cwd, "Gemfile"))) {
|
|
6211
6371
|
return {
|
|
6212
6372
|
command: ["bundle", "install"],
|
|
6213
6373
|
description: "Installing dependencies with bundler",
|
|
6214
|
-
detectedFrom:
|
|
6374
|
+
detectedFrom: fs15.existsSync(path16.join(cwd, "Gemfile.lock")) ? "Gemfile.lock" : "Gemfile"
|
|
6215
6375
|
};
|
|
6216
6376
|
}
|
|
6217
|
-
if (
|
|
6377
|
+
if (fs15.existsSync(path16.join(cwd, "go.sum")) || fs15.existsSync(path16.join(cwd, "go.mod"))) {
|
|
6218
6378
|
return {
|
|
6219
6379
|
command: ["go", "mod", "download"],
|
|
6220
6380
|
description: "Downloading Go modules",
|
|
6221
|
-
detectedFrom:
|
|
6381
|
+
detectedFrom: fs15.existsSync(path16.join(cwd, "go.sum")) ? "go.sum" : "go.mod"
|
|
6222
6382
|
};
|
|
6223
6383
|
}
|
|
6224
|
-
if (
|
|
6384
|
+
if (fs15.existsSync(path16.join(cwd, "Cargo.lock")) || fs15.existsSync(path16.join(cwd, "Cargo.toml"))) {
|
|
6225
6385
|
return {
|
|
6226
6386
|
command: ["cargo", "build"],
|
|
6227
6387
|
description: "Building Rust project (downloads dependencies)",
|
|
6228
|
-
detectedFrom:
|
|
6388
|
+
detectedFrom: fs15.existsSync(path16.join(cwd, "Cargo.lock")) ? "Cargo.lock" : "Cargo.toml"
|
|
6229
6389
|
};
|
|
6230
6390
|
}
|
|
6231
6391
|
return null;
|
|
6232
6392
|
}
|
|
6233
6393
|
|
|
6234
6394
|
// src/daemon/daemon-process.ts
|
|
6235
|
-
var
|
|
6236
|
-
var
|
|
6237
|
-
var
|
|
6395
|
+
var fs16 = __toESM(require("fs"));
|
|
6396
|
+
var os6 = __toESM(require("os"));
|
|
6397
|
+
var path17 = __toESM(require("path"));
|
|
6238
6398
|
var packageJson = require_package();
|
|
6239
6399
|
async function ensureValidToken(config, bufferMs = 5 * 60 * 1e3) {
|
|
6240
6400
|
const now = Date.now();
|
|
@@ -6303,7 +6463,7 @@ async function fetchWithAuth(url, options = {}, retryOnUnauthorized = true) {
|
|
|
6303
6463
|
}
|
|
6304
6464
|
return response;
|
|
6305
6465
|
}
|
|
6306
|
-
async function
|
|
6466
|
+
async function fetchEnvVars2() {
|
|
6307
6467
|
try {
|
|
6308
6468
|
const config = await (0, import_core10.loadConfig)();
|
|
6309
6469
|
if (!config?.project_id) {
|
|
@@ -6446,9 +6606,9 @@ var Daemon = class _Daemon {
|
|
|
6446
6606
|
machineId: this.machineId,
|
|
6447
6607
|
deviceId: this.deviceId,
|
|
6448
6608
|
// EP726: UUID for unified device identification
|
|
6449
|
-
hostname:
|
|
6450
|
-
platform:
|
|
6451
|
-
arch:
|
|
6609
|
+
hostname: os6.hostname(),
|
|
6610
|
+
platform: os6.platform(),
|
|
6611
|
+
arch: os6.arch(),
|
|
6452
6612
|
projects
|
|
6453
6613
|
};
|
|
6454
6614
|
});
|
|
@@ -6731,7 +6891,7 @@ var Daemon = class _Daemon {
|
|
|
6731
6891
|
client.updateActivity();
|
|
6732
6892
|
try {
|
|
6733
6893
|
const gitCmd = message.command;
|
|
6734
|
-
const bareRepoPath =
|
|
6894
|
+
const bareRepoPath = path17.join(projectPath, ".bare");
|
|
6735
6895
|
const cwd = gitCmd.worktreePath || bareRepoPath;
|
|
6736
6896
|
if (gitCmd.worktreePath) {
|
|
6737
6897
|
console.log(`[Daemon] Routing command to worktree: ${gitCmd.worktreePath}`);
|
|
@@ -7251,7 +7411,7 @@ var Daemon = class _Daemon {
|
|
|
7251
7411
|
}
|
|
7252
7412
|
const worktreeConfig = await (0, import_core10.loadConfig)();
|
|
7253
7413
|
const setupConfig = worktreeConfig?.project_settings;
|
|
7254
|
-
const envVars = await
|
|
7414
|
+
const envVars = await fetchEnvVars2();
|
|
7255
7415
|
const hasEnvVars = Object.keys(envVars).length > 0;
|
|
7256
7416
|
const hasSetupConfig = setupConfig?.worktree_copy_files?.length || setupConfig?.worktree_setup_script || hasEnvVars;
|
|
7257
7417
|
{
|
|
@@ -7365,8 +7525,8 @@ var Daemon = class _Daemon {
|
|
|
7365
7525
|
let daemonPid;
|
|
7366
7526
|
try {
|
|
7367
7527
|
const pidPath = getPidFilePath();
|
|
7368
|
-
if (
|
|
7369
|
-
const pidStr =
|
|
7528
|
+
if (fs16.existsSync(pidPath)) {
|
|
7529
|
+
const pidStr = fs16.readFileSync(pidPath, "utf-8").trim();
|
|
7370
7530
|
daemonPid = parseInt(pidStr, 10);
|
|
7371
7531
|
}
|
|
7372
7532
|
} catch (pidError) {
|
|
@@ -7390,9 +7550,9 @@ var Daemon = class _Daemon {
|
|
|
7390
7550
|
client.once("auth_error", errorHandler);
|
|
7391
7551
|
});
|
|
7392
7552
|
await client.connect(wsUrl, config.access_token, this.machineId, {
|
|
7393
|
-
hostname:
|
|
7394
|
-
osPlatform:
|
|
7395
|
-
osArch:
|
|
7553
|
+
hostname: os6.hostname(),
|
|
7554
|
+
osPlatform: os6.platform(),
|
|
7555
|
+
osArch: os6.arch(),
|
|
7396
7556
|
daemonPid
|
|
7397
7557
|
});
|
|
7398
7558
|
console.log(`[Daemon] Successfully connected to project ${projectId}`);
|
|
@@ -7487,27 +7647,27 @@ var Daemon = class _Daemon {
|
|
|
7487
7647
|
*/
|
|
7488
7648
|
async installGitHooks(projectPath) {
|
|
7489
7649
|
const hooks = ["post-checkout", "pre-commit", "post-commit"];
|
|
7490
|
-
const hooksDir =
|
|
7491
|
-
if (!
|
|
7650
|
+
const hooksDir = path17.join(projectPath, ".git", "hooks");
|
|
7651
|
+
if (!fs16.existsSync(hooksDir)) {
|
|
7492
7652
|
console.warn(`[Daemon] Hooks directory not found: ${hooksDir}`);
|
|
7493
7653
|
return;
|
|
7494
7654
|
}
|
|
7495
7655
|
for (const hookName of hooks) {
|
|
7496
7656
|
try {
|
|
7497
|
-
const hookPath =
|
|
7498
|
-
const bundledHookPath =
|
|
7499
|
-
if (!
|
|
7657
|
+
const hookPath = path17.join(hooksDir, hookName);
|
|
7658
|
+
const bundledHookPath = path17.join(__dirname, "..", "hooks", hookName);
|
|
7659
|
+
if (!fs16.existsSync(bundledHookPath)) {
|
|
7500
7660
|
console.warn(`[Daemon] Bundled hook not found: ${bundledHookPath}`);
|
|
7501
7661
|
continue;
|
|
7502
7662
|
}
|
|
7503
|
-
const hookContent =
|
|
7504
|
-
if (
|
|
7505
|
-
const existingContent =
|
|
7663
|
+
const hookContent = fs16.readFileSync(bundledHookPath, "utf-8");
|
|
7664
|
+
if (fs16.existsSync(hookPath)) {
|
|
7665
|
+
const existingContent = fs16.readFileSync(hookPath, "utf-8");
|
|
7506
7666
|
if (existingContent === hookContent) {
|
|
7507
7667
|
continue;
|
|
7508
7668
|
}
|
|
7509
7669
|
}
|
|
7510
|
-
|
|
7670
|
+
fs16.writeFileSync(hookPath, hookContent, { mode: 493 });
|
|
7511
7671
|
console.log(`[Daemon] Installed git hook: ${hookName}`);
|
|
7512
7672
|
} catch (error) {
|
|
7513
7673
|
console.warn(`[Daemon] Failed to install ${hookName} hook:`, error instanceof Error ? error.message : error);
|
|
@@ -7739,7 +7899,7 @@ var Daemon = class _Daemon {
|
|
|
7739
7899
|
continue;
|
|
7740
7900
|
}
|
|
7741
7901
|
const setupConfig = config.project_settings;
|
|
7742
|
-
const envVars = await
|
|
7902
|
+
const envVars = await fetchEnvVars2();
|
|
7743
7903
|
console.log(`[Daemon] EP995: Starting setup for reconciled module ${moduleUid}`);
|
|
7744
7904
|
await worktreeManager.updateWorktreeStatus(moduleUid, "pending");
|
|
7745
7905
|
await this.updateModuleWorktreeStatus(moduleUid, "pending", newWorktree.path);
|
|
@@ -8623,8 +8783,8 @@ var Daemon = class _Daemon {
|
|
|
8623
8783
|
await this.shutdown();
|
|
8624
8784
|
try {
|
|
8625
8785
|
const pidPath = getPidFilePath();
|
|
8626
|
-
if (
|
|
8627
|
-
|
|
8786
|
+
if (fs16.existsSync(pidPath)) {
|
|
8787
|
+
fs16.unlinkSync(pidPath);
|
|
8628
8788
|
console.log("[Daemon] PID file cleaned up");
|
|
8629
8789
|
}
|
|
8630
8790
|
} catch (error) {
|