@lorekit/cli 1.59.0 → 1.60.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lorekit/cli",
3
- "version": "1.59.0",
3
+ "version": "1.60.0",
4
4
  "description": "Install the LoreKit shared-memory skill and run health checks for the LoreKit MCP server.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -28,7 +28,7 @@ export const cursor = {
28
28
  cwd:
29
29
  input.cwd ||
30
30
  (Array.isArray(input.workspace_roots) ? input.workspace_roots[0] : null),
31
- sessionId: input.generation_id || input.conversation_id || null,
31
+ sessionId: input.conversation_id || input.generation_id || null,
32
32
  toolName: 'command',
33
33
  toolResponse: null,
34
34
  event: input.hook_event_name || null,
@@ -109,6 +109,23 @@ async function run(args, meter) {
109
109
  const parsed = adapter.parse(input);
110
110
  const event = args.event || parsed.event;
111
111
 
112
+ // Every adapter already normalises the host's own session id off the stdin
113
+ // payload (Claude's `session_id`, Codex's `thread_id`, Cursor's
114
+ // `conversation_id`). Publishing it as `LOREKIT_SESSION_ID` — the first name
115
+ // `deriveSessionContext` looks for — is what lets a hook-driven remote read
116
+ // carry a `correlation_id`, so the dashboard's Runs view can group a session's
117
+ // reads and writes. It is the AUTHORITATIVE id: the payload says which session
118
+ // this fire belongs to, whereas an inherited env var only says which process
119
+ // tree we happen to be in, and Cursor/Codex export nothing at all.
120
+ //
121
+ // `||=`, never an overwrite: an explicit LOREKIT_SESSION_ID (or the
122
+ // LOREKIT_CORRELATION_ID that outranks all of this) is a deliberate override
123
+ // and must keep winning. Process-local and short-lived — this CLI invocation
124
+ // handles exactly one hook fire and exits.
125
+ if (parsed.sessionId && !process.env.LOREKIT_SESSION_ID) {
126
+ process.env.LOREKIT_SESSION_ID = parsed.sessionId;
127
+ }
128
+
112
129
  // Harvest the real payload when recording is enabled (opt-in via env).
113
130
  recordFixture(args.adapter, event, raw);
114
131
 
@@ -46,6 +46,9 @@ export const LORE_PARAM_DEFAULTS = {
46
46
  // "unfiltered".
47
47
  filters: null,
48
48
  tags: [], // string[] — legacy label filter (AND across labels); [] means "no filter". Still READ by the app, superseded by `filters`
49
+ // RetentionConditions | null — the retention-preview trio (min age / unseen-for
50
+ // / seen-at-most). `null` means no narrowing; absent from the URL when unset.
51
+ retention: null,
49
52
  // 'active' | 'archived' | 'expiring' | null — the Explorer's Status control.
50
53
  // `null`, NOT 'active', is the default for `filters`' reason: the app has to
51
54
  // tell "absent" from an explicit choice, because an absent `status` falls back
@@ -59,9 +62,21 @@ export const LORE_PARAM_DEFAULTS = {
59
62
 
60
63
  // A stable, readable param order (also makes URLs deterministic for tests).
61
64
  // Mirrors the `useUrlState` call order in `LoreExplorer.tsx` (+ the `lesson`
62
- // param last), so `filters` and `tags` sit between `owner` and `status`. `scope`
63
- // precedes `lesson` so a lesson link reads `?scope=…&lesson=…`.
64
- const PARAM_ORDER = ['scope', 'q', 'range', 'owner', 'filters', 'tags', 'status', 'archived', 'lesson'];
65
+ // param last), so `filters` and `tags` sit between `owner` and `status`, and
66
+ // `retention` sits between `tags` and `status`. `scope` precedes `lesson` so a
67
+ // lesson link reads `?scope=…&lesson=…`.
68
+ const PARAM_ORDER = [
69
+ 'scope',
70
+ 'q',
71
+ 'range',
72
+ 'owner',
73
+ 'filters',
74
+ 'tags',
75
+ 'retention',
76
+ 'status',
77
+ 'archived',
78
+ 'lesson',
79
+ ];
65
80
 
66
81
  // Strip trailing slashes from a base URL, falling back to the default when the
67
82
  // input is empty/absent. Pure.
@@ -231,7 +231,19 @@ export function deriveSessionContext(env = process.env) {
231
231
  // Well-known agent-host session id env vars. Best-effort: hosts differ and
232
232
  // this is not an exhaustive registry, so an unrecognised host still falls
233
233
  // through to `unknown` rather than fabricating an id.
234
- const sessionId = firstNonEmptyEnv(env, ['LOREKIT_SESSION_ID', 'CLAUDE_SESSION_ID']);
234
+ //
235
+ // `CLAUDE_CODE_SESSION_ID` is the name Claude Code actually exports (verified
236
+ // against a live session's env); `CLAUDE_SESSION_ID` was a guess and is not
237
+ // set by any Claude Code version, so before it was joined here EVERY local
238
+ // Claude session fell through to `unknown` with no correlation id — which is
239
+ // why `GET /memories/usage/runs` returned an empty list on an account with
240
+ // ~44K usage events. Kept alongside rather than replaced: it costs nothing,
241
+ // and dropping a name is how the same blind spot comes back.
242
+ const sessionId = firstNonEmptyEnv(env, [
243
+ 'LOREKIT_SESSION_ID',
244
+ 'CLAUDE_CODE_SESSION_ID',
245
+ 'CLAUDE_SESSION_ID',
246
+ ]);
235
247
  if (sessionId) {
236
248
  // A local session IS known even when the specific id fails the
237
249
  // correlation-id charset/length check — report the kind either way, and
@@ -528,6 +528,135 @@ export const MCP_TOOL_DEFS = [
528
528
  "minimum": 0,
529
529
  "maximum": 100000,
530
530
  "description": "Match only lessons that have recurred at most this many times."
531
+ },
532
+ "tags": {
533
+ "type": "array",
534
+ "items": {
535
+ "type": "string"
536
+ },
537
+ "description": "Match lessons carrying these labels — combined by `tags_mode`."
538
+ },
539
+ "tags_mode": {
540
+ "type": "string",
541
+ "enum": [
542
+ "any",
543
+ "all",
544
+ "none"
545
+ ],
546
+ "default": "any",
547
+ "description": "\"any\" (carries at least one), \"all\" (carries every one), or \"none\" (carries none)."
548
+ },
549
+ "source_agent": {
550
+ "type": "array",
551
+ "items": {
552
+ "type": "string"
553
+ },
554
+ "description": "Match lessons whose writing agent is one of these (or, with mode \"nin\", none of these) — e.g. \"claude\", \"aw\"."
555
+ },
556
+ "source_agent_mode": {
557
+ "type": "string",
558
+ "enum": [
559
+ "in",
560
+ "nin"
561
+ ],
562
+ "default": "in",
563
+ "description": "How the source_agent filter combines."
564
+ },
565
+ "trigger": {
566
+ "type": "array",
567
+ "items": {
568
+ "type": "string"
569
+ },
570
+ "description": "Match lessons whose write trigger is one of these (or, with mode \"nin\", none of these) — e.g. \"stuck-loop\", \"pr-webhook\"."
571
+ },
572
+ "trigger_mode": {
573
+ "type": "string",
574
+ "enum": [
575
+ "in",
576
+ "nin"
577
+ ],
578
+ "default": "in",
579
+ "description": "How the trigger filter combines."
580
+ },
581
+ "kind": {
582
+ "type": "array",
583
+ "items": {
584
+ "type": "string"
585
+ },
586
+ "description": "Match lessons whose kind is one of these (or, with mode \"nin\", none of these) — e.g. \"lesson\", \"bus\", \"signal\"."
587
+ },
588
+ "kind_mode": {
589
+ "type": "string",
590
+ "enum": [
591
+ "in",
592
+ "nin"
593
+ ],
594
+ "default": "in",
595
+ "description": "How the kind filter combines."
596
+ },
597
+ "host": {
598
+ "type": "array",
599
+ "items": {
600
+ "type": "string"
601
+ },
602
+ "description": "Match lessons whose owning host is one of these (or, with mode \"nin\", none of these) — e.g. \"reviewer\", \"aw\"."
603
+ },
604
+ "host_mode": {
605
+ "type": "string",
606
+ "enum": [
607
+ "in",
608
+ "nin"
609
+ ],
610
+ "default": "in",
611
+ "description": "How the host filter combines."
612
+ },
613
+ "origin_repo": {
614
+ "type": "array",
615
+ "items": {
616
+ "type": "string"
617
+ },
618
+ "description": "Match lessons whose origin repository is one of these (or, with mode \"nin\", none of these) — e.g. \"owner/repo\"."
619
+ },
620
+ "origin_repo_mode": {
621
+ "type": "string",
622
+ "enum": [
623
+ "in",
624
+ "nin"
625
+ ],
626
+ "default": "in",
627
+ "description": "How the origin_repo filter combines."
628
+ },
629
+ "origin_branch": {
630
+ "type": "array",
631
+ "items": {
632
+ "type": "string"
633
+ },
634
+ "description": "Match lessons whose origin branch is one of these (or, with mode \"nin\", none of these) — e.g. \"main\", \"feat/x\"."
635
+ },
636
+ "origin_branch_mode": {
637
+ "type": "string",
638
+ "enum": [
639
+ "in",
640
+ "nin"
641
+ ],
642
+ "default": "in",
643
+ "description": "How the origin_branch filter combines."
644
+ },
645
+ "origin_pr": {
646
+ "type": "array",
647
+ "items": {
648
+ "type": "string"
649
+ },
650
+ "description": "Match lessons from one of these pull-request numbers, as digit strings — e.g. \"482\"."
651
+ },
652
+ "origin_pr_mode": {
653
+ "type": "string",
654
+ "enum": [
655
+ "in",
656
+ "nin"
657
+ ],
658
+ "default": "in",
659
+ "description": "How the origin_pr filter combines."
531
660
  }
532
661
  }
533
662
  }
@@ -578,6 +707,135 @@ export const MCP_TOOL_DEFS = [
578
707
  "minimum": 0,
579
708
  "maximum": 100000,
580
709
  "description": "Match only lessons that have recurred at most this many times. Omit to leave unchanged; pass explicit null to clear."
710
+ },
711
+ "tags": {
712
+ "type": "array",
713
+ "items": {
714
+ "type": "string"
715
+ },
716
+ "description": "Match lessons carrying these labels — combined by `tags_mode`. Omit to leave unchanged; pass explicit null to clear."
717
+ },
718
+ "tags_mode": {
719
+ "type": "string",
720
+ "enum": [
721
+ "any",
722
+ "all",
723
+ "none"
724
+ ],
725
+ "default": "any",
726
+ "description": "\"any\" (carries at least one), \"all\" (carries every one), or \"none\" (carries none). Omit to leave unchanged; pass explicit null to clear."
727
+ },
728
+ "source_agent": {
729
+ "type": "array",
730
+ "items": {
731
+ "type": "string"
732
+ },
733
+ "description": "Match lessons whose writing agent is one of these (or, with mode \"nin\", none of these) — e.g. \"claude\", \"aw\". Omit to leave unchanged; pass explicit null to clear."
734
+ },
735
+ "source_agent_mode": {
736
+ "type": "string",
737
+ "enum": [
738
+ "in",
739
+ "nin"
740
+ ],
741
+ "default": "in",
742
+ "description": "How the source_agent filter combines. Omit to leave unchanged; pass explicit null to clear."
743
+ },
744
+ "trigger": {
745
+ "type": "array",
746
+ "items": {
747
+ "type": "string"
748
+ },
749
+ "description": "Match lessons whose write trigger is one of these (or, with mode \"nin\", none of these) — e.g. \"stuck-loop\", \"pr-webhook\". Omit to leave unchanged; pass explicit null to clear."
750
+ },
751
+ "trigger_mode": {
752
+ "type": "string",
753
+ "enum": [
754
+ "in",
755
+ "nin"
756
+ ],
757
+ "default": "in",
758
+ "description": "How the trigger filter combines. Omit to leave unchanged; pass explicit null to clear."
759
+ },
760
+ "kind": {
761
+ "type": "array",
762
+ "items": {
763
+ "type": "string"
764
+ },
765
+ "description": "Match lessons whose kind is one of these (or, with mode \"nin\", none of these) — e.g. \"lesson\", \"bus\", \"signal\". Omit to leave unchanged; pass explicit null to clear."
766
+ },
767
+ "kind_mode": {
768
+ "type": "string",
769
+ "enum": [
770
+ "in",
771
+ "nin"
772
+ ],
773
+ "default": "in",
774
+ "description": "How the kind filter combines. Omit to leave unchanged; pass explicit null to clear."
775
+ },
776
+ "host": {
777
+ "type": "array",
778
+ "items": {
779
+ "type": "string"
780
+ },
781
+ "description": "Match lessons whose owning host is one of these (or, with mode \"nin\", none of these) — e.g. \"reviewer\", \"aw\". Omit to leave unchanged; pass explicit null to clear."
782
+ },
783
+ "host_mode": {
784
+ "type": "string",
785
+ "enum": [
786
+ "in",
787
+ "nin"
788
+ ],
789
+ "default": "in",
790
+ "description": "How the host filter combines. Omit to leave unchanged; pass explicit null to clear."
791
+ },
792
+ "origin_repo": {
793
+ "type": "array",
794
+ "items": {
795
+ "type": "string"
796
+ },
797
+ "description": "Match lessons whose origin repository is one of these (or, with mode \"nin\", none of these) — e.g. \"owner/repo\". Omit to leave unchanged; pass explicit null to clear."
798
+ },
799
+ "origin_repo_mode": {
800
+ "type": "string",
801
+ "enum": [
802
+ "in",
803
+ "nin"
804
+ ],
805
+ "default": "in",
806
+ "description": "How the origin_repo filter combines. Omit to leave unchanged; pass explicit null to clear."
807
+ },
808
+ "origin_branch": {
809
+ "type": "array",
810
+ "items": {
811
+ "type": "string"
812
+ },
813
+ "description": "Match lessons whose origin branch is one of these (or, with mode \"nin\", none of these) — e.g. \"main\", \"feat/x\". Omit to leave unchanged; pass explicit null to clear."
814
+ },
815
+ "origin_branch_mode": {
816
+ "type": "string",
817
+ "enum": [
818
+ "in",
819
+ "nin"
820
+ ],
821
+ "default": "in",
822
+ "description": "How the origin_branch filter combines. Omit to leave unchanged; pass explicit null to clear."
823
+ },
824
+ "origin_pr": {
825
+ "type": "array",
826
+ "items": {
827
+ "type": "string"
828
+ },
829
+ "description": "Match lessons from one of these pull-request numbers, as digit strings — e.g. \"482\". Omit to leave unchanged; pass explicit null to clear."
830
+ },
831
+ "origin_pr_mode": {
832
+ "type": "string",
833
+ "enum": [
834
+ "in",
835
+ "nin"
836
+ ],
837
+ "default": "in",
838
+ "description": "How the origin_pr filter combines. Omit to leave unchanged; pass explicit null to clear."
581
839
  }
582
840
  }
583
841
  }
@@ -629,6 +887,135 @@ export const MCP_TOOL_DEFS = [
629
887
  "minimum": 0,
630
888
  "maximum": 100000,
631
889
  "description": "Match only lessons that have recurred at most this many times."
890
+ },
891
+ "tags": {
892
+ "type": "array",
893
+ "items": {
894
+ "type": "string"
895
+ },
896
+ "description": "Match lessons carrying these labels — combined by `tags_mode`."
897
+ },
898
+ "tags_mode": {
899
+ "type": "string",
900
+ "enum": [
901
+ "any",
902
+ "all",
903
+ "none"
904
+ ],
905
+ "default": "any",
906
+ "description": "\"any\" (carries at least one), \"all\" (carries every one), or \"none\" (carries none)."
907
+ },
908
+ "source_agent": {
909
+ "type": "array",
910
+ "items": {
911
+ "type": "string"
912
+ },
913
+ "description": "Match lessons whose writing agent is one of these (or, with mode \"nin\", none of these) — e.g. \"claude\", \"aw\"."
914
+ },
915
+ "source_agent_mode": {
916
+ "type": "string",
917
+ "enum": [
918
+ "in",
919
+ "nin"
920
+ ],
921
+ "default": "in",
922
+ "description": "How the source_agent filter combines."
923
+ },
924
+ "trigger": {
925
+ "type": "array",
926
+ "items": {
927
+ "type": "string"
928
+ },
929
+ "description": "Match lessons whose write trigger is one of these (or, with mode \"nin\", none of these) — e.g. \"stuck-loop\", \"pr-webhook\"."
930
+ },
931
+ "trigger_mode": {
932
+ "type": "string",
933
+ "enum": [
934
+ "in",
935
+ "nin"
936
+ ],
937
+ "default": "in",
938
+ "description": "How the trigger filter combines."
939
+ },
940
+ "kind": {
941
+ "type": "array",
942
+ "items": {
943
+ "type": "string"
944
+ },
945
+ "description": "Match lessons whose kind is one of these (or, with mode \"nin\", none of these) — e.g. \"lesson\", \"bus\", \"signal\"."
946
+ },
947
+ "kind_mode": {
948
+ "type": "string",
949
+ "enum": [
950
+ "in",
951
+ "nin"
952
+ ],
953
+ "default": "in",
954
+ "description": "How the kind filter combines."
955
+ },
956
+ "host": {
957
+ "type": "array",
958
+ "items": {
959
+ "type": "string"
960
+ },
961
+ "description": "Match lessons whose owning host is one of these (or, with mode \"nin\", none of these) — e.g. \"reviewer\", \"aw\"."
962
+ },
963
+ "host_mode": {
964
+ "type": "string",
965
+ "enum": [
966
+ "in",
967
+ "nin"
968
+ ],
969
+ "default": "in",
970
+ "description": "How the host filter combines."
971
+ },
972
+ "origin_repo": {
973
+ "type": "array",
974
+ "items": {
975
+ "type": "string"
976
+ },
977
+ "description": "Match lessons whose origin repository is one of these (or, with mode \"nin\", none of these) — e.g. \"owner/repo\"."
978
+ },
979
+ "origin_repo_mode": {
980
+ "type": "string",
981
+ "enum": [
982
+ "in",
983
+ "nin"
984
+ ],
985
+ "default": "in",
986
+ "description": "How the origin_repo filter combines."
987
+ },
988
+ "origin_branch": {
989
+ "type": "array",
990
+ "items": {
991
+ "type": "string"
992
+ },
993
+ "description": "Match lessons whose origin branch is one of these (or, with mode \"nin\", none of these) — e.g. \"main\", \"feat/x\"."
994
+ },
995
+ "origin_branch_mode": {
996
+ "type": "string",
997
+ "enum": [
998
+ "in",
999
+ "nin"
1000
+ ],
1001
+ "default": "in",
1002
+ "description": "How the origin_branch filter combines."
1003
+ },
1004
+ "origin_pr": {
1005
+ "type": "array",
1006
+ "items": {
1007
+ "type": "string"
1008
+ },
1009
+ "description": "Match lessons from one of these pull-request numbers, as digit strings — e.g. \"482\"."
1010
+ },
1011
+ "origin_pr_mode": {
1012
+ "type": "string",
1013
+ "enum": [
1014
+ "in",
1015
+ "nin"
1016
+ ],
1017
+ "default": "in",
1018
+ "description": "How the origin_pr filter combines."
632
1019
  }
633
1020
  }
634
1021
  }
@@ -664,6 +1051,135 @@ export const MCP_TOOL_DEFS = [
664
1051
  "minimum": 0,
665
1052
  "maximum": 100000,
666
1053
  "description": "Match only lessons that have recurred at most this many times."
1054
+ },
1055
+ "tags": {
1056
+ "type": "array",
1057
+ "items": {
1058
+ "type": "string"
1059
+ },
1060
+ "description": "Match lessons carrying these labels — combined by `tags_mode`."
1061
+ },
1062
+ "tags_mode": {
1063
+ "type": "string",
1064
+ "enum": [
1065
+ "any",
1066
+ "all",
1067
+ "none"
1068
+ ],
1069
+ "default": "any",
1070
+ "description": "\"any\" (carries at least one), \"all\" (carries every one), or \"none\" (carries none)."
1071
+ },
1072
+ "source_agent": {
1073
+ "type": "array",
1074
+ "items": {
1075
+ "type": "string"
1076
+ },
1077
+ "description": "Match lessons whose writing agent is one of these (or, with mode \"nin\", none of these) — e.g. \"claude\", \"aw\"."
1078
+ },
1079
+ "source_agent_mode": {
1080
+ "type": "string",
1081
+ "enum": [
1082
+ "in",
1083
+ "nin"
1084
+ ],
1085
+ "default": "in",
1086
+ "description": "How the source_agent filter combines."
1087
+ },
1088
+ "trigger": {
1089
+ "type": "array",
1090
+ "items": {
1091
+ "type": "string"
1092
+ },
1093
+ "description": "Match lessons whose write trigger is one of these (or, with mode \"nin\", none of these) — e.g. \"stuck-loop\", \"pr-webhook\"."
1094
+ },
1095
+ "trigger_mode": {
1096
+ "type": "string",
1097
+ "enum": [
1098
+ "in",
1099
+ "nin"
1100
+ ],
1101
+ "default": "in",
1102
+ "description": "How the trigger filter combines."
1103
+ },
1104
+ "kind": {
1105
+ "type": "array",
1106
+ "items": {
1107
+ "type": "string"
1108
+ },
1109
+ "description": "Match lessons whose kind is one of these (or, with mode \"nin\", none of these) — e.g. \"lesson\", \"bus\", \"signal\"."
1110
+ },
1111
+ "kind_mode": {
1112
+ "type": "string",
1113
+ "enum": [
1114
+ "in",
1115
+ "nin"
1116
+ ],
1117
+ "default": "in",
1118
+ "description": "How the kind filter combines."
1119
+ },
1120
+ "host": {
1121
+ "type": "array",
1122
+ "items": {
1123
+ "type": "string"
1124
+ },
1125
+ "description": "Match lessons whose owning host is one of these (or, with mode \"nin\", none of these) — e.g. \"reviewer\", \"aw\"."
1126
+ },
1127
+ "host_mode": {
1128
+ "type": "string",
1129
+ "enum": [
1130
+ "in",
1131
+ "nin"
1132
+ ],
1133
+ "default": "in",
1134
+ "description": "How the host filter combines."
1135
+ },
1136
+ "origin_repo": {
1137
+ "type": "array",
1138
+ "items": {
1139
+ "type": "string"
1140
+ },
1141
+ "description": "Match lessons whose origin repository is one of these (or, with mode \"nin\", none of these) — e.g. \"owner/repo\"."
1142
+ },
1143
+ "origin_repo_mode": {
1144
+ "type": "string",
1145
+ "enum": [
1146
+ "in",
1147
+ "nin"
1148
+ ],
1149
+ "default": "in",
1150
+ "description": "How the origin_repo filter combines."
1151
+ },
1152
+ "origin_branch": {
1153
+ "type": "array",
1154
+ "items": {
1155
+ "type": "string"
1156
+ },
1157
+ "description": "Match lessons whose origin branch is one of these (or, with mode \"nin\", none of these) — e.g. \"main\", \"feat/x\"."
1158
+ },
1159
+ "origin_branch_mode": {
1160
+ "type": "string",
1161
+ "enum": [
1162
+ "in",
1163
+ "nin"
1164
+ ],
1165
+ "default": "in",
1166
+ "description": "How the origin_branch filter combines."
1167
+ },
1168
+ "origin_pr": {
1169
+ "type": "array",
1170
+ "items": {
1171
+ "type": "string"
1172
+ },
1173
+ "description": "Match lessons from one of these pull-request numbers, as digit strings — e.g. \"482\"."
1174
+ },
1175
+ "origin_pr_mode": {
1176
+ "type": "string",
1177
+ "enum": [
1178
+ "in",
1179
+ "nin"
1180
+ ],
1181
+ "default": "in",
1182
+ "description": "How the origin_pr filter combines."
667
1183
  }
668
1184
  }
669
1185
  }