@automagik/genie 4.260330.12 → 4.260330.13
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/.claude-plugin/marketplace.json +1 -1
- package/dist/genie.js +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/plugins/genie/.claude-plugin/plugin.json +1 -1
- package/plugins/genie/package.json +1 -1
- package/scripts/tmux/genie.tmux.conf +5 -7
- package/src/tui/tmux.ts +7 -2
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"plugins": [
|
|
11
11
|
{
|
|
12
12
|
"name": "genie",
|
|
13
|
-
"version": "4.260330.
|
|
13
|
+
"version": "4.260330.13",
|
|
14
14
|
"source": "./plugins/genie",
|
|
15
15
|
"description": "Human-AI partnership for Claude Code. Share a terminal, orchestrate workers, evolve together. Brainstorm ideas, wish them into plans, make with parallel agents, ship as one team. A coding genie that grows with your project."
|
|
16
16
|
}
|
package/dist/genie.js
CHANGED
|
@@ -1373,7 +1373,7 @@ exec ${bunPath} ${genieBin}
|
|
|
1373
1373
|
genie serve is running. Press Ctrl+C to stop.`);let shutdown2=()=>{console.log(`
|
|
1374
1374
|
Shutting down genie serve...`),handles.agentWatcher?.close(),handles.schedulerHandle?.stop(),killTmuxServer(TUI_SOCKET,tuiTmuxConf()),killTmuxServer(GENIE_SOCKET,genieTmuxConf()),removeServePid(),console.log("genie serve stopped.")};if(process.on("SIGTERM",()=>{shutdown2(),process.exit(143)}),process.on("SIGINT",()=>{shutdown2(),process.exit(130)}),handles.schedulerHandle)await handles.schedulerHandle.done;else await new Promise(()=>{});removeServePid()}async function startBackground(){let existingPid=readServePid();if(existingPid&&isProcessAlive(existingPid))console.log(`genie serve already running (PID ${existingPid})`),process.exit(0);if(existingPid)removeServePid();let bunPath=process.execPath??"bun",genieBin=process.argv[1]??"genie",child=spawn3(bunPath,[genieBin,"serve","--foreground"],{detached:!0,stdio:"ignore",env:{...process.env,GENIE_IS_DAEMON:"1"}});if(child.unref(),child.pid)if(await new Promise((resolve5)=>setTimeout(resolve5,1000)),isProcessAlive(child.pid))console.log(`genie serve started (PID ${child.pid})`);else console.error("Error: genie serve exited immediately."),process.exit(1);else console.error("Error: failed to spawn genie serve"),process.exit(1)}async function stopServe(){let pid=readServePid();if(!pid){console.log("genie serve is not running (no PID file).");return}if(!isProcessAlive(pid)){console.log(`Stale PID file (PID ${pid} not running). Cleaning up.`),removeServePid(),killTmuxServer(TUI_SOCKET,tuiTmuxConf()),killTmuxServer(GENIE_SOCKET,genieTmuxConf());return}console.log(`Stopping genie serve (PID ${pid})...`);try{process.kill(-pid,"SIGTERM")}catch{try{process.kill(pid,"SIGTERM")}catch{}}let deadline=Date.now()+1e4;while(Date.now()<deadline&&isProcessAlive(pid))await new Promise((resolve5)=>setTimeout(resolve5,250));if(isProcessAlive(pid)){console.log("Did not stop within 10s. Sending SIGKILL.");try{process.kill(-pid,"SIGKILL")}catch{try{process.kill(pid,"SIGKILL")}catch{}}}killTmuxServer(TUI_SOCKET,tuiTmuxConf()),killTmuxServer(GENIE_SOCKET,genieTmuxConf()),removeServePid(),console.log("genie serve stopped.")}async function printPgserveStatus(){try{let{isAvailable:isAvailable2,getActivePort:getActivePort2}=await Promise.resolve().then(() => (init_db(),exports_db)),dbOk=await isAvailable2();console.log(` pgserve: ${dbOk?`healthy (port ${getActivePort2()})`:"unreachable"}`)}catch{console.log(" pgserve: unavailable")}}function printTmuxStatus(){let agentRunning=isTmuxServerRunning(GENIE_SOCKET,genieTmuxConf()),sessions=agentRunning?listAgentSessions():[];if(console.log(` tmux -L ${GENIE_SOCKET}: ${agentRunning?`running (${sessions.length} sessions)`:"stopped"}`),sessions.length>0)console.log(` ${sessions.join(", ")}`);let tuiRunning=isTmuxServerRunning(TUI_SOCKET,tuiTmuxConf());console.log(` tmux -L ${TUI_SOCKET}: ${tuiRunning?"running":"stopped"}`)}async function printDaemonStatus(serveRunning){try{let schedulerPidPath=join31(genieHome(),"scheduler.pid");if(existsSync24(schedulerPidPath)){let sPid=Number.parseInt(readFileSync11(schedulerPidPath,"utf-8").trim(),10),sAlive=!Number.isNaN(sPid)&&isProcessAlive(sPid);console.log(` scheduler: ${sAlive?`running (PID ${sPid})`:"stopped"}`)}else if(serveRunning)console.log(" scheduler: integrated (in-process)");else console.log(" scheduler: stopped")}catch{console.log(" scheduler: unknown")}try{let{getInboxPollIntervalMs:getInboxPollIntervalMs2}=await Promise.resolve().then(() => (init_inbox_watcher(),exports_inbox_watcher)),pollMs=getInboxPollIntervalMs2();if(pollMs===0)console.log(" inbox: disabled");else console.log(` inbox: ${serveRunning?"watching":"stopped"} (poll ${pollMs/1000}s)`)}catch{console.log(" inbox: unavailable")}}async function statusServe(){let pid=readServePid(),running2=pid!==null&&isProcessAlive(pid);if(console.log(`
|
|
1375
1375
|
Genie Serve`),console.log("\u2500".repeat(50)),console.log(` Status: ${running2?"running":"stopped"}`),running2&&pid)console.log(` PID: ${pid}`);await printPgserveStatus(),printTmuxStatus(),await printDaemonStatus(running2),console.log(` PID file: ${servePidPath()}`),console.log("")}function registerServeCommands(program2){let serve=program2.command("serve").description("Start all genie infrastructure (pgserve, tmux, scheduler)");serve.command("start",{isDefault:!0}).description("Start genie serve").option("--daemon","Run in background").option("--foreground","Run in foreground (default)").action(async(options)=>{if(options.daemon)await startBackground();else await startForeground()}),serve.command("stop").description("Stop genie serve and all services").action(async()=>{await stopServe()}),serve.command("status").description("Show service health").action(async()=>{await statusServe()})}var GENIE_SOCKET="genie",TUI_SOCKET="genie-tui",TUI_SESSION="genie-tui",NAV_WIDTH=30,KEY_TABLE="genie-tui",TUI_STYLE,handles;var init_serve=__esm(()=>{TUI_STYLE={activeBorder:"#7c3aed",inactiveBorder:"#414868"};handles={schedulerHandle:null,agentWatcher:null}});var exports_tmux2={};__export(exports_tmux2,{attachTuiSession:()=>attachTuiSession,attachProjectWindow:()=>attachProjectWindow});import{execSync as execSync7,spawnSync as spawnSync2}from"child_process";function resolveRightPane(rightPane){try{return execSync7(`${TMUX} display-message -t ${rightPane} -p ''`,{stdio:"ignore"}),rightPane}catch{try{let panes=execSync7(`${TMUX} list-panes -t ${SESSION_NAME}:0 -F '#{pane_id}'`,{encoding:"utf-8"}).trim().split(`
|
|
1376
|
-
`);return panes[1]||panes[0]}catch{return rightPane}}}function ensureAgentSession(sessionName){let agentTmux=`tmux -L ${GENIE_AGENT_SOCKET}`;try{execSync7(`${agentTmux} has-session -t '${sessionName}' 2>/dev/null`,{stdio:"ignore"})}catch{try{execSync7(`${agentTmux} new-session -d -s '${sessionName}'`,{stdio:"ignore"})}catch{}}}function attachProjectWindow(rightPane,targetSession,windowIndex){if(targetSession===SESSION_NAME)return;let pane=resolveRightPane(rightPane);if(ensureAgentSession(targetSession),windowIndex!==void 0)try{let agentTmux=`tmux -L ${GENIE_AGENT_SOCKET}`;execSync7(`${agentTmux} select-window -t '${targetSession}:${windowIndex}'`,{stdio:"ignore"})}catch{}try{let
|
|
1376
|
+
`);return panes[1]||panes[0]}catch{return rightPane}}}function ensureAgentSession(sessionName){let agentTmux=`tmux -L ${GENIE_AGENT_SOCKET}`;try{execSync7(`${agentTmux} has-session -t '${sessionName}' 2>/dev/null`,{stdio:"ignore"})}catch{try{execSync7(`${agentTmux} new-session -d -s '${sessionName}'`,{stdio:"ignore"})}catch{}}}function attachProjectWindow(rightPane,targetSession,windowIndex){if(targetSession===SESSION_NAME)return;let pane=resolveRightPane(rightPane);if(ensureAgentSession(targetSession),windowIndex!==void 0)try{let agentTmux=`tmux -L ${GENIE_AGENT_SOCKET}`;execSync7(`${agentTmux} select-window -t '${targetSession}:${windowIndex}'`,{stdio:"ignore"})}catch{}try{let attachCmd=`sleep 0.1 && printf '\\033[2J\\033[H' && TMUX='' ${`tmux -L ${GENIE_AGENT_SOCKET}`} attach-session -t '${targetSession}'`;execSync7(`${TMUX} respawn-pane -k -t ${pane} "sh -c \\"${attachCmd}\\""`,{stdio:"ignore"})}catch{}}function attachTuiSession(){spawnSync2("tmux",["-L",TMUX_SOCKET,"-f",GENIE_TMUX_CONF,"attach-session","-t",SESSION_NAME],{stdio:"inherit"})}var SESSION_NAME="genie-tui",TMUX_SOCKET="genie-tui",GENIE_AGENT_SOCKET="genie",GENIE_TMUX_CONF,TMUX;var init_tmux2=__esm(()=>{GENIE_TMUX_CONF=(()=>{let{existsSync:existsSync25}=__require("fs");return[`${process.env.GENIE_HOME??`${process.env.HOME}/.genie`}/tmux.conf`,`${process.env.HOME}/.tmux.conf`].find((p)=>existsSync25(p))??"/dev/null"})(),TMUX=`tmux -L ${TMUX_SOCKET} -f ${GENIE_TMUX_CONF}`});function onBridgeEvent(handler){return listeners.add(handler),()=>{listeners.delete(handler)}}function emit2(event){for(let handler of listeners)handler(event)}async function listAgents2(){return(await getConnection())`
|
|
1377
1377
|
SELECT a.id, a.custom_name, a.role, a.team, a.title, a.state,
|
|
1378
1378
|
a.reports_to, a.current_executor_id, a.started_at
|
|
1379
1379
|
FROM agents a
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genie",
|
|
3
|
-
"version": "4.260330.
|
|
3
|
+
"version": "4.260330.13",
|
|
4
4
|
"description": "Human-AI partnership for Claude Code. Share a terminal, orchestrate workers, evolve together. Brainstorm ideas, turn them into wishes, execute with /work, validate with /review, and ship as one team.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Namastex Labs"
|
|
@@ -50,21 +50,19 @@ setw -g mode-style "bg=#7b2ff7,fg=#e0e0e0"
|
|
|
50
50
|
setw -g clock-mode-colour "#7b2ff7"
|
|
51
51
|
|
|
52
52
|
# ============================================================================
|
|
53
|
-
# TOP BAR — pane-border:
|
|
53
|
+
# TOP BAR — pane-border: clean labels, NO shell probes
|
|
54
|
+
# Shell probes (#() calls) cause garbled escape sequences when TUI/app
|
|
55
|
+
# attaches to agent sessions. Observability lives in TUI/app status bar.
|
|
54
56
|
# ============================================================================
|
|
55
57
|
set -g pane-border-status top
|
|
56
58
|
set -g pane-border-lines heavy
|
|
57
59
|
set -g pane-border-format "\
|
|
58
60
|
#[align=left,bg=#16213e,fg=#e0e0e0]\
|
|
59
|
-
#[fg=#7b2ff7,bold]Genie#[fg=#6c6c8a,nobold]
|
|
61
|
+
#[fg=#7b2ff7,bold]Genie#[fg=#6c6c8a,nobold] \
|
|
60
62
|
#[fg=#0f3460]│ \
|
|
61
63
|
#[fg=#b8a9c9]#{pane_current_path}\
|
|
62
64
|
#[align=right,bg=#16213e]\
|
|
63
|
-
#[fg=#
|
|
64
|
-
#[fg=#0f3460]│ \
|
|
65
|
-
#[fg=#00d2ff]CPU #($HOME/.genie/scripts/cpu-info.sh) \
|
|
66
|
-
#[fg=#0f3460]│ \
|
|
67
|
-
#[fg=#00d2ff]RAM #($HOME/.genie/scripts/ram-info.sh) \
|
|
65
|
+
#[fg=#e0e0e0]#{session_name}:#{window_name} \
|
|
68
66
|
#[fg=#0f3460]│ \
|
|
69
67
|
#[fg=#e0e0e0]%H:%M "
|
|
70
68
|
|
package/src/tui/tmux.ts
CHANGED
|
@@ -76,9 +76,14 @@ export function attachProjectWindow(rightPane: string, targetSession: string, wi
|
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
try {
|
|
79
|
-
// Attach to sessions on the genie agent server
|
|
79
|
+
// Attach to sessions on the genie agent server.
|
|
80
|
+
// Use a wrapper script that clears probe artifacts:
|
|
81
|
+
// 1. Sleep briefly so tmux finishes its terminal capability detection
|
|
82
|
+
// 2. Clear screen to hide probe escape sequences
|
|
83
|
+
// 3. Attach to the agent session
|
|
80
84
|
const agentTmux = `tmux -L ${GENIE_AGENT_SOCKET}`;
|
|
81
|
-
|
|
85
|
+
const attachCmd = `sleep 0.1 && printf '\\033[2J\\033[H' && TMUX='' ${agentTmux} attach-session -t '${targetSession}'`;
|
|
86
|
+
execSync(`${TMUX} respawn-pane -k -t ${pane} "sh -c \\"${attachCmd}\\""`, {
|
|
82
87
|
stdio: 'ignore',
|
|
83
88
|
});
|
|
84
89
|
} catch {
|