@episoda/cli 0.2.189 → 0.2.190
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 +192 -129
- package/dist/daemon/daemon-process.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1640,15 +1640,15 @@ var require_git_executor = __commonJS({
|
|
|
1640
1640
|
try {
|
|
1641
1641
|
const { stdout: gitDir } = await execAsync3("git rev-parse --git-dir", { cwd, timeout: 5e3 });
|
|
1642
1642
|
const gitDirPath = gitDir.trim();
|
|
1643
|
-
const
|
|
1643
|
+
const fs36 = await Promise.resolve().then(() => __importStar(require("fs"))).then((m) => m.promises);
|
|
1644
1644
|
const rebaseMergePath = `${gitDirPath}/rebase-merge`;
|
|
1645
1645
|
const rebaseApplyPath = `${gitDirPath}/rebase-apply`;
|
|
1646
1646
|
try {
|
|
1647
|
-
await
|
|
1647
|
+
await fs36.access(rebaseMergePath);
|
|
1648
1648
|
inRebase = true;
|
|
1649
1649
|
} catch {
|
|
1650
1650
|
try {
|
|
1651
|
-
await
|
|
1651
|
+
await fs36.access(rebaseApplyPath);
|
|
1652
1652
|
inRebase = true;
|
|
1653
1653
|
} catch {
|
|
1654
1654
|
inRebase = false;
|
|
@@ -1704,9 +1704,9 @@ var require_git_executor = __commonJS({
|
|
|
1704
1704
|
};
|
|
1705
1705
|
}
|
|
1706
1706
|
}
|
|
1707
|
-
const
|
|
1707
|
+
const fs36 = await Promise.resolve().then(() => __importStar(require("fs"))).then((m) => m.promises);
|
|
1708
1708
|
try {
|
|
1709
|
-
await
|
|
1709
|
+
await fs36.access(command.path);
|
|
1710
1710
|
return {
|
|
1711
1711
|
success: false,
|
|
1712
1712
|
error: "WORKTREE_EXISTS",
|
|
@@ -1765,9 +1765,9 @@ var require_git_executor = __commonJS({
|
|
|
1765
1765
|
*/
|
|
1766
1766
|
async executeWorktreeRemove(command, cwd, options) {
|
|
1767
1767
|
try {
|
|
1768
|
-
const
|
|
1768
|
+
const fs36 = await Promise.resolve().then(() => __importStar(require("fs"))).then((m) => m.promises);
|
|
1769
1769
|
try {
|
|
1770
|
-
await
|
|
1770
|
+
await fs36.access(command.path);
|
|
1771
1771
|
} catch {
|
|
1772
1772
|
return {
|
|
1773
1773
|
success: false,
|
|
@@ -1802,7 +1802,7 @@ var require_git_executor = __commonJS({
|
|
|
1802
1802
|
const result = await this.runGitCommand(args, cwd, options);
|
|
1803
1803
|
if (result.success) {
|
|
1804
1804
|
try {
|
|
1805
|
-
await
|
|
1805
|
+
await fs36.rm(command.path, { recursive: true, force: true });
|
|
1806
1806
|
} catch {
|
|
1807
1807
|
}
|
|
1808
1808
|
return {
|
|
@@ -1936,10 +1936,10 @@ var require_git_executor = __commonJS({
|
|
|
1936
1936
|
*/
|
|
1937
1937
|
async executeCloneBare(command, options) {
|
|
1938
1938
|
try {
|
|
1939
|
-
const
|
|
1940
|
-
const
|
|
1939
|
+
const fs36 = await Promise.resolve().then(() => __importStar(require("fs"))).then((m) => m.promises);
|
|
1940
|
+
const path38 = await Promise.resolve().then(() => __importStar(require("path")));
|
|
1941
1941
|
try {
|
|
1942
|
-
await
|
|
1942
|
+
await fs36.access(command.path);
|
|
1943
1943
|
return {
|
|
1944
1944
|
success: false,
|
|
1945
1945
|
error: "BRANCH_ALREADY_EXISTS",
|
|
@@ -1948,9 +1948,9 @@ var require_git_executor = __commonJS({
|
|
|
1948
1948
|
};
|
|
1949
1949
|
} catch {
|
|
1950
1950
|
}
|
|
1951
|
-
const parentDir =
|
|
1951
|
+
const parentDir = path38.dirname(command.path);
|
|
1952
1952
|
try {
|
|
1953
|
-
await
|
|
1953
|
+
await fs36.mkdir(parentDir, { recursive: true });
|
|
1954
1954
|
} catch {
|
|
1955
1955
|
}
|
|
1956
1956
|
const { stdout, stderr } = await execAsync3(
|
|
@@ -1998,22 +1998,22 @@ var require_git_executor = __commonJS({
|
|
|
1998
1998
|
*/
|
|
1999
1999
|
async executeProjectInfo(cwd, options) {
|
|
2000
2000
|
try {
|
|
2001
|
-
const
|
|
2002
|
-
const
|
|
2001
|
+
const fs36 = await Promise.resolve().then(() => __importStar(require("fs"))).then((m) => m.promises);
|
|
2002
|
+
const path38 = await Promise.resolve().then(() => __importStar(require("path")));
|
|
2003
2003
|
let currentPath = cwd;
|
|
2004
2004
|
let projectPath = cwd;
|
|
2005
2005
|
let bareRepoPath;
|
|
2006
2006
|
for (let i = 0; i < 10; i++) {
|
|
2007
|
-
const bareDir =
|
|
2008
|
-
const episodaDir =
|
|
2007
|
+
const bareDir = path38.join(currentPath, ".bare");
|
|
2008
|
+
const episodaDir = path38.join(currentPath, ".episoda");
|
|
2009
2009
|
try {
|
|
2010
|
-
await
|
|
2011
|
-
await
|
|
2010
|
+
await fs36.access(bareDir);
|
|
2011
|
+
await fs36.access(episodaDir);
|
|
2012
2012
|
projectPath = currentPath;
|
|
2013
2013
|
bareRepoPath = bareDir;
|
|
2014
2014
|
break;
|
|
2015
2015
|
} catch {
|
|
2016
|
-
const parentPath =
|
|
2016
|
+
const parentPath = path38.dirname(currentPath);
|
|
2017
2017
|
if (parentPath === currentPath) {
|
|
2018
2018
|
break;
|
|
2019
2019
|
}
|
|
@@ -2724,33 +2724,33 @@ var require_auth = __commonJS({
|
|
|
2724
2724
|
exports2.loadConfig = loadConfig16;
|
|
2725
2725
|
exports2.saveConfig = saveConfig4;
|
|
2726
2726
|
exports2.validateToken = validateToken;
|
|
2727
|
-
var
|
|
2728
|
-
var
|
|
2729
|
-
var
|
|
2727
|
+
var fs36 = __importStar(require("fs"));
|
|
2728
|
+
var path38 = __importStar(require("path"));
|
|
2729
|
+
var os17 = __importStar(require("os"));
|
|
2730
2730
|
var child_process_1 = require("child_process");
|
|
2731
2731
|
var DEFAULT_CONFIG_FILE = "config.json";
|
|
2732
2732
|
var hasWarnedMissingProjectId = false;
|
|
2733
2733
|
var hasWarnedMissingRequiredFields = false;
|
|
2734
2734
|
function getConfigDir10() {
|
|
2735
|
-
return process.env.EPISODA_CONFIG_DIR ||
|
|
2735
|
+
return process.env.EPISODA_CONFIG_DIR || path38.join(os17.homedir(), ".episoda");
|
|
2736
2736
|
}
|
|
2737
2737
|
function getConfigPath(configPath) {
|
|
2738
2738
|
if (configPath) {
|
|
2739
2739
|
return configPath;
|
|
2740
2740
|
}
|
|
2741
|
-
return
|
|
2741
|
+
return path38.join(getConfigDir10(), DEFAULT_CONFIG_FILE);
|
|
2742
2742
|
}
|
|
2743
2743
|
function ensureConfigDir(configPath) {
|
|
2744
|
-
const dir =
|
|
2745
|
-
const isNew = !
|
|
2744
|
+
const dir = path38.dirname(configPath);
|
|
2745
|
+
const isNew = !fs36.existsSync(dir);
|
|
2746
2746
|
if (isNew) {
|
|
2747
|
-
|
|
2747
|
+
fs36.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
2748
2748
|
}
|
|
2749
2749
|
if (process.platform === "darwin") {
|
|
2750
|
-
const nosyncPath =
|
|
2751
|
-
if (isNew || !
|
|
2750
|
+
const nosyncPath = path38.join(dir, ".nosync");
|
|
2751
|
+
if (isNew || !fs36.existsSync(nosyncPath)) {
|
|
2752
2752
|
try {
|
|
2753
|
-
|
|
2753
|
+
fs36.writeFileSync(nosyncPath, "", { mode: 384 });
|
|
2754
2754
|
(0, child_process_1.execSync)(`xattr -w com.apple.fileprovider.ignore 1 "${dir}"`, {
|
|
2755
2755
|
stdio: "ignore",
|
|
2756
2756
|
timeout: 5e3
|
|
@@ -2764,11 +2764,11 @@ var require_auth = __commonJS({
|
|
|
2764
2764
|
const fullPath = getConfigPath(configPath);
|
|
2765
2765
|
const isCloudMode = process.env.EPISODA_MODE === "cloud";
|
|
2766
2766
|
const readConfigFile = (pathToFile) => {
|
|
2767
|
-
if (!
|
|
2767
|
+
if (!fs36.existsSync(pathToFile)) {
|
|
2768
2768
|
return null;
|
|
2769
2769
|
}
|
|
2770
2770
|
try {
|
|
2771
|
-
const content =
|
|
2771
|
+
const content = fs36.readFileSync(pathToFile, "utf8");
|
|
2772
2772
|
return JSON.parse(content);
|
|
2773
2773
|
} catch (error) {
|
|
2774
2774
|
console.error("Error loading config:", error);
|
|
@@ -2807,11 +2807,11 @@ var require_auth = __commonJS({
|
|
|
2807
2807
|
}
|
|
2808
2808
|
const homeDir = process.env.HOME || require("os").homedir();
|
|
2809
2809
|
const workspaceConfigPath = require("path").join(homeDir, "episoda", process.env.EPISODA_WORKSPACE, ".episoda", "config.json");
|
|
2810
|
-
if (!
|
|
2810
|
+
if (!fs36.existsSync(workspaceConfigPath)) {
|
|
2811
2811
|
return null;
|
|
2812
2812
|
}
|
|
2813
2813
|
try {
|
|
2814
|
-
const content =
|
|
2814
|
+
const content = fs36.readFileSync(workspaceConfigPath, "utf8");
|
|
2815
2815
|
const workspaceConfig2 = JSON.parse(content);
|
|
2816
2816
|
const expiresAtEnv = envValue(process.env.EPISODA_ACCESS_TOKEN_EXPIRES_AT);
|
|
2817
2817
|
return {
|
|
@@ -2839,11 +2839,11 @@ var require_auth = __commonJS({
|
|
|
2839
2839
|
}
|
|
2840
2840
|
const homeDir = process.env.HOME || require("os").homedir();
|
|
2841
2841
|
const projectConfigPath = require("path").join(homeDir, "episoda", workspaceSlug, projectSlug, ".episoda", "config.json");
|
|
2842
|
-
if (!
|
|
2842
|
+
if (!fs36.existsSync(projectConfigPath)) {
|
|
2843
2843
|
return null;
|
|
2844
2844
|
}
|
|
2845
2845
|
try {
|
|
2846
|
-
const content =
|
|
2846
|
+
const content = fs36.readFileSync(projectConfigPath, "utf8");
|
|
2847
2847
|
const projectConfig2 = JSON.parse(content);
|
|
2848
2848
|
return {
|
|
2849
2849
|
project_id: projectConfig2.projectId || projectConfig2.project_id,
|
|
@@ -2911,7 +2911,7 @@ var require_auth = __commonJS({
|
|
|
2911
2911
|
ensureConfigDir(fullPath);
|
|
2912
2912
|
try {
|
|
2913
2913
|
const content = JSON.stringify(config, null, 2);
|
|
2914
|
-
|
|
2914
|
+
fs36.writeFileSync(fullPath, content, { mode: 384 });
|
|
2915
2915
|
} catch (error) {
|
|
2916
2916
|
throw new Error(`Failed to save config: ${error instanceof Error ? error.message : String(error)}`);
|
|
2917
2917
|
}
|
|
@@ -3046,7 +3046,7 @@ var require_package = __commonJS({
|
|
|
3046
3046
|
"package.json"(exports2, module2) {
|
|
3047
3047
|
module2.exports = {
|
|
3048
3048
|
name: "@episoda/cli",
|
|
3049
|
-
version: "0.2.
|
|
3049
|
+
version: "0.2.190",
|
|
3050
3050
|
description: "CLI tool for Episoda local development workflow orchestration",
|
|
3051
3051
|
main: "dist/index.js",
|
|
3052
3052
|
types: "dist/index.d.ts",
|
|
@@ -9663,14 +9663,14 @@ function getInstallCommand(cwd) {
|
|
|
9663
9663
|
}
|
|
9664
9664
|
|
|
9665
9665
|
// src/daemon/daemon-process.ts
|
|
9666
|
-
var
|
|
9666
|
+
var fs35 = __toESM(require("fs"));
|
|
9667
9667
|
var http2 = __toESM(require("http"));
|
|
9668
|
-
var
|
|
9669
|
-
var
|
|
9668
|
+
var os16 = __toESM(require("os"));
|
|
9669
|
+
var path37 = __toESM(require("path"));
|
|
9670
9670
|
var import_child_process19 = require("child_process");
|
|
9671
9671
|
|
|
9672
9672
|
// src/daemon/ipc-router.ts
|
|
9673
|
-
var
|
|
9673
|
+
var os15 = __toESM(require("os"));
|
|
9674
9674
|
var import_core15 = __toESM(require_dist());
|
|
9675
9675
|
|
|
9676
9676
|
// src/daemon/handlers/file-handlers.ts
|
|
@@ -12873,6 +12873,9 @@ async function handleProjectSetup(params) {
|
|
|
12873
12873
|
|
|
12874
12874
|
// src/daemon/handlers/pty-handler.ts
|
|
12875
12875
|
var pty = __toESM(require("@lydell/node-pty"));
|
|
12876
|
+
var fs30 = __toESM(require("fs"));
|
|
12877
|
+
var os14 = __toESM(require("os"));
|
|
12878
|
+
var path30 = __toESM(require("path"));
|
|
12876
12879
|
var INACTIVITY_TIMEOUT_MS3 = 30 * 60 * 1e3;
|
|
12877
12880
|
var sessions = /* @__PURE__ */ new Map();
|
|
12878
12881
|
async function handlePtySpawn(payload, client) {
|
|
@@ -12882,6 +12885,7 @@ async function handlePtySpawn(payload, client) {
|
|
|
12882
12885
|
return;
|
|
12883
12886
|
}
|
|
12884
12887
|
console.log(`[PTY] Spawning PTY for ${moduleUid} / ${agent_run_id}: ${command} ${args.join(" ")}`);
|
|
12888
|
+
const bootstrap = createCredentialBootstrap(payload, agent_run_id);
|
|
12885
12889
|
let proc;
|
|
12886
12890
|
try {
|
|
12887
12891
|
proc = pty.spawn(command, args, {
|
|
@@ -12889,9 +12893,14 @@ async function handlePtySpawn(payload, client) {
|
|
|
12889
12893
|
cols,
|
|
12890
12894
|
rows,
|
|
12891
12895
|
cwd: cwd || process.cwd(),
|
|
12892
|
-
env: {
|
|
12896
|
+
env: {
|
|
12897
|
+
...process.env,
|
|
12898
|
+
...env || {},
|
|
12899
|
+
...bootstrap.env
|
|
12900
|
+
}
|
|
12893
12901
|
});
|
|
12894
12902
|
} catch (err) {
|
|
12903
|
+
cleanupCredentialDirs(bootstrap.cleanupDirs);
|
|
12895
12904
|
console.error(`[PTY] Failed to spawn PTY for ${agent_run_id}:`, err);
|
|
12896
12905
|
await client.send({
|
|
12897
12906
|
type: "pty_exit",
|
|
@@ -12908,7 +12917,8 @@ async function handlePtySpawn(payload, client) {
|
|
|
12908
12917
|
agent_run_id,
|
|
12909
12918
|
startedAt: Date.now(),
|
|
12910
12919
|
lastOutputAt: Date.now(),
|
|
12911
|
-
watchdogTimer: null
|
|
12920
|
+
watchdogTimer: null,
|
|
12921
|
+
credentialDirs: bootstrap.cleanupDirs
|
|
12912
12922
|
};
|
|
12913
12923
|
sessions.set(agent_run_id, session);
|
|
12914
12924
|
const resetWatchdog = () => {
|
|
@@ -12942,6 +12952,7 @@ async function handlePtySpawn(payload, client) {
|
|
|
12942
12952
|
if (session.watchdogTimer) clearTimeout(session.watchdogTimer);
|
|
12943
12953
|
console.log(`[PTY] Process exited for ${agent_run_id} with code ${exitCode} after ${durationMs}ms`);
|
|
12944
12954
|
sessions.delete(agent_run_id);
|
|
12955
|
+
cleanupCredentialDirs(session.credentialDirs);
|
|
12945
12956
|
client.send({
|
|
12946
12957
|
type: "pty_exit",
|
|
12947
12958
|
moduleUid,
|
|
@@ -12977,15 +12988,67 @@ function handlePtyKill(payload) {
|
|
|
12977
12988
|
session.pty.kill();
|
|
12978
12989
|
} catch {
|
|
12979
12990
|
}
|
|
12991
|
+
cleanupCredentialDirs(session.credentialDirs);
|
|
12980
12992
|
sessions.delete(agent_run_id);
|
|
12981
12993
|
console.log(`[PTY] Killed session ${agent_run_id}`);
|
|
12982
12994
|
}
|
|
12995
|
+
function createCredentialBootstrap(payload, agentRunId) {
|
|
12996
|
+
const bootstrap = payload.credential_bootstrap;
|
|
12997
|
+
if (!bootstrap?.oauth?.access_token) {
|
|
12998
|
+
return { env: {}, cleanupDirs: [] };
|
|
12999
|
+
}
|
|
13000
|
+
const baseDir = fs30.mkdtempSync(path30.join(os14.tmpdir(), `episoda-pty-${agentRunId}-`));
|
|
13001
|
+
const cleanupDirs = [baseDir];
|
|
13002
|
+
if (bootstrap.provider === "claude") {
|
|
13003
|
+
const claudeConfigDir = path30.join(baseDir, ".claude");
|
|
13004
|
+
fs30.mkdirSync(claudeConfigDir, { recursive: true });
|
|
13005
|
+
const credentialsPath = path30.join(claudeConfigDir, ".credentials.json");
|
|
13006
|
+
const claudeAiOauth = {
|
|
13007
|
+
accessToken: bootstrap.oauth.access_token
|
|
13008
|
+
};
|
|
13009
|
+
if (bootstrap.oauth.refresh_token) claudeAiOauth.refreshToken = bootstrap.oauth.refresh_token;
|
|
13010
|
+
if (bootstrap.oauth.expires_at) claudeAiOauth.expiresAt = new Date(bootstrap.oauth.expires_at).getTime();
|
|
13011
|
+
if (bootstrap.oauth.scopes) claudeAiOauth.scopes = bootstrap.oauth.scopes;
|
|
13012
|
+
fs30.writeFileSync(credentialsPath, JSON.stringify({ claudeAiOauth }, null, 2), { mode: 384 });
|
|
13013
|
+
return {
|
|
13014
|
+
env: { CLAUDE_CONFIG_DIR: claudeConfigDir },
|
|
13015
|
+
cleanupDirs
|
|
13016
|
+
};
|
|
13017
|
+
}
|
|
13018
|
+
const codexHome = path30.join(baseDir, ".codex");
|
|
13019
|
+
fs30.mkdirSync(codexHome, { recursive: true });
|
|
13020
|
+
const authPath = path30.join(codexHome, "auth.json");
|
|
13021
|
+
const authPayload = {
|
|
13022
|
+
tokens: {
|
|
13023
|
+
access_token: bootstrap.oauth.access_token,
|
|
13024
|
+
refresh_token: bootstrap.oauth.refresh_token,
|
|
13025
|
+
id_token: bootstrap.oauth.id_token,
|
|
13026
|
+
account_id: bootstrap.oauth.account_id
|
|
13027
|
+
}
|
|
13028
|
+
};
|
|
13029
|
+
fs30.writeFileSync(authPath, JSON.stringify(authPayload, null, 2), { mode: 384 });
|
|
13030
|
+
return {
|
|
13031
|
+
env: { CODEX_HOME: codexHome },
|
|
13032
|
+
cleanupDirs
|
|
13033
|
+
};
|
|
13034
|
+
}
|
|
13035
|
+
function cleanupCredentialDirs(dirs) {
|
|
13036
|
+
for (const dirPath of dirs) {
|
|
13037
|
+
try {
|
|
13038
|
+
if (fs30.existsSync(dirPath)) {
|
|
13039
|
+
fs30.rmSync(dirPath, { recursive: true, force: true });
|
|
13040
|
+
}
|
|
13041
|
+
} catch (error) {
|
|
13042
|
+
console.warn(`[PTY] Failed to cleanup credential dir ${dirPath}:`, error);
|
|
13043
|
+
}
|
|
13044
|
+
}
|
|
13045
|
+
}
|
|
12983
13046
|
|
|
12984
13047
|
// src/utils/dev-server.ts
|
|
12985
13048
|
var import_child_process15 = require("child_process");
|
|
12986
13049
|
var import_core14 = __toESM(require_dist());
|
|
12987
|
-
var
|
|
12988
|
-
var
|
|
13050
|
+
var fs31 = __toESM(require("fs"));
|
|
13051
|
+
var path31 = __toESM(require("path"));
|
|
12989
13052
|
var MAX_RESTART_ATTEMPTS = 5;
|
|
12990
13053
|
var INITIAL_RESTART_DELAY_MS = 2e3;
|
|
12991
13054
|
var MAX_RESTART_DELAY_MS = 3e4;
|
|
@@ -12993,26 +13056,26 @@ var MAX_LOG_SIZE_BYTES2 = 5 * 1024 * 1024;
|
|
|
12993
13056
|
var NODE_MEMORY_LIMIT_MB = 2048;
|
|
12994
13057
|
var activeServers = /* @__PURE__ */ new Map();
|
|
12995
13058
|
function getLogsDir() {
|
|
12996
|
-
const logsDir =
|
|
12997
|
-
if (!
|
|
12998
|
-
|
|
13059
|
+
const logsDir = path31.join((0, import_core14.getConfigDir)(), "logs");
|
|
13060
|
+
if (!fs31.existsSync(logsDir)) {
|
|
13061
|
+
fs31.mkdirSync(logsDir, { recursive: true });
|
|
12999
13062
|
}
|
|
13000
13063
|
return logsDir;
|
|
13001
13064
|
}
|
|
13002
13065
|
function getLogFilePath(moduleUid) {
|
|
13003
|
-
return
|
|
13066
|
+
return path31.join(getLogsDir(), `dev-${moduleUid}.log`);
|
|
13004
13067
|
}
|
|
13005
13068
|
function rotateLogIfNeeded(logPath) {
|
|
13006
13069
|
try {
|
|
13007
|
-
if (
|
|
13008
|
-
const stats =
|
|
13070
|
+
if (fs31.existsSync(logPath)) {
|
|
13071
|
+
const stats = fs31.statSync(logPath);
|
|
13009
13072
|
if (stats.size > MAX_LOG_SIZE_BYTES2) {
|
|
13010
13073
|
const backupPath = `${logPath}.1`;
|
|
13011
|
-
if (
|
|
13012
|
-
|
|
13074
|
+
if (fs31.existsSync(backupPath)) {
|
|
13075
|
+
fs31.unlinkSync(backupPath);
|
|
13013
13076
|
}
|
|
13014
|
-
|
|
13015
|
-
console.log(`[DevServer] EP932: Rotated log file for ${
|
|
13077
|
+
fs31.renameSync(logPath, backupPath);
|
|
13078
|
+
console.log(`[DevServer] EP932: Rotated log file for ${path31.basename(logPath)}`);
|
|
13016
13079
|
}
|
|
13017
13080
|
}
|
|
13018
13081
|
} catch (error) {
|
|
@@ -13025,7 +13088,7 @@ function writeToLog(logPath, line, isError = false) {
|
|
|
13025
13088
|
const prefix = isError ? "ERR" : "OUT";
|
|
13026
13089
|
const logLine = `[${timestamp}] [${prefix}] ${line}
|
|
13027
13090
|
`;
|
|
13028
|
-
|
|
13091
|
+
fs31.appendFileSync(logPath, logLine);
|
|
13029
13092
|
} catch {
|
|
13030
13093
|
}
|
|
13031
13094
|
}
|
|
@@ -13204,8 +13267,8 @@ async function startDevServer(projectPath, port = 3e3, moduleUid = "default", op
|
|
|
13204
13267
|
});
|
|
13205
13268
|
injectedEnvVars = result.envVars;
|
|
13206
13269
|
console.log(`[DevServer] EP998: Loaded ${Object.keys(injectedEnvVars).length} env vars (from ${result.fromCache ? "cache" : "server"})`);
|
|
13207
|
-
const envFilePath =
|
|
13208
|
-
if (!
|
|
13270
|
+
const envFilePath = path31.join(projectPath, ".env");
|
|
13271
|
+
if (!fs31.existsSync(envFilePath) && Object.keys(injectedEnvVars).length > 0) {
|
|
13209
13272
|
console.log(`[DevServer] EP1004: .env file missing, writing ${Object.keys(injectedEnvVars).length} vars to ${envFilePath}`);
|
|
13210
13273
|
writeEnvFile(projectPath, injectedEnvVars);
|
|
13211
13274
|
}
|
|
@@ -13343,9 +13406,9 @@ var IPCRouter = class {
|
|
|
13343
13406
|
// EP726: Kept for backward compatibility
|
|
13344
13407
|
machineName: this.host.deviceName,
|
|
13345
13408
|
// EP1186: User-friendly machine name from server
|
|
13346
|
-
hostname:
|
|
13347
|
-
platform:
|
|
13348
|
-
arch:
|
|
13409
|
+
hostname: os15.hostname(),
|
|
13410
|
+
platform: os15.platform(),
|
|
13411
|
+
arch: os15.arch(),
|
|
13349
13412
|
projects
|
|
13350
13413
|
};
|
|
13351
13414
|
});
|
|
@@ -13547,8 +13610,8 @@ var IPCRouter = class {
|
|
|
13547
13610
|
};
|
|
13548
13611
|
|
|
13549
13612
|
// src/daemon/update-manager.ts
|
|
13550
|
-
var
|
|
13551
|
-
var
|
|
13613
|
+
var fs32 = __toESM(require("fs"));
|
|
13614
|
+
var path32 = __toESM(require("path"));
|
|
13552
13615
|
var import_child_process17 = require("child_process");
|
|
13553
13616
|
var import_core17 = __toESM(require_dist());
|
|
13554
13617
|
var semver2 = __toESM(require("semver"));
|
|
@@ -13806,8 +13869,8 @@ var UpdateManager = class _UpdateManager {
|
|
|
13806
13869
|
console.log(`[Daemon] EP1324: Update to ${targetVersion} installed, restarting daemon...`);
|
|
13807
13870
|
await this.host.shutdown();
|
|
13808
13871
|
const configDir = (0, import_core17.getConfigDir)();
|
|
13809
|
-
const logPath =
|
|
13810
|
-
const logFd =
|
|
13872
|
+
const logPath = path32.join(configDir, "daemon.log");
|
|
13873
|
+
const logFd = fs32.openSync(logPath, "a");
|
|
13811
13874
|
const child = (0, import_child_process17.spawn)("node", [this.daemonEntryFile], {
|
|
13812
13875
|
detached: true,
|
|
13813
13876
|
stdio: ["ignore", logFd, logFd],
|
|
@@ -13817,7 +13880,7 @@ var UpdateManager = class _UpdateManager {
|
|
|
13817
13880
|
});
|
|
13818
13881
|
if (!child.pid) {
|
|
13819
13882
|
try {
|
|
13820
|
-
|
|
13883
|
+
fs32.closeSync(logFd);
|
|
13821
13884
|
} catch {
|
|
13822
13885
|
}
|
|
13823
13886
|
this.recordUpdateFailure(targetVersion, "Failed to spawn replacement daemon (missing pid)");
|
|
@@ -13825,7 +13888,7 @@ var UpdateManager = class _UpdateManager {
|
|
|
13825
13888
|
}
|
|
13826
13889
|
child.unref();
|
|
13827
13890
|
const pidPath = getPidFilePath();
|
|
13828
|
-
|
|
13891
|
+
fs32.writeFileSync(pidPath, child.pid.toString(), "utf-8");
|
|
13829
13892
|
console.log(`[Daemon] EP1324: New daemon spawned (PID: ${child.pid}), exiting old process`);
|
|
13830
13893
|
process.exit(0);
|
|
13831
13894
|
} catch (error) {
|
|
@@ -13876,8 +13939,8 @@ var UpdateManager = class _UpdateManager {
|
|
|
13876
13939
|
};
|
|
13877
13940
|
|
|
13878
13941
|
// src/daemon/health-orchestrator.ts
|
|
13879
|
-
var
|
|
13880
|
-
var
|
|
13942
|
+
var fs33 = __toESM(require("fs"));
|
|
13943
|
+
var path33 = __toESM(require("path"));
|
|
13881
13944
|
var import_core18 = __toESM(require_dist());
|
|
13882
13945
|
var HealthOrchestrator = class _HealthOrchestrator {
|
|
13883
13946
|
constructor(host) {
|
|
@@ -14137,26 +14200,26 @@ var HealthOrchestrator = class _HealthOrchestrator {
|
|
|
14137
14200
|
checkAndRotateLog() {
|
|
14138
14201
|
try {
|
|
14139
14202
|
const configDir = (0, import_core18.getConfigDir)();
|
|
14140
|
-
const logPath =
|
|
14141
|
-
if (!
|
|
14142
|
-
const stats =
|
|
14203
|
+
const logPath = path33.join(configDir, "daemon.log");
|
|
14204
|
+
if (!fs33.existsSync(logPath)) return;
|
|
14205
|
+
const stats = fs33.statSync(logPath);
|
|
14143
14206
|
if (stats.size < _HealthOrchestrator.MAX_LOG_SIZE_BYTES) return;
|
|
14144
14207
|
console.log(`[Daemon] EP1351: daemon.log is ${Math.round(stats.size / 1024 / 1024)}MB, rotating...`);
|
|
14145
14208
|
for (let i = _HealthOrchestrator.MAX_LOG_FILES - 1; i >= 1; i--) {
|
|
14146
14209
|
const src = `${logPath}.${i}`;
|
|
14147
14210
|
const dst = `${logPath}.${i + 1}`;
|
|
14148
|
-
if (
|
|
14211
|
+
if (fs33.existsSync(src)) {
|
|
14149
14212
|
try {
|
|
14150
|
-
|
|
14213
|
+
fs33.renameSync(src, dst);
|
|
14151
14214
|
} catch {
|
|
14152
14215
|
}
|
|
14153
14216
|
}
|
|
14154
14217
|
}
|
|
14155
14218
|
try {
|
|
14156
|
-
|
|
14219
|
+
fs33.copyFileSync(logPath, `${logPath}.1`);
|
|
14157
14220
|
} catch {
|
|
14158
14221
|
}
|
|
14159
|
-
|
|
14222
|
+
fs33.truncateSync(logPath, 0);
|
|
14160
14223
|
console.log("[Daemon] EP1351: Log rotated successfully");
|
|
14161
14224
|
} catch (error) {
|
|
14162
14225
|
console.warn("[Daemon] EP1351: Log rotation failed:", error instanceof Error ? error.message : error);
|
|
@@ -14205,9 +14268,9 @@ var HealthOrchestrator = class _HealthOrchestrator {
|
|
|
14205
14268
|
if (Number.isFinite(lastAccessedMs)) {
|
|
14206
14269
|
referenceTimestampMs = lastAccessedMs;
|
|
14207
14270
|
fallbackAgeSource.push(`${w.moduleUid}(lastAccessed)`);
|
|
14208
|
-
} else if (w.worktreePath &&
|
|
14271
|
+
} else if (w.worktreePath && fs33.existsSync(w.worktreePath)) {
|
|
14209
14272
|
try {
|
|
14210
|
-
const stats =
|
|
14273
|
+
const stats = fs33.statSync(w.worktreePath);
|
|
14211
14274
|
referenceTimestampMs = stats.mtimeMs;
|
|
14212
14275
|
fallbackAgeSource.push(`${w.moduleUid}(fs.mtime)`);
|
|
14213
14276
|
} catch {
|
|
@@ -14753,7 +14816,7 @@ function resolveDaemonWsEndpoint(config, env = process.env) {
|
|
|
14753
14816
|
|
|
14754
14817
|
// src/daemon/project-message-router.ts
|
|
14755
14818
|
var import_core19 = __toESM(require_dist());
|
|
14756
|
-
var
|
|
14819
|
+
var path34 = __toESM(require("path"));
|
|
14757
14820
|
var ProjectMessageRouter = class {
|
|
14758
14821
|
constructor(host) {
|
|
14759
14822
|
this.host = host;
|
|
@@ -14771,7 +14834,7 @@ var ProjectMessageRouter = class {
|
|
|
14771
14834
|
client.updateActivity();
|
|
14772
14835
|
try {
|
|
14773
14836
|
const gitCmd = message.command;
|
|
14774
|
-
const bareRepoPath =
|
|
14837
|
+
const bareRepoPath = path34.join(projectPath, ".bare");
|
|
14775
14838
|
const cwd = gitCmd.worktreePath || bareRepoPath;
|
|
14776
14839
|
if (gitCmd.worktreePath) {
|
|
14777
14840
|
console.log(`[Daemon] Routing command to worktree: ${gitCmd.worktreePath}`);
|
|
@@ -15145,32 +15208,32 @@ async function fetchEnvVars2(projectId) {
|
|
|
15145
15208
|
}
|
|
15146
15209
|
|
|
15147
15210
|
// src/daemon/project-git-config.ts
|
|
15148
|
-
var
|
|
15149
|
-
var
|
|
15211
|
+
var fs34 = __toESM(require("fs"));
|
|
15212
|
+
var path35 = __toESM(require("path"));
|
|
15150
15213
|
var import_core21 = __toESM(require_dist());
|
|
15151
15214
|
function getGitDirs(projectPath) {
|
|
15152
|
-
const bareDir =
|
|
15153
|
-
const gitPath =
|
|
15154
|
-
if (
|
|
15215
|
+
const bareDir = path35.join(projectPath, ".bare");
|
|
15216
|
+
const gitPath = path35.join(projectPath, ".git");
|
|
15217
|
+
if (fs34.existsSync(bareDir) && fs34.statSync(bareDir).isDirectory()) {
|
|
15155
15218
|
return { gitDir: bareDir, workDir: projectPath };
|
|
15156
15219
|
}
|
|
15157
|
-
if (
|
|
15220
|
+
if (fs34.existsSync(gitPath) && fs34.statSync(gitPath).isDirectory()) {
|
|
15158
15221
|
return { gitDir: null, workDir: projectPath };
|
|
15159
15222
|
}
|
|
15160
|
-
if (
|
|
15223
|
+
if (fs34.existsSync(gitPath) && fs34.statSync(gitPath).isFile()) {
|
|
15161
15224
|
return { gitDir: null, workDir: projectPath };
|
|
15162
15225
|
}
|
|
15163
|
-
const entries =
|
|
15226
|
+
const entries = fs34.readdirSync(projectPath, { withFileTypes: true });
|
|
15164
15227
|
for (const entry of entries) {
|
|
15165
15228
|
if (entry.isDirectory() && entry.name.startsWith("EP")) {
|
|
15166
|
-
const worktreePath =
|
|
15167
|
-
const worktreeGit =
|
|
15168
|
-
if (
|
|
15229
|
+
const worktreePath = path35.join(projectPath, entry.name);
|
|
15230
|
+
const worktreeGit = path35.join(worktreePath, ".git");
|
|
15231
|
+
if (fs34.existsSync(worktreeGit)) {
|
|
15169
15232
|
return { gitDir: null, workDir: worktreePath };
|
|
15170
15233
|
}
|
|
15171
15234
|
}
|
|
15172
15235
|
}
|
|
15173
|
-
if (
|
|
15236
|
+
if (fs34.existsSync(bareDir)) {
|
|
15174
15237
|
return { gitDir: bareDir, workDir: projectPath };
|
|
15175
15238
|
}
|
|
15176
15239
|
return { gitDir: null, workDir: projectPath };
|
|
@@ -15215,24 +15278,24 @@ async function configureGitUser(projectPath, userId, workspaceId, machineId, pro
|
|
|
15215
15278
|
async function installGitHooks(projectPath) {
|
|
15216
15279
|
const hooks = ["post-checkout", "pre-commit", "post-commit"];
|
|
15217
15280
|
let hooksDir;
|
|
15218
|
-
const bareHooksDir =
|
|
15219
|
-
const gitHooksDir =
|
|
15220
|
-
if (
|
|
15281
|
+
const bareHooksDir = path35.join(projectPath, ".bare", "hooks");
|
|
15282
|
+
const gitHooksDir = path35.join(projectPath, ".git", "hooks");
|
|
15283
|
+
if (fs34.existsSync(bareHooksDir)) {
|
|
15221
15284
|
hooksDir = bareHooksDir;
|
|
15222
|
-
} else if (
|
|
15285
|
+
} else if (fs34.existsSync(gitHooksDir) && fs34.statSync(path35.join(projectPath, ".git")).isDirectory()) {
|
|
15223
15286
|
hooksDir = gitHooksDir;
|
|
15224
15287
|
} else {
|
|
15225
|
-
const parentBareHooks =
|
|
15226
|
-
if (
|
|
15288
|
+
const parentBareHooks = path35.join(projectPath, "..", ".bare", "hooks");
|
|
15289
|
+
if (fs34.existsSync(parentBareHooks)) {
|
|
15227
15290
|
hooksDir = parentBareHooks;
|
|
15228
15291
|
} else {
|
|
15229
15292
|
console.warn(`[Daemon] Hooks directory not found for: ${projectPath}`);
|
|
15230
15293
|
return;
|
|
15231
15294
|
}
|
|
15232
15295
|
}
|
|
15233
|
-
if (!
|
|
15296
|
+
if (!fs34.existsSync(hooksDir)) {
|
|
15234
15297
|
try {
|
|
15235
|
-
|
|
15298
|
+
fs34.mkdirSync(hooksDir, { recursive: true });
|
|
15236
15299
|
} catch {
|
|
15237
15300
|
console.warn(`[Daemon] Hooks directory not found and could not create: ${hooksDir}`);
|
|
15238
15301
|
return;
|
|
@@ -15240,20 +15303,20 @@ async function installGitHooks(projectPath) {
|
|
|
15240
15303
|
}
|
|
15241
15304
|
for (const hookName of hooks) {
|
|
15242
15305
|
try {
|
|
15243
|
-
const hookPath =
|
|
15244
|
-
const bundledHookPath =
|
|
15245
|
-
if (!
|
|
15306
|
+
const hookPath = path35.join(hooksDir, hookName);
|
|
15307
|
+
const bundledHookPath = path35.join(__dirname, "..", "hooks", hookName);
|
|
15308
|
+
if (!fs34.existsSync(bundledHookPath)) {
|
|
15246
15309
|
console.warn(`[Daemon] Bundled hook not found: ${bundledHookPath}`);
|
|
15247
15310
|
continue;
|
|
15248
15311
|
}
|
|
15249
|
-
const hookContent =
|
|
15250
|
-
if (
|
|
15251
|
-
const existingContent =
|
|
15312
|
+
const hookContent = fs34.readFileSync(bundledHookPath, "utf-8");
|
|
15313
|
+
if (fs34.existsSync(hookPath)) {
|
|
15314
|
+
const existingContent = fs34.readFileSync(hookPath, "utf-8");
|
|
15252
15315
|
if (existingContent === hookContent) {
|
|
15253
15316
|
continue;
|
|
15254
15317
|
}
|
|
15255
15318
|
}
|
|
15256
|
-
|
|
15319
|
+
fs34.writeFileSync(hookPath, hookContent, { mode: 493 });
|
|
15257
15320
|
console.log(`[Daemon] Installed git hook: ${hookName}`);
|
|
15258
15321
|
} catch (error) {
|
|
15259
15322
|
console.warn(`[Daemon] Failed to install ${hookName} hook:`, error instanceof Error ? error.message : error);
|
|
@@ -15284,21 +15347,21 @@ async function cacheMachineUuid(machineUuid, machineId) {
|
|
|
15284
15347
|
}
|
|
15285
15348
|
|
|
15286
15349
|
// src/daemon/reconciliation-utils.ts
|
|
15287
|
-
var
|
|
15350
|
+
var path36 = __toESM(require("path"));
|
|
15288
15351
|
function isPathUnderRoot(candidatePath, projectRoot) {
|
|
15289
|
-
const relative4 =
|
|
15290
|
-
return relative4 !== "" && !relative4.startsWith("..") && !
|
|
15352
|
+
const relative4 = path36.relative(projectRoot, candidatePath);
|
|
15353
|
+
return relative4 !== "" && !relative4.startsWith("..") && !path36.isAbsolute(relative4);
|
|
15291
15354
|
}
|
|
15292
15355
|
function collectUnexpectedWorktrees(params) {
|
|
15293
|
-
const projectRootResolved =
|
|
15294
|
-
const bareRepoPathResolved =
|
|
15356
|
+
const projectRootResolved = path36.resolve(params.projectRoot);
|
|
15357
|
+
const bareRepoPathResolved = path36.resolve(params.bareRepoPath);
|
|
15295
15358
|
const unexpectedWorktrees = [];
|
|
15296
15359
|
for (const worktree of params.worktrees) {
|
|
15297
|
-
const worktreePathResolved =
|
|
15360
|
+
const worktreePathResolved = path36.resolve(worktree.path);
|
|
15298
15361
|
if (worktreePathResolved === bareRepoPathResolved) continue;
|
|
15299
15362
|
if (worktree.prunable || worktree.locked) continue;
|
|
15300
15363
|
if (!isPathUnderRoot(worktreePathResolved, projectRootResolved)) continue;
|
|
15301
|
-
const moduleUid =
|
|
15364
|
+
const moduleUid = path36.basename(worktreePathResolved);
|
|
15302
15365
|
if (!validateModuleUid(moduleUid)) continue;
|
|
15303
15366
|
if (!/^EP\d+$/.test(moduleUid)) continue;
|
|
15304
15367
|
if (params.expectedModuleUids.has(moduleUid)) continue;
|
|
@@ -15515,9 +15578,9 @@ var Daemon = class _Daemon {
|
|
|
15515
15578
|
this.healthServer = http2.createServer((req, res) => {
|
|
15516
15579
|
if (req.url === "/health" || req.url === "/") {
|
|
15517
15580
|
const isConnected = this.connectionManager.liveConnectionCount() > 0;
|
|
15518
|
-
const projects = Array.from(this.connectionManager.entries()).map(([
|
|
15519
|
-
path:
|
|
15520
|
-
connected: this.connectionManager.hasLiveConnection(
|
|
15581
|
+
const projects = Array.from(this.connectionManager.entries()).map(([path38, conn]) => ({
|
|
15582
|
+
path: path38,
|
|
15583
|
+
connected: this.connectionManager.hasLiveConnection(path38)
|
|
15521
15584
|
}));
|
|
15522
15585
|
const status = {
|
|
15523
15586
|
status: isConnected ? "healthy" : "degraded",
|
|
@@ -15590,8 +15653,8 @@ var Daemon = class _Daemon {
|
|
|
15590
15653
|
await this.shutdown();
|
|
15591
15654
|
try {
|
|
15592
15655
|
const pidPath = getPidFilePath();
|
|
15593
|
-
if (
|
|
15594
|
-
|
|
15656
|
+
if (fs35.existsSync(pidPath)) {
|
|
15657
|
+
fs35.unlinkSync(pidPath);
|
|
15595
15658
|
console.log("[Daemon] PID file cleaned up (watchdog)");
|
|
15596
15659
|
}
|
|
15597
15660
|
} catch (error) {
|
|
@@ -16269,8 +16332,8 @@ var Daemon = class _Daemon {
|
|
|
16269
16332
|
let daemonPid;
|
|
16270
16333
|
try {
|
|
16271
16334
|
const pidPath = getPidFilePath();
|
|
16272
|
-
if (
|
|
16273
|
-
const pidStr =
|
|
16335
|
+
if (fs35.existsSync(pidPath)) {
|
|
16336
|
+
const pidStr = fs35.readFileSync(pidPath, "utf-8").trim();
|
|
16274
16337
|
daemonPid = parseInt(pidStr, 10);
|
|
16275
16338
|
}
|
|
16276
16339
|
} catch (pidError) {
|
|
@@ -16281,9 +16344,9 @@ var Daemon = class _Daemon {
|
|
|
16281
16344
|
const containerId = process.env.EPISODA_CONTAINER_ID;
|
|
16282
16345
|
const capabilities = ["worktree_create_v1"];
|
|
16283
16346
|
await client.connect(wsEndpoint.wsUrl, config.access_token, this.machineId, {
|
|
16284
|
-
hostname:
|
|
16285
|
-
osPlatform:
|
|
16286
|
-
osArch:
|
|
16347
|
+
hostname: os16.hostname(),
|
|
16348
|
+
osPlatform: os16.platform(),
|
|
16349
|
+
osArch: os16.arch(),
|
|
16287
16350
|
daemonPid,
|
|
16288
16351
|
cliVersion: this.cliRuntimeVersion,
|
|
16289
16352
|
cliPackageName: packageJson.name,
|
|
@@ -16520,7 +16583,7 @@ var Daemon = class _Daemon {
|
|
|
16520
16583
|
await tunnelManager.initialize();
|
|
16521
16584
|
const moduleStatuses = [];
|
|
16522
16585
|
const expectedModuleUids = new Set(modules.map((m) => m.uid));
|
|
16523
|
-
const bareRepoPath =
|
|
16586
|
+
const bareRepoPath = path37.join(projectPath, ".bare");
|
|
16524
16587
|
for (const mod of modules) {
|
|
16525
16588
|
const moduleUid = mod.uid;
|
|
16526
16589
|
const worktree = await getWorktreeInfoForModule(moduleUid);
|
|
@@ -16963,8 +17026,8 @@ var Daemon = class _Daemon {
|
|
|
16963
17026
|
await this.shutdown();
|
|
16964
17027
|
try {
|
|
16965
17028
|
const pidPath = getPidFilePath();
|
|
16966
|
-
if (
|
|
16967
|
-
|
|
17029
|
+
if (fs35.existsSync(pidPath)) {
|
|
17030
|
+
fs35.unlinkSync(pidPath);
|
|
16968
17031
|
console.log("[Daemon] PID file cleaned up");
|
|
16969
17032
|
}
|
|
16970
17033
|
} catch (error) {
|