@misterhuydo/sentinel 1.2.1 → 1.2.3

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-23T09:27:13.974Z",
3
- "checkpoint_at": "2026-03-23T09:27:13.976Z",
2
+ "message": "Auto-checkpoint at 2026-03-23T09:45:10.463Z",
3
+ "checkpoint_at": "2026-03-23T09:45:10.464Z",
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.2.1",
3
+ "version": "1.2.3",
4
4
  "description": "Sentinel — Autonomous DevOps Agent installer and manager",
5
5
  "bin": {
6
6
  "sentinel": "./bin/sentinel.js"
@@ -187,6 +187,13 @@ Session context — critical rules:
187
187
  - When handling a new request, call the tools fresh. Do not assume any prior tool result is still current or that any prior step "counts" toward the current task.
188
188
  - The only exception: if the user explicitly asks about something from the history ("what did you find earlier?"), you may reference it — but note it is from a prior session.
189
189
 
190
+ Trust your tool results — never contradict them:
191
+ - If any search_logs call in this response returned total_matches > 0, you HAVE results. Report them.
192
+ - Never say "no results found" or "nothing was found" when a tool result shows total_matches > 0.
193
+ - If one source-specific call returns 0 but a broader call returned matches, use the broader results.
194
+ - A cached result with files_searched=0 is a source-name lookup failure, NOT an absence of log data.
195
+ Treat it as "source not recognised" and fall back to the broad search results you already have.
196
+
190
197
  Avoid redundant tool calls (within a single response only — always run tools fresh for new requests):
191
198
  - If a broad search (e.g. search_logs with no source filter) already returned results in THIS response, do NOT repeat the same search with a source filter to "refine" — use what you already fetched.
192
199
  - If a tool call fails in THIS response, do NOT retry the entire search from scratch. Continue with what succeeded and note the failure.
@@ -361,6 +368,14 @@ _TOOLS = [
361
368
  "description": "Max matching lines to return per source (default 30)",
362
369
  "default": 30,
363
370
  },
371
+ "tail": {
372
+ "type": "integer",
373
+ "description": (
374
+ "Number of log lines to fetch from the server before grepping (default: config value, typically 500). "
375
+ "Increase when the user asks for a longer time window — e.g. 'yesterday up to now' → use 5000-10000. "
376
+ "Higher values take longer but cover more history."
377
+ ),
378
+ },
364
379
  },
365
380
  "required": ["query"],
366
381
  },
@@ -1077,6 +1092,7 @@ async def _run_tool(name: str, inputs: dict, cfg_loader, store, slack_client=Non
1077
1092
  query = inputs.get("query", "")
1078
1093
  source = inputs.get("source", "").lower()
1079
1094
  max_matches = int(inputs.get("max_matches", 30))
1095
+ tail_override = inputs.get("tail")
1080
1096
 
1081
1097
  # ── Live fetch path: SSH to servers and grep in real time ──────────────
1082
1098
  script = Path(__file__).resolve().parent.parent / "scripts" / "fetch_log.sh"
@@ -1088,6 +1104,8 @@ async def _run_tool(name: str, inputs: dict, cfg_loader, store, slack_client=Non
1088
1104
  for props in props_files:
1089
1105
  env = os.environ.copy()
1090
1106
  env["GREP_FILTER"] = query
1107
+ if tail_override:
1108
+ env["TAIL"] = str(tail_override)
1091
1109
  try:
1092
1110
  r = subprocess.run(
1093
1111
  ["bash", str(script), str(props)],
@@ -1111,9 +1129,15 @@ async def _run_tool(name: str, inputs: dict, cfg_loader, store, slack_client=Non
1111
1129
  })
1112
1130
 
1113
1131
  # ── Fallback: search locally-cached log files ──────────────────────────
1132
+ # Reaching here means: live script unavailable OR source filter matched no config files.
1133
+ # A result with files_searched=0 means the source name wasn't recognised — NOT that
1134
+ # there are no log entries. Do not interpret this as "no results found".
1114
1135
  fetched_dir = Path("workspace/fetched")
1115
1136
  if not fetched_dir.exists():
1116
- return json.dumps({"error": "No fetched logs found and fetch_log.sh unavailable"})
1137
+ return json.dumps({
1138
+ "error": "No fetched logs found and fetch_log.sh unavailable",
1139
+ "note": "This is a config/setup problem, not a 'no results' answer.",
1140
+ })
1117
1141
  try:
1118
1142
  pattern = re.compile(query, re.IGNORECASE)
1119
1143
  except re.error as e:
@@ -1134,13 +1158,21 @@ async def _run_tool(name: str, inputs: dict, cfg_loader, store, slack_client=Non
1134
1158
  except Exception:
1135
1159
  pass
1136
1160
  total = sum(len(r["matches"]) for r in results)
1137
- return json.dumps({
1161
+ files_searched = len(list(fetched_dir.glob("*.log")))
1162
+ result = {
1138
1163
  "query": query,
1139
1164
  "mode": "cached",
1140
1165
  "total_matches": total,
1141
- "files_searched": len(list(fetched_dir.glob("*.log"))),
1166
+ "files_searched": files_searched,
1142
1167
  "results": results,
1143
- })
1168
+ }
1169
+ if files_searched == 0:
1170
+ result["warning"] = (
1171
+ "No cached log files found for this source filter. "
1172
+ "This means the source name was not recognised — not that there are no log entries. "
1173
+ "Try search_logs without a source filter to search all sources."
1174
+ )
1175
+ return json.dumps(result)
1144
1176
 
1145
1177
  if name == "trigger_poll":
1146
1178
  Path("SENTINEL_POLL_NOW").touch()