shiva-code 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-4GL27U2Z.js +174 -0
- package/dist/chunk-66D4NGIK.js +560 -0
- package/dist/chunk-G2G6UUWM.js +169 -0
- package/dist/chunk-GHAT2D55.js +175 -0
- package/dist/chunk-KXYP4OCK.js +236 -0
- package/dist/chunk-MDMZWOX7.js +304 -0
- package/dist/github-R3I7U2DQ.js +49 -0
- package/dist/index.js +5249 -89
- package/dist/package-manager-OOJUNEKG.js +26 -0
- package/dist/project-config-GELL5QUH.js +40 -0
- package/dist/session-manager-THTEDIUG.js +45 -0
- package/dist/tags-P6L3BWO7.js +28 -0
- package/package.json +7 -2
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
// src/services/cache.ts
|
|
2
|
+
var CacheService = class _CacheService {
|
|
3
|
+
cache;
|
|
4
|
+
// Default TTLs in milliseconds
|
|
5
|
+
static TTL = {
|
|
6
|
+
SESSIONS: 30 * 1e3,
|
|
7
|
+
// 30 seconds for sessions
|
|
8
|
+
GITHUB_ISSUES: 5 * 60 * 1e3,
|
|
9
|
+
// 5 minutes for GitHub issues
|
|
10
|
+
GITHUB_PRS: 5 * 60 * 1e3,
|
|
11
|
+
// 5 minutes for GitHub PRs
|
|
12
|
+
GITHUB_CONTEXT: 5 * 60 * 1e3,
|
|
13
|
+
// 5 minutes for full context
|
|
14
|
+
TERMINAL: 24 * 60 * 60 * 1e3
|
|
15
|
+
// 24 hours for terminal detection
|
|
16
|
+
};
|
|
17
|
+
constructor() {
|
|
18
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Get a cached value
|
|
22
|
+
*/
|
|
23
|
+
get(key) {
|
|
24
|
+
const entry = this.cache.get(key);
|
|
25
|
+
if (!entry) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
if (Date.now() - entry.timestamp > entry.ttl) {
|
|
29
|
+
this.cache.delete(key);
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
return entry.data;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Set a cached value with TTL
|
|
36
|
+
*/
|
|
37
|
+
set(key, data, ttlMs) {
|
|
38
|
+
this.cache.set(key, {
|
|
39
|
+
data,
|
|
40
|
+
timestamp: Date.now(),
|
|
41
|
+
ttl: ttlMs
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Invalidate a specific key
|
|
46
|
+
*/
|
|
47
|
+
invalidate(key) {
|
|
48
|
+
this.cache.delete(key);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Invalidate all keys matching a pattern
|
|
52
|
+
*/
|
|
53
|
+
invalidatePattern(pattern) {
|
|
54
|
+
const regex = new RegExp(pattern.replace(/\*/g, ".*"));
|
|
55
|
+
for (const key of this.cache.keys()) {
|
|
56
|
+
if (regex.test(key)) {
|
|
57
|
+
this.cache.delete(key);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Clear the entire cache
|
|
63
|
+
*/
|
|
64
|
+
clear() {
|
|
65
|
+
this.cache.clear();
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get cache statistics
|
|
69
|
+
*/
|
|
70
|
+
stats() {
|
|
71
|
+
return {
|
|
72
|
+
size: this.cache.size,
|
|
73
|
+
keys: Array.from(this.cache.keys())
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
// ============================================
|
|
77
|
+
// Session-specific methods
|
|
78
|
+
// ============================================
|
|
79
|
+
/**
|
|
80
|
+
* Get cached Claude projects (sessions)
|
|
81
|
+
*/
|
|
82
|
+
getSessions() {
|
|
83
|
+
return this.get("sessions:all");
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Set cached Claude projects (sessions)
|
|
87
|
+
*/
|
|
88
|
+
setSessions(projects) {
|
|
89
|
+
this.set("sessions:all", projects, _CacheService.TTL.SESSIONS);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Invalidate sessions cache
|
|
93
|
+
*/
|
|
94
|
+
invalidateSessions() {
|
|
95
|
+
this.invalidatePattern("sessions:*");
|
|
96
|
+
}
|
|
97
|
+
// ============================================
|
|
98
|
+
// GitHub-specific methods
|
|
99
|
+
// ============================================
|
|
100
|
+
/**
|
|
101
|
+
* Get cached GitHub issues for a repo
|
|
102
|
+
*/
|
|
103
|
+
getGitHubIssues(repo) {
|
|
104
|
+
return this.get(`github:issues:${repo}`);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Set cached GitHub issues for a repo
|
|
108
|
+
*/
|
|
109
|
+
setGitHubIssues(repo, issues) {
|
|
110
|
+
this.set(`github:issues:${repo}`, issues, _CacheService.TTL.GITHUB_ISSUES);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Get cached GitHub PRs for a repo
|
|
114
|
+
*/
|
|
115
|
+
getGitHubPRs(repo) {
|
|
116
|
+
return this.get(`github:prs:${repo}`);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Set cached GitHub PRs for a repo
|
|
120
|
+
*/
|
|
121
|
+
setGitHubPRs(repo, prs) {
|
|
122
|
+
this.set(`github:prs:${repo}`, prs, _CacheService.TTL.GITHUB_PRS);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Get cached GitHub context for a project
|
|
126
|
+
*/
|
|
127
|
+
getGitHubContext(projectPath) {
|
|
128
|
+
return this.get(`github:context:${projectPath}`);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Set cached GitHub context for a project
|
|
132
|
+
*/
|
|
133
|
+
setGitHubContext(projectPath, context) {
|
|
134
|
+
this.set(`github:context:${projectPath}`, context, _CacheService.TTL.GITHUB_CONTEXT);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Invalidate all GitHub caches
|
|
138
|
+
*/
|
|
139
|
+
invalidateGitHub() {
|
|
140
|
+
this.invalidatePattern("github:*");
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Invalidate GitHub caches for a specific repo
|
|
144
|
+
*/
|
|
145
|
+
invalidateGitHubRepo(repo) {
|
|
146
|
+
this.invalidate(`github:issues:${repo}`);
|
|
147
|
+
this.invalidate(`github:prs:${repo}`);
|
|
148
|
+
}
|
|
149
|
+
// ============================================
|
|
150
|
+
// Terminal detection cache
|
|
151
|
+
// ============================================
|
|
152
|
+
/**
|
|
153
|
+
* Get cached detected terminal
|
|
154
|
+
*/
|
|
155
|
+
getDetectedTerminal() {
|
|
156
|
+
return this.get("terminal:detected");
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Set cached detected terminal
|
|
160
|
+
*/
|
|
161
|
+
setDetectedTerminal(terminal) {
|
|
162
|
+
this.set("terminal:detected", terminal, _CacheService.TTL.TERMINAL);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
var cache = new CacheService();
|
|
166
|
+
|
|
167
|
+
export {
|
|
168
|
+
cache
|
|
169
|
+
};
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import {
|
|
2
|
+
findProject,
|
|
3
|
+
getProjectName
|
|
4
|
+
} from "./chunk-MDMZWOX7.js";
|
|
5
|
+
|
|
6
|
+
// src/services/package-manager.ts
|
|
7
|
+
import Conf from "conf";
|
|
8
|
+
import * as fs from "fs";
|
|
9
|
+
import * as path from "path";
|
|
10
|
+
var packageStore = new Conf({
|
|
11
|
+
projectName: "shiva-code",
|
|
12
|
+
configName: "packages",
|
|
13
|
+
defaults: {
|
|
14
|
+
packages: {}
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
function getAllPackages() {
|
|
18
|
+
const packages = packageStore.get("packages") || {};
|
|
19
|
+
return Object.values(packages).sort(
|
|
20
|
+
(a, b) => new Date(b.modified).getTime() - new Date(a.modified).getTime()
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
function getPackage(name) {
|
|
24
|
+
const packages = packageStore.get("packages") || {};
|
|
25
|
+
return packages[name.toLowerCase()] || null;
|
|
26
|
+
}
|
|
27
|
+
function createPackage(name, description, launchOrder = "parallel") {
|
|
28
|
+
const packages = packageStore.get("packages") || {};
|
|
29
|
+
const key = name.toLowerCase();
|
|
30
|
+
if (packages[key]) {
|
|
31
|
+
throw new Error(`Package "${name}" existiert bereits`);
|
|
32
|
+
}
|
|
33
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
34
|
+
const newPackage = {
|
|
35
|
+
name,
|
|
36
|
+
description,
|
|
37
|
+
projects: [],
|
|
38
|
+
created: now,
|
|
39
|
+
modified: now,
|
|
40
|
+
launchOrder
|
|
41
|
+
};
|
|
42
|
+
packages[key] = newPackage;
|
|
43
|
+
packageStore.set("packages", packages);
|
|
44
|
+
return newPackage;
|
|
45
|
+
}
|
|
46
|
+
function updatePackage(name, updates) {
|
|
47
|
+
const packages = packageStore.get("packages") || {};
|
|
48
|
+
const key = name.toLowerCase();
|
|
49
|
+
const existing = packages[key];
|
|
50
|
+
if (!existing) {
|
|
51
|
+
throw new Error(`Package "${name}" nicht gefunden`);
|
|
52
|
+
}
|
|
53
|
+
if (updates.name && updates.name.toLowerCase() !== key) {
|
|
54
|
+
const newKey = updates.name.toLowerCase();
|
|
55
|
+
if (packages[newKey]) {
|
|
56
|
+
throw new Error(`Package "${updates.name}" existiert bereits`);
|
|
57
|
+
}
|
|
58
|
+
delete packages[key];
|
|
59
|
+
packages[newKey] = {
|
|
60
|
+
...existing,
|
|
61
|
+
...updates,
|
|
62
|
+
modified: (/* @__PURE__ */ new Date()).toISOString()
|
|
63
|
+
};
|
|
64
|
+
packageStore.set("packages", packages);
|
|
65
|
+
return packages[newKey];
|
|
66
|
+
}
|
|
67
|
+
packages[key] = {
|
|
68
|
+
...existing,
|
|
69
|
+
...updates,
|
|
70
|
+
modified: (/* @__PURE__ */ new Date()).toISOString()
|
|
71
|
+
};
|
|
72
|
+
packageStore.set("packages", packages);
|
|
73
|
+
return packages[key];
|
|
74
|
+
}
|
|
75
|
+
function deletePackage(name) {
|
|
76
|
+
const packages = packageStore.get("packages") || {};
|
|
77
|
+
const key = name.toLowerCase();
|
|
78
|
+
if (!packages[key]) {
|
|
79
|
+
throw new Error(`Package "${name}" nicht gefunden`);
|
|
80
|
+
}
|
|
81
|
+
delete packages[key];
|
|
82
|
+
packageStore.set("packages", packages);
|
|
83
|
+
}
|
|
84
|
+
function addProjectToPackage(packageName, projectPath) {
|
|
85
|
+
const packages = packageStore.get("packages") || {};
|
|
86
|
+
const key = packageName.toLowerCase();
|
|
87
|
+
const pkg = packages[key];
|
|
88
|
+
if (!pkg) {
|
|
89
|
+
throw new Error(`Package "${packageName}" nicht gefunden`);
|
|
90
|
+
}
|
|
91
|
+
const absolutePath = path.resolve(projectPath);
|
|
92
|
+
if (!fs.existsSync(absolutePath)) {
|
|
93
|
+
throw new Error(`Pfad existiert nicht: ${absolutePath}`);
|
|
94
|
+
}
|
|
95
|
+
if (pkg.projects.includes(absolutePath)) {
|
|
96
|
+
throw new Error(`Projekt bereits in Package: ${getProjectName(absolutePath)}`);
|
|
97
|
+
}
|
|
98
|
+
pkg.projects.push(absolutePath);
|
|
99
|
+
pkg.modified = (/* @__PURE__ */ new Date()).toISOString();
|
|
100
|
+
packageStore.set("packages", packages);
|
|
101
|
+
return pkg;
|
|
102
|
+
}
|
|
103
|
+
function removeProjectFromPackage(packageName, projectPath) {
|
|
104
|
+
const packages = packageStore.get("packages") || {};
|
|
105
|
+
const key = packageName.toLowerCase();
|
|
106
|
+
const pkg = packages[key];
|
|
107
|
+
if (!pkg) {
|
|
108
|
+
throw new Error(`Package "${packageName}" nicht gefunden`);
|
|
109
|
+
}
|
|
110
|
+
const absolutePath = path.resolve(projectPath);
|
|
111
|
+
const projectName = getProjectName(projectPath);
|
|
112
|
+
const index = pkg.projects.findIndex(
|
|
113
|
+
(p) => p === absolutePath || getProjectName(p).toLowerCase() === projectName.toLowerCase()
|
|
114
|
+
);
|
|
115
|
+
if (index === -1) {
|
|
116
|
+
throw new Error(`Projekt nicht in Package: ${projectPath}`);
|
|
117
|
+
}
|
|
118
|
+
pkg.projects.splice(index, 1);
|
|
119
|
+
pkg.modified = (/* @__PURE__ */ new Date()).toISOString();
|
|
120
|
+
packageStore.set("packages", packages);
|
|
121
|
+
return pkg;
|
|
122
|
+
}
|
|
123
|
+
async function getPackageLaunchConfig(packageName, newSessions = false) {
|
|
124
|
+
const pkg = getPackage(packageName);
|
|
125
|
+
if (!pkg) {
|
|
126
|
+
throw new Error(`Package "${packageName}" nicht gefunden`);
|
|
127
|
+
}
|
|
128
|
+
const launches = [];
|
|
129
|
+
for (const projectPath of pkg.projects) {
|
|
130
|
+
if (!fs.existsSync(projectPath)) {
|
|
131
|
+
console.warn(`Skipping non-existent path: ${projectPath}`);
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
const project = await findProject(projectPath);
|
|
135
|
+
const latestSession = project?.latestSession;
|
|
136
|
+
launches.push({
|
|
137
|
+
projectPath,
|
|
138
|
+
projectName: getProjectName(projectPath),
|
|
139
|
+
sessionId: newSessions ? void 0 : latestSession?.sessionId,
|
|
140
|
+
newSession: newSessions || !latestSession
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
return launches;
|
|
144
|
+
}
|
|
145
|
+
function findPackagesWithProject(projectPath) {
|
|
146
|
+
const absolutePath = path.resolve(projectPath);
|
|
147
|
+
const packages = getAllPackages();
|
|
148
|
+
return packages.filter(
|
|
149
|
+
(pkg) => pkg.projects.some(
|
|
150
|
+
(p) => p === absolutePath || getProjectName(p).toLowerCase() === getProjectName(projectPath).toLowerCase()
|
|
151
|
+
)
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
function getPackageStats() {
|
|
155
|
+
const packages = getAllPackages();
|
|
156
|
+
const totalProjects = packages.reduce((sum, pkg) => sum + pkg.projects.length, 0);
|
|
157
|
+
return {
|
|
158
|
+
totalPackages: packages.length,
|
|
159
|
+
totalProjects,
|
|
160
|
+
averageProjectsPerPackage: packages.length > 0 ? Math.round(totalProjects / packages.length * 10) / 10 : 0
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export {
|
|
165
|
+
getAllPackages,
|
|
166
|
+
getPackage,
|
|
167
|
+
createPackage,
|
|
168
|
+
updatePackage,
|
|
169
|
+
deletePackage,
|
|
170
|
+
addProjectToPackage,
|
|
171
|
+
removeProjectFromPackage,
|
|
172
|
+
getPackageLaunchConfig,
|
|
173
|
+
findPackagesWithProject,
|
|
174
|
+
getPackageStats
|
|
175
|
+
};
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
// src/services/project-config.ts
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
import * as path from "path";
|
|
4
|
+
var SHIVA_DIR = ".shiva";
|
|
5
|
+
var CONFIG_FILE = "config.json";
|
|
6
|
+
var SESSIONS_DIR = "sessions";
|
|
7
|
+
var CONTEXT_DIR = "context";
|
|
8
|
+
var GITHUB_CONTEXT_FILE = "github.md";
|
|
9
|
+
var DEFAULT_CONFIG = {
|
|
10
|
+
version: 1,
|
|
11
|
+
autoInjectContext: true,
|
|
12
|
+
branchSessions: {}
|
|
13
|
+
};
|
|
14
|
+
function getShivaDir(projectPath) {
|
|
15
|
+
return path.join(projectPath, SHIVA_DIR);
|
|
16
|
+
}
|
|
17
|
+
function getConfigPath(projectPath) {
|
|
18
|
+
return path.join(getShivaDir(projectPath), CONFIG_FILE);
|
|
19
|
+
}
|
|
20
|
+
function getSessionsDir(projectPath) {
|
|
21
|
+
return path.join(getShivaDir(projectPath), SESSIONS_DIR);
|
|
22
|
+
}
|
|
23
|
+
function getContextDir(projectPath) {
|
|
24
|
+
return path.join(getShivaDir(projectPath), CONTEXT_DIR);
|
|
25
|
+
}
|
|
26
|
+
function hasShivaDir(projectPath) {
|
|
27
|
+
return fs.existsSync(getShivaDir(projectPath));
|
|
28
|
+
}
|
|
29
|
+
function initShivaDir(projectPath) {
|
|
30
|
+
const shivaDir = getShivaDir(projectPath);
|
|
31
|
+
const sessionsDir = getSessionsDir(projectPath);
|
|
32
|
+
const contextDir = getContextDir(projectPath);
|
|
33
|
+
if (!fs.existsSync(shivaDir)) {
|
|
34
|
+
fs.mkdirSync(shivaDir, { recursive: true });
|
|
35
|
+
}
|
|
36
|
+
if (!fs.existsSync(sessionsDir)) {
|
|
37
|
+
fs.mkdirSync(sessionsDir, { recursive: true });
|
|
38
|
+
}
|
|
39
|
+
if (!fs.existsSync(contextDir)) {
|
|
40
|
+
fs.mkdirSync(contextDir, { recursive: true });
|
|
41
|
+
}
|
|
42
|
+
const configPath = getConfigPath(projectPath);
|
|
43
|
+
if (!fs.existsSync(configPath)) {
|
|
44
|
+
fs.writeFileSync(configPath, JSON.stringify(DEFAULT_CONFIG, null, 2), "utf-8");
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function addToGitignore(projectPath) {
|
|
48
|
+
const gitignorePath = path.join(projectPath, ".gitignore");
|
|
49
|
+
let content = "";
|
|
50
|
+
if (fs.existsSync(gitignorePath)) {
|
|
51
|
+
content = fs.readFileSync(gitignorePath, "utf-8");
|
|
52
|
+
if (content.includes(".shiva") || content.includes("/.shiva")) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const newEntry = "\n# SHIVA Code local config\n.shiva/\n";
|
|
57
|
+
fs.writeFileSync(gitignorePath, content + newEntry, "utf-8");
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
function removeFromGitignore(projectPath) {
|
|
61
|
+
const gitignorePath = path.join(projectPath, ".gitignore");
|
|
62
|
+
if (!fs.existsSync(gitignorePath)) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
let content = fs.readFileSync(gitignorePath, "utf-8");
|
|
66
|
+
const lines = content.split("\n");
|
|
67
|
+
const filtered = lines.filter((line) => {
|
|
68
|
+
const trimmed = line.trim();
|
|
69
|
+
return trimmed !== ".shiva/" && trimmed !== ".shiva" && trimmed !== "/.shiva/";
|
|
70
|
+
});
|
|
71
|
+
const finalLines = filtered.filter((line, i, arr) => {
|
|
72
|
+
return !(line.includes("# SHIVA Code") && arr[i + 1]?.trim() === "");
|
|
73
|
+
});
|
|
74
|
+
const newContent = finalLines.join("\n");
|
|
75
|
+
if (newContent !== content) {
|
|
76
|
+
fs.writeFileSync(gitignorePath, newContent, "utf-8");
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
function getProjectConfig(projectPath) {
|
|
82
|
+
const configPath = getConfigPath(projectPath);
|
|
83
|
+
if (!fs.existsSync(configPath)) {
|
|
84
|
+
return { ...DEFAULT_CONFIG };
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
const content = fs.readFileSync(configPath, "utf-8");
|
|
88
|
+
const config = JSON.parse(content);
|
|
89
|
+
return { ...DEFAULT_CONFIG, ...config };
|
|
90
|
+
} catch {
|
|
91
|
+
return { ...DEFAULT_CONFIG };
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function saveProjectConfig(projectPath, config) {
|
|
95
|
+
initShivaDir(projectPath);
|
|
96
|
+
const configPath = getConfigPath(projectPath);
|
|
97
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
98
|
+
}
|
|
99
|
+
function updateProjectConfig(projectPath, updates) {
|
|
100
|
+
const current = getProjectConfig(projectPath);
|
|
101
|
+
const updated = { ...current, ...updates };
|
|
102
|
+
saveProjectConfig(projectPath, updated);
|
|
103
|
+
return updated;
|
|
104
|
+
}
|
|
105
|
+
function sanitizeBranchName(branch) {
|
|
106
|
+
return branch.replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
107
|
+
}
|
|
108
|
+
function mapBranchToSession(projectPath, branch, sessionId, metadata) {
|
|
109
|
+
initShivaDir(projectPath);
|
|
110
|
+
const config = getProjectConfig(projectPath);
|
|
111
|
+
config.branchSessions[branch] = {
|
|
112
|
+
branch,
|
|
113
|
+
sessionId,
|
|
114
|
+
lastAccessed: (/* @__PURE__ */ new Date()).toISOString(),
|
|
115
|
+
...metadata
|
|
116
|
+
};
|
|
117
|
+
saveProjectConfig(projectPath, config);
|
|
118
|
+
const sessionsDir = getSessionsDir(projectPath);
|
|
119
|
+
const sessionFile = path.join(sessionsDir, `${sanitizeBranchName(branch)}.json`);
|
|
120
|
+
fs.writeFileSync(
|
|
121
|
+
sessionFile,
|
|
122
|
+
JSON.stringify(config.branchSessions[branch], null, 2),
|
|
123
|
+
"utf-8"
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
function getSessionForBranch(projectPath, branch) {
|
|
127
|
+
const config = getProjectConfig(projectPath);
|
|
128
|
+
if (config.branchSessions[branch]) {
|
|
129
|
+
return config.branchSessions[branch];
|
|
130
|
+
}
|
|
131
|
+
const sessionsDir = getSessionsDir(projectPath);
|
|
132
|
+
const sessionFile = path.join(sessionsDir, `${sanitizeBranchName(branch)}.json`);
|
|
133
|
+
if (fs.existsSync(sessionFile)) {
|
|
134
|
+
try {
|
|
135
|
+
const content = fs.readFileSync(sessionFile, "utf-8");
|
|
136
|
+
return JSON.parse(content);
|
|
137
|
+
} catch {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
function getAllBranchSessions(projectPath) {
|
|
144
|
+
const config = getProjectConfig(projectPath);
|
|
145
|
+
return config.branchSessions || {};
|
|
146
|
+
}
|
|
147
|
+
function updateBranchSession(projectPath, branch, updates) {
|
|
148
|
+
const existing = getSessionForBranch(projectPath, branch);
|
|
149
|
+
if (!existing) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
mapBranchToSession(projectPath, branch, existing.sessionId, {
|
|
153
|
+
...existing,
|
|
154
|
+
...updates,
|
|
155
|
+
lastAccessed: (/* @__PURE__ */ new Date()).toISOString()
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
function removeBranchSession(projectPath, branch) {
|
|
159
|
+
const config = getProjectConfig(projectPath);
|
|
160
|
+
if (config.branchSessions[branch]) {
|
|
161
|
+
delete config.branchSessions[branch];
|
|
162
|
+
saveProjectConfig(projectPath, config);
|
|
163
|
+
}
|
|
164
|
+
const sessionsDir = getSessionsDir(projectPath);
|
|
165
|
+
const sessionFile = path.join(sessionsDir, `${sanitizeBranchName(branch)}.json`);
|
|
166
|
+
if (fs.existsSync(sessionFile)) {
|
|
167
|
+
fs.unlinkSync(sessionFile);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function cacheGitHubContext(projectPath, context) {
|
|
171
|
+
initShivaDir(projectPath);
|
|
172
|
+
const contextDir = getContextDir(projectPath);
|
|
173
|
+
const contextFile = path.join(contextDir, GITHUB_CONTEXT_FILE);
|
|
174
|
+
fs.writeFileSync(contextFile, context, "utf-8");
|
|
175
|
+
return contextFile;
|
|
176
|
+
}
|
|
177
|
+
function getCachedGitHubContext(projectPath) {
|
|
178
|
+
const contextDir = getContextDir(projectPath);
|
|
179
|
+
const contextFile = path.join(contextDir, GITHUB_CONTEXT_FILE);
|
|
180
|
+
if (!fs.existsSync(contextFile)) {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
try {
|
|
184
|
+
return fs.readFileSync(contextFile, "utf-8");
|
|
185
|
+
} catch {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
function getContextCacheAge(projectPath) {
|
|
190
|
+
const contextDir = getContextDir(projectPath);
|
|
191
|
+
const contextFile = path.join(contextDir, GITHUB_CONTEXT_FILE);
|
|
192
|
+
if (!fs.existsSync(contextFile)) {
|
|
193
|
+
return Infinity;
|
|
194
|
+
}
|
|
195
|
+
try {
|
|
196
|
+
const stats = fs.statSync(contextFile);
|
|
197
|
+
const ageMs = Date.now() - stats.mtimeMs;
|
|
198
|
+
return Math.floor(ageMs / (1e3 * 60));
|
|
199
|
+
} catch {
|
|
200
|
+
return Infinity;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
function clearContextCache(projectPath) {
|
|
204
|
+
const contextDir = getContextDir(projectPath);
|
|
205
|
+
const contextFile = path.join(contextDir, GITHUB_CONTEXT_FILE);
|
|
206
|
+
if (fs.existsSync(contextFile)) {
|
|
207
|
+
fs.unlinkSync(contextFile);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function removeShivaDir(projectPath) {
|
|
211
|
+
const shivaDir = getShivaDir(projectPath);
|
|
212
|
+
if (fs.existsSync(shivaDir)) {
|
|
213
|
+
fs.rmSync(shivaDir, { recursive: true, force: true });
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export {
|
|
218
|
+
getShivaDir,
|
|
219
|
+
hasShivaDir,
|
|
220
|
+
initShivaDir,
|
|
221
|
+
addToGitignore,
|
|
222
|
+
removeFromGitignore,
|
|
223
|
+
getProjectConfig,
|
|
224
|
+
saveProjectConfig,
|
|
225
|
+
updateProjectConfig,
|
|
226
|
+
mapBranchToSession,
|
|
227
|
+
getSessionForBranch,
|
|
228
|
+
getAllBranchSessions,
|
|
229
|
+
updateBranchSession,
|
|
230
|
+
removeBranchSession,
|
|
231
|
+
cacheGitHubContext,
|
|
232
|
+
getCachedGitHubContext,
|
|
233
|
+
getContextCacheAge,
|
|
234
|
+
clearContextCache,
|
|
235
|
+
removeShivaDir
|
|
236
|
+
};
|