Spaces:
Running
Running
New sessions land on top unless created inside a group; prompt tracks current dir relative to workspaces root
Browse files- server/src/runner.js +2 -1
- session.bashrc +19 -4
- web/src/App.tsx +10 -4
server/src/runner.js
CHANGED
|
@@ -247,11 +247,12 @@ export function attach(session, cols, rows) {
|
|
| 247 |
'-e', `AM_SESSION=${folder}`,
|
| 248 |
'-e', `AM_NAME=${session.name}`,
|
| 249 |
'-e', `AM_USER=${AM_USER}`,
|
|
|
|
| 250 |
'sh', '-lc', full,
|
| 251 |
);
|
| 252 |
term = pty.spawn('tmux', args, { name: 'xterm-256color', cols, rows, cwd: workdir, env: TERM_ENV });
|
| 253 |
} else {
|
| 254 |
-
const env = { ...TERM_ENV, AM_SESSION: folder, AM_NAME: session.name, AM_USER };
|
| 255 |
term = pty.spawn('bash', ['-lc', full], { name: 'xterm-256color', cols, rows, cwd: workdir, env });
|
| 256 |
}
|
| 257 |
|
|
|
|
| 247 |
'-e', `AM_SESSION=${folder}`,
|
| 248 |
'-e', `AM_NAME=${session.name}`,
|
| 249 |
'-e', `AM_USER=${AM_USER}`,
|
| 250 |
+
'-e', `AM_ROOT=${WORKSPACES_DIR}`, // prompt shows $PWD relative to this
|
| 251 |
'sh', '-lc', full,
|
| 252 |
);
|
| 253 |
term = pty.spawn('tmux', args, { name: 'xterm-256color', cols, rows, cwd: workdir, env: TERM_ENV });
|
| 254 |
} else {
|
| 255 |
+
const env = { ...TERM_ENV, AM_SESSION: folder, AM_NAME: session.name, AM_USER, AM_ROOT: WORKSPACES_DIR };
|
| 256 |
term = pty.spawn('bash', ['-lc', full], { name: 'xterm-256color', cols, rows, cwd: workdir, env });
|
| 257 |
}
|
| 258 |
|
session.bashrc
CHANGED
|
@@ -3,8 +3,23 @@
|
|
| 3 |
[ -f /etc/bash.bashrc ] && . /etc/bash.bashrc
|
| 4 |
|
| 5 |
AM_USER="${AM_USER:-${SPACE_AUTHOR_NAME:-user}}"
|
| 6 |
-
AM_SESSION="${AM_SESSION:-session}"
|
| 7 |
|
| 8 |
-
#
|
| 9 |
-
#
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
[ -f /etc/bash.bashrc ] && . /etc/bash.bashrc
|
| 4 |
|
| 5 |
AM_USER="${AM_USER:-${SPACE_AUTHOR_NAME:-user}}"
|
|
|
|
| 6 |
|
| 7 |
+
# The prompt's location segment: the CURRENT directory, shown relative to the
|
| 8 |
+
# workspaces root (AM_ROOT, exported by the manager) so it starts as the
|
| 9 |
+
# session's folder and follows you as you cd around. Falls back to ~-style
|
| 10 |
+
# for anything outside the workspace tree.
|
| 11 |
+
_am_pwd() {
|
| 12 |
+
local root="${AM_ROOT:-/data/workspaces}"
|
| 13 |
+
case "$PWD" in
|
| 14 |
+
"$root") printf 'workspaces' ;;
|
| 15 |
+
"$root"/*) printf '%s' "${PWD#"$root"/}" ;;
|
| 16 |
+
"$HOME") printf '~' ;;
|
| 17 |
+
"$HOME"/*) printf '~/%s' "${PWD#"$HOME"/}" ;;
|
| 18 |
+
*) printf '%s' "$PWD" ;;
|
| 19 |
+
esac
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
# Prompt: "user/current-dir $" — colors come from the (theme-tuned) ANSI
|
| 23 |
+
# palette, bold cyan user + bold green location, readable on both light and
|
| 24 |
+
# dark backgrounds. $(_am_pwd) is single-quoted so it re-evaluates per prompt.
|
| 25 |
+
PS1='\[\e[1;36m\]'"${AM_USER}"'\[\e[0;2m\]/\[\e[0m\]\[\e[1;32m\]$(_am_pwd)\[\e[0;2m\] \$\[\e[0m\] '
|
web/src/App.tsx
CHANGED
|
@@ -93,12 +93,18 @@ export default function App() {
|
|
| 93 |
}, [visibleIds, focusedId]);
|
| 94 |
|
| 95 |
// actions
|
| 96 |
-
const
|
| 97 |
-
const s = await api.createSession(name, cli,
|
| 98 |
rememberPath(s.path);
|
| 99 |
await refresh();
|
| 100 |
-
setActiveRef(`
|
|
|
|
| 101 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 102 |
const newGroup = async (name: string, cart?: { cli: string; count: number }[], path = '') => {
|
| 103 |
const g = await api.createGroup(name);
|
| 104 |
for (const { cli, count } of cart || []) {
|
|
@@ -221,7 +227,7 @@ export default function App() {
|
|
| 221 |
<div className="empty-card">
|
| 222 |
<h2>{activeGroup.name}</h2>
|
| 223 |
<p>Create an agent here, or drag one in from the sidebar.</p>
|
| 224 |
-
<NewSession clis={clis} sessions={tree.sessions} defaultPath={lastPath} onCreate={
|
| 225 |
<div className="dropline">⤓ drop an agent to add it to this group</div>
|
| 226 |
</div>
|
| 227 |
</div>
|
|
|
|
| 93 |
}, [visibleIds, focusedId]);
|
| 94 |
|
| 95 |
// actions
|
| 96 |
+
const createSession = async (name: string, cli: string, path: string, groupId?: string) => {
|
| 97 |
+
const s = await api.createSession(name, cli, groupId, path);
|
| 98 |
rememberPath(s.path);
|
| 99 |
await refresh();
|
| 100 |
+
if (groupId) { setActiveRef(`g:${groupId}`); setFocusedId(s.id); }
|
| 101 |
+
else setActiveRef(`s:${s.id}`);
|
| 102 |
};
|
| 103 |
+
// Sidebar + quick-add creations always land loose at the top of the list —
|
| 104 |
+
// never in a group just because one happens to be selected.
|
| 105 |
+
const newSession = (name: string, cli: string, path: string) => createSession(name, cli, path);
|
| 106 |
+
// The empty-group card explicitly creates "an agent here".
|
| 107 |
+
const newSessionHere = (name: string, cli: string, path: string) => createSession(name, cli, path, activeGroup?.id);
|
| 108 |
const newGroup = async (name: string, cart?: { cli: string; count: number }[], path = '') => {
|
| 109 |
const g = await api.createGroup(name);
|
| 110 |
for (const { cli, count } of cart || []) {
|
|
|
|
| 227 |
<div className="empty-card">
|
| 228 |
<h2>{activeGroup.name}</h2>
|
| 229 |
<p>Create an agent here, or drag one in from the sidebar.</p>
|
| 230 |
+
<NewSession clis={clis} sessions={tree.sessions} defaultPath={lastPath} onCreate={newSessionHere} />
|
| 231 |
<div className="dropline">⤓ drop an agent to add it to this group</div>
|
| 232 |
</div>
|
| 233 |
</div>
|