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
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join, basename } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { getContextDir, getHistoryDir, getPlansDir, getStatusDir } from "./paths.js";
|
|
5
|
+
import { readHistory } from "./context/history.js";
|
|
6
|
+
import { debug, debugPreamble } from "./debug.js";
|
|
7
|
+
import { listWorktrees as listAllWorktrees } from "./worktree.js";
|
|
8
|
+
export class SessionBootstrapService {
|
|
9
|
+
deps;
|
|
10
|
+
constructor(deps) {
|
|
11
|
+
this.deps = deps;
|
|
12
|
+
}
|
|
13
|
+
buildSessionPreamble(opts) {
|
|
14
|
+
const { sessionId, worktreePath, extraPreamble } = opts;
|
|
15
|
+
let preamble = "You are running inside aimux, an agent multiplexer. " +
|
|
16
|
+
"Other agents may be working on this codebase simultaneously.\n" +
|
|
17
|
+
`Your session ID is ${sessionId}.\n` +
|
|
18
|
+
`- .aimux/context/${sessionId}/live.md — your recent conversation history\n` +
|
|
19
|
+
`- .aimux/context/${sessionId}/summary.md — your compacted history\n` +
|
|
20
|
+
`- .aimux/plans/${sessionId}.md — your shared working plan\n` +
|
|
21
|
+
"- .aimux/sessions.json — all running agents\n" +
|
|
22
|
+
"- Other agent contexts are in .aimux/context/{their-session-id}/. Check sessions.json for the list.\n" +
|
|
23
|
+
"- Other agent plans are in .aimux/plans/{their-session-id}.md.\n" +
|
|
24
|
+
"- .aimux/history/ — full raw conversation history (JSONL)";
|
|
25
|
+
const globalAimuxMd = join(homedir(), "AIMUX.md");
|
|
26
|
+
const projectAimuxMd = join(process.cwd(), "AIMUX.md");
|
|
27
|
+
for (const mdPath of [globalAimuxMd, projectAimuxMd]) {
|
|
28
|
+
if (!existsSync(mdPath))
|
|
29
|
+
continue;
|
|
30
|
+
try {
|
|
31
|
+
const userPreamble = readFileSync(mdPath, "utf-8").trim();
|
|
32
|
+
if (!userPreamble)
|
|
33
|
+
continue;
|
|
34
|
+
preamble += "\n\n" + userPreamble;
|
|
35
|
+
debug(`loaded ${mdPath} (${userPreamble.length} chars)`, "preamble");
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// Ignore unreadable user preamble files.
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (worktreePath) {
|
|
42
|
+
try {
|
|
43
|
+
const allWt = listAllWorktrees(worktreePath);
|
|
44
|
+
const thisWt = allWt.find((w) => w.path === worktreePath);
|
|
45
|
+
const mainWt = allWt[0];
|
|
46
|
+
const siblings = allWt
|
|
47
|
+
.filter((w) => w.path !== worktreePath)
|
|
48
|
+
.map((w) => `${w.name} (${w.branch})`)
|
|
49
|
+
.join(", ");
|
|
50
|
+
preamble +=
|
|
51
|
+
`\n\nYou are working in git worktree "${thisWt?.name ?? basename(worktreePath)}" at ${worktreePath} on branch "${thisWt?.branch ?? "unknown"}".` +
|
|
52
|
+
`\nMain repository: ${mainWt?.path ?? "unknown"}.` +
|
|
53
|
+
(siblings ? `\nSibling worktrees: ${siblings}` : "") +
|
|
54
|
+
"\nStay in your worktree directory.";
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
preamble += `\n\nYou are working in a git worktree at ${worktreePath}. Stay in this directory.`;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
preamble +=
|
|
61
|
+
"\n\n## Planning\n" +
|
|
62
|
+
"Maintain a plan file at .aimux/plans/" +
|
|
63
|
+
sessionId +
|
|
64
|
+
".md.\n" +
|
|
65
|
+
"Keep it current enough that other agents can audit, annotate, or continue your work.\n" +
|
|
66
|
+
"Use this structure:\n" +
|
|
67
|
+
"- Goal\n" +
|
|
68
|
+
"- Current Status\n" +
|
|
69
|
+
"- Steps\n" +
|
|
70
|
+
"- Notes\n" +
|
|
71
|
+
"Update it when your plan materially changes or when you complete a step.";
|
|
72
|
+
preamble +=
|
|
73
|
+
"\n\n## Status\n" +
|
|
74
|
+
"Maintain a status file at .aimux/status/" +
|
|
75
|
+
sessionId +
|
|
76
|
+
".md (3-5 lines max).\n" +
|
|
77
|
+
"Update it whenever your focus changes. Include:\n" +
|
|
78
|
+
"- What you're currently working on\n" +
|
|
79
|
+
"- Key files involved\n" +
|
|
80
|
+
"- Current state (investigating, implementing, testing, blocked, etc.)";
|
|
81
|
+
preamble +=
|
|
82
|
+
"\n\n## Aimux Cross-Agent Delegation\n" +
|
|
83
|
+
"IMPORTANT: This is the aimux delegation system for coordinating work across agents in this multiplexer. " +
|
|
84
|
+
"It is separate from any built-in task/todo features in your own tool.\n\n" +
|
|
85
|
+
"### Delegating work to another agent\n" +
|
|
86
|
+
"When asked to delegate, hand off, or assign work to another agent, create a JSON file:\n" +
|
|
87
|
+
"```\n" +
|
|
88
|
+
".aimux/tasks/{short-descriptive-name}.json\n" +
|
|
89
|
+
"```\n" +
|
|
90
|
+
"Contents:\n" +
|
|
91
|
+
"```json\n" +
|
|
92
|
+
'{\n "id": "{same as filename without .json}",\n "status": "pending",\n' +
|
|
93
|
+
' "assignedBy": "' +
|
|
94
|
+
sessionId +
|
|
95
|
+
'",\n' +
|
|
96
|
+
' "description": "Brief summary of the task",\n' +
|
|
97
|
+
' "prompt": "Detailed instructions for the other agent",\n' +
|
|
98
|
+
' "createdAt": "{ISO timestamp}",\n "updatedAt": "{ISO timestamp}"\n}\n' +
|
|
99
|
+
"```\n" +
|
|
100
|
+
"Optional fields: `assignedTo` (target session ID), `tool` (preferred tool type).\n" +
|
|
101
|
+
"Aimux will automatically dispatch pending tasks to idle agents and inject the prompt.\n" +
|
|
102
|
+
"Check .aimux/sessions.json for available agents and their session IDs.\n\n" +
|
|
103
|
+
"### Receiving a delegated task\n" +
|
|
104
|
+
"When you see `[AIMUX TASK ...]` in your input, another agent delegated work to you.\n" +
|
|
105
|
+
"Complete the work, then update the task file:\n" +
|
|
106
|
+
'- Success: set `status` to `"done"` and add a `result` field with a summary\n' +
|
|
107
|
+
'- Failure: set `status` to `"failed"` and add an `error` field\n' +
|
|
108
|
+
"The delegating agent will be notified automatically.";
|
|
109
|
+
if (extraPreamble) {
|
|
110
|
+
preamble += "\n" + extraPreamble;
|
|
111
|
+
}
|
|
112
|
+
return preamble;
|
|
113
|
+
}
|
|
114
|
+
ensurePlanFile(sessionId, command, worktreePath) {
|
|
115
|
+
try {
|
|
116
|
+
const plansDir = getPlansDir();
|
|
117
|
+
mkdirSync(plansDir, { recursive: true });
|
|
118
|
+
const planPath = join(plansDir, `${sessionId}.md`);
|
|
119
|
+
if (existsSync(planPath))
|
|
120
|
+
return;
|
|
121
|
+
const worktreeLabel = worktreePath ? worktreePath : "main";
|
|
122
|
+
const content = `---\n` +
|
|
123
|
+
`sessionId: ${sessionId}\n` +
|
|
124
|
+
`tool: ${command}\n` +
|
|
125
|
+
`worktree: ${worktreeLabel}\n` +
|
|
126
|
+
`updatedAt: ${new Date().toISOString()}\n` +
|
|
127
|
+
`---\n\n` +
|
|
128
|
+
`# Goal\n\n` +
|
|
129
|
+
`TBD\n\n` +
|
|
130
|
+
`# Current Status\n\n` +
|
|
131
|
+
`TBD\n\n` +
|
|
132
|
+
`# Steps\n\n` +
|
|
133
|
+
`- [ ] TBD\n\n` +
|
|
134
|
+
`# Notes\n\n` +
|
|
135
|
+
`- None yet.\n`;
|
|
136
|
+
writeFileSync(planPath, content);
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
// Keep session creation resilient even if plan file creation fails.
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
composeToolArgs(toolCfg, actionArgs, savedArgs = []) {
|
|
143
|
+
const baseArgs = [...(toolCfg.args ?? [])];
|
|
144
|
+
const trailingArgs = baseArgs.length > 0 && savedArgs.length >= baseArgs.length && baseArgs.every((arg, idx) => savedArgs[idx] === arg)
|
|
145
|
+
? savedArgs.slice(baseArgs.length)
|
|
146
|
+
: [...savedArgs];
|
|
147
|
+
return [...baseArgs, ...actionArgs, ...trailingArgs];
|
|
148
|
+
}
|
|
149
|
+
canResumeWithBackendSessionId(toolCfg, backendSessionId) {
|
|
150
|
+
return Boolean(backendSessionId && toolCfg?.resumeArgs && toolCfg.resumeByBackendSessionId !== false);
|
|
151
|
+
}
|
|
152
|
+
readForkSourceSnapshot(sourceSessionId) {
|
|
153
|
+
const historyTurns = readHistory(sourceSessionId, { lastN: 20 });
|
|
154
|
+
const historyText = historyTurns.length > 0
|
|
155
|
+
? historyTurns
|
|
156
|
+
.map((turn) => {
|
|
157
|
+
const prefix = turn.type === "prompt"
|
|
158
|
+
? "User"
|
|
159
|
+
: turn.type === "response"
|
|
160
|
+
? "Agent"
|
|
161
|
+
: turn.type === "git"
|
|
162
|
+
? "Git"
|
|
163
|
+
: "Note";
|
|
164
|
+
return `- ${prefix}: ${turn.content}`;
|
|
165
|
+
})
|
|
166
|
+
.join("\n")
|
|
167
|
+
: undefined;
|
|
168
|
+
let liveText = "";
|
|
169
|
+
const sourceTarget = this.deps.getSessionTmuxTarget(sourceSessionId);
|
|
170
|
+
if (sourceTarget) {
|
|
171
|
+
try {
|
|
172
|
+
liveText = this.deps.tmuxRuntimeManager.captureTarget(sourceTarget, { startLine: -160 }).trim();
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
// Fall back to live.md.
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (!liveText) {
|
|
179
|
+
const sourceLivePath = join(getContextDir(), sourceSessionId, "live.md");
|
|
180
|
+
try {
|
|
181
|
+
if (existsSync(sourceLivePath)) {
|
|
182
|
+
liveText = readFileSync(sourceLivePath, "utf-8").trim();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
// Ignore unreadable live context.
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
const sourcePlanPath = join(getPlansDir(), `${sourceSessionId}.md`);
|
|
190
|
+
let planText = "";
|
|
191
|
+
try {
|
|
192
|
+
if (existsSync(sourcePlanPath)) {
|
|
193
|
+
const raw = readFileSync(sourcePlanPath, "utf-8")
|
|
194
|
+
.replace(/^---\n[\s\S]*?\n---\n?/, "")
|
|
195
|
+
.trim();
|
|
196
|
+
if (raw && !this.isDefaultPlanContent(raw)) {
|
|
197
|
+
planText = raw;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
// Ignore unreadable plan files.
|
|
203
|
+
}
|
|
204
|
+
const sourceStatusPath = join(getStatusDir(), `${sourceSessionId}.md`);
|
|
205
|
+
let statusText = "";
|
|
206
|
+
try {
|
|
207
|
+
if (existsSync(sourceStatusPath)) {
|
|
208
|
+
statusText = readFileSync(sourceStatusPath, "utf-8").trim();
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
// Ignore unreadable status files.
|
|
213
|
+
}
|
|
214
|
+
return {
|
|
215
|
+
historyText: historyText || undefined,
|
|
216
|
+
liveText: liveText || undefined,
|
|
217
|
+
planText: planText || undefined,
|
|
218
|
+
statusText: statusText || undefined,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
summarizeForkSourceActivity(snapshot) {
|
|
222
|
+
if (snapshot.statusText?.trim()) {
|
|
223
|
+
return snapshot.statusText.trim();
|
|
224
|
+
}
|
|
225
|
+
const source = snapshot.historyText || snapshot.liveText;
|
|
226
|
+
if (!source)
|
|
227
|
+
return undefined;
|
|
228
|
+
const lines = source
|
|
229
|
+
.split("\n")
|
|
230
|
+
.map((line) => line.replace(/\s+/g, " ").trim())
|
|
231
|
+
.filter(Boolean)
|
|
232
|
+
.filter((line) => !line.startsWith("# ") &&
|
|
233
|
+
!line.startsWith("Updated:") &&
|
|
234
|
+
!line.startsWith("Recent terminal output:") &&
|
|
235
|
+
!line.includes("gpt-5.4 medium") &&
|
|
236
|
+
!line.includes("Opus 4.6") &&
|
|
237
|
+
!line.startsWith("sam@") &&
|
|
238
|
+
!line.startsWith("▐") &&
|
|
239
|
+
!line.startsWith("▝") &&
|
|
240
|
+
!line.startsWith("⏵⏵"));
|
|
241
|
+
const tail = lines.slice(-8);
|
|
242
|
+
if (tail.length === 0)
|
|
243
|
+
return undefined;
|
|
244
|
+
return tail.join(" ").slice(0, 500);
|
|
245
|
+
}
|
|
246
|
+
buildForkPreamble(sourceSessionId, targetSessionId) {
|
|
247
|
+
const sourceLabel = this.deps.getSessionLabel(sourceSessionId) ?? sourceSessionId;
|
|
248
|
+
const sourceRole = this.deps.getSessionRole(sourceSessionId);
|
|
249
|
+
const sourceWorktree = this.deps.getSessionWorktreePath(sourceSessionId);
|
|
250
|
+
const snapshot = this.readForkSourceSnapshot(sourceSessionId);
|
|
251
|
+
const activitySummary = this.summarizeForkSourceActivity(snapshot);
|
|
252
|
+
return [
|
|
253
|
+
"## Aimux Handoff",
|
|
254
|
+
`You are a fork of ${sourceLabel}${sourceRole ? ` (${sourceRole})` : ""}.`,
|
|
255
|
+
`Your new session ID is ${targetSessionId}.`,
|
|
256
|
+
sourceWorktree ? `Source worktree: ${sourceWorktree}` : undefined,
|
|
257
|
+
"",
|
|
258
|
+
"Continue the same line of work using the source agent's carried-over context below.",
|
|
259
|
+
"You are independent now, but should preserve continuity and build on the source agent's progress.",
|
|
260
|
+
"Treat the provided summary, history, and live snapshot as prior context you already know.",
|
|
261
|
+
"Do not describe yourself as a fresh session if any carried-over context is present.",
|
|
262
|
+
"A blank source plan does not mean there was no prior work or interaction.",
|
|
263
|
+
activitySummary ? `\n### Recent Activity Summary\n${activitySummary}` : undefined,
|
|
264
|
+
snapshot.planText ? `\n### Source Plan\n${snapshot.planText}` : undefined,
|
|
265
|
+
snapshot.historyText ? `\n### Recent History\n${snapshot.historyText}` : undefined,
|
|
266
|
+
snapshot.liveText ? `\n### Live Terminal Snapshot\n${snapshot.liveText}` : undefined,
|
|
267
|
+
]
|
|
268
|
+
.filter(Boolean)
|
|
269
|
+
.join("\n");
|
|
270
|
+
}
|
|
271
|
+
buildForkKickoffPrompt(sourceSessionId, targetSessionId, snapshot, instruction) {
|
|
272
|
+
const activitySummary = this.summarizeForkSourceActivity(snapshot);
|
|
273
|
+
return [
|
|
274
|
+
`This session is a fork of ${sourceSessionId}.`,
|
|
275
|
+
`Read .aimux/context/${targetSessionId}/summary.md, .aimux/context/${targetSessionId}/live.md, and .aimux/plans/${targetSessionId}.md first.`,
|
|
276
|
+
"Treat them as real carried-over memory, not fresh-session scaffolding.",
|
|
277
|
+
"Do not start with git archaeology.",
|
|
278
|
+
activitySummary ? `Recent source activity: ${activitySummary}` : undefined,
|
|
279
|
+
instruction?.trim() ? `Instruction: ${instruction.trim()}` : undefined,
|
|
280
|
+
"After reading them, briefly summarize what we were doing and continue from that context.",
|
|
281
|
+
]
|
|
282
|
+
.filter(Boolean)
|
|
283
|
+
.join(" ");
|
|
284
|
+
}
|
|
285
|
+
seedForkArtifacts(sourceSessionId, targetSessionId, targetToolConfigKey) {
|
|
286
|
+
const snapshot = this.readForkSourceSnapshot(sourceSessionId);
|
|
287
|
+
const activitySummary = this.summarizeForkSourceActivity(snapshot);
|
|
288
|
+
const sourceHistoryPath = join(getHistoryDir(), `${sourceSessionId}.jsonl`);
|
|
289
|
+
const targetHistoryPath = join(getHistoryDir(), `${targetSessionId}.jsonl`);
|
|
290
|
+
if (existsSync(sourceHistoryPath) && !existsSync(targetHistoryPath)) {
|
|
291
|
+
copyFileSync(sourceHistoryPath, targetHistoryPath);
|
|
292
|
+
}
|
|
293
|
+
const targetContextDir = join(getContextDir(), targetSessionId);
|
|
294
|
+
mkdirSync(targetContextDir, { recursive: true });
|
|
295
|
+
const sourceStatusPath = join(getStatusDir(), `${sourceSessionId}.md`);
|
|
296
|
+
const targetStatusPath = join(getStatusDir(), `${targetSessionId}.md`);
|
|
297
|
+
if (existsSync(sourceStatusPath) && !existsSync(targetStatusPath)) {
|
|
298
|
+
copyFileSync(sourceStatusPath, targetStatusPath);
|
|
299
|
+
}
|
|
300
|
+
else if (!existsSync(targetStatusPath) && snapshot.statusText) {
|
|
301
|
+
writeFileSync(targetStatusPath, snapshot.statusText + "\n");
|
|
302
|
+
}
|
|
303
|
+
const targetPlanPath = join(getPlansDir(), `${targetSessionId}.md`);
|
|
304
|
+
const targetWorktree = this.deps.getSessionWorktreePath(sourceSessionId) ?? "main";
|
|
305
|
+
const handoffPlan = `---\n` +
|
|
306
|
+
`sessionId: ${targetSessionId}\n` +
|
|
307
|
+
`tool: ${targetToolConfigKey}\n` +
|
|
308
|
+
`worktree: ${targetWorktree}\n` +
|
|
309
|
+
`updatedAt: ${new Date().toISOString()}\n` +
|
|
310
|
+
`---\n\n` +
|
|
311
|
+
`# Goal\n\n` +
|
|
312
|
+
`${snapshot.planText ? "Continue the forked work described below." : `Continue work forked from ${sourceSessionId}.`}\n\n` +
|
|
313
|
+
`# Current Status\n\n` +
|
|
314
|
+
`${snapshot.statusText || activitySummary || "Forked from an existing agent with carried-over context."}\n\n` +
|
|
315
|
+
`# Steps\n\n` +
|
|
316
|
+
`- [ ] Review .aimux/context/${targetSessionId}/summary.md and live.md\n` +
|
|
317
|
+
`- [ ] Continue the forked line of work\n\n` +
|
|
318
|
+
`# Notes\n\n` +
|
|
319
|
+
`- Forked from ${sourceSessionId}\n` +
|
|
320
|
+
(activitySummary ? `- Recent carried-over activity: ${activitySummary}\n` : "") +
|
|
321
|
+
(snapshot.planText ? `- Source plan carried below\n\n## Source Plan\n\n${snapshot.planText}\n` : "");
|
|
322
|
+
writeFileSync(targetPlanPath, handoffPlan);
|
|
323
|
+
const targetLivePath = join(targetContextDir, "live.md");
|
|
324
|
+
if (snapshot.liveText) {
|
|
325
|
+
writeFileSync(targetLivePath, snapshot.liveText + "\n");
|
|
326
|
+
}
|
|
327
|
+
const targetSummaryPath = join(targetContextDir, "summary.md");
|
|
328
|
+
writeFileSync(targetSummaryPath, [
|
|
329
|
+
`# Forked from ${sourceSessionId}`,
|
|
330
|
+
"",
|
|
331
|
+
`Target session: ${targetSessionId}`,
|
|
332
|
+
"",
|
|
333
|
+
"Treat this file as carried-over prior context from the source session.",
|
|
334
|
+
"Do not describe yourself as a fresh session if this file contains prior interaction.",
|
|
335
|
+
"A blank source plan does not mean there was no prior context.",
|
|
336
|
+
"",
|
|
337
|
+
snapshot.statusText ? `## Source Status\n\n${snapshot.statusText}\n` : "",
|
|
338
|
+
activitySummary ? `## Recent Activity Summary\n\n${activitySummary}\n` : "",
|
|
339
|
+
snapshot.planText ? `## Source Plan\n\n${snapshot.planText}\n` : "",
|
|
340
|
+
snapshot.historyText ? `## Recent History\n\n${snapshot.historyText}\n` : "",
|
|
341
|
+
snapshot.liveText ? `## Live Terminal Snapshot\n\n${snapshot.liveText}\n` : "",
|
|
342
|
+
]
|
|
343
|
+
.filter(Boolean)
|
|
344
|
+
.join("\n"));
|
|
345
|
+
}
|
|
346
|
+
waitForCodexKickoffSubmit(targetSessionId, target, kickoff) {
|
|
347
|
+
const startedAt = Date.now();
|
|
348
|
+
return new Promise((resolve) => {
|
|
349
|
+
const step = (attempt = 1, lastFingerprint = "") => {
|
|
350
|
+
if (Date.now() - startedAt > 12000 || attempt > 12) {
|
|
351
|
+
debug(`fork kickoff submit: target=${targetSessionId} timeout`, "fork");
|
|
352
|
+
resolve(false);
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
setTimeout(() => {
|
|
356
|
+
try {
|
|
357
|
+
const currentTarget = this.deps.getSessionTmuxTarget(targetSessionId);
|
|
358
|
+
if (!currentTarget || currentTarget.windowId !== target.windowId) {
|
|
359
|
+
debug(`fork kickoff submit: target=${targetSessionId} no longer active`, "fork");
|
|
360
|
+
resolve(false);
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
const stillDraft = this.paneStillContainsDraft(target, kickoff);
|
|
364
|
+
const fingerprint = this.capturePaneFingerprint(target);
|
|
365
|
+
const settled = stillDraft && fingerprint.length > 0 && fingerprint === lastFingerprint;
|
|
366
|
+
debug(`fork kickoff submit: target=${targetSessionId} attempt=${attempt} stillDraft=${stillDraft ? "yes" : "no"} settled=${settled ? "yes" : "no"} mode=Enter`, "fork");
|
|
367
|
+
if (!stillDraft && attempt > 1) {
|
|
368
|
+
resolve(true);
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
if (!settled) {
|
|
372
|
+
step(attempt, fingerprint);
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
const client = this.deps.tmuxRuntimeManager.getAttachedClientForTarget(target);
|
|
376
|
+
if (client) {
|
|
377
|
+
this.deps.tmuxRuntimeManager.switchClientToTarget(client.tty, target);
|
|
378
|
+
this.deps.tmuxRuntimeManager.sendClientCarriageReturn(client.tty, target);
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
this.deps.tmuxRuntimeManager.sendEnter(target);
|
|
382
|
+
}
|
|
383
|
+
step(attempt + 1, "");
|
|
384
|
+
}
|
|
385
|
+
catch {
|
|
386
|
+
resolve(false);
|
|
387
|
+
}
|
|
388
|
+
}, attempt === 1 ? 1200 : 700);
|
|
389
|
+
};
|
|
390
|
+
step();
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
finalizePreamble(command, preamble) {
|
|
394
|
+
debugPreamble(command, Buffer.byteLength(preamble));
|
|
395
|
+
}
|
|
396
|
+
isDefaultPlanContent(content) {
|
|
397
|
+
const normalized = content.replace(/\r/g, "").trim();
|
|
398
|
+
return (normalized.includes("# Goal\n\nTBD") &&
|
|
399
|
+
normalized.includes("# Current Status\n\nTBD") &&
|
|
400
|
+
normalized.includes("# Steps\n\n- [ ] TBD"));
|
|
401
|
+
}
|
|
402
|
+
paneStillContainsDraft(target, draft) {
|
|
403
|
+
try {
|
|
404
|
+
const pane = this.deps.tmuxRuntimeManager.captureTarget(target, { startLine: -60 });
|
|
405
|
+
const normalize = (value) => value.replace(/\s+/g, " ").trim().toLowerCase();
|
|
406
|
+
const normalizedPane = normalize(pane);
|
|
407
|
+
const expectedFragments = [
|
|
408
|
+
"this session is a fork of",
|
|
409
|
+
"treat them as real carried-over memory",
|
|
410
|
+
"after reading them, briefly summarize",
|
|
411
|
+
].filter((fragment) => normalize(draft).includes(fragment));
|
|
412
|
+
if (expectedFragments.length === 0)
|
|
413
|
+
return false;
|
|
414
|
+
return expectedFragments.every((fragment) => normalizedPane.includes(fragment));
|
|
415
|
+
}
|
|
416
|
+
catch {
|
|
417
|
+
return false;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
capturePaneFingerprint(target) {
|
|
421
|
+
try {
|
|
422
|
+
const pane = this.deps.tmuxRuntimeManager.captureTarget(target, { startLine: -80 });
|
|
423
|
+
return pane.replace(/\s+/g, " ").trim().slice(-800);
|
|
424
|
+
}
|
|
425
|
+
catch {
|
|
426
|
+
return "";
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
export function getToolResumeArgs(toolCfg, backendSessionId) {
|
|
431
|
+
if (!backendSessionId || !toolCfg?.resumeArgs || toolCfg.resumeByBackendSessionId === false) {
|
|
432
|
+
return undefined;
|
|
433
|
+
}
|
|
434
|
+
return toolCfg.resumeArgs.map((arg) => arg.replace("{sessionId}", backendSessionId));
|
|
435
|
+
}
|
|
436
|
+
//# sourceMappingURL=session-bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-bootstrap.js","sourceRoot":"","sources":["../src/session-bootstrap.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { AgentInputPart } from "./agent-message-parts.js";
|
|
2
|
+
export interface SessionMessagePart {
|
|
3
|
+
type: "text" | "image";
|
|
4
|
+
text?: string;
|
|
5
|
+
attachmentId?: string;
|
|
6
|
+
alt?: string;
|
|
7
|
+
filename?: string;
|
|
8
|
+
mimeType?: string;
|
|
9
|
+
contentUrl?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface SessionMessageRecord {
|
|
12
|
+
id: string;
|
|
13
|
+
clientMessageId?: string;
|
|
14
|
+
sessionId: string;
|
|
15
|
+
role: "user";
|
|
16
|
+
ts: string;
|
|
17
|
+
parts: SessionMessagePart[];
|
|
18
|
+
}
|
|
19
|
+
export declare function appendSessionMessage(sessionId: string, input: {
|
|
20
|
+
data?: string;
|
|
21
|
+
parts?: AgentInputPart[];
|
|
22
|
+
clientMessageId?: string;
|
|
23
|
+
}): SessionMessageRecord | null;
|
|
24
|
+
export declare function readSessionMessages(sessionId: string, opts?: {
|
|
25
|
+
lastN?: number;
|
|
26
|
+
maxBytes?: number;
|
|
27
|
+
}): SessionMessageRecord[];
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync, statSync, openSync, readSync, closeSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
import { getSessionMessagesDir } from "./paths.js";
|
|
5
|
+
import { getAttachment } from "./attachment-store.js";
|
|
6
|
+
function historyPath(sessionId) {
|
|
7
|
+
return join(getSessionMessagesDir(), `${sessionId}.jsonl`);
|
|
8
|
+
}
|
|
9
|
+
export function appendSessionMessage(sessionId, input) {
|
|
10
|
+
const parts = normalizeMessageParts(input);
|
|
11
|
+
if (parts.length === 0)
|
|
12
|
+
return null;
|
|
13
|
+
const dir = getSessionMessagesDir();
|
|
14
|
+
if (!existsSync(dir)) {
|
|
15
|
+
mkdirSync(dir, { recursive: true });
|
|
16
|
+
}
|
|
17
|
+
const record = {
|
|
18
|
+
id: `msg_${randomUUID()}`,
|
|
19
|
+
clientMessageId: input.clientMessageId?.trim() || undefined,
|
|
20
|
+
sessionId,
|
|
21
|
+
role: "user",
|
|
22
|
+
ts: new Date().toISOString(),
|
|
23
|
+
parts,
|
|
24
|
+
};
|
|
25
|
+
appendFileSync(historyPath(sessionId), `${JSON.stringify(record)}\n`);
|
|
26
|
+
return record;
|
|
27
|
+
}
|
|
28
|
+
export function readSessionMessages(sessionId, opts) {
|
|
29
|
+
const filePath = historyPath(sessionId);
|
|
30
|
+
if (!existsSync(filePath))
|
|
31
|
+
return [];
|
|
32
|
+
const maxBytes = opts?.maxBytes ?? 100 * 1024;
|
|
33
|
+
let raw;
|
|
34
|
+
try {
|
|
35
|
+
const size = statSync(filePath).size;
|
|
36
|
+
if (size <= maxBytes) {
|
|
37
|
+
raw = readFileSync(filePath, "utf-8");
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
const buf = Buffer.alloc(maxBytes);
|
|
41
|
+
const fd = openSync(filePath, "r");
|
|
42
|
+
try {
|
|
43
|
+
readSync(fd, buf, 0, maxBytes, size - maxBytes);
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
closeSync(fd);
|
|
47
|
+
}
|
|
48
|
+
raw = buf.toString("utf-8");
|
|
49
|
+
const firstNewline = raw.indexOf("\n");
|
|
50
|
+
if (firstNewline !== -1) {
|
|
51
|
+
raw = raw.slice(firstNewline + 1);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
let records = raw
|
|
59
|
+
.split("\n")
|
|
60
|
+
.map((line) => line.trim())
|
|
61
|
+
.filter(Boolean)
|
|
62
|
+
.flatMap((line) => {
|
|
63
|
+
try {
|
|
64
|
+
return [JSON.parse(line)];
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
if (opts?.lastN !== undefined && records.length > opts.lastN) {
|
|
71
|
+
records = records.slice(-opts.lastN);
|
|
72
|
+
}
|
|
73
|
+
return records;
|
|
74
|
+
}
|
|
75
|
+
function normalizeMessageParts(input) {
|
|
76
|
+
const parts = Array.isArray(input.parts) ? input.parts : [];
|
|
77
|
+
if (parts.length === 0) {
|
|
78
|
+
const text = String(input.data ?? "");
|
|
79
|
+
return text.trim() ? [{ type: "text", text }] : [];
|
|
80
|
+
}
|
|
81
|
+
const normalized = [];
|
|
82
|
+
for (const part of parts) {
|
|
83
|
+
if (part.type === "text") {
|
|
84
|
+
const text = String(part.text ?? "");
|
|
85
|
+
if (text.trim()) {
|
|
86
|
+
normalized.push({ type: "text", text });
|
|
87
|
+
}
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
const attachmentId = part.attachmentId?.trim();
|
|
91
|
+
if (!attachmentId)
|
|
92
|
+
continue;
|
|
93
|
+
const attachment = getAttachment(attachmentId);
|
|
94
|
+
normalized.push({
|
|
95
|
+
type: "image",
|
|
96
|
+
attachmentId,
|
|
97
|
+
alt: part.alt?.trim() || undefined,
|
|
98
|
+
filename: attachment?.filename,
|
|
99
|
+
mimeType: attachment?.mimeType,
|
|
100
|
+
contentUrl: attachment?.contentUrl,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
return normalized;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=session-message-history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-message-history.js","sourceRoot":"","sources":["../src/session-message-history.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACvH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEnD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAqBtD,SAAS,WAAW,CAAC,SAAiB;IACpC,OAAO,IAAI,CAAC,qBAAqB,EAAE,EAAE,GAAG,SAAS,QAAQ,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,SAAiB,EACjB,KAIC;IAED,MAAM,KAAK,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAC3C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,MAAM,GAAG,GAAG,qBAAqB,EAAE,CAAC;IACpC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACrB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,CAAC;IACD,MAAM,MAAM,GAAyB;QACnC,EAAE,EAAE,OAAO,UAAU,EAAE,EAAE;QACzB,eAAe,EAAE,KAAK,CAAC,eAAe,EAAE,IAAI,EAAE,IAAI,SAAS;QAC3D,SAAS;QACT,IAAI,EAAE,MAAM;QACZ,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QAC5B,KAAK;KACN,CAAC;IACF,cAAc,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACtE,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,SAAiB,EACjB,IAA4C;IAE5C,MAAM,QAAQ,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;IACxC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,CAAC;IACrC,MAAM,QAAQ,GAAG,IAAI,EAAE,QAAQ,IAAI,GAAG,GAAG,IAAI,CAAC;IAE9C,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC;QACrC,IAAI,IAAI,IAAI,QAAQ,EAAE,CAAC;YACrB,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACxC,CAAC;aAAM,CAAC;YACN,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YACnC,MAAM,EAAE,GAAG,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YACnC,IAAI,CAAC;gBACH,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,GAAG,QAAQ,CAAC,CAAC;YAClD,CAAC;oBAAS,CAAC;gBACT,SAAS,CAAC,EAAE,CAAC,CAAC;YAChB,CAAC;YACD,GAAG,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC5B,MAAM,YAAY,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACvC,IAAI,YAAY,KAAK,CAAC,CAAC,EAAE,CAAC;gBACxB,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,OAAO,GAAG,GAAG;SACd,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,OAAO,CAAC;SACf,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QAChB,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAyB,CAAC,CAAC;QACpD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,IAAI,IAAI,EAAE,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;QAC7D,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAkD;IAC/E,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QACtC,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACrD,CAAC;IAED,MAAM,UAAU,GAAyB,EAAE,CAAC;IAC5C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACzB,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;YACrC,IAAI,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;gBAChB,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YAC1C,CAAC;YACD,SAAS;QACX,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC;QAC/C,IAAI,CAAC,YAAY;YAAE,SAAS;QAC5B,MAAM,UAAU,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC;QAC/C,UAAU,CAAC,IAAI,CAAC;YACd,IAAI,EAAE,OAAO;YACb,YAAY;YACZ,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,SAAS;YAClC,QAAQ,EAAE,UAAU,EAAE,QAAQ;YAC9B,QAAQ,EAAE,UAAU,EAAE,QAAQ;YAC9B,UAAU,EAAE,UAAU,EAAE,UAAU;SACnC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { SessionStatus } from "./status-detector.js";
|
|
2
|
+
export interface SessionTransport {
|
|
3
|
+
id: string;
|
|
4
|
+
command: string;
|
|
5
|
+
backendSessionId?: string;
|
|
6
|
+
readonly exited: boolean;
|
|
7
|
+
readonly exitCode: number | undefined;
|
|
8
|
+
readonly status: SessionStatus;
|
|
9
|
+
write(data: string): void;
|
|
10
|
+
resize(cols: number, rows: number): void;
|
|
11
|
+
onData(cb: (data: string) => void): void;
|
|
12
|
+
onExit(cb: (code: number) => void): void;
|
|
13
|
+
kill(): void;
|
|
14
|
+
destroy(): void;
|
|
15
|
+
}
|
|
16
|
+
export interface SessionRuntimeHooks {
|
|
17
|
+
onEvent?: (event: SessionRuntimeEvent) => void;
|
|
18
|
+
}
|
|
19
|
+
export type SessionRuntimeEvent = {
|
|
20
|
+
type: "output";
|
|
21
|
+
data: string;
|
|
22
|
+
} | {
|
|
23
|
+
type: "exit";
|
|
24
|
+
code: number;
|
|
25
|
+
};
|
|
26
|
+
export declare class SessionRuntime {
|
|
27
|
+
readonly transport: SessionTransport;
|
|
28
|
+
private hooks;
|
|
29
|
+
private readonly startedAt?;
|
|
30
|
+
constructor(transport: SessionTransport, startTime: number | undefined, hooks?: SessionRuntimeHooks);
|
|
31
|
+
get id(): string;
|
|
32
|
+
get command(): string;
|
|
33
|
+
get backendSessionId(): string | undefined;
|
|
34
|
+
set backendSessionId(value: string | undefined);
|
|
35
|
+
get exited(): boolean;
|
|
36
|
+
get exitCode(): number | undefined;
|
|
37
|
+
get status(): SessionStatus;
|
|
38
|
+
get startTime(): number | undefined;
|
|
39
|
+
write(data: string): void;
|
|
40
|
+
resize(cols: number, rows: number): void;
|
|
41
|
+
onExit(cb: (code: number) => void): void;
|
|
42
|
+
kill(): void;
|
|
43
|
+
destroy(): void;
|
|
44
|
+
}
|