@misterhuydo/sentinel 1.4.53 → 1.4.55
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/.cairn/session.json +2 -2
- package/package.json +1 -1
- package/python/sentinel/sentinel_boss.py +42 -27
package/.cairn/session.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"message": "Auto-checkpoint at 2026-03-
|
|
3
|
-
"checkpoint_at": "2026-03-
|
|
2
|
+
"message": "Auto-checkpoint at 2026-03-25T12:06:52.775Z",
|
|
3
|
+
"checkpoint_at": "2026-03-25T12:06:52.777Z",
|
|
4
4
|
"active_files": [],
|
|
5
5
|
"notes": [],
|
|
6
6
|
"mtime_snapshot": {}
|
package/package.json
CHANGED
|
@@ -296,27 +296,28 @@ Avoid redundant tool calls (within a single response only — always run tools f
|
|
|
296
296
|
- If a tool call fails in THIS response, do NOT retry the entire search from scratch. Continue with what succeeded and note the failure.
|
|
297
297
|
- One pass per task: gather all needed data in a single round of tool calls, then produce the final answer.
|
|
298
298
|
|
|
299
|
-
Issue identification —
|
|
299
|
+
Issue identification — create_issue autonomy:
|
|
300
|
+
Sentinel is a 24/7 autonomous agent. Act on clear signals without asking permission.
|
|
301
|
+
|
|
300
302
|
1. Determine if the message is a REAL issue/task (bug report, feature request, investigation ask)
|
|
301
303
|
vs. a status question, tool query, or casual chat. If not an issue, just answer normally.
|
|
302
|
-
2. If it IS an issue
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
-
|
|
306
|
-
-
|
|
307
|
-
- Identity: always captured automatically from the Slack session.
|
|
304
|
+
2. If it IS an issue — gather context, run relevant read tools (logs, codebase) if useful, then
|
|
305
|
+
create the issue immediately. Do NOT ask "Should I create this?" or "Does that look right?"
|
|
306
|
+
ONLY pause if a critical piece of information is genuinely missing and cannot be inferred:
|
|
307
|
+
- Project is completely unknown AND list_projects doesn't help → ask once, briefly.
|
|
308
|
+
- Everything else: use your best judgment and act.
|
|
308
309
|
3. Populate `findings` with curated evidence — only when relevant and concise:
|
|
309
|
-
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
310
|
+
- Summarise: which services, how often, key pattern, 1-3 example lines. Max 500 words.
|
|
311
|
+
- Do NOT paste raw tool output.
|
|
312
|
+
4. After creating, tell them the issue was queued and Sentinel will pick it up on the next poll.
|
|
313
|
+
|
|
314
|
+
Autonomous action policy — Sentinel acts, humans review outcomes:
|
|
315
|
+
- Read/investigate tools → always act immediately, no confirmation needed.
|
|
316
|
+
- create_issue, retry_issue, trigger_poll, install_tool, pull_repo → act immediately when
|
|
317
|
+
intent is clear. Only pause for genuinely ambiguous target (unknown project/repo).
|
|
318
|
+
- merge_pr → confirm once: "Merging PR #N for <repo> to <branch> — confirm?" Then act.
|
|
319
|
+
- pause_sentinel → confirm once (halts all monitoring).
|
|
320
|
+
- Everything else → use judgment. When in doubt, act and report what you did.
|
|
320
321
|
|
|
321
322
|
When the engineer's request is fully handled, end your LAST message with the token: [DONE]
|
|
322
323
|
IMPORTANT: Always write your actual reply text FIRST, then append [DONE] at the end. Example: "Hello! I'm Sentinel. [DONE]". Never output [DONE] as your only content.
|
|
@@ -348,11 +349,11 @@ _TOOLS = [
|
|
|
348
349
|
{
|
|
349
350
|
"name": "create_issue",
|
|
350
351
|
"description": (
|
|
351
|
-
"Deliver
|
|
352
|
-
"
|
|
353
|
-
"(2)
|
|
354
|
-
"
|
|
355
|
-
"
|
|
352
|
+
"Deliver an issue/task to a Sentinel project instance. "
|
|
353
|
+
"Call this as soon as you have identified: (1) a real issue or task (not a status question "
|
|
354
|
+
"or casual chat), (2) the target project, (3) enough context to describe the problem. "
|
|
355
|
+
"Act immediately — do not ask the user for confirmation first. "
|
|
356
|
+
"Only pause if the target project is genuinely unknown and cannot be inferred."
|
|
356
357
|
),
|
|
357
358
|
"input_schema": {
|
|
358
359
|
"type": "object",
|
|
@@ -2696,12 +2697,14 @@ async def _handle_with_cli(
|
|
|
2696
2697
|
logger.error("Boss CLI call failed: %s", e)
|
|
2697
2698
|
return f":warning: Boss unavailable: {e}", True
|
|
2698
2699
|
|
|
2700
|
+
tools_ran = []
|
|
2699
2701
|
for m in _ACTION_RE.finditer(output):
|
|
2700
2702
|
try:
|
|
2701
2703
|
action = json.loads(m.group(1))
|
|
2702
2704
|
name = action.pop("action", "")
|
|
2703
2705
|
if name:
|
|
2704
2706
|
result_str = await _run_tool(name, action, cfg_loader, store, user_id=user_id)
|
|
2707
|
+
tools_ran.append(name)
|
|
2705
2708
|
logger.info("Boss CLI action: %s → %s", name, result_str[:80])
|
|
2706
2709
|
except Exception as e:
|
|
2707
2710
|
logger.warning("Boss action parse error: %s", e)
|
|
@@ -2710,8 +2713,11 @@ async def _handle_with_cli(
|
|
|
2710
2713
|
is_done = "[DONE]" in reply
|
|
2711
2714
|
reply = reply.replace("[DONE]", "").strip()
|
|
2712
2715
|
if not reply:
|
|
2713
|
-
|
|
2714
|
-
|
|
2716
|
+
if tools_ran:
|
|
2717
|
+
reply = f":white_check_mark: Done ({', '.join(tools_ran)})."
|
|
2718
|
+
else:
|
|
2719
|
+
greeting = f"Hi {user_name}! " if user_name else "Hi! "
|
|
2720
|
+
reply = f"{greeting}I'm Sentinel, your autonomous DevOps agent. How can I help you?"
|
|
2715
2721
|
|
|
2716
2722
|
history.append({"role": "user", "content": message})
|
|
2717
2723
|
history.append({"role": "assistant", "content": reply})
|
|
@@ -2877,8 +2883,17 @@ async def _handle_with_api(
|
|
|
2877
2883
|
is_done = "[DONE]" in reply
|
|
2878
2884
|
reply = reply.replace("[DONE]", "").strip()
|
|
2879
2885
|
if not reply:
|
|
2880
|
-
|
|
2881
|
-
|
|
2886
|
+
# Only greet on a truly empty/hello message — not after tool execution
|
|
2887
|
+
tools_ran_this_session = any(
|
|
2888
|
+
m.get("role") == "user" and isinstance(m.get("content"), list)
|
|
2889
|
+
and any(r.get("type") == "tool_result" for r in m["content"])
|
|
2890
|
+
for m in messages
|
|
2891
|
+
)
|
|
2892
|
+
if tools_ran_this_session:
|
|
2893
|
+
reply = ":white_check_mark: Done."
|
|
2894
|
+
else:
|
|
2895
|
+
greeting = f"Hi {user_name}! " if user_name else "Hi! "
|
|
2896
|
+
reply = f"{greeting}I'm Sentinel, your autonomous DevOps agent. How can I help you?"
|
|
2882
2897
|
# Heuristic override: if reply ends with a question, Claude is waiting for input
|
|
2883
2898
|
if is_done and re.search(r'\?\s*$', reply):
|
|
2884
2899
|
is_done = False
|