hackwriter 0.0.2 → 0.0.4
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/agent/Agent.d.ts +1 -1
- package/dist/agent/Agent.d.ts.map +1 -1
- package/dist/agent/AgentExecutor.d.ts +17 -4
- package/dist/agent/AgentExecutor.d.ts.map +1 -1
- package/dist/agent/AgentExecutor.js +166 -84
- package/dist/agent/AgentExecutor.js.map +1 -1
- package/dist/agent/AgentTypes.d.ts +33 -0
- package/dist/agent/AgentTypes.d.ts.map +1 -0
- package/dist/agent/AgentTypes.js +13 -0
- package/dist/agent/AgentTypes.js.map +1 -0
- package/dist/agent/ApprovalManager.d.ts +26 -3
- package/dist/agent/ApprovalManager.d.ts.map +1 -1
- package/dist/agent/ApprovalManager.js +62 -27
- package/dist/agent/ApprovalManager.js.map +1 -1
- package/dist/agent/ApprovalProvider.d.ts +21 -0
- package/dist/agent/ApprovalProvider.d.ts.map +1 -0
- package/dist/agent/ApprovalProvider.js +2 -0
- package/dist/agent/ApprovalProvider.js.map +1 -0
- package/dist/agent/CompactionPrompt.d.ts +12 -0
- package/dist/agent/CompactionPrompt.d.ts.map +1 -0
- package/dist/agent/CompactionPrompt.js +23 -0
- package/dist/agent/CompactionPrompt.js.map +1 -0
- package/dist/agent/ContextCompressor.d.ts +2 -2
- package/dist/agent/ContextCompressor.d.ts.map +1 -1
- package/dist/agent/ContextCompressor.js +14 -22
- package/dist/agent/ContextCompressor.js.map +1 -1
- package/dist/agent/ConversationContext.d.ts +2 -2
- package/dist/agent/ConversationContext.d.ts.map +1 -1
- package/dist/agent/ConversationContext.js +40 -154
- package/dist/agent/ConversationContext.js.map +1 -1
- package/dist/agent/ModelFactory.d.ts +2 -2
- package/dist/agent/ModelFactory.d.ts.map +1 -1
- package/dist/agent/ModelFactory.js +14 -7
- package/dist/agent/ModelFactory.js.map +1 -1
- package/dist/cli.js +13 -25
- package/dist/cli.js.map +1 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +65 -41
- package/dist/commands/setup.js.map +1 -1
- package/dist/config/ConfigSchema.d.ts +5 -3
- package/dist/config/ConfigSchema.d.ts.map +1 -1
- package/dist/config/ConfigSchema.js +12 -9
- package/dist/config/ConfigSchema.js.map +1 -1
- package/dist/config/Configuration.d.ts +2 -2
- package/dist/config/Configuration.d.ts.map +1 -1
- package/dist/config/ConfigurationLoader.d.ts +1 -1
- package/dist/config/ConfigurationLoader.d.ts.map +1 -1
- package/dist/config/ConfigurationLoader.js +4 -4
- package/dist/config/ConfigurationLoader.js.map +1 -1
- package/dist/messaging/MessageBus.d.ts +1 -1
- package/dist/messaging/MessageBus.d.ts.map +1 -1
- package/dist/messaging/MessageTypes.d.ts +2 -2
- package/dist/messaging/MessageTypes.d.ts.map +1 -1
- package/dist/session/SessionManager.js +1 -1
- package/dist/session/SessionManager.js.map +1 -1
- package/dist/tools/base/Tool.d.ts +2 -1
- package/dist/tools/base/Tool.d.ts.map +1 -1
- package/dist/tools/base/Tool.js.map +1 -1
- package/dist/tools/base/ToolRegistry.d.ts +1 -1
- package/dist/tools/base/ToolRegistry.d.ts.map +1 -1
- package/dist/tools/file/ListFilesTool.d.ts +1 -1
- package/dist/tools/file/ListFilesTool.d.ts.map +1 -1
- package/dist/tools/file/ListFilesTool.js +1 -1
- package/dist/tools/file/ListFilesTool.js.map +1 -1
- package/dist/tools/file/ReadFileTool.d.ts +1 -1
- package/dist/tools/file/ReadFileTool.d.ts.map +1 -1
- package/dist/tools/file/ReadFileTool.js +1 -1
- package/dist/tools/file/ReadFileTool.js.map +1 -1
- package/dist/tools/file/WriteFileTool.d.ts +2 -2
- package/dist/tools/file/WriteFileTool.d.ts.map +1 -1
- package/dist/tools/file/WriteFileTool.js +1 -1
- package/dist/tools/file/WriteFileTool.js.map +1 -1
- package/dist/tools/file/index.d.ts +3 -3
- package/dist/tools/file/index.d.ts.map +1 -1
- package/dist/tools/file/index.js +3 -3
- package/dist/tools/file/index.js.map +1 -1
- package/dist/tools/hackmd/CreateNoteTool.d.ts +3 -3
- package/dist/tools/hackmd/CreateNoteTool.d.ts.map +1 -1
- package/dist/tools/hackmd/CreateNoteTool.js +3 -3
- package/dist/tools/hackmd/CreateNoteTool.js.map +1 -1
- package/dist/tools/hackmd/DeleteNoteTool.d.ts +2 -2
- package/dist/tools/hackmd/DeleteNoteTool.d.ts.map +1 -1
- package/dist/tools/hackmd/DeleteNoteTool.js +2 -2
- package/dist/tools/hackmd/DeleteNoteTool.js.map +1 -1
- package/dist/tools/hackmd/ExportNoteTool.d.ts +1 -1
- package/dist/tools/hackmd/ExportNoteTool.d.ts.map +1 -1
- package/dist/tools/hackmd/ExportNoteTool.js +1 -1
- package/dist/tools/hackmd/ExportNoteTool.js.map +1 -1
- package/dist/tools/hackmd/GetHistoryTool.d.ts +1 -1
- package/dist/tools/hackmd/GetHistoryTool.d.ts.map +1 -1
- package/dist/tools/hackmd/GetHistoryTool.js +1 -1
- package/dist/tools/hackmd/GetHistoryTool.js.map +1 -1
- package/dist/tools/hackmd/GetUserInfoTool.d.ts +2 -2
- package/dist/tools/hackmd/GetUserInfoTool.d.ts.map +1 -1
- package/dist/tools/hackmd/GetUserInfoTool.js +10 -10
- package/dist/tools/hackmd/GetUserInfoTool.js.map +1 -1
- package/dist/tools/hackmd/ListNotesTool.d.ts +1 -1
- package/dist/tools/hackmd/ListNotesTool.d.ts.map +1 -1
- package/dist/tools/hackmd/ListNotesTool.js +3 -3
- package/dist/tools/hackmd/ListNotesTool.js.map +1 -1
- package/dist/tools/hackmd/ListTeamsTool.d.ts +1 -1
- package/dist/tools/hackmd/ListTeamsTool.d.ts.map +1 -1
- package/dist/tools/hackmd/ListTeamsTool.js +1 -1
- package/dist/tools/hackmd/ListTeamsTool.js.map +1 -1
- package/dist/tools/hackmd/ReadNoteTool.d.ts +1 -1
- package/dist/tools/hackmd/ReadNoteTool.d.ts.map +1 -1
- package/dist/tools/hackmd/ReadNoteTool.js +2 -2
- package/dist/tools/hackmd/ReadNoteTool.js.map +1 -1
- package/dist/tools/hackmd/SearchNotesTool.d.ts +1 -1
- package/dist/tools/hackmd/SearchNotesTool.d.ts.map +1 -1
- package/dist/tools/hackmd/SearchNotesTool.js +1 -1
- package/dist/tools/hackmd/SearchNotesTool.js.map +1 -1
- package/dist/tools/hackmd/UpdateNoteTool.d.ts +2 -2
- package/dist/tools/hackmd/UpdateNoteTool.d.ts.map +1 -1
- package/dist/tools/hackmd/UpdateNoteTool.js +2 -2
- package/dist/tools/hackmd/UpdateNoteTool.js.map +1 -1
- package/dist/tools/hackmd/errorHandler.d.ts +1 -1
- package/dist/tools/hackmd/errorHandler.d.ts.map +1 -1
- package/dist/tools/hackmd/errorHandler.js +1 -1
- package/dist/tools/hackmd/errorHandler.js.map +1 -1
- package/dist/tools/hackmd/index.d.ts +10 -10
- package/dist/tools/hackmd/index.d.ts.map +1 -1
- package/dist/tools/hackmd/index.js +10 -10
- package/dist/tools/hackmd/index.js.map +1 -1
- package/dist/ui/shell/CommandRegistry.d.ts +1 -1
- package/dist/ui/shell/CommandRegistry.d.ts.map +1 -1
- package/dist/ui/shell/InteractiveShell.d.ts +1 -1
- package/dist/ui/shell/InteractiveShell.d.ts.map +1 -1
- package/dist/ui/shell/InteractiveShell.js +4 -4
- package/dist/ui/shell/InteractiveShell.js.map +1 -1
- package/dist/ui/shell/OutputRenderer.d.ts +1 -1
- package/dist/ui/shell/OutputRenderer.d.ts.map +1 -1
- package/package.json +16 -14
|
@@ -1,8 +1,31 @@
|
|
|
1
|
+
import type { ApprovalProvider, ApprovalResponse } from "./ApprovalProvider.js";
|
|
2
|
+
/**
|
|
3
|
+
* CLI-based approval provider using readline
|
|
4
|
+
* This is the implementation for interactive terminal use
|
|
5
|
+
*/
|
|
6
|
+
export declare class CLIApprovalProvider implements ApprovalProvider {
|
|
7
|
+
request(req: {
|
|
8
|
+
toolName: string;
|
|
9
|
+
action: string;
|
|
10
|
+
description: string;
|
|
11
|
+
}): Promise<ApprovalResponse>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Non-interactive approval provider (auto-approves everything)
|
|
15
|
+
* Useful for -c flag / yolo mode
|
|
16
|
+
*/
|
|
17
|
+
export declare class YoloApprovalProvider implements ApprovalProvider {
|
|
18
|
+
request(): Promise<ApprovalResponse>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Approval manager that delegates to a provider
|
|
22
|
+
* Handles session-based auto-approval logic
|
|
23
|
+
*/
|
|
1
24
|
export declare class ApprovalManager {
|
|
2
|
-
private yolo;
|
|
3
25
|
private autoApproveActions;
|
|
4
|
-
|
|
26
|
+
private provider;
|
|
27
|
+
constructor(provider?: ApprovalProvider, yolo?: boolean);
|
|
5
28
|
request(toolName: string, action: string, description: string): Promise<boolean>;
|
|
6
|
-
|
|
29
|
+
setProvider(provider: ApprovalProvider): void;
|
|
7
30
|
}
|
|
8
31
|
//# sourceMappingURL=ApprovalManager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApprovalManager.d.ts","sourceRoot":"","sources":["../../src/agent/ApprovalManager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ApprovalManager.d.ts","sourceRoot":"","sources":["../../src/agent/ApprovalManager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEhF;;;GAGG;AACH,qBAAa,mBAAoB,YAAW,gBAAgB;IACpD,OAAO,CAAC,GAAG,EAAE;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC,gBAAgB,CAAC;CA8B9B;AAED;;;GAGG;AACH,qBAAa,oBAAqB,YAAW,gBAAgB;IAC3D,OAAO,IAAI,OAAO,CAAC,gBAAgB,CAAC;CAGrC;AAED;;;GAGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,QAAQ,CAAmB;gBAEvB,QAAQ,CAAC,EAAE,gBAAgB,EAAE,IAAI,UAAQ;IAM/C,OAAO,CACX,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,OAAO,CAAC;IAwBnB,WAAW,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI;CAG9C"}
|
|
@@ -1,45 +1,80 @@
|
|
|
1
|
-
import * as readline from
|
|
1
|
+
import * as readline from "readline";
|
|
2
|
+
/**
|
|
3
|
+
* CLI-based approval provider using readline
|
|
4
|
+
* This is the implementation for interactive terminal use
|
|
5
|
+
*/
|
|
6
|
+
export class CLIApprovalProvider {
|
|
7
|
+
async request(req) {
|
|
8
|
+
console.log("\n⚠️ Approval Required");
|
|
9
|
+
console.log(`Tool: ${req.toolName}`);
|
|
10
|
+
console.log(`Action: ${req.description}`);
|
|
11
|
+
console.log("\nOptions:");
|
|
12
|
+
console.log(" 1. Approve once");
|
|
13
|
+
console.log(" 2. Approve for this session");
|
|
14
|
+
console.log(" 3. Reject");
|
|
15
|
+
const rl = readline.createInterface({
|
|
16
|
+
input: process.stdin,
|
|
17
|
+
output: process.stdout,
|
|
18
|
+
});
|
|
19
|
+
const answer = await new Promise((resolve) => {
|
|
20
|
+
rl.question("\nYour choice (1-3): ", resolve);
|
|
21
|
+
});
|
|
22
|
+
rl.close();
|
|
23
|
+
switch (answer.trim()) {
|
|
24
|
+
case "1":
|
|
25
|
+
return "approve";
|
|
26
|
+
case "2":
|
|
27
|
+
return "approve_for_session";
|
|
28
|
+
case "3":
|
|
29
|
+
default:
|
|
30
|
+
return "reject";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Non-interactive approval provider (auto-approves everything)
|
|
36
|
+
* Useful for -c flag / yolo mode
|
|
37
|
+
*/
|
|
38
|
+
export class YoloApprovalProvider {
|
|
39
|
+
request() {
|
|
40
|
+
return Promise.resolve("approve");
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Approval manager that delegates to a provider
|
|
45
|
+
* Handles session-based auto-approval logic
|
|
46
|
+
*/
|
|
2
47
|
export class ApprovalManager {
|
|
3
|
-
yolo;
|
|
4
48
|
autoApproveActions = new Set();
|
|
5
|
-
|
|
6
|
-
|
|
49
|
+
provider;
|
|
50
|
+
constructor(provider, yolo = false) {
|
|
51
|
+
this.provider =
|
|
52
|
+
provider ??
|
|
53
|
+
(yolo ? new YoloApprovalProvider() : new CLIApprovalProvider());
|
|
7
54
|
}
|
|
8
55
|
async request(toolName, action, description) {
|
|
9
|
-
if
|
|
10
|
-
return true;
|
|
11
|
-
}
|
|
56
|
+
// Check if already auto-approved for this session
|
|
12
57
|
if (this.autoApproveActions.has(action)) {
|
|
13
58
|
return true;
|
|
14
59
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
console.log(' 1. Approve once');
|
|
20
|
-
console.log(' 2. Approve for this session');
|
|
21
|
-
console.log(' 3. Reject');
|
|
22
|
-
const rl = readline.createInterface({
|
|
23
|
-
input: process.stdin,
|
|
24
|
-
output: process.stdout,
|
|
25
|
-
});
|
|
26
|
-
const answer = await new Promise(resolve => {
|
|
27
|
-
rl.question('\nYour choice (1-3): ', resolve);
|
|
60
|
+
const response = await this.provider.request({
|
|
61
|
+
toolName,
|
|
62
|
+
action,
|
|
63
|
+
description,
|
|
28
64
|
});
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
case '1':
|
|
65
|
+
switch (response) {
|
|
66
|
+
case "approve":
|
|
32
67
|
return true;
|
|
33
|
-
case
|
|
68
|
+
case "approve_for_session":
|
|
34
69
|
this.autoApproveActions.add(action);
|
|
35
70
|
return true;
|
|
36
|
-
case
|
|
71
|
+
case "reject":
|
|
37
72
|
default:
|
|
38
73
|
return false;
|
|
39
74
|
}
|
|
40
75
|
}
|
|
41
|
-
|
|
42
|
-
this.
|
|
76
|
+
setProvider(provider) {
|
|
77
|
+
this.provider = provider;
|
|
43
78
|
}
|
|
44
79
|
}
|
|
45
80
|
//# sourceMappingURL=ApprovalManager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApprovalManager.js","sourceRoot":"","sources":["../../src/agent/ApprovalManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"ApprovalManager.js","sourceRoot":"","sources":["../../src/agent/ApprovalManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AAGrC;;;GAGG;AACH,MAAM,OAAO,mBAAmB;IAC9B,KAAK,CAAC,OAAO,CAAC,GAIb;QACC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QACjC,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAE3B,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC;YAClC,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;YACnD,EAAE,CAAC,QAAQ,CAAC,uBAAuB,EAAE,OAAO,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,KAAK,EAAE,CAAC;QAEX,QAAQ,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;YACtB,KAAK,GAAG;gBACN,OAAO,SAAS,CAAC;YACnB,KAAK,GAAG;gBACN,OAAO,qBAAqB,CAAC;YAC/B,KAAK,GAAG,CAAC;YACT;gBACE,OAAO,QAAQ,CAAC;QACpB,CAAC;IACH,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,oBAAoB;IAC/B,OAAO;QACL,OAAO,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACpC,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,eAAe;IAClB,kBAAkB,GAAG,IAAI,GAAG,EAAU,CAAC;IACvC,QAAQ,CAAmB;IAEnC,YAAY,QAA2B,EAAE,IAAI,GAAG,KAAK;QACnD,IAAI,CAAC,QAAQ;YACX,QAAQ;gBACR,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC,CAAC,IAAI,mBAAmB,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,KAAK,CAAC,OAAO,CACX,QAAgB,EAChB,MAAc,EACd,WAAmB;QAEnB,kDAAkD;QAClD,IAAI,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACxC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;YAC3C,QAAQ;YACR,MAAM;YACN,WAAW;SACZ,CAAC,CAAC;QAEH,QAAQ,QAAQ,EAAE,CAAC;YACjB,KAAK,SAAS;gBACZ,OAAO,IAAI,CAAC;YACd,KAAK,qBAAqB;gBACxB,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACpC,OAAO,IAAI,CAAC;YACd,KAAK,QAAQ,CAAC;YACd;gBACE,OAAO,KAAK,CAAC;QACjB,CAAC;IACH,CAAC;IAED,WAAW,CAAC,QAA0B;QACpC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;CACF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response type for approval requests
|
|
3
|
+
*/
|
|
4
|
+
export type ApprovalResponse = "approve" | "approve_for_session" | "reject";
|
|
5
|
+
/**
|
|
6
|
+
* Interface for approval providers
|
|
7
|
+
* This allows different implementations (CLI, UI, non-interactive, etc.)
|
|
8
|
+
*/
|
|
9
|
+
export interface ApprovalProvider {
|
|
10
|
+
/**
|
|
11
|
+
* Request approval for a potentially dangerous operation
|
|
12
|
+
* @param request The approval request details
|
|
13
|
+
* @returns Promise resolving to approval response
|
|
14
|
+
*/
|
|
15
|
+
request(request: {
|
|
16
|
+
toolName: string;
|
|
17
|
+
action: string;
|
|
18
|
+
description: string;
|
|
19
|
+
}): Promise<ApprovalResponse>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=ApprovalProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApprovalProvider.d.ts","sourceRoot":"","sources":["../../src/agent/ApprovalProvider.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,qBAAqB,GAAG,QAAQ,CAAC;AAE5E;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,OAAO,CAAC,OAAO,EAAE;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAC/B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApprovalProvider.js","sourceRoot":"","sources":["../../src/agent/ApprovalProvider.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* System prompt template for context compaction
|
|
3
|
+
*
|
|
4
|
+
* This prompt instructs the model to compress conversation history while
|
|
5
|
+
* preserving essential information for continued execution.
|
|
6
|
+
*/
|
|
7
|
+
export declare const COMPACTION_PROMPT_TEMPLATE = "You are tasked with compacting a conversation context. Focus on:\n1. Current task state and goals\n2. Important errors and solutions\n3. Key decisions made\n4. Pending TODO items\n\nContext to compress:\n{{HISTORY}}\n\nProvide a concise summary that preserves essential information.";
|
|
8
|
+
/**
|
|
9
|
+
* Build the compaction prompt with given history
|
|
10
|
+
*/
|
|
11
|
+
export declare function buildCompactionPrompt(historyText: string): string;
|
|
12
|
+
//# sourceMappingURL=CompactionPrompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompactionPrompt.d.ts","sourceRoot":"","sources":["../../src/agent/CompactionPrompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,+RASyB,CAAC;AAEjE;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEjE"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* System prompt template for context compaction
|
|
3
|
+
*
|
|
4
|
+
* This prompt instructs the model to compress conversation history while
|
|
5
|
+
* preserving essential information for continued execution.
|
|
6
|
+
*/
|
|
7
|
+
export const COMPACTION_PROMPT_TEMPLATE = `You are tasked with compacting a conversation context. Focus on:
|
|
8
|
+
1. Current task state and goals
|
|
9
|
+
2. Important errors and solutions
|
|
10
|
+
3. Key decisions made
|
|
11
|
+
4. Pending TODO items
|
|
12
|
+
|
|
13
|
+
Context to compress:
|
|
14
|
+
{{HISTORY}}
|
|
15
|
+
|
|
16
|
+
Provide a concise summary that preserves essential information.`;
|
|
17
|
+
/**
|
|
18
|
+
* Build the compaction prompt with given history
|
|
19
|
+
*/
|
|
20
|
+
export function buildCompactionPrompt(historyText) {
|
|
21
|
+
return COMPACTION_PROMPT_TEMPLATE.replace("{{HISTORY}}", historyText);
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=CompactionPrompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompactionPrompt.js","sourceRoot":"","sources":["../../src/agent/CompactionPrompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG;;;;;;;;;gEASsB,CAAC;AAEjE;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,WAAmB;IACvD,OAAO,0BAA0B,CAAC,OAAO,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;AACxE,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { LanguageModel, ModelMessage } from
|
|
1
|
+
import type { LanguageModel, ModelMessage } from "ai";
|
|
2
2
|
export declare class ContextCompressor {
|
|
3
3
|
private readonly model;
|
|
4
4
|
constructor(model: LanguageModel);
|
|
5
|
-
compress(history: ModelMessage[]
|
|
5
|
+
compress(history: ModelMessage[]): Promise<string>;
|
|
6
6
|
private buildCompactionPrompt;
|
|
7
7
|
private formatContent;
|
|
8
8
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContextCompressor.d.ts","sourceRoot":"","sources":["../../src/agent/ContextCompressor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"ContextCompressor.d.ts","sourceRoot":"","sources":["../../src/agent/ContextCompressor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAItD,qBAAa,iBAAiB;IAChB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,aAAa;IAE3C,QAAQ,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAUxD,OAAO,CAAC,qBAAqB;IAW7B,OAAO,CAAC,aAAa;CA4BtB"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { generateText } from
|
|
1
|
+
import { generateText } from "ai";
|
|
2
|
+
import { buildCompactionPrompt } from "./CompactionPrompt.js";
|
|
2
3
|
export class ContextCompressor {
|
|
3
4
|
model;
|
|
4
5
|
constructor(model) {
|
|
5
6
|
this.model = model;
|
|
6
7
|
}
|
|
7
|
-
async compress(history
|
|
8
|
+
async compress(history) {
|
|
8
9
|
const compactionPrompt = this.buildCompactionPrompt(history);
|
|
9
10
|
const response = await generateText({
|
|
10
11
|
model: this.model,
|
|
@@ -16,41 +17,32 @@ export class ContextCompressor {
|
|
|
16
17
|
buildCompactionPrompt(history) {
|
|
17
18
|
const historyText = history
|
|
18
19
|
.map((msg, i) => `## Message ${i + 1}\nRole: ${msg.role}\nContent: ${this.formatContent(msg.content)}`)
|
|
19
|
-
.join(
|
|
20
|
-
return
|
|
21
|
-
1. Current task state and goals
|
|
22
|
-
2. Important errors and solutions
|
|
23
|
-
3. Key decisions made
|
|
24
|
-
4. Pending TODO items
|
|
25
|
-
|
|
26
|
-
Context to compress:
|
|
27
|
-
${historyText}
|
|
28
|
-
|
|
29
|
-
Provide a concise summary that preserves essential information.`;
|
|
20
|
+
.join("\n\n");
|
|
21
|
+
return buildCompactionPrompt(historyText);
|
|
30
22
|
}
|
|
31
23
|
formatContent(content) {
|
|
32
|
-
if (typeof content ===
|
|
24
|
+
if (typeof content === "string") {
|
|
33
25
|
return content;
|
|
34
26
|
}
|
|
35
27
|
if (Array.isArray(content)) {
|
|
36
28
|
return content
|
|
37
|
-
.map(part => {
|
|
38
|
-
if (typeof part !==
|
|
29
|
+
.map((part) => {
|
|
30
|
+
if (typeof part !== "object" || !part) {
|
|
39
31
|
return undefined;
|
|
40
32
|
}
|
|
41
|
-
if (
|
|
33
|
+
if ("text" in part && typeof part.text === "string") {
|
|
42
34
|
return part.text;
|
|
43
35
|
}
|
|
44
|
-
if (
|
|
36
|
+
if ("type" in part && part.type === "tool-call") {
|
|
45
37
|
return `[tool:${part.toolName}] ${JSON.stringify(part.input)}`;
|
|
46
38
|
}
|
|
47
|
-
if (
|
|
39
|
+
if ("type" in part && part.type === "tool-result") {
|
|
48
40
|
return `[tool-result:${part.toolName}] ${JSON.stringify(part.output)}`;
|
|
49
41
|
}
|
|
50
|
-
return `[${part.type ??
|
|
42
|
+
return `[${part.type ?? "unknown-part"}]`;
|
|
51
43
|
})
|
|
52
|
-
.filter((value) => typeof value ===
|
|
53
|
-
.join(
|
|
44
|
+
.filter((value) => typeof value === "string")
|
|
45
|
+
.join("\n");
|
|
54
46
|
}
|
|
55
47
|
return JSON.stringify(content);
|
|
56
48
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContextCompressor.js","sourceRoot":"","sources":["../../src/agent/ContextCompressor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"ContextCompressor.js","sourceRoot":"","sources":["../../src/agent/ContextCompressor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,MAAM,OAAO,iBAAiB;IACC;IAA7B,YAA6B,KAAoB;QAApB,UAAK,GAAL,KAAK,CAAe;IAAG,CAAC;IAErD,KAAK,CAAC,QAAQ,CAAC,OAAuB;QACpC,MAAM,gBAAgB,GAAG,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC;QAC7D,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC;YAClC,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,eAAe,EAAE,IAAI;YACrB,MAAM,EAAE,gBAAgB;SACzB,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAC9B,CAAC;IAEO,qBAAqB,CAAC,OAAuB;QACnD,MAAM,WAAW,GAAG,OAAO;aACxB,GAAG,CACF,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CACT,cAAc,CAAC,GAAG,CAAC,WAAW,GAAG,CAAC,IAAI,cAAc,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CACxF;aACA,IAAI,CAAC,MAAM,CAAC,CAAC;QAEhB,OAAO,qBAAqB,CAAC,WAAW,CAAC,CAAC;IAC5C,CAAC;IAEO,aAAa,CAAC,OAAgC;QACpD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAChC,OAAO,OAAO,CAAC;QACjB,CAAC;QAED,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,OAAO,OAAO;iBACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;gBACZ,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;oBACtC,OAAO,SAAS,CAAC;gBACnB,CAAC;gBACD,IAAI,MAAM,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACpD,OAAO,IAAI,CAAC,IAAI,CAAC;gBACnB,CAAC;gBACD,IAAI,MAAM,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;oBAChD,OAAO,SAAS,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBACjE,CAAC;gBACD,IAAI,MAAM,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;oBAClD,OAAO,gBAAgB,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;gBACzE,CAAC;gBACD,OAAO,IAAK,IAA0B,CAAC,IAAI,IAAI,cAAc,GAAG,CAAC;YACnE,CAAC,CAAC;iBACD,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC;iBAC7D,IAAI,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC;QAED,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IACjC,CAAC;CACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ModelMessage } from
|
|
1
|
+
import type { ModelMessage } from "ai";
|
|
2
2
|
export declare class ConversationContext {
|
|
3
3
|
private messages;
|
|
4
4
|
private _tokenCount;
|
|
@@ -9,7 +9,7 @@ export declare class ConversationContext {
|
|
|
9
9
|
loadFromDisk(): Promise<boolean>;
|
|
10
10
|
createCheckpoint(): Promise<number>;
|
|
11
11
|
addMessage(message: ModelMessage | ModelMessage[]): Promise<void>;
|
|
12
|
-
|
|
12
|
+
setTokenCount(count: number): Promise<void>;
|
|
13
13
|
revertToCheckpoint(checkpointId: number): Promise<void>;
|
|
14
14
|
getHistory(): ModelMessage[];
|
|
15
15
|
get tokenCount(): number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConversationContext.d.ts","sourceRoot":"","sources":["../../src/agent/ConversationContext.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"ConversationContext.d.ts","sourceRoot":"","sources":["../../src/agent/ConversationContext.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAQvC,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,YAAY,CAAU;gBAElB,WAAW,EAAE,MAAM;IAKzB,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC;IAgDhC,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;IAMnC,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,YAAY,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IASjE,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK3C,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA0C7D,UAAU,IAAI,YAAY,EAAE;IAI5B,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,IAAI,eAAe,IAAI,MAAM,CAE5B;YAEa,aAAa;CAM5B"}
|
|
@@ -1,123 +1,5 @@
|
|
|
1
|
-
import { promises as fs } from
|
|
2
|
-
import { Logger } from
|
|
3
|
-
const SUPPORTED_ROLES = new Set(['system', 'user', 'assistant', 'tool']);
|
|
4
|
-
function isSupportedRole(value) {
|
|
5
|
-
return typeof value === 'string' && SUPPORTED_ROLES.has(value);
|
|
6
|
-
}
|
|
7
|
-
function isModelMessage(value) {
|
|
8
|
-
if (!value || typeof value !== 'object') {
|
|
9
|
-
return false;
|
|
10
|
-
}
|
|
11
|
-
const candidate = value;
|
|
12
|
-
return isSupportedRole(candidate.role);
|
|
13
|
-
}
|
|
14
|
-
function coerceLegacyMessage(data) {
|
|
15
|
-
if (isModelMessage(data)) {
|
|
16
|
-
return data;
|
|
17
|
-
}
|
|
18
|
-
if (!data || typeof data !== 'object') {
|
|
19
|
-
return undefined;
|
|
20
|
-
}
|
|
21
|
-
const { role, content } = data;
|
|
22
|
-
if (!isSupportedRole(role)) {
|
|
23
|
-
return undefined;
|
|
24
|
-
}
|
|
25
|
-
if (role === 'tool') {
|
|
26
|
-
const toolContent = coerceLegacyToolContent(content);
|
|
27
|
-
if (toolContent) {
|
|
28
|
-
return { role: 'tool', content: toolContent };
|
|
29
|
-
}
|
|
30
|
-
return undefined;
|
|
31
|
-
}
|
|
32
|
-
const textContent = coerceLegacyTextContent(content);
|
|
33
|
-
if (textContent !== undefined) {
|
|
34
|
-
return { role: role, content: textContent };
|
|
35
|
-
}
|
|
36
|
-
return undefined;
|
|
37
|
-
}
|
|
38
|
-
function coerceLegacyTextContent(content) {
|
|
39
|
-
if (typeof content === 'string') {
|
|
40
|
-
return content;
|
|
41
|
-
}
|
|
42
|
-
if (Array.isArray(content)) {
|
|
43
|
-
const flattened = content
|
|
44
|
-
.map(block => {
|
|
45
|
-
if (!block || typeof block !== 'object') {
|
|
46
|
-
return undefined;
|
|
47
|
-
}
|
|
48
|
-
const kind = block.type;
|
|
49
|
-
if (kind === 'text' && typeof block.text === 'string') {
|
|
50
|
-
return block.text;
|
|
51
|
-
}
|
|
52
|
-
if (kind === 'tool_use') {
|
|
53
|
-
const name = block.name ?? 'unknown-tool';
|
|
54
|
-
return `[tool:${name}]`;
|
|
55
|
-
}
|
|
56
|
-
if (kind === 'tool_result') {
|
|
57
|
-
return `[tool-result:${JSON.stringify(block)}]`;
|
|
58
|
-
}
|
|
59
|
-
return undefined;
|
|
60
|
-
})
|
|
61
|
-
.filter((val) => typeof val === 'string');
|
|
62
|
-
if (flattened.length > 0) {
|
|
63
|
-
return flattened.join('\n');
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
if (content !== undefined) {
|
|
67
|
-
try {
|
|
68
|
-
return JSON.stringify(content);
|
|
69
|
-
}
|
|
70
|
-
catch {
|
|
71
|
-
return undefined;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
return undefined;
|
|
75
|
-
}
|
|
76
|
-
function coerceLegacyToolContent(content) {
|
|
77
|
-
if (!Array.isArray(content)) {
|
|
78
|
-
return undefined;
|
|
79
|
-
}
|
|
80
|
-
const parts = [];
|
|
81
|
-
for (const block of content) {
|
|
82
|
-
if (!block || typeof block !== 'object') {
|
|
83
|
-
continue;
|
|
84
|
-
}
|
|
85
|
-
const kind = block.type;
|
|
86
|
-
if (kind !== 'tool_result') {
|
|
87
|
-
continue;
|
|
88
|
-
}
|
|
89
|
-
const id = block.tool_call_id ??
|
|
90
|
-
block.tool_use_id ??
|
|
91
|
-
`legacy-tool-${parts.length}`;
|
|
92
|
-
const name = block.tool_name ?? block.name ?? 'legacy-tool';
|
|
93
|
-
const isError = Boolean(block.is_error);
|
|
94
|
-
const value = block.content ?? block.output ?? null;
|
|
95
|
-
const serializedValue = serializeLegacyValue(value);
|
|
96
|
-
parts.push({
|
|
97
|
-
type: 'tool-result',
|
|
98
|
-
toolCallId: String(id),
|
|
99
|
-
toolName: String(name),
|
|
100
|
-
output: isError
|
|
101
|
-
? { type: 'error-json', value: { ok: false, content: serializedValue } }
|
|
102
|
-
: { type: 'json', value: { ok: true, content: serializedValue } },
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
return parts.length > 0 ? parts : undefined;
|
|
106
|
-
}
|
|
107
|
-
function serializeLegacyValue(value) {
|
|
108
|
-
if (value === null || value === undefined) {
|
|
109
|
-
return null;
|
|
110
|
-
}
|
|
111
|
-
if (typeof value === 'string') {
|
|
112
|
-
return value;
|
|
113
|
-
}
|
|
114
|
-
try {
|
|
115
|
-
return JSON.stringify(value);
|
|
116
|
-
}
|
|
117
|
-
catch {
|
|
118
|
-
return null;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
1
|
+
import { promises as fs } from "fs";
|
|
2
|
+
import { Logger } from "../utils/Logger.js";
|
|
121
3
|
export class ConversationContext {
|
|
122
4
|
messages = [];
|
|
123
5
|
_tokenCount = 0;
|
|
@@ -126,35 +8,43 @@ export class ConversationContext {
|
|
|
126
8
|
isMemoryMode;
|
|
127
9
|
constructor(storageFile) {
|
|
128
10
|
this.storageFile = storageFile;
|
|
129
|
-
this.isMemoryMode = storageFile ===
|
|
11
|
+
this.isMemoryMode = storageFile === ":memory:";
|
|
130
12
|
}
|
|
131
13
|
async loadFromDisk() {
|
|
132
14
|
if (this.isMemoryMode) {
|
|
133
15
|
return false;
|
|
134
16
|
}
|
|
135
17
|
try {
|
|
136
|
-
const content = await fs.readFile(this.storageFile,
|
|
137
|
-
const lines = content.split(
|
|
18
|
+
const content = await fs.readFile(this.storageFile, "utf-8");
|
|
19
|
+
const lines = content.split("\n").filter((l) => l.trim());
|
|
20
|
+
let corruptedLines = 0;
|
|
138
21
|
for (const line of lines) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
else if (record.type === 'message') {
|
|
147
|
-
const normalized = coerceLegacyMessage(record.data);
|
|
148
|
-
if (normalized) {
|
|
149
|
-
this.messages.push(normalized);
|
|
22
|
+
try {
|
|
23
|
+
const record = JSON.parse(line);
|
|
24
|
+
if (record.type === "usage") {
|
|
25
|
+
this._tokenCount = record.tokenCount;
|
|
26
|
+
}
|
|
27
|
+
else if (record.type === "checkpoint") {
|
|
28
|
+
this.checkpointCounter = record.id + 1;
|
|
150
29
|
}
|
|
30
|
+
else if (record.type === "message") {
|
|
31
|
+
this.messages.push(record.data);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch (e) {
|
|
35
|
+
corruptedLines++;
|
|
36
|
+
Logger.warn("ConversationContext", "Skipping corrupted history line", {
|
|
37
|
+
line: line.slice(0, 100),
|
|
38
|
+
error: e instanceof Error ? e.message : String(e),
|
|
39
|
+
});
|
|
40
|
+
continue;
|
|
151
41
|
}
|
|
152
42
|
}
|
|
153
|
-
Logger.debug(
|
|
43
|
+
Logger.debug("ConversationContext", `Loaded ${this.messages.length} messages, ${this._tokenCount} tokens`, corruptedLines > 0 ? { corruptedLines } : undefined);
|
|
154
44
|
return true;
|
|
155
45
|
}
|
|
156
46
|
catch (error) {
|
|
157
|
-
if (error.code ===
|
|
47
|
+
if (error.code === "ENOENT") {
|
|
158
48
|
return false;
|
|
159
49
|
}
|
|
160
50
|
throw error;
|
|
@@ -162,19 +52,19 @@ export class ConversationContext {
|
|
|
162
52
|
}
|
|
163
53
|
async createCheckpoint() {
|
|
164
54
|
const checkpointId = this.checkpointCounter++;
|
|
165
|
-
await this.persistRecord({ type:
|
|
55
|
+
await this.persistRecord({ type: "checkpoint", id: checkpointId });
|
|
166
56
|
return checkpointId;
|
|
167
57
|
}
|
|
168
58
|
async addMessage(message) {
|
|
169
59
|
const msgs = Array.isArray(message) ? message : [message];
|
|
170
60
|
this.messages.push(...msgs);
|
|
171
61
|
for (const msg of msgs) {
|
|
172
|
-
await this.persistRecord({ type:
|
|
62
|
+
await this.persistRecord({ type: "message", data: msg });
|
|
173
63
|
}
|
|
174
64
|
}
|
|
175
|
-
async
|
|
176
|
-
this._tokenCount
|
|
177
|
-
await this.persistRecord({ type:
|
|
65
|
+
async setTokenCount(count) {
|
|
66
|
+
this._tokenCount = count;
|
|
67
|
+
await this.persistRecord({ type: "usage", tokenCount: this._tokenCount });
|
|
178
68
|
}
|
|
179
69
|
async revertToCheckpoint(checkpointId) {
|
|
180
70
|
if (this.isMemoryMode) {
|
|
@@ -184,8 +74,8 @@ export class ConversationContext {
|
|
|
184
74
|
this.checkpointCounter = 0;
|
|
185
75
|
return;
|
|
186
76
|
}
|
|
187
|
-
const originalContent = await fs.readFile(this.storageFile,
|
|
188
|
-
const lines = originalContent.split(
|
|
77
|
+
const originalContent = await fs.readFile(this.storageFile, "utf-8");
|
|
78
|
+
const lines = originalContent.split("\n").filter((l) => l.trim());
|
|
189
79
|
// Create backup
|
|
190
80
|
const backupFile = `${this.storageFile}.${Date.now()}.backup`;
|
|
191
81
|
await fs.rename(this.storageFile, backupFile);
|
|
@@ -195,23 +85,19 @@ export class ConversationContext {
|
|
|
195
85
|
this.checkpointCounter = 0;
|
|
196
86
|
for (const line of lines) {
|
|
197
87
|
const record = JSON.parse(line);
|
|
198
|
-
if (record.type ===
|
|
88
|
+
if (record.type === "checkpoint" && record.id === checkpointId) {
|
|
199
89
|
break;
|
|
200
90
|
}
|
|
201
|
-
if (record.type ===
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
continue;
|
|
205
|
-
}
|
|
206
|
-
await this.persistRecord({ type: 'message', data: normalized });
|
|
207
|
-
this.messages.push(normalized);
|
|
91
|
+
if (record.type === "message") {
|
|
92
|
+
await this.persistRecord({ type: "message", data: record.data });
|
|
93
|
+
this.messages.push(record.data);
|
|
208
94
|
}
|
|
209
95
|
else {
|
|
210
96
|
await this.persistRecord(record);
|
|
211
|
-
if (record.type ===
|
|
97
|
+
if (record.type === "usage") {
|
|
212
98
|
this._tokenCount = record.tokenCount;
|
|
213
99
|
}
|
|
214
|
-
else if (record.type ===
|
|
100
|
+
else if (record.type === "checkpoint") {
|
|
215
101
|
this.checkpointCounter = record.id + 1;
|
|
216
102
|
}
|
|
217
103
|
}
|
|
@@ -230,7 +116,7 @@ export class ConversationContext {
|
|
|
230
116
|
if (this.isMemoryMode) {
|
|
231
117
|
return;
|
|
232
118
|
}
|
|
233
|
-
await fs.appendFile(this.storageFile, JSON.stringify(data) +
|
|
119
|
+
await fs.appendFile(this.storageFile, JSON.stringify(data) + "\n", "utf-8");
|
|
234
120
|
}
|
|
235
121
|
}
|
|
236
122
|
//# sourceMappingURL=ConversationContext.js.map
|