@misterhuydo/sentinel 1.0.45 → 1.0.46
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 +58 -18
package/.cairn/session.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"message": "Auto-checkpoint at 2026-03-22T05:
|
|
3
|
-
"checkpoint_at": "2026-03-22T05:
|
|
2
|
+
"message": "Auto-checkpoint at 2026-03-22T05:40:32.023Z",
|
|
3
|
+
"checkpoint_at": "2026-03-22T05:40:32.024Z",
|
|
4
4
|
"active_files": [],
|
|
5
5
|
"notes": [],
|
|
6
6
|
"mtime_snapshot": {}
|
package/package.json
CHANGED
|
@@ -29,17 +29,20 @@ and opens GitHub PRs for admin review (or pushes directly if AUTO_PUBLISH=true).
|
|
|
29
29
|
Your job:
|
|
30
30
|
- Understand what the DevOps engineer needs in natural language
|
|
31
31
|
- Query Sentinel's live state (errors, fixes, open PRs) on their behalf
|
|
32
|
-
-
|
|
32
|
+
- Deliver tasks/issues to the right project — you know all projects in this workspace
|
|
33
33
|
- Control Sentinel (pause/resume) when asked
|
|
34
34
|
- Give honest, concise answers — you know this system inside out
|
|
35
|
+
- If a project name is unclear or ambiguous, ask the engineer to clarify — never guess
|
|
35
36
|
|
|
36
37
|
What you can do (tools available):
|
|
37
38
|
|
|
38
39
|
1. get_status — Show recent errors detected, fixes applied/pending, open PRs.
|
|
39
40
|
e.g. "what happened today?", "any issues?", "show open PRs"
|
|
40
41
|
|
|
41
|
-
2. create_issue —
|
|
42
|
-
|
|
42
|
+
2. create_issue — Deliver a fix/task to any project in this workspace by short name.
|
|
43
|
+
You know all project names — use list_projects if you're unsure.
|
|
44
|
+
If the project name is ambiguous or not found, ask to clarify.
|
|
45
|
+
e.g. "tell 1881 to fix X", "look into Y in elprint", "investigate Z"
|
|
43
46
|
|
|
44
47
|
3. pause_sentinel — Create SENTINEL_PAUSE file to halt all auto-fix activity.
|
|
45
48
|
e.g. "pause sentinel", "stop auto-fixing"
|
|
@@ -69,8 +72,11 @@ What you can do (tools available):
|
|
|
69
72
|
11. list_errors — List recent errors from the state store, optionally filtered by repo or source.
|
|
70
73
|
e.g. "show all errors today", "what errors hit elprint this week?"
|
|
71
74
|
|
|
72
|
-
12. pull_repo — Run git pull on one or all managed repos.
|
|
73
|
-
e.g. "pull changes
|
|
75
|
+
12. pull_repo — Run git pull on one or all managed application repos.
|
|
76
|
+
e.g. "pull changes", "git pull all repos", "update the code"
|
|
77
|
+
|
|
78
|
+
13. pull_config — Run git pull on one or all Sentinel project config dirs.
|
|
79
|
+
e.g. "pull config for 1881", "update sentinel config", "pull all configs"
|
|
74
80
|
|
|
75
81
|
Tone: direct, professional, like a senior engineer who owns the system.
|
|
76
82
|
Don't pad responses. Don't say "Great question!" or "Certainly!".
|
|
@@ -104,20 +110,25 @@ _TOOLS = [
|
|
|
104
110
|
{
|
|
105
111
|
"name": "create_issue",
|
|
106
112
|
"description": (
|
|
107
|
-
"
|
|
108
|
-
"Use
|
|
109
|
-
"
|
|
113
|
+
"Deliver a fix/task request to a Sentinel project instance. "
|
|
114
|
+
"Use when the engineer says 'tell 1881 to do X', 'look into Y in project elprint', "
|
|
115
|
+
"'implement this in 1881: ...'. Can target any project by short name. "
|
|
116
|
+
"Defaults to the current project if no project is specified."
|
|
110
117
|
),
|
|
111
118
|
"input_schema": {
|
|
112
119
|
"type": "object",
|
|
113
120
|
"properties": {
|
|
114
121
|
"description": {
|
|
115
122
|
"type": "string",
|
|
116
|
-
"description": "Full problem description — everything the engineer told you",
|
|
123
|
+
"description": "Full task/problem description — everything the engineer told you",
|
|
124
|
+
},
|
|
125
|
+
"project": {
|
|
126
|
+
"type": "string",
|
|
127
|
+
"description": "Project short name to deliver to (e.g. '1881', 'elprint'). Omit for current project.",
|
|
117
128
|
},
|
|
118
129
|
"target_repo": {
|
|
119
130
|
"type": "string",
|
|
120
|
-
"description": "
|
|
131
|
+
"description": "Specific repo within the project (omit to let Sentinel auto-route)",
|
|
121
132
|
},
|
|
122
133
|
},
|
|
123
134
|
"required": ["description"],
|
|
@@ -349,16 +360,43 @@ def _run_tool(name: str, inputs: dict, cfg_loader, store) -> str:
|
|
|
349
360
|
if name == "create_issue":
|
|
350
361
|
description = inputs["description"]
|
|
351
362
|
target_repo = inputs.get("target_repo", "")
|
|
352
|
-
|
|
363
|
+
project_arg = inputs.get("project", "")
|
|
364
|
+
|
|
365
|
+
if project_arg:
|
|
366
|
+
project_dirs = _find_project_dirs(project_arg)
|
|
367
|
+
if not project_dirs:
|
|
368
|
+
all_names = [_short_name(d.name) for d in _find_project_dirs()]
|
|
369
|
+
return json.dumps({
|
|
370
|
+
"error": f"No project found matching '{project_arg}'",
|
|
371
|
+
"available_projects": all_names,
|
|
372
|
+
"action_needed": "Ask the user which project they meant.",
|
|
373
|
+
})
|
|
374
|
+
if len(project_dirs) > 1:
|
|
375
|
+
matches = [_short_name(d.name) for d in project_dirs]
|
|
376
|
+
return json.dumps({
|
|
377
|
+
"error": f"Ambiguous project name '{project_arg}' — matches: {matches}",
|
|
378
|
+
"action_needed": "Ask the user to clarify which project they mean.",
|
|
379
|
+
})
|
|
380
|
+
project_dir = project_dirs[0]
|
|
381
|
+
else:
|
|
382
|
+
project_dir = Path(".")
|
|
383
|
+
|
|
384
|
+
issues_dir = project_dir / "issues"
|
|
353
385
|
issues_dir.mkdir(exist_ok=True)
|
|
354
386
|
fname = f"slack-{uuid.uuid4().hex[:8]}.txt"
|
|
355
387
|
content = (f"TARGET_REPO: {target_repo}\n\n" if target_repo else "") + description
|
|
356
388
|
(issues_dir / fname).write_text(content, encoding="utf-8")
|
|
357
|
-
|
|
389
|
+
|
|
390
|
+
# Touch SENTINEL_POLL_NOW so the target instance picks it up immediately
|
|
391
|
+
(project_dir / "SENTINEL_POLL_NOW").touch()
|
|
392
|
+
|
|
393
|
+
project_label = _short_name(project_dir.resolve().name) if project_arg else "this project"
|
|
394
|
+
logger.info("Boss created issue for %s: %s", project_label, fname)
|
|
358
395
|
return json.dumps({
|
|
359
|
-
"status":
|
|
360
|
-
"
|
|
361
|
-
"
|
|
396
|
+
"status": "queued",
|
|
397
|
+
"project": project_label,
|
|
398
|
+
"file": fname,
|
|
399
|
+
"note": f"Delivered to '{project_label}'. Sentinel will process it on the next poll cycle.",
|
|
362
400
|
})
|
|
363
401
|
|
|
364
402
|
if name == "get_fix_details":
|
|
@@ -662,14 +700,16 @@ async def handle_message(
|
|
|
662
700
|
client = anthropic.Anthropic(api_key=api_key)
|
|
663
701
|
|
|
664
702
|
# Build system context snapshot
|
|
665
|
-
paused
|
|
666
|
-
repos
|
|
667
|
-
ts
|
|
703
|
+
paused = Path("SENTINEL_PAUSE").exists()
|
|
704
|
+
repos = list(cfg_loader.repos.keys())
|
|
705
|
+
ts = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC")
|
|
706
|
+
known_projects = [_short_name(d.name) for d in _find_project_dirs()]
|
|
668
707
|
system = (
|
|
669
708
|
_SYSTEM
|
|
670
709
|
+ f"\n\nCurrent time: {ts}"
|
|
671
710
|
+ f"\nSentinel status: {'⏸ PAUSED' if paused else '▶ RUNNING'}"
|
|
672
711
|
+ f"\nManaged repos: {', '.join(repos) if repos else '(none configured)'}"
|
|
712
|
+
+ (f"\nKnown projects in workspace: {', '.join(known_projects)}" if known_projects else "")
|
|
673
713
|
)
|
|
674
714
|
|
|
675
715
|
history.append({"role": "user", "content": message})
|