@humanu/orchestra 0.5.74 → 0.5.75

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@humanu/orchestra",
3
- "version": "0.5.74",
3
+ "version": "0.5.75",
4
4
  "description": "AI-powered Git worktree and tmux session manager with modern TUI",
5
5
  "keywords": [
6
6
  "git",
@@ -434,7 +434,7 @@ with open(active_path, "r", encoding="utf-8") as handle:
434
434
  line = raw_line.rstrip("\n")
435
435
  if not line:
436
436
  continue
437
- parts = line.split("\t", 1)
437
+ parts = line.split("\t")
438
438
  name = parts[0].strip()
439
439
  display_name = parts[1].strip() if len(parts) > 1 else ""
440
440
  if not name:
@@ -651,18 +651,21 @@ _tmux_configure_orchestra_bindings() {
651
651
  bridge="$(_orchestra_bridge_script)"
652
652
  [[ -f "$bridge" ]] || return
653
653
 
654
- local quoted_bridge rename_command prompt_command next_command previous_command help_command
654
+ local quoted_bridge rename_command prompt_command next_command previous_command new_session_command help_command
655
655
  printf -v quoted_bridge '%q' "$bridge"
656
656
  rename_command="$quoted_bridge manual-rename-session \\\"#{session_name}\\\" \\\"%%\\\" >/dev/null 2>&1"
657
657
  prompt_command="command-prompt -p 'Rename Orchestra session:' 'run-shell -b \"$rename_command\"'"
658
658
  next_command="$quoted_bridge cycle-workspace-session \\\"#{session_name}\\\" next \\\"#{client_tty}\\\" >/dev/null 2>&1"
659
659
  previous_command="$quoted_bridge cycle-workspace-session \\\"#{session_name}\\\" previous \\\"#{client_tty}\\\" >/dev/null 2>&1"
660
+ new_session_command="$quoted_bridge create-workspace-session \\\"#{session_name}\\\" \\\"#{client_tty}\\\" >/dev/null 2>&1"
660
661
  help_command="$quoted_bridge tmux-help-popup \\\"#{client_tty}\\\" >/dev/null 2>&1"
661
662
 
662
663
  tmux bind-key -T prefix '?' if-shell -F '#{@orchestra_display_name}' \
663
664
  "run-shell -b \"$help_command\"" 'list-keys -N' >/dev/null 2>&1 || true
664
665
  tmux bind-key -T prefix h if-shell -F '#{@orchestra_display_name}' \
665
666
  "run-shell -b \"$help_command\"" 'refresh-client -S' >/dev/null 2>&1 || true
667
+ tmux bind-key -T prefix n if-shell -F '#{@orchestra_display_name}' \
668
+ "run-shell -b \"$new_session_command\"" 'next-window' >/dev/null 2>&1 || true
666
669
  tmux bind-key -T prefix r if-shell -F '#{@orchestra_display_name}' \
667
670
  "$prompt_command" 'refresh-client -S' >/dev/null 2>&1 || true
668
671
  tmux bind-key -T prefix '>' if-shell -F '#{@orchestra_display_name}' \
@@ -900,6 +903,47 @@ tmux_ensure_session() {
900
903
  _tmux_source_command_hook "$sess"
901
904
  }
902
905
 
906
+ # Create a new auto-named Orchestra session in the current session's worktree and switch to it.
907
+ # Uses the same tmux_ensure_session path as the TUI tree view create action.
908
+ # Usage: tmux_create_workspace_session <current_session> [client_tty]
909
+ tmux_create_workspace_session() {
910
+ local current_session="$1"
911
+ local target_client="${2:-}"
912
+ local session_dir branch slug new_session
913
+
914
+ if ! tmux_available; then
915
+ err "tmux not installed"
916
+ return 1
917
+ fi
918
+ if [[ -z "$current_session" ]]; then
919
+ err "tmux_create_workspace_session: current session required"
920
+ return 1
921
+ fi
922
+
923
+ session_dir="$(tmux display-message -t "$current_session" -p '#{pane_current_path}' 2>/dev/null || echo "")"
924
+ if [[ -z "$session_dir" || ! -d "$session_dir" ]]; then
925
+ err "Unable to determine current worktree path"
926
+ return 1
927
+ fi
928
+
929
+ branch="$(_tmux_branch_for_path "$session_dir" 2>/dev/null || true)"
930
+ if [[ -z "$branch" || "$branch" == "detached" ]]; then
931
+ err "Unable to determine current worktree branch"
932
+ return 1
933
+ fi
934
+
935
+ slug="$(git_branch_to_slug "$branch")"
936
+ new_session="$(tmux_ensure_session "$slug" "" "$session_dir")" || return 1
937
+
938
+ if [[ -n "$target_client" ]]; then
939
+ tmux switch-client -c "$target_client" -t "$new_session" >/dev/null 2>&1 || return 1
940
+ else
941
+ tmux switch-client -t "$new_session" >/dev/null 2>&1 || return 1
942
+ fi
943
+
944
+ printf '%s\n' "$new_session"
945
+ }
946
+
903
947
  # Check if a session exists
904
948
  # Usage: tmux_session_exists <session_name>
905
949
  tmux_session_exists() {
@@ -1077,7 +1121,7 @@ tmux_rename_session() {
1077
1121
 
1078
1122
  # --------------------------- Session Discovery ------------------------------
1079
1123
 
1080
- # Get tmux sessions for a slug prefix; prints session names sorted by last attached/activity
1124
+ # Get tmux sessions for a slug prefix; prints session names sorted by creation time, oldest first
1081
1125
  # Expected session format: [worktreename]_[worktreehash]_[datetime]_[readable_name]
1082
1126
  # Usage: tmux_list_sessions_for_slug <slug> [worktree_path]
1083
1127
  tmux_list_sessions_for_slug() {
@@ -1108,19 +1152,19 @@ tmux_list_sessions_for_slug() {
1108
1152
  fi
1109
1153
 
1110
1154
  # List sessions with any known prefix variant
1111
- tmux list-sessions -F '#{session_name}|||#{session_last_attached}|||#{session_activity}' 2>/dev/null \
1155
+ tmux list-sessions -F '#{session_name}|||#{session_created}' 2>/dev/null \
1112
1156
  | sed 's/|||/\t/g' \
1113
- | awk -v a="$p1_new" -v b="$p2_new" -v c="$p1_old" -v d="$p2_old" -v e="$p1_branch_hash" -v f="$p2_branch_hash" 'BEGIN{FS="\t"} (length(a)>0 && index($1, a)==1) || (length(b)>0 && index($1, b)==1) || (length(c)>0 && index($1, c)==1) || (length(d)>0 && index($1, d)==1) || (length(e)>0 && index($1, e)==1) || (length(f)>0 && index($1, f)==1) {print $1"\t"$2"\t"$3}' \
1114
- | sort -t $'\t' -k2,2nr -k3,3nr \
1157
+ | awk -v a="$p1_new" -v b="$p2_new" -v c="$p1_old" -v d="$p2_old" -v e="$p1_branch_hash" -v f="$p2_branch_hash" 'BEGIN{FS="\t"} (length(a)>0 && index($1, a)==1) || (length(b)>0 && index($1, b)==1) || (length(c)>0 && index($1, c)==1) || (length(d)>0 && index($1, d)==1) || (length(e)>0 && index($1, e)==1) || (length(f)>0 && index($1, f)==1) {print $1"\t"$2}' \
1158
+ | sort -t $'\t' -k2,2n -k1,1f \
1115
1159
  | awk -F '\t' '{print $1}' | awk '!seen[$0]++' || true
1116
1160
  else
1117
1161
  # New-format prefix matching without hash: orchestra__slug__... or slug__...
1118
1162
  local prefix1="${ORCH_PREFIX}${slug}${d}"
1119
1163
  local prefix2="${slug}${d}"
1120
- tmux list-sessions -F '#{session_name}|||#{session_last_attached}|||#{session_activity}' 2>/dev/null \
1164
+ tmux list-sessions -F '#{session_name}|||#{session_created}' 2>/dev/null \
1121
1165
  | sed 's/|||/\t/g' \
1122
- | awk -v p1="$prefix1" -v p2="$prefix2" 'BEGIN{FS="\t"} index($1, p1)==1 || index($1, p2)==1 {print $1"\t"$2"\t"$3}' \
1123
- | sort -t $'\t' -k2,2nr -k3,3nr \
1166
+ | awk -v p1="$prefix1" -v p2="$prefix2" 'BEGIN{FS="\t"} index($1, p1)==1 || index($1, p2)==1 {print $1"\t"$2}' \
1167
+ | sort -t $'\t' -k2,2n -k1,1f \
1124
1168
  | awk -F '\t' '{print $1}' || true
1125
1169
  fi
1126
1170
  }
@@ -1511,6 +1555,7 @@ printf "%s\n" \
1511
1555
  "" \
1512
1556
  "Ctrl+b, d Detach and return to Orchestra" \
1513
1557
  "Ctrl+b, r Rename the current Orchestra session" \
1558
+ "Ctrl+b, n New Orchestra session in this worktree" \
1514
1559
  "" \
1515
1560
  "Ctrl+b, Left Previous Orchestra session in this workspace" \
1516
1561
  "Ctrl+b, Right Next Orchestra session in this workspace" \
@@ -1561,7 +1606,7 @@ tmux_workspace_cycle_target() {
1561
1606
  }
1562
1607
 
1563
1608
  active_file="$(mktemp)"
1564
- tmux list-sessions -F $'#{session_name}\t#{@orchestra_display_name}' > "$active_file" 2>/dev/null || {
1609
+ tmux list-sessions -F $'#{session_name}\t#{@orchestra_display_name}\t#{session_last_attached}\t#{session_activity}' > "$active_file" 2>/dev/null || {
1565
1610
  rm -f "$active_file"
1566
1611
  err "Unable to list tmux sessions"
1567
1612
  return 1
@@ -97,7 +97,11 @@ case "${1:-}" in
97
97
  "create-session-exact")
98
98
  bridge_create_session_exact "${2:-}" "${3:-}"
99
99
  ;;
100
-
100
+
101
+ "create-workspace-session")
102
+ bridge_create_workspace_session "${2:-}" "${3:-}"
103
+ ;;
104
+
101
105
  "kill-session")
102
106
  bridge_kill_session "${2:-}"
103
107
  ;;
@@ -243,6 +247,8 @@ Commands:
243
247
  copy-env-files <source> <target> Copy .env files between directories
244
248
  cycle-workspace-session <session> <next|previous> [client]
245
249
  Switch within registered Orchestra sessions for this repo
250
+ create-workspace-session <session> [client]
251
+ Create a new session in the current worktree and switch to it
246
252
  tmux-help-popup [client] Show Orchestra tmux shortcut popup
247
253
  repo-info Get repository information
248
254
  git-status Get git status --porcelain
@@ -62,6 +62,26 @@ bridge_create_session_exact() {
62
62
  fi
63
63
  }
64
64
 
65
+ # Create a new tmux session in the current session's worktree and switch to it.
66
+ bridge_create_workspace_session() {
67
+ if [[ -z "${1:-}" ]]; then
68
+ json_error "Current session name required"
69
+ return 1
70
+ fi
71
+ session_name="$1"
72
+ target_client="${2:-}"
73
+
74
+ if tmux_available; then
75
+ created_session="$(tmux_create_workspace_session "$session_name" "$target_client")" || {
76
+ json_error "Failed to create workspace session"
77
+ return 1
78
+ }
79
+ json_object "ok:b=true" "session:s=$created_session"
80
+ else
81
+ json_error "tmux not available"
82
+ fi
83
+ }
84
+
65
85
  # Kill tmux session
66
86
  bridge_kill_session() {
67
87
  if [[ -z "${1:-}" ]]; then