aimux-cli 0.1.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/README.md +743 -0
- package/bin/aimux +2 -0
- package/dist/agent-events.d.ts +20 -0
- package/dist/agent-events.js +2 -0
- package/dist/agent-events.js.map +1 -0
- package/dist/agent-message-parts.d.ts +17 -0
- package/dist/agent-message-parts.js +31 -0
- package/dist/agent-message-parts.js.map +1 -0
- package/dist/agent-output-parser.d.ts +16 -0
- package/dist/agent-output-parser.js +229 -0
- package/dist/agent-output-parser.js.map +1 -0
- package/dist/agent-tracker.d.ts +9 -0
- package/dist/agent-tracker.js +144 -0
- package/dist/agent-tracker.js.map +1 -0
- package/dist/agent-watcher.d.ts +15 -0
- package/dist/agent-watcher.js +2 -0
- package/dist/agent-watcher.js.map +1 -0
- package/dist/attachment-store.d.ts +35 -0
- package/dist/attachment-store.js +129 -0
- package/dist/attachment-store.js.map +1 -0
- package/dist/builtin-metadata-watchers.d.ts +2 -0
- package/dist/builtin-metadata-watchers.js +275 -0
- package/dist/builtin-metadata-watchers.js.map +1 -0
- package/dist/claude-hooks.d.ts +29 -0
- package/dist/claude-hooks.js +106 -0
- package/dist/claude-hooks.js.map +1 -0
- package/dist/config.d.ts +78 -0
- package/dist/config.js +172 -0
- package/dist/config.js.map +1 -0
- package/dist/context/compactor.d.ts +20 -0
- package/dist/context/compactor.js +212 -0
- package/dist/context/compactor.js.map +1 -0
- package/dist/context/context-bridge.d.ts +67 -0
- package/dist/context/context-bridge.js +471 -0
- package/dist/context/context-bridge.js.map +1 -0
- package/dist/context/context-file.d.ts +11 -0
- package/dist/context/context-file.js +93 -0
- package/dist/context/context-file.js.map +1 -0
- package/dist/context/history.d.ts +40 -0
- package/dist/context/history.js +108 -0
- package/dist/context/history.js.map +1 -0
- package/dist/daemon.d.ts +39 -0
- package/dist/daemon.js +344 -0
- package/dist/daemon.js.map +1 -0
- package/dist/dashboard-session-registry.d.ts +47 -0
- package/dist/dashboard-session-registry.js +161 -0
- package/dist/dashboard-session-registry.js.map +1 -0
- package/dist/dashboard-state.d.ts +18 -0
- package/dist/dashboard-state.js +26 -0
- package/dist/dashboard-state.js.map +1 -0
- package/dist/dashboard.d.ts +118 -0
- package/dist/dashboard.js +91 -0
- package/dist/dashboard.js.map +1 -0
- package/dist/debug.d.ts +7 -0
- package/dist/debug.js +41 -0
- package/dist/debug.js.map +1 -0
- package/dist/fast-control.d.ts +45 -0
- package/dist/fast-control.js +174 -0
- package/dist/fast-control.js.map +1 -0
- package/dist/hotkeys.d.ts +44 -0
- package/dist/hotkeys.js +118 -0
- package/dist/hotkeys.js.map +1 -0
- package/dist/http-client.d.ts +10 -0
- package/dist/http-client.js +54 -0
- package/dist/http-client.js.map +1 -0
- package/dist/instance-directory.d.ts +32 -0
- package/dist/instance-directory.js +82 -0
- package/dist/instance-directory.js.map +1 -0
- package/dist/instance-registry.d.ts +38 -0
- package/dist/instance-registry.js +208 -0
- package/dist/instance-registry.js.map +1 -0
- package/dist/key-parser.d.ts +30 -0
- package/dist/key-parser.js +272 -0
- package/dist/key-parser.js.map +1 -0
- package/dist/last-used.d.ts +31 -0
- package/dist/last-used.js +93 -0
- package/dist/last-used.js.map +1 -0
- package/dist/main.d.ts +1 -0
- package/dist/main.js +2483 -0
- package/dist/main.js.map +1 -0
- package/dist/metadata-server.d.ts +268 -0
- package/dist/metadata-server.js +1379 -0
- package/dist/metadata-server.js.map +1 -0
- package/dist/metadata-store.d.ts +80 -0
- package/dist/metadata-store.js +87 -0
- package/dist/metadata-store.js.map +1 -0
- package/dist/multiplexer.d.ts +471 -0
- package/dist/multiplexer.js +5714 -0
- package/dist/multiplexer.js.map +1 -0
- package/dist/notification-context.d.ts +18 -0
- package/dist/notification-context.js +68 -0
- package/dist/notification-context.js.map +1 -0
- package/dist/notifications.d.ts +38 -0
- package/dist/notifications.js +111 -0
- package/dist/notifications.js.map +1 -0
- package/dist/notify.d.ts +10 -0
- package/dist/notify.js +62 -0
- package/dist/notify.js.map +1 -0
- package/dist/orchestration-actions.d.ts +76 -0
- package/dist/orchestration-actions.js +310 -0
- package/dist/orchestration-actions.js.map +1 -0
- package/dist/orchestration-dispatcher.d.ts +22 -0
- package/dist/orchestration-dispatcher.js +49 -0
- package/dist/orchestration-dispatcher.js.map +1 -0
- package/dist/orchestration-routing.d.ts +20 -0
- package/dist/orchestration-routing.js +78 -0
- package/dist/orchestration-routing.js.map +1 -0
- package/dist/orchestration.d.ts +26 -0
- package/dist/orchestration.js +110 -0
- package/dist/orchestration.js.map +1 -0
- package/dist/osc-notifications.d.ts +15 -0
- package/dist/osc-notifications.js +180 -0
- package/dist/osc-notifications.js.map +1 -0
- package/dist/paths.d.ts +55 -0
- package/dist/paths.js +259 -0
- package/dist/paths.js.map +1 -0
- package/dist/plugin-runtime.d.ts +46 -0
- package/dist/plugin-runtime.js +180 -0
- package/dist/plugin-runtime.js.map +1 -0
- package/dist/project-events.d.ts +36 -0
- package/dist/project-events.js +63 -0
- package/dist/project-events.js.map +1 -0
- package/dist/project-scanner.d.ts +38 -0
- package/dist/project-scanner.js +243 -0
- package/dist/project-scanner.js.map +1 -0
- package/dist/project-service-manifest.d.ts +18 -0
- package/dist/project-service-manifest.js +56 -0
- package/dist/project-service-manifest.js.map +1 -0
- package/dist/recency.d.ts +2 -0
- package/dist/recency.js +34 -0
- package/dist/recency.js.map +1 -0
- package/dist/recorder.d.ts +14 -0
- package/dist/recorder.js +130 -0
- package/dist/recorder.js.map +1 -0
- package/dist/session-bootstrap.d.ts +45 -0
- package/dist/session-bootstrap.js +436 -0
- package/dist/session-bootstrap.js.map +1 -0
- package/dist/session-message-history.d.ts +27 -0
- package/dist/session-message-history.js +105 -0
- package/dist/session-message-history.js.map +1 -0
- package/dist/session-runtime.d.ts +44 -0
- package/dist/session-runtime.js +56 -0
- package/dist/session-runtime.js.map +1 -0
- package/dist/session-semantics.d.ts +35 -0
- package/dist/session-semantics.js +110 -0
- package/dist/session-semantics.js.map +1 -0
- package/dist/status-detector.d.ts +17 -0
- package/dist/status-detector.js +67 -0
- package/dist/status-detector.js.map +1 -0
- package/dist/statusline-model.d.ts +103 -0
- package/dist/statusline-model.js +177 -0
- package/dist/statusline-model.js.map +1 -0
- package/dist/task-dispatcher.d.ts +63 -0
- package/dist/task-dispatcher.js +210 -0
- package/dist/task-dispatcher.js.map +1 -0
- package/dist/task-workflow.d.ts +13 -0
- package/dist/task-workflow.js +153 -0
- package/dist/task-workflow.js.map +1 -0
- package/dist/tasks.d.ts +60 -0
- package/dist/tasks.js +120 -0
- package/dist/tasks.js.map +1 -0
- package/dist/team.d.ts +28 -0
- package/dist/team.js +91 -0
- package/dist/team.js.map +1 -0
- package/dist/terminal-host.d.ts +10 -0
- package/dist/terminal-host.js +52 -0
- package/dist/terminal-host.js.map +1 -0
- package/dist/threads.d.ts +61 -0
- package/dist/threads.js +200 -0
- package/dist/threads.js.map +1 -0
- package/dist/tmux-doctor.d.ts +47 -0
- package/dist/tmux-doctor.js +112 -0
- package/dist/tmux-doctor.js.map +1 -0
- package/dist/tmux-runtime-manager.d.ts +164 -0
- package/dist/tmux-runtime-manager.js +794 -0
- package/dist/tmux-runtime-manager.js.map +1 -0
- package/dist/tmux-session-transport.d.ts +31 -0
- package/dist/tmux-session-transport.js +115 -0
- package/dist/tmux-session-transport.js.map +1 -0
- package/dist/tmux-statusline.d.ts +17 -0
- package/dist/tmux-statusline.js +166 -0
- package/dist/tmux-statusline.js.map +1 -0
- package/dist/tool-output-watchers.d.ts +10 -0
- package/dist/tool-output-watchers.js +190 -0
- package/dist/tool-output-watchers.js.map +1 -0
- package/dist/tui/render/box.d.ts +1 -0
- package/dist/tui/render/box.js +20 -0
- package/dist/tui/render/box.js.map +1 -0
- package/dist/tui/render/text.d.ts +8 -0
- package/dist/tui/render/text.js +92 -0
- package/dist/tui/render/text.js.map +1 -0
- package/dist/tui/screens/dashboard-renderers.d.ts +23 -0
- package/dist/tui/screens/dashboard-renderers.js +411 -0
- package/dist/tui/screens/dashboard-renderers.js.map +1 -0
- package/dist/tui/screens/overlay-renderers.d.ts +10 -0
- package/dist/tui/screens/overlay-renderers.js +274 -0
- package/dist/tui/screens/overlay-renderers.js.map +1 -0
- package/dist/tui/screens/subscreen-renderers.d.ts +9 -0
- package/dist/tui/screens/subscreen-renderers.js +327 -0
- package/dist/tui/screens/subscreen-renderers.js.map +1 -0
- package/dist/workflow.d.ts +19 -0
- package/dist/workflow.js +111 -0
- package/dist/workflow.js.map +1 -0
- package/dist/worktree.d.ts +23 -0
- package/dist/worktree.js +101 -0
- package/dist/worktree.js.map +1 -0
- package/package.json +70 -0
package/dist/config.js
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { getGlobalAimuxDir, getGlobalConfigPath, getLocalAimuxDir, getConfigPath, getProjectStateDir, } from "./paths.js";
|
|
4
|
+
const DEFAULT_CONFIG = {
|
|
5
|
+
defaultTool: "claude",
|
|
6
|
+
contextMaxEntries: 20,
|
|
7
|
+
liveWindowSize: 20,
|
|
8
|
+
compactEveryNTurns: 50,
|
|
9
|
+
notifications: {
|
|
10
|
+
enabled: true,
|
|
11
|
+
onPrompt: true,
|
|
12
|
+
onError: true,
|
|
13
|
+
onComplete: true,
|
|
14
|
+
},
|
|
15
|
+
runtime: {
|
|
16
|
+
tmux: {
|
|
17
|
+
sessionPrefix: "aimux",
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
worktrees: {
|
|
21
|
+
baseDir: ".aimux/worktrees",
|
|
22
|
+
},
|
|
23
|
+
tools: {
|
|
24
|
+
claude: {
|
|
25
|
+
command: "claude",
|
|
26
|
+
args: ["--dangerously-skip-permissions"],
|
|
27
|
+
enabled: true,
|
|
28
|
+
wrapperEnabled: true,
|
|
29
|
+
preambleFlag: ["--append-system-prompt"],
|
|
30
|
+
sessionIdFlag: ["--session-id", "{sessionId}"],
|
|
31
|
+
resumeArgs: ["--resume", "{sessionId}"],
|
|
32
|
+
resumeByBackendSessionId: false,
|
|
33
|
+
resumeFallback: ["--continue"],
|
|
34
|
+
promptPatterns: ["^> $", "\\$ $"],
|
|
35
|
+
turnPatterns: ["^[❯>]\\s*(.+)", "^❯\\s+(.+)", "^>\\s+(.+)"],
|
|
36
|
+
compactCommand: "claude --print --output-format text",
|
|
37
|
+
},
|
|
38
|
+
codex: {
|
|
39
|
+
command: "codex",
|
|
40
|
+
args: ["--dangerously-bypass-approvals-and-sandbox"],
|
|
41
|
+
enabled: true,
|
|
42
|
+
resumeArgs: ["resume", "{sessionId}"],
|
|
43
|
+
resumeByBackendSessionId: true,
|
|
44
|
+
resumeFallback: ["resume", "--last"],
|
|
45
|
+
instructionsFile: "AGENTS.md",
|
|
46
|
+
sessionCapture: {
|
|
47
|
+
dir: "{home}/.codex/sessions/{yyyy}/{mm}/{dd}",
|
|
48
|
+
pattern: "([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\\.jsonl$",
|
|
49
|
+
delayMs: 2000,
|
|
50
|
+
},
|
|
51
|
+
promptPatterns: ["^> $"],
|
|
52
|
+
turnPatterns: ["^[>❯]\\s*(.+)"],
|
|
53
|
+
},
|
|
54
|
+
aider: {
|
|
55
|
+
command: "aider",
|
|
56
|
+
args: [],
|
|
57
|
+
enabled: true,
|
|
58
|
+
resumeFallback: ["--restore-chat-history"],
|
|
59
|
+
promptPatterns: ["^aider> $", "^> $"],
|
|
60
|
+
turnPatterns: ["^aider>\\s*(.+)", "^>\\s*(.+)"],
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
function cloneJson(value) {
|
|
65
|
+
return JSON.parse(JSON.stringify(value));
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Load config with hierarchy: defaults → global (~/.aimux/config.json) → project (.aimux/config.json)
|
|
69
|
+
* Project settings override global, global overrides defaults.
|
|
70
|
+
*/
|
|
71
|
+
export function loadConfig() {
|
|
72
|
+
let config = cloneJson(DEFAULT_CONFIG);
|
|
73
|
+
// Layer 1: global config
|
|
74
|
+
const globalPath = getGlobalConfigPath();
|
|
75
|
+
if (existsSync(globalPath)) {
|
|
76
|
+
try {
|
|
77
|
+
const globalRaw = JSON.parse(readFileSync(globalPath, "utf-8"));
|
|
78
|
+
config = deepMerge(config, globalRaw);
|
|
79
|
+
}
|
|
80
|
+
catch { }
|
|
81
|
+
}
|
|
82
|
+
// Layer 2: project config
|
|
83
|
+
const projectPath = getConfigPath();
|
|
84
|
+
if (existsSync(projectPath)) {
|
|
85
|
+
try {
|
|
86
|
+
const projectRaw = JSON.parse(readFileSync(projectPath, "utf-8"));
|
|
87
|
+
config = deepMerge(config, projectRaw);
|
|
88
|
+
}
|
|
89
|
+
catch { }
|
|
90
|
+
}
|
|
91
|
+
return config;
|
|
92
|
+
}
|
|
93
|
+
/** Save config to project-level .aimux/config.json */
|
|
94
|
+
export function saveConfig(config) {
|
|
95
|
+
const dir = getLocalAimuxDir();
|
|
96
|
+
if (!existsSync(dir)) {
|
|
97
|
+
mkdirSync(dir, { recursive: true });
|
|
98
|
+
}
|
|
99
|
+
writeFileSync(getConfigPath(), JSON.stringify(config, null, 2) + "\n");
|
|
100
|
+
}
|
|
101
|
+
/** Save config to global ~/.aimux/config.json */
|
|
102
|
+
export function saveGlobalConfig(config) {
|
|
103
|
+
const dir = getGlobalAimuxDir();
|
|
104
|
+
if (!existsSync(dir)) {
|
|
105
|
+
mkdirSync(dir, { recursive: true });
|
|
106
|
+
}
|
|
107
|
+
writeFileSync(getGlobalConfigPath(), JSON.stringify(config, null, 2) + "\n");
|
|
108
|
+
}
|
|
109
|
+
const GITIGNORE_CONTENTS = `# Runtime-private session state (lives in ~/.aimux/projects/)
|
|
110
|
+
state.json
|
|
111
|
+
graveyard.json
|
|
112
|
+
sessions.json
|
|
113
|
+
instances.json
|
|
114
|
+
|
|
115
|
+
# Agent-facing shared artifacts
|
|
116
|
+
context/
|
|
117
|
+
history/
|
|
118
|
+
tasks/
|
|
119
|
+
status/
|
|
120
|
+
threads/
|
|
121
|
+
|
|
122
|
+
# Terminal recordings (large, machine-specific)
|
|
123
|
+
recordings/
|
|
124
|
+
|
|
125
|
+
# Agent plan files
|
|
126
|
+
plans/
|
|
127
|
+
|
|
128
|
+
# Managed git worktrees
|
|
129
|
+
worktrees/
|
|
130
|
+
|
|
131
|
+
`;
|
|
132
|
+
export function initProject() {
|
|
133
|
+
// In-repo directory (agent-facing shared contract + config/team)
|
|
134
|
+
const localDir = getLocalAimuxDir();
|
|
135
|
+
mkdirSync(localDir, { recursive: true });
|
|
136
|
+
for (const subdir of ["plans", "context", "history", "tasks", "status", "threads"]) {
|
|
137
|
+
mkdirSync(join(localDir, subdir), { recursive: true });
|
|
138
|
+
}
|
|
139
|
+
if (!existsSync(getConfigPath())) {
|
|
140
|
+
saveConfig(DEFAULT_CONFIG);
|
|
141
|
+
}
|
|
142
|
+
const gitignorePath = join(localDir, ".gitignore");
|
|
143
|
+
if (!existsSync(gitignorePath)) {
|
|
144
|
+
writeFileSync(gitignorePath, GITIGNORE_CONTENTS);
|
|
145
|
+
}
|
|
146
|
+
// Global runtime-private project state directory
|
|
147
|
+
const stateDir = getProjectStateDir();
|
|
148
|
+
for (const subdir of ["recordings"]) {
|
|
149
|
+
mkdirSync(join(stateDir, subdir), { recursive: true });
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/** Deep merge b into a (b values override a). Handles nested objects, not arrays. */
|
|
153
|
+
function deepMerge(a, b) {
|
|
154
|
+
const result = { ...a };
|
|
155
|
+
for (const key of Object.keys(b)) {
|
|
156
|
+
const aVal = a[key];
|
|
157
|
+
const bVal = b[key];
|
|
158
|
+
if (aVal &&
|
|
159
|
+
bVal &&
|
|
160
|
+
typeof aVal === "object" &&
|
|
161
|
+
typeof bVal === "object" &&
|
|
162
|
+
!Array.isArray(aVal) &&
|
|
163
|
+
!Array.isArray(bVal)) {
|
|
164
|
+
result[key] = deepMerge(aVal, bVal);
|
|
165
|
+
}
|
|
166
|
+
else if (bVal !== undefined) {
|
|
167
|
+
result[key] = bVal;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return result;
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface SummaryProvenance {
|
|
2
|
+
sessionId: string;
|
|
3
|
+
mode: "algorithmic" | "llm";
|
|
4
|
+
generatedAt: string;
|
|
5
|
+
turns: number;
|
|
6
|
+
firstTurnTs?: string;
|
|
7
|
+
lastTurnTs?: string;
|
|
8
|
+
historyDigest: string;
|
|
9
|
+
summaryBytes: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Algorithmic compaction: extract key signals from history and write per-session summaries.
|
|
13
|
+
* Each session gets its own context/{session-id}/summary.md.
|
|
14
|
+
*/
|
|
15
|
+
export declare function algorithmicCompact(sessionIds: string[]): void;
|
|
16
|
+
/**
|
|
17
|
+
* LLM-powered compaction: send each session's history to claude for summarization.
|
|
18
|
+
* Each session gets its own context/{session-id}/summary.md.
|
|
19
|
+
*/
|
|
20
|
+
export declare function llmCompact(sessionIds: string[]): void;
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync, appendFileSync } from "node:fs";
|
|
2
|
+
import { execSync } from "node:child_process";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { createHash } from "node:crypto";
|
|
5
|
+
import { loadConfig } from "../config.js";
|
|
6
|
+
import { getContextDir } from "../paths.js";
|
|
7
|
+
import { readHistory } from "./history.js";
|
|
8
|
+
const MAX_SUMMARY_BYTES = 30 * 1024;
|
|
9
|
+
const DECISION_KEYWORDS = /\b(decided|chose|instead|approach|switched to|went with)\b/i;
|
|
10
|
+
const ERROR_KEYWORDS = /\b(error|failed|blocked|issue|broken|crash|exception)\b/i;
|
|
11
|
+
function historyDigest(turns) {
|
|
12
|
+
const hash = createHash("sha1");
|
|
13
|
+
for (const turn of turns) {
|
|
14
|
+
hash.update(turn.ts);
|
|
15
|
+
hash.update("\0");
|
|
16
|
+
hash.update(turn.type);
|
|
17
|
+
hash.update("\0");
|
|
18
|
+
hash.update(turn.content);
|
|
19
|
+
hash.update("\0");
|
|
20
|
+
}
|
|
21
|
+
return hash.digest("hex");
|
|
22
|
+
}
|
|
23
|
+
function withSummaryHeader(summary, provenance) {
|
|
24
|
+
const lines = [
|
|
25
|
+
`# ${provenance.sessionId} — Session Summary`,
|
|
26
|
+
`Generated: ${provenance.generatedAt}`,
|
|
27
|
+
`Source: ${provenance.mode}`,
|
|
28
|
+
`Turns covered: ${provenance.turns}`,
|
|
29
|
+
];
|
|
30
|
+
if (provenance.firstTurnTs || provenance.lastTurnTs) {
|
|
31
|
+
lines.push(`History range: ${provenance.firstTurnTs ?? "unknown"} -> ${provenance.lastTurnTs ?? "unknown"}`);
|
|
32
|
+
}
|
|
33
|
+
lines.push(`History digest: ${provenance.historyDigest}`);
|
|
34
|
+
lines.push("");
|
|
35
|
+
return `${lines.join("\n")}${summary.trimStart() ? `\n${summary.trimStart()}` : ""}`;
|
|
36
|
+
}
|
|
37
|
+
function writeSummaryArtifacts(sessionDir, sessionId, mode, turns, summary) {
|
|
38
|
+
const generatedAt = new Date().toISOString();
|
|
39
|
+
const baseProvenance = {
|
|
40
|
+
sessionId,
|
|
41
|
+
mode,
|
|
42
|
+
generatedAt,
|
|
43
|
+
turns: turns.length,
|
|
44
|
+
firstTurnTs: turns[0]?.ts,
|
|
45
|
+
lastTurnTs: turns.at(-1)?.ts,
|
|
46
|
+
historyDigest: historyDigest(turns),
|
|
47
|
+
summaryBytes: 0,
|
|
48
|
+
};
|
|
49
|
+
const summaryWithHeader = withSummaryHeader(summary, baseProvenance);
|
|
50
|
+
const provenance = {
|
|
51
|
+
...baseProvenance,
|
|
52
|
+
summaryBytes: Buffer.byteLength(summaryWithHeader),
|
|
53
|
+
};
|
|
54
|
+
writeFileSync(join(sessionDir, "summary.md"), summaryWithHeader);
|
|
55
|
+
writeFileSync(join(sessionDir, "summary.meta.json"), JSON.stringify(provenance, null, 2) + "\n");
|
|
56
|
+
appendFileSync(join(sessionDir, "summary.checkpoints.jsonl"), JSON.stringify(provenance) + "\n");
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Algorithmic compaction: extract key signals from history and write per-session summaries.
|
|
60
|
+
* Each session gets its own context/{session-id}/summary.md.
|
|
61
|
+
*/
|
|
62
|
+
export function algorithmicCompact(sessionIds) {
|
|
63
|
+
const baseDir = getContextDir();
|
|
64
|
+
if (!existsSync(baseDir))
|
|
65
|
+
mkdirSync(baseDir, { recursive: true });
|
|
66
|
+
for (const sessionId of sessionIds) {
|
|
67
|
+
const turns = readHistory(sessionId);
|
|
68
|
+
if (turns.length === 0)
|
|
69
|
+
continue;
|
|
70
|
+
const sessionDir = join(baseDir, sessionId);
|
|
71
|
+
if (!existsSync(sessionDir))
|
|
72
|
+
mkdirSync(sessionDir, { recursive: true });
|
|
73
|
+
const sections = [];
|
|
74
|
+
const tasks = [];
|
|
75
|
+
const fileCounts = new Map();
|
|
76
|
+
const decisions = [];
|
|
77
|
+
const errors = [];
|
|
78
|
+
for (const turn of turns) {
|
|
79
|
+
if (turn.type === "prompt") {
|
|
80
|
+
tasks.push(turn.content);
|
|
81
|
+
}
|
|
82
|
+
if (turn.type === "response") {
|
|
83
|
+
for (const line of turn.content.split("\n")) {
|
|
84
|
+
const trimmed = line.trim();
|
|
85
|
+
if (!trimmed)
|
|
86
|
+
continue;
|
|
87
|
+
if (DECISION_KEYWORDS.test(trimmed)) {
|
|
88
|
+
decisions.push(trimmed);
|
|
89
|
+
}
|
|
90
|
+
if (ERROR_KEYWORDS.test(trimmed)) {
|
|
91
|
+
errors.push(trimmed);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (turn.files) {
|
|
96
|
+
for (const file of turn.files) {
|
|
97
|
+
fileCounts.set(file, (fileCounts.get(file) ?? 0) + 1);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
sections.push(`${turns.length} turns`);
|
|
102
|
+
sections.push("");
|
|
103
|
+
if (tasks.length > 0) {
|
|
104
|
+
sections.push("### Key tasks");
|
|
105
|
+
const uniqueTasks = [...new Set(tasks)];
|
|
106
|
+
for (const task of uniqueTasks.slice(-20)) {
|
|
107
|
+
sections.push(`- ${truncate(task, 150)}`);
|
|
108
|
+
}
|
|
109
|
+
sections.push("");
|
|
110
|
+
}
|
|
111
|
+
if (fileCounts.size > 0) {
|
|
112
|
+
sections.push("### Files modified");
|
|
113
|
+
const sorted = [...fileCounts.entries()].sort((a, b) => b[1] - a[1]);
|
|
114
|
+
for (const [file, count] of sorted) {
|
|
115
|
+
sections.push(`- ${file} (${count} time${count > 1 ? "s" : ""})`);
|
|
116
|
+
}
|
|
117
|
+
sections.push("");
|
|
118
|
+
}
|
|
119
|
+
if (decisions.length > 0) {
|
|
120
|
+
sections.push("### Key decisions");
|
|
121
|
+
for (const d of decisions.slice(-10)) {
|
|
122
|
+
sections.push(`- ${truncate(d, 200)}`);
|
|
123
|
+
}
|
|
124
|
+
sections.push("");
|
|
125
|
+
}
|
|
126
|
+
if (errors.length > 0) {
|
|
127
|
+
sections.push("### Errors & blockers");
|
|
128
|
+
for (const e of errors.slice(-10)) {
|
|
129
|
+
sections.push(`- ${truncate(e, 200)}`);
|
|
130
|
+
}
|
|
131
|
+
sections.push("");
|
|
132
|
+
}
|
|
133
|
+
let content = sections.join("\n");
|
|
134
|
+
// Enforce size limit
|
|
135
|
+
if (content.length > MAX_SUMMARY_BYTES) {
|
|
136
|
+
content = content.slice(0, MAX_SUMMARY_BYTES);
|
|
137
|
+
}
|
|
138
|
+
writeSummaryArtifacts(sessionDir, sessionId, "algorithmic", turns, content);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* LLM-powered compaction: send each session's history to claude for summarization.
|
|
143
|
+
* Each session gets its own context/{session-id}/summary.md.
|
|
144
|
+
*/
|
|
145
|
+
export function llmCompact(sessionIds) {
|
|
146
|
+
const baseDir = getContextDir();
|
|
147
|
+
if (!existsSync(baseDir))
|
|
148
|
+
mkdirSync(baseDir, { recursive: true });
|
|
149
|
+
for (const sessionId of sessionIds) {
|
|
150
|
+
const turns = readHistory(sessionId, { lastN: 200 });
|
|
151
|
+
if (turns.length === 0)
|
|
152
|
+
continue;
|
|
153
|
+
const sessionDir = join(baseDir, sessionId);
|
|
154
|
+
if (!existsSync(sessionDir))
|
|
155
|
+
mkdirSync(sessionDir, { recursive: true });
|
|
156
|
+
const historyParts = [];
|
|
157
|
+
historyParts.push(`=== Session: ${sessionId} (${turns.length} turns) ===`);
|
|
158
|
+
for (const turn of turns) {
|
|
159
|
+
const time = turn.ts.slice(11, 16);
|
|
160
|
+
if (turn.type === "prompt") {
|
|
161
|
+
historyParts.push(`[${time}] User: ${turn.content}`);
|
|
162
|
+
}
|
|
163
|
+
else if (turn.type === "response") {
|
|
164
|
+
historyParts.push(`[${time}] Agent: ${truncate(turn.content, 1000)}`);
|
|
165
|
+
if (turn.files && turn.files.length > 0) {
|
|
166
|
+
historyParts.push(` Files: ${turn.files.join(", ")}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
else if (turn.type === "git") {
|
|
170
|
+
historyParts.push(`[${time}] Git: ${turn.content}`);
|
|
171
|
+
if (turn.files) {
|
|
172
|
+
historyParts.push(` Files: ${turn.files.join(", ")}`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
const history = historyParts.join("\n");
|
|
177
|
+
if (!history.trim())
|
|
178
|
+
continue;
|
|
179
|
+
const prompt = "Summarize the following agent session history. " +
|
|
180
|
+
"List: key tasks completed, files modified, " +
|
|
181
|
+
"important decisions made, and any errors or blockers encountered. " +
|
|
182
|
+
"Be concise but thorough. Output markdown.\n\n" +
|
|
183
|
+
history;
|
|
184
|
+
try {
|
|
185
|
+
// Find compactCommand from any tool that has one configured
|
|
186
|
+
const config = loadConfig();
|
|
187
|
+
const compactCmd = Object.values(config.tools).find((t) => t.compactCommand)?.compactCommand ??
|
|
188
|
+
"claude --print --output-format text";
|
|
189
|
+
const output = execSync(compactCmd, {
|
|
190
|
+
input: prompt,
|
|
191
|
+
encoding: "utf-8",
|
|
192
|
+
timeout: 60_000,
|
|
193
|
+
maxBuffer: 1024 * 1024,
|
|
194
|
+
});
|
|
195
|
+
let summary = output;
|
|
196
|
+
if (summary.length > MAX_SUMMARY_BYTES) {
|
|
197
|
+
summary = summary.slice(0, MAX_SUMMARY_BYTES);
|
|
198
|
+
}
|
|
199
|
+
writeSummaryArtifacts(sessionDir, sessionId, "llm", turns, summary);
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
// If claude CLI fails for this session, fall back to algorithmic for just this session
|
|
203
|
+
algorithmicCompact([sessionId]);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function truncate(text, max) {
|
|
208
|
+
if (text.length <= max)
|
|
209
|
+
return text;
|
|
210
|
+
return text.slice(0, max) + "...";
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=compactor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compactor.js","sourceRoot":"","sources":["../../src/context/compactor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { type TmuxTarget } from "../tmux-runtime-manager.js";
|
|
2
|
+
/**
|
|
3
|
+
* Capture git diff and write a context entry on session exit.
|
|
4
|
+
*/
|
|
5
|
+
export declare function captureGitContext(sessionName: string, tool: string): Promise<void>;
|
|
6
|
+
/**
|
|
7
|
+
* Live context watcher. Tmux pane snapshots are the primary continuity source:
|
|
8
|
+
* they keep `live.md` current and backfill append-only history when a tool settles.
|
|
9
|
+
*
|
|
10
|
+
* Raw terminal recordings are kept as secondary audit/backfill artifacts only.
|
|
11
|
+
* They may yield extra turns when available, but continuity should not depend on
|
|
12
|
+
* recordings existing or parsing perfectly.
|
|
13
|
+
*/
|
|
14
|
+
export declare class ContextWatcher {
|
|
15
|
+
private readonly capturePane;
|
|
16
|
+
constructor(capturePane?: (target: TmuxTarget) => string);
|
|
17
|
+
private interval;
|
|
18
|
+
private sessions;
|
|
19
|
+
/** Track how far we've read into each session's secondary raw recording */
|
|
20
|
+
private readOffsets;
|
|
21
|
+
/** Track last turn type per session to detect response→prompt transitions */
|
|
22
|
+
private lastTurnTypes;
|
|
23
|
+
/** Hash of last git diff output for change detection */
|
|
24
|
+
private lastDiffHash;
|
|
25
|
+
/** Total turn count across all sessions, for compaction trigger */
|
|
26
|
+
private totalTurnCount;
|
|
27
|
+
/** Track which sessions have new turns since last write */
|
|
28
|
+
private dirtySessions;
|
|
29
|
+
/** Track last pane snapshot hash per session for tmux-backed live context. */
|
|
30
|
+
private paneSnapshotHashes;
|
|
31
|
+
private panePromptVisible;
|
|
32
|
+
updateSessions(sessions: Array<{
|
|
33
|
+
id: string;
|
|
34
|
+
command: string;
|
|
35
|
+
turnPatterns?: RegExp[];
|
|
36
|
+
tmuxTarget?: TmuxTarget;
|
|
37
|
+
}>): void;
|
|
38
|
+
start(intervalMs?: number): void;
|
|
39
|
+
stop(): void;
|
|
40
|
+
syncNow(sessionId?: string): Promise<void>;
|
|
41
|
+
private initOffset;
|
|
42
|
+
private recordingPath;
|
|
43
|
+
private tick;
|
|
44
|
+
/**
|
|
45
|
+
* Read new content from a session's raw recording since our last read offset.
|
|
46
|
+
* This is a secondary audit/backfill path; tmux pane capture is primary.
|
|
47
|
+
*/
|
|
48
|
+
private extractNewContent;
|
|
49
|
+
private capturePaneSnapshot;
|
|
50
|
+
/**
|
|
51
|
+
* Check for git changes and append a git turn to history if files changed.
|
|
52
|
+
*/
|
|
53
|
+
private captureGitDiff;
|
|
54
|
+
/**
|
|
55
|
+
* Write per-session live context from history JSONL files.
|
|
56
|
+
* Each session gets its own context/{session-id}/live.md.
|
|
57
|
+
*/
|
|
58
|
+
private writeLiveContext;
|
|
59
|
+
/**
|
|
60
|
+
* Build live.md content for a single session from its history.
|
|
61
|
+
*/
|
|
62
|
+
private buildSessionLiveContent;
|
|
63
|
+
}
|
|
64
|
+
/** Get recent stripped output from a session's raw recording as a fallback/debug aid. */
|
|
65
|
+
export declare function getRecentOutput(sessionId: string, maxLines?: number): string;
|
|
66
|
+
/** Build a context preamble for a new session from other sessions' per-session context files. */
|
|
67
|
+
export declare function buildContextPreamble(otherSessionIds: string[], maxLinesPerSession?: number): string;
|