engrm 0.4.37 → 0.4.39

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.
@@ -137,6 +137,12 @@ function containsSecrets(text, customPatterns = []) {
137
137
  }
138
138
  return false;
139
139
  }
140
+ var FLEET_HOSTNAME_PATTERN = /\b(?=.{1,253}\b)(?!-)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}\b/gi;
141
+ var FLEET_IP_PATTERN = /\b(?:\d{1,3}\.){3}\d{1,3}\b/g;
142
+ var FLEET_MAC_PATTERN = /\b(?:[0-9a-f]{2}[:-]){5}[0-9a-f]{2}\b/gi;
143
+ function scrubFleetIdentifiers(text) {
144
+ return text.replace(FLEET_MAC_PATTERN, "[REDACTED_MAC]").replace(FLEET_IP_PATTERN, "[REDACTED_IP]").replace(FLEET_HOSTNAME_PATTERN, "[REDACTED_HOSTNAME]");
145
+ }
140
146
 
141
147
  // src/capture/quality.ts
142
148
  var QUALITY_THRESHOLD = 0.1;
@@ -713,6 +719,35 @@ function narrativesConflict(narrative1, narrative2) {
713
719
  return null;
714
720
  }
715
721
 
722
+ // src/sync/targets.ts
723
+ function isFleetProjectName(projectName, config) {
724
+ const fleetProjectName = config.fleet?.project_name ?? "shared-experience";
725
+ if (!projectName || !fleetProjectName)
726
+ return false;
727
+ return projectName.trim().toLowerCase() === fleetProjectName.trim().toLowerCase();
728
+ }
729
+ function hasFleetTarget(config) {
730
+ return Boolean(config.fleet?.namespace?.trim() && config.fleet?.api_key?.trim() && (config.fleet?.project_name ?? "shared-experience").trim());
731
+ }
732
+ function resolveSyncTarget(config, projectName) {
733
+ if (isFleetProjectName(projectName, config) && hasFleetTarget(config)) {
734
+ return {
735
+ key: `fleet:${config.fleet.namespace}`,
736
+ apiKey: config.fleet.api_key,
737
+ namespace: config.fleet.namespace,
738
+ siteId: config.site_id,
739
+ isFleet: true
740
+ };
741
+ }
742
+ return {
743
+ key: `default:${config.namespace}`,
744
+ apiKey: config.candengo_api_key,
745
+ namespace: config.namespace,
746
+ siteId: config.site_id,
747
+ isFleet: false
748
+ };
749
+ }
750
+
716
751
  // src/tools/save.ts
717
752
  var VALID_TYPES = [
718
753
  "bugfix",
@@ -761,7 +796,8 @@ async function saveObservation(db, config, input) {
761
796
  const factsJson = structuredFacts.length > 0 ? config.scrubbing.enabled ? scrubSecrets(JSON.stringify(structuredFacts), customPatterns) : JSON.stringify(structuredFacts) : null;
762
797
  const filesReadJson = filesRead ? JSON.stringify(filesRead) : null;
763
798
  const filesModifiedJson = filesModified ? JSON.stringify(filesModified) : null;
764
- let sensitivity = input.sensitivity ?? config.scrubbing.default_sensitivity;
799
+ const fleetProject = isFleetProjectName(project.name, config);
800
+ let sensitivity = input.sensitivity ?? (fleetProject ? "shared" : config.scrubbing.default_sensitivity);
765
801
  if (config.scrubbing.enabled && containsSecrets([input.title, input.narrative, JSON.stringify(input.facts)].filter(Boolean).join(" "), customPatterns)) {
766
802
  if (sensitivity === "shared") {
767
803
  sensitivity = "personal";
@@ -940,6 +976,16 @@ function createDefaultConfig() {
940
976
  },
941
977
  transcript_analysis: {
942
978
  enabled: false
979
+ },
980
+ http: {
981
+ enabled: false,
982
+ port: 3767,
983
+ bearer_tokens: []
984
+ },
985
+ fleet: {
986
+ project_name: "shared-experience",
987
+ namespace: "",
988
+ api_key: ""
943
989
  }
944
990
  };
945
991
  }
@@ -1001,6 +1047,16 @@ function loadConfig() {
1001
1047
  },
1002
1048
  transcript_analysis: {
1003
1049
  enabled: asBool(config["transcript_analysis"]?.["enabled"], defaults.transcript_analysis.enabled)
1050
+ },
1051
+ http: {
1052
+ enabled: asBool(config["http"]?.["enabled"], defaults.http.enabled),
1053
+ port: asNumber(config["http"]?.["port"], defaults.http.port),
1054
+ bearer_tokens: asStringArray(config["http"]?.["bearer_tokens"], defaults.http.bearer_tokens)
1055
+ },
1056
+ fleet: {
1057
+ project_name: asString(config["fleet"]?.["project_name"], defaults.fleet.project_name),
1058
+ namespace: asString(config["fleet"]?.["namespace"], defaults.fleet.namespace),
1059
+ api_key: asString(config["fleet"]?.["api_key"], defaults.fleet.api_key)
1004
1060
  }
1005
1061
  };
1006
1062
  }
@@ -282,6 +282,16 @@ function createDefaultConfig() {
282
282
  },
283
283
  transcript_analysis: {
284
284
  enabled: false
285
+ },
286
+ http: {
287
+ enabled: false,
288
+ port: 3767,
289
+ bearer_tokens: []
290
+ },
291
+ fleet: {
292
+ project_name: "shared-experience",
293
+ namespace: "",
294
+ api_key: ""
285
295
  }
286
296
  };
287
297
  }
@@ -343,6 +353,16 @@ function loadConfig() {
343
353
  },
344
354
  transcript_analysis: {
345
355
  enabled: asBool(config["transcript_analysis"]?.["enabled"], defaults.transcript_analysis.enabled)
356
+ },
357
+ http: {
358
+ enabled: asBool(config["http"]?.["enabled"], defaults.http.enabled),
359
+ port: asNumber(config["http"]?.["port"], defaults.http.port),
360
+ bearer_tokens: asStringArray(config["http"]?.["bearer_tokens"], defaults.http.bearer_tokens)
361
+ },
362
+ fleet: {
363
+ project_name: asString(config["fleet"]?.["project_name"], defaults.fleet.project_name),
364
+ namespace: asString(config["fleet"]?.["namespace"], defaults.fleet.namespace),
365
+ api_key: asString(config["fleet"]?.["api_key"], defaults.fleet.api_key)
346
366
  }
347
367
  };
348
368
  }
@@ -2216,6 +2236,12 @@ function containsSecrets(text, customPatterns = []) {
2216
2236
  }
2217
2237
  return false;
2218
2238
  }
2239
+ var FLEET_HOSTNAME_PATTERN = /\b(?=.{1,253}\b)(?!-)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}\b/gi;
2240
+ var FLEET_IP_PATTERN = /\b(?:\d{1,3}\.){3}\d{1,3}\b/g;
2241
+ var FLEET_MAC_PATTERN = /\b(?:[0-9a-f]{2}[:-]){5}[0-9a-f]{2}\b/gi;
2242
+ function scrubFleetIdentifiers(text) {
2243
+ return text.replace(FLEET_MAC_PATTERN, "[REDACTED_MAC]").replace(FLEET_IP_PATTERN, "[REDACTED_IP]").replace(FLEET_HOSTNAME_PATTERN, "[REDACTED_HOSTNAME]");
2244
+ }
2219
2245
 
2220
2246
  // src/capture/quality.ts
2221
2247
  var QUALITY_THRESHOLD = 0.1;
@@ -2792,6 +2818,35 @@ function narrativesConflict(narrative1, narrative2) {
2792
2818
  return null;
2793
2819
  }
2794
2820
 
2821
+ // src/sync/targets.ts
2822
+ function isFleetProjectName(projectName, config) {
2823
+ const fleetProjectName = config.fleet?.project_name ?? "shared-experience";
2824
+ if (!projectName || !fleetProjectName)
2825
+ return false;
2826
+ return projectName.trim().toLowerCase() === fleetProjectName.trim().toLowerCase();
2827
+ }
2828
+ function hasFleetTarget(config) {
2829
+ return Boolean(config.fleet?.namespace?.trim() && config.fleet?.api_key?.trim() && (config.fleet?.project_name ?? "shared-experience").trim());
2830
+ }
2831
+ function resolveSyncTarget(config, projectName) {
2832
+ if (isFleetProjectName(projectName, config) && hasFleetTarget(config)) {
2833
+ return {
2834
+ key: `fleet:${config.fleet.namespace}`,
2835
+ apiKey: config.fleet.api_key,
2836
+ namespace: config.fleet.namespace,
2837
+ siteId: config.site_id,
2838
+ isFleet: true
2839
+ };
2840
+ }
2841
+ return {
2842
+ key: `default:${config.namespace}`,
2843
+ apiKey: config.candengo_api_key,
2844
+ namespace: config.namespace,
2845
+ siteId: config.site_id,
2846
+ isFleet: false
2847
+ };
2848
+ }
2849
+
2795
2850
  // src/tools/save.ts
2796
2851
  var VALID_TYPES = [
2797
2852
  "bugfix",
@@ -2840,7 +2895,8 @@ async function saveObservation(db, config, input) {
2840
2895
  const factsJson = structuredFacts.length > 0 ? config.scrubbing.enabled ? scrubSecrets(JSON.stringify(structuredFacts), customPatterns) : JSON.stringify(structuredFacts) : null;
2841
2896
  const filesReadJson = filesRead ? JSON.stringify(filesRead) : null;
2842
2897
  const filesModifiedJson = filesModified ? JSON.stringify(filesModified) : null;
2843
- let sensitivity = input.sensitivity ?? config.scrubbing.default_sensitivity;
2898
+ const fleetProject = isFleetProjectName(project.name, config);
2899
+ let sensitivity = input.sensitivity ?? (fleetProject ? "shared" : config.scrubbing.default_sensitivity);
2844
2900
  if (config.scrubbing.enabled && containsSecrets([input.title, input.narrative, JSON.stringify(input.facts)].filter(Boolean).join(" "), customPatterns)) {
2845
2901
  if (sensitivity === "shared") {
2846
2902
  sensitivity = "personal";
@@ -76,6 +76,16 @@ function createDefaultConfig() {
76
76
  },
77
77
  transcript_analysis: {
78
78
  enabled: false
79
+ },
80
+ http: {
81
+ enabled: false,
82
+ port: 3767,
83
+ bearer_tokens: []
84
+ },
85
+ fleet: {
86
+ project_name: "shared-experience",
87
+ namespace: "",
88
+ api_key: ""
79
89
  }
80
90
  };
81
91
  }
@@ -137,6 +147,16 @@ function loadConfig() {
137
147
  },
138
148
  transcript_analysis: {
139
149
  enabled: asBool(config["transcript_analysis"]?.["enabled"], defaults.transcript_analysis.enabled)
150
+ },
151
+ http: {
152
+ enabled: asBool(config["http"]?.["enabled"], defaults.http.enabled),
153
+ port: asNumber(config["http"]?.["port"], defaults.http.port),
154
+ bearer_tokens: asStringArray(config["http"]?.["bearer_tokens"], defaults.http.bearer_tokens)
155
+ },
156
+ fleet: {
157
+ project_name: asString(config["fleet"]?.["project_name"], defaults.fleet.project_name),
158
+ namespace: asString(config["fleet"]?.["namespace"], defaults.fleet.namespace),
159
+ api_key: asString(config["fleet"]?.["api_key"], defaults.fleet.api_key)
140
160
  }
141
161
  };
142
162
  }
@@ -2490,6 +2510,12 @@ function containsSecrets(text, customPatterns = []) {
2490
2510
  }
2491
2511
  return false;
2492
2512
  }
2513
+ var FLEET_HOSTNAME_PATTERN = /\b(?=.{1,253}\b)(?!-)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}\b/gi;
2514
+ var FLEET_IP_PATTERN = /\b(?:\d{1,3}\.){3}\d{1,3}\b/g;
2515
+ var FLEET_MAC_PATTERN = /\b(?:[0-9a-f]{2}[:-]){5}[0-9a-f]{2}\b/gi;
2516
+ function scrubFleetIdentifiers(text) {
2517
+ return text.replace(FLEET_MAC_PATTERN, "[REDACTED_MAC]").replace(FLEET_IP_PATTERN, "[REDACTED_IP]").replace(FLEET_HOSTNAME_PATTERN, "[REDACTED_HOSTNAME]");
2518
+ }
2493
2519
 
2494
2520
  // src/capture/quality.ts
2495
2521
  var QUALITY_THRESHOLD = 0.1;
@@ -2885,6 +2911,35 @@ function narrativesConflict(narrative1, narrative2) {
2885
2911
  return null;
2886
2912
  }
2887
2913
 
2914
+ // src/sync/targets.ts
2915
+ function isFleetProjectName(projectName, config) {
2916
+ const fleetProjectName = config.fleet?.project_name ?? "shared-experience";
2917
+ if (!projectName || !fleetProjectName)
2918
+ return false;
2919
+ return projectName.trim().toLowerCase() === fleetProjectName.trim().toLowerCase();
2920
+ }
2921
+ function hasFleetTarget(config) {
2922
+ return Boolean(config.fleet?.namespace?.trim() && config.fleet?.api_key?.trim() && (config.fleet?.project_name ?? "shared-experience").trim());
2923
+ }
2924
+ function resolveSyncTarget(config, projectName) {
2925
+ if (isFleetProjectName(projectName, config) && hasFleetTarget(config)) {
2926
+ return {
2927
+ key: `fleet:${config.fleet.namespace}`,
2928
+ apiKey: config.fleet.api_key,
2929
+ namespace: config.fleet.namespace,
2930
+ siteId: config.site_id,
2931
+ isFleet: true
2932
+ };
2933
+ }
2934
+ return {
2935
+ key: `default:${config.namespace}`,
2936
+ apiKey: config.candengo_api_key,
2937
+ namespace: config.namespace,
2938
+ siteId: config.site_id,
2939
+ isFleet: false
2940
+ };
2941
+ }
2942
+
2888
2943
  // src/tools/save.ts
2889
2944
  var VALID_TYPES = [
2890
2945
  "bugfix",
@@ -2933,7 +2988,8 @@ async function saveObservation(db, config, input) {
2933
2988
  const factsJson = structuredFacts.length > 0 ? config.scrubbing.enabled ? scrubSecrets(JSON.stringify(structuredFacts), customPatterns) : JSON.stringify(structuredFacts) : null;
2934
2989
  const filesReadJson = filesRead ? JSON.stringify(filesRead) : null;
2935
2990
  const filesModifiedJson = filesModified ? JSON.stringify(filesModified) : null;
2936
- let sensitivity = input.sensitivity ?? config.scrubbing.default_sensitivity;
2991
+ const fleetProject = isFleetProjectName(project.name, config);
2992
+ let sensitivity = input.sensitivity ?? (fleetProject ? "shared" : config.scrubbing.default_sensitivity);
2937
2993
  if (config.scrubbing.enabled && containsSecrets([input.title, input.narrative, JSON.stringify(input.facts)].filter(Boolean).join(" "), customPatterns)) {
2938
2994
  if (sensitivity === "shared") {
2939
2995
  sensitivity = "personal";
@@ -152,6 +152,16 @@ function createDefaultConfig() {
152
152
  },
153
153
  transcript_analysis: {
154
154
  enabled: false
155
+ },
156
+ http: {
157
+ enabled: false,
158
+ port: 3767,
159
+ bearer_tokens: []
160
+ },
161
+ fleet: {
162
+ project_name: "shared-experience",
163
+ namespace: "",
164
+ api_key: ""
155
165
  }
156
166
  };
157
167
  }
@@ -213,6 +223,16 @@ function loadConfig() {
213
223
  },
214
224
  transcript_analysis: {
215
225
  enabled: asBool(config["transcript_analysis"]?.["enabled"], defaults.transcript_analysis.enabled)
226
+ },
227
+ http: {
228
+ enabled: asBool(config["http"]?.["enabled"], defaults.http.enabled),
229
+ port: asNumber(config["http"]?.["port"], defaults.http.port),
230
+ bearer_tokens: asStringArray(config["http"]?.["bearer_tokens"], defaults.http.bearer_tokens)
231
+ },
232
+ fleet: {
233
+ project_name: asString(config["fleet"]?.["project_name"], defaults.fleet.project_name),
234
+ namespace: asString(config["fleet"]?.["namespace"], defaults.fleet.namespace),
235
+ api_key: asString(config["fleet"]?.["api_key"], defaults.fleet.api_key)
216
236
  }
217
237
  };
218
238
  }
@@ -755,6 +755,12 @@ function containsSecrets(text, customPatterns = []) {
755
755
  }
756
756
  return false;
757
757
  }
758
+ var FLEET_HOSTNAME_PATTERN = /\b(?=.{1,253}\b)(?!-)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}\b/gi;
759
+ var FLEET_IP_PATTERN = /\b(?:\d{1,3}\.){3}\d{1,3}\b/g;
760
+ var FLEET_MAC_PATTERN = /\b(?:[0-9a-f]{2}[:-]){5}[0-9a-f]{2}\b/gi;
761
+ function scrubFleetIdentifiers(text) {
762
+ return text.replace(FLEET_MAC_PATTERN, "[REDACTED_MAC]").replace(FLEET_IP_PATTERN, "[REDACTED_IP]").replace(FLEET_HOSTNAME_PATTERN, "[REDACTED_HOSTNAME]");
763
+ }
758
764
 
759
765
  // src/capture/quality.ts
760
766
  var QUALITY_THRESHOLD = 0.1;
@@ -1150,6 +1156,35 @@ function narrativesConflict(narrative1, narrative2) {
1150
1156
  return null;
1151
1157
  }
1152
1158
 
1159
+ // src/sync/targets.ts
1160
+ function isFleetProjectName(projectName, config) {
1161
+ const fleetProjectName = config.fleet?.project_name ?? "shared-experience";
1162
+ if (!projectName || !fleetProjectName)
1163
+ return false;
1164
+ return projectName.trim().toLowerCase() === fleetProjectName.trim().toLowerCase();
1165
+ }
1166
+ function hasFleetTarget(config) {
1167
+ return Boolean(config.fleet?.namespace?.trim() && config.fleet?.api_key?.trim() && (config.fleet?.project_name ?? "shared-experience").trim());
1168
+ }
1169
+ function resolveSyncTarget(config, projectName) {
1170
+ if (isFleetProjectName(projectName, config) && hasFleetTarget(config)) {
1171
+ return {
1172
+ key: `fleet:${config.fleet.namespace}`,
1173
+ apiKey: config.fleet.api_key,
1174
+ namespace: config.fleet.namespace,
1175
+ siteId: config.site_id,
1176
+ isFleet: true
1177
+ };
1178
+ }
1179
+ return {
1180
+ key: `default:${config.namespace}`,
1181
+ apiKey: config.candengo_api_key,
1182
+ namespace: config.namespace,
1183
+ siteId: config.site_id,
1184
+ isFleet: false
1185
+ };
1186
+ }
1187
+
1153
1188
  // src/tools/save.ts
1154
1189
  var VALID_TYPES = [
1155
1190
  "bugfix",
@@ -1198,7 +1233,8 @@ async function saveObservation(db, config, input) {
1198
1233
  const factsJson = structuredFacts.length > 0 ? config.scrubbing.enabled ? scrubSecrets(JSON.stringify(structuredFacts), customPatterns) : JSON.stringify(structuredFacts) : null;
1199
1234
  const filesReadJson = filesRead ? JSON.stringify(filesRead) : null;
1200
1235
  const filesModifiedJson = filesModified ? JSON.stringify(filesModified) : null;
1201
- let sensitivity = input.sensitivity ?? config.scrubbing.default_sensitivity;
1236
+ const fleetProject = isFleetProjectName(project.name, config);
1237
+ let sensitivity = input.sensitivity ?? (fleetProject ? "shared" : config.scrubbing.default_sensitivity);
1202
1238
  if (config.scrubbing.enabled && containsSecrets([input.title, input.narrative, JSON.stringify(input.facts)].filter(Boolean).join(" "), customPatterns)) {
1203
1239
  if (sensitivity === "shared") {
1204
1240
  sensitivity = "personal";
@@ -3104,6 +3140,11 @@ function describeContinuityState(state) {
3104
3140
  return "No fresh repo-local continuity yet; older memory should be treated cautiously.";
3105
3141
  }
3106
3142
  }
3143
+ function pickPreferredAgent(activeAgents, latestAgent) {
3144
+ if (activeAgents.includes("claude-code"))
3145
+ return "claude-code";
3146
+ return latestAgent && activeAgents.includes(latestAgent) ? latestAgent : activeAgents[0] ?? null;
3147
+ }
3107
3148
 
3108
3149
  // src/telemetry/stack-detect.ts
3109
3150
  import { existsSync as existsSync2 } from "node:fs";
@@ -3225,7 +3266,7 @@ import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync
3225
3266
  import { join as join3 } from "node:path";
3226
3267
  import { homedir } from "node:os";
3227
3268
  var STATE_PATH = join3(homedir(), ".engrm", "config-fingerprint.json");
3228
- var CLIENT_VERSION = "0.4.37";
3269
+ var CLIENT_VERSION = "0.4.39";
3229
3270
  function hashFile(filePath) {
3230
3271
  try {
3231
3272
  if (!existsSync3(filePath))
@@ -3429,6 +3470,16 @@ function createDefaultConfig() {
3429
3470
  },
3430
3471
  transcript_analysis: {
3431
3472
  enabled: false
3473
+ },
3474
+ http: {
3475
+ enabled: false,
3476
+ port: 3767,
3477
+ bearer_tokens: []
3478
+ },
3479
+ fleet: {
3480
+ project_name: "shared-experience",
3481
+ namespace: "",
3482
+ api_key: ""
3432
3483
  }
3433
3484
  };
3434
3485
  }
@@ -3490,6 +3541,16 @@ function loadConfig() {
3490
3541
  },
3491
3542
  transcript_analysis: {
3492
3543
  enabled: asBool(config["transcript_analysis"]?.["enabled"], defaults.transcript_analysis.enabled)
3544
+ },
3545
+ http: {
3546
+ enabled: asBool(config["http"]?.["enabled"], defaults.http.enabled),
3547
+ port: asNumber(config["http"]?.["port"], defaults.http.port),
3548
+ bearer_tokens: asStringArray(config["http"]?.["bearer_tokens"], defaults.http.bearer_tokens)
3549
+ },
3550
+ fleet: {
3551
+ project_name: asString(config["fleet"]?.["project_name"], defaults.fleet.project_name),
3552
+ namespace: asString(config["fleet"]?.["namespace"], defaults.fleet.namespace),
3553
+ api_key: asString(config["fleet"]?.["api_key"], defaults.fleet.api_key)
3493
3554
  }
3494
3555
  };
3495
3556
  }
@@ -3610,10 +3671,13 @@ function parseSourceId(sourceId) {
3610
3671
  }
3611
3672
 
3612
3673
  // src/sync/pull.ts
3613
- var PULL_CURSOR_KEY = "pull_cursor";
3674
+ function pullCursorKey(namespace) {
3675
+ return namespace === "default" ? "pull_cursor" : `pull_cursor:${namespace}`;
3676
+ }
3614
3677
  var MAX_PAGES = 20;
3615
3678
  async function pullFromVector(db, client, config, limit = 50) {
3616
- let cursor = db.getSyncState(PULL_CURSOR_KEY) ?? undefined;
3679
+ const cursorKey = pullCursorKey(client.namespace || "default");
3680
+ let cursor = db.getSyncState(cursorKey) ?? undefined;
3617
3681
  let totalReceived = 0;
3618
3682
  let totalMerged = 0;
3619
3683
  let totalSkipped = 0;
@@ -3624,7 +3688,7 @@ async function pullFromVector(db, client, config, limit = 50) {
3624
3688
  totalMerged += merged;
3625
3689
  totalSkipped += skipped;
3626
3690
  if (response.cursor) {
3627
- db.setSyncState(PULL_CURSOR_KEY, response.cursor);
3691
+ db.setSyncState(cursorKey, response.cursor);
3628
3692
  cursor = response.cursor;
3629
3693
  }
3630
3694
  if (!response.has_more || response.changes.length === 0)
@@ -3841,16 +3905,16 @@ class VectorClient {
3841
3905
  apiKey;
3842
3906
  siteId;
3843
3907
  namespace;
3844
- constructor(config) {
3908
+ constructor(config, overrides = {}) {
3845
3909
  const baseUrl = getBaseUrl(config);
3846
- const apiKey = getApiKey(config);
3910
+ const apiKey = overrides.apiKey ?? getApiKey(config);
3847
3911
  if (!baseUrl || !apiKey) {
3848
3912
  throw new Error("VectorClient requires candengo_url and candengo_api_key");
3849
3913
  }
3850
3914
  this.baseUrl = baseUrl.replace(/\/$/, "");
3851
3915
  this.apiKey = apiKey;
3852
- this.siteId = config.site_id;
3853
- this.namespace = config.namespace;
3916
+ this.siteId = overrides.siteId ?? config.site_id;
3917
+ this.namespace = overrides.namespace ?? config.namespace;
3854
3918
  }
3855
3919
  static isConfigured(config) {
3856
3920
  return getApiKey(config) !== null && getBaseUrl(config) !== null;
@@ -5980,8 +6044,9 @@ function formatInspectHints(context, visibleObservationIds = [], recallItems = [
5980
6044
  if (unique.length === 0)
5981
6045
  return [];
5982
6046
  const ids = visibleObservationIds.slice(0, 5);
5983
- const openNowItem = recallItems.find((item) => item.kind !== "memory") ?? null;
5984
- const resumeAgent = activeAgents.length > 1 ? context.recentSessions?.[0]?.agent ?? null : null;
6047
+ const preferredAgent = pickPreferredAgent(activeAgents, context.recentSessions?.[0]?.agent ?? null);
6048
+ const openNowItem = (preferredAgent ? recallItems.find((item) => item.source_agent === preferredAgent && item.kind !== "memory") ?? recallItems.find((item) => item.source_agent === preferredAgent) : null) ?? recallItems.find((item) => item.kind !== "memory") ?? null;
6049
+ const resumeAgent = activeAgents.length > 1 ? preferredAgent : null;
5985
6050
  const fetchHint = ids.length > 0 ? `get_observations([${ids.join(", ")}])` : null;
5986
6051
  return [
5987
6052
  `${c2.dim}Next look:${c2.reset} ${unique.join(" \xB7 ")}`,
@@ -6058,7 +6123,12 @@ function buildStartupRecallItems(context) {
6058
6123
  });
6059
6124
  }
6060
6125
  const seen = new Set;
6061
- return items.sort((a, b) => b.score - a.score || a.key.localeCompare(b.key)).filter((item) => {
6126
+ const preferredAgent = pickPreferredAgent(collectStartupAgents(context), context.recentSessions?.[0]?.agent ?? null);
6127
+ return items.sort((a, b) => {
6128
+ const aBoost = preferredAgent && a.source_agent === preferredAgent ? 1 : 0;
6129
+ const bBoost = preferredAgent && b.source_agent === preferredAgent ? 1 : 0;
6130
+ return b.score + bBoost - (a.score + aBoost) || a.key.localeCompare(b.key);
6131
+ }).filter((item) => {
6062
6132
  if (seen.has(item.key))
6063
6133
  return false;
6064
6134
  seen.add(item.key);