loki-mode 6.73.1 → 6.74.0

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.
Files changed (70) hide show
  1. package/LICENSE +2 -0
  2. package/SKILL.md +8 -4
  3. package/VERSION +1 -1
  4. package/dashboard/__init__.py +1 -1
  5. package/dashboard/server.py +247 -1
  6. package/docs/INSTALLATION.md +1 -1
  7. package/mcp/__init__.py +1 -1
  8. package/package.json +1 -1
  9. package/web-app/dist/assets/{AdminPage-iWZB_xo6.js → AdminPage-_tI-DDJH.js} +2 -2
  10. package/web-app/dist/assets/Avatar-CzqKTLpE.js +6 -0
  11. package/web-app/dist/assets/{Badge-7_-AUQsz.js → Badge-D1wzRJkX.js} +1 -1
  12. package/web-app/dist/assets/{Button-C0spb1Uw.js → Button-CYGcdukI.js} +1 -1
  13. package/web-app/dist/assets/{ComparePage-DbS1sOwZ.js → ComparePage-ZQ92Ob4z.js} +1 -1
  14. package/web-app/dist/assets/GitHubIssuesPanel-C0QQO7rE.js +17 -0
  15. package/web-app/dist/assets/GitHubPRsPanel-D_dcefsN.js +17 -0
  16. package/web-app/dist/assets/HomePage-hXF60uhR.js +28 -0
  17. package/web-app/dist/assets/{LoginPage-DAvTqpCV.js → LoginPage-BB5ovU-v.js} +1 -1
  18. package/web-app/dist/assets/{MetricsPage-na-RTWaj.js → MetricsPage-CDktpwJU.js} +1 -1
  19. package/web-app/dist/assets/NotFoundPage-ChbuKZug.js +1 -0
  20. package/web-app/dist/assets/ProjectPage-Bg_iB9fR.js +287 -0
  21. package/web-app/dist/assets/{ProjectsPage-gQyc9LU9.js → ProjectsPage-CtYbkLUY.js} +1 -1
  22. package/web-app/dist/assets/{SettingsPage-bMY5uKwO.js → SettingsPage-Dv9LWh__.js} +1 -1
  23. package/web-app/dist/assets/{ShowcasePage-C05_1W29.js → ShowcasePage-CUcwmKXK.js} +1 -1
  24. package/web-app/dist/assets/{SystemSettingsPage-D1tMDxIN.js → SystemSettingsPage-wExXyxQ-.js} +1 -1
  25. package/web-app/dist/assets/{TeamsPage-D-dlvdrK.js → TeamsPage-vfNcTTrZ.js} +2 -2
  26. package/web-app/dist/assets/{TemplatesPage-_zJFBcbN.js → TemplatesPage-DykEaiQv.js} +1 -1
  27. package/web-app/dist/assets/{TerminalOutput-tm07J4dD.js → TerminalOutput-elG2cTB3.js} +1 -1
  28. package/web-app/dist/assets/{activity-DicKfzsP.js → activity-Cc_Lxe6l.js} +1 -1
  29. package/web-app/dist/assets/{bell-BFjvQnJx.js → bell-CaP8yKuo.js} +1 -1
  30. package/web-app/dist/assets/{bot-B35Xf30p.js → bot-Czr4bhA-.js} +1 -1
  31. package/web-app/dist/assets/{check-Ck2kcsO2.js → check-CyZMFrVP.js} +1 -1
  32. package/web-app/dist/assets/{chevron-left-BlMYWHUT.js → chevron-left-B7GlH2RP.js} +1 -1
  33. package/web-app/dist/assets/{circle-alert-BgoWCgi3.js → circle-alert-Cn3wOAee.js} +1 -1
  34. package/web-app/dist/assets/{clock-8-8I4vDX.js → clock-BgDwqVg2.js} +1 -1
  35. package/web-app/dist/assets/{cloud-DIxBvxak.js → cloud-7zbPlpRr.js} +1 -1
  36. package/web-app/dist/assets/{copy-D3bp38SQ.js → copy-C3mlG0DN.js} +1 -1
  37. package/web-app/dist/assets/{database-WnB0jRbx.js → database-ndWcDAoa.js} +1 -1
  38. package/web-app/dist/assets/{dollar-sign-DdIr6uXn.js → dollar-sign-DvbonzNh.js} +1 -1
  39. package/web-app/dist/assets/{file-code-corner-CYvOV3oD.js → file-code-corner-CN598VYP.js} +1 -1
  40. package/web-app/dist/assets/{file-plus-nPF3UxIN.js → file-plus-C73kytfr.js} +1 -1
  41. package/web-app/dist/assets/{folder-open-DjWfr--L.js → folder-open-fgrz3ALE.js} +1 -1
  42. package/web-app/dist/assets/{git-commit-horizontal-BhMiJhih.js → git-commit-horizontal-C5o2smjW.js} +1 -1
  43. package/web-app/dist/assets/{globe-BmiZUUW8.js → globe--RVntJ63.js} +1 -1
  44. package/web-app/dist/assets/{hammer-DbUBDETj.js → hammer-B8rdFNHw.js} +1 -1
  45. package/web-app/dist/assets/{index-rTnHmRAz.js → index-C7230tHo.js} +76 -76
  46. package/web-app/dist/assets/index-CVM4A1Fw.css +1 -0
  47. package/web-app/dist/assets/{layers-Ci_g9-gn.js → layers-DBVHQA2R.js} +1 -1
  48. package/web-app/dist/assets/{lightbulb-Cj7GjfmO.js → lightbulb-Drr3GVJK.js} +1 -1
  49. package/web-app/dist/assets/{loader-circle-aOSrwU8R.js → loader-circle-eykWmnmB.js} +1 -1
  50. package/web-app/dist/assets/{lock-Dhltj_XS.js → lock-DPhzdbD8.js} +1 -1
  51. package/web-app/dist/assets/{mail-CtlZ9yw2.js → mail-Jt2RYOPJ.js} +1 -1
  52. package/web-app/dist/assets/{package-B1_yf5pm.js → package-DAXMJ7Pm.js} +1 -1
  53. package/web-app/dist/assets/{plus-CRPZWClI.js → plus-D41LllNi.js} +1 -1
  54. package/web-app/dist/assets/{refresh-cw-CghmSSTV.js → refresh-cw-Dg7n3s0V.js} +1 -1
  55. package/web-app/dist/assets/{rotate-ccw-BmzS2O9R.js → rotate-ccw-bG8iIrQc.js} +1 -1
  56. package/web-app/dist/assets/{save-B4b5vDLE.js → save-eazGhHFM.js} +1 -1
  57. package/web-app/dist/assets/{server-C0JT7EJD.js → server-BdKIWXiX.js} +1 -1
  58. package/web-app/dist/assets/{shield-alert-DJHtTwb_.js → shield-alert-i0zGOCu8.js} +1 -1
  59. package/web-app/dist/assets/{trash-2-B0AnvXQh.js → trash-2-CdvB-je7.js} +1 -1
  60. package/web-app/dist/assets/{trending-down-Dc8zUzA-.js → trending-down-BYkSeH-T.js} +1 -1
  61. package/web-app/dist/assets/{trending-up-DkfQ5KmN.js → trending-up-CwXOwbN7.js} +1 -1
  62. package/web-app/dist/assets/{usePolling-q5-TS-ML.js → usePolling-BSLSkfKL.js} +1 -1
  63. package/web-app/dist/assets/user-CmBX1sm3.js +6 -0
  64. package/web-app/dist/index.html +2 -2
  65. package/web-app/server.py +1248 -0
  66. package/web-app/dist/assets/Avatar-BbMCzgGt.js +0 -11
  67. package/web-app/dist/assets/HomePage-784kkdTZ.js +0 -28
  68. package/web-app/dist/assets/NotFoundPage-lcZpPG2U.js +0 -1
  69. package/web-app/dist/assets/ProjectPage-DQSwA6aT.js +0 -265
  70. package/web-app/dist/assets/index-PKxNfesE.css +0 -1
package/LICENSE CHANGED
@@ -1,3 +1,5 @@
1
+ SPDX-License-Identifier: BUSL-1.1
2
+
1
3
  Business Source License 1.1
2
4
 
3
5
  Parameters
package/SKILL.md CHANGED
@@ -3,7 +3,7 @@ name: loki-mode
3
3
  description: Multi-agent autonomous startup system. Triggers on "Loki Mode". Takes PRD to deployed product with minimal human intervention. Requires --dangerously-skip-permissions flag.
4
4
  ---
5
5
 
6
- # Loki Mode v6.73.1
6
+ # Loki Mode v6.74.0
7
7
 
8
8
  **You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
9
9
 
@@ -21,7 +21,7 @@ Execute these steps IN ORDER at the start of EVERY turn:
21
21
  - Load 1-2 modules matching your current phase
22
22
  - Register session: Write .loki/session.json with:
23
23
  {"pid": null, "startedAt": "<ISO timestamp>", "provider": "<provider>",
24
- "invokedVia": "skill", "status": "running"}
24
+ "invokedVia": "skill", "status": "running", "updatedAt": "<ISO timestamp>"}
25
25
 
26
26
  2. Read .loki/state/orchestrator.json
27
27
  - Extract: currentPhase, tasksCompleted, tasksFailed
@@ -32,6 +32,10 @@ Execute these steps IN ORDER at the start of EVERY turn:
32
32
 
33
33
  4. Check .loki/PAUSE - IF exists: Stop work, wait for removal.
34
34
  Check .loki/STOP - IF exists: End session, update session.json status to "stopped".
35
+
36
+ 5. EVERY TURN: Update .loki/session.json "updatedAt" field to current ISO timestamp.
37
+ This keeps the dashboard aware the skill session is alive. Sessions without
38
+ an update in 5 minutes are treated as stale/stopped by the dashboard.
35
39
  ```
36
40
 
37
41
  ---
@@ -137,7 +141,7 @@ GROWTH ──[continuous improvement loop]──> GROWTH
137
141
 
138
142
  | File | Read | Write |
139
143
  |------|------|-------|
140
- | `.loki/session.json` | Session start | Session start (register), session end (update status) |
144
+ | `.loki/session.json` | Session start | Session start (register), every turn (updatedAt), session end (status) |
141
145
  | `.loki/state/orchestrator.json` | Every turn | On phase change |
142
146
  | `.loki/queue/pending.json` | Every turn | When claiming/completing tasks |
143
147
  | `.loki/queue/current-task.json` | Before each ACT | When claiming task |
@@ -268,4 +272,4 @@ The following features are documented in skill modules but not yet fully automat
268
272
  | Quality gates 3-reviewer system | Implemented (v5.35.0) | 5 specialist reviewers in `skills/quality-gates.md`; execution in run.sh |
269
273
  | Benchmarks (HumanEval, SWE-bench) | Infrastructure only | Runner scripts and datasets exist in `benchmarks/`; no published results |
270
274
 
271
- **v6.73.1 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
275
+ **v6.74.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 6.73.1
1
+ 6.74.0
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "6.73.1"
10
+ __version__ = "6.74.0"
11
11
 
12
12
  # Expose the control app for easy import
13
13
  try:
@@ -345,8 +345,12 @@ async def _push_loki_state_loop() -> None:
345
345
 
346
346
  Reads dashboard-state.json every 2s when running (30s when idle) and
347
347
  broadcasts a state_update message so clients don't rely solely on polling.
348
+
349
+ When dashboard-state.json is absent (skill-invoked sessions), reads state
350
+ from session.json + orchestrator.json + queue files instead.
348
351
  """
349
352
  last_mtime: float = 0.0
353
+ _last_skill_hash: str = "" # Track skill-session state changes
350
354
  while True:
351
355
  try:
352
356
  if not manager.active_connections:
@@ -355,6 +359,9 @@ async def _push_loki_state_loop() -> None:
355
359
 
356
360
  loki_dir = _get_loki_dir()
357
361
  state_file = loki_dir / "dashboard-state.json"
362
+ _session_file = loki_dir / "session.json"
363
+
364
+ _broadcast_sent = False
358
365
 
359
366
  if state_file.exists():
360
367
  try:
@@ -397,6 +404,15 @@ async def _push_loki_state_loop() -> None:
397
404
  except (ValueError, OSError, ProcessLookupError):
398
405
  pass
399
406
 
407
+ # Also check session.json for skill sessions
408
+ if not _pid_alive and _session_file.exists():
409
+ try:
410
+ _sd = _safe_json_read(_session_file, {})
411
+ if _sd.get("status") == "running":
412
+ _pid_alive = True
413
+ except (json.JSONDecodeError, KeyError):
414
+ pass
415
+
400
416
  status_str = raw.get("mode", "autonomous")
401
417
  if not _pid_alive:
402
418
  status_str = "stopped"
@@ -423,9 +439,128 @@ async def _push_loki_state_loop() -> None:
423
439
  "type": "status_update",
424
440
  "data": payload,
425
441
  })
442
+ _broadcast_sent = True
426
443
  except (json.JSONDecodeError, OSError, KeyError):
427
444
  pass
428
445
 
446
+ # Skill-session fallback: when dashboard-state.json is missing,
447
+ # read state from session.json + orchestrator.json + queue files
448
+ if not _broadcast_sent and _session_file.exists():
449
+ try:
450
+ _sd = _safe_json_read(_session_file, {})
451
+ if _sd.get("status") == "running":
452
+ # Validate freshness (5 min staleness threshold)
453
+ _sk_ts = _sd.get("updatedAt") or _sd.get("startedAt", "")
454
+ _sk_fresh = True
455
+ if _sk_ts:
456
+ try:
457
+ _sk_dt = datetime.fromisoformat(
458
+ _sk_ts.replace("Z", "+00:00")
459
+ )
460
+ if _sk_dt.tzinfo is None:
461
+ _sk_dt = _sk_dt.replace(tzinfo=timezone.utc)
462
+ if (datetime.now(timezone.utc) - _sk_dt).total_seconds() > 300:
463
+ _sk_fresh = False
464
+ except (ValueError, AttributeError):
465
+ pass
466
+ else:
467
+ try:
468
+ if time.time() - _session_file.stat().st_mtime > 300:
469
+ _sk_fresh = False
470
+ except OSError:
471
+ pass
472
+
473
+ if _sk_fresh:
474
+ # Read version from VERSION file
475
+ _sk_version = ""
476
+ _vf = _Path(os.path.dirname(os.path.dirname(__file__))) / "VERSION"
477
+ if _vf.is_file():
478
+ try:
479
+ _sk_version = _vf.read_text().strip()
480
+ except OSError:
481
+ pass
482
+
483
+ # Read orchestrator state
484
+ _sk_phase = ""
485
+ _sk_iteration = 0
486
+ _sk_complexity = "standard"
487
+ _orch_f = loki_dir / "state" / "orchestrator.json"
488
+ if _orch_f.exists():
489
+ try:
490
+ _orch = _safe_json_read(_orch_f, {})
491
+ _sk_phase = _orch.get("currentPhase", "") or ""
492
+ _sk_iteration = _orch.get("iteration", 0)
493
+ _sk_complexity = _orch.get("complexity", "standard") or "standard"
494
+ except (json.JSONDecodeError, KeyError):
495
+ pass
496
+
497
+ # Read pending tasks
498
+ _sk_pending = 0
499
+ _sk_current_task = ""
500
+ _pf = loki_dir / "queue" / "pending.json"
501
+ if _pf.exists():
502
+ try:
503
+ _pd = _safe_json_read(_pf, [])
504
+ _pt = _pd.get("tasks", _pd) if isinstance(_pd, dict) else _pd
505
+ if isinstance(_pt, list):
506
+ _sk_pending = len(_pt)
507
+ except (json.JSONDecodeError, KeyError, AttributeError):
508
+ pass
509
+
510
+ _ipf = loki_dir / "queue" / "in-progress.json"
511
+ if _ipf.exists():
512
+ try:
513
+ _ipd = _safe_json_read(_ipf, [])
514
+ _ipt = _ipd.get("tasks", _ipd) if isinstance(_ipd, dict) else _ipd
515
+ if isinstance(_ipt, list) and _ipt:
516
+ _f = _ipt[0]
517
+ if isinstance(_f, dict):
518
+ _sk_current_task = (
519
+ _f.get("title", "")
520
+ or _f.get("payload", {}).get("action", "")
521
+ or _f.get("id", "")
522
+ )
523
+ except (json.JSONDecodeError, KeyError, AttributeError):
524
+ pass
525
+
526
+ if not _sk_current_task:
527
+ _ctf = loki_dir / "queue" / "current-task.json"
528
+ if _ctf.exists():
529
+ try:
530
+ _ct = _safe_json_read(_ctf, {})
531
+ if isinstance(_ct, dict):
532
+ _sk_current_task = (
533
+ _ct.get("title", "")
534
+ or _ct.get("payload", {}).get("action", "")
535
+ or _ct.get("id", "")
536
+ )
537
+ except (json.JSONDecodeError, KeyError, AttributeError):
538
+ pass
539
+
540
+ # Build a change hash to avoid redundant broadcasts
541
+ _sk_hash = f"{_sk_phase}:{_sk_iteration}:{_sk_pending}:{_sk_current_task}"
542
+ if _sk_hash != _last_skill_hash:
543
+ _last_skill_hash = _sk_hash
544
+ payload = {
545
+ "status": "running",
546
+ "phase": _sk_phase,
547
+ "iteration": _sk_iteration,
548
+ "complexity": _sk_complexity,
549
+ "mode": "autonomous",
550
+ "provider": _sd.get("provider", "claude"),
551
+ "running_agents": 0,
552
+ "pending_tasks": _sk_pending,
553
+ "current_task": _sk_current_task,
554
+ "version": _sk_version,
555
+ }
556
+ await manager.broadcast({
557
+ "type": "status_update",
558
+ "data": payload,
559
+ })
560
+ _broadcast_sent = True
561
+ except (json.JSONDecodeError, OSError, KeyError):
562
+ pass
563
+
429
564
  # Poll faster when a session is running
430
565
  pid_file = loki_dir / "loki.pid"
431
566
  is_running = False
@@ -437,6 +572,15 @@ async def _push_loki_state_loop() -> None:
437
572
  except (ValueError, OSError, ProcessLookupError):
438
573
  pass
439
574
 
575
+ # Also consider skill sessions as "running" for poll interval
576
+ if not is_running and _session_file.exists():
577
+ try:
578
+ _sd2 = _safe_json_read(_session_file, {})
579
+ if _sd2.get("status") == "running":
580
+ is_running = True
581
+ except (json.JSONDecodeError, KeyError):
582
+ pass
583
+
440
584
  await asyncio.sleep(2.0 if is_running else 30.0)
441
585
  except asyncio.CancelledError:
442
586
  return
@@ -598,9 +742,12 @@ async def get_status() -> StatusResponse:
598
742
  running_agents = 0
599
743
 
600
744
  # Read dashboard state (with retry for concurrent writes)
745
+ _has_dashboard_state = False
601
746
  if state_file.exists():
602
747
  try:
603
748
  state = _safe_json_read(state_file, {})
749
+ if state:
750
+ _has_dashboard_state = True
604
751
  phase = state.get("phase", "")
605
752
  iteration = state.get("iteration", 0)
606
753
  complexity = state.get("complexity", "standard")
@@ -641,14 +788,113 @@ async def get_status() -> StatusResponse:
641
788
  pass
642
789
 
643
790
  # Also check session.json for skill-invoked sessions
791
+ _skill_session = False
644
792
  if not running and session_file.exists():
645
793
  try:
646
794
  sd = _safe_json_read(session_file, {})
647
795
  if sd.get("status") == "running":
648
- running = True
796
+ # Validate freshness: session.json must have been updated within
797
+ # the last 5 minutes to be considered active (skill agents update
798
+ # it each turn). Fall back to file mtime if no timestamp field.
799
+ _session_fresh = True
800
+ _session_ts = sd.get("updatedAt") or sd.get("startedAt", "")
801
+ if _session_ts:
802
+ try:
803
+ _sdt = datetime.fromisoformat(
804
+ _session_ts.replace("Z", "+00:00")
805
+ )
806
+ if _sdt.tzinfo is None:
807
+ _sdt = _sdt.replace(tzinfo=timezone.utc)
808
+ _age = (datetime.now(timezone.utc) - _sdt).total_seconds()
809
+ if _age > 300:
810
+ _session_fresh = False
811
+ except (ValueError, AttributeError):
812
+ pass
813
+ else:
814
+ # No timestamp -- check file mtime
815
+ try:
816
+ _mtime = session_file.stat().st_mtime
817
+ _age = time.time() - _mtime
818
+ if _age > 300:
819
+ _session_fresh = False
820
+ except OSError:
821
+ pass
822
+
823
+ if _session_fresh:
824
+ running = True
825
+ _skill_session = True
826
+ # Pull provider from session.json if available
827
+ _sp = sd.get("provider", "")
828
+ if _sp:
829
+ provider = _sp
649
830
  except (json.JSONDecodeError, KeyError):
650
831
  pass
651
832
 
833
+ # When running as a skill (no dashboard-state.json), read state from
834
+ # the orchestrator and queue files that the skill agent writes directly.
835
+ if _skill_session and not _has_dashboard_state:
836
+ orch_file = loki_dir / "state" / "orchestrator.json"
837
+ if orch_file.exists():
838
+ try:
839
+ orch = _safe_json_read(orch_file, {})
840
+ phase = orch.get("currentPhase", phase) or phase
841
+ iteration = orch.get("iteration", iteration)
842
+ complexity = orch.get("complexity", complexity) or complexity
843
+ _metrics = orch.get("metrics", {})
844
+ if isinstance(_metrics, dict):
845
+ _tc = _metrics.get("tasksCompleted", 0)
846
+ _tf = _metrics.get("tasksFailed", 0)
847
+ if isinstance(_tc, (int, float)):
848
+ pass # available for future use
849
+ except (json.JSONDecodeError, KeyError):
850
+ pass
851
+
852
+ # Read pending task count from queue files
853
+ _q_pending = loki_dir / "queue" / "pending.json"
854
+ if _q_pending.exists():
855
+ try:
856
+ _qd = _safe_json_read(_q_pending, [])
857
+ _tasks = _qd.get("tasks", _qd) if isinstance(_qd, dict) else _qd
858
+ if isinstance(_tasks, list):
859
+ pending_tasks = len(_tasks)
860
+ except (json.JSONDecodeError, KeyError, AttributeError):
861
+ pass
862
+
863
+ # Read current task from in-progress queue
864
+ _q_inprog = loki_dir / "queue" / "in-progress.json"
865
+ if _q_inprog.exists():
866
+ try:
867
+ _ipd = _safe_json_read(_q_inprog, [])
868
+ _ip_tasks = _ipd.get("tasks", _ipd) if isinstance(_ipd, dict) else _ipd
869
+ if isinstance(_ip_tasks, list) and _ip_tasks:
870
+ _first = _ip_tasks[0]
871
+ if isinstance(_first, dict):
872
+ current_task = (
873
+ _first.get("title", "")
874
+ or _first.get("payload", {}).get("action", "")
875
+ or _first.get("id", "")
876
+ )
877
+ except (json.JSONDecodeError, KeyError, AttributeError):
878
+ pass
879
+
880
+ # Read current-task.json (skill agents write this when claiming a task)
881
+ _q_current = loki_dir / "queue" / "current-task.json"
882
+ if not current_task and _q_current.exists():
883
+ try:
884
+ _ct = _safe_json_read(_q_current, {})
885
+ if isinstance(_ct, dict):
886
+ current_task = (
887
+ _ct.get("title", "")
888
+ or _ct.get("payload", {}).get("action", "")
889
+ or _ct.get("id", "")
890
+ )
891
+ except (json.JSONDecodeError, KeyError, AttributeError):
892
+ pass
893
+
894
+ # Skill sessions are autonomous by definition
895
+ if not mode:
896
+ mode = "autonomous"
897
+
652
898
  # Determine status string
653
899
  if not running:
654
900
  status = "stopped"
@@ -2,7 +2,7 @@
2
2
 
3
3
  The flagship product of [Autonomi](https://www.autonomi.dev/). Complete installation instructions for all platforms and use cases.
4
4
 
5
- **Version:** v6.73.1
5
+ **Version:** v6.74.0
6
6
 
7
7
  ---
8
8
 
package/mcp/__init__.py CHANGED
@@ -57,4 +57,4 @@ try:
57
57
  except ImportError:
58
58
  __all__ = ['mcp']
59
59
 
60
- __version__ = '6.73.1'
60
+ __version__ = '6.74.0'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loki-mode",
3
- "version": "6.73.1",
3
+ "version": "6.74.0",
4
4
  "description": "Loki Mode by Autonomi - Multi-agent autonomous startup system for Claude Code, Codex CLI, and Gemini CLI",
5
5
  "keywords": [
6
6
  "agent",