@hasna/recordings 0.1.34 → 0.1.36
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/README.md +17 -0
- package/dist/cli/index.js +328 -95
- package/dist/db/storage-config.d.ts +2 -1
- package/dist/db/storage-config.d.ts.map +1 -1
- package/dist/db/storage-sync.d.ts.map +1 -1
- package/dist/index.js +79 -57
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/mcp/index.js +85 -61
- package/dist/storage.js +79 -57
- package/dist/version.d.ts +1 -1
- package/package.json +5 -3
- package/scripts/install_macos_app.sh +2 -2
- package/scripts/release-guard.ts +129 -0
- package/src/native/Recordings/RecordingsTests/CLIRunnerTests.swift +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export type StorageMode = "local" | "hybrid" | "remote";
|
|
2
2
|
export interface StorageConfig {
|
|
3
3
|
mode: StorageMode;
|
|
4
|
-
|
|
4
|
+
postgres: {
|
|
5
5
|
host: string;
|
|
6
6
|
port: number;
|
|
7
7
|
username: string;
|
|
@@ -16,6 +16,7 @@ export declare const RECORDINGS_STORAGE_ENV = "HASNA_RECORDINGS_DATABASE_URL";
|
|
|
16
16
|
export declare const RECORDINGS_STORAGE_FALLBACK_ENV = "RECORDINGS_DATABASE_URL";
|
|
17
17
|
export declare const RECORDINGS_STORAGE_MODE_ENV = "HASNA_RECORDINGS_STORAGE_MODE";
|
|
18
18
|
export declare const RECORDINGS_STORAGE_MODE_FALLBACK_ENV = "RECORDINGS_STORAGE_MODE";
|
|
19
|
+
export declare const RECORDINGS_STORAGE_CONFIG_ENV = "HASNA_RECORDINGS_STORAGE_CONFIG";
|
|
19
20
|
export declare const STORAGE_DATABASE_ENV: readonly ["HASNA_RECORDINGS_DATABASE_URL", "RECORDINGS_DATABASE_URL"];
|
|
20
21
|
export declare const STORAGE_MODE_ENV: readonly ["HASNA_RECORDINGS_STORAGE_MODE", "RECORDINGS_STORAGE_MODE"];
|
|
21
22
|
export declare function getStorageDatabaseEnvName(): (typeof STORAGE_DATABASE_ENV)[number] | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage-config.d.ts","sourceRoot":"","sources":["../../src/db/storage-config.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAExD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,WAAW,CAAC;IAClB,
|
|
1
|
+
{"version":3,"file":"storage-config.d.ts","sourceRoot":"","sources":["../../src/db/storage-config.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAExD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;QACrB,GAAG,EAAE,OAAO,CAAC;KACd,CAAC;CACH;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;CACd;AAGD,eAAO,MAAM,sBAAsB,kCAAkC,CAAC;AACtE,eAAO,MAAM,+BAA+B,4BAA4B,CAAC;AACzE,eAAO,MAAM,2BAA2B,kCAAkC,CAAC;AAC3E,eAAO,MAAM,oCAAoC,4BAA4B,CAAC;AAC9E,eAAO,MAAM,6BAA6B,oCAAoC,CAAC;AAC/E,eAAO,MAAM,oBAAoB,uEAAqE,CAAC;AACvG,eAAO,MAAM,gBAAgB,uEAA+E,CAAC;AAa7G,wBAAgB,yBAAyB,IAAI,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,CAKxF;AAED,wBAAgB,qBAAqB,IAAI,UAAU,GAAG,IAAI,CAGzD;AAED,wBAAgB,qBAAqB,IAAI,MAAM,GAAG,SAAS,CAG1D;AAQD,wBAAgB,gBAAgB,IAAI,aAAa,CAoChD;AAED,wBAAgB,0BAA0B,CAAC,MAAM,SAAe,GAAG,MAAM,CAiBxE;AAED,eAAO,MAAM,mBAAmB,mCAA6B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage-sync.d.ts","sourceRoot":"","sources":["../../src/db/storage-sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,EACL,oBAAoB,EAIpB,KAAK,WAAW,EACjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAKrD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,OAAO,oBAAoB,CAAC;IACjC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChD;AAED,eAAO,MAAM,cAAc,6EAMjB,CAAC;AAEX,eAAO,MAAM,yBAAyB,6EAAiB,CAAC;AA6ExD,wBAAsB,YAAY,IAAI,OAAO,CAAC,cAAc,CAAC,CAE5D;AAED,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAIhF;AAED,wBAAgB,gBAAgB,CAAC,EAAE,GAAE,QAAwB,GAAG,aAAa,
|
|
1
|
+
{"version":3,"file":"storage-sync.d.ts","sourceRoot":"","sources":["../../src/db/storage-sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,EACL,oBAAoB,EAIpB,KAAK,WAAW,EACjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAKrD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,OAAO,oBAAoB,CAAC;IACjC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChD;AAED,eAAO,MAAM,cAAc,6EAMjB,CAAC;AAEX,eAAO,MAAM,yBAAyB,6EAAiB,CAAC;AA6ExD,wBAAsB,YAAY,IAAI,OAAO,CAAC,cAAc,CAAC,CAE5D;AAED,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAIhF;AAED,wBAAgB,gBAAgB,CAAC,EAAE,GAAE,QAAwB,GAAG,aAAa,CAqB5E;AAED,wBAAsB,kBAAkB,CAAC,MAAM,GAAE,MAAM,EAAwB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAuBtG;AAED,wBAAsB,kBAAkB,CAAC,MAAM,GAAE,MAAM,EAAwB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAuBtG;AAED,wBAAsB,kBAAkB,CAAC,MAAM,GAAE,MAAM,EAAwB,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,UAAU,EAAE,CAAC;IAAC,IAAI,EAAE,UAAU,EAAE,CAAA;CAAE,CAAC,CAKpI;AAED,wBAAgB,kBAAkB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAQzD"}
|
package/dist/index.js
CHANGED
|
@@ -2940,7 +2940,7 @@ var require_dist = __commonJS((exports) => {
|
|
|
2940
2940
|
function parse(stream, callback) {
|
|
2941
2941
|
const parser = new parser_1.Parser;
|
|
2942
2942
|
stream.on("data", (buffer) => parser.parse(buffer, callback));
|
|
2943
|
-
return new Promise((
|
|
2943
|
+
return new Promise((resolve2) => stream.on("end", () => resolve2()));
|
|
2944
2944
|
}
|
|
2945
2945
|
exports.parse = parse;
|
|
2946
2946
|
});
|
|
@@ -3619,12 +3619,12 @@ var require_client = __commonJS((exports, module) => {
|
|
|
3619
3619
|
this._connect(callback);
|
|
3620
3620
|
return;
|
|
3621
3621
|
}
|
|
3622
|
-
return new this._Promise((
|
|
3622
|
+
return new this._Promise((resolve2, reject) => {
|
|
3623
3623
|
this._connect((error) => {
|
|
3624
3624
|
if (error) {
|
|
3625
3625
|
reject(error);
|
|
3626
3626
|
} else {
|
|
3627
|
-
|
|
3627
|
+
resolve2(this);
|
|
3628
3628
|
}
|
|
3629
3629
|
});
|
|
3630
3630
|
});
|
|
@@ -3956,8 +3956,8 @@ var require_client = __commonJS((exports, module) => {
|
|
|
3956
3956
|
readTimeout = config.query_timeout || this.connectionParameters.query_timeout;
|
|
3957
3957
|
query = new Query(config, values, callback);
|
|
3958
3958
|
if (!query.callback) {
|
|
3959
|
-
result = new this._Promise((
|
|
3960
|
-
query.callback = (err, res) => err ? reject(err) :
|
|
3959
|
+
result = new this._Promise((resolve2, reject) => {
|
|
3960
|
+
query.callback = (err, res) => err ? reject(err) : resolve2(res);
|
|
3961
3961
|
}).catch((err) => {
|
|
3962
3962
|
Error.captureStackTrace(err);
|
|
3963
3963
|
throw err;
|
|
@@ -4032,8 +4032,8 @@ var require_client = __commonJS((exports, module) => {
|
|
|
4032
4032
|
if (cb) {
|
|
4033
4033
|
this.connection.once("end", cb);
|
|
4034
4034
|
} else {
|
|
4035
|
-
return new this._Promise((
|
|
4036
|
-
this.connection.once("end",
|
|
4035
|
+
return new this._Promise((resolve2) => {
|
|
4036
|
+
this.connection.once("end", resolve2);
|
|
4037
4037
|
});
|
|
4038
4038
|
}
|
|
4039
4039
|
}
|
|
@@ -4080,8 +4080,8 @@ var require_pg_pool = __commonJS((exports, module) => {
|
|
|
4080
4080
|
const cb = function(err, client) {
|
|
4081
4081
|
err ? rej(err) : res(client);
|
|
4082
4082
|
};
|
|
4083
|
-
const result = new Promise2(function(
|
|
4084
|
-
res =
|
|
4083
|
+
const result = new Promise2(function(resolve2, reject) {
|
|
4084
|
+
res = resolve2;
|
|
4085
4085
|
rej = reject;
|
|
4086
4086
|
}).catch((err) => {
|
|
4087
4087
|
Error.captureStackTrace(err);
|
|
@@ -4142,7 +4142,7 @@ var require_pg_pool = __commonJS((exports, module) => {
|
|
|
4142
4142
|
if (typeof Promise2.try === "function") {
|
|
4143
4143
|
return Promise2.try(f);
|
|
4144
4144
|
}
|
|
4145
|
-
return new Promise2((
|
|
4145
|
+
return new Promise2((resolve2) => resolve2(f()));
|
|
4146
4146
|
}
|
|
4147
4147
|
_isFull() {
|
|
4148
4148
|
return this._clients.length >= this.options.max;
|
|
@@ -4518,8 +4518,8 @@ var require_query2 = __commonJS((exports, module) => {
|
|
|
4518
4518
|
NativeQuery.prototype._getPromise = function() {
|
|
4519
4519
|
if (this._promise)
|
|
4520
4520
|
return this._promise;
|
|
4521
|
-
this._promise = new Promise(function(
|
|
4522
|
-
this._once("end",
|
|
4521
|
+
this._promise = new Promise(function(resolve2, reject) {
|
|
4522
|
+
this._once("end", resolve2);
|
|
4523
4523
|
this._once("error", reject);
|
|
4524
4524
|
}.bind(this));
|
|
4525
4525
|
return this._promise;
|
|
@@ -4693,12 +4693,12 @@ var require_client2 = __commonJS((exports, module) => {
|
|
|
4693
4693
|
this._connect(callback);
|
|
4694
4694
|
return;
|
|
4695
4695
|
}
|
|
4696
|
-
return new this._Promise((
|
|
4696
|
+
return new this._Promise((resolve2, reject) => {
|
|
4697
4697
|
this._connect((error) => {
|
|
4698
4698
|
if (error) {
|
|
4699
4699
|
reject(error);
|
|
4700
4700
|
} else {
|
|
4701
|
-
|
|
4701
|
+
resolve2(this);
|
|
4702
4702
|
}
|
|
4703
4703
|
});
|
|
4704
4704
|
});
|
|
@@ -4722,8 +4722,8 @@ var require_client2 = __commonJS((exports, module) => {
|
|
|
4722
4722
|
query = new NativeQuery(config, values, callback);
|
|
4723
4723
|
if (!query.callback) {
|
|
4724
4724
|
let resolveOut, rejectOut;
|
|
4725
|
-
result = new this._Promise((
|
|
4726
|
-
resolveOut =
|
|
4725
|
+
result = new this._Promise((resolve2, reject) => {
|
|
4726
|
+
resolveOut = resolve2;
|
|
4727
4727
|
rejectOut = reject;
|
|
4728
4728
|
}).catch((err) => {
|
|
4729
4729
|
Error.captureStackTrace(err);
|
|
@@ -4781,8 +4781,8 @@ var require_client2 = __commonJS((exports, module) => {
|
|
|
4781
4781
|
}
|
|
4782
4782
|
let result;
|
|
4783
4783
|
if (!cb) {
|
|
4784
|
-
result = new this._Promise(function(
|
|
4785
|
-
cb = (err) => err ? reject(err) :
|
|
4784
|
+
result = new this._Promise(function(resolve2, reject) {
|
|
4785
|
+
cb = (err) => err ? reject(err) : resolve2();
|
|
4786
4786
|
});
|
|
4787
4787
|
}
|
|
4788
4788
|
this.native.end(function() {
|
|
@@ -4963,11 +4963,11 @@ class SqliteAdapter {
|
|
|
4963
4963
|
|
|
4964
4964
|
// src/db/database.ts
|
|
4965
4965
|
import { mkdirSync as mkdirSync2 } from "fs";
|
|
4966
|
-
import { dirname } from "path";
|
|
4966
|
+
import { dirname as dirname2 } from "path";
|
|
4967
4967
|
|
|
4968
4968
|
// src/lib/config.ts
|
|
4969
|
-
import { existsSync, readFileSync, mkdirSync,
|
|
4970
|
-
import { join } from "path";
|
|
4969
|
+
import { copyFileSync, existsSync, readFileSync, mkdirSync, readdirSync, statSync } from "fs";
|
|
4970
|
+
import { dirname, join, resolve } from "path";
|
|
4971
4971
|
import { homedir } from "os";
|
|
4972
4972
|
var DEFAULT_CONFIG = {
|
|
4973
4973
|
openai_api_key: "",
|
|
@@ -5061,44 +5061,53 @@ function expandEnvBackedConfig(config) {
|
|
|
5061
5061
|
return expanded;
|
|
5062
5062
|
}
|
|
5063
5063
|
function findConfigFile() {
|
|
5064
|
-
|
|
5065
|
-
const root = "/";
|
|
5066
|
-
while (dir !== root) {
|
|
5067
|
-
const candidate = join(dir, ".recordings", "config.json");
|
|
5068
|
-
if (existsSync(candidate))
|
|
5069
|
-
return candidate;
|
|
5070
|
-
const parent = join(dir, "..");
|
|
5071
|
-
if (parent === dir)
|
|
5072
|
-
break;
|
|
5073
|
-
dir = parent;
|
|
5074
|
-
}
|
|
5075
|
-
return null;
|
|
5064
|
+
return findProjectRecordingsPath("config.json");
|
|
5076
5065
|
}
|
|
5077
5066
|
function getDataDir() {
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
if (existsSync(candidate))
|
|
5083
|
-
return candidate;
|
|
5084
|
-
const parent = join(dir, "..");
|
|
5085
|
-
if (parent === dir)
|
|
5086
|
-
break;
|
|
5087
|
-
dir = parent;
|
|
5088
|
-
}
|
|
5089
|
-
const home = homedir();
|
|
5067
|
+
const projectLocalDir = findProjectRecordingsPath();
|
|
5068
|
+
if (projectLocalDir)
|
|
5069
|
+
return projectLocalDir;
|
|
5070
|
+
const home = getHomeDir();
|
|
5090
5071
|
const newDir = join(home, ".hasna", "recordings");
|
|
5091
5072
|
const oldDir = join(home, ".recordings");
|
|
5092
|
-
if (
|
|
5073
|
+
if (existsSync(oldDir)) {
|
|
5093
5074
|
try {
|
|
5094
|
-
|
|
5095
|
-
cpSync(oldDir, newDir, { recursive: true });
|
|
5075
|
+
mergeDirectoryContents(oldDir, newDir);
|
|
5096
5076
|
} catch {}
|
|
5097
5077
|
}
|
|
5098
5078
|
return newDir;
|
|
5099
5079
|
}
|
|
5080
|
+
function findProjectRecordingsPath(entry) {
|
|
5081
|
+
const home = resolve(getHomeDir());
|
|
5082
|
+
let dir = resolve(process.cwd());
|
|
5083
|
+
while (true) {
|
|
5084
|
+
if (dir !== home) {
|
|
5085
|
+
const candidate = entry ? join(dir, ".recordings", entry) : join(dir, ".recordings");
|
|
5086
|
+
if (existsSync(candidate))
|
|
5087
|
+
return candidate;
|
|
5088
|
+
}
|
|
5089
|
+
const parent = dirname(dir);
|
|
5090
|
+
if (parent === dir)
|
|
5091
|
+
break;
|
|
5092
|
+
dir = parent;
|
|
5093
|
+
}
|
|
5094
|
+
return null;
|
|
5095
|
+
}
|
|
5096
|
+
function mergeDirectoryContents(sourceDir, targetDir) {
|
|
5097
|
+
mkdirSync(targetDir, { recursive: true });
|
|
5098
|
+
for (const entry of readdirSync(sourceDir)) {
|
|
5099
|
+
const sourcePath = join(sourceDir, entry);
|
|
5100
|
+
const targetPath = join(targetDir, entry);
|
|
5101
|
+
const sourceStats = statSync(sourcePath);
|
|
5102
|
+
if (sourceStats.isDirectory()) {
|
|
5103
|
+
mergeDirectoryContents(sourcePath, targetPath);
|
|
5104
|
+
} else if (!existsSync(targetPath)) {
|
|
5105
|
+
copyFileSync(sourcePath, targetPath);
|
|
5106
|
+
}
|
|
5107
|
+
}
|
|
5108
|
+
}
|
|
5100
5109
|
function loadSecretKey(keyName) {
|
|
5101
|
-
const secretsPath = join(
|
|
5110
|
+
const secretsPath = join(getHomeDir(), ".secrets");
|
|
5102
5111
|
if (!existsSync(secretsPath))
|
|
5103
5112
|
return "";
|
|
5104
5113
|
for (const candidate of listSecretFiles(secretsPath)) {
|
|
@@ -5139,6 +5148,9 @@ function listSecretFiles(path) {
|
|
|
5139
5148
|
return [];
|
|
5140
5149
|
}
|
|
5141
5150
|
}
|
|
5151
|
+
function getHomeDir() {
|
|
5152
|
+
return process.env["HOME"] || process.env["USERPROFILE"] || homedir();
|
|
5153
|
+
}
|
|
5142
5154
|
function ensureDataDir(config) {
|
|
5143
5155
|
const { mkdirSync: mkdirSync2 } = __require("fs");
|
|
5144
5156
|
mkdirSync2(config.audio_dir, { recursive: true });
|
|
@@ -5233,7 +5245,7 @@ function getDatabase(dbPath) {
|
|
|
5233
5245
|
if (_db)
|
|
5234
5246
|
return _db;
|
|
5235
5247
|
const path = dbPath || loadConfig().db_path;
|
|
5236
|
-
const dir =
|
|
5248
|
+
const dir = dirname2(path);
|
|
5237
5249
|
mkdirSync2(dir, { recursive: true });
|
|
5238
5250
|
_adapter = new SqliteAdapter(path);
|
|
5239
5251
|
_db = _adapter.raw;
|
|
@@ -5359,11 +5371,12 @@ class PgAdapterAsync {
|
|
|
5359
5371
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
5360
5372
|
import { homedir as homedir2 } from "os";
|
|
5361
5373
|
import { join as join2 } from "path";
|
|
5362
|
-
var
|
|
5374
|
+
var LEGACY_DATABASE_CONFIG_KEY = ["r", "d", "s"].join("");
|
|
5363
5375
|
var RECORDINGS_STORAGE_ENV = "HASNA_RECORDINGS_DATABASE_URL";
|
|
5364
5376
|
var RECORDINGS_STORAGE_FALLBACK_ENV = "RECORDINGS_DATABASE_URL";
|
|
5365
5377
|
var RECORDINGS_STORAGE_MODE_ENV = "HASNA_RECORDINGS_STORAGE_MODE";
|
|
5366
5378
|
var RECORDINGS_STORAGE_MODE_FALLBACK_ENV = "RECORDINGS_STORAGE_MODE";
|
|
5379
|
+
var RECORDINGS_STORAGE_CONFIG_ENV = "HASNA_RECORDINGS_STORAGE_CONFIG";
|
|
5367
5380
|
var STORAGE_DATABASE_ENV = [RECORDINGS_STORAGE_ENV, RECORDINGS_STORAGE_FALLBACK_ENV];
|
|
5368
5381
|
var STORAGE_MODE_ENV = [RECORDINGS_STORAGE_MODE_ENV, RECORDINGS_STORAGE_MODE_FALLBACK_ENV];
|
|
5369
5382
|
function readEnv(name) {
|
|
@@ -5391,10 +5404,16 @@ function getStorageDatabaseUrl() {
|
|
|
5391
5404
|
const env = getStorageDatabaseEnv();
|
|
5392
5405
|
return env ? readEnv(env.name) : undefined;
|
|
5393
5406
|
}
|
|
5407
|
+
function getStorageConfigPath() {
|
|
5408
|
+
const override = readEnv(RECORDINGS_STORAGE_CONFIG_ENV);
|
|
5409
|
+
if (override)
|
|
5410
|
+
return override;
|
|
5411
|
+
return join2(homedir2(), ".hasna", "recordings", "storage", "config.json");
|
|
5412
|
+
}
|
|
5394
5413
|
function getStorageConfig() {
|
|
5395
5414
|
const config = {
|
|
5396
5415
|
mode: "local",
|
|
5397
|
-
|
|
5416
|
+
postgres: {
|
|
5398
5417
|
host: "",
|
|
5399
5418
|
port: 5432,
|
|
5400
5419
|
username: "",
|
|
@@ -5402,11 +5421,13 @@ function getStorageConfig() {
|
|
|
5402
5421
|
ssl: true
|
|
5403
5422
|
}
|
|
5404
5423
|
};
|
|
5405
|
-
|
|
5424
|
+
const storageConfigPath = getStorageConfigPath();
|
|
5425
|
+
if (existsSync2(storageConfigPath)) {
|
|
5406
5426
|
try {
|
|
5407
|
-
const raw = JSON.parse(readFileSync2(
|
|
5427
|
+
const raw = JSON.parse(readFileSync2(storageConfigPath, "utf-8"));
|
|
5428
|
+
const legacyDatabaseConfig = typeof raw[LEGACY_DATABASE_CONFIG_KEY] === "object" && raw[LEGACY_DATABASE_CONFIG_KEY] !== null ? raw[LEGACY_DATABASE_CONFIG_KEY] : {};
|
|
5408
5429
|
config.mode = normalizeMode(raw.mode) ?? config.mode;
|
|
5409
|
-
config.
|
|
5430
|
+
config.postgres = { ...config.postgres, ...legacyDatabaseConfig, ...raw.postgres ?? {} };
|
|
5410
5431
|
} catch {}
|
|
5411
5432
|
}
|
|
5412
5433
|
const modeOverride = readEnv(RECORDINGS_STORAGE_MODE_ENV) ?? readEnv(RECORDINGS_STORAGE_MODE_FALLBACK_ENV);
|
|
@@ -5423,7 +5444,7 @@ function getStorageConnectionString(dbName = "recordings") {
|
|
|
5423
5444
|
if (direct)
|
|
5424
5445
|
return direct;
|
|
5425
5446
|
const config = getStorageConfig();
|
|
5426
|
-
const { host, port, username, password_env, ssl } = config.
|
|
5447
|
+
const { host, port, username, password_env, ssl } = config.postgres;
|
|
5427
5448
|
if (!host || !username) {
|
|
5428
5449
|
throw new Error("Storage database is not configured. Set HASNA_RECORDINGS_DATABASE_URL or configure ~/.hasna/recordings/storage/config.json.");
|
|
5429
5450
|
}
|
|
@@ -5575,8 +5596,9 @@ async function runStorageMigrations(remote) {
|
|
|
5575
5596
|
function getStorageStatus(db = getDatabase()) {
|
|
5576
5597
|
const config = getStorageConfig();
|
|
5577
5598
|
const activeEnv = getStorageDatabaseEnv();
|
|
5599
|
+
const hasConfiguredPostgres = Boolean(config.postgres.host && config.postgres.username);
|
|
5578
5600
|
return {
|
|
5579
|
-
configured: Boolean(activeEnv),
|
|
5601
|
+
configured: Boolean(activeEnv) || hasConfiguredPostgres,
|
|
5580
5602
|
mode: config.mode,
|
|
5581
5603
|
enabled: config.mode === "hybrid" || config.mode === "remote",
|
|
5582
5604
|
env: STORAGE_DATABASE_ENV,
|
package/dist/lib/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,eAAO,MAAM,cAAc,EAAE,gBA2B5B,CAAC;AAEF,wBAAgB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAqEhE;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,eAAO,MAAM,cAAc,EAAE,gBA2B5B,CAAC;AAEF,wBAAgB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAqEhE;AAmBD,wBAAgB,UAAU,IAAI,MAAM,CAoBnC;AAwFD,wBAAgB,aAAa,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAU5D"}
|
package/dist/mcp/index.js
CHANGED
|
@@ -2954,7 +2954,7 @@ var require_dist = __commonJS((exports) => {
|
|
|
2954
2954
|
function parse(stream, callback) {
|
|
2955
2955
|
const parser = new parser_1.Parser;
|
|
2956
2956
|
stream.on("data", (buffer) => parser.parse(buffer, callback));
|
|
2957
|
-
return new Promise((
|
|
2957
|
+
return new Promise((resolve2) => stream.on("end", () => resolve2()));
|
|
2958
2958
|
}
|
|
2959
2959
|
exports.parse = parse;
|
|
2960
2960
|
});
|
|
@@ -3633,12 +3633,12 @@ var require_client = __commonJS((exports, module) => {
|
|
|
3633
3633
|
this._connect(callback);
|
|
3634
3634
|
return;
|
|
3635
3635
|
}
|
|
3636
|
-
return new this._Promise((
|
|
3636
|
+
return new this._Promise((resolve2, reject) => {
|
|
3637
3637
|
this._connect((error) => {
|
|
3638
3638
|
if (error) {
|
|
3639
3639
|
reject(error);
|
|
3640
3640
|
} else {
|
|
3641
|
-
|
|
3641
|
+
resolve2(this);
|
|
3642
3642
|
}
|
|
3643
3643
|
});
|
|
3644
3644
|
});
|
|
@@ -3970,8 +3970,8 @@ var require_client = __commonJS((exports, module) => {
|
|
|
3970
3970
|
readTimeout = config.query_timeout || this.connectionParameters.query_timeout;
|
|
3971
3971
|
query = new Query(config, values, callback);
|
|
3972
3972
|
if (!query.callback) {
|
|
3973
|
-
result = new this._Promise((
|
|
3974
|
-
query.callback = (err, res) => err ? reject(err) :
|
|
3973
|
+
result = new this._Promise((resolve2, reject) => {
|
|
3974
|
+
query.callback = (err, res) => err ? reject(err) : resolve2(res);
|
|
3975
3975
|
}).catch((err) => {
|
|
3976
3976
|
Error.captureStackTrace(err);
|
|
3977
3977
|
throw err;
|
|
@@ -4046,8 +4046,8 @@ var require_client = __commonJS((exports, module) => {
|
|
|
4046
4046
|
if (cb) {
|
|
4047
4047
|
this.connection.once("end", cb);
|
|
4048
4048
|
} else {
|
|
4049
|
-
return new this._Promise((
|
|
4050
|
-
this.connection.once("end",
|
|
4049
|
+
return new this._Promise((resolve2) => {
|
|
4050
|
+
this.connection.once("end", resolve2);
|
|
4051
4051
|
});
|
|
4052
4052
|
}
|
|
4053
4053
|
}
|
|
@@ -4094,8 +4094,8 @@ var require_pg_pool = __commonJS((exports, module) => {
|
|
|
4094
4094
|
const cb = function(err, client) {
|
|
4095
4095
|
err ? rej(err) : res(client);
|
|
4096
4096
|
};
|
|
4097
|
-
const result = new Promise2(function(
|
|
4098
|
-
res =
|
|
4097
|
+
const result = new Promise2(function(resolve2, reject) {
|
|
4098
|
+
res = resolve2;
|
|
4099
4099
|
rej = reject;
|
|
4100
4100
|
}).catch((err) => {
|
|
4101
4101
|
Error.captureStackTrace(err);
|
|
@@ -4156,7 +4156,7 @@ var require_pg_pool = __commonJS((exports, module) => {
|
|
|
4156
4156
|
if (typeof Promise2.try === "function") {
|
|
4157
4157
|
return Promise2.try(f);
|
|
4158
4158
|
}
|
|
4159
|
-
return new Promise2((
|
|
4159
|
+
return new Promise2((resolve2) => resolve2(f()));
|
|
4160
4160
|
}
|
|
4161
4161
|
_isFull() {
|
|
4162
4162
|
return this._clients.length >= this.options.max;
|
|
@@ -4532,8 +4532,8 @@ var require_query2 = __commonJS((exports, module) => {
|
|
|
4532
4532
|
NativeQuery.prototype._getPromise = function() {
|
|
4533
4533
|
if (this._promise)
|
|
4534
4534
|
return this._promise;
|
|
4535
|
-
this._promise = new Promise(function(
|
|
4536
|
-
this._once("end",
|
|
4535
|
+
this._promise = new Promise(function(resolve2, reject) {
|
|
4536
|
+
this._once("end", resolve2);
|
|
4537
4537
|
this._once("error", reject);
|
|
4538
4538
|
}.bind(this));
|
|
4539
4539
|
return this._promise;
|
|
@@ -4707,12 +4707,12 @@ var require_client2 = __commonJS((exports, module) => {
|
|
|
4707
4707
|
this._connect(callback);
|
|
4708
4708
|
return;
|
|
4709
4709
|
}
|
|
4710
|
-
return new this._Promise((
|
|
4710
|
+
return new this._Promise((resolve2, reject) => {
|
|
4711
4711
|
this._connect((error) => {
|
|
4712
4712
|
if (error) {
|
|
4713
4713
|
reject(error);
|
|
4714
4714
|
} else {
|
|
4715
|
-
|
|
4715
|
+
resolve2(this);
|
|
4716
4716
|
}
|
|
4717
4717
|
});
|
|
4718
4718
|
});
|
|
@@ -4736,8 +4736,8 @@ var require_client2 = __commonJS((exports, module) => {
|
|
|
4736
4736
|
query = new NativeQuery(config, values, callback);
|
|
4737
4737
|
if (!query.callback) {
|
|
4738
4738
|
let resolveOut, rejectOut;
|
|
4739
|
-
result = new this._Promise((
|
|
4740
|
-
resolveOut =
|
|
4739
|
+
result = new this._Promise((resolve2, reject) => {
|
|
4740
|
+
resolveOut = resolve2;
|
|
4741
4741
|
rejectOut = reject;
|
|
4742
4742
|
}).catch((err) => {
|
|
4743
4743
|
Error.captureStackTrace(err);
|
|
@@ -4795,8 +4795,8 @@ var require_client2 = __commonJS((exports, module) => {
|
|
|
4795
4795
|
}
|
|
4796
4796
|
let result;
|
|
4797
4797
|
if (!cb) {
|
|
4798
|
-
result = new this._Promise(function(
|
|
4799
|
-
cb = (err) => err ? reject(err) :
|
|
4798
|
+
result = new this._Promise(function(resolve2, reject) {
|
|
4799
|
+
cb = (err) => err ? reject(err) : resolve2();
|
|
4800
4800
|
});
|
|
4801
4801
|
}
|
|
4802
4802
|
this.native.end(function() {
|
|
@@ -4920,7 +4920,7 @@ var require_lib2 = __commonJS((exports, module) => {
|
|
|
4920
4920
|
var require_package = __commonJS((exports, module) => {
|
|
4921
4921
|
module.exports = {
|
|
4922
4922
|
name: "@hasna/recordings",
|
|
4923
|
-
version: "0.1.
|
|
4923
|
+
version: "0.1.36",
|
|
4924
4924
|
type: "module",
|
|
4925
4925
|
description: "Speech-to-text recording tool with MCP and CLI \u2014 records, transcribes, and optionally enhances text using AI",
|
|
4926
4926
|
repository: {
|
|
@@ -4954,7 +4954,9 @@ var require_package = __commonJS((exports, module) => {
|
|
|
4954
4954
|
"test:coverage": "bun test --coverage",
|
|
4955
4955
|
"dev:cli": "bun run src/cli/index.ts",
|
|
4956
4956
|
"dev:mcp": "bun run src/mcp/index.ts",
|
|
4957
|
-
|
|
4957
|
+
"verify:release": "bun run scripts/release-guard.ts",
|
|
4958
|
+
prepack: "bun run build && bun run verify:release",
|
|
4959
|
+
prepublishOnly: "bun run typecheck && bun run test",
|
|
4958
4960
|
postinstall: "bash scripts/install_macos_app.sh --postinstall"
|
|
4959
4961
|
},
|
|
4960
4962
|
files: [
|
|
@@ -4970,7 +4972,7 @@ var require_package = __commonJS((exports, module) => {
|
|
|
4970
4972
|
"LICENSE"
|
|
4971
4973
|
],
|
|
4972
4974
|
dependencies: {
|
|
4973
|
-
"@hasna/events": "^0.1.
|
|
4975
|
+
"@hasna/events": "^0.1.11",
|
|
4974
4976
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
4975
4977
|
chalk: "^5.4.1",
|
|
4976
4978
|
commander: "^13.1.0",
|
|
@@ -9015,8 +9017,8 @@ var coerce = {
|
|
|
9015
9017
|
};
|
|
9016
9018
|
var NEVER = INVALID;
|
|
9017
9019
|
// src/lib/config.ts
|
|
9018
|
-
import { existsSync, readFileSync, mkdirSync,
|
|
9019
|
-
import { join } from "path";
|
|
9020
|
+
import { copyFileSync, existsSync, readFileSync, mkdirSync, readdirSync, statSync } from "fs";
|
|
9021
|
+
import { dirname, join, resolve } from "path";
|
|
9020
9022
|
import { homedir } from "os";
|
|
9021
9023
|
var DEFAULT_CONFIG = {
|
|
9022
9024
|
openai_api_key: "",
|
|
@@ -9110,44 +9112,53 @@ function expandEnvBackedConfig(config) {
|
|
|
9110
9112
|
return expanded;
|
|
9111
9113
|
}
|
|
9112
9114
|
function findConfigFile() {
|
|
9113
|
-
|
|
9114
|
-
const root = "/";
|
|
9115
|
-
while (dir !== root) {
|
|
9116
|
-
const candidate = join(dir, ".recordings", "config.json");
|
|
9117
|
-
if (existsSync(candidate))
|
|
9118
|
-
return candidate;
|
|
9119
|
-
const parent = join(dir, "..");
|
|
9120
|
-
if (parent === dir)
|
|
9121
|
-
break;
|
|
9122
|
-
dir = parent;
|
|
9123
|
-
}
|
|
9124
|
-
return null;
|
|
9115
|
+
return findProjectRecordingsPath("config.json");
|
|
9125
9116
|
}
|
|
9126
9117
|
function getDataDir() {
|
|
9127
|
-
|
|
9128
|
-
|
|
9129
|
-
|
|
9130
|
-
|
|
9131
|
-
if (existsSync(candidate))
|
|
9132
|
-
return candidate;
|
|
9133
|
-
const parent = join(dir, "..");
|
|
9134
|
-
if (parent === dir)
|
|
9135
|
-
break;
|
|
9136
|
-
dir = parent;
|
|
9137
|
-
}
|
|
9138
|
-
const home = homedir();
|
|
9118
|
+
const projectLocalDir = findProjectRecordingsPath();
|
|
9119
|
+
if (projectLocalDir)
|
|
9120
|
+
return projectLocalDir;
|
|
9121
|
+
const home = getHomeDir();
|
|
9139
9122
|
const newDir = join(home, ".hasna", "recordings");
|
|
9140
9123
|
const oldDir = join(home, ".recordings");
|
|
9141
|
-
if (
|
|
9124
|
+
if (existsSync(oldDir)) {
|
|
9142
9125
|
try {
|
|
9143
|
-
|
|
9144
|
-
cpSync(oldDir, newDir, { recursive: true });
|
|
9126
|
+
mergeDirectoryContents(oldDir, newDir);
|
|
9145
9127
|
} catch {}
|
|
9146
9128
|
}
|
|
9147
9129
|
return newDir;
|
|
9148
9130
|
}
|
|
9131
|
+
function findProjectRecordingsPath(entry) {
|
|
9132
|
+
const home = resolve(getHomeDir());
|
|
9133
|
+
let dir = resolve(process.cwd());
|
|
9134
|
+
while (true) {
|
|
9135
|
+
if (dir !== home) {
|
|
9136
|
+
const candidate = entry ? join(dir, ".recordings", entry) : join(dir, ".recordings");
|
|
9137
|
+
if (existsSync(candidate))
|
|
9138
|
+
return candidate;
|
|
9139
|
+
}
|
|
9140
|
+
const parent = dirname(dir);
|
|
9141
|
+
if (parent === dir)
|
|
9142
|
+
break;
|
|
9143
|
+
dir = parent;
|
|
9144
|
+
}
|
|
9145
|
+
return null;
|
|
9146
|
+
}
|
|
9147
|
+
function mergeDirectoryContents(sourceDir, targetDir) {
|
|
9148
|
+
mkdirSync(targetDir, { recursive: true });
|
|
9149
|
+
for (const entry of readdirSync(sourceDir)) {
|
|
9150
|
+
const sourcePath = join(sourceDir, entry);
|
|
9151
|
+
const targetPath = join(targetDir, entry);
|
|
9152
|
+
const sourceStats = statSync(sourcePath);
|
|
9153
|
+
if (sourceStats.isDirectory()) {
|
|
9154
|
+
mergeDirectoryContents(sourcePath, targetPath);
|
|
9155
|
+
} else if (!existsSync(targetPath)) {
|
|
9156
|
+
copyFileSync(sourcePath, targetPath);
|
|
9157
|
+
}
|
|
9158
|
+
}
|
|
9159
|
+
}
|
|
9149
9160
|
function loadSecretKey(keyName) {
|
|
9150
|
-
const secretsPath = join(
|
|
9161
|
+
const secretsPath = join(getHomeDir(), ".secrets");
|
|
9151
9162
|
if (!existsSync(secretsPath))
|
|
9152
9163
|
return "";
|
|
9153
9164
|
for (const candidate of listSecretFiles(secretsPath)) {
|
|
@@ -9188,6 +9199,9 @@ function listSecretFiles(path) {
|
|
|
9188
9199
|
return [];
|
|
9189
9200
|
}
|
|
9190
9201
|
}
|
|
9202
|
+
function getHomeDir() {
|
|
9203
|
+
return process.env["HOME"] || process.env["USERPROFILE"] || homedir();
|
|
9204
|
+
}
|
|
9191
9205
|
function ensureDataDir(config) {
|
|
9192
9206
|
const { mkdirSync: mkdirSync2 } = __require("fs");
|
|
9193
9207
|
mkdirSync2(config.audio_dir, { recursive: true });
|
|
@@ -9229,7 +9243,7 @@ class SqliteAdapter {
|
|
|
9229
9243
|
|
|
9230
9244
|
// src/db/database.ts
|
|
9231
9245
|
import { mkdirSync as mkdirSync2 } from "fs";
|
|
9232
|
-
import { dirname } from "path";
|
|
9246
|
+
import { dirname as dirname2 } from "path";
|
|
9233
9247
|
var _db = null;
|
|
9234
9248
|
var _adapter = null;
|
|
9235
9249
|
var MIGRATIONS = [
|
|
@@ -9315,7 +9329,7 @@ function getDatabase(dbPath) {
|
|
|
9315
9329
|
if (_db)
|
|
9316
9330
|
return _db;
|
|
9317
9331
|
const path = dbPath || loadConfig().db_path;
|
|
9318
|
-
const dir =
|
|
9332
|
+
const dir = dirname2(path);
|
|
9319
9333
|
mkdirSync2(dir, { recursive: true });
|
|
9320
9334
|
_adapter = new SqliteAdapter(path);
|
|
9321
9335
|
_db = _adapter.raw;
|
|
@@ -9798,17 +9812,18 @@ async function processText(rawText, config, systemPrompt) {
|
|
|
9798
9812
|
}
|
|
9799
9813
|
|
|
9800
9814
|
// src/version.ts
|
|
9801
|
-
var VERSION = "0.1.
|
|
9815
|
+
var VERSION = "0.1.36";
|
|
9802
9816
|
|
|
9803
9817
|
// src/db/storage-config.ts
|
|
9804
9818
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
9805
9819
|
import { homedir as homedir2 } from "os";
|
|
9806
9820
|
import { join as join2 } from "path";
|
|
9807
|
-
var
|
|
9821
|
+
var LEGACY_DATABASE_CONFIG_KEY = ["r", "d", "s"].join("");
|
|
9808
9822
|
var RECORDINGS_STORAGE_ENV = "HASNA_RECORDINGS_DATABASE_URL";
|
|
9809
9823
|
var RECORDINGS_STORAGE_FALLBACK_ENV = "RECORDINGS_DATABASE_URL";
|
|
9810
9824
|
var RECORDINGS_STORAGE_MODE_ENV = "HASNA_RECORDINGS_STORAGE_MODE";
|
|
9811
9825
|
var RECORDINGS_STORAGE_MODE_FALLBACK_ENV = "RECORDINGS_STORAGE_MODE";
|
|
9826
|
+
var RECORDINGS_STORAGE_CONFIG_ENV = "HASNA_RECORDINGS_STORAGE_CONFIG";
|
|
9812
9827
|
var STORAGE_DATABASE_ENV = [RECORDINGS_STORAGE_ENV, RECORDINGS_STORAGE_FALLBACK_ENV];
|
|
9813
9828
|
function readEnv(name) {
|
|
9814
9829
|
const value = process.env[name]?.trim();
|
|
@@ -9835,10 +9850,16 @@ function getStorageDatabaseUrl() {
|
|
|
9835
9850
|
const env = getStorageDatabaseEnv();
|
|
9836
9851
|
return env ? readEnv(env.name) : undefined;
|
|
9837
9852
|
}
|
|
9853
|
+
function getStorageConfigPath() {
|
|
9854
|
+
const override = readEnv(RECORDINGS_STORAGE_CONFIG_ENV);
|
|
9855
|
+
if (override)
|
|
9856
|
+
return override;
|
|
9857
|
+
return join2(homedir2(), ".hasna", "recordings", "storage", "config.json");
|
|
9858
|
+
}
|
|
9838
9859
|
function getStorageConfig() {
|
|
9839
9860
|
const config = {
|
|
9840
9861
|
mode: "local",
|
|
9841
|
-
|
|
9862
|
+
postgres: {
|
|
9842
9863
|
host: "",
|
|
9843
9864
|
port: 5432,
|
|
9844
9865
|
username: "",
|
|
@@ -9846,11 +9867,13 @@ function getStorageConfig() {
|
|
|
9846
9867
|
ssl: true
|
|
9847
9868
|
}
|
|
9848
9869
|
};
|
|
9849
|
-
|
|
9870
|
+
const storageConfigPath = getStorageConfigPath();
|
|
9871
|
+
if (existsSync2(storageConfigPath)) {
|
|
9850
9872
|
try {
|
|
9851
|
-
const raw = JSON.parse(readFileSync2(
|
|
9873
|
+
const raw = JSON.parse(readFileSync2(storageConfigPath, "utf-8"));
|
|
9874
|
+
const legacyDatabaseConfig = typeof raw[LEGACY_DATABASE_CONFIG_KEY] === "object" && raw[LEGACY_DATABASE_CONFIG_KEY] !== null ? raw[LEGACY_DATABASE_CONFIG_KEY] : {};
|
|
9852
9875
|
config.mode = normalizeMode(raw.mode) ?? config.mode;
|
|
9853
|
-
config.
|
|
9876
|
+
config.postgres = { ...config.postgres, ...legacyDatabaseConfig, ...raw.postgres ?? {} };
|
|
9854
9877
|
} catch {}
|
|
9855
9878
|
}
|
|
9856
9879
|
const modeOverride = readEnv(RECORDINGS_STORAGE_MODE_ENV) ?? readEnv(RECORDINGS_STORAGE_MODE_FALLBACK_ENV);
|
|
@@ -9867,7 +9890,7 @@ function getStorageConnectionString(dbName = "recordings") {
|
|
|
9867
9890
|
if (direct)
|
|
9868
9891
|
return direct;
|
|
9869
9892
|
const config = getStorageConfig();
|
|
9870
|
-
const { host, port, username, password_env, ssl } = config.
|
|
9893
|
+
const { host, port, username, password_env, ssl } = config.postgres;
|
|
9871
9894
|
if (!host || !username) {
|
|
9872
9895
|
throw new Error("Storage database is not configured. Set HASNA_RECORDINGS_DATABASE_URL or configure ~/.hasna/recordings/storage/config.json.");
|
|
9873
9896
|
}
|
|
@@ -10071,8 +10094,9 @@ async function runStorageMigrations(remote) {
|
|
|
10071
10094
|
function getStorageStatus(db = getDatabase()) {
|
|
10072
10095
|
const config = getStorageConfig();
|
|
10073
10096
|
const activeEnv = getStorageDatabaseEnv();
|
|
10097
|
+
const hasConfiguredPostgres = Boolean(config.postgres.host && config.postgres.username);
|
|
10074
10098
|
return {
|
|
10075
|
-
configured: Boolean(activeEnv),
|
|
10099
|
+
configured: Boolean(activeEnv) || hasConfiguredPostgres,
|
|
10076
10100
|
mode: config.mode,
|
|
10077
10101
|
enabled: config.mode === "hybrid" || config.mode === "remote",
|
|
10078
10102
|
env: STORAGE_DATABASE_ENV,
|