@misterhuydo/sentinel 1.4.57 → 1.4.59
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/.hint-lock
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2026-03-
|
|
1
|
+
2026-03-25T12:30:48.361Z
|
package/.cairn/session.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"message": "Auto-checkpoint at 2026-03-25T12:
|
|
3
|
-
"checkpoint_at": "2026-03-25T12:
|
|
2
|
+
"message": "Auto-checkpoint at 2026-03-25T12:25:21.116Z",
|
|
3
|
+
"checkpoint_at": "2026-03-25T12:25:21.118Z",
|
|
4
4
|
"active_files": [],
|
|
5
5
|
"notes": [],
|
|
6
6
|
"mtime_snapshot": {}
|
package/package.json
CHANGED
|
@@ -74,6 +74,7 @@ class SentinelConfig:
|
|
|
74
74
|
sync_interval_seconds: int = 300
|
|
75
75
|
sync_retention_days: int = 30 # delete synced log files older than this many days
|
|
76
76
|
sync_max_file_mb: int = 200 # truncate synced log files exceeding this size (MB)
|
|
77
|
+
boss_mode: str = "standard" # standard | strict | fun
|
|
77
78
|
|
|
78
79
|
|
|
79
80
|
@dataclass
|
|
@@ -190,6 +191,8 @@ class ConfigLoader:
|
|
|
190
191
|
c.sync_interval_seconds = int(d.get("SYNC_INTERVAL_SECONDS", 300))
|
|
191
192
|
c.sync_retention_days = int(d.get("SYNC_RETENTION_DAYS", 30))
|
|
192
193
|
c.sync_max_file_mb = int(d.get("SYNC_MAX_FILE_MB", 200))
|
|
194
|
+
raw_mode = d.get("BOSS_MODE", "standard").lower().strip()
|
|
195
|
+
c.boss_mode = raw_mode if raw_mode in ("standard", "strict", "fun") else "standard"
|
|
193
196
|
self.sentinel = c
|
|
194
197
|
|
|
195
198
|
def _load_log_sources(self):
|
|
@@ -238,6 +238,7 @@ Events to subscribe: app_mention, message.im, message.channels
|
|
|
238
238
|
Tone: direct, professional, like a senior engineer who owns the system.
|
|
239
239
|
Don't pad responses. Don't say "Great question!" or "Certainly!".
|
|
240
240
|
If you don't know something, use a tool to find out before saying you don't know.
|
|
241
|
+
{BOSS_MODE_HINT}
|
|
241
242
|
|
|
242
243
|
When to act vs. when to ask:
|
|
243
244
|
- Any read/investigate tool (ask_codebase, filter_logs, search_logs, get_status, tail_log, ask_logs,
|
|
@@ -325,6 +326,31 @@ For greetings like "hello" or empty messages, introduce yourself briefly and off
|
|
|
325
326
|
If you need a follow-up from them, do NOT include [DONE] — wait for their next message.
|
|
326
327
|
"""
|
|
327
328
|
|
|
329
|
+
_BOSS_MODE_HINTS = {
|
|
330
|
+
"standard": (
|
|
331
|
+
"For requests that are clearly not DevOps tasks (jokes, stories, SVGs, general questions, "
|
|
332
|
+
"creative tasks) — just answer helpfully and naturally. No need to redirect back to "
|
|
333
|
+
"Sentinel's purpose."
|
|
334
|
+
),
|
|
335
|
+
"strict": (
|
|
336
|
+
"You are a DevOps-only assistant. If the user asks for something unrelated to software "
|
|
337
|
+
"engineering, infrastructure, or this project's operations (e.g. jokes, stories, creative "
|
|
338
|
+
"writing), politely decline and steer back to DevOps topics. Keep it brief and friendly."
|
|
339
|
+
),
|
|
340
|
+
"fun": (
|
|
341
|
+
"For requests that are clearly not DevOps tasks (jokes, stories, SVGs, creative writing, "
|
|
342
|
+
"trivia, anything fun) — engage fully and enthusiastically. You're a senior engineer who "
|
|
343
|
+
"also happens to be great company. Have fun with it, keep your personality, and don't "
|
|
344
|
+
"over-explain. Then offer to help with DevOps if relevant."
|
|
345
|
+
),
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def _resolve_system(boss_mode: str = "standard") -> str:
|
|
350
|
+
hint = _BOSS_MODE_HINTS.get(boss_mode, _BOSS_MODE_HINTS["standard"])
|
|
351
|
+
return _SYSTEM.replace("{BOSS_MODE_HINT}", hint)
|
|
352
|
+
|
|
353
|
+
|
|
328
354
|
# ── Tool definitions ─────────────────────────────────────────────────────────
|
|
329
355
|
|
|
330
356
|
_TOOLS = [
|
|
@@ -2641,7 +2667,7 @@ async def _handle_with_cli(
|
|
|
2641
2667
|
known_users = store.get_all_users()
|
|
2642
2668
|
users_hint = ", ".join(f"<@{uid}> = {name}" for uid, name in known_users.items())
|
|
2643
2669
|
prompt = (
|
|
2644
|
-
|
|
2670
|
+
_resolve_system(getattr(cfg_loader.sentinel, "boss_mode", "standard"))
|
|
2645
2671
|
+ (f"\nYou are speaking with: {user_name} (Slack mention: {slack_mention})" if user_name else "")
|
|
2646
2672
|
+ "\nAlways start your reply by addressing the user directly using their Slack mention, e.g. \"<@U123> here is what I found...\"."
|
|
2647
2673
|
+ " Never use their plain name — always use the <@USER_ID> format so Slack highlights it."
|
|
@@ -2840,7 +2866,7 @@ async def _handle_with_api(
|
|
|
2840
2866
|
else:
|
|
2841
2867
|
user_time_hint = ""
|
|
2842
2868
|
system = (
|
|
2843
|
-
|
|
2869
|
+
_resolve_system(getattr(cfg_loader.sentinel, "boss_mode", "standard"))
|
|
2844
2870
|
+ (f"\nYou are speaking with: {user_name} (Slack mention: {slack_mention})" if user_name else "")
|
|
2845
2871
|
+ "\nAlways start your reply by addressing the user directly using their Slack mention, e.g. \"<@U123> here is what I found...\"."
|
|
2846
2872
|
+ " Never use their plain name — always use the <@USER_ID> format so Slack highlights it."
|
|
@@ -59,3 +59,9 @@ WORKSPACE_DIR=./workspace
|
|
|
59
59
|
# Use "@Sentinel list watched bots" to see the current list.
|
|
60
60
|
# Comma-separated list of Slack bot IDs (starts with B, not U).
|
|
61
61
|
# SLACK_WATCH_BOT_IDS=B12345678, B87654321
|
|
62
|
+
|
|
63
|
+
# Boss conversation mode — controls how Boss handles off-topic requests (default: standard)
|
|
64
|
+
# standard — professional DevOps agent; off-topic questions answered helpfully but concisely
|
|
65
|
+
# strict — DevOps only; politely redirects off-topic requests (recommended for shared/enterprise workspaces)
|
|
66
|
+
# fun — fully open; jokes, stories, SVGs, creative tasks — Boss engages enthusiastically
|
|
67
|
+
# BOSS_MODE=standard
|