autohand-cli 0.6.12 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -48
- package/dist/AutomodeManager-FQQPBHAD.js +1422 -0
- package/dist/AutomodeManager-PUNJS7IZ.cjs +1422 -0
- package/dist/{CommunitySkillsCache-XPDVYU3K.js → CommunitySkillsCache-AY3ZYDTN.js} +1 -0
- package/dist/{CommunitySkillsCache-X3X237QQ.cjs → CommunitySkillsCache-KO4DSKMA.cjs} +1 -0
- package/dist/{GitHubRegistryFetcher-K744NNAJ.cjs → GitHubRegistryFetcher-S4JREWUQ.cjs} +1 -0
- package/dist/{GitHubRegistryFetcher-US2JJID4.js → GitHubRegistryFetcher-V23KTTLM.js} +1 -0
- package/dist/HookManager-OGINWAJN.cjs +7 -0
- package/dist/HookManager-VG46FXSZ.js +7 -0
- package/dist/MemoryManager-AFS5EZJ2.js +8 -0
- package/dist/MemoryManager-KE6EKW7Y.cjs +8 -0
- package/dist/{PermissionManager-PMTQN263.cjs → PermissionManager-MAPKIJMD.cjs} +1 -0
- package/dist/{PermissionManager-YFZI4ZZ6.js → PermissionManager-V2Q2OAS2.js} +1 -0
- package/dist/SessionManager-MKLGLZWC.cjs +10 -0
- package/dist/SessionManager-V25OJDDY.js +10 -0
- package/dist/{SkillsRegistry-OINIPILA.cjs → SkillsRegistry-4RU2OAEQ.cjs} +1 -0
- package/dist/{SkillsRegistry-7NICF6FY.js → SkillsRegistry-FTLVJZMA.js} +1 -0
- package/dist/{agents-GRAFXZY3.cjs → agents-CHNQ7LQ4.cjs} +1 -0
- package/dist/{agents-B33IAATH.js → agents-E4NEH2PN.js} +1 -0
- package/dist/{agents-new-67NJJSDA.cjs → agents-new-GHVWXW7T.cjs} +1 -0
- package/dist/{agents-new-KTXJFC5E.js → agents-new-W6HMQ7V5.js} +1 -0
- package/dist/automode-BJYGRMEQ.cjs +9 -0
- package/dist/automode-XCNP6HP4.js +9 -0
- package/dist/chunk-2FLBGPE3.js +199 -0
- package/dist/{chunk-5RX6NVQO.cjs → chunk-3L76MLO5.cjs} +20 -2
- package/dist/chunk-3RG5ZIWI.js +10 -0
- package/dist/chunk-4L5WYXHN.js +246 -0
- package/dist/{chunk-SFT6BEYU.js → chunk-BAFJQUWR.js} +20 -2
- package/dist/chunk-CXZEPTRI.js +172 -0
- package/dist/{chunk-CT2VTDPQ.cjs → chunk-E6U4UE3B.cjs} +1 -1
- package/dist/{chunk-TG34DNLU.cjs → chunk-EBM5QDJ4.cjs} +2 -2
- package/dist/{chunk-MFLRXVKU.js → chunk-HUE3GT5M.js} +1 -1
- package/dist/{chunk-A2TFZJD4.js → chunk-LCCJ26QR.js} +2 -2
- package/dist/chunk-OBGZSXTJ.cjs +10 -0
- package/dist/chunk-OTS4YFSZ.cjs +172 -0
- package/dist/chunk-SXYYH3VD.cjs +497 -0
- package/dist/chunk-UOLJZFPJ.js +497 -0
- package/dist/chunk-UPR5PKX4.cjs +199 -0
- package/dist/chunk-URY4AS4L.cjs +246 -0
- package/dist/{completion-Y42FKDT3.js → completion-2XTEWNMC.js} +1 -0
- package/dist/{completion-WVFWX7XQ.cjs → completion-BTDPVWVB.cjs} +1 -0
- package/dist/{constants-QYBEF3DB.js → constants-RVCOJL3L.js} +1 -0
- package/dist/{constants-PE5DLI7Q.cjs → constants-V4V43DZQ.cjs} +1 -0
- package/dist/{defaultHooks-3G3DVF6I.js → defaultHooks-3GRSZNKA.js} +2 -0
- package/dist/{defaultHooks-Z4KA6U5C.cjs → defaultHooks-7EAUU6MN.cjs} +3 -1
- package/dist/{export-BKBJ7PB2.cjs → export-CB34FSEH.cjs} +1 -0
- package/dist/{export-WJ5P6E5Z.js → export-LNPP3XXH.js} +1 -0
- package/dist/{feedback-PZ2PINDU.js → feedback-IZKDNGHP.js} +1 -0
- package/dist/{feedback-R66B3B3C.cjs → feedback-OKGBXZZ4.cjs} +1 -0
- package/dist/{formatters-UG6VZJJ5.js → formatters-JJK6RS55.js} +1 -0
- package/dist/{formatters-N5IJKYZY.cjs → formatters-OIGPANHJ.cjs} +1 -0
- package/dist/{help-PKC6QCNG.js → help-MU553D6W.js} +1 -0
- package/dist/{help-UEELQRHP.cjs → help-QAAUDLFS.cjs} +1 -0
- package/dist/{hooks-5NY5K4L3.js → hooks-4N5VRVOF.js} +2 -1
- package/dist/hooks-7DZGBMXP.cjs +10 -0
- package/dist/index.cjs +933 -1395
- package/dist/index.js +863 -1325
- package/dist/{init-SLLSDDJN.cjs → init-2QEB7GL5.cjs} +1 -0
- package/dist/{init-DML7AOII.js → init-WW4RITLV.js} +1 -0
- package/dist/{lint-TA2ZHVLM.js → lint-L2TD6NY6.js} +1 -0
- package/dist/{lint-44UQJ673.cjs → lint-ZLRBEAFF.cjs} +1 -0
- package/dist/{localProjectPermissions-75X3ZGKH.cjs → localProjectPermissions-2DP6X55S.cjs} +1 -0
- package/dist/{localProjectPermissions-DURCNDZG.js → localProjectPermissions-5CXHD4DO.js} +1 -0
- package/dist/{login-BZ7J4Z4M.js → login-LH62FYMH.js} +1 -0
- package/dist/{login-HUH3CEWL.cjs → login-TWWYJKX6.cjs} +1 -0
- package/dist/{logout-3V3SH7OL.cjs → logout-35XNU6Q2.cjs} +1 -0
- package/dist/{logout-BZKEMNHB.js → logout-KPHUXO23.js} +1 -0
- package/dist/{memory-4GSP7NKV.js → memory-2SGSO4MW.js} +1 -0
- package/dist/{memory-CFNC7RJH.cjs → memory-ALXCFFQY.cjs} +1 -0
- package/dist/{model-TKVEJ5BC.cjs → model-JC43B3KM.cjs} +1 -0
- package/dist/{model-HKEFSH5E.js → model-U3BWIWVH.js} +1 -0
- package/dist/{new-EB2MBQXA.cjs → new-24YT5KVI.cjs} +1 -0
- package/dist/{new-EEZC4XXV.js → new-PCOF6OLV.js} +1 -0
- package/dist/{patch-J32X2QQP.cjs → patch-ETANEGRW.cjs} +3 -1
- package/dist/{patch-BAAQIYSW.js → patch-RPK3BZQR.js} +2 -0
- package/dist/{permissions-5MTH22EF.js → permissions-5W5JOVM7.js} +1 -0
- package/dist/{permissions-IP5SITPI.cjs → permissions-NHPJPHDV.cjs} +1 -0
- package/dist/{quit-RSYIERO5.js → quit-NIDVPHNL.js} +1 -0
- package/dist/{quit-2RYFGIJP.cjs → quit-TMKMX2YF.cjs} +1 -0
- package/dist/{resume-OYZMJRNO.cjs → resume-5C44HAAH.cjs} +1 -0
- package/dist/{resume-2NERFSTD.js → resume-ZZ2D2NMB.js} +1 -0
- package/dist/{session-T3TAZ5ZU.cjs → session-6TMBGN7N.cjs} +1 -0
- package/dist/{session-H5QWKE5E.js → session-76F55XKA.js} +1 -0
- package/dist/{sessions-4KXIT76T.js → sessions-ERKBJ7MC.js} +1 -0
- package/dist/{sessions-7RTCPVNE.cjs → sessions-NUPCJVCF.cjs} +1 -0
- package/dist/{skills-CRFOVWEQ.js → skills-R25OBHE5.js} +2 -1
- package/dist/skills-UCWKIHHG.cjs +13 -0
- package/dist/{skills-install-RMPXN6RK.js → skills-install-GNTBBL46.js} +1 -0
- package/dist/{skills-install-Z27KPEGF.cjs → skills-install-VUSVGSON.cjs} +1 -0
- package/dist/{skills-new-3QJUST7P.cjs → skills-new-AGXQNBRA.cjs} +1 -0
- package/dist/{skills-new-S2YPO635.js → skills-new-L36LQXIE.js} +1 -0
- package/dist/status-2QV7C3JJ.cjs +9 -0
- package/dist/{status-KC56ITDB.js → status-VJ6FOSRI.js} +2 -1
- package/dist/{theme-LIF3RD3A.cjs → theme-MI3BM56M.cjs} +1 -0
- package/dist/{theme-JAMJSCKR.js → theme-ZXGSJBZI.js} +1 -0
- package/dist/{undo-7QJBXARS.js → undo-3UU5LWQS.js} +1 -0
- package/dist/{undo-2WR2ZIEC.cjs → undo-W4VN2Y37.cjs} +1 -0
- package/package.json +2 -2
- package/dist/hooks-PIYYJZMI.cjs +0 -9
- package/dist/skills-6PIGHOWS.cjs +0 -12
- package/dist/status-VDVKZCQR.cjs +0 -8
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
|
+
|
|
3
|
+
var _chunkURY4AS4Lcjs = require('./chunk-URY4AS4L.cjs');
|
|
4
|
+
require('./chunk-XTHHDIBG.cjs');
|
|
5
|
+
require('./chunk-OBGZSXTJ.cjs');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
exports.MemoryManager = _chunkURY4AS4Lcjs.MemoryManager;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
var _chunkUPR5PKX4cjs = require('./chunk-UPR5PKX4.cjs');
|
|
5
|
+
require('./chunk-XTHHDIBG.cjs');
|
|
6
|
+
require('./chunk-OBGZSXTJ.cjs');
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
exports.Session = _chunkUPR5PKX4cjs.Session; exports.SessionManager = _chunkUPR5PKX4cjs.SessionManager;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
var _chunkOTS4YFSZcjs = require('./chunk-OTS4YFSZ.cjs');
|
|
5
|
+
require('./chunk-OBGZSXTJ.cjs');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
exports.automode = _chunkOTS4YFSZcjs.automode; exports.metadata = _chunkOTS4YFSZcjs.metadata;
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AUTOHAND_PATHS
|
|
3
|
+
} from "./chunk-FUEL6BK7.js";
|
|
4
|
+
|
|
5
|
+
// src/session/SessionManager.ts
|
|
6
|
+
import fs from "fs-extra";
|
|
7
|
+
import path from "path";
|
|
8
|
+
import crypto from "crypto";
|
|
9
|
+
var SessionManager = class {
|
|
10
|
+
constructor(baseDir) {
|
|
11
|
+
this.currentSession = null;
|
|
12
|
+
this.index = null;
|
|
13
|
+
this.sessionsDir = baseDir ?? AUTOHAND_PATHS.sessions;
|
|
14
|
+
}
|
|
15
|
+
async initialize() {
|
|
16
|
+
await fs.ensureDir(this.sessionsDir);
|
|
17
|
+
await this.loadIndex();
|
|
18
|
+
}
|
|
19
|
+
async createSession(projectPath, model) {
|
|
20
|
+
const sessionId = this.generateSessionId();
|
|
21
|
+
const sessionDir = path.join(this.sessionsDir, sessionId);
|
|
22
|
+
await fs.ensureDir(sessionDir);
|
|
23
|
+
const metadata = {
|
|
24
|
+
sessionId,
|
|
25
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
26
|
+
lastActiveAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
27
|
+
projectPath: path.resolve(projectPath),
|
|
28
|
+
projectName: path.basename(projectPath),
|
|
29
|
+
model,
|
|
30
|
+
messageCount: 0,
|
|
31
|
+
status: "active"
|
|
32
|
+
};
|
|
33
|
+
const session = new Session(sessionDir, metadata);
|
|
34
|
+
await session.save();
|
|
35
|
+
this.currentSession = session;
|
|
36
|
+
await this.addToIndex(session.metadata);
|
|
37
|
+
return session;
|
|
38
|
+
}
|
|
39
|
+
async loadSession(sessionId) {
|
|
40
|
+
const sessionDir = path.join(this.sessionsDir, sessionId);
|
|
41
|
+
if (!await fs.pathExists(sessionDir)) {
|
|
42
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
43
|
+
}
|
|
44
|
+
const metadataPath = path.join(sessionDir, "metadata.json");
|
|
45
|
+
const metadata = await fs.readJson(metadataPath);
|
|
46
|
+
const session = new Session(sessionDir, metadata);
|
|
47
|
+
await session.load();
|
|
48
|
+
this.currentSession = session;
|
|
49
|
+
return session;
|
|
50
|
+
}
|
|
51
|
+
async listSessions(filter) {
|
|
52
|
+
await this.loadIndex();
|
|
53
|
+
if (!this.index) return [];
|
|
54
|
+
let sessions = this.index.sessions;
|
|
55
|
+
if (filter?.project) {
|
|
56
|
+
const projectPath = path.resolve(filter.project);
|
|
57
|
+
const sessionIds = this.index.byProject[projectPath] || [];
|
|
58
|
+
sessions = sessions.filter((s) => sessionIds.includes(s.id));
|
|
59
|
+
}
|
|
60
|
+
if (filter?.since) {
|
|
61
|
+
sessions = sessions.filter((s) => new Date(s.createdAt) >= filter.since);
|
|
62
|
+
}
|
|
63
|
+
const fullMetadata = [];
|
|
64
|
+
for (const s of sessions) {
|
|
65
|
+
const sessionDir = path.join(this.sessionsDir, s.id);
|
|
66
|
+
const metadataPath = path.join(sessionDir, "metadata.json");
|
|
67
|
+
if (await fs.pathExists(metadataPath)) {
|
|
68
|
+
const metadata = await fs.readJson(metadataPath);
|
|
69
|
+
fullMetadata.push(metadata);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return fullMetadata.sort(
|
|
73
|
+
(a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
async getLastSession(projectPath) {
|
|
77
|
+
const sessions = await this.listSessions(projectPath ? { project: projectPath } : void 0);
|
|
78
|
+
return sessions[0] || null;
|
|
79
|
+
}
|
|
80
|
+
async closeSession(summary) {
|
|
81
|
+
if (!this.currentSession) return;
|
|
82
|
+
this.currentSession.metadata.closedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
83
|
+
this.currentSession.metadata.lastActiveAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
84
|
+
this.currentSession.metadata.status = "completed";
|
|
85
|
+
if (summary) {
|
|
86
|
+
this.currentSession.metadata.summary = summary;
|
|
87
|
+
}
|
|
88
|
+
await this.currentSession.save();
|
|
89
|
+
await this.updateIndex(this.currentSession.metadata);
|
|
90
|
+
this.currentSession = null;
|
|
91
|
+
}
|
|
92
|
+
getCurrentSession() {
|
|
93
|
+
return this.currentSession;
|
|
94
|
+
}
|
|
95
|
+
generateSessionId() {
|
|
96
|
+
const timestamp = Date.now();
|
|
97
|
+
const uuid = crypto.randomUUID();
|
|
98
|
+
return `${uuid}-${timestamp}`;
|
|
99
|
+
}
|
|
100
|
+
async loadIndex() {
|
|
101
|
+
const indexPath = path.join(this.sessionsDir, "index.json");
|
|
102
|
+
if (await fs.pathExists(indexPath)) {
|
|
103
|
+
this.index = await fs.readJson(indexPath);
|
|
104
|
+
} else {
|
|
105
|
+
this.index = { sessions: [], byProject: {} };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
async saveIndex() {
|
|
109
|
+
const indexPath = path.join(this.sessionsDir, "index.json");
|
|
110
|
+
await fs.writeJson(indexPath, this.index, { spaces: 2 });
|
|
111
|
+
}
|
|
112
|
+
async addToIndex(metadata) {
|
|
113
|
+
if (!this.index) await this.loadIndex();
|
|
114
|
+
if (!this.index) return;
|
|
115
|
+
this.index.sessions.push({
|
|
116
|
+
id: metadata.sessionId,
|
|
117
|
+
projectPath: metadata.projectPath,
|
|
118
|
+
createdAt: metadata.createdAt,
|
|
119
|
+
summary: metadata.summary
|
|
120
|
+
});
|
|
121
|
+
if (!this.index.byProject[metadata.projectPath]) {
|
|
122
|
+
this.index.byProject[metadata.projectPath] = [];
|
|
123
|
+
}
|
|
124
|
+
this.index.byProject[metadata.projectPath].push(metadata.sessionId);
|
|
125
|
+
await this.saveIndex();
|
|
126
|
+
}
|
|
127
|
+
async updateIndex(metadata) {
|
|
128
|
+
if (!this.index) return;
|
|
129
|
+
const session = this.index.sessions.find((s) => s.id === metadata.sessionId);
|
|
130
|
+
if (session) {
|
|
131
|
+
session.summary = metadata.summary;
|
|
132
|
+
}
|
|
133
|
+
await this.saveIndex();
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
var Session = class {
|
|
137
|
+
constructor(sessionDir, metadata) {
|
|
138
|
+
this.messages = [];
|
|
139
|
+
this.state = null;
|
|
140
|
+
this.sessionDir = sessionDir;
|
|
141
|
+
this.metadata = metadata;
|
|
142
|
+
}
|
|
143
|
+
async append(message) {
|
|
144
|
+
this.messages.push(message);
|
|
145
|
+
this.metadata.messageCount = this.messages.length;
|
|
146
|
+
this.metadata.lastActiveAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
147
|
+
const conversationPath = path.join(this.sessionDir, "conversation.jsonl");
|
|
148
|
+
await fs.appendFile(conversationPath, JSON.stringify(message) + "\n");
|
|
149
|
+
await this.save();
|
|
150
|
+
}
|
|
151
|
+
async appendTransient(message) {
|
|
152
|
+
const conversationPath = path.join(this.sessionDir, "conversation.jsonl");
|
|
153
|
+
await fs.appendFile(conversationPath, JSON.stringify(message) + "\n");
|
|
154
|
+
}
|
|
155
|
+
async updateState(state) {
|
|
156
|
+
this.state = state;
|
|
157
|
+
const statePath = path.join(this.sessionDir, "state.json");
|
|
158
|
+
await fs.writeJson(statePath, state, { spaces: 2 });
|
|
159
|
+
}
|
|
160
|
+
async save() {
|
|
161
|
+
const metadataPath = path.join(this.sessionDir, "metadata.json");
|
|
162
|
+
await fs.writeJson(metadataPath, this.metadata, { spaces: 2 });
|
|
163
|
+
}
|
|
164
|
+
async load() {
|
|
165
|
+
const conversationPath = path.join(this.sessionDir, "conversation.jsonl");
|
|
166
|
+
if (await fs.pathExists(conversationPath)) {
|
|
167
|
+
const content = await fs.readFile(conversationPath, "utf-8");
|
|
168
|
+
this.messages = content.trim().split("\n").filter((line) => line).map((line) => JSON.parse(line));
|
|
169
|
+
}
|
|
170
|
+
const statePath = path.join(this.sessionDir, "state.json");
|
|
171
|
+
if (await fs.pathExists(statePath)) {
|
|
172
|
+
this.state = await fs.readJson(statePath);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
getMessages() {
|
|
176
|
+
return this.messages;
|
|
177
|
+
}
|
|
178
|
+
getState() {
|
|
179
|
+
return this.state;
|
|
180
|
+
}
|
|
181
|
+
async close(summary) {
|
|
182
|
+
this.metadata.closedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
183
|
+
this.metadata.status = "completed";
|
|
184
|
+
if (summary) {
|
|
185
|
+
this.metadata.summary = summary;
|
|
186
|
+
}
|
|
187
|
+
await this.save();
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
export {
|
|
192
|
+
SessionManager,
|
|
193
|
+
Session
|
|
194
|
+
};
|
|
195
|
+
/**
|
|
196
|
+
* @license
|
|
197
|
+
* Copyright 2025 Autohand AI LLC
|
|
198
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
199
|
+
*/
|
|
@@ -15,7 +15,16 @@ var HOOK_EVENTS = [
|
|
|
15
15
|
"subagent-stop",
|
|
16
16
|
"permission-request",
|
|
17
17
|
"notification",
|
|
18
|
-
"session-error"
|
|
18
|
+
"session-error",
|
|
19
|
+
// Auto-mode events
|
|
20
|
+
"automode:start",
|
|
21
|
+
"automode:iteration",
|
|
22
|
+
"automode:checkpoint",
|
|
23
|
+
"automode:pause",
|
|
24
|
+
"automode:resume",
|
|
25
|
+
"automode:cancel",
|
|
26
|
+
"automode:complete",
|
|
27
|
+
"automode:error"
|
|
19
28
|
];
|
|
20
29
|
var EVENT_DESCRIPTIONS = {
|
|
21
30
|
"session-start": "When a session begins",
|
|
@@ -29,7 +38,16 @@ var EVENT_DESCRIPTIONS = {
|
|
|
29
38
|
"subagent-stop": "When a subagent finishes",
|
|
30
39
|
"permission-request": "When permission is requested",
|
|
31
40
|
"notification": "When notifications are shown",
|
|
32
|
-
"session-error": "When an error occurs"
|
|
41
|
+
"session-error": "When an error occurs",
|
|
42
|
+
// Auto-mode events
|
|
43
|
+
"automode:start": "When auto-mode loop starts",
|
|
44
|
+
"automode:iteration": "Each auto-mode iteration",
|
|
45
|
+
"automode:checkpoint": "When auto-mode creates a checkpoint",
|
|
46
|
+
"automode:pause": "When auto-mode is paused",
|
|
47
|
+
"automode:resume": "When auto-mode is resumed",
|
|
48
|
+
"automode:cancel": "When auto-mode is cancelled",
|
|
49
|
+
"automode:complete": "When auto-mode completes",
|
|
50
|
+
"automode:error": "When auto-mode encounters an error"
|
|
33
51
|
};
|
|
34
52
|
var HOOK_ICONS = {
|
|
35
53
|
// Script-based hooks
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
__require
|
|
10
|
+
};
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AUTOHAND_PATHS,
|
|
3
|
+
PROJECT_DIR_NAME
|
|
4
|
+
} from "./chunk-FUEL6BK7.js";
|
|
5
|
+
|
|
6
|
+
// src/memory/MemoryManager.ts
|
|
7
|
+
import fs from "fs-extra";
|
|
8
|
+
import path from "path";
|
|
9
|
+
import crypto from "crypto";
|
|
10
|
+
var SIMILARITY_THRESHOLD = 0.6;
|
|
11
|
+
var MemoryManager = class {
|
|
12
|
+
constructor(workspaceRoot) {
|
|
13
|
+
this.projectMemoryDir = null;
|
|
14
|
+
this.userMemoryDir = AUTOHAND_PATHS.memory;
|
|
15
|
+
if (workspaceRoot) {
|
|
16
|
+
this.projectMemoryDir = path.join(workspaceRoot, PROJECT_DIR_NAME, "memory");
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
setWorkspace(workspaceRoot) {
|
|
20
|
+
this.projectMemoryDir = path.join(workspaceRoot, PROJECT_DIR_NAME, "memory");
|
|
21
|
+
}
|
|
22
|
+
async initialize() {
|
|
23
|
+
await fs.ensureDir(this.userMemoryDir);
|
|
24
|
+
if (this.projectMemoryDir) {
|
|
25
|
+
await fs.ensureDir(this.projectMemoryDir);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
getMemoryDir(level) {
|
|
29
|
+
if (level === "project") {
|
|
30
|
+
if (!this.projectMemoryDir) {
|
|
31
|
+
throw new Error("Project memory directory not set. Use setWorkspace() first.");
|
|
32
|
+
}
|
|
33
|
+
return this.projectMemoryDir;
|
|
34
|
+
}
|
|
35
|
+
return this.userMemoryDir;
|
|
36
|
+
}
|
|
37
|
+
async store(content, level, tags, source) {
|
|
38
|
+
const dir = this.getMemoryDir(level);
|
|
39
|
+
await fs.ensureDir(dir);
|
|
40
|
+
const similar = await this.findSimilar(content, level);
|
|
41
|
+
if (similar && similar.score >= SIMILARITY_THRESHOLD) {
|
|
42
|
+
return this.updateMemory(similar.entry.id, content, level, tags);
|
|
43
|
+
}
|
|
44
|
+
const id = this.generateId();
|
|
45
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
46
|
+
const entry = {
|
|
47
|
+
id,
|
|
48
|
+
content,
|
|
49
|
+
createdAt: now,
|
|
50
|
+
updatedAt: now,
|
|
51
|
+
tags,
|
|
52
|
+
source
|
|
53
|
+
};
|
|
54
|
+
const entryPath = path.join(dir, `${id}.json`);
|
|
55
|
+
await fs.writeJson(entryPath, entry, { spaces: 2 });
|
|
56
|
+
await this.updateIndex(level, entry);
|
|
57
|
+
return entry;
|
|
58
|
+
}
|
|
59
|
+
async updateMemory(id, content, level, tags) {
|
|
60
|
+
const dir = this.getMemoryDir(level);
|
|
61
|
+
const entryPath = path.join(dir, `${id}.json`);
|
|
62
|
+
if (!await fs.pathExists(entryPath)) {
|
|
63
|
+
throw new Error(`Memory entry not found: ${id}`);
|
|
64
|
+
}
|
|
65
|
+
const existing = await fs.readJson(entryPath);
|
|
66
|
+
const updated = {
|
|
67
|
+
...existing,
|
|
68
|
+
content,
|
|
69
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
70
|
+
tags: tags ?? existing.tags
|
|
71
|
+
};
|
|
72
|
+
await fs.writeJson(entryPath, updated, { spaces: 2 });
|
|
73
|
+
await this.updateIndex(level, updated);
|
|
74
|
+
return updated;
|
|
75
|
+
}
|
|
76
|
+
async get(id, level) {
|
|
77
|
+
const dir = this.getMemoryDir(level);
|
|
78
|
+
const entryPath = path.join(dir, `${id}.json`);
|
|
79
|
+
if (!await fs.pathExists(entryPath)) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
return fs.readJson(entryPath);
|
|
83
|
+
}
|
|
84
|
+
async list(level) {
|
|
85
|
+
const dir = this.getMemoryDir(level);
|
|
86
|
+
if (!await fs.pathExists(dir)) {
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
const files = await fs.readdir(dir);
|
|
90
|
+
const entries = [];
|
|
91
|
+
for (const file of files) {
|
|
92
|
+
if (file.endsWith(".json") && file !== "index.json") {
|
|
93
|
+
const entryPath = path.join(dir, file);
|
|
94
|
+
const entry = await fs.readJson(entryPath);
|
|
95
|
+
entries.push(entry);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return entries.sort(
|
|
99
|
+
(a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
async listAll() {
|
|
103
|
+
const user = await this.list("user");
|
|
104
|
+
let project = [];
|
|
105
|
+
if (this.projectMemoryDir) {
|
|
106
|
+
try {
|
|
107
|
+
project = await this.list("project");
|
|
108
|
+
} catch {
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return { project, user };
|
|
112
|
+
}
|
|
113
|
+
async delete(id, level) {
|
|
114
|
+
const dir = this.getMemoryDir(level);
|
|
115
|
+
const entryPath = path.join(dir, `${id}.json`);
|
|
116
|
+
if (await fs.pathExists(entryPath)) {
|
|
117
|
+
await fs.remove(entryPath);
|
|
118
|
+
await this.removeFromIndex(level, id);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
async findSimilar(content, level) {
|
|
122
|
+
const entries = await this.list(level);
|
|
123
|
+
let bestMatch = null;
|
|
124
|
+
for (const entry of entries) {
|
|
125
|
+
const score = this.calculateSimilarity(content, entry.content);
|
|
126
|
+
if (!bestMatch || score > bestMatch.score) {
|
|
127
|
+
bestMatch = { entry, score };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return bestMatch;
|
|
131
|
+
}
|
|
132
|
+
async search(query, level) {
|
|
133
|
+
const levels = level ? [level] : ["project", "user"];
|
|
134
|
+
const results = [];
|
|
135
|
+
const queryLower = query.toLowerCase();
|
|
136
|
+
for (const lvl of levels) {
|
|
137
|
+
try {
|
|
138
|
+
const entries = await this.list(lvl);
|
|
139
|
+
for (const entry of entries) {
|
|
140
|
+
if (entry.content.toLowerCase().includes(queryLower) || entry.tags?.some((t) => t.toLowerCase().includes(queryLower))) {
|
|
141
|
+
results.push(entry);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
} catch {
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return results;
|
|
148
|
+
}
|
|
149
|
+
async recall(query, level) {
|
|
150
|
+
const levels = level ? [level] : ["user", "project"];
|
|
151
|
+
const results = [];
|
|
152
|
+
for (const lvl of levels) {
|
|
153
|
+
try {
|
|
154
|
+
const entries = await this.list(lvl);
|
|
155
|
+
for (const entry of entries) {
|
|
156
|
+
if (!query || entry.content.toLowerCase().includes(query.toLowerCase())) {
|
|
157
|
+
results.push({ content: entry.content, level: lvl });
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
} catch {
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return results;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Get memories formatted for LLM context injection
|
|
167
|
+
*/
|
|
168
|
+
async getContextMemories() {
|
|
169
|
+
const { project, user } = await this.listAll();
|
|
170
|
+
const parts = [];
|
|
171
|
+
if (project.length > 0) {
|
|
172
|
+
parts.push("## Project Memories");
|
|
173
|
+
for (const entry of project.slice(0, 10)) {
|
|
174
|
+
parts.push(`- ${entry.content}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (user.length > 0) {
|
|
178
|
+
parts.push("## User Preferences");
|
|
179
|
+
for (const entry of user.slice(0, 10)) {
|
|
180
|
+
parts.push(`- ${entry.content}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return parts.join("\n");
|
|
184
|
+
}
|
|
185
|
+
calculateSimilarity(a, b) {
|
|
186
|
+
const wordsA = this.tokenize(a);
|
|
187
|
+
const wordsB = this.tokenize(b);
|
|
188
|
+
if (wordsA.size === 0 || wordsB.size === 0) {
|
|
189
|
+
return 0;
|
|
190
|
+
}
|
|
191
|
+
const intersection = new Set([...wordsA].filter((x) => wordsB.has(x)));
|
|
192
|
+
const union = /* @__PURE__ */ new Set([...wordsA, ...wordsB]);
|
|
193
|
+
return intersection.size / union.size;
|
|
194
|
+
}
|
|
195
|
+
tokenize(text) {
|
|
196
|
+
return new Set(
|
|
197
|
+
text.toLowerCase().replace(/[^\w\s]/g, " ").split(/\s+/).filter((w) => w.length > 2)
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
generateId() {
|
|
201
|
+
return crypto.randomUUID().split("-")[0];
|
|
202
|
+
}
|
|
203
|
+
async updateIndex(level, entry) {
|
|
204
|
+
const dir = this.getMemoryDir(level);
|
|
205
|
+
const indexPath = path.join(dir, "index.json");
|
|
206
|
+
let index;
|
|
207
|
+
if (await fs.pathExists(indexPath)) {
|
|
208
|
+
index = await fs.readJson(indexPath);
|
|
209
|
+
} else {
|
|
210
|
+
index = { version: 1, entries: [] };
|
|
211
|
+
}
|
|
212
|
+
const existingIdx = index.entries.findIndex((e) => e.id === entry.id);
|
|
213
|
+
const indexEntry = {
|
|
214
|
+
id: entry.id,
|
|
215
|
+
preview: entry.content.slice(0, 100),
|
|
216
|
+
createdAt: entry.createdAt,
|
|
217
|
+
updatedAt: entry.updatedAt,
|
|
218
|
+
tags: entry.tags
|
|
219
|
+
};
|
|
220
|
+
if (existingIdx >= 0) {
|
|
221
|
+
index.entries[existingIdx] = indexEntry;
|
|
222
|
+
} else {
|
|
223
|
+
index.entries.push(indexEntry);
|
|
224
|
+
}
|
|
225
|
+
await fs.writeJson(indexPath, index, { spaces: 2 });
|
|
226
|
+
}
|
|
227
|
+
async removeFromIndex(level, id) {
|
|
228
|
+
const dir = this.getMemoryDir(level);
|
|
229
|
+
const indexPath = path.join(dir, "index.json");
|
|
230
|
+
if (!await fs.pathExists(indexPath)) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
const index = await fs.readJson(indexPath);
|
|
234
|
+
index.entries = index.entries.filter((e) => e.id !== id);
|
|
235
|
+
await fs.writeJson(indexPath, index, { spaces: 2 });
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
export {
|
|
240
|
+
MemoryManager
|
|
241
|
+
};
|
|
242
|
+
/**
|
|
243
|
+
* @license
|
|
244
|
+
* Copyright 2025 Autohand AI LLC
|
|
245
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
246
|
+
*/
|