@karmaniverous/jeeves-watcher 0.6.5 → 0.6.6

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.
@@ -4381,6 +4381,7 @@ async function* scrollCollection(client, collectionName, filter, limit = 100) {
4381
4381
  */
4382
4382
  class VectorStoreClient {
4383
4383
  client;
4384
+ clientConfig;
4384
4385
  collectionName;
4385
4386
  dims;
4386
4387
  log;
@@ -4393,16 +4394,27 @@ class VectorStoreClient {
4393
4394
  * @param logger - Optional pino logger for retry warnings.
4394
4395
  */
4395
4396
  constructor(config, dimensions, logger) {
4396
- this.client = new QdrantClient({
4397
- url: config.url,
4398
- apiKey: config.apiKey,
4399
- checkCompatibility: false,
4400
- });
4397
+ this.clientConfig = { url: config.url, apiKey: config.apiKey };
4398
+ this.client = this.createClient();
4401
4399
  this.collectionName = config.collectionName;
4402
4400
  this.dims = dimensions;
4403
4401
  this.log = getLogger(logger);
4404
4402
  this.pinoLogger = logger;
4405
4403
  }
4404
+ /**
4405
+ * Create a fresh QdrantClient instance.
4406
+ *
4407
+ * Used to avoid stale HTTP keep-alive connections. The Qdrant JS client's
4408
+ * internal undici Agent uses keepAliveTimeout: 10s, which causes ECONNRESET
4409
+ * when connections sit idle during slow embedding calls (Gemini p99 ~8s).
4410
+ * Creating a fresh client for write operations ensures clean TCP connections.
4411
+ */
4412
+ createClient() {
4413
+ return new QdrantClient({
4414
+ ...this.clientConfig,
4415
+ checkCompatibility: false,
4416
+ });
4417
+ }
4406
4418
  /**
4407
4419
  * Ensure the collection exists with correct dimensions and Cosine distance.
4408
4420
  */
@@ -4450,13 +4462,18 @@ class VectorStoreClient {
4450
4462
  /**
4451
4463
  * Upsert points into the collection.
4452
4464
  *
4465
+ * Uses a fresh QdrantClient per attempt to avoid stale keep-alive connections.
4466
+ * Between embedding calls and upserts, idle connections may be closed by the
4467
+ * server, causing ECONNRESET on reuse.
4468
+ *
4453
4469
  * @param points - The points to upsert.
4454
4470
  */
4455
4471
  async upsert(points) {
4456
4472
  if (points.length === 0)
4457
4473
  return;
4458
4474
  await this.retryOperation('upsert', async () => {
4459
- await this.client.upsert(this.collectionName, {
4475
+ const freshClient = this.createClient();
4476
+ await freshClient.upsert(this.collectionName, {
4460
4477
  wait: true,
4461
4478
  points: points.map((p) => ({
4462
4479
  id: p.id,
@@ -4469,13 +4486,16 @@ class VectorStoreClient {
4469
4486
  /**
4470
4487
  * Delete points by their IDs.
4471
4488
  *
4489
+ * Uses a fresh QdrantClient per attempt to avoid stale keep-alive connections.
4490
+ *
4472
4491
  * @param ids - The point IDs to delete.
4473
4492
  */
4474
4493
  async delete(ids) {
4475
4494
  if (ids.length === 0)
4476
4495
  return;
4477
4496
  await this.retryOperation('delete', async () => {
4478
- await this.client.delete(this.collectionName, {
4497
+ const freshClient = this.createClient();
4498
+ await freshClient.delete(this.collectionName, {
4479
4499
  wait: true,
4480
4500
  points: ids,
4481
4501
  });
package/dist/index.d.ts CHANGED
@@ -742,6 +742,7 @@ interface VectorStore {
742
742
  */
743
743
  declare class VectorStoreClient implements VectorStore {
744
744
  private readonly client;
745
+ private readonly clientConfig;
745
746
  private readonly collectionName;
746
747
  private readonly dims;
747
748
  private readonly log;
@@ -754,6 +755,15 @@ declare class VectorStoreClient implements VectorStore {
754
755
  * @param logger - Optional pino logger for retry warnings.
755
756
  */
756
757
  constructor(config: VectorStoreConfig, dimensions: number, logger?: pino.Logger);
758
+ /**
759
+ * Create a fresh QdrantClient instance.
760
+ *
761
+ * Used to avoid stale HTTP keep-alive connections. The Qdrant JS client's
762
+ * internal undici Agent uses keepAliveTimeout: 10s, which causes ECONNRESET
763
+ * when connections sit idle during slow embedding calls (Gemini p99 ~8s).
764
+ * Creating a fresh client for write operations ensures clean TCP connections.
765
+ */
766
+ private createClient;
757
767
  /**
758
768
  * Ensure the collection exists with correct dimensions and Cosine distance.
759
769
  */
@@ -768,12 +778,18 @@ declare class VectorStoreClient implements VectorStore {
768
778
  /**
769
779
  * Upsert points into the collection.
770
780
  *
781
+ * Uses a fresh QdrantClient per attempt to avoid stale keep-alive connections.
782
+ * Between embedding calls and upserts, idle connections may be closed by the
783
+ * server, causing ECONNRESET on reuse.
784
+ *
771
785
  * @param points - The points to upsert.
772
786
  */
773
787
  upsert(points: VectorPoint[]): Promise<void>;
774
788
  /**
775
789
  * Delete points by their IDs.
776
790
  *
791
+ * Uses a fresh QdrantClient per attempt to avoid stale keep-alive connections.
792
+ *
777
793
  * @param ids - The point IDs to delete.
778
794
  */
779
795
  delete(ids: string[]): Promise<void>;
package/dist/index.js CHANGED
@@ -4363,6 +4363,7 @@ async function* scrollCollection(client, collectionName, filter, limit = 100) {
4363
4363
  */
4364
4364
  class VectorStoreClient {
4365
4365
  client;
4366
+ clientConfig;
4366
4367
  collectionName;
4367
4368
  dims;
4368
4369
  log;
@@ -4375,16 +4376,27 @@ class VectorStoreClient {
4375
4376
  * @param logger - Optional pino logger for retry warnings.
4376
4377
  */
4377
4378
  constructor(config, dimensions, logger) {
4378
- this.client = new QdrantClient({
4379
- url: config.url,
4380
- apiKey: config.apiKey,
4381
- checkCompatibility: false,
4382
- });
4379
+ this.clientConfig = { url: config.url, apiKey: config.apiKey };
4380
+ this.client = this.createClient();
4383
4381
  this.collectionName = config.collectionName;
4384
4382
  this.dims = dimensions;
4385
4383
  this.log = getLogger(logger);
4386
4384
  this.pinoLogger = logger;
4387
4385
  }
4386
+ /**
4387
+ * Create a fresh QdrantClient instance.
4388
+ *
4389
+ * Used to avoid stale HTTP keep-alive connections. The Qdrant JS client's
4390
+ * internal undici Agent uses keepAliveTimeout: 10s, which causes ECONNRESET
4391
+ * when connections sit idle during slow embedding calls (Gemini p99 ~8s).
4392
+ * Creating a fresh client for write operations ensures clean TCP connections.
4393
+ */
4394
+ createClient() {
4395
+ return new QdrantClient({
4396
+ ...this.clientConfig,
4397
+ checkCompatibility: false,
4398
+ });
4399
+ }
4388
4400
  /**
4389
4401
  * Ensure the collection exists with correct dimensions and Cosine distance.
4390
4402
  */
@@ -4432,13 +4444,18 @@ class VectorStoreClient {
4432
4444
  /**
4433
4445
  * Upsert points into the collection.
4434
4446
  *
4447
+ * Uses a fresh QdrantClient per attempt to avoid stale keep-alive connections.
4448
+ * Between embedding calls and upserts, idle connections may be closed by the
4449
+ * server, causing ECONNRESET on reuse.
4450
+ *
4435
4451
  * @param points - The points to upsert.
4436
4452
  */
4437
4453
  async upsert(points) {
4438
4454
  if (points.length === 0)
4439
4455
  return;
4440
4456
  await this.retryOperation('upsert', async () => {
4441
- await this.client.upsert(this.collectionName, {
4457
+ const freshClient = this.createClient();
4458
+ await freshClient.upsert(this.collectionName, {
4442
4459
  wait: true,
4443
4460
  points: points.map((p) => ({
4444
4461
  id: p.id,
@@ -4451,13 +4468,16 @@ class VectorStoreClient {
4451
4468
  /**
4452
4469
  * Delete points by their IDs.
4453
4470
  *
4471
+ * Uses a fresh QdrantClient per attempt to avoid stale keep-alive connections.
4472
+ *
4454
4473
  * @param ids - The point IDs to delete.
4455
4474
  */
4456
4475
  async delete(ids) {
4457
4476
  if (ids.length === 0)
4458
4477
  return;
4459
4478
  await this.retryOperation('delete', async () => {
4460
- await this.client.delete(this.collectionName, {
4479
+ const freshClient = this.createClient();
4480
+ await freshClient.delete(this.collectionName, {
4461
4481
  wait: true,
4462
4482
  points: ids,
4463
4483
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@karmaniverous/jeeves-watcher",
3
- "version": "0.6.5",
3
+ "version": "0.6.6",
4
4
  "author": "Jason Williscroft",
5
5
  "description": "Filesystem watcher that keeps a Qdrant vector store in sync with document changes",
6
6
  "license": "BSD-3-Clause",