@hasna/recordings 0.3.1 → 0.3.8
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 +38 -34
- package/bun.lock +96 -36
- package/dist/__tests__/helpers/installer-guard-execution.d.ts.map +1 -1
- package/dist/__tests__/helpers/source-assertions.d.ts +6 -4
- package/dist/__tests__/helpers/source-assertions.d.ts.map +1 -1
- package/dist/cli/index.js +197 -95
- package/dist/cli/macos-shortcut.d.ts +2 -2
- package/dist/db/pg-migrations.d.ts +1 -1
- package/dist/http/client.d.ts +0 -1
- package/dist/http/client.d.ts.map +1 -1
- package/dist/index.js +162 -73
- package/dist/lib/capture-probe.d.ts +3 -3
- package/dist/lib/capture-probe.d.ts.map +1 -1
- package/dist/lib/macos-bundle.d.ts +1 -1
- package/dist/lib/release-install-policy.d.ts +21 -0
- package/dist/lib/release-install-policy.d.ts.map +1 -1
- package/dist/mcp/index.js +144 -59
- package/dist/sdk/index.d.ts +2 -2
- package/dist/sdk/index.js +7 -3
- package/dist/sdk/v1.generated.d.ts.map +1 -1
- package/dist/server/cloud-config.d.ts +4 -19
- package/dist/server/cloud-config.d.ts.map +1 -1
- package/dist/server/cloud.d.ts +1 -1
- package/dist/server/cloud.d.ts.map +1 -1
- package/dist/server/index.js +168 -110
- package/dist/server/serve.d.ts.map +1 -1
- package/dist/storage.d.ts +1 -1
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +144 -60
- package/dist/store.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/package.json +4 -3
- package/packaging/macos/build_release_pkg.sh +10 -4
- package/packaging/macos/managed_bootstrap.sh +4 -4
- package/packaging/macos/scripts/postinstall +2 -2
- package/packaging/macos/scripts/preinstall +2 -0
- package/scripts/generate-sdk.ts +17 -16
- package/scripts/install_macos_app.sh +75 -28
- package/scripts/macos_artifact.ts +162 -45
- package/scripts/migrate.ts +2 -2
- package/scripts/release-suite-gate.ts +181 -0
- package/scripts/set-version.ts +5 -5
- package/scripts/smoke_macos_app.sh +80 -34
- package/scripts/vacuity-manifests/version-sites.tsv +8 -4
- package/src/native/Recordings/App/MenuBarStatusView.swift +9 -4
- package/src/native/Recordings/App/RecordingsApp.swift +37 -1
- package/src/native/Recordings/RecordingsLib/Info.plist +3 -3
- package/src/native/Recordings/RecordingsLib/PermissionRequestLaunchPlan.swift +21 -1
- package/src/native/Recordings/RecordingsTests/BarOnlyLaunchPlanTests.swift +99 -0
- package/src/native/Recordings/RecordingsTests/CLIRunnerTests.swift +2 -2
- package/src/native/Recordings/RecordingsTests/RecordingStartGateTests.swift +1 -1
- package/src/native/Recordings/Updater/BootstrapPreflight/BootstrapPreflightMain.swift +1 -1
- package/src/native/Recordings/Updater/Broker/ApplicationNamespace.swift +2 -2
- package/src/native/Recordings/Updater/Broker/BrokerMain.swift +1 -1
- package/src/native/Recordings/Updater/Broker/CanonicalTreeCopy.swift +1 -1
- package/src/native/Recordings/Updater/Broker/InstallJournal.swift +1 -1
- package/src/native/Recordings/Updater/BrokerTests/ActivationRecoveryPolicyTests.swift +2 -2
- package/src/native/Recordings/Updater/Protocol/UpdateProtocol.swift +1 -1
- package/src/native/Recordings/Updater/VerifierLauncher/RecordingsVerifierLauncher.c +2 -2
- package/src/native/Recordings/build.sh +152 -18
- package/dist/lib/retired-deployment-modes.d.ts +0 -24
- package/dist/lib/retired-deployment-modes.d.ts.map +0 -1
package/dist/server/index.js
CHANGED
|
@@ -17,8 +17,125 @@ var __export = (target, all) => {
|
|
|
17
17
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
18
18
|
var __require = import.meta.require;
|
|
19
19
|
|
|
20
|
+
// package.json
|
|
21
|
+
var package_default;
|
|
22
|
+
var init_package = __esm(() => {
|
|
23
|
+
package_default = {
|
|
24
|
+
name: "@hasna/recordings",
|
|
25
|
+
version: "0.3.8",
|
|
26
|
+
type: "module",
|
|
27
|
+
description: "Speech-to-text recording tool with MCP and CLI \u2014 records, transcribes, and optionally enhances text using AI",
|
|
28
|
+
repository: {
|
|
29
|
+
type: "git",
|
|
30
|
+
url: "git+https://github.com/hasna/apps"
|
|
31
|
+
},
|
|
32
|
+
main: "dist/index.js",
|
|
33
|
+
types: "dist/index.d.ts",
|
|
34
|
+
bin: {
|
|
35
|
+
recordings: "dist/cli/index.js",
|
|
36
|
+
"recordings-mcp": "dist/mcp/index.js",
|
|
37
|
+
"recordings-serve": "dist/server/index.js"
|
|
38
|
+
},
|
|
39
|
+
exports: {
|
|
40
|
+
".": {
|
|
41
|
+
import: "./dist/index.js",
|
|
42
|
+
types: "./dist/index.d.ts"
|
|
43
|
+
},
|
|
44
|
+
"./storage": {
|
|
45
|
+
import: "./dist/storage.js",
|
|
46
|
+
types: "./dist/storage.d.ts"
|
|
47
|
+
},
|
|
48
|
+
"./sdk": {
|
|
49
|
+
import: "./dist/sdk/index.js",
|
|
50
|
+
types: "./dist/sdk/index.d.ts"
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
engines: {
|
|
54
|
+
bun: ">=1.0.0"
|
|
55
|
+
},
|
|
56
|
+
scripts: {
|
|
57
|
+
clean: "rm -rf dist",
|
|
58
|
+
build: "bun run clean && bun run build:cli && bun run build:mcp && bun run build:serve && bun run build:lib && tsc --emitDeclarationOnly --outDir dist",
|
|
59
|
+
"build:cli": "bun build src/cli/index.ts --target=bun --outfile=dist/cli/index.js --external=commander --external=chalk --external=openai",
|
|
60
|
+
"build:mcp": "bun build src/mcp/index.ts --target=bun --outfile=dist/mcp/index.js --external=@modelcontextprotocol/sdk --external=openai",
|
|
61
|
+
"build:serve": "bun build src/server/index.ts --target=bun --outfile=dist/server/index.js --external=@modelcontextprotocol/sdk --external=@hasna/contracts --external=openai --external=pg",
|
|
62
|
+
"build:lib": "bun build src/index.ts src/storage.ts src/sdk/index.ts --target=bun --outdir=dist --external=openai",
|
|
63
|
+
"build:native-fs-guard": "/bin/bash scripts/build_native_fs_guard.sh",
|
|
64
|
+
"generate:sdk": "bun run scripts/generate-sdk.ts",
|
|
65
|
+
migrate: "bun run scripts/migrate.ts",
|
|
66
|
+
typecheck: "tsc --noEmit",
|
|
67
|
+
"typecheck:tcc-contract": "tsc --noEmit -p tsconfig.tcc-contract.json",
|
|
68
|
+
test: "bun test",
|
|
69
|
+
"verify:ci-suite": "bun scripts/ci-linux-suite.ts --check",
|
|
70
|
+
"verify:ci-suite:run": "bun scripts/ci-linux-suite.ts --verify-run",
|
|
71
|
+
"verify:ci-native": "bun scripts/ci-native-build.ts",
|
|
72
|
+
"test:gated": 'bun scripts/ci-linux-suite.ts --check && RECORDINGS_TEST_TIMEOUT_MS="${RECORDINGS_TEST_TIMEOUT_MS:-120000}" bun test --timeout "$RECORDINGS_TEST_TIMEOUT_MS" $(bun scripts/ci-linux-suite.ts --gated)',
|
|
73
|
+
"test:vacuity-battery": 'bun scripts/vacuity-manifest-gen.ts > "${TMPDIR:-/tmp}/vacuity-corrupt-sites.tsv" && bun scripts/vacuity-mutation-battery.ts "${TMPDIR:-/tmp}/vacuity-corrupt-sites.tsv"',
|
|
74
|
+
"test:vacuity-battery:source": "bun scripts/vacuity-mutation-battery.ts scripts/vacuity-manifests/source-side.tsv",
|
|
75
|
+
"test:vacuity-battery:chain": "bun scripts/vacuity-mutation-battery.ts scripts/vacuity-manifests/install-chain.tsv",
|
|
76
|
+
"test:vacuity-battery:vars": "bun scripts/vacuity-mutation-battery.ts scripts/vacuity-manifests/variable-operands.tsv",
|
|
77
|
+
"test:vacuity-battery:reorder": "bun scripts/vacuity-mutation-battery.ts scripts/vacuity-manifests/reorder.tsv",
|
|
78
|
+
"test:coverage": "bun test --coverage",
|
|
79
|
+
"dev:cli": "bun run src/cli/index.ts",
|
|
80
|
+
"desktop:snapshot": "bun run src/cli/index.ts app snapshot",
|
|
81
|
+
"dev:mcp": "bun run src/mcp/index.ts",
|
|
82
|
+
"verify:release": "bun run scripts/release-guard.ts",
|
|
83
|
+
"scan:artifact": "bun run scripts/scan-artifact.ts",
|
|
84
|
+
"version:set": "bun run scripts/set-version.ts",
|
|
85
|
+
"version:check": "bun run scripts/set-version.ts --check",
|
|
86
|
+
prepack: "bun run prepack:platform-gate && bun run version:check && bun run build && bun run verify:release && bun run scan:artifact",
|
|
87
|
+
"prepack:platform-gate": `bash -c 'if [ "$(uname -s)" = Darwin ]; then bun run build:native-fs-guard; else echo "WARN: native fs-guard build skipped on $(uname -s) \u2014 dry-run/CI pack; publish recordings from macOS"; fi'`,
|
|
88
|
+
prepublishOnly: "bun run typecheck && bun run release-suite-gate",
|
|
89
|
+
"release-suite-gate": "bun run scripts/release-suite-gate.ts",
|
|
90
|
+
"typecheck:shortcut-contract": "tsc --noEmit -p tsconfig.test.json"
|
|
91
|
+
},
|
|
92
|
+
files: [
|
|
93
|
+
"dist/",
|
|
94
|
+
"scripts/",
|
|
95
|
+
"Dockerfile.package",
|
|
96
|
+
"bun.lock",
|
|
97
|
+
"src/native/Recordings/App/",
|
|
98
|
+
"src/native/Recordings/RecordingsLib/",
|
|
99
|
+
"src/native/Recordings/RecordingsTests/",
|
|
100
|
+
"src/native/Recordings/Updater/",
|
|
101
|
+
"src/native/Recordings/Package.swift",
|
|
102
|
+
"src/native/Recordings/Package.resolved",
|
|
103
|
+
"src/native/Recordings/build.sh",
|
|
104
|
+
"packaging/macos/",
|
|
105
|
+
"README.md",
|
|
106
|
+
"LICENSE"
|
|
107
|
+
],
|
|
108
|
+
dependencies: {
|
|
109
|
+
"@hasna/contracts": "0.13.3",
|
|
110
|
+
"@hasna/events": "0.1.11",
|
|
111
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
112
|
+
chalk: "^5.4.1",
|
|
113
|
+
commander: "^13.1.0",
|
|
114
|
+
openai: "^5.1.0",
|
|
115
|
+
pg: "^8.13.3",
|
|
116
|
+
zod: "^3.24.2"
|
|
117
|
+
},
|
|
118
|
+
devDependencies: {
|
|
119
|
+
"@types/bun": "^1.2.5",
|
|
120
|
+
"@types/pg": "^8.11.11",
|
|
121
|
+
"node-api-headers": "1.9.0",
|
|
122
|
+
typescript: "^5.8.2"
|
|
123
|
+
},
|
|
124
|
+
publishConfig: {
|
|
125
|
+
registry: "https://registry.npmjs.org",
|
|
126
|
+
access: "public"
|
|
127
|
+
},
|
|
128
|
+
license: "Apache-2.0",
|
|
129
|
+
author: "Hasna <andrei@hasna.com>"
|
|
130
|
+
};
|
|
131
|
+
});
|
|
132
|
+
|
|
20
133
|
// src/version.ts
|
|
21
|
-
var VERSION
|
|
134
|
+
var VERSION;
|
|
135
|
+
var init_version = __esm(() => {
|
|
136
|
+
init_package();
|
|
137
|
+
VERSION = package_default.version;
|
|
138
|
+
});
|
|
22
139
|
|
|
23
140
|
// src/db/remote-storage.ts
|
|
24
141
|
import pg from "pg";
|
|
@@ -82,59 +199,12 @@ class PgAdapterAsync {
|
|
|
82
199
|
}
|
|
83
200
|
var init_remote_storage = () => {};
|
|
84
201
|
|
|
85
|
-
// src/lib/retired-deployment-modes.ts
|
|
86
|
-
function normalizeModeToken(value) {
|
|
87
|
-
return value.trim().toLowerCase().replace(/-/g, "_");
|
|
88
|
-
}
|
|
89
|
-
function asRetiredDeploymentMode(value) {
|
|
90
|
-
const token = normalizeModeToken(value);
|
|
91
|
-
return RETIRED_DEPLOYMENT_MODES.includes(token) ? token : null;
|
|
92
|
-
}
|
|
93
|
-
function retiredDeploymentModeError(rawValue, sourceEnvKey, replacement) {
|
|
94
|
-
const mode = asRetiredDeploymentMode(rawValue);
|
|
95
|
-
const value = mode === "local" ? replacement.onBox : replacement.offBox;
|
|
96
|
-
return new Error(`${sourceEnvKey}=${rawValue} names a deployment mode, and deployment modes are removed: ` + `${RETIRED_DEPLOYMENT_MODES.join(" | ")} no longer select anything. ` + `Set ${replacement.envKey}=${value} instead ` + `(${replacement.envKey} takes ${replacement.onBox} or ${replacement.offBox}).`);
|
|
97
|
-
}
|
|
98
|
-
var RETIRED_DEPLOYMENT_MODES;
|
|
99
|
-
var init_retired_deployment_modes = __esm(() => {
|
|
100
|
-
RETIRED_DEPLOYMENT_MODES = [
|
|
101
|
-
"local",
|
|
102
|
-
"self_hosted",
|
|
103
|
-
"cloud",
|
|
104
|
-
"remote",
|
|
105
|
-
"hybrid"
|
|
106
|
-
];
|
|
107
|
-
});
|
|
108
|
-
|
|
109
202
|
// src/server/cloud-config.ts
|
|
110
|
-
function
|
|
111
|
-
return { envKey: DATA_BACKEND_ENV_KEYS[0], onBox: "sqlite", offBox: "postgresql" };
|
|
112
|
-
}
|
|
113
|
-
function resolveCloudDatabaseUrl(env = process.env) {
|
|
203
|
+
function resolveDatabaseUrl(env = process.env) {
|
|
114
204
|
return env.HASNA_RECORDINGS_DATABASE_URL || env.RECORDINGS_DATABASE_URL || env.DATABASE_URL || undefined;
|
|
115
205
|
}
|
|
116
|
-
function configuredDataBackend(env = process.env) {
|
|
117
|
-
for (const key of DATA_BACKEND_ENV_KEYS) {
|
|
118
|
-
const raw = env[key]?.trim();
|
|
119
|
-
if (!raw)
|
|
120
|
-
continue;
|
|
121
|
-
const token = normalizeModeToken(raw);
|
|
122
|
-
if (token === "sqlite")
|
|
123
|
-
return { backend: "sqlite", source: key };
|
|
124
|
-
if (token === "postgresql" || token === "postgres")
|
|
125
|
-
return { backend: "postgresql", source: key };
|
|
126
|
-
if (asRetiredDeploymentMode(raw)) {
|
|
127
|
-
throw retiredDeploymentModeError(raw, key, backendReplacement());
|
|
128
|
-
}
|
|
129
|
-
throw new Error(`${key}=${raw} is not a data backend. Use ${DATA_BACKEND_ENV_KEYS[0]}=sqlite or ` + `${DATA_BACKEND_ENV_KEYS[0]}=postgresql.`);
|
|
130
|
-
}
|
|
131
|
-
return null;
|
|
132
|
-
}
|
|
133
206
|
function resolveDataBackend(env = process.env) {
|
|
134
|
-
|
|
135
|
-
if (configured)
|
|
136
|
-
return configured.backend;
|
|
137
|
-
return resolveCloudDatabaseUrl(env) ? "postgresql" : "sqlite";
|
|
207
|
+
return resolveDatabaseUrl(env) ? "postgresql" : "sqlite";
|
|
138
208
|
}
|
|
139
209
|
function isPostgresBackendEnabled(env = process.env) {
|
|
140
210
|
return resolveDataBackend(env) === "postgresql";
|
|
@@ -152,14 +222,6 @@ function requireSigningSecret(env = process.env) {
|
|
|
152
222
|
}
|
|
153
223
|
return signingSecret;
|
|
154
224
|
}
|
|
155
|
-
var DATA_BACKEND_ENV_KEYS;
|
|
156
|
-
var init_cloud_config = __esm(() => {
|
|
157
|
-
init_retired_deployment_modes();
|
|
158
|
-
DATA_BACKEND_ENV_KEYS = [
|
|
159
|
-
"HASNA_RECORDINGS_STORAGE_MODE",
|
|
160
|
-
"RECORDINGS_STORAGE_MODE"
|
|
161
|
-
];
|
|
162
|
-
});
|
|
163
225
|
|
|
164
226
|
// src/server/cloud-readiness.ts
|
|
165
227
|
var exports_cloud_readiness = {};
|
|
@@ -221,7 +283,7 @@ async function assertCloudSchemaContract(pg2) {
|
|
|
221
283
|
ON attribute_row.attrelid = constraint_row.conrelid
|
|
222
284
|
AND attribute_row.attnum = key_row.attnum
|
|
223
285
|
ORDER BY key_row.position
|
|
224
|
-
) AS columns,
|
|
286
|
+
)::text[] AS columns,
|
|
225
287
|
referenced_namespace.nspname AS referenced_schema,
|
|
226
288
|
referenced_table.relname AS referenced_table,
|
|
227
289
|
CASE WHEN constraint_row.confrelid = 0 THEN ARRAY[]::text[] ELSE ARRAY(
|
|
@@ -231,7 +293,7 @@ async function assertCloudSchemaContract(pg2) {
|
|
|
231
293
|
ON attribute_row.attrelid = constraint_row.confrelid
|
|
232
294
|
AND attribute_row.attnum = key_row.attnum
|
|
233
295
|
ORDER BY key_row.position
|
|
234
|
-
) END AS referenced_columns,
|
|
296
|
+
)::text[] END AS referenced_columns,
|
|
235
297
|
NULLIF(constraint_row.confdeltype::text, ' ') AS delete_action,
|
|
236
298
|
NULLIF(constraint_row.confupdtype::text, ' ') AS update_action,
|
|
237
299
|
NULLIF(constraint_row.confmatchtype::text, ' ') AS match_type
|
|
@@ -265,7 +327,7 @@ async function assertCloudSchemaContract(pg2) {
|
|
|
265
327
|
AND attribute_row.attnum = key_row.attnum
|
|
266
328
|
WHERE key_row.position <= index_row.indnkeyatts
|
|
267
329
|
ORDER BY key_row.position
|
|
268
|
-
) AS columns
|
|
330
|
+
)::text[] AS columns
|
|
269
331
|
FROM pg_index index_row
|
|
270
332
|
JOIN pg_class table_row ON table_row.oid = index_row.indrelid
|
|
271
333
|
JOIN pg_namespace namespace_row ON namespace_row.oid = table_row.relnamespace
|
|
@@ -671,8 +733,8 @@ var init_migrate_command = __esm(() => {
|
|
|
671
733
|
var exports_cloud = {};
|
|
672
734
|
__export(exports_cloud, {
|
|
673
735
|
resolveSigningSecret: () => resolveSigningSecret,
|
|
736
|
+
resolveDatabaseUrl: () => resolveDatabaseUrl,
|
|
674
737
|
resolveDataBackend: () => resolveDataBackend,
|
|
675
|
-
resolveCloudDatabaseUrl: () => resolveCloudDatabaseUrl,
|
|
676
738
|
requireSigningSecret: () => requireSigningSecret,
|
|
677
739
|
pingCloudConnectivity: () => pingCloudConnectivity2,
|
|
678
740
|
pingCloud: () => pingCloud,
|
|
@@ -682,7 +744,6 @@ __export(exports_cloud, {
|
|
|
682
744
|
getCloudPg: () => getCloudPg,
|
|
683
745
|
getApiKeyStore: () => getApiKeyStore,
|
|
684
746
|
ensureCloudSchema: () => ensureCloudSchema,
|
|
685
|
-
configuredDataBackend: () => configuredDataBackend,
|
|
686
747
|
closeCloud: () => closeCloud,
|
|
687
748
|
RECORDINGS_APP_SLUG: () => RECORDINGS_APP_SLUG
|
|
688
749
|
});
|
|
@@ -691,7 +752,7 @@ import { ApiKeyStore } from "@hasna/contracts/auth";
|
|
|
691
752
|
function getCloudPg() {
|
|
692
753
|
if (cachedPg)
|
|
693
754
|
return cachedPg;
|
|
694
|
-
const url =
|
|
755
|
+
const url = resolveDatabaseUrl();
|
|
695
756
|
if (!url) {
|
|
696
757
|
throw new Error("The /v1 API requires a PostgreSQL database URL (HASNA_RECORDINGS_DATABASE_URL / RECORDINGS_DATABASE_URL / DATABASE_URL).");
|
|
697
758
|
}
|
|
@@ -759,10 +820,8 @@ async function closeCloud() {
|
|
|
759
820
|
var RECORDINGS_APP_SLUG = "recordings", cachedPg = null, cachedStore = null, cachedVerifier = null, schemaEnsured = null;
|
|
760
821
|
var init_cloud = __esm(() => {
|
|
761
822
|
init_remote_storage();
|
|
762
|
-
init_cloud_config();
|
|
763
823
|
init_cloud_readiness();
|
|
764
824
|
init_migrate_command();
|
|
765
|
-
init_cloud_config();
|
|
766
825
|
});
|
|
767
826
|
|
|
768
827
|
// src/db/errors.ts
|
|
@@ -1672,6 +1731,7 @@ function buildV1OpenApiDocument(version = VERSION) {
|
|
|
1672
1731
|
}
|
|
1673
1732
|
var recordingSchema, agentSchema, projectSchema;
|
|
1674
1733
|
var init_openapi = __esm(() => {
|
|
1734
|
+
init_version();
|
|
1675
1735
|
recordingSchema = {
|
|
1676
1736
|
type: "object",
|
|
1677
1737
|
properties: {
|
|
@@ -6727,38 +6787,29 @@ function saveFeedback2(input) {
|
|
|
6727
6787
|
}
|
|
6728
6788
|
var init_feedback = __esm(() => {
|
|
6729
6789
|
init_database();
|
|
6790
|
+
init_version();
|
|
6730
6791
|
});
|
|
6731
6792
|
|
|
6732
6793
|
// src/http/client.ts
|
|
6733
6794
|
function envToken(name) {
|
|
6734
6795
|
return name.toUpperCase().replace(/-/g, "_");
|
|
6735
6796
|
}
|
|
6736
|
-
function
|
|
6737
|
-
|
|
6797
|
+
function envKeys(name) {
|
|
6798
|
+
const token = envToken(name);
|
|
6799
|
+
return {
|
|
6800
|
+
storeKeys: [`HASNA_${token}_CLIENT_STORE`, `${token}_CLIENT_STORE`],
|
|
6801
|
+
apiUrlKeys: [`HASNA_${token}_API_URL`],
|
|
6802
|
+
apiKeyKeys: [`HASNA_${token}_API_KEY`]
|
|
6803
|
+
};
|
|
6738
6804
|
}
|
|
6739
|
-
function normalizeClientStore(value
|
|
6740
|
-
const normalized =
|
|
6805
|
+
function normalizeClientStore(value) {
|
|
6806
|
+
const normalized = value.trim().toLowerCase();
|
|
6741
6807
|
if (normalized === "sqlite")
|
|
6742
6808
|
return "sqlite";
|
|
6743
6809
|
if (normalized === "http" || normalized === "https")
|
|
6744
6810
|
return "http";
|
|
6745
|
-
if (asRetiredDeploymentMode(value)) {
|
|
6746
|
-
throw retiredDeploymentModeError(value, sourceEnvKey, clientStoreReplacement(replacementEnvKey));
|
|
6747
|
-
}
|
|
6748
6811
|
throw new Error(`Unknown client store: ${value}. Use sqlite or http.`);
|
|
6749
6812
|
}
|
|
6750
|
-
function defaultApiBaseUrl(name) {
|
|
6751
|
-
return `https://${name}.hasna.xyz`;
|
|
6752
|
-
}
|
|
6753
|
-
function envKeys(name) {
|
|
6754
|
-
const token = envToken(name);
|
|
6755
|
-
return {
|
|
6756
|
-
storeKeys: [`HASNA_${token}_CLIENT_STORE`, `${token}_CLIENT_STORE`],
|
|
6757
|
-
retiredModeKeys: [`HASNA_${token}_STORAGE_MODE`, `HASNA_${token}_MODE`, `${token}_STORAGE_MODE`, `${token}_MODE`],
|
|
6758
|
-
apiUrlKeys: [`HASNA_${token}_API_URL`, `${token}_API_URL`],
|
|
6759
|
-
apiKeyKeys: [`HASNA_${token}_API_KEY`, `${token}_API_KEY`]
|
|
6760
|
-
};
|
|
6761
|
-
}
|
|
6762
6813
|
function firstEnv(env, keys) {
|
|
6763
6814
|
for (const key of keys) {
|
|
6764
6815
|
const value = env[key]?.trim();
|
|
@@ -6767,20 +6818,6 @@ function firstEnv(env, keys) {
|
|
|
6767
6818
|
}
|
|
6768
6819
|
return null;
|
|
6769
6820
|
}
|
|
6770
|
-
function assertNoRetiredMode(env, keys) {
|
|
6771
|
-
for (const key of keys.retiredModeKeys) {
|
|
6772
|
-
const value = env[key]?.trim();
|
|
6773
|
-
if (!value)
|
|
6774
|
-
continue;
|
|
6775
|
-
const normalized = normalizeModeToken(value);
|
|
6776
|
-
if (SERVER_BACKEND_VALUES.includes(normalized))
|
|
6777
|
-
continue;
|
|
6778
|
-
if (asRetiredDeploymentMode(value)) {
|
|
6779
|
-
throw retiredDeploymentModeError(value, key, clientStoreReplacement(keys.storeKeys[0]));
|
|
6780
|
-
}
|
|
6781
|
-
throw new Error(`${key}=${value} is not a client store. ${key} no longer selects one; ` + `set ${keys.storeKeys[0]}=sqlite or ${keys.storeKeys[0]}=http instead.`);
|
|
6782
|
-
}
|
|
6783
|
-
}
|
|
6784
6821
|
function toV1BaseUrl(apiUrl) {
|
|
6785
6822
|
const url = new URL(apiUrl);
|
|
6786
6823
|
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
@@ -6796,22 +6833,44 @@ function toV1BaseUrl(apiUrl) {
|
|
|
6796
6833
|
}
|
|
6797
6834
|
function resolveTransport(name, env = process.env) {
|
|
6798
6835
|
const keys = envKeys(name);
|
|
6799
|
-
assertNoRetiredMode(env, keys);
|
|
6800
6836
|
const storeHit = firstEnv(env, keys.storeKeys);
|
|
6801
6837
|
const urlHit = firstEnv(env, keys.apiUrlKeys);
|
|
6802
6838
|
const keyHit = firstEnv(env, keys.apiKeyKeys);
|
|
6803
6839
|
let requested = "sqlite";
|
|
6804
6840
|
let modeSource = "default";
|
|
6805
6841
|
if (storeHit) {
|
|
6806
|
-
requested = normalizeClientStore(storeHit.value
|
|
6842
|
+
requested = normalizeClientStore(storeHit.value);
|
|
6807
6843
|
modeSource = storeHit.key;
|
|
6808
6844
|
} else if (urlHit && keyHit) {
|
|
6809
6845
|
requested = "http";
|
|
6810
6846
|
modeSource = "auto:api-url+api-key";
|
|
6847
|
+
} else if (urlHit || keyHit) {
|
|
6848
|
+
const missing = urlHit ? keys.apiKeyKeys[0] : keys.apiUrlKeys[0];
|
|
6849
|
+
const present = urlHit ? keys.apiUrlKeys[0] : keys.apiKeyKeys[0];
|
|
6850
|
+
return {
|
|
6851
|
+
transport: "sqlite",
|
|
6852
|
+
requested,
|
|
6853
|
+
modeSource,
|
|
6854
|
+
baseUrl: null,
|
|
6855
|
+
apiKeyPresent: Boolean(keyHit),
|
|
6856
|
+
misconfigured: true,
|
|
6857
|
+
warning: `${present} is set but ${missing} is not: the hosted API is only ` + `selected when BOTH are present. Set ${missing}, or unset ${present} to ` + `use the on-box store.`
|
|
6858
|
+
};
|
|
6811
6859
|
}
|
|
6812
6860
|
if (requested === "sqlite") {
|
|
6813
6861
|
return { transport: "sqlite", requested, modeSource, baseUrl: null, apiKeyPresent: Boolean(keyHit), misconfigured: false, warning: null };
|
|
6814
6862
|
}
|
|
6863
|
+
if (!urlHit) {
|
|
6864
|
+
return {
|
|
6865
|
+
transport: "sqlite",
|
|
6866
|
+
requested,
|
|
6867
|
+
modeSource,
|
|
6868
|
+
baseUrl: null,
|
|
6869
|
+
apiKeyPresent: Boolean(keyHit),
|
|
6870
|
+
misconfigured: true,
|
|
6871
|
+
warning: `${modeSource}=http but no API URL is set (${keys.apiUrlKeys[0]}). Refusing to route to the API.`
|
|
6872
|
+
};
|
|
6873
|
+
}
|
|
6815
6874
|
if (!keyHit) {
|
|
6816
6875
|
return {
|
|
6817
6876
|
transport: "sqlite",
|
|
@@ -6823,7 +6882,7 @@ function resolveTransport(name, env = process.env) {
|
|
|
6823
6882
|
warning: `${modeSource}=http but no API key is set (${keys.apiKeyKeys[0]}). Refusing to route to the API.`
|
|
6824
6883
|
};
|
|
6825
6884
|
}
|
|
6826
|
-
const rawUrl = urlHit
|
|
6885
|
+
const rawUrl = urlHit.value;
|
|
6827
6886
|
let baseUrl;
|
|
6828
6887
|
try {
|
|
6829
6888
|
baseUrl = toV1BaseUrl(rawUrl);
|
|
@@ -7010,10 +7069,8 @@ function resolveStorageClient(name, env = process.env, fetchImpl) {
|
|
|
7010
7069
|
const transport = createHttpTransport({ name, baseUrl: resolution.baseUrl, apiKey, ...fetchImpl ? { fetchImpl } : {} });
|
|
7011
7070
|
return { transport: "http", client: createStorageClient(name, transport), resolution };
|
|
7012
7071
|
}
|
|
7013
|
-
var
|
|
7072
|
+
var HasnaHttpError, RETRY_STATUSES, IDEMPOTENT, defaultSleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
7014
7073
|
var init_client = __esm(() => {
|
|
7015
|
-
init_retired_deployment_modes();
|
|
7016
|
-
SERVER_BACKEND_VALUES = ["sqlite", "postgresql", "postgres"];
|
|
7017
7074
|
HasnaHttpError = class HasnaHttpError extends Error {
|
|
7018
7075
|
status;
|
|
7019
7076
|
method;
|
|
@@ -8229,6 +8286,7 @@ var init_mcp = __esm(async () => {
|
|
|
8229
8286
|
init_store();
|
|
8230
8287
|
init_transcriber();
|
|
8231
8288
|
init_enhancer();
|
|
8289
|
+
init_version();
|
|
8232
8290
|
init_machine();
|
|
8233
8291
|
config = loadConfig();
|
|
8234
8292
|
ensureDataDir(config);
|
|
@@ -8371,7 +8429,7 @@ async function startServer(port, options) {
|
|
|
8371
8429
|
}
|
|
8372
8430
|
var SECURITY_HEADERS, rateLimitMap, RATE_LIMIT_WINDOW_MS = 60000, RATE_LIMIT_MAX;
|
|
8373
8431
|
var init_serve = __esm(() => {
|
|
8374
|
-
|
|
8432
|
+
init_version();
|
|
8375
8433
|
init_v1();
|
|
8376
8434
|
init_openapi();
|
|
8377
8435
|
SECURITY_HEADERS = {
|
|
@@ -8385,6 +8443,7 @@ var init_serve = __esm(() => {
|
|
|
8385
8443
|
});
|
|
8386
8444
|
|
|
8387
8445
|
// src/server/index.ts
|
|
8446
|
+
init_version();
|
|
8388
8447
|
var DEFAULT_PORT = 8874;
|
|
8389
8448
|
function parsePort() {
|
|
8390
8449
|
const arg = process.argv.find((a) => a === "--port" || a.startsWith("--port="));
|
|
@@ -8421,8 +8480,7 @@ Commands:
|
|
|
8421
8480
|
migrate Apply the PostgreSQL schema, then exit. Idempotent.
|
|
8422
8481
|
|
|
8423
8482
|
Environment:
|
|
8424
|
-
|
|
8425
|
-
HASNA_RECORDINGS_DATABASE_URL PostgreSQL DSN (implies postgresql)
|
|
8483
|
+
HASNA_RECORDINGS_DATABASE_URL PostgreSQL DSN (present -> postgresql backend, else sqlite)
|
|
8426
8484
|
HASNA_RECORDINGS_API_SIGNING_KEY HMAC signing secret for API-key auth`);
|
|
8427
8485
|
}
|
|
8428
8486
|
async function runMigrate() {
|
|
@@ -8431,11 +8489,11 @@ async function runMigrate() {
|
|
|
8431
8489
|
getCloudPg: getCloudPg2,
|
|
8432
8490
|
migrateCloudSchema: migrateCloudSchema2,
|
|
8433
8491
|
pingCloudConnectivity: pingCloudConnectivity3,
|
|
8434
|
-
|
|
8492
|
+
resolveDatabaseUrl: resolveDatabaseUrl2
|
|
8435
8493
|
} = await Promise.resolve().then(() => (init_cloud(), exports_cloud));
|
|
8436
8494
|
const { assertCloudSchemaContract: assertCloudSchemaContract2 } = await Promise.resolve().then(() => (init_cloud_readiness(), exports_cloud_readiness));
|
|
8437
8495
|
const { runCloudMigration: runCloudMigration2 } = await Promise.resolve().then(() => (init_migrate_command(), exports_migrate_command));
|
|
8438
|
-
if (!
|
|
8496
|
+
if (!resolveDatabaseUrl2()) {
|
|
8439
8497
|
console.error("migrate: no database URL (HASNA_RECORDINGS_DATABASE_URL / RECORDINGS_DATABASE_URL / DATABASE_URL)");
|
|
8440
8498
|
process.exit(2);
|
|
8441
8499
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/server/serve.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/server/serve.ts"],"names":[],"mappings":"AAsBA,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAKnD,CAAC;AAyCF,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,cAAc,CAAC,EAAE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAClD,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACnC,QAAQ,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACzC;AAED,wBAAgB,UAAU,CAAC,OAAO,GAAE,iBAAsB,IAWtD,KAAK,OAAO,EACZ,QAAQ;IAAE,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;CAAE,KAC9D,OAAO,CAAC,QAAQ,CAAC,CAqFrB;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,CAqBnH"}
|
package/dist/storage.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { getStore, __resetStore, APP } from "./store.js";
|
|
2
2
|
export type { Store, RecordingStats, FeedbackInput } from "./store.js";
|
|
3
|
-
export { resolveStorageClient, resolveTransport, createHttpTransport, createStorageClient, toV1BaseUrl,
|
|
3
|
+
export { resolveStorageClient, resolveTransport, createHttpTransport, createStorageClient, toV1BaseUrl, HasnaHttpError, } from "./http/client.js";
|
|
4
4
|
export type { StorageClient, ClientStore, TransportKind, TransportResolution, HttpTransport, } from "./http/client.js";
|
|
5
5
|
//# sourceMappingURL=storage.d.ts.map
|
package/dist/storage.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACzD,YAAY,EAAE,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEvE,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,WAAW,EACX,
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACzD,YAAY,EAAE,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEvE,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,WAAW,EACX,cAAc,GACf,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,aAAa,EACb,WAAW,EACX,aAAa,EACb,mBAAmB,EACnB,aAAa,GACd,MAAM,kBAAkB,CAAC"}
|