@carllee1983/dbcli 1.43.0 → 1.44.1

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dbcli-agent",
3
- "version": "1.43.0",
3
+ "version": "1.44.1",
4
4
  "description": "Database CLI skill and command reference for AI agents.",
5
5
  "author": {
6
6
  "name": "Carl Lee",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dbcli-agent",
3
- "version": "1.43.0",
3
+ "version": "1.44.1",
4
4
  "description": "Database CLI skill and command reference for AI agents",
5
5
  "author": {
6
6
  "name": "Carl Lee",
@@ -2,7 +2,7 @@
2
2
  "name": "dbcli-agent",
3
3
  "displayName": "dbcli Agent",
4
4
  "description": "Database CLI skill and command reference for AI agents.",
5
- "version": "1.43.0",
5
+ "version": "1.44.1",
6
6
  "author": {
7
7
  "name": "Carl Lee",
8
8
  "url": "https://github.com/CarlLee1983"
package/CHANGELOG.md CHANGED
@@ -5,6 +5,26 @@ All notable changes to dbcli are documented here.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.44.1] - 2026-08-02 - `agent-core` 的 `loadEnvFile` 改用 node:fs,可在 Node 執行
9
+
10
+ ### Fixed
11
+
12
+ - **`loadEnvFile` 不再依賴 `Bun.file`。** `./agent-core` 存在的理由是給下游 agent CLI 共用,而那些工具不一定跑在 Bun 上;`loadEnvFile` 內部呼叫 `Bun.file()`,在 Node 下直接 `ReferenceError: Bun is not defined`,使整個匯出對第一個 Node 消費者(logq)不可用。改以 `node:fs/promises` 讀檔,解析與「不覆寫既有 `process.env`」的行為完全不變;檔案不存在仍拋 `ConfigError`。其餘五個匯出本來就沒有 runtime 相依,不受影響。
13
+
14
+ ### Added
15
+
16
+ - **Node runtime 契約測試。** 本 repo 的測試全部跑在 Bun 上,所以 agent-core 裡的 Bun-only 呼叫對它們是隱形的 —— 這正是這個 bug 得以發布的原因。新增的契約測試會 spawn 真正的 `node` 行程去 import 建置後的 `dist/agent-core.mjs`,逐一呼叫每個匯出。還原修正後此測試會失敗(已驗證),因此這個失敗模式不會再次出貨。
17
+
18
+ ### Changed
19
+
20
+ - **同步跨平台發版 metadata。** npm package、Codex/Claude/Cursor plugin、packaged Codex plugin 與 Gemini extension 統一為 `1.44.1`。
21
+
22
+ ## [1.44.0] - 2026-08-02 - agent-core 補上錯誤型別與 env reference 型別
23
+
24
+ ### Added
25
+
26
+ - **`./agent-core` 匯出 `ConfigError` 與 `EnvReference`。** 下游工具原本無法用 `instanceof` 判別 env reference 解析失敗,只能比對錯誤訊息字串;也無法引用 `{ $env: string }` 的型別名稱,只能各自重複定義一個結構相同的介面。兩者都是既有模組早已匯出、只是沒有出現在 `public.ts` 的疏漏。runtime interface 因此從五項變六項,型別從三項變四項,皆為加法變更。
27
+
8
28
  ## [1.43.0] - 2026-08-02 - Agent Core、查詢完整性與跨平台修復
9
29
 
10
30
  ### Added
@@ -1,6 +1,12 @@
1
1
  // Generated by dts-bundle-generator v9.5.1
2
2
 
3
- /** Load a file into process.env without overwriting existing values. */
3
+ /**
4
+ * Load a file into process.env without overwriting existing values.
5
+ *
6
+ * Uses `node:fs` rather than `Bun.file` on purpose: `agent-core` is the public
7
+ * surface downstream tools consume, and those tools do not necessarily run on
8
+ * Bun. A Bun-only builtin here makes the whole export unusable for them.
9
+ */
4
10
  export declare function loadEnvFile(filePath: string): Promise<void>;
5
11
  export interface AppliedLimitMetadata {
6
12
  /** True only when the caller fetched and removed an additional row. */
@@ -23,10 +29,14 @@ export interface ConnectionSelectorInputs {
23
29
  export declare function resolveConnectionSelector(inputs: ConnectionSelectorInputs): string | undefined;
24
30
  /** Parse a comma-separated selector into ordered, unique names. */
25
31
  export declare function parseConnectionNames(selector: string): string[];
26
- interface EnvReference {
32
+ export interface EnvReference {
27
33
  $env: string;
28
34
  }
29
35
  /** Resolve a literal or environment reference with a field-specific error. */
30
36
  export declare function resolveEnvRef(value: string | EnvReference, fieldName: string, env?: Record<string, string | undefined>): string;
37
+ /** Configuration error shared by agent-facing command-line tools. */
38
+ export declare class ConfigError extends Error {
39
+ constructor(message: string);
40
+ }
31
41
 
32
42
  export {};
@@ -1,4 +1,7 @@
1
1
  // @bun
2
+ // src/agent-core/env-loader.ts
3
+ import { readFile } from "fs/promises";
4
+
2
5
  // src/agent-core/errors.ts
3
6
  class ConfigError extends Error {
4
7
  constructor(message) {
@@ -30,10 +33,17 @@ function parseEnvContent(content) {
30
33
  return entries;
31
34
  }
32
35
  async function loadEnvFile(filePath) {
33
- const file = Bun.file(filePath);
34
- if (!await file.exists())
35
- throw new ConfigError(`\u627E\u4E0D\u5230 env \u6A94\u6848\uFF1A${filePath}`);
36
- for (const [key, value] of parseEnvContent(await file.text())) {
36
+ let content;
37
+ try {
38
+ content = await readFile(filePath, "utf8");
39
+ } catch (cause) {
40
+ const code = cause.code;
41
+ if (code === "ENOENT" || code === "EISDIR") {
42
+ throw new ConfigError(`\u627E\u4E0D\u5230 env \u6A94\u6848\uFF1A${filePath}`);
43
+ }
44
+ throw cause;
45
+ }
46
+ for (const [key, value] of parseEnvContent(content)) {
37
47
  if (process.env[key] === undefined)
38
48
  process.env[key] = value;
39
49
  }
@@ -88,5 +98,6 @@ export {
88
98
  resolveEnvRef,
89
99
  resolveConnectionSelector,
90
100
  parseConnectionNames,
91
- loadEnvFile
101
+ loadEnvFile,
102
+ ConfigError
92
103
  };
package/dist/cli.mjs CHANGED
@@ -52,7 +52,7 @@ var package_default;
52
52
  var init_package = __esm(() => {
53
53
  package_default = {
54
54
  name: "@carllee1983/dbcli",
55
- version: "1.43.0",
55
+ version: "1.44.1",
56
56
  description: "Database CLI for AI agents",
57
57
  type: "module",
58
58
  publishConfig: {
@@ -7284,6 +7284,7 @@ var init_errors3 = __esm(() => {
7284
7284
  });
7285
7285
 
7286
7286
  // src/agent-core/env-loader.ts
7287
+ import { readFile } from "fs/promises";
7287
7288
  function parseEnvContent(content) {
7288
7289
  const entries = [];
7289
7290
  for (const line of content.split(`
@@ -7304,10 +7305,17 @@ function parseEnvContent(content) {
7304
7305
  return entries;
7305
7306
  }
7306
7307
  async function loadEnvFile(filePath) {
7307
- const file = Bun.file(filePath);
7308
- if (!await file.exists())
7309
- throw new ConfigError(`\u627E\u4E0D\u5230 env \u6A94\u6848\uFF1A${filePath}`);
7310
- for (const [key, value] of parseEnvContent(await file.text())) {
7308
+ let content;
7309
+ try {
7310
+ content = await readFile(filePath, "utf8");
7311
+ } catch (cause) {
7312
+ const code = cause.code;
7313
+ if (code === "ENOENT" || code === "EISDIR") {
7314
+ throw new ConfigError(`\u627E\u4E0D\u5230 env \u6A94\u6848\uFF1A${filePath}`);
7315
+ }
7316
+ throw cause;
7317
+ }
7318
+ for (const [key, value] of parseEnvContent(content)) {
7311
7319
  if (process.env[key] === undefined)
7312
7320
  process.env[key] = value;
7313
7321
  }
@@ -7517,6 +7525,7 @@ var init_env_ref = __esm(() => {
7517
7525
  var init_public = __esm(() => {
7518
7526
  init_env_loader();
7519
7527
  init_env_ref();
7528
+ init_errors2();
7520
7529
  });
7521
7530
 
7522
7531
  // node_modules/lru-cache/dist/esm/node/index.min.js
@@ -18703,7 +18712,7 @@ var init_assert_artifact = __esm(() => {
18703
18712
  });
18704
18713
 
18705
18714
  // src/core/verification/reader.ts
18706
- import { lstat, readdir as readdir2, readFile } from "fs/promises";
18715
+ import { lstat, readdir as readdir2, readFile as readFile2 } from "fs/promises";
18707
18716
  import { join as join15, isAbsolute, resolve as resolve3, sep as sep2 } from "path";
18708
18717
  function isArtifactFilename(name2) {
18709
18718
  return /^verification-.*\.json$/.test(name2);
@@ -18807,7 +18816,7 @@ async function readVerificationArtifacts(storageRoot) {
18807
18816
  if (!stats.isFile()) {
18808
18817
  throw new Error("artifact path is not a regular file");
18809
18818
  }
18810
- const raw = await readFile(path4, "utf8");
18819
+ const raw = await readFile2(path4, "utf8");
18811
18820
  const parsed = JSON.parse(raw);
18812
18821
  const artifact = validateVerificationArtifact(parsed);
18813
18822
  artifacts.push({ path: path4, filename, artifact });
@@ -19393,7 +19402,7 @@ var init_rotation = __esm(() => {
19393
19402
  });
19394
19403
 
19395
19404
  // src/core/audit/logger.ts
19396
- import { appendFile, mkdir as mkdir7, readFile as readFile2, stat } from "fs/promises";
19405
+ import { appendFile, mkdir as mkdir7, readFile as readFile3, stat } from "fs/promises";
19397
19406
  import { join as join16 } from "path";
19398
19407
  import { randomUUID } from "crypto";
19399
19408
 
@@ -19521,7 +19530,7 @@ class AuditLogger {
19521
19530
  try {
19522
19531
  const s = await stat(this.auditFilePath);
19523
19532
  this.currentSizeBytes = s.size;
19524
- const raw = await readFile2(this.auditFilePath, "utf8");
19533
+ const raw = await readFile3(this.auditFilePath, "utf8");
19525
19534
  this.currentEntryCount = raw.split(`
19526
19535
  `).filter(Boolean).length;
19527
19536
  } catch {
@@ -19547,7 +19556,7 @@ var init_logger2 = __esm(() => {
19547
19556
  });
19548
19557
 
19549
19558
  // src/core/audit/session-id.ts
19550
- import { mkdir as mkdir8, readFile as readFile3, rename as rename3, stat as stat2, writeFile as writeFile2 } from "fs/promises";
19559
+ import { mkdir as mkdir8, readFile as readFile4, rename as rename3, stat as stat2, writeFile as writeFile2 } from "fs/promises";
19551
19560
  import { randomBytes as randomBytes2 } from "crypto";
19552
19561
  import { dirname as dirname4, join as join17 } from "path";
19553
19562
  function generateSessionId(pid, nowMs) {
@@ -19562,7 +19571,7 @@ async function readSessionIdFile(storagePath) {
19562
19571
  return null;
19563
19572
  }
19564
19573
  try {
19565
- const raw = await readFile3(target, "utf8");
19574
+ const raw = await readFile4(target, "utf8");
19566
19575
  const parsed = JSON.parse(raw);
19567
19576
  if (parsed && typeof parsed.sessionId === "string" && typeof parsed.pid === "number" && typeof parsed.createdAt === "string") {
19568
19577
  return {
@@ -21347,7 +21356,7 @@ var init_render_markdown = __esm(() => {
21347
21356
  });
21348
21357
 
21349
21358
  // src/core/recovery/last-envelope.ts
21350
- import { writeFile as writeFile3, readFile as readFile4, rename as rename4, mkdir as mkdir9, stat as stat3 } from "fs/promises";
21359
+ import { writeFile as writeFile3, readFile as readFile5, rename as rename4, mkdir as mkdir9, stat as stat3 } from "fs/promises";
21351
21360
  import { dirname as dirname5, join as join18 } from "path";
21352
21361
  import { randomUUID as randomUUID2 } from "crypto";
21353
21362
  function sanitizeCommandSummary(argv) {
@@ -21379,7 +21388,7 @@ async function readLastEnvelope(cwd) {
21379
21388
  return null;
21380
21389
  }
21381
21390
  try {
21382
- const raw = await readFile4(target, "utf8");
21391
+ const raw = await readFile5(target, "utf8");
21383
21392
  return JSON.parse(raw);
21384
21393
  } catch {
21385
21394
  return null;
@@ -21394,7 +21403,7 @@ async function readLastEnvelopeRaw(cwd) {
21394
21403
  }
21395
21404
  let raw;
21396
21405
  try {
21397
- raw = await readFile4(target, "utf8");
21406
+ raw = await readFile5(target, "utf8");
21398
21407
  } catch {
21399
21408
  return null;
21400
21409
  }
@@ -81720,11 +81729,11 @@ var init_suggest_commands = __esm(() => {
81720
81729
  });
81721
81730
 
81722
81731
  // src/core/audit/reader.ts
81723
- import { readFile as readFile5, readdir as readdir4 } from "fs/promises";
81732
+ import { readFile as readFile6, readdir as readdir4 } from "fs/promises";
81724
81733
  async function readSingle(path4) {
81725
81734
  let raw;
81726
81735
  try {
81727
- raw = await readFile5(path4, "utf8");
81736
+ raw = await readFile6(path4, "utf8");
81728
81737
  } catch (err) {
81729
81738
  if (err.code === "ENOENT")
81730
81739
  return [];
@@ -83948,7 +83957,7 @@ var init_guide_missing_index = __esm(() => {
83948
83957
  });
83949
83958
 
83950
83959
  // src/core/explain/bulk-runner.ts
83951
- import { readFile as readFile6 } from "fs/promises";
83960
+ import { readFile as readFile7 } from "fs/promises";
83952
83961
  import path4 from "path";
83953
83962
  import { existsSync } from "fs";
83954
83963
  async function resolveBulkInputs(inputs, deps) {
@@ -83991,7 +84000,7 @@ async function resolveBulkInputs(inputs, deps) {
83991
84000
  if (!existsSync(ref)) {
83992
84001
  throw new Error(`No such file or saved query: '${ref}'`);
83993
84002
  }
83994
- appendFileInputs(out, ref, await readFile6(ref, "utf-8"));
84003
+ appendFileInputs(out, ref, await readFile7(ref, "utf-8"));
83995
84004
  }
83996
84005
  return out;
83997
84006
  }
@@ -92872,7 +92881,7 @@ var init_sql_metadata = __esm(() => {
92872
92881
  });
92873
92882
 
92874
92883
  // src/proxy/events.ts
92875
- import { appendFile as appendFile2, mkdir as mkdir15, readFile as readFile7, stat as stat8 } from "fs/promises";
92884
+ import { appendFile as appendFile2, mkdir as mkdir15, readFile as readFile8, stat as stat8 } from "fs/promises";
92876
92885
  import { dirname as dirname11 } from "path";
92877
92886
  function hasSql(e) {
92878
92887
  return e.type === "query_observed" || e.type === "query_completed" || e.type === "query_errored";
@@ -92936,7 +92945,7 @@ class EventWriter {
92936
92945
  try {
92937
92946
  const s = await stat8(this.path);
92938
92947
  this.currentSizeBytes = s.size;
92939
- const raw = await readFile7(this.path, "utf8");
92948
+ const raw = await readFile8(this.path, "utf8");
92940
92949
  this.currentEntryCount = raw.split(`
92941
92950
  `).filter(Boolean).length;
92942
92951
  } catch {
@@ -93533,7 +93542,7 @@ var init_server = __esm(() => {
93533
93542
  });
93534
93543
 
93535
93544
  // src/proxy/event-reader.ts
93536
- import { readFile as readFile8 } from "fs/promises";
93545
+ import { readFile as readFile9 } from "fs/promises";
93537
93546
  async function readEvents(path5, opts) {
93538
93547
  const candidates = opts.includeRotated ? [path5, `${path5}.1`] : [path5];
93539
93548
  const files = [];
@@ -93542,7 +93551,7 @@ async function readEvents(path5, opts) {
93542
93551
  for (const file of candidates) {
93543
93552
  let raw;
93544
93553
  try {
93545
- raw = await readFile8(file, "utf8");
93554
+ raw = await readFile9(file, "utf8");
93546
93555
  } catch (err) {
93547
93556
  if (err.code !== "ENOENT")
93548
93557
  throw err;
package/dist/core.mjs CHANGED
@@ -21714,6 +21714,7 @@ class ConfigError extends Error {
21714
21714
  }
21715
21715
  }
21716
21716
  // src/agent-core/env-loader.ts
21717
+ import { readFile as readFile3 } from "fs/promises";
21717
21718
  function parseEnvContent(content) {
21718
21719
  const entries = [];
21719
21720
  for (const line of content.split(`
@@ -21734,10 +21735,17 @@ function parseEnvContent(content) {
21734
21735
  return entries;
21735
21736
  }
21736
21737
  async function loadEnvFile(filePath) {
21737
- const file = Bun.file(filePath);
21738
- if (!await file.exists())
21739
- throw new ConfigError(`\u627E\u4E0D\u5230 env \u6A94\u6848\uFF1A${filePath}`);
21740
- for (const [key, value] of parseEnvContent(await file.text())) {
21738
+ let content;
21739
+ try {
21740
+ content = await readFile3(filePath, "utf8");
21741
+ } catch (cause) {
21742
+ const code = cause.code;
21743
+ if (code === "ENOENT" || code === "EISDIR") {
21744
+ throw new ConfigError(`\u627E\u4E0D\u5230 env \u6A94\u6848\uFF1A${filePath}`);
21745
+ }
21746
+ throw cause;
21747
+ }
21748
+ for (const [key, value] of parseEnvContent(content)) {
21741
21749
  if (process.env[key] === undefined)
21742
21750
  process.env[key] = value;
21743
21751
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dbcli-agent",
3
- "version": "1.43.0",
3
+ "version": "1.44.1",
4
4
  "description": "Database CLI skill and command reference for AI agents.",
5
5
  "contextFileName": "AGENTS.md"
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@carllee1983/dbcli",
3
- "version": "1.43.0",
3
+ "version": "1.44.1",
4
4
  "description": "Database CLI for AI agents",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dbcli-agent",
3
- "version": "1.43.0",
3
+ "version": "1.44.1",
4
4
  "description": "Database CLI skill and command reference for AI agents",
5
5
  "author": {
6
6
  "name": "Carl Lee",