episoda 0.2.67 → 0.2.68
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 +88 -14
- package/dist/daemon/daemon-process.js.map +1 -1
- package/dist/index.js +30 -16
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -2730,7 +2730,7 @@ var require_package = __commonJS({
|
|
|
2730
2730
|
"package.json"(exports2, module2) {
|
|
2731
2731
|
module2.exports = {
|
|
2732
2732
|
name: "episoda",
|
|
2733
|
-
version: "0.2.
|
|
2733
|
+
version: "0.2.68",
|
|
2734
2734
|
description: "CLI tool for Episoda local development workflow orchestration",
|
|
2735
2735
|
main: "dist/index.js",
|
|
2736
2736
|
types: "dist/index.d.ts",
|
|
@@ -8902,6 +8902,23 @@ var Daemon = class _Daemon {
|
|
|
8902
8902
|
console.log(`[Daemon] EP949: Received token refresh for ${projectId}`);
|
|
8903
8903
|
client.updateToken(tokenMsg.accessToken);
|
|
8904
8904
|
});
|
|
8905
|
+
client.on("machine_uuid_update", async (message) => {
|
|
8906
|
+
const uuidMsg = message;
|
|
8907
|
+
if (uuidMsg.machineUuid) {
|
|
8908
|
+
this.machineUuid = uuidMsg.machineUuid;
|
|
8909
|
+
console.log(`[Daemon] EP1095: Machine UUID updated: ${this.machineUuid}`);
|
|
8910
|
+
await this.cacheMachineUuid(uuidMsg.machineUuid);
|
|
8911
|
+
this.syncMachineProjectPath(projectId, projectPath).catch((err) => {
|
|
8912
|
+
console.warn("[Daemon] EP1095: Deferred project path sync failed:", err.message);
|
|
8913
|
+
});
|
|
8914
|
+
const connection2 = this.connections.get(projectPath);
|
|
8915
|
+
if (connection2) {
|
|
8916
|
+
this.reconcileWorktrees(projectId, projectPath, connection2.client).catch((err) => {
|
|
8917
|
+
console.warn("[Daemon] EP1095: Deferred reconciliation failed:", err.message);
|
|
8918
|
+
});
|
|
8919
|
+
}
|
|
8920
|
+
}
|
|
8921
|
+
});
|
|
8905
8922
|
client.on("disconnected", (event) => {
|
|
8906
8923
|
const disconnectEvent = event;
|
|
8907
8924
|
console.log(`[Daemon] Connection closed for ${projectId}: code=${disconnectEvent.code}, willReconnect=${disconnectEvent.willReconnect}`);
|
|
@@ -8984,12 +9001,47 @@ var Daemon = class _Daemon {
|
|
|
8984
9001
|
process.on("SIGTERM", () => shutdownHandler("SIGTERM"));
|
|
8985
9002
|
process.on("SIGINT", () => shutdownHandler("SIGINT"));
|
|
8986
9003
|
}
|
|
9004
|
+
/**
|
|
9005
|
+
* EP1095: Get git directory and working directory for a project path
|
|
9006
|
+
* Handles both traditional (.git directory) and worktree (.bare directory) structures
|
|
9007
|
+
* Returns { gitDir, workDir } where:
|
|
9008
|
+
* - gitDir: The --git-dir value to use with git commands
|
|
9009
|
+
* - workDir: The directory to run git commands in (cwd)
|
|
9010
|
+
*/
|
|
9011
|
+
getGitDirs(projectPath) {
|
|
9012
|
+
const bareDir = path19.join(projectPath, ".bare");
|
|
9013
|
+
const gitPath = path19.join(projectPath, ".git");
|
|
9014
|
+
if (fs18.existsSync(bareDir) && fs18.statSync(bareDir).isDirectory()) {
|
|
9015
|
+
return { gitDir: bareDir, workDir: projectPath };
|
|
9016
|
+
}
|
|
9017
|
+
if (fs18.existsSync(gitPath) && fs18.statSync(gitPath).isDirectory()) {
|
|
9018
|
+
return { gitDir: null, workDir: projectPath };
|
|
9019
|
+
}
|
|
9020
|
+
if (fs18.existsSync(gitPath) && fs18.statSync(gitPath).isFile()) {
|
|
9021
|
+
return { gitDir: null, workDir: projectPath };
|
|
9022
|
+
}
|
|
9023
|
+
const entries = fs18.readdirSync(projectPath, { withFileTypes: true });
|
|
9024
|
+
for (const entry of entries) {
|
|
9025
|
+
if (entry.isDirectory() && entry.name.startsWith("EP")) {
|
|
9026
|
+
const worktreePath = path19.join(projectPath, entry.name);
|
|
9027
|
+
const worktreeGit = path19.join(worktreePath, ".git");
|
|
9028
|
+
if (fs18.existsSync(worktreeGit)) {
|
|
9029
|
+
return { gitDir: null, workDir: worktreePath };
|
|
9030
|
+
}
|
|
9031
|
+
}
|
|
9032
|
+
}
|
|
9033
|
+
if (fs18.existsSync(bareDir)) {
|
|
9034
|
+
return { gitDir: bareDir, workDir: projectPath };
|
|
9035
|
+
}
|
|
9036
|
+
return { gitDir: null, workDir: projectPath };
|
|
9037
|
+
}
|
|
8987
9038
|
/**
|
|
8988
9039
|
* EP595: Configure git with user and workspace ID for post-checkout hook
|
|
8989
9040
|
* EP655: Added machineId for device isolation in multi-device environments
|
|
8990
9041
|
* EP725: Added projectId for main branch badge tracking
|
|
8991
9042
|
* EP726: Added machineUuid (UUID) for unified device identification
|
|
8992
9043
|
* EP1091: Renamed deviceId param to machineUuid for consistency
|
|
9044
|
+
* EP1095: Added worktree structure support (uses .bare as gitDir)
|
|
8993
9045
|
*
|
|
8994
9046
|
* This stores the IDs in .git/config so the post-checkout hook can
|
|
8995
9047
|
* update module.checkout_* fields when git operations happen from terminal.
|
|
@@ -8997,29 +9049,31 @@ var Daemon = class _Daemon {
|
|
|
8997
9049
|
async configureGitUser(projectPath, userId, workspaceId, machineId, projectId, machineUuid) {
|
|
8998
9050
|
try {
|
|
8999
9051
|
const { execSync: execSync9 } = await import("child_process");
|
|
9000
|
-
|
|
9001
|
-
|
|
9052
|
+
const { gitDir, workDir } = this.getGitDirs(projectPath);
|
|
9053
|
+
const gitCmd = gitDir ? `git --git-dir="${gitDir}"` : "git";
|
|
9054
|
+
execSync9(`${gitCmd} config episoda.userId ${userId}`, {
|
|
9055
|
+
cwd: workDir,
|
|
9002
9056
|
encoding: "utf8",
|
|
9003
9057
|
stdio: "pipe"
|
|
9004
9058
|
});
|
|
9005
|
-
execSync9(
|
|
9006
|
-
cwd:
|
|
9059
|
+
execSync9(`${gitCmd} config episoda.workspaceId ${workspaceId}`, {
|
|
9060
|
+
cwd: workDir,
|
|
9007
9061
|
encoding: "utf8",
|
|
9008
9062
|
stdio: "pipe"
|
|
9009
9063
|
});
|
|
9010
|
-
execSync9(
|
|
9011
|
-
cwd:
|
|
9064
|
+
execSync9(`${gitCmd} config episoda.machineId ${machineId}`, {
|
|
9065
|
+
cwd: workDir,
|
|
9012
9066
|
encoding: "utf8",
|
|
9013
9067
|
stdio: "pipe"
|
|
9014
9068
|
});
|
|
9015
|
-
execSync9(
|
|
9016
|
-
cwd:
|
|
9069
|
+
execSync9(`${gitCmd} config episoda.projectId ${projectId}`, {
|
|
9070
|
+
cwd: workDir,
|
|
9017
9071
|
encoding: "utf8",
|
|
9018
9072
|
stdio: "pipe"
|
|
9019
9073
|
});
|
|
9020
9074
|
if (machineUuid) {
|
|
9021
|
-
execSync9(
|
|
9022
|
-
cwd:
|
|
9075
|
+
execSync9(`${gitCmd} config episoda.deviceId ${machineUuid}`, {
|
|
9076
|
+
cwd: workDir,
|
|
9023
9077
|
encoding: "utf8",
|
|
9024
9078
|
stdio: "pipe"
|
|
9025
9079
|
});
|
|
@@ -9031,6 +9085,7 @@ var Daemon = class _Daemon {
|
|
|
9031
9085
|
}
|
|
9032
9086
|
/**
|
|
9033
9087
|
* EP610: Install git hooks from bundled files
|
|
9088
|
+
* EP1095: Added worktree structure support (hooks in .bare/hooks)
|
|
9034
9089
|
*
|
|
9035
9090
|
* Installs post-checkout and pre-commit hooks to enable:
|
|
9036
9091
|
* - Branch tracking (post-checkout updates module.checkout_* fields)
|
|
@@ -9038,10 +9093,29 @@ var Daemon = class _Daemon {
|
|
|
9038
9093
|
*/
|
|
9039
9094
|
async installGitHooks(projectPath) {
|
|
9040
9095
|
const hooks = ["post-checkout", "pre-commit", "post-commit"];
|
|
9041
|
-
|
|
9096
|
+
let hooksDir;
|
|
9097
|
+
const bareHooksDir = path19.join(projectPath, ".bare", "hooks");
|
|
9098
|
+
const gitHooksDir = path19.join(projectPath, ".git", "hooks");
|
|
9099
|
+
if (fs18.existsSync(bareHooksDir)) {
|
|
9100
|
+
hooksDir = bareHooksDir;
|
|
9101
|
+
} else if (fs18.existsSync(gitHooksDir) && fs18.statSync(path19.join(projectPath, ".git")).isDirectory()) {
|
|
9102
|
+
hooksDir = gitHooksDir;
|
|
9103
|
+
} else {
|
|
9104
|
+
const parentBareHooks = path19.join(projectPath, "..", ".bare", "hooks");
|
|
9105
|
+
if (fs18.existsSync(parentBareHooks)) {
|
|
9106
|
+
hooksDir = parentBareHooks;
|
|
9107
|
+
} else {
|
|
9108
|
+
console.warn(`[Daemon] Hooks directory not found for: ${projectPath}`);
|
|
9109
|
+
return;
|
|
9110
|
+
}
|
|
9111
|
+
}
|
|
9042
9112
|
if (!fs18.existsSync(hooksDir)) {
|
|
9043
|
-
|
|
9044
|
-
|
|
9113
|
+
try {
|
|
9114
|
+
fs18.mkdirSync(hooksDir, { recursive: true });
|
|
9115
|
+
} catch (error) {
|
|
9116
|
+
console.warn(`[Daemon] Hooks directory not found and could not create: ${hooksDir}`);
|
|
9117
|
+
return;
|
|
9118
|
+
}
|
|
9045
9119
|
}
|
|
9046
9120
|
for (const hookName of hooks) {
|
|
9047
9121
|
try {
|