groove-dev 0.27.186 → 0.27.187

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.
@@ -6,7 +6,7 @@
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <link rel="icon" type="image/png" href="/favicon.png" />
8
8
  <title>Groove GUI</title>
9
- <script type="module" crossorigin src="/assets/index-DOOaCFRS.js"></script>
9
+ <script type="module" crossorigin src="/assets/index-DyI84i9Y.js"></script>
10
10
  <link rel="modulepreload" crossorigin href="/assets/vendor-26L3JoZv.js">
11
11
  <link rel="modulepreload" crossorigin href="/assets/reactflow-DoBZjiHE.js">
12
12
  <link rel="modulepreload" crossorigin href="/assets/codemirror-BYKpdS2W.js">
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groove-dev/gui",
3
- "version": "0.27.186",
3
+ "version": "0.27.187",
4
4
  "description": "GROOVE GUI — visual agent control plane",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",
@@ -385,9 +385,28 @@ function InnerChatMessage({ msg, agent }) {
385
385
  );
386
386
  }
387
387
 
388
+ // Single-quote a value for safe use inside the shell command we inject.
389
+ function shq(s) {
390
+ return `'${String(s).replace(/'/g, `'\\''`)}'`;
391
+ }
392
+
393
+ // Build a `tail -f` that actually resolves. Agents usually write a log path
394
+ // relative to wherever they ran it — often a bare filename several directories
395
+ // deep — but the terminal opens in a different cwd, so a naive `tail -f name`
396
+ // fails. Absolute paths are used as-is; anything else is resolved against the
397
+ // agent's working directory, falling back to a `find` by basename when the file
398
+ // sits below that directory.
399
+ function tailCommand(path, workdir) {
400
+ if (/^[/~]/.test(path) || !workdir) return `tail -f ${shq(path)}`;
401
+ const base = path.split('/').pop();
402
+ return `cd ${shq(workdir)} 2>/dev/null; `
403
+ + `if [ -f ${shq(path)} ]; then tail -f ${shq(path)}; `
404
+ + `else tail -f "$(find . -name ${shq(base)} -type f 2>/dev/null | head -1)"; fi`;
405
+ }
406
+
388
407
  // One-click "tail" chips for any log paths the agent mentioned — saves asking
389
408
  // "what's the log file?" and hand-copying it into a terminal.
390
- function LogChips({ text }) {
409
+ function LogChips({ text, workdir }) {
391
410
  const runInTerminal = useGrooveStore((s) => s.runInTerminal);
392
411
  const paths = useMemo(() => extractLogPaths(text), [text]);
393
412
  if (paths.length === 0) return null;
@@ -397,7 +416,7 @@ function LogChips({ text }) {
397
416
  {paths.map((path) => (
398
417
  <button
399
418
  key={path}
400
- onClick={() => runInTerminal(`tail -f ${path}`)}
419
+ onClick={() => runInTerminal(tailCommand(path, workdir))}
401
420
  title={`tail -f ${path}`}
402
421
  className="inline-flex items-center gap-1.5 px-2 py-0.5 rounded-md bg-accent/10 hover:bg-accent/20 text-accent text-[11px] font-medium font-sans cursor-pointer transition-colors max-w-full"
403
422
  >
@@ -430,7 +449,7 @@ function AgentMessage({ msg, agent, answeredTo }) {
430
449
  <div className={cn('pl-3.5 py-1 border-l', answeredTo ? 'border-indigo/50' : 'border-accent')}>
431
450
  <StructuredMessage text={collapsed ? msg.text.slice(0, 600) + '...' : msg.text} />
432
451
  </div>
433
- <LogChips text={msg.text} />
452
+ <LogChips text={msg.text} workdir={agent?.workingDir} />
434
453
  {collapsed && (
435
454
  <button
436
455
  onClick={() => setCollapsed(false)}