S-Dreamer commited on
Commit
6988b5e
·
verified ·
1 Parent(s): 7bec021

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +102 -29
app.py CHANGED
@@ -21,18 +21,22 @@ from huggingface_hub import InferenceClient
21
 
22
  TASK_REGISTRY: Dict[str, Any] = {}
23
 
 
24
  def _register_tasks():
25
  """
26
  Import tasks.* modules dynamically and pull their run() functions.
 
27
  """
28
- def _try(name, module):
 
29
  try:
30
  m = __import__(f"tasks.{module}", fromlist=["*"])
31
  fn = getattr(m, "run", None)
32
  if callable(fn):
33
  TASK_REGISTRY[name] = fn
34
  except Exception:
35
- pass # In HF Spaces, missing tasks won't break startup.
 
36
 
37
  _try("lookup_ip", "lookup_ip")
38
  _try("lookup_domain", "lookup_domain")
@@ -43,14 +47,15 @@ def _register_tasks():
43
  _try("mitre_map", "mitre_map")
44
  _try("quickscan", "quickscan")
45
 
46
- _register_tasks()
47
 
 
48
 
49
  # ---------------------------------------------------------------------
50
  # Task Execution + Normalization
51
  # ---------------------------------------------------------------------
52
 
53
- def call_task(name: str, payload: Dict[str, Any]):
 
54
  fn = TASK_REGISTRY.get(name)
55
  if not fn:
56
  return {"error": f"Unknown tool '{name}'."}
@@ -64,7 +69,7 @@ def call_task(name: str, payload: Dict[str, Any]):
64
  return {"error": str(e), "traceback": traceback.format_exc()}
65
 
66
 
67
- def normalize_result(res: Dict[str, Any]):
68
  """Ensures consistent UI formatting."""
69
  pretty = json.dumps(res, indent=2, default=str)
70
  summary = res.get("summary", "")
@@ -73,7 +78,8 @@ def normalize_result(res: Dict[str, Any]):
73
  if not markdown and summary:
74
  markdown = f"## Summary\n\n{summary}"
75
 
76
- safe_json = lambda v: json.dumps(v, indent=2, default=str) if v else ""
 
77
 
78
  return {
79
  "summary": summary,
@@ -89,6 +95,7 @@ def normalize_result(res: Dict[str, Any]):
89
  # Analyst Copilot LLM
90
  # ---------------------------------------------------------------------
91
 
 
92
  def respond(
93
  message,
94
  history,
@@ -101,11 +108,11 @@ def respond(
101
  ):
102
  """
103
  Streaming LLM output using WhiteRabbit Neo or Cybertron.
104
- hf_token is a raw string entered by user.
105
  """
106
  client = InferenceClient(
107
  model=model_name,
108
- token=hf_token, # Direct string, no OAuthToken object
109
  )
110
 
111
  msgs = [{"role": "system", "content": system_prompt}]
@@ -128,12 +135,17 @@ def respond(
128
 
129
 
130
  def inject_osint(history, osint_obj):
131
- """Inject OSINT result JSON into copilot context."""
 
 
 
132
  pretty = json.dumps(osint_obj, indent=2, default=str)
133
- history.append({
134
- "role": "system",
135
- "content": f"### Injected OSINT Result\n```\n{pretty}\n```"
136
- })
 
 
137
  return history
138
 
139
 
@@ -141,22 +153,49 @@ def inject_osint(history, osint_obj):
141
  # OSINT Dashboard Callbacks
142
  # ---------------------------------------------------------------------
143
 
 
144
  def ui_lookup_ip(ip, enrich, mitre):
145
  raw = call_task("lookup_ip", {"ip": ip, "enrich": enrich, "map_mitre": mitre})
146
  norm = normalize_result(raw)
147
- return norm["summary"], norm["markdown"], norm["json"], norm["mitre"], norm["stix"], raw
 
 
 
 
 
 
 
148
 
149
 
150
  def ui_lookup_domain(domain, enrich, mitre):
151
- raw = call_task("lookup_domain", {"domain": domain, "enrich": enrich, "map_mitre": mitre})
 
 
152
  norm = normalize_result(raw)
153
- return norm["summary"], norm["markdown"], norm["json"], norm["mitre"], norm["stix"], raw
 
 
 
 
 
 
 
154
 
155
 
156
  def ui_lookup_hash(h, ht, enrich, mitre):
157
- raw = call_task("lookup_hash", {"hash": h, "hash_type": ht, "enrich": enrich, "map_mitre": mitre})
 
 
 
158
  norm = normalize_result(raw)
159
- return norm["summary"], norm["markdown"], norm["json"], norm["mitre"], norm["stix"], raw
 
 
 
 
 
 
 
160
 
161
 
162
  def ui_correlate_iocs(iocs):
@@ -176,6 +215,7 @@ def ui_quickscan(target):
176
  # MCP Bridge
177
  # ---------------------------------------------------------------------
178
 
 
179
  def ui_bridge(tool, args_json):
180
  try:
181
  payload = json.loads(args_json)
@@ -191,10 +231,15 @@ def ui_bridge(tool, args_json):
191
  # UI Layout
192
  # ---------------------------------------------------------------------
193
 
 
194
  def build_interface():
195
  with gr.Blocks(title="Parrot OSINT MCP Console") as demo:
196
- gr.Markdown("# 🦜 Parrot OSINT MCP Console\nMulti-mode Intelligence Workstation.")
 
 
 
197
 
 
198
  osint_state = gr.State({})
199
 
200
  # -------------------------
@@ -218,9 +263,11 @@ def build_interface():
218
  run.click(
219
  ui_lookup_ip,
220
  [ip, enrich, mitre],
221
- [out_s, out_md, out_json, out_mitre, out_stix, osint_state]
222
  )
223
 
 
 
224
  # -------------------------
225
  # MCP Bridge
226
  # -------------------------
@@ -235,14 +282,16 @@ def build_interface():
235
  btn.click(
236
  ui_bridge,
237
  [tool, args],
238
- [out_bridge_json, out_bridge_md, osint_state]
239
  )
240
 
241
  # -------------------------
242
  # Analyst Copilot
243
  # -------------------------
244
  with gr.Tab("Analyst Copilot"):
245
- gr.Markdown("### WhiteRabbit Neo + Cybertron Threat Intelligence Assistant")
 
 
246
 
247
  system_prompt = gr.Textbox(
248
  label="System Prompt",
@@ -259,18 +308,23 @@ def build_interface():
259
  "berkeley-nest/WhiteRabbitNeo-8B",
260
  "cybertronai/cybertron-1.1-1b",
261
  "cybertronai/cybertron-1.1-7b",
262
- "cybertronai/cybertron-1.1-32b"
263
  ],
264
  value="berkeley-nest/WhiteRabbitNeo-8B",
265
  )
266
 
267
- gr.Markdown("### HuggingFace API Token (required for LLM inference)")
 
 
268
  hf_token = gr.Textbox(
269
  label="HF Token",
270
  type="password",
271
  placeholder="hf_xxx...",
272
  )
273
 
 
 
 
274
  chatbot = gr.ChatInterface(
275
  respond,
276
  type="messages",
@@ -278,17 +332,36 @@ def build_interface():
278
  system_prompt,
279
  model_select,
280
  hf_token,
281
- gr.Slider(0.1, 2.0, value=0.7, step=0.1, label="Temperature"),
282
- gr.Slider(0.1, 1.0, value=0.95, step=0.05, label="Top-p"),
283
- gr.Slider(32, 4096, value=512, step=32, label="Max Tokens"),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
284
  ],
 
285
  )
286
 
287
  inject_btn = gr.Button("Inject Last OSINT Result into Copilot")
288
  inject_btn.click(
289
  inject_osint,
290
- [chatbot._chatbot_state, osint_state],
291
- [chatbot._chatbot_state],
292
  )
293
 
294
  return demo
 
21
 
22
  TASK_REGISTRY: Dict[str, Any] = {}
23
 
24
+
25
  def _register_tasks():
26
  """
27
  Import tasks.* modules dynamically and pull their run() functions.
28
+ Missing modules are ignored so the UI can still boot.
29
  """
30
+
31
+ def _try(name: str, module: str):
32
  try:
33
  m = __import__(f"tasks.{module}", fromlist=["*"])
34
  fn = getattr(m, "run", None)
35
  if callable(fn):
36
  TASK_REGISTRY[name] = fn
37
  except Exception:
38
+ # In Spaces, you might not have all tasks yet; that's fine.
39
+ pass
40
 
41
  _try("lookup_ip", "lookup_ip")
42
  _try("lookup_domain", "lookup_domain")
 
47
  _try("mitre_map", "mitre_map")
48
  _try("quickscan", "quickscan")
49
 
 
50
 
51
+ _register_tasks()
52
 
53
  # ---------------------------------------------------------------------
54
  # Task Execution + Normalization
55
  # ---------------------------------------------------------------------
56
 
57
+
58
+ def call_task(name: str, payload: Dict[str, Any]) -> Dict[str, Any]:
59
  fn = TASK_REGISTRY.get(name)
60
  if not fn:
61
  return {"error": f"Unknown tool '{name}'."}
 
69
  return {"error": str(e), "traceback": traceback.format_exc()}
70
 
71
 
72
+ def normalize_result(res: Dict[str, Any]) -> Dict[str, str]:
73
  """Ensures consistent UI formatting."""
74
  pretty = json.dumps(res, indent=2, default=str)
75
  summary = res.get("summary", "")
 
78
  if not markdown and summary:
79
  markdown = f"## Summary\n\n{summary}"
80
 
81
+ def safe_json(value: Any) -> str:
82
+ return json.dumps(value, indent=2, default=str) if value else ""
83
 
84
  return {
85
  "summary": summary,
 
95
  # Analyst Copilot LLM
96
  # ---------------------------------------------------------------------
97
 
98
+
99
  def respond(
100
  message,
101
  history,
 
108
  ):
109
  """
110
  Streaming LLM output using WhiteRabbit Neo or Cybertron.
111
+ `hf_token` is a raw string entered by the user.
112
  """
113
  client = InferenceClient(
114
  model=model_name,
115
+ token=hf_token, # Direct string token
116
  )
117
 
118
  msgs = [{"role": "system", "content": system_prompt}]
 
135
 
136
 
137
  def inject_osint(history, osint_obj):
138
+ """
139
+ Inject OSINT result JSON into the copilot's chat history as a system message.
140
+ `history` is the ChatInterface state (list of messages).
141
+ """
142
  pretty = json.dumps(osint_obj, indent=2, default=str)
143
+ history.append(
144
+ {
145
+ "role": "system",
146
+ "content": f"### Injected OSINT Result\n```\n{pretty}\n```",
147
+ }
148
+ )
149
  return history
150
 
151
 
 
153
  # OSINT Dashboard Callbacks
154
  # ---------------------------------------------------------------------
155
 
156
+
157
  def ui_lookup_ip(ip, enrich, mitre):
158
  raw = call_task("lookup_ip", {"ip": ip, "enrich": enrich, "map_mitre": mitre})
159
  norm = normalize_result(raw)
160
+ return (
161
+ norm["summary"],
162
+ norm["markdown"],
163
+ norm["json"],
164
+ norm["mitre"],
165
+ norm["stix"],
166
+ raw,
167
+ )
168
 
169
 
170
  def ui_lookup_domain(domain, enrich, mitre):
171
+ raw = call_task(
172
+ "lookup_domain", {"domain": domain, "enrich": enrich, "map_mitre": mitre}
173
+ )
174
  norm = normalize_result(raw)
175
+ return (
176
+ norm["summary"],
177
+ norm["markdown"],
178
+ norm["json"],
179
+ norm["mitre"],
180
+ norm["stix"],
181
+ raw,
182
+ )
183
 
184
 
185
  def ui_lookup_hash(h, ht, enrich, mitre):
186
+ raw = call_task(
187
+ "lookup_hash",
188
+ {"hash": h, "hash_type": ht, "enrich": enrich, "map_mitre": mitre},
189
+ )
190
  norm = normalize_result(raw)
191
+ return (
192
+ norm["summary"],
193
+ norm["markdown"],
194
+ norm["json"],
195
+ norm["mitre"],
196
+ norm["stix"],
197
+ raw,
198
+ )
199
 
200
 
201
  def ui_correlate_iocs(iocs):
 
215
  # MCP Bridge
216
  # ---------------------------------------------------------------------
217
 
218
+
219
  def ui_bridge(tool, args_json):
220
  try:
221
  payload = json.loads(args_json)
 
231
  # UI Layout
232
  # ---------------------------------------------------------------------
233
 
234
+
235
  def build_interface():
236
  with gr.Blocks(title="Parrot OSINT MCP Console") as demo:
237
+ gr.Markdown(
238
+ "# 🦜 Parrot OSINT MCP Console\n"
239
+ "Multi-mode Intelligence Workstation."
240
+ )
241
 
242
+ # Holds the last OSINT result (dict) to inject into the copilot
243
  osint_state = gr.State({})
244
 
245
  # -------------------------
 
263
  run.click(
264
  ui_lookup_ip,
265
  [ip, enrich, mitre],
266
+ [out_s, out_md, out_json, out_mitre, out_stix, osint_state],
267
  )
268
 
269
+ # You can add more tabs here: Domain Lookup, Hash Lookup, Correlate IOCs, Quickscan
270
+
271
  # -------------------------
272
  # MCP Bridge
273
  # -------------------------
 
282
  btn.click(
283
  ui_bridge,
284
  [tool, args],
285
+ [out_bridge_json, out_bridge_md, osint_state],
286
  )
287
 
288
  # -------------------------
289
  # Analyst Copilot
290
  # -------------------------
291
  with gr.Tab("Analyst Copilot"):
292
+ gr.Markdown(
293
+ "### WhiteRabbit Neo + Cybertron Threat Intelligence Assistant"
294
+ )
295
 
296
  system_prompt = gr.Textbox(
297
  label="System Prompt",
 
308
  "berkeley-nest/WhiteRabbitNeo-8B",
309
  "cybertronai/cybertron-1.1-1b",
310
  "cybertronai/cybertron-1.1-7b",
311
+ "cybertronai/cybertron-1.1-32b",
312
  ],
313
  value="berkeley-nest/WhiteRabbitNeo-8B",
314
  )
315
 
316
+ gr.Markdown(
317
+ "### HuggingFace API Token (required for LLM inference)"
318
+ )
319
  hf_token = gr.Textbox(
320
  label="HF Token",
321
  type="password",
322
  placeholder="hf_xxx...",
323
  )
324
 
325
+ # Chat history state for the copilot (list of messages)
326
+ chat_state = gr.State([])
327
+
328
  chatbot = gr.ChatInterface(
329
  respond,
330
  type="messages",
 
332
  system_prompt,
333
  model_select,
334
  hf_token,
335
+ gr.Slider(
336
+ 0.1,
337
+ 2.0,
338
+ value=0.7,
339
+ step=0.1,
340
+ label="Temperature",
341
+ ),
342
+ gr.Slider(
343
+ 0.1,
344
+ 1.0,
345
+ value=0.95,
346
+ step=0.05,
347
+ label="Top-p",
348
+ ),
349
+ gr.Slider(
350
+ 32,
351
+ 4096,
352
+ value=512,
353
+ step=32,
354
+ label="Max Tokens",
355
+ ),
356
  ],
357
+ state=chat_state,
358
  )
359
 
360
  inject_btn = gr.Button("Inject Last OSINT Result into Copilot")
361
  inject_btn.click(
362
  inject_osint,
363
+ inputs=[chat_state, osint_state],
364
+ outputs=[chat_state],
365
  )
366
 
367
  return demo