@misterhuydo/sentinel 1.4.54 → 1.4.56

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.
@@ -1,6 +1,6 @@
1
1
  {
2
- "message": "Auto-checkpoint at 2026-03-25T11:59:09.003Z",
3
- "checkpoint_at": "2026-03-25T11:59:09.014Z",
2
+ "message": "Auto-checkpoint at 2026-03-25T12:11:43.792Z",
3
+ "checkpoint_at": "2026-03-25T12:11:43.793Z",
4
4
  "active_files": [],
5
5
  "notes": [],
6
6
  "mtime_snapshot": {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@misterhuydo/sentinel",
3
- "version": "1.4.54",
3
+ "version": "1.4.56",
4
4
  "description": "Sentinel — Autonomous DevOps Agent installer and manager",
5
5
  "bin": {
6
6
  "sentinel": "./bin/sentinel.js"
@@ -2492,6 +2492,7 @@ async def _run_tool(name: str, inputs: dict, cfg_loader, store, slack_client=Non
2492
2492
 
2493
2493
  if name == "install_tool":
2494
2494
  import subprocess as _sp
2495
+ import os as _os
2495
2496
  tool_name = inputs.get("tool_name", "").strip()
2496
2497
  if not tool_name:
2497
2498
  return json.dumps({"error": "tool_name is required"})
@@ -2697,12 +2698,14 @@ async def _handle_with_cli(
2697
2698
  logger.error("Boss CLI call failed: %s", e)
2698
2699
  return f":warning: Boss unavailable: {e}", True
2699
2700
 
2701
+ tools_ran = []
2700
2702
  for m in _ACTION_RE.finditer(output):
2701
2703
  try:
2702
2704
  action = json.loads(m.group(1))
2703
2705
  name = action.pop("action", "")
2704
2706
  if name:
2705
2707
  result_str = await _run_tool(name, action, cfg_loader, store, user_id=user_id)
2708
+ tools_ran.append(name)
2706
2709
  logger.info("Boss CLI action: %s → %s", name, result_str[:80])
2707
2710
  except Exception as e:
2708
2711
  logger.warning("Boss action parse error: %s", e)
@@ -2711,8 +2714,11 @@ async def _handle_with_cli(
2711
2714
  is_done = "[DONE]" in reply
2712
2715
  reply = reply.replace("[DONE]", "").strip()
2713
2716
  if not reply:
2714
- greeting = f"Hi {user_name}! " if user_name else "Hi! "
2715
- reply = f"{greeting}I'm Sentinel, your autonomous DevOps agent. How can I help you?"
2717
+ if tools_ran:
2718
+ reply = f":white_check_mark: Done ({', '.join(tools_ran)})."
2719
+ else:
2720
+ greeting = f"Hi {user_name}! " if user_name else "Hi! "
2721
+ reply = f"{greeting}I'm Sentinel, your autonomous DevOps agent. How can I help you?"
2716
2722
 
2717
2723
  history.append({"role": "user", "content": message})
2718
2724
  history.append({"role": "assistant", "content": reply})
@@ -2878,8 +2884,17 @@ async def _handle_with_api(
2878
2884
  is_done = "[DONE]" in reply
2879
2885
  reply = reply.replace("[DONE]", "").strip()
2880
2886
  if not reply:
2881
- greeting = f"Hi {user_name}! " if user_name else "Hi! "
2882
- reply = f"{greeting}I'm Sentinel, your autonomous DevOps agent. How can I help you?"
2887
+ # Only greet on a truly empty/hello message not after tool execution
2888
+ tools_ran_this_session = any(
2889
+ m.get("role") == "user" and isinstance(m.get("content"), list)
2890
+ and any(r.get("type") == "tool_result" for r in m["content"])
2891
+ for m in messages
2892
+ )
2893
+ if tools_ran_this_session:
2894
+ reply = ":white_check_mark: Done."
2895
+ else:
2896
+ greeting = f"Hi {user_name}! " if user_name else "Hi! "
2897
+ reply = f"{greeting}I'm Sentinel, your autonomous DevOps agent. How can I help you?"
2883
2898
  # Heuristic override: if reply ends with a question, Claude is waiting for input
2884
2899
  if is_done and re.search(r'\?\s*$', reply):
2885
2900
  is_done = False