claude-symphony 0.2.8 → 0.2.10
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/cli/index.js
CHANGED
|
@@ -1532,7 +1532,7 @@ import { fileURLToPath as fileURLToPath2 } from "url";
|
|
|
1532
1532
|
import os from "os";
|
|
1533
1533
|
import path5 from "path";
|
|
1534
1534
|
import { existsSync as existsSync3 } from "fs";
|
|
1535
|
-
var
|
|
1535
|
+
var SESSION_PREFIX = "symphony-session";
|
|
1536
1536
|
var DEFAULT_RELAY_DIR = path5.join(os.homedir(), ".claude/memory-relay");
|
|
1537
1537
|
var cachedConfig = null;
|
|
1538
1538
|
function resolveBaseDir(scriptDir) {
|
|
@@ -1595,7 +1595,7 @@ async function checkDependencies2() {
|
|
|
1595
1595
|
const [tmux, claude] = await Promise.all([commandExists("tmux"), commandExists("claude")]);
|
|
1596
1596
|
return { tmux, claude };
|
|
1597
1597
|
}
|
|
1598
|
-
function sessionExists(sessionName =
|
|
1598
|
+
function sessionExists(sessionName = SESSION_PREFIX) {
|
|
1599
1599
|
try {
|
|
1600
1600
|
execSync(`tmux has-session -t "${sessionName}" 2>/dev/null`, { stdio: "pipe" });
|
|
1601
1601
|
return true;
|
|
@@ -1603,31 +1603,43 @@ function sessionExists(sessionName = SESSION_NAME) {
|
|
|
1603
1603
|
return false;
|
|
1604
1604
|
}
|
|
1605
1605
|
}
|
|
1606
|
-
|
|
1606
|
+
function findNextAvailableSessionName() {
|
|
1607
|
+
if (!sessionExists(SESSION_PREFIX)) {
|
|
1608
|
+
return SESSION_PREFIX;
|
|
1609
|
+
}
|
|
1610
|
+
let n = 2;
|
|
1611
|
+
while (sessionExists(`${SESSION_PREFIX}-${n}`)) {
|
|
1612
|
+
n++;
|
|
1613
|
+
}
|
|
1614
|
+
return `${SESSION_PREFIX}-${n}`;
|
|
1615
|
+
}
|
|
1616
|
+
async function handleExistingSession(sessionName = SESSION_PREFIX) {
|
|
1607
1617
|
console.log(chalk5.yellow(`Session '${sessionName}' already exists.`));
|
|
1608
1618
|
console.log("");
|
|
1619
|
+
const nextName = findNextAvailableSessionName();
|
|
1609
1620
|
const choice = await select2({
|
|
1610
1621
|
message: "What would you like to do?",
|
|
1611
1622
|
choices: [
|
|
1612
1623
|
{ name: "Attach to existing session", value: "attach" },
|
|
1624
|
+
{ name: `Create new session (${nextName})`, value: "new" },
|
|
1613
1625
|
{ name: "Kill and recreate", value: "recreate" },
|
|
1614
1626
|
{ name: "Cancel", value: "cancel" }
|
|
1615
1627
|
]
|
|
1616
1628
|
});
|
|
1617
1629
|
return choice;
|
|
1618
1630
|
}
|
|
1619
|
-
function killSession(sessionName =
|
|
1631
|
+
function killSession(sessionName = SESSION_PREFIX) {
|
|
1620
1632
|
try {
|
|
1621
1633
|
execSync(`tmux kill-session -t "${sessionName}"`, { stdio: "pipe" });
|
|
1622
1634
|
} catch {
|
|
1623
1635
|
}
|
|
1624
1636
|
}
|
|
1625
|
-
function attachSession(sessionName =
|
|
1637
|
+
function attachSession(sessionName = SESSION_PREFIX) {
|
|
1626
1638
|
console.log("Attaching to existing session...");
|
|
1627
1639
|
spawnSync("tmux", ["attach-session", "-t", sessionName], { stdio: "inherit" });
|
|
1628
1640
|
}
|
|
1629
1641
|
function createTmuxSession(options) {
|
|
1630
|
-
const sessionName =
|
|
1642
|
+
const sessionName = options.sessionName ?? SESSION_PREFIX;
|
|
1631
1643
|
try {
|
|
1632
1644
|
execSync(
|
|
1633
1645
|
`tmux new-session -d -s "${sessionName}" -c "${options.workDir}" -x 200 -y 50`,
|
|
@@ -1703,12 +1715,17 @@ async function startSession(options) {
|
|
|
1703
1715
|
console.log("Please install Claude Code CLI first");
|
|
1704
1716
|
process.exit(1);
|
|
1705
1717
|
}
|
|
1718
|
+
let sessionName = SESSION_PREFIX;
|
|
1706
1719
|
if (sessionExists()) {
|
|
1707
1720
|
const choice = await handleExistingSession();
|
|
1708
1721
|
switch (choice) {
|
|
1709
1722
|
case "attach":
|
|
1710
1723
|
attachSession();
|
|
1711
1724
|
return;
|
|
1725
|
+
case "new":
|
|
1726
|
+
sessionName = findNextAvailableSessionName();
|
|
1727
|
+
console.log(`Creating parallel session: ${chalk5.green(sessionName)}`);
|
|
1728
|
+
break;
|
|
1712
1729
|
case "recreate":
|
|
1713
1730
|
console.log("Killing existing session...");
|
|
1714
1731
|
killSession();
|
|
@@ -1719,19 +1736,19 @@ async function startSession(options) {
|
|
|
1719
1736
|
}
|
|
1720
1737
|
}
|
|
1721
1738
|
console.log("");
|
|
1722
|
-
console.log(`Creating new session: ${chalk5.green(
|
|
1739
|
+
console.log(`Creating new session: ${chalk5.green(sessionName)}`);
|
|
1723
1740
|
console.log(`Working directory: ${chalk5.blue(options.workDir)}`);
|
|
1724
1741
|
console.log(`Relay base: ${chalk5.blue(config.baseDir)}`);
|
|
1725
1742
|
console.log("");
|
|
1726
|
-
const created = createTmuxSession(options);
|
|
1743
|
+
const created = createTmuxSession({ ...options, sessionName });
|
|
1727
1744
|
if (!created) {
|
|
1728
1745
|
console.error(chalk5.red("Failed to create session"));
|
|
1729
1746
|
process.exit(1);
|
|
1730
1747
|
}
|
|
1731
1748
|
console.log(chalk5.green("Session created successfully!"));
|
|
1732
1749
|
showSessionLayout();
|
|
1733
|
-
console.log(`Attaching to session ${chalk5.green(
|
|
1734
|
-
attachSession();
|
|
1750
|
+
console.log(`Attaching to session ${chalk5.green(sessionName)}...`);
|
|
1751
|
+
attachSession(sessionName);
|
|
1735
1752
|
}
|
|
1736
1753
|
|
|
1737
1754
|
// src/relay/orchestrator.ts
|
package/package.json
CHANGED
|
@@ -154,8 +154,9 @@ if [[ -n "${HANDOFF_FILE}" ]] && [[ -f "${HANDOFF_FILE}" ]]; then
|
|
|
154
154
|
|
|
155
155
|
show_relay_banner
|
|
156
156
|
|
|
157
|
-
# Start Claude with
|
|
158
|
-
|
|
157
|
+
# Start Claude with system prompt to read handoff file and continue work
|
|
158
|
+
# Using --append-system-prompt to stay in interactive mode (not -p which exits after response)
|
|
159
|
+
exec $(get_claude_cmd) --append-system-prompt "IMPORTANT: A handoff file has been created at ${HANDOFF_FILE}. You MUST read this file immediately using the Read tool and continue the previous work described within it. This is a session continuation - start by reading the handoff file."
|
|
159
160
|
else
|
|
160
161
|
log_relay "Starting fresh Claude session with relay support"
|
|
161
162
|
show_relay_banner
|
|
@@ -143,6 +143,10 @@ handle_relay_signal() {
|
|
|
143
143
|
log "INFO" "New Claude session started successfully"
|
|
144
144
|
send_ack "${source_pane}" "${new_pane}"
|
|
145
145
|
archive_handoff "${handoff_path}"
|
|
146
|
+
# Terminate old pane after new session is stable
|
|
147
|
+
sleep 2
|
|
148
|
+
log "INFO" "Terminating old pane: ${source_pane}"
|
|
149
|
+
tmux kill-pane -t "${source_pane}" 2>/dev/null || true
|
|
146
150
|
return 0
|
|
147
151
|
else
|
|
148
152
|
log "ERROR" "New pane ${new_pane} not found after creation"
|
|
@@ -23,8 +23,30 @@ ORCHESTRATOR_DIR="${RELAY_BASE}/orchestrator"
|
|
|
23
23
|
ORCHESTRATOR_SCRIPT="${ORCHESTRATOR_DIR}/orchestrator.sh"
|
|
24
24
|
WRAPPER_SCRIPT="${ORCHESTRATOR_DIR}/claude-wrapper.sh"
|
|
25
25
|
|
|
26
|
-
# Session name - symphony branding
|
|
27
|
-
|
|
26
|
+
# Session name prefix - symphony branding
|
|
27
|
+
SESSION_PREFIX="symphony-session"
|
|
28
|
+
|
|
29
|
+
# Function to find next available session name
|
|
30
|
+
# Returns: symphony-session, symphony-session-2, symphony-session-3, ...
|
|
31
|
+
find_next_session_name() {
|
|
32
|
+
local base="${SESSION_PREFIX}"
|
|
33
|
+
|
|
34
|
+
# Check if base session exists
|
|
35
|
+
if ! tmux has-session -t "${base}" 2>/dev/null; then
|
|
36
|
+
echo "${base}"
|
|
37
|
+
return
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
# Find next available numbered session
|
|
41
|
+
local n=2
|
|
42
|
+
while tmux has-session -t "${base}-${n}" 2>/dev/null; do
|
|
43
|
+
((n++))
|
|
44
|
+
done
|
|
45
|
+
echo "${base}-${n}"
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
# Default session name (will be updated if creating new parallel session)
|
|
49
|
+
SESSION_NAME="${SESSION_PREFIX}"
|
|
28
50
|
|
|
29
51
|
# Colors
|
|
30
52
|
RED='\033[0;31m'
|
|
@@ -74,24 +96,31 @@ for script in "${ORCHESTRATOR_SCRIPT}" "${WRAPPER_SCRIPT}"; do
|
|
|
74
96
|
done
|
|
75
97
|
|
|
76
98
|
# Check if session already exists
|
|
77
|
-
if tmux has-session -t "${
|
|
78
|
-
|
|
99
|
+
if tmux has-session -t "${SESSION_PREFIX}" 2>/dev/null; then
|
|
100
|
+
NEXT_SESSION_NAME=$(find_next_session_name)
|
|
101
|
+
echo -e "${YELLOW}Session '${SESSION_PREFIX}' already exists.${NC}"
|
|
79
102
|
echo ""
|
|
80
103
|
echo "Options:"
|
|
81
104
|
echo " 1. Attach to existing session"
|
|
82
|
-
echo " 2.
|
|
83
|
-
echo " 3.
|
|
105
|
+
echo " 2. Create new session (${NEXT_SESSION_NAME})"
|
|
106
|
+
echo " 3. Kill and recreate"
|
|
107
|
+
echo " 4. Cancel"
|
|
84
108
|
echo ""
|
|
85
|
-
read -p "Choice [1/2/3]: " choice
|
|
109
|
+
read -p "Choice [1/2/3/4]: " choice
|
|
86
110
|
|
|
87
111
|
case "${choice}" in
|
|
88
112
|
1)
|
|
89
113
|
echo "Attaching to existing session..."
|
|
90
|
-
exec tmux attach-session -t "${
|
|
114
|
+
exec tmux attach-session -t "${SESSION_PREFIX}"
|
|
91
115
|
;;
|
|
92
116
|
2)
|
|
117
|
+
echo -e "Creating parallel session: ${GREEN}${NEXT_SESSION_NAME}${NC}"
|
|
118
|
+
SESSION_NAME="${NEXT_SESSION_NAME}"
|
|
119
|
+
;;
|
|
120
|
+
3)
|
|
93
121
|
echo "Killing existing session..."
|
|
94
|
-
tmux kill-session -t "${
|
|
122
|
+
tmux kill-session -t "${SESSION_PREFIX}"
|
|
123
|
+
SESSION_NAME="${SESSION_PREFIX}"
|
|
95
124
|
;;
|
|
96
125
|
*)
|
|
97
126
|
echo "Cancelled."
|