@deepseek-ai/dsh-session-query-sqlite 0.0.1-rc.3 → 0.1.0-rc.2

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/LICENSE CHANGED
@@ -1,28 +1,21 @@
1
- BSD 3-Clause License
1
+ MIT License
2
2
 
3
- Copyright (c) 2026, DeepSeek
3
+ Copyright (c) 2026 DeepSeek
4
4
 
5
- Redistribution and use in source and binary forms, with or without
6
- modification, are permitted provided that the following conditions are met:
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
7
11
 
8
- 1. Redistributions of source code must retain the above copyright notice, this
9
- list of conditions and the following disclaimer.
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
10
14
 
11
- 2. Redistributions in binary form must reproduce the above copyright notice,
12
- this list of conditions and the following disclaimer in the documentation
13
- and/or other materials provided with the distribution.
14
-
15
- 3. Neither the name of the copyright holder nor the names of its
16
- contributors may be used to endorse or promote products derived from
17
- this software without specific prior written permission.
18
-
19
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/session-query/session-query-sqlite/README.md
5
- README.md: 846f79bd8383a8114a6d1329e7dbe931a67d98d0
6
- README.zh.md: e84e521dd5f392dbcede1e1dd957e4ce0a9bc50f
5
+ README.md: 25257ddbe672d47faf39e1472a1bd882205d8c4e
6
+ README.zh.md: 584e466a5042334e22797a6c2794cce910844d5a
package/README.md CHANGED
@@ -16,7 +16,7 @@ All three surfaces (`current`, `shadowed`, and `log-only`) are searchable by def
16
16
 
17
17
  The service requires `ctx.sessions` and observes optional `ctx.sessionPersistence` dynamically. One serialized state machine compares source-qualified lightweight durable snapshot revisions, non-mutatingly inspects only new or changed logs, extracts shared semantic documents, reconciles changes transactionally, and runs the query. Session queries never invoke the persistence backend's crash-repairing `load()`; an owner attaching during inspection cannot mutate its log, and the stable-observation retry makes the result live-preferred. The TEMP live row still records persisted availability, and the durable base refreshes after that live owner detaches. Repeated queries and an unchanged same-store reopen perform no full durable-log inspection; switching stores, or observing new, changed, deleted, or externally load-repaired sources, reconciles on the next stable observation. Source or transaction failure commits nothing, and the next search retries.
18
18
 
19
- `openAt: startup` is the default: service activation imports `node:sqlite`, opens the handle, and fails before publication when the index is invalid. `openAt: first-search` publishes the service as ACTIVE without importing the SQLite module or opening a handle; the first concurrent searches share one readiness promise, and disposal before any search opens nothing. This mode supports compositions that need clean Node 22 startup output by deferring SQLite's experimental warning until the first actual search; it does not suppress a warning at that point. An invalid database likewise fails the first search instead of service activation.
19
+ `openAt: startup` is the default: service activation imports `node:sqlite`, opens the handle, and fails before publication when the index is invalid. `openAt: first-search` publishes the service as ACTIVE without importing the SQLite module or opening a handle; the first concurrent searches share one readiness promise, and disposal before any search opens nothing. This mode supports compositions that need clean Node 22 startup output by deferring SQLite's experimental warning until the first actual search; it does not suppress a warning at that point. An invalid database likewise fails the first search instead of service activation. `openAt: never` turns full-text search off for the deployment: `searchSessions` and `searchEvents` fail with `SESSION_QUERY_SEARCH_DISABLED` before any request normalization, node:sqlite is never imported or opened, and no source observation or reconciliation runs, while every inherited exact read, filter, and trace on `ctx.sessionQuery` keeps working.
20
20
 
21
21
  Persisted FTS rows live in a dedicated derived database. Connection-local TEMP tables hold live rows, which shadow the durable base for the same session and reveal it when the live owner disappears. Unmounting persistence hides durable rows without discarding the cache; remounting reconciles it. Closing or reopening the database drops every live overlay while retaining persisted rows.
22
22
 
@@ -27,7 +27,7 @@ The database is disposable but reset is guarded: every recognized schema version
27
27
  | Key | Default | Contract |
28
28
  |---|---:|---|
29
29
  | `path` | required | Dedicated derived-index SQLite path; `:memory:` is supported. Missing filesystem paths are created owner-only on POSIX filesystems. |
30
- | `openAt` | `startup` | `startup` opens before service activation completes; `first-search` defers the SQLite module and handle until search. |
30
+ | `openAt` | `startup` | `startup` opens before service activation completes; `first-search` defers the SQLite module and handle until search; `never` disables full-text search (typed `SESSION_QUERY_SEARCH_DISABLED` failures) while inherited reads stay available. |
31
31
  | `journalMode` | `wal` | `wal`, `delete`, `truncate`, or `persist`. |
32
32
  | `defaultLimit` | `20` | Page size when a request omits `limit`; at most `Number.MAX_SAFE_INTEGER - 1`. |
33
33
  | `maxLimit` | `100` | Largest accepted request page size; at most `Number.MAX_SAFE_INTEGER - 1`. |
package/README.zh.md CHANGED
@@ -16,7 +16,7 @@
16
16
 
17
17
  该服务需要 `ctx.sessions`,并动态观察可选的 `ctx.sessionPersistence`。一个串行化状态机比较来源限定的轻量持久化快照修订,仅以不修改日志的方式检查新日志或已更改日志,提取共享语义文档,以事务方式对账变更,然后运行查询。会话查询绝不会调用持久化后端会修复崩溃的 `load()`;检查期间接入的活动所有者无法修改其日志,稳定观察重试使结果优先使用实时来源。TEMP 实时行仍会记录持久化可用性,而持久基库会在该活动所有者脱离后刷新。重复查询以及同一存储未发生变化的重新打开操作不会执行完整持久化日志检查;切换存储,或观察到新增、已更改、已删除或经外部 load 修复的来源时,会在下次稳定观察时对账。来源或事务失败不会提交任何内容,下一次搜索会重试。
18
18
 
19
- `openAt: startup` 是默认值:服务激活会导入 `node:sqlite` 并打开句柄;如果索引无效,则会在服务发布前失败。`openAt: first-search` 会将服务以 ACTIVE 状态发布,同时不导入 SQLite 模块也不打开句柄;首批并发搜索共享同一个就绪 promise,在任何搜索前 dispose(资源释放)服务时也不会导入模块或打开句柄。此模式通过把 SQLite 的实验性警告推迟到首次实际搜索,支持需要干净 Node 22 启动输出的组合;它不会抑制届时的警告。无效数据库同样会使首次搜索失败,而不是服务激活失败。
19
+ `openAt: startup` 是默认值:服务激活会导入 `node:sqlite` 并打开句柄;如果索引无效,则会在服务发布前失败。`openAt: first-search` 会将服务以 ACTIVE 状态发布,同时不导入 SQLite 模块也不打开句柄;首批并发搜索共享同一个就绪 promise,在任何搜索前 dispose(资源释放)服务时也不会导入模块或打开句柄。此模式通过把 SQLite 的实验性警告推迟到首次实际搜索,支持需要干净 Node 22 启动输出的组合;它不会抑制届时的警告。无效数据库同样会使首次搜索失败,而不是服务激活失败。`openAt: never` 为该部署关闭全文搜索:`searchSessions` 和 `searchEvents` 在任何请求规范化之前就以 `SESSION_QUERY_SEARCH_DISABLED` 失败,node:sqlite 绝不会被导入或打开,也不运行任何来源观察或对账,而 `ctx.sessionQuery` 上继承的全部精确读取、过滤和跟踪保持可用。
20
20
 
21
21
  持久化 FTS 行位于专用派生数据库中。连接本地 TEMP 表保存实时行,这些行会遮蔽同一会话的持久化基库,并在实时所有者消失后使其重新可见。卸载持久化会隐藏持久行,但不会丢弃缓存;重新挂载会对账缓存。关闭或重新打开数据库会删除全部实时覆盖层,但保留持久行。
22
22
 
@@ -27,7 +27,7 @@
27
27
  | 键 | 默认值 | 约定 |
28
28
  |---|---:|---|
29
29
  | `path` | 必填 | 专用派生索引 SQLite 路径;支持 `:memory:`。在 POSIX 文件系统上,缺失的文件系统路径会以仅所有者可访问的方式创建。 |
30
- | `openAt` | `startup` | `startup` 会在服务激活完成前打开;`first-search` 把 SQLite 模块与句柄推迟到搜索时再加载和打开。 |
30
+ | `openAt` | `startup` | `startup` 会在服务激活完成前打开;`first-search` 把 SQLite 模块与句柄推迟到搜索时再加载和打开;`never` 关闭全文搜索(以类型化的 `SESSION_QUERY_SEARCH_DISABLED` 失败),继承的读取保持可用。 |
31
31
  | `journalMode` | `wal` | `wal`、`delete`、`truncate` 或 `persist`。 |
32
32
  | `defaultLimit` | `20` | 请求省略 `limit` 时的分页大小;最多为 `Number.MAX_SAFE_INTEGER - 1`。 |
33
33
  | `maxLimit` | `100` | 接受的最大请求分页大小;最多为 `Number.MAX_SAFE_INTEGER - 1`。 |
package/lib/index.js CHANGED
@@ -476,7 +476,11 @@ var SqliteSessionQueryEngine = class extends SessionQueryEngine {
476
476
  static inject = ["sessions"];
477
477
  static Config = z.object({
478
478
  path: z.string().required(),
479
- openAt: z.union(["startup", "first-search"]).default("startup"),
479
+ openAt: z.union([
480
+ "startup",
481
+ "first-search",
482
+ "never"
483
+ ]).default("startup"),
480
484
  journalMode: z.union([
481
485
  "wal",
482
486
  "delete",
@@ -529,6 +533,7 @@ var SqliteSessionQueryEngine = class extends SessionQueryEngine {
529
533
  if (this.config.openAt === "startup") await this._ensureReady(void 0);
530
534
  }
531
535
  async searchSessions(request, exec) {
536
+ this._assertSearchEnabled();
532
537
  const normalized = normalizeSessionRequest(request, this.config);
533
538
  const signal = exec?.signal;
534
539
  return this._serialized(signal, async () => {
@@ -549,6 +554,7 @@ var SqliteSessionQueryEngine = class extends SessionQueryEngine {
549
554
  });
550
555
  }
551
556
  async searchEvents(request, exec) {
557
+ this._assertSearchEnabled();
552
558
  const normalized = normalizeEventRequest(request, this.config);
553
559
  const signal = exec?.signal;
554
560
  return this._serialized(signal, async () => {
@@ -577,6 +583,15 @@ var SqliteSessionQueryEngine = class extends SessionQueryEngine {
577
583
  this._closePromise ??= this._close();
578
584
  return this._closePromise;
579
585
  }
586
+ /**
587
+ * Refuse full-text calls under `openAt: 'never'` before any request
588
+ * normalization or SQLite work, so a disabled deployment never imports
589
+ * node:sqlite, opens the index, or observes sources.
590
+ */
591
+ _assertSearchEnabled() {
592
+ if (this.config.openAt !== "never") return;
593
+ throw new SessionQueryError("session search is disabled: this deployment configures the session-query index with openAt \"never\"", "SESSION_QUERY_SEARCH_DISABLED");
594
+ }
580
595
  async _close() {
581
596
  this._closed = true;
582
597
  await this._tail;
@@ -1066,7 +1081,11 @@ function resolveConfig(config) {
1066
1081
  persistedInspectConcurrency: config.persistedInspectConcurrency ?? SESSION_QUERY_DEFAULT_PERSISTED_INSPECT_CONCURRENCY
1067
1082
  };
1068
1083
  if (typeof resolved.path !== "string" || resolved.path.trim().length === 0) throw invalidConfig("path must not be blank");
1069
- if (!["startup", "first-search"].includes(resolved.openAt)) throw invalidConfig("openAt is not supported");
1084
+ if (![
1085
+ "startup",
1086
+ "first-search",
1087
+ "never"
1088
+ ].includes(resolved.openAt)) throw invalidConfig("openAt is not supported");
1070
1089
  assertPageLimit("defaultLimit", resolved.defaultLimit);
1071
1090
  assertPageLimit("maxLimit", resolved.maxLimit);
1072
1091
  assertPositiveInteger("snippetChars", resolved.snippetChars);
@@ -23,8 +23,8 @@ export declare const SESSION_QUERY_SQLITE_DEFAULT_LIMIT = 20;
23
23
  export declare const SESSION_QUERY_SQLITE_MAX_LIMIT = 100;
24
24
  /** Default maximum snippet length in Unicode code points. */
25
25
  export declare const SESSION_QUERY_SQLITE_SNIPPET_CHARS = 240;
26
- /** SQLite module/handle opening phase. */
27
- export type OpenAt = 'startup' | 'first-search';
26
+ /** SQLite module/handle opening phase; `never` disables full-text search entirely. */
27
+ export type OpenAt = 'startup' | 'first-search' | 'never';
28
28
  /** Combined session-query configuration backed by SQLite full-text search. */
29
29
  export interface Config extends SessionQueryConfig {
30
30
  /**
@@ -33,7 +33,13 @@ export interface Config extends SessionQueryConfig {
33
33
  * POSIX filesystems; existing modes are preserved.
34
34
  */
35
35
  path: string;
36
- /** Open the SQLite module and handle at service activation or the first search. Defaults to `startup`. */
36
+ /**
37
+ * Open the SQLite module and handle at service activation or the first
38
+ * search, or `never` to disable full-text search: the inherited exact
39
+ * reads, filters, and traces stay available, while `searchSessions` and
40
+ * `searchEvents` fail with `SESSION_QUERY_SEARCH_DISABLED` and SQLite is
41
+ * never imported or opened. Defaults to `startup`.
42
+ */
37
43
  openAt?: OpenAt;
38
44
  /** SQLite journal mode. Defaults to `wal`. */
39
45
  journalMode?: JournalMode;
@@ -81,6 +87,12 @@ export declare class SqliteSessionQueryEngine extends SessionQueryEngine {
81
87
  searchEvents(request: SessionEventSearchRequest, exec?: SessionSearchExecContext): Promise<SessionEventSearchPage>;
82
88
  /** Close the database after every accepted operation reaches quiescence. */
83
89
  close(): Promise<void>;
90
+ /**
91
+ * Refuse full-text calls under `openAt: 'never'` before any request
92
+ * normalization or SQLite work, so a disabled deployment never imports
93
+ * node:sqlite, opens the index, or observes sources.
94
+ */
95
+ private _assertSearchEnabled;
84
96
  private _close;
85
97
  private _open;
86
98
  private _ensureReady;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-session-query-sqlite",
3
3
  "description": "Concrete ctx.sessionQuery backend with SQLite FTS5 search",
4
- "version": "0.0.1-rc.3",
4
+ "version": "0.1.0-rc.2",
5
5
  "publishConfig": {
6
6
  "access": "restricted"
7
7
  },
@@ -30,13 +30,13 @@
30
30
  "lib/invariant.js",
31
31
  "lib/types/**/*.d.ts"
32
32
  ],
33
- "license": "BSD-3-Clause",
33
+ "license": "MIT",
34
34
  "peerDependencies": {
35
- "@deepseek-ai/dsh-session-persistence": "^0.0.1-rc.3",
36
- "@deepseek-ai/dsh-invariants": "^0.0.1-rc.3",
37
- "@deepseek-ai/dsh-session": "^0.0.1-rc.3",
38
- "@deepseek-ai/dsh-session-query": "^0.0.1-rc.3",
39
- "@deepseek-ai/cordis": "^4.0.1-rc.1"
35
+ "@deepseek-ai/dsh-invariants": "^0.1.0-rc.2",
36
+ "@deepseek-ai/dsh-session": "^0.1.0-rc.2",
37
+ "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.2",
38
+ "@deepseek-ai/dsh-session-query": "^0.1.0-rc.2",
39
+ "@deepseek-ai/cordis": "^4.0.1"
40
40
  },
41
41
  "peerDependenciesMeta": {
42
42
  "@deepseek-ai/dsh-session-persistence": {
@@ -44,15 +44,15 @@
44
44
  }
45
45
  },
46
46
  "dependencies": {
47
- "@deepseek-ai/schemastery": "^3.18.1-rc.1"
47
+ "@deepseek-ai/schemastery": "^3.18.1"
48
48
  },
49
49
  "devDependencies": {
50
- "@deepseek-ai/cordis-plugin-loader": "^1.0.1-rc.1",
51
- "@deepseek-ai/dsh-invariants": "^0.0.1-rc.3",
52
- "@deepseek-ai/dsh-session": "^0.0.1-rc.3",
53
- "@deepseek-ai/dsh-session-persistence": "^0.0.1-rc.3",
54
- "@deepseek-ai/dsh-session-persistence-sqlite": "^0.0.1-rc.3",
55
- "@deepseek-ai/dsh-session-query": "^0.0.1-rc.3",
56
- "@deepseek-ai/cordis": "^4.0.1-rc.1"
50
+ "@deepseek-ai/cordis-plugin-loader": "^1.0.2",
51
+ "@deepseek-ai/dsh-invariants": "^0.1.0-rc.2",
52
+ "@deepseek-ai/dsh-session": "^0.1.0-rc.2",
53
+ "@deepseek-ai/dsh-session-persistence": "^0.1.0-rc.2",
54
+ "@deepseek-ai/dsh-session-persistence-sqlite": "^0.1.0-rc.2",
55
+ "@deepseek-ai/dsh-session-query": "^0.1.0-rc.2",
56
+ "@deepseek-ai/cordis": "^4.0.1"
57
57
  }
58
58
  }