haansi 0.1.29 → 0.1.30

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.
Files changed (2) hide show
  1. package/dist/haansi.js +1226 -197
  2. package/package.json +1 -1
package/dist/haansi.js CHANGED
@@ -34,12 +34,68 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
34
34
  ));
35
35
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
36
36
 
37
+ // ../../packages/@company/config/src/service-urls.ts
38
+ var SERVICE_URL_DEFAULTS, HAANSI_API_V1_BASE_URL;
39
+ var init_service_urls = __esm({
40
+ "../../packages/@company/config/src/service-urls.ts"() {
41
+ SERVICE_URL_DEFAULTS = Object.freeze({
42
+ haansiApiBaseUrl: "https://api.haansi.co",
43
+ localApiBaseUrl: "http://localhost:3000",
44
+ localWebAppUrl: "http://localhost:3001",
45
+ localDeliveryServiceUrl: "http://localhost:3200",
46
+ platformKnowledgeMcpUrl: "http://localhost:3300/mcp",
47
+ sessionSolutionsMcpUrl: "http://localhost:3301/mcp",
48
+ codeContextMcpUrl: "http://localhost:3302/mcp"
49
+ });
50
+ HAANSI_API_V1_BASE_URL = `${SERVICE_URL_DEFAULTS.haansiApiBaseUrl}/api/v1`;
51
+ }
52
+ });
53
+
54
+ // src/lib/paths.ts
55
+ function apiUrl() {
56
+ return process.env.HAANSI_API_URL ?? DEFAULT_API_URL;
57
+ }
58
+ function resolveToken() {
59
+ if (process.env.HAANSI_TOKEN) return process.env.HAANSI_TOKEN;
60
+ if ((0, import_node_fs.existsSync)(CREDENTIALS_FILE)) {
61
+ try {
62
+ const creds = JSON.parse((0, import_node_fs.readFileSync)(CREDENTIALS_FILE, "utf-8"));
63
+ if (typeof creds.token === "string" && creds.token) return creds.token;
64
+ } catch {
65
+ }
66
+ }
67
+ return null;
68
+ }
69
+ function resolveHaansiBin() {
70
+ try {
71
+ const binPath = (0, import_node_child_process.execSync)("which haansi", { encoding: "utf-8" }).trim();
72
+ if (binPath) return binPath;
73
+ } catch {
74
+ }
75
+ return "haansi";
76
+ }
77
+ var import_node_fs, import_node_path, import_node_os, import_node_child_process, DEFAULT_API_URL, HAANSI_DIR, CREDENTIALS_FILE, CONFIG_FILE;
78
+ var init_paths = __esm({
79
+ "src/lib/paths.ts"() {
80
+ "use strict";
81
+ import_node_fs = require("node:fs");
82
+ import_node_path = require("node:path");
83
+ import_node_os = require("node:os");
84
+ import_node_child_process = require("node:child_process");
85
+ init_service_urls();
86
+ DEFAULT_API_URL = SERVICE_URL_DEFAULTS.haansiApiBaseUrl;
87
+ HAANSI_DIR = (0, import_node_path.join)((0, import_node_os.homedir)(), ".haansi");
88
+ CREDENTIALS_FILE = (0, import_node_path.join)(HAANSI_DIR, "credentials.json");
89
+ CONFIG_FILE = (0, import_node_path.join)(HAANSI_DIR, "config.json");
90
+ }
91
+ });
92
+
37
93
  // package.json
38
94
  var require_package = __commonJS({
39
95
  "package.json"(exports2, module2) {
40
96
  module2.exports = {
41
97
  name: "haansi",
42
- version: "0.1.29",
98
+ version: "0.1.30",
43
99
  description: "Haansi CLI - Session collector and MCP server for Claude Code & OpenAI Codex",
44
100
  bin: {
45
101
  haansi: "./dist/haansi.js"
@@ -70,9 +126,9 @@ __export(auth_login_exports, {
70
126
  authLogin: () => authLogin
71
127
  });
72
128
  function openBrowser(url2) {
73
- const cmd = (0, import_node_os.platform)() === "darwin" ? "open" : (0, import_node_os.platform)() === "win32" ? "start" : "xdg-open";
129
+ const cmd = (0, import_node_os2.platform)() === "darwin" ? "open" : (0, import_node_os2.platform)() === "win32" ? "start" : "xdg-open";
74
130
  try {
75
- (0, import_node_child_process.exec)(`${cmd} ${JSON.stringify(url2)}`);
131
+ (0, import_node_child_process2.exec)(`${cmd} ${JSON.stringify(url2)}`);
76
132
  return true;
77
133
  } catch {
78
134
  return false;
@@ -82,7 +138,7 @@ function sleep(ms) {
82
138
  return new Promise((resolve4) => setTimeout(resolve4, ms));
83
139
  }
84
140
  async function authLogin() {
85
- const apiUrl2 = process.env.HAANSI_API_URL ?? DEFAULT_API_URL;
141
+ const apiUrl2 = apiUrl();
86
142
  console.log("Haansi CLI \u2014 Browser Login\n");
87
143
  const initiateRes = await fetch(`${apiUrl2}/api/v1/auth/extension/initiate`, {
88
144
  method: "POST",
@@ -156,9 +212,9 @@ If the browser didn't open, visit this URL:
156
212
  );
157
213
  }
158
214
  const { token: hskToken } = await tokenRes.json();
159
- (0, import_node_fs.mkdirSync)(HAANSI_DIR, { recursive: true });
160
- (0, import_node_fs.writeFileSync)(
161
- CREDENTIALS_FILE,
215
+ (0, import_node_fs2.mkdirSync)(HAANSI_DIR2, { recursive: true });
216
+ (0, import_node_fs2.writeFileSync)(
217
+ CREDENTIALS_FILE2,
162
218
  JSON.stringify({ token: hskToken }, null, 2),
163
219
  {
164
220
  encoding: "utf-8",
@@ -167,22 +223,22 @@ If the browser didn't open, visit this URL:
167
223
  );
168
224
  console.log(`
169
225
  Authenticated successfully${orgName ? ` (${orgName})` : ""}!`);
170
- console.log(`Token saved to ${CREDENTIALS_FILE}`);
226
+ console.log(`Token saved to ${CREDENTIALS_FILE2}`);
171
227
  console.log(
172
228
  "Run `haansi collect` to upload sessions or `haansi setup-mcp` to configure Claude Code."
173
229
  );
174
230
  }
175
- var import_node_child_process, import_node_fs, import_node_path, import_node_os, DEFAULT_API_URL, HAANSI_DIR, CREDENTIALS_FILE, POLL_INTERVAL_MS, TIMEOUT_MS;
231
+ var import_node_child_process2, import_node_fs2, import_node_path2, import_node_os2, HAANSI_DIR2, CREDENTIALS_FILE2, POLL_INTERVAL_MS, TIMEOUT_MS;
176
232
  var init_auth_login = __esm({
177
233
  "src/commands/auth-login.ts"() {
178
234
  "use strict";
179
- import_node_child_process = require("node:child_process");
180
- import_node_fs = require("node:fs");
181
- import_node_path = require("node:path");
182
- import_node_os = require("node:os");
183
- DEFAULT_API_URL = "https://api.haansi.co";
184
- HAANSI_DIR = (0, import_node_path.join)((0, import_node_os.homedir)(), ".haansi");
185
- CREDENTIALS_FILE = (0, import_node_path.join)(HAANSI_DIR, "credentials.json");
235
+ import_node_child_process2 = require("node:child_process");
236
+ import_node_fs2 = require("node:fs");
237
+ import_node_path2 = require("node:path");
238
+ import_node_os2 = require("node:os");
239
+ init_paths();
240
+ HAANSI_DIR2 = (0, import_node_path2.join)((0, import_node_os2.homedir)(), ".haansi");
241
+ CREDENTIALS_FILE2 = (0, import_node_path2.join)(HAANSI_DIR2, "credentials.json");
186
242
  POLL_INTERVAL_MS = 2e3;
187
243
  TIMEOUT_MS = 5 * 60 * 1e3;
188
244
  }
@@ -220,7 +276,7 @@ async function validateToken(token, apiUrl2) {
220
276
  }
221
277
  }
222
278
  async function init() {
223
- const apiUrl2 = process.env.HAANSI_API_URL ?? DEFAULT_API_URL2;
279
+ const apiUrl2 = apiUrl();
224
280
  console.log("Haansi CLI \u2014 Setup\n");
225
281
  console.log(
226
282
  "Tip: For interactive login, run `haansi auth login` to authenticate via browser.\n"
@@ -240,28 +296,28 @@ async function init() {
240
296
  }
241
297
  console.log("\nValidating token...");
242
298
  await validateToken(token, apiUrl2);
243
- (0, import_node_fs2.mkdirSync)(HAANSI_DIR2, { recursive: true });
244
- (0, import_node_fs2.writeFileSync)(CREDENTIALS_FILE2, JSON.stringify({ token }, null, 2), {
299
+ (0, import_node_fs3.mkdirSync)(HAANSI_DIR3, { recursive: true });
300
+ (0, import_node_fs3.writeFileSync)(CREDENTIALS_FILE3, JSON.stringify({ token }, null, 2), {
245
301
  encoding: "utf-8",
246
302
  mode: 384
247
303
  });
248
304
  console.log(`
249
- Token saved to ${CREDENTIALS_FILE2}`);
305
+ Token saved to ${CREDENTIALS_FILE3}`);
250
306
  console.log(
251
307
  "Run `haansi daemon` to start collecting or `haansi setup-mcp` to configure your coding agent(s) (Claude Code / Codex)."
252
308
  );
253
309
  }
254
- var readline, import_node_fs2, import_node_path2, import_node_os2, DEFAULT_API_URL2, HAANSI_DIR2, CREDENTIALS_FILE2;
310
+ var readline, import_node_fs3, import_node_path3, import_node_os3, HAANSI_DIR3, CREDENTIALS_FILE3;
255
311
  var init_init = __esm({
256
312
  "src/commands/init.ts"() {
257
313
  "use strict";
258
314
  readline = __toESM(require("node:readline"));
259
- import_node_fs2 = require("node:fs");
260
- import_node_path2 = require("node:path");
261
- import_node_os2 = require("node:os");
262
- DEFAULT_API_URL2 = "https://api.haansi.co";
263
- HAANSI_DIR2 = (0, import_node_path2.join)((0, import_node_os2.homedir)(), ".haansi");
264
- CREDENTIALS_FILE2 = (0, import_node_path2.join)(HAANSI_DIR2, "credentials.json");
315
+ import_node_fs3 = require("node:fs");
316
+ import_node_path3 = require("node:path");
317
+ import_node_os3 = require("node:os");
318
+ init_paths();
319
+ HAANSI_DIR3 = (0, import_node_path3.join)((0, import_node_os3.homedir)(), ".haansi");
320
+ CREDENTIALS_FILE3 = (0, import_node_path3.join)(HAANSI_DIR3, "credentials.json");
265
321
  }
266
322
  });
267
323
 
@@ -339,7 +395,7 @@ var require_main = __commonJS({
339
395
  var fs = require("fs");
340
396
  var path = require("path");
341
397
  var os = require("os");
342
- var crypto6 = require("crypto");
398
+ var crypto8 = require("crypto");
343
399
  var packageJson = require_package2();
344
400
  var version3 = packageJson.version;
345
401
  var LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;
@@ -558,7 +614,7 @@ var require_main = __commonJS({
558
614
  const authTag = ciphertext.subarray(-16);
559
615
  ciphertext = ciphertext.subarray(12, -16);
560
616
  try {
561
- const aesgcm = crypto6.createDecipheriv("aes-256-gcm", key, nonce);
617
+ const aesgcm = crypto8.createDecipheriv("aes-256-gcm", key, nonce);
562
618
  aesgcm.setAuthTag(authTag);
563
619
  return `${aesgcm.update(ciphertext)}${aesgcm.final()}`;
564
620
  } catch (error2) {
@@ -623,61 +679,1028 @@ var require_main = __commonJS({
623
679
  }
624
680
  });
625
681
 
626
- // ../service-capture/common/logger.ts
627
- function createLogger(service, level) {
628
- const logLevel = level ?? (process.env.LOG_LEVEL === "debug" ? 0 /* DEBUG */ : 1 /* INFO */);
629
- return new Logger(service, logLevel);
682
+ // ../../packages/@company/observability/node_modules/uuid/dist/esm-node/rng.js
683
+ function rng() {
684
+ if (poolPtr > rnds8Pool.length - 16) {
685
+ import_crypto.default.randomFillSync(rnds8Pool);
686
+ poolPtr = 0;
687
+ }
688
+ return rnds8Pool.slice(poolPtr, poolPtr += 16);
689
+ }
690
+ var import_crypto, rnds8Pool, poolPtr;
691
+ var init_rng = __esm({
692
+ "../../packages/@company/observability/node_modules/uuid/dist/esm-node/rng.js"() {
693
+ import_crypto = __toESM(require("crypto"));
694
+ rnds8Pool = new Uint8Array(256);
695
+ poolPtr = rnds8Pool.length;
696
+ }
697
+ });
698
+
699
+ // ../../packages/@company/observability/node_modules/uuid/dist/esm-node/stringify.js
700
+ function unsafeStringify(arr, offset = 0) {
701
+ return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];
702
+ }
703
+ var byteToHex;
704
+ var init_stringify = __esm({
705
+ "../../packages/@company/observability/node_modules/uuid/dist/esm-node/stringify.js"() {
706
+ byteToHex = [];
707
+ for (let i = 0; i < 256; ++i) {
708
+ byteToHex.push((i + 256).toString(16).slice(1));
709
+ }
710
+ }
711
+ });
712
+
713
+ // ../../packages/@company/observability/node_modules/uuid/dist/esm-node/native.js
714
+ var import_crypto2, native_default;
715
+ var init_native = __esm({
716
+ "../../packages/@company/observability/node_modules/uuid/dist/esm-node/native.js"() {
717
+ import_crypto2 = __toESM(require("crypto"));
718
+ native_default = {
719
+ randomUUID: import_crypto2.default.randomUUID
720
+ };
721
+ }
722
+ });
723
+
724
+ // ../../packages/@company/observability/node_modules/uuid/dist/esm-node/v4.js
725
+ function v4(options, buf, offset) {
726
+ if (native_default.randomUUID && !buf && !options) {
727
+ return native_default.randomUUID();
728
+ }
729
+ options = options || {};
730
+ const rnds = options.random || (options.rng || rng)();
731
+ rnds[6] = rnds[6] & 15 | 64;
732
+ rnds[8] = rnds[8] & 63 | 128;
733
+ if (buf) {
734
+ offset = offset || 0;
735
+ for (let i = 0; i < 16; ++i) {
736
+ buf[offset + i] = rnds[i];
737
+ }
738
+ return buf;
739
+ }
740
+ return unsafeStringify(rnds);
741
+ }
742
+ var v4_default;
743
+ var init_v4 = __esm({
744
+ "../../packages/@company/observability/node_modules/uuid/dist/esm-node/v4.js"() {
745
+ init_native();
746
+ init_rng();
747
+ init_stringify();
748
+ v4_default = v4;
749
+ }
750
+ });
751
+
752
+ // ../../packages/@company/observability/node_modules/uuid/dist/esm-node/index.js
753
+ var init_esm_node = __esm({
754
+ "../../packages/@company/observability/node_modules/uuid/dist/esm-node/index.js"() {
755
+ init_v4();
756
+ }
757
+ });
758
+
759
+ // ../../packages/@company/observability/src/types.ts
760
+ var init_types = __esm({
761
+ "../../packages/@company/observability/src/types.ts"() {
762
+ "use strict";
763
+ }
764
+ });
765
+
766
+ // ../../packages/@company/cloud/src/provider-registry.ts
767
+ var ProviderRegistry, cloudRegistry;
768
+ var init_provider_registry = __esm({
769
+ "../../packages/@company/cloud/src/provider-registry.ts"() {
770
+ "use strict";
771
+ ProviderRegistry = class {
772
+ _provider = null;
773
+ _config = null;
774
+ _storage = null;
775
+ _loggerBackend = null;
776
+ _metricsBackend = null;
777
+ _messageQueueParser = null;
778
+ _secretsManager = null;
779
+ _databaseSslResolver = null;
780
+ get provider() {
781
+ return this._provider;
782
+ }
783
+ get config() {
784
+ return this._config;
785
+ }
786
+ register(config6) {
787
+ this._provider = config6.provider;
788
+ this._config = config6;
789
+ }
790
+ // ── Setters (called by cloud-gcp / cloud-aws register functions) ──────────
791
+ setStorage(client) {
792
+ this._storage = client;
793
+ }
794
+ setLoggerBackend(backend) {
795
+ this._loggerBackend = backend;
796
+ }
797
+ setMetricsBackend(backend) {
798
+ this._metricsBackend = backend;
799
+ }
800
+ setMessageQueueParser(parser) {
801
+ this._messageQueueParser = parser;
802
+ }
803
+ setSecretsManager(manager) {
804
+ this._secretsManager = manager;
805
+ }
806
+ setDatabaseSslResolver(resolver) {
807
+ this._databaseSslResolver = resolver;
808
+ }
809
+ // ── Getters (called by consumers) ─────────────────────────────────────────
810
+ getStorage() {
811
+ if (!this._storage) {
812
+ throw new Error(
813
+ "No storage client registered. Call bootstrapCloudProvider() at startup."
814
+ );
815
+ }
816
+ return this._storage;
817
+ }
818
+ getLoggerBackend() {
819
+ return this._loggerBackend;
820
+ }
821
+ getMetricsBackend() {
822
+ return this._metricsBackend;
823
+ }
824
+ getMessageQueueParser() {
825
+ return this._messageQueueParser;
826
+ }
827
+ getSecretsManager() {
828
+ if (!this._secretsManager) {
829
+ throw new Error(
830
+ "No secrets manager registered. Call bootstrapCloudProvider() at startup."
831
+ );
832
+ }
833
+ return this._secretsManager;
834
+ }
835
+ getDatabaseSslConfig(connectionString) {
836
+ if (!this._databaseSslResolver) {
837
+ return {
838
+ ssl: process.env.NODE_ENV === "production" ? { rejectUnauthorized: true } : false
839
+ };
840
+ }
841
+ return this._databaseSslResolver(connectionString);
842
+ }
843
+ /**
844
+ * Reset all registrations. Primarily for testing.
845
+ */
846
+ reset() {
847
+ this._provider = null;
848
+ this._config = null;
849
+ this._storage = null;
850
+ this._loggerBackend = null;
851
+ this._metricsBackend = null;
852
+ this._messageQueueParser = null;
853
+ this._secretsManager = null;
854
+ this._databaseSslResolver = null;
855
+ }
856
+ };
857
+ cloudRegistry = new ProviderRegistry();
858
+ }
859
+ });
860
+
861
+ // ../../packages/@company/cloud/src/bootstrap.ts
862
+ function bootstrapCloudProvider(override) {
863
+ const provider = override ?? process.env.CLOUD_PROVIDER;
864
+ if (!provider || provider === "local") {
865
+ return;
866
+ }
867
+ const pkg = PROVIDER_PACKAGES[provider];
868
+ if (!pkg) {
869
+ throw new Error(
870
+ `Unknown CLOUD_PROVIDER "${provider}". Supported: ${Object.keys(PROVIDER_PACKAGES).join(", ")}, local`
871
+ );
872
+ }
873
+ try {
874
+ const mod = _require(pkg);
875
+ const registerFnName = `register${provider.charAt(0).toUpperCase() + provider.slice(1)}Provider`;
876
+ const registerFn = mod[registerFnName] ?? mod.default;
877
+ if (typeof registerFn !== "function") {
878
+ throw new Error(
879
+ `${pkg} does not export ${registerFnName}() or a default registration function`
880
+ );
881
+ }
882
+ registerFn();
883
+ } catch (err) {
884
+ if (err.code === "ERR_MODULE_NOT_FOUND" || err.code === "MODULE_NOT_FOUND") {
885
+ throw new Error(
886
+ `CLOUD_PROVIDER is "${provider}" but ${pkg} is not installed. Add it to your service's package.json dependencies.`
887
+ );
888
+ }
889
+ throw err;
890
+ }
891
+ }
892
+ var PROVIDER_PACKAGES, _require;
893
+ var init_bootstrap = __esm({
894
+ "../../packages/@company/cloud/src/bootstrap.ts"() {
895
+ "use strict";
896
+ PROVIDER_PACKAGES = {
897
+ gcp: "@company/cloud-gcp",
898
+ aws: "@company/cloud-aws"
899
+ };
900
+ _require = require;
901
+ }
902
+ });
903
+
904
+ // ../../packages/@company/cloud/src/storage-uri.ts
905
+ function storageUri(bucket, path) {
906
+ const provider = cloudRegistry.provider;
907
+ const scheme = provider === "aws" ? "s3" : provider === "gcp" ? "gs" : "file";
908
+ return `${scheme}://${bucket}/${path}`;
909
+ }
910
+ var init_storage_uri = __esm({
911
+ "../../packages/@company/cloud/src/storage-uri.ts"() {
912
+ "use strict";
913
+ init_provider_registry();
914
+ }
915
+ });
916
+
917
+ // ../../packages/@company/cloud/src/index.ts
918
+ var src_exports = {};
919
+ __export(src_exports, {
920
+ ProviderRegistry: () => ProviderRegistry,
921
+ bootstrapCloudProvider: () => bootstrapCloudProvider,
922
+ cloudRegistry: () => cloudRegistry,
923
+ storageUri: () => storageUri
924
+ });
925
+ var init_src = __esm({
926
+ "../../packages/@company/cloud/src/index.ts"() {
927
+ init_provider_registry();
928
+ init_bootstrap();
929
+ init_storage_uri();
930
+ }
931
+ });
932
+
933
+ // ../../packages/@company/observability/src/logger.ts
934
+ function getCloudBackend() {
935
+ if (_cloudBackend === void 0) {
936
+ try {
937
+ const { cloudRegistry: cloudRegistry2 } = (
938
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
939
+ (init_src(), __toCommonJS(src_exports))
940
+ );
941
+ _cloudBackend = cloudRegistry2.getLoggerBackend();
942
+ } catch {
943
+ _cloudBackend = null;
944
+ }
945
+ }
946
+ return _cloudBackend;
947
+ }
948
+ function normKey(key) {
949
+ return key.toLowerCase().replace(/[_\-]/g, "");
950
+ }
951
+ function isSensitiveKey(key) {
952
+ return SENSITIVE_KEY_RE.test(normKey(key));
630
953
  }
631
- var Logger;
954
+ function sanitizeMetadata(obj, depth = 0) {
955
+ if (depth > 5) return obj;
956
+ const result = {};
957
+ for (const [k, v] of Object.entries(obj)) {
958
+ if (isSensitiveKey(k)) {
959
+ result[k] = "[REDACTED]";
960
+ } else if (v !== null && typeof v === "object" && !Array.isArray(v) && !(v instanceof Date)) {
961
+ result[k] = sanitizeMetadata(v, depth + 1);
962
+ } else {
963
+ result[k] = v;
964
+ }
965
+ }
966
+ return result;
967
+ }
968
+ function normalizeErrorMetadata(error2, metadata) {
969
+ if (!error2) return metadata;
970
+ if (error2 instanceof Error) {
971
+ return {
972
+ error: {
973
+ message: error2.message,
974
+ name: error2.name,
975
+ // Omit stack in production — it exposes internal file paths and code structure
976
+ ...process.env.NODE_ENV !== "production" && {
977
+ stack: error2.stack
978
+ }
979
+ },
980
+ ...metadata
981
+ };
982
+ }
983
+ if (typeof error2 === "object" && error2 !== null && !Array.isArray(error2)) {
984
+ return { ...error2, ...metadata };
985
+ }
986
+ return { error: String(error2), ...metadata };
987
+ }
988
+ function createLogger(serviceName, projectId) {
989
+ return new StructuredLogger(
990
+ serviceName,
991
+ projectId === null ? void 0 : projectId || process.env.GCP_PROJECT_ID
992
+ );
993
+ }
994
+ var import_async_hooks, _cloudBackend, SENSITIVE_KEY_RE, traceStorage, StructuredLogger, TraceContext;
632
995
  var init_logger = __esm({
633
- "../service-capture/common/logger.ts"() {
996
+ "../../packages/@company/observability/src/logger.ts"() {
634
997
  "use strict";
635
- Logger = class {
636
- level;
637
- service;
638
- constructor(service, level = 1 /* INFO */) {
639
- this.service = service;
640
- this.level = level;
998
+ import_async_hooks = require("async_hooks");
999
+ init_esm_node();
1000
+ init_types();
1001
+ SENSITIVE_KEY_RE = /^(password|passwd|secret|token|apikey|authorization|auth|authtoken|authkey|credentials?|connectionstring|privatekey)$/;
1002
+ traceStorage = new import_async_hooks.AsyncLocalStorage();
1003
+ StructuredLogger = class {
1004
+ serviceName;
1005
+ isLocal;
1006
+ projectId;
1007
+ constructor(serviceName, projectId) {
1008
+ this.serviceName = serviceName;
1009
+ this.projectId = projectId ?? void 0;
1010
+ this.isLocal = process.env.NODE_ENV === "development" || !this.projectId;
1011
+ if (!this.isLocal && !getCloudBackend()) {
1012
+ console.error(
1013
+ `[StructuredLogger] WARNING: No cloud logger backend registered for service "${serviceName}". Falling back to console logging. Register a cloud provider to enable cloud logging.`
1014
+ );
1015
+ }
641
1016
  }
642
- formatMessage(level, message, context) {
643
- const timestamp = (/* @__PURE__ */ new Date()).toISOString();
644
- const contextStr = context ? ` ${JSON.stringify(context)}` : "";
645
- return `[${timestamp}] [${this.service}] [${level}] ${message}${contextStr}`;
1017
+ /**
1018
+ * Write a structured log entry. Sanitises metadata before writing so that
1019
+ * PII / secrets never reach cloud logging.
1020
+ */
1021
+ async write(entry) {
1022
+ const logEntry = {
1023
+ ...entry,
1024
+ serviceName: this.serviceName,
1025
+ timestamp: entry.timestamp || /* @__PURE__ */ new Date(),
1026
+ metadata: entry.metadata ? sanitizeMetadata(entry.metadata) : void 0
1027
+ };
1028
+ const backend = getCloudBackend();
1029
+ if (this.isLocal || !backend) {
1030
+ this.consoleLog(logEntry);
1031
+ } else {
1032
+ try {
1033
+ await backend.writeLog({
1034
+ severity: logEntry.severity,
1035
+ message: logEntry.message,
1036
+ timestamp: logEntry.timestamp,
1037
+ traceId: logEntry.traceId,
1038
+ spanId: logEntry.spanId,
1039
+ userId: logEntry.userId,
1040
+ organizationId: logEntry.organizationId,
1041
+ serviceName: logEntry.serviceName,
1042
+ metadata: logEntry.metadata
1043
+ });
1044
+ } catch (e) {
1045
+ console.error("[StructuredLogger] Cloud Logging write failed:", e);
1046
+ }
1047
+ }
646
1048
  }
647
- debug(message, context) {
648
- if (this.level <= 0 /* DEBUG */) {
649
- console.error(this.formatMessage("DEBUG", message, context));
1049
+ /**
1050
+ * Console logging for local development
1051
+ */
1052
+ consoleLog(entry) {
1053
+ const timestamp = entry.timestamp?.toISOString() || (/* @__PURE__ */ new Date()).toISOString();
1054
+ const traceInfo = entry.traceId ? ` [trace: ${entry.traceId.slice(0, 8)}]` : "";
1055
+ const orgInfo = entry.organizationId ? ` [org: ${entry.organizationId.slice(0, 8)}]` : "";
1056
+ const prefix = `[${timestamp}] [${entry.severity}] [${this.serviceName}]${traceInfo}${orgInfo}`;
1057
+ const message = `${prefix} ${entry.message}`;
1058
+ const metadata = entry.metadata ? `
1059
+ ${JSON.stringify(entry.metadata, null, 2)}` : "";
1060
+ switch (entry.severity) {
1061
+ case "ERROR" /* ERROR */:
1062
+ case "CRITICAL" /* CRITICAL */:
1063
+ case "ALERT" /* ALERT */:
1064
+ case "EMERGENCY" /* EMERGENCY */:
1065
+ console.error(message + metadata);
1066
+ break;
1067
+ case "WARNING" /* WARNING */:
1068
+ console.warn(message + metadata);
1069
+ break;
1070
+ default:
1071
+ console.log(message + metadata);
650
1072
  }
651
1073
  }
652
- info(message, context) {
653
- if (this.level <= 1 /* INFO */) {
654
- console.error(this.formatMessage("INFO", message, context));
1074
+ // ─── Convenience level methods ──────────────────────────────────────────────
1075
+ async debug(message, metadata, context) {
1076
+ await this.write({
1077
+ severity: "DEBUG" /* DEBUG */,
1078
+ message,
1079
+ metadata,
1080
+ ...context
1081
+ });
1082
+ }
1083
+ async info(message, metadata, context) {
1084
+ await this.write({
1085
+ severity: "INFO" /* INFO */,
1086
+ message,
1087
+ metadata,
1088
+ ...context
1089
+ });
1090
+ }
1091
+ async notice(message, metadata, context) {
1092
+ await this.write({
1093
+ severity: "NOTICE" /* NOTICE */,
1094
+ message,
1095
+ metadata,
1096
+ ...context
1097
+ });
1098
+ }
1099
+ async warning(message, metadata, context) {
1100
+ await this.write({
1101
+ severity: "WARNING" /* WARNING */,
1102
+ message,
1103
+ metadata,
1104
+ ...context
1105
+ });
1106
+ }
1107
+ async warn(message, metadata, context) {
1108
+ await this.warning(message, metadata, context);
1109
+ }
1110
+ async error(message, error2, metadata, context) {
1111
+ const errorMetadata = normalizeErrorMetadata(error2, metadata);
1112
+ await this.write({
1113
+ severity: "ERROR" /* ERROR */,
1114
+ message,
1115
+ metadata: errorMetadata,
1116
+ ...context
1117
+ });
1118
+ }
1119
+ async critical(message, error2, metadata, context) {
1120
+ const errorMetadata = normalizeErrorMetadata(error2, metadata);
1121
+ await this.write({
1122
+ severity: "CRITICAL" /* CRITICAL */,
1123
+ message,
1124
+ metadata: errorMetadata,
1125
+ ...context
1126
+ });
1127
+ }
1128
+ };
1129
+ TraceContext = class {
1130
+ static generateTraceId() {
1131
+ return v4_default();
1132
+ }
1133
+ static generateSpanId() {
1134
+ return v4_default().slice(0, 16);
1135
+ }
1136
+ /**
1137
+ * Return the trace IDs for the current async execution context.
1138
+ * Returns { traceId: null, spanId: null } when called outside any trace context.
1139
+ */
1140
+ static getTrace() {
1141
+ const store = traceStorage.getStore();
1142
+ return {
1143
+ traceId: store?.traceId ?? null,
1144
+ spanId: store?.spanId ?? null
1145
+ };
1146
+ }
1147
+ /**
1148
+ * Run fn inside a scoped trace context. All async continuations started
1149
+ * within fn (awaits, Promise chains, timer callbacks) automatically inherit
1150
+ * this context — this is the correct way to scope a single HTTP request.
1151
+ *
1152
+ * Used by traceMiddleware: TraceContext.runInContext(traceId, spanId, next)
1153
+ */
1154
+ static runInContext(traceId, spanId, fn) {
1155
+ return traceStorage.run({ traceId, spanId }, fn);
1156
+ }
1157
+ /**
1158
+ * Run an async function with a new (or supplied) trace context.
1159
+ * Preferred API for background jobs, workers, and test isolation.
1160
+ */
1161
+ static async runWithTrace(fn, traceId) {
1162
+ const id = traceId || this.generateTraceId();
1163
+ const spanId = this.generateSpanId();
1164
+ return traceStorage.run({ traceId: id, spanId }, fn);
1165
+ }
1166
+ /**
1167
+ * @deprecated No-op. AsyncLocalStorage replaced process-global static fields.
1168
+ * Use `TraceContext.runWithTrace(fn)` for background jobs or rely on the
1169
+ * traceMiddleware (which calls runInContext automatically) for HTTP requests.
1170
+ */
1171
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1172
+ static setTrace(_traceId, _spanId) {
1173
+ }
1174
+ /**
1175
+ * @deprecated No-op — AsyncLocalStorage context is automatically scoped.
1176
+ */
1177
+ static clear() {
1178
+ }
1179
+ };
1180
+ }
1181
+ });
1182
+
1183
+ // ../../packages/@company/observability/src/metrics.ts
1184
+ function getCloudBackend2() {
1185
+ if (_cloudBackend2 === void 0) {
1186
+ try {
1187
+ const { cloudRegistry: cloudRegistry2 } = (
1188
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
1189
+ (init_src(), __toCommonJS(src_exports))
1190
+ );
1191
+ _cloudBackend2 = cloudRegistry2.getMetricsBackend();
1192
+ } catch {
1193
+ _cloudBackend2 = null;
1194
+ }
1195
+ }
1196
+ return _cloudBackend2;
1197
+ }
1198
+ var _cloudBackend2, MetricsService;
1199
+ var init_metrics = __esm({
1200
+ "../../packages/@company/observability/src/metrics.ts"() {
1201
+ "use strict";
1202
+ init_types();
1203
+ MetricsService = class {
1204
+ projectId;
1205
+ serviceName;
1206
+ isLocal;
1207
+ constructor(serviceName, projectId) {
1208
+ this.serviceName = serviceName;
1209
+ this.projectId = projectId === null ? "" : projectId || process.env.GCP_PROJECT_ID || "";
1210
+ this.isLocal = process.env.NODE_ENV === "development" || !this.projectId;
1211
+ if (!this.isLocal && !getCloudBackend2()) {
1212
+ console.error(
1213
+ `[MetricsService] WARNING: No cloud metrics backend registered for service "${serviceName}". Metrics will be logged to console only. Register a cloud provider to enable cloud metrics.`
1214
+ );
655
1215
  }
656
1216
  }
657
- warn(message, context) {
658
- if (this.level <= 2 /* WARN */) {
659
- console.warn(this.formatMessage("WARN", message, context));
1217
+ /**
1218
+ * Record a custom metric
1219
+ */
1220
+ async recordMetric(metric) {
1221
+ if (this.isLocal) {
1222
+ console.log("[METRIC]", {
1223
+ name: metric.name,
1224
+ value: metric.value,
1225
+ type: metric.type,
1226
+ labels: metric.labels,
1227
+ unit: metric.unit
1228
+ });
1229
+ return;
1230
+ }
1231
+ const backend = getCloudBackend2();
1232
+ if (!backend) {
1233
+ console.warn("Metrics backend not initialized");
1234
+ return;
1235
+ }
1236
+ try {
1237
+ await backend.writeMetric({
1238
+ name: metric.name,
1239
+ value: metric.value,
1240
+ type: metric.type,
1241
+ labels: metric.labels,
1242
+ timestamp: metric.timestamp,
1243
+ unit: metric.unit,
1244
+ serviceName: this.serviceName
1245
+ });
1246
+ } catch (error2) {
1247
+ console.error("Failed to record metric:", error2);
660
1248
  }
661
1249
  }
662
- error(message, error2, context) {
663
- if (this.level <= 3 /* ERROR */) {
664
- const errorContext = {
665
- ...context,
666
- ...error2 instanceof Error ? { error: error2.message, stack: error2.stack } : { error: String(error2) }
667
- };
668
- console.error(this.formatMessage("ERROR", message, errorContext));
1250
+ /**
1251
+ * Record API request metrics
1252
+ */
1253
+ async recordAPICall(metrics) {
1254
+ await this.recordMetric({
1255
+ name: "api/requests_total",
1256
+ value: 1,
1257
+ type: "COUNTER" /* COUNTER */,
1258
+ labels: {
1259
+ endpoint: metrics.endpoint,
1260
+ method: metrics.method,
1261
+ status_code: metrics.statusCode.toString(),
1262
+ organization_id: metrics.organizationId || "unknown"
1263
+ }
1264
+ });
1265
+ await this.recordMetric({
1266
+ name: "api/request_duration_ms",
1267
+ value: metrics.duration,
1268
+ type: "HISTOGRAM" /* HISTOGRAM */,
1269
+ labels: {
1270
+ endpoint: metrics.endpoint,
1271
+ method: metrics.method
1272
+ },
1273
+ unit: "ms"
1274
+ });
1275
+ if (metrics.statusCode >= 400) {
1276
+ await this.recordMetric({
1277
+ name: "api/errors_total",
1278
+ value: 1,
1279
+ type: "COUNTER" /* COUNTER */,
1280
+ labels: {
1281
+ endpoint: metrics.endpoint,
1282
+ method: metrics.method,
1283
+ status_code: metrics.statusCode.toString(),
1284
+ organization_id: metrics.organizationId || "unknown"
1285
+ }
1286
+ });
669
1287
  }
670
1288
  }
671
- setLevel(level) {
672
- this.level = level;
1289
+ /**
1290
+ * Record LLM usage metrics
1291
+ */
1292
+ async recordLLMCall(metrics) {
1293
+ await this.recordMetric({
1294
+ name: "llm/calls_total",
1295
+ value: 1,
1296
+ type: "COUNTER" /* COUNTER */,
1297
+ labels: {
1298
+ model: metrics.model,
1299
+ success: metrics.success.toString(),
1300
+ organization_id: metrics.organizationId || "unknown"
1301
+ }
1302
+ });
1303
+ await this.recordMetric({
1304
+ name: "llm/tokens_total",
1305
+ value: metrics.totalTokens,
1306
+ type: "COUNTER" /* COUNTER */,
1307
+ labels: {
1308
+ model: metrics.model,
1309
+ type: "total",
1310
+ organization_id: metrics.organizationId || "unknown"
1311
+ }
1312
+ });
1313
+ await this.recordMetric({
1314
+ name: "llm/tokens_total",
1315
+ value: metrics.inputTokens,
1316
+ type: "COUNTER" /* COUNTER */,
1317
+ labels: {
1318
+ model: metrics.model,
1319
+ type: "input",
1320
+ organization_id: metrics.organizationId || "unknown"
1321
+ }
1322
+ });
1323
+ await this.recordMetric({
1324
+ name: "llm/tokens_total",
1325
+ value: metrics.outputTokens,
1326
+ type: "COUNTER" /* COUNTER */,
1327
+ labels: {
1328
+ model: metrics.model,
1329
+ type: "output",
1330
+ organization_id: metrics.organizationId || "unknown"
1331
+ }
1332
+ });
1333
+ await this.recordMetric({
1334
+ name: "llm/request_duration_ms",
1335
+ value: metrics.duration,
1336
+ type: "HISTOGRAM" /* HISTOGRAM */,
1337
+ labels: {
1338
+ model: metrics.model
1339
+ },
1340
+ unit: "ms"
1341
+ });
1342
+ if (!metrics.success) {
1343
+ await this.recordMetric({
1344
+ name: "llm/errors_total",
1345
+ value: 1,
1346
+ type: "COUNTER" /* COUNTER */,
1347
+ labels: {
1348
+ model: metrics.model,
1349
+ error_type: metrics.error || "unknown"
1350
+ }
1351
+ });
1352
+ }
1353
+ }
1354
+ /**
1355
+ * Record data capture metrics
1356
+ */
1357
+ async recordDataCapture(metrics) {
1358
+ await this.recordMetric({
1359
+ name: "data_capture/operations_total",
1360
+ value: 1,
1361
+ type: "COUNTER" /* COUNTER */,
1362
+ labels: {
1363
+ integration: metrics.integration,
1364
+ operation: metrics.operation,
1365
+ success: metrics.success.toString()
1366
+ }
1367
+ });
1368
+ await this.recordMetric({
1369
+ name: "data_capture/records_processed",
1370
+ value: metrics.recordsProcessed,
1371
+ type: "COUNTER" /* COUNTER */,
1372
+ labels: {
1373
+ integration: metrics.integration,
1374
+ operation: metrics.operation
1375
+ }
1376
+ });
1377
+ await this.recordMetric({
1378
+ name: "data_capture/duration_ms",
1379
+ value: metrics.duration,
1380
+ type: "HISTOGRAM" /* HISTOGRAM */,
1381
+ labels: {
1382
+ integration: metrics.integration,
1383
+ operation: metrics.operation
1384
+ },
1385
+ unit: "ms"
1386
+ });
1387
+ if (!metrics.success) {
1388
+ await this.recordMetric({
1389
+ name: "data_capture/errors_total",
1390
+ value: 1,
1391
+ type: "COUNTER" /* COUNTER */,
1392
+ labels: {
1393
+ integration: metrics.integration,
1394
+ operation: metrics.operation,
1395
+ error_type: metrics.error || "unknown"
1396
+ }
1397
+ });
1398
+ }
1399
+ }
1400
+ /**
1401
+ * Record usage metrics for billing/quota tracking
1402
+ */
1403
+ async recordUsage(metrics) {
1404
+ await this.recordMetric({
1405
+ name: "usage/api_calls",
1406
+ value: metrics.apiCalls,
1407
+ type: "GAUGE" /* GAUGE */,
1408
+ labels: {
1409
+ organization_id: metrics.organizationId
1410
+ },
1411
+ timestamp: metrics.timestamp
1412
+ });
1413
+ await this.recordMetric({
1414
+ name: "usage/llm_tokens",
1415
+ value: metrics.llmTokens,
1416
+ type: "GAUGE" /* GAUGE */,
1417
+ labels: {
1418
+ organization_id: metrics.organizationId
1419
+ },
1420
+ timestamp: metrics.timestamp
1421
+ });
1422
+ await this.recordMetric({
1423
+ name: "usage/storage_bytes",
1424
+ value: metrics.storageBytes,
1425
+ type: "GAUGE" /* GAUGE */,
1426
+ labels: {
1427
+ organization_id: metrics.organizationId
1428
+ },
1429
+ unit: "bytes",
1430
+ timestamp: metrics.timestamp
1431
+ });
1432
+ }
1433
+ /**
1434
+ * Record custom business metric
1435
+ */
1436
+ async recordCounter(name, value = 1, labels) {
1437
+ await this.recordMetric({
1438
+ name,
1439
+ value,
1440
+ type: "COUNTER" /* COUNTER */,
1441
+ labels
1442
+ });
1443
+ }
1444
+ async recordGauge(name, value, labels) {
1445
+ await this.recordMetric({
1446
+ name,
1447
+ value,
1448
+ type: "GAUGE" /* GAUGE */,
1449
+ labels
1450
+ });
1451
+ }
1452
+ async recordHistogram(name, value, labels, unit) {
1453
+ await this.recordMetric({
1454
+ name,
1455
+ value,
1456
+ type: "HISTOGRAM" /* HISTOGRAM */,
1457
+ labels,
1458
+ unit
1459
+ });
673
1460
  }
674
1461
  };
675
1462
  }
676
1463
  });
677
1464
 
1465
+ // ../../packages/@company/observability/src/observability-service.ts
1466
+ function createObservabilityService(serviceName, projectId) {
1467
+ return new ObservabilityService(serviceName, projectId);
1468
+ }
1469
+ var ObservabilityService;
1470
+ var init_observability_service = __esm({
1471
+ "../../packages/@company/observability/src/observability-service.ts"() {
1472
+ "use strict";
1473
+ init_logger();
1474
+ init_metrics();
1475
+ init_types();
1476
+ ObservabilityService = class {
1477
+ logger;
1478
+ metrics;
1479
+ serviceName;
1480
+ constructor(serviceName, projectId) {
1481
+ this.serviceName = serviceName;
1482
+ this.logger = new StructuredLogger(serviceName, projectId);
1483
+ this.metrics = new MetricsService(serviceName, projectId);
1484
+ }
1485
+ /**
1486
+ * Track API request with both logging and metrics
1487
+ */
1488
+ async trackAPIRequest(metrics, error2) {
1489
+ await this.metrics.recordAPICall(metrics);
1490
+ const { traceId, spanId } = TraceContext.getTrace();
1491
+ const severity = metrics.statusCode >= 500 ? "ERROR" /* ERROR */ : metrics.statusCode >= 400 ? "WARNING" /* WARNING */ : "INFO" /* INFO */;
1492
+ await this.logger.write({
1493
+ severity,
1494
+ message: `${metrics.method} ${metrics.endpoint} ${metrics.statusCode} ${metrics.duration}ms`,
1495
+ traceId: traceId || void 0,
1496
+ spanId: spanId || void 0,
1497
+ organizationId: metrics.organizationId,
1498
+ userId: metrics.userId,
1499
+ metadata: {
1500
+ endpoint: metrics.endpoint,
1501
+ method: metrics.method,
1502
+ statusCode: metrics.statusCode,
1503
+ duration: metrics.duration,
1504
+ error: error2 ? {
1505
+ message: error2.message,
1506
+ ...process.env.NODE_ENV !== "production" && {
1507
+ stack: error2.stack
1508
+ }
1509
+ } : void 0
1510
+ }
1511
+ });
1512
+ }
1513
+ /**
1514
+ * Track LLM call with both logging and metrics
1515
+ */
1516
+ async trackLLMCall(metrics, error2) {
1517
+ await this.metrics.recordLLMCall(metrics);
1518
+ const { traceId, spanId } = TraceContext.getTrace();
1519
+ const severity = metrics.success ? "INFO" /* INFO */ : "ERROR" /* ERROR */;
1520
+ await this.logger.write({
1521
+ severity,
1522
+ message: `LLM call to ${metrics.model}: ${metrics.totalTokens} tokens in ${metrics.duration}ms`,
1523
+ traceId: traceId || void 0,
1524
+ spanId: spanId || void 0,
1525
+ organizationId: metrics.organizationId,
1526
+ metadata: {
1527
+ model: metrics.model,
1528
+ inputTokens: metrics.inputTokens,
1529
+ outputTokens: metrics.outputTokens,
1530
+ totalTokens: metrics.totalTokens,
1531
+ duration: metrics.duration,
1532
+ success: metrics.success,
1533
+ error: error2 ? {
1534
+ message: error2.message,
1535
+ ...process.env.NODE_ENV !== "production" && {
1536
+ stack: error2.stack
1537
+ }
1538
+ } : void 0
1539
+ }
1540
+ });
1541
+ }
1542
+ /**
1543
+ * Track data capture operation
1544
+ */
1545
+ async trackDataCapture(metrics, error2) {
1546
+ await this.metrics.recordDataCapture(metrics);
1547
+ const { traceId, spanId } = TraceContext.getTrace();
1548
+ const severity = metrics.success ? "INFO" /* INFO */ : "ERROR" /* ERROR */;
1549
+ await this.logger.write({
1550
+ severity,
1551
+ message: `${metrics.integration} ${metrics.operation}: ${metrics.recordsProcessed} records in ${metrics.duration}ms`,
1552
+ traceId: traceId || void 0,
1553
+ spanId: spanId || void 0,
1554
+ metadata: {
1555
+ integration: metrics.integration,
1556
+ operation: metrics.operation,
1557
+ recordsProcessed: metrics.recordsProcessed,
1558
+ duration: metrics.duration,
1559
+ success: metrics.success,
1560
+ error: error2 ? {
1561
+ message: error2.message,
1562
+ ...process.env.NODE_ENV !== "production" && {
1563
+ stack: error2.stack
1564
+ }
1565
+ } : void 0
1566
+ }
1567
+ });
1568
+ }
1569
+ /**
1570
+ * Track organization usage
1571
+ */
1572
+ async trackUsage(metrics) {
1573
+ await this.metrics.recordUsage(metrics);
1574
+ await this.logger.info(
1575
+ `Usage recorded for organization ${metrics.organizationId}`,
1576
+ {
1577
+ apiCalls: metrics.apiCalls,
1578
+ llmTokens: metrics.llmTokens,
1579
+ storageBytes: metrics.storageBytes
1580
+ },
1581
+ {
1582
+ organizationId: metrics.organizationId
1583
+ }
1584
+ );
1585
+ }
1586
+ /**
1587
+ * Convenience methods for logging
1588
+ */
1589
+ async debug(message, metadata) {
1590
+ const { traceId, spanId } = TraceContext.getTrace();
1591
+ await this.logger.debug(message, metadata, {
1592
+ traceId: traceId || void 0,
1593
+ spanId: spanId || void 0
1594
+ });
1595
+ }
1596
+ async info(message, metadata) {
1597
+ const { traceId, spanId } = TraceContext.getTrace();
1598
+ await this.logger.info(message, metadata, {
1599
+ traceId: traceId || void 0,
1600
+ spanId: spanId || void 0
1601
+ });
1602
+ }
1603
+ async warning(message, metadata) {
1604
+ const { traceId, spanId } = TraceContext.getTrace();
1605
+ await this.logger.warning(message, metadata, {
1606
+ traceId: traceId || void 0,
1607
+ spanId: spanId || void 0
1608
+ });
1609
+ }
1610
+ /**
1611
+ * Alias for warning() to match console.warn() convention
1612
+ */
1613
+ async warn(message, metadata) {
1614
+ return this.warning(message, metadata);
1615
+ }
1616
+ async error(message, error2, metadata) {
1617
+ const { traceId, spanId } = TraceContext.getTrace();
1618
+ await this.logger.error(message, error2, metadata, {
1619
+ traceId: traceId || void 0,
1620
+ spanId: spanId || void 0
1621
+ });
1622
+ }
1623
+ async critical(message, error2, metadata) {
1624
+ const { traceId, spanId } = TraceContext.getTrace();
1625
+ await this.logger.critical(message, error2, metadata, {
1626
+ traceId: traceId || void 0,
1627
+ spanId: spanId || void 0
1628
+ });
1629
+ }
1630
+ /**
1631
+ * @deprecated No-op. Use `withTrace(fn)` instead.
1632
+ * Direct setTrace/endTrace are not safe under concurrency and have no effect
1633
+ * with the AsyncLocalStorage-based TraceContext.
1634
+ */
1635
+ startTrace(traceId) {
1636
+ return traceId || TraceContext.generateTraceId();
1637
+ }
1638
+ /**
1639
+ * @deprecated No-op — AsyncLocalStorage context is automatically scoped.
1640
+ */
1641
+ endTrace() {
1642
+ }
1643
+ /**
1644
+ * Run a function with automatic trace context.
1645
+ * Preferred API for background jobs and standalone traces.
1646
+ */
1647
+ async withTrace(fn, traceId) {
1648
+ return TraceContext.runWithTrace(fn, traceId);
1649
+ }
1650
+ };
1651
+ }
1652
+ });
1653
+
1654
+ // ../../packages/@company/observability/src/middleware.ts
1655
+ var init_middleware = __esm({
1656
+ "../../packages/@company/observability/src/middleware.ts"() {
1657
+ "use strict";
1658
+ init_logger();
1659
+ }
1660
+ });
1661
+
1662
+ // ../../packages/@company/observability/src/health.ts
1663
+ var init_health = __esm({
1664
+ "../../packages/@company/observability/src/health.ts"() {
1665
+ "use strict";
1666
+ }
1667
+ });
1668
+
1669
+ // ../../packages/@company/observability/src/index.ts
1670
+ var defaultObservability, getDefaultObservability, observability;
1671
+ var init_src2 = __esm({
1672
+ "../../packages/@company/observability/src/index.ts"() {
1673
+ init_observability_service();
1674
+ init_observability_service();
1675
+ init_logger();
1676
+ init_metrics();
1677
+ init_middleware();
1678
+ init_health();
1679
+ defaultObservability = null;
1680
+ getDefaultObservability = () => {
1681
+ if (!defaultObservability) {
1682
+ defaultObservability = createObservabilityService(
1683
+ process.env.SERVICE_NAME || "haansi-platform"
1684
+ );
1685
+ }
1686
+ return defaultObservability;
1687
+ };
1688
+ observability = new Proxy(
1689
+ {},
1690
+ {
1691
+ get(_target, prop) {
1692
+ const instance = getDefaultObservability();
1693
+ const value = instance[prop];
1694
+ return typeof value === "function" ? value.bind(instance) : value;
1695
+ }
1696
+ }
1697
+ );
1698
+ }
1699
+ });
1700
+
678
1701
  // ../service-capture/common/agents/types.ts
679
1702
  var AGENT_IDS;
680
- var init_types = __esm({
1703
+ var init_types2 = __esm({
681
1704
  "../service-capture/common/agents/types.ts"() {
682
1705
  "use strict";
683
1706
  AGENT_IDS = ["claude-code", "codex"];
@@ -926,7 +1949,7 @@ __export(agents_exports, {
926
1949
  var init_agents = __esm({
927
1950
  "../service-capture/common/agents/index.ts"() {
928
1951
  "use strict";
929
- init_types();
1952
+ init_types2();
930
1953
  init_claude_code();
931
1954
  init_codex();
932
1955
  init_registry();
@@ -1031,15 +2054,15 @@ function extractGitInfo(projectDir, sessionTimestamp, sessionBranch) {
1031
2054
  }
1032
2055
  return result;
1033
2056
  }
1034
- function resolveToken() {
2057
+ function resolveToken2() {
1035
2058
  if (process.env.HAANSI_TOKEN) return process.env.HAANSI_TOKEN;
1036
- if ((0, import_fs3.existsSync)(CREDENTIALS_FILE3)) {
2059
+ if ((0, import_fs3.existsSync)(CREDENTIALS_FILE4)) {
1037
2060
  try {
1038
- const creds = JSON.parse((0, import_fs3.readFileSync)(CREDENTIALS_FILE3, "utf-8"));
2061
+ const creds = JSON.parse((0, import_fs3.readFileSync)(CREDENTIALS_FILE4, "utf-8"));
1039
2062
  if (creds.token) return creds.token;
1040
2063
  } catch {
1041
2064
  logger.warn("Could not parse credentials file", {
1042
- file: CREDENTIALS_FILE3
2065
+ file: CREDENTIALS_FILE4
1043
2066
  });
1044
2067
  }
1045
2068
  }
@@ -1050,6 +2073,11 @@ function resolveAgentIds(agents) {
1050
2073
  const installed = detectInstalled().map((a) => a.id);
1051
2074
  return installed.length > 0 ? installed : ["claude-code"];
1052
2075
  }
2076
+ function canResolveGit(session) {
2077
+ if (session.gitRemoteUrl || session.gitCommit) return true;
2078
+ if (!session.cwd) return false;
2079
+ return (0, import_fs3.existsSync)(effectiveGitDir(session.cwd));
2080
+ }
1053
2081
  function discoverSessions(agentIds) {
1054
2082
  const sessions = [];
1055
2083
  for (const id of agentIds) {
@@ -1124,8 +2152,8 @@ async function uploadSession(sessionId, content, apiUrl2, token, agentSource, gi
1124
2152
  }
1125
2153
  }
1126
2154
  async function collect(options) {
1127
- const apiUrl2 = process.env.HAANSI_API_URL ?? DEFAULT_API_URL3;
1128
- const token = resolveToken();
2155
+ const apiUrl2 = process.env.HAANSI_API_URL ?? DEFAULT_API_URL2;
2156
+ const token = resolveToken2();
1129
2157
  if (!token && !options.dryRun) {
1130
2158
  throw new Error(
1131
2159
  "HAANSI_TOKEN is required. Set it as env var or in ~/.haansi/credentials.json"
@@ -1146,7 +2174,9 @@ async function collect(options) {
1146
2174
  const toUpload = [];
1147
2175
  for (const session of localSessions) {
1148
2176
  const remote = remoteMap.get(session.sessionId);
1149
- if (remote && remote.lineCount >= session.lineCount && remote.hasGitMeta) {
2177
+ const contentUnchanged = !!remote && remote.lineCount >= session.lineCount;
2178
+ const worthRetryingForGit = !remote?.hasGitMeta && canResolveGit(session);
2179
+ if (contentUnchanged && !worthRetryingForGit) {
1150
2180
  skipped++;
1151
2181
  } else {
1152
2182
  toUpload.push(session);
@@ -1228,14 +2258,18 @@ async function main() {
1228
2258
  const limitIdx = process.argv.indexOf("--limit");
1229
2259
  const limit = limitIdx !== -1 ? parseInt(process.argv[limitIdx + 1], 10) : void 0;
1230
2260
  logger.info("Collector starting", { forceAll, dryRun });
1231
- const { uploaded, skipped, errors } = await collect({
2261
+ const {
2262
+ uploaded: _uploaded,
2263
+ skipped: _skipped,
2264
+ errors
2265
+ } = await collect({
1232
2266
  forceAll,
1233
2267
  dryRun,
1234
2268
  limit
1235
2269
  });
1236
2270
  if (errors > 0) process.exit(1);
1237
2271
  }
1238
- var import_dotenv, import_path3, import_fs3, import_os3, import_zlib, import_child_process, logger, DEFAULT_API_URL3, CREDENTIALS_FILE3, MIN_LINES, EDGE_SCRUB_PATTERNS, GIT_BIN_CANDIDATES, resolvedGitBin;
2272
+ var import_dotenv, import_path3, import_fs3, import_os3, import_zlib, import_child_process, logger, DEFAULT_API_URL2, CREDENTIALS_FILE4, MIN_LINES, EDGE_SCRUB_PATTERNS, GIT_BIN_CANDIDATES, resolvedGitBin;
1239
2273
  var init_collector = __esm({
1240
2274
  "../service-capture/claude-sessions/collector.ts"() {
1241
2275
  "use strict";
@@ -1245,12 +2279,13 @@ var init_collector = __esm({
1245
2279
  import_os3 = require("os");
1246
2280
  import_zlib = require("zlib");
1247
2281
  import_child_process = require("child_process");
1248
- init_logger();
2282
+ init_src2();
2283
+ init_service_urls();
1249
2284
  init_agents();
1250
2285
  (0, import_dotenv.config)({ path: (0, import_path3.resolve)(__dirname, "../../../.env") });
1251
2286
  logger = createLogger("session-collector");
1252
- DEFAULT_API_URL3 = "https://api.haansi.co";
1253
- CREDENTIALS_FILE3 = (0, import_path3.join)((0, import_os3.homedir)(), ".haansi", "credentials.json");
2287
+ DEFAULT_API_URL2 = SERVICE_URL_DEFAULTS.haansiApiBaseUrl;
2288
+ CREDENTIALS_FILE4 = (0, import_path3.join)((0, import_os3.homedir)(), ".haansi", "credentials.json");
1254
2289
  MIN_LINES = 4;
1255
2290
  EDGE_SCRUB_PATTERNS = [
1256
2291
  {
@@ -1306,44 +2341,6 @@ var init_collector = __esm({
1306
2341
  }
1307
2342
  });
1308
2343
 
1309
- // src/lib/paths.ts
1310
- function apiUrl() {
1311
- return process.env.HAANSI_API_URL ?? DEFAULT_API_URL4;
1312
- }
1313
- function resolveToken2() {
1314
- if (process.env.HAANSI_TOKEN) return process.env.HAANSI_TOKEN;
1315
- if ((0, import_node_fs3.existsSync)(CREDENTIALS_FILE4)) {
1316
- try {
1317
- const creds = JSON.parse((0, import_node_fs3.readFileSync)(CREDENTIALS_FILE4, "utf-8"));
1318
- if (typeof creds.token === "string" && creds.token) return creds.token;
1319
- } catch {
1320
- }
1321
- }
1322
- return null;
1323
- }
1324
- function resolveHaansiBin() {
1325
- try {
1326
- const binPath = (0, import_node_child_process2.execSync)("which haansi", { encoding: "utf-8" }).trim();
1327
- if (binPath) return binPath;
1328
- } catch {
1329
- }
1330
- return "haansi";
1331
- }
1332
- var import_node_fs3, import_node_path3, import_node_os3, import_node_child_process2, DEFAULT_API_URL4, HAANSI_DIR3, CREDENTIALS_FILE4, CONFIG_FILE;
1333
- var init_paths = __esm({
1334
- "src/lib/paths.ts"() {
1335
- "use strict";
1336
- import_node_fs3 = require("node:fs");
1337
- import_node_path3 = require("node:path");
1338
- import_node_os3 = require("node:os");
1339
- import_node_child_process2 = require("node:child_process");
1340
- DEFAULT_API_URL4 = "https://api.haansi.co";
1341
- HAANSI_DIR3 = (0, import_node_path3.join)((0, import_node_os3.homedir)(), ".haansi");
1342
- CREDENTIALS_FILE4 = (0, import_node_path3.join)(HAANSI_DIR3, "credentials.json");
1343
- CONFIG_FILE = (0, import_node_path3.join)(HAANSI_DIR3, "config.json");
1344
- }
1345
- });
1346
-
1347
2344
  // src/lib/agent-selection.ts
1348
2345
  var agent_selection_exports = {};
1349
2346
  __export(agent_selection_exports, {
@@ -1391,7 +2388,7 @@ function saveAgents(agents) {
1391
2388
  }
1392
2389
  }
1393
2390
  cfg.agents = agents;
1394
- (0, import_node_fs4.mkdirSync)(HAANSI_DIR3, { recursive: true });
2391
+ (0, import_node_fs4.mkdirSync)(HAANSI_DIR, { recursive: true });
1395
2392
  (0, import_node_fs4.writeFileSync)(CONFIG_FILE, JSON.stringify(cfg, null, 2) + "\n", {
1396
2393
  encoding: "utf-8",
1397
2394
  mode: 384
@@ -1864,19 +2861,19 @@ var require_scheduler = __commonJS({
1864
2861
  });
1865
2862
 
1866
2863
  // ../../node_modules/node-cron/node_modules/uuid/dist/esm-node/rng.js
1867
- function rng() {
1868
- if (poolPtr > rnds8Pool.length - 16) {
1869
- import_crypto.default.randomFillSync(rnds8Pool);
1870
- poolPtr = 0;
2864
+ function rng2() {
2865
+ if (poolPtr2 > rnds8Pool2.length - 16) {
2866
+ import_crypto3.default.randomFillSync(rnds8Pool2);
2867
+ poolPtr2 = 0;
1871
2868
  }
1872
- return rnds8Pool.slice(poolPtr, poolPtr += 16);
2869
+ return rnds8Pool2.slice(poolPtr2, poolPtr2 += 16);
1873
2870
  }
1874
- var import_crypto, rnds8Pool, poolPtr;
1875
- var init_rng = __esm({
2871
+ var import_crypto3, rnds8Pool2, poolPtr2;
2872
+ var init_rng2 = __esm({
1876
2873
  "../../node_modules/node-cron/node_modules/uuid/dist/esm-node/rng.js"() {
1877
- import_crypto = __toESM(require("crypto"));
1878
- rnds8Pool = new Uint8Array(256);
1879
- poolPtr = rnds8Pool.length;
2874
+ import_crypto3 = __toESM(require("crypto"));
2875
+ rnds8Pool2 = new Uint8Array(256);
2876
+ poolPtr2 = rnds8Pool2.length;
1880
2877
  }
1881
2878
  });
1882
2879
 
@@ -1902,19 +2899,19 @@ var init_validate = __esm({
1902
2899
 
1903
2900
  // ../../node_modules/node-cron/node_modules/uuid/dist/esm-node/stringify.js
1904
2901
  function stringify(arr, offset = 0) {
1905
- const uuid3 = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
2902
+ const uuid3 = (byteToHex2[arr[offset + 0]] + byteToHex2[arr[offset + 1]] + byteToHex2[arr[offset + 2]] + byteToHex2[arr[offset + 3]] + "-" + byteToHex2[arr[offset + 4]] + byteToHex2[arr[offset + 5]] + "-" + byteToHex2[arr[offset + 6]] + byteToHex2[arr[offset + 7]] + "-" + byteToHex2[arr[offset + 8]] + byteToHex2[arr[offset + 9]] + "-" + byteToHex2[arr[offset + 10]] + byteToHex2[arr[offset + 11]] + byteToHex2[arr[offset + 12]] + byteToHex2[arr[offset + 13]] + byteToHex2[arr[offset + 14]] + byteToHex2[arr[offset + 15]]).toLowerCase();
1906
2903
  if (!validate_default(uuid3)) {
1907
2904
  throw TypeError("Stringified UUID is invalid");
1908
2905
  }
1909
2906
  return uuid3;
1910
2907
  }
1911
- var byteToHex, stringify_default;
1912
- var init_stringify = __esm({
2908
+ var byteToHex2, stringify_default;
2909
+ var init_stringify2 = __esm({
1913
2910
  "../../node_modules/node-cron/node_modules/uuid/dist/esm-node/stringify.js"() {
1914
2911
  init_validate();
1915
- byteToHex = [];
2912
+ byteToHex2 = [];
1916
2913
  for (let i = 0; i < 256; ++i) {
1917
- byteToHex.push((i + 256).toString(16).substr(1));
2914
+ byteToHex2.push((i + 256).toString(16).substr(1));
1918
2915
  }
1919
2916
  stringify_default = stringify;
1920
2917
  }
@@ -1928,7 +2925,7 @@ function v1(options, buf, offset) {
1928
2925
  let node = options.node || _nodeId;
1929
2926
  let clockseq = options.clockseq !== void 0 ? options.clockseq : _clockseq;
1930
2927
  if (node == null || clockseq == null) {
1931
- const seedBytes = options.random || (options.rng || rng)();
2928
+ const seedBytes = options.random || (options.rng || rng2)();
1932
2929
  if (node == null) {
1933
2930
  node = _nodeId = [seedBytes[0] | 1, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]];
1934
2931
  }
@@ -1972,8 +2969,8 @@ function v1(options, buf, offset) {
1972
2969
  var _nodeId, _clockseq, _lastMSecs, _lastNSecs, v1_default;
1973
2970
  var init_v1 = __esm({
1974
2971
  "../../node_modules/node-cron/node_modules/uuid/dist/esm-node/v1.js"() {
1975
- init_rng();
1976
- init_stringify();
2972
+ init_rng2();
2973
+ init_stringify2();
1977
2974
  _lastMSecs = 0;
1978
2975
  _lastNSecs = 0;
1979
2976
  v1_default = v1;
@@ -2059,7 +3056,7 @@ function v35_default(name, version3, hashfunc) {
2059
3056
  var DNS, URL2;
2060
3057
  var init_v35 = __esm({
2061
3058
  "../../node_modules/node-cron/node_modules/uuid/dist/esm-node/v35.js"() {
2062
- init_stringify();
3059
+ init_stringify2();
2063
3060
  init_parse();
2064
3061
  DNS = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
2065
3062
  URL2 = "6ba7b811-9dad-11d1-80b4-00c04fd430c8";
@@ -2073,12 +3070,12 @@ function md5(bytes) {
2073
3070
  } else if (typeof bytes === "string") {
2074
3071
  bytes = Buffer.from(bytes, "utf8");
2075
3072
  }
2076
- return import_crypto2.default.createHash("md5").update(bytes).digest();
3073
+ return import_crypto4.default.createHash("md5").update(bytes).digest();
2077
3074
  }
2078
- var import_crypto2, md5_default;
3075
+ var import_crypto4, md5_default;
2079
3076
  var init_md5 = __esm({
2080
3077
  "../../node_modules/node-cron/node_modules/uuid/dist/esm-node/md5.js"() {
2081
- import_crypto2 = __toESM(require("crypto"));
3078
+ import_crypto4 = __toESM(require("crypto"));
2082
3079
  md5_default = md5;
2083
3080
  }
2084
3081
  });
@@ -2095,9 +3092,9 @@ var init_v3 = __esm({
2095
3092
  });
2096
3093
 
2097
3094
  // ../../node_modules/node-cron/node_modules/uuid/dist/esm-node/v4.js
2098
- function v4(options, buf, offset) {
3095
+ function v42(options, buf, offset) {
2099
3096
  options = options || {};
2100
- const rnds = options.random || (options.rng || rng)();
3097
+ const rnds = options.random || (options.rng || rng2)();
2101
3098
  rnds[6] = rnds[6] & 15 | 64;
2102
3099
  rnds[8] = rnds[8] & 63 | 128;
2103
3100
  if (buf) {
@@ -2109,12 +3106,12 @@ function v4(options, buf, offset) {
2109
3106
  }
2110
3107
  return stringify_default(rnds);
2111
3108
  }
2112
- var v4_default;
2113
- var init_v4 = __esm({
3109
+ var v4_default2;
3110
+ var init_v42 = __esm({
2114
3111
  "../../node_modules/node-cron/node_modules/uuid/dist/esm-node/v4.js"() {
2115
- init_rng();
2116
- init_stringify();
2117
- v4_default = v4;
3112
+ init_rng2();
3113
+ init_stringify2();
3114
+ v4_default2 = v42;
2118
3115
  }
2119
3116
  });
2120
3117
 
@@ -2125,12 +3122,12 @@ function sha1(bytes) {
2125
3122
  } else if (typeof bytes === "string") {
2126
3123
  bytes = Buffer.from(bytes, "utf8");
2127
3124
  }
2128
- return import_crypto3.default.createHash("sha1").update(bytes).digest();
3125
+ return import_crypto5.default.createHash("sha1").update(bytes).digest();
2129
3126
  }
2130
- var import_crypto3, sha1_default;
3127
+ var import_crypto5, sha1_default;
2131
3128
  var init_sha1 = __esm({
2132
3129
  "../../node_modules/node-cron/node_modules/uuid/dist/esm-node/sha1.js"() {
2133
- import_crypto3 = __toESM(require("crypto"));
3130
+ import_crypto5 = __toESM(require("crypto"));
2134
3131
  sha1_default = sha1;
2135
3132
  }
2136
3133
  });
@@ -2177,21 +3174,21 @@ __export(esm_node_exports, {
2177
3174
  stringify: () => stringify_default,
2178
3175
  v1: () => v1_default,
2179
3176
  v3: () => v3_default,
2180
- v4: () => v4_default,
3177
+ v4: () => v4_default2,
2181
3178
  v5: () => v5_default,
2182
3179
  validate: () => validate_default,
2183
3180
  version: () => version_default
2184
3181
  });
2185
- var init_esm_node = __esm({
3182
+ var init_esm_node2 = __esm({
2186
3183
  "../../node_modules/node-cron/node_modules/uuid/dist/esm-node/index.js"() {
2187
3184
  init_v1();
2188
3185
  init_v3();
2189
- init_v4();
3186
+ init_v42();
2190
3187
  init_v5();
2191
3188
  init_nil();
2192
3189
  init_version();
2193
3190
  init_validate();
2194
- init_stringify();
3191
+ init_stringify2();
2195
3192
  init_parse();
2196
3193
  }
2197
3194
  });
@@ -2203,7 +3200,7 @@ var require_scheduled_task = __commonJS({
2203
3200
  var EventEmitter = require("events");
2204
3201
  var Task = require_task();
2205
3202
  var Scheduler = require_scheduler();
2206
- var uuid3 = (init_esm_node(), __toCommonJS(esm_node_exports));
3203
+ var uuid3 = (init_esm_node2(), __toCommonJS(esm_node_exports));
2207
3204
  var ScheduledTask = class extends EventEmitter {
2208
3205
  constructor(cronExpression, func, options) {
2209
3206
  super();
@@ -2248,7 +3245,7 @@ var require_background_scheduled_task = __commonJS({
2248
3245
  var EventEmitter = require("events");
2249
3246
  var path = require("path");
2250
3247
  var { fork } = require("child_process");
2251
- var uuid3 = (init_esm_node(), __toCommonJS(esm_node_exports));
3248
+ var uuid3 = (init_esm_node2(), __toCommonJS(esm_node_exports));
2252
3249
  var daemonPath = `${__dirname}/daemon.js`;
2253
3250
  var BackgroundScheduledTask = class extends EventEmitter {
2254
3251
  constructor(cronExpression, taskPath, options) {
@@ -2314,7 +3311,7 @@ var require_storage = __commonJS({
2314
3311
  return {
2315
3312
  save: (task) => {
2316
3313
  if (!task.options) {
2317
- const uuid3 = (init_esm_node(), __toCommonJS(esm_node_exports));
3314
+ const uuid3 = (init_esm_node2(), __toCommonJS(esm_node_exports));
2318
3315
  task.options = {};
2319
3316
  task.options.name = uuid3.v4();
2320
3317
  }
@@ -2432,10 +3429,11 @@ var init_collector_daemon = __esm({
2432
3429
  import_path4 = require("path");
2433
3430
  import_node_cron = __toESM(require_node_cron());
2434
3431
  init_collector();
2435
- init_logger();
3432
+ init_src2();
2436
3433
  (0, import_dotenv2.config)({ path: (0, import_path4.resolve)(__dirname, "../../../.env") });
2437
3434
  logger2 = createLogger("collector-daemon");
2438
- IN_MEMORY_VERSION = require_package().version;
3435
+ IN_MEMORY_VERSION = // eslint-disable-next-line @typescript-eslint/no-require-imports
3436
+ require_package().version;
2439
3437
  SCHEDULE = process.env.HAANSI_COLLECT_SCHEDULE ?? process.env.CLAUDE_COLLECT_SCHEDULE ?? "*/30 * * * *";
2440
3438
  main2().catch((err) => {
2441
3439
  logger2.error("Daemon failed to start", err);
@@ -2659,14 +3657,39 @@ var init_taxonomy = __esm({
2659
3657
  });
2660
3658
 
2661
3659
  // ../../packages/@company/types/src/embedding.ts
3660
+ var EMBEDDING_DEFAULTS, EMBEDDING_COLUMN, SUMMARY_EMBEDDING_COLUMN;
2662
3661
  var init_embedding = __esm({
2663
3662
  "../../packages/@company/types/src/embedding.ts"() {
2664
3663
  "use strict";
3664
+ EMBEDDING_DEFAULTS = {
3665
+ // `as const` gives a literal string type for the provider field, which
3666
+ // is assignable to llm-client's LLMProvider union without forcing
3667
+ // @company/types to import that union (which would re-introduce the
3668
+ // dependency edge we want to keep absent).
3669
+ // CUTOVER (2026-07-17): in-house model is now the active config. Reads +
3670
+ // writes + backfills all target the local-768 columns. The old OpenAI 1536
3671
+ // columns (`embedding` / `summary_embedding`) are retained but dormant —
3672
+ // roll back by flipping this whole object back to
3673
+ // { provider:"openai", model:"text-embedding-3-small", dimensions:1536,
3674
+ // column:"embedding", summaryColumn:"summary_embedding" }
3675
+ // (a later contract migration drops the dormant columns). Readers alias
3676
+ // `<column> AS embedding` so result-row field names stay stable.
3677
+ provider: "local",
3678
+ model: "Alibaba-NLP/gte-base-en-v1.5",
3679
+ dimensions: 768,
3680
+ // The ACTIVE dense-vector column that every reader + writer + backfill targets.
3681
+ column: "embedding_v2",
3682
+ // The active summary-embedding column (process_registry's second vector,
3683
+ // used by the process matcher).
3684
+ summaryColumn: "summary_embedding_v2"
3685
+ };
3686
+ EMBEDDING_COLUMN = EMBEDDING_DEFAULTS.column;
3687
+ SUMMARY_EMBEDDING_COLUMN = EMBEDDING_DEFAULTS.summaryColumn;
2665
3688
  }
2666
3689
  });
2667
3690
 
2668
3691
  // ../../packages/@company/types/src/index.ts
2669
- var init_src = __esm({
3692
+ var init_src3 = __esm({
2670
3693
  "../../packages/@company/types/src/index.ts"() {
2671
3694
  init_timeline();
2672
3695
  init_artifact();
@@ -3353,7 +4376,7 @@ function createZodEnum(values, params) {
3353
4376
  });
3354
4377
  }
3355
4378
  var ParseInputLazyPath, handleResult, ZodType, cuidRegex, cuid2Regex, ulidRegex, uuidRegex, nanoidRegex, jwtRegex, durationRegex, emailRegex, _emojiRegex, emojiRegex, ipv4Regex, ipv4CidrRegex, ipv6Regex, ipv6CidrRegex, base64Regex, base64urlRegex, dateRegexSource, dateRegex, ZodString, ZodNumber, ZodBigInt, ZodBoolean, ZodDate, ZodSymbol, ZodUndefined, ZodNull, ZodAny, ZodUnknown, ZodNever, ZodVoid, ZodArray, ZodObject, ZodUnion, getDiscriminator, ZodDiscriminatedUnion, ZodIntersection, ZodTuple, ZodRecord, ZodMap, ZodSet, ZodFunction, ZodLazy, ZodLiteral, ZodEnum, ZodNativeEnum, ZodPromise, ZodEffects, ZodOptional, ZodNullable, ZodDefault, ZodCatch, ZodNaN, BRAND, ZodBranded, ZodPipeline, ZodReadonly, late, ZodFirstPartyTypeKind, stringType, numberType, nanType, bigIntType, booleanType, dateType, symbolType, undefinedType, nullType, anyType, unknownType, neverType, voidType, arrayType, objectType, strictObjectType, unionType, discriminatedUnionType, intersectionType, tupleType, recordType, mapType, setType, functionType, lazyType, literalType, enumType, nativeEnumType, promiseType, effectsType, optionalType, nullableType, preprocessType, pipelineType;
3356
- var init_types2 = __esm({
4379
+ var init_types3 = __esm({
3357
4380
  "../../node_modules/zod/v3/types.js"() {
3358
4381
  init_ZodError();
3359
4382
  init_errors();
@@ -6606,7 +7629,7 @@ var init_external = __esm({
6606
7629
  init_parseUtil();
6607
7630
  init_typeAliases();
6608
7631
  init_util();
6609
- init_types2();
7632
+ init_types3();
6610
7633
  init_ZodError();
6611
7634
  }
6612
7635
  });
@@ -14367,7 +15390,7 @@ var init_classic = __esm({
14367
15390
  });
14368
15391
 
14369
15392
  // ../../node_modules/zod/v4/index.js
14370
- var init_v42 = __esm({
15393
+ var init_v43 = __esm({
14371
15394
  "../../node_modules/zod/v4/index.js"() {
14372
15395
  init_classic();
14373
15396
  init_classic();
@@ -14388,9 +15411,9 @@ function assertCompleteRequestResourceTemplate(request) {
14388
15411
  void request;
14389
15412
  }
14390
15413
  var LATEST_PROTOCOL_VERSION, DEFAULT_NEGOTIATED_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, RELATED_TASK_META_KEY, JSONRPC_VERSION, AssertObjectSchema, ProgressTokenSchema, CursorSchema, TaskCreationParamsSchema, TaskMetadataSchema, RelatedTaskMetadataSchema, RequestMetaSchema, BaseRequestParamsSchema, TaskAugmentedRequestParamsSchema, isTaskAugmentedRequestParams, RequestSchema, NotificationsParamsSchema, NotificationSchema, ResultSchema, RequestIdSchema, JSONRPCRequestSchema, isJSONRPCRequest, JSONRPCNotificationSchema, isJSONRPCNotification, JSONRPCResultResponseSchema, isJSONRPCResultResponse, ErrorCode, JSONRPCErrorResponseSchema, isJSONRPCErrorResponse, JSONRPCMessageSchema, JSONRPCResponseSchema, EmptyResultSchema, CancelledNotificationParamsSchema, CancelledNotificationSchema, IconSchema, IconsSchema, BaseMetadataSchema, ImplementationSchema, FormElicitationCapabilitySchema, ElicitationCapabilitySchema, ClientTasksCapabilitySchema, ServerTasksCapabilitySchema, ClientCapabilitiesSchema, InitializeRequestParamsSchema, InitializeRequestSchema, isInitializeRequest, ServerCapabilitiesSchema, InitializeResultSchema, InitializedNotificationSchema, PingRequestSchema, ProgressSchema, ProgressNotificationParamsSchema, ProgressNotificationSchema, PaginatedRequestParamsSchema, PaginatedRequestSchema, PaginatedResultSchema, TaskStatusSchema, TaskSchema, CreateTaskResultSchema, TaskStatusNotificationParamsSchema, TaskStatusNotificationSchema, GetTaskRequestSchema, GetTaskResultSchema, GetTaskPayloadRequestSchema, GetTaskPayloadResultSchema, ListTasksRequestSchema, ListTasksResultSchema, CancelTaskRequestSchema, CancelTaskResultSchema, ResourceContentsSchema, TextResourceContentsSchema, Base64Schema, BlobResourceContentsSchema, RoleSchema, AnnotationsSchema, ResourceSchema, ResourceTemplateSchema, ListResourcesRequestSchema, ListResourcesResultSchema, ListResourceTemplatesRequestSchema, ListResourceTemplatesResultSchema, ResourceRequestParamsSchema, ReadResourceRequestParamsSchema, ReadResourceRequestSchema, ReadResourceResultSchema, ResourceListChangedNotificationSchema, SubscribeRequestParamsSchema, SubscribeRequestSchema, UnsubscribeRequestParamsSchema, UnsubscribeRequestSchema, ResourceUpdatedNotificationParamsSchema, ResourceUpdatedNotificationSchema, PromptArgumentSchema, PromptSchema, ListPromptsRequestSchema, ListPromptsResultSchema, GetPromptRequestParamsSchema, GetPromptRequestSchema, TextContentSchema, ImageContentSchema, AudioContentSchema, ToolUseContentSchema, EmbeddedResourceSchema, ResourceLinkSchema, ContentBlockSchema, PromptMessageSchema, GetPromptResultSchema, PromptListChangedNotificationSchema, ToolAnnotationsSchema, ToolExecutionSchema, ToolSchema, ListToolsRequestSchema, ListToolsResultSchema, CallToolResultSchema, CompatibilityCallToolResultSchema, CallToolRequestParamsSchema, CallToolRequestSchema, ToolListChangedNotificationSchema, ListChangedOptionsBaseSchema, LoggingLevelSchema, SetLevelRequestParamsSchema, SetLevelRequestSchema, LoggingMessageNotificationParamsSchema, LoggingMessageNotificationSchema, ModelHintSchema, ModelPreferencesSchema, ToolChoiceSchema, ToolResultContentSchema, SamplingContentSchema, SamplingMessageContentBlockSchema, SamplingMessageSchema, CreateMessageRequestParamsSchema, CreateMessageRequestSchema, CreateMessageResultSchema, CreateMessageResultWithToolsSchema, BooleanSchemaSchema, StringSchemaSchema, NumberSchemaSchema, UntitledSingleSelectEnumSchemaSchema, TitledSingleSelectEnumSchemaSchema, LegacyTitledEnumSchemaSchema, SingleSelectEnumSchemaSchema, UntitledMultiSelectEnumSchemaSchema, TitledMultiSelectEnumSchemaSchema, MultiSelectEnumSchemaSchema, EnumSchemaSchema, PrimitiveSchemaDefinitionSchema, ElicitRequestFormParamsSchema, ElicitRequestURLParamsSchema, ElicitRequestParamsSchema, ElicitRequestSchema, ElicitationCompleteNotificationParamsSchema, ElicitationCompleteNotificationSchema, ElicitResultSchema, ResourceTemplateReferenceSchema, PromptReferenceSchema, CompleteRequestParamsSchema, CompleteRequestSchema, CompleteResultSchema, RootSchema, ListRootsRequestSchema, ListRootsResultSchema, RootsListChangedNotificationSchema, ClientRequestSchema, ClientNotificationSchema, ClientResultSchema, ServerRequestSchema, ServerNotificationSchema, ServerResultSchema, McpError, UrlElicitationRequiredError;
14391
- var init_types3 = __esm({
15414
+ var init_types4 = __esm({
14392
15415
  "../service-capture/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js"() {
14393
- init_v42();
15416
+ init_v43();
14394
15417
  LATEST_PROTOCOL_VERSION = "2025-11-25";
14395
15418
  DEFAULT_NEGOTIATED_PROTOCOL_VERSION = "2025-03-26";
14396
15419
  SUPPORTED_PROTOCOL_VERSIONS = [LATEST_PROTOCOL_VERSION, "2025-06-18", "2025-03-26", "2024-11-05", "2024-10-07"];
@@ -17554,7 +18577,7 @@ var DEFAULT_REQUEST_TIMEOUT_MSEC, Protocol;
17554
18577
  var init_protocol = __esm({
17555
18578
  "../service-capture/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js"() {
17556
18579
  init_zod_compat();
17557
- init_types3();
18580
+ init_types4();
17558
18581
  init_interfaces();
17559
18582
  init_zod_json_schema_compat();
17560
18583
  DEFAULT_REQUEST_TIMEOUT_MSEC = 6e4;
@@ -31136,7 +32159,7 @@ var Server;
31136
32159
  var init_server2 = __esm({
31137
32160
  "../service-capture/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js"() {
31138
32161
  init_protocol();
31139
- init_types3();
32162
+ init_types4();
31140
32163
  init_ajv_provider();
31141
32164
  init_zod_compat();
31142
32165
  init_server();
@@ -31706,7 +32729,7 @@ var init_mcp = __esm({
31706
32729
  init_server2();
31707
32730
  init_zod_compat();
31708
32731
  init_zod_json_schema_compat();
31709
- init_types3();
32732
+ init_types4();
31710
32733
  init_completable();
31711
32734
  init_uriTemplate();
31712
32735
  init_toolNameValidation();
@@ -32447,7 +33470,7 @@ function serializeMessage(message) {
32447
33470
  var ReadBuffer;
32448
33471
  var init_stdio = __esm({
32449
33472
  "../service-capture/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js"() {
32450
- init_types3();
33473
+ init_types4();
32451
33474
  ReadBuffer = class {
32452
33475
  append(chunk) {
32453
33476
  this._buffer = this._buffer ? Buffer.concat([this._buffer, chunk]) : chunk;
@@ -51347,14 +52370,14 @@ var require_etag = __commonJS({
51347
52370
  "../../node_modules/etag/index.js"(exports2, module2) {
51348
52371
  "use strict";
51349
52372
  module2.exports = etag;
51350
- var crypto6 = require("crypto");
52373
+ var crypto8 = require("crypto");
51351
52374
  var Stats = require("fs").Stats;
51352
52375
  var toString = Object.prototype.toString;
51353
52376
  function entitytag(entity) {
51354
52377
  if (entity.length === 0) {
51355
52378
  return '"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"';
51356
52379
  }
51357
- var hash2 = crypto6.createHash("sha1").update(entity, "utf8").digest("base64").substring(0, 27);
52380
+ var hash2 = crypto8.createHash("sha1").update(entity, "utf8").digest("base64").substring(0, 27);
51358
52381
  var len = typeof entity === "string" ? Buffer.byteLength(entity, "utf8") : entity.length;
51359
52382
  return '"' + len.toString(16) + "-" + hash2 + '"';
51360
52383
  }
@@ -54769,17 +55792,17 @@ var require_content_disposition = __commonJS({
54769
55792
  // ../service-capture/node_modules/cookie-signature/index.js
54770
55793
  var require_cookie_signature = __commonJS({
54771
55794
  "../service-capture/node_modules/cookie-signature/index.js"(exports2) {
54772
- var crypto6 = require("crypto");
55795
+ var crypto8 = require("crypto");
54773
55796
  exports2.sign = function(val, secret) {
54774
55797
  if ("string" != typeof val) throw new TypeError("Cookie value must be provided as a string.");
54775
55798
  if (null == secret) throw new TypeError("Secret key must be provided.");
54776
- return val + "." + crypto6.createHmac("sha256", secret).update(val).digest("base64").replace(/\=+$/, "");
55799
+ return val + "." + crypto8.createHmac("sha256", secret).update(val).digest("base64").replace(/\=+$/, "");
54777
55800
  };
54778
55801
  exports2.unsign = function(input, secret) {
54779
55802
  if ("string" != typeof input) throw new TypeError("Signed cookie string must be provided.");
54780
55803
  if (null == secret) throw new TypeError("Secret key must be provided.");
54781
55804
  var tentativeValue = input.slice(0, input.lastIndexOf(".")), expectedInput = exports2.sign(tentativeValue, secret), expectedBuffer = Buffer.from(expectedInput), inputBuffer = Buffer.from(input);
54782
- return expectedBuffer.length === inputBuffer.length && crypto6.timingSafeEqual(expectedBuffer, inputBuffer) ? tentativeValue : false;
55805
+ return expectedBuffer.length === inputBuffer.length && crypto8.timingSafeEqual(expectedBuffer, inputBuffer) ? tentativeValue : false;
54783
55806
  };
54784
55807
  }
54785
55808
  });
@@ -56174,13 +57197,13 @@ function writeFromReadableStream(stream, writable) {
56174
57197
  }
56175
57198
  return writeFromReadableStreamDefaultReader(stream.getReader(), writable);
56176
57199
  }
56177
- var import_http2, import_http22, import_stream, import_crypto4, RequestError, toRequestError, GlobalRequest, Request, newHeadersFromIncoming, wrapBodyStream, newRequestFromIncoming, getRequestCache, requestCache, incomingKey, urlKey, headersKey, abortControllerKey, getAbortController, requestPrototype, newRequest, responseCache, getResponseCache, cacheKey, GlobalResponse, Response2, buildOutgoingHttpHeaders, X_ALREADY_SENT, outgoingEnded, handleRequestError, handleFetchError, handleResponseError, flushHeaders, responseViaCache, isPromise, responseViaResponseObject, getRequestListener;
57200
+ var import_http2, import_http22, import_stream, import_crypto6, RequestError, toRequestError, GlobalRequest, Request, newHeadersFromIncoming, wrapBodyStream, newRequestFromIncoming, getRequestCache, requestCache, incomingKey, urlKey, headersKey, abortControllerKey, getAbortController, requestPrototype, newRequest, responseCache, getResponseCache, cacheKey, GlobalResponse, Response2, buildOutgoingHttpHeaders, X_ALREADY_SENT, outgoingEnded, handleRequestError, handleFetchError, handleResponseError, flushHeaders, responseViaCache, isPromise, responseViaResponseObject, getRequestListener;
56178
57201
  var init_dist = __esm({
56179
57202
  "../../node_modules/@hono/node-server/dist/index.mjs"() {
56180
57203
  import_http2 = require("http2");
56181
57204
  import_http22 = require("http2");
56182
57205
  import_stream = require("stream");
56183
- import_crypto4 = __toESM(require("crypto"), 1);
57206
+ import_crypto6 = __toESM(require("crypto"), 1);
56184
57207
  RequestError = class extends Error {
56185
57208
  constructor(message, options) {
56186
57209
  super(message, options);
@@ -56450,7 +57473,7 @@ var init_dist = __esm({
56450
57473
  };
56451
57474
  X_ALREADY_SENT = "x-hono-already-sent";
56452
57475
  if (typeof global.crypto === "undefined") {
56453
- global.crypto = import_crypto4.default;
57476
+ global.crypto = import_crypto6.default;
56454
57477
  }
56455
57478
  outgoingEnded = Symbol("outgoingEnded");
56456
57479
  handleRequestError = () => new Response(null, {
@@ -56669,7 +57692,7 @@ var init_dist = __esm({
56669
57692
  var WebStandardStreamableHTTPServerTransport;
56670
57693
  var init_webStandardStreamableHttp = __esm({
56671
57694
  "../service-capture/node_modules/@modelcontextprotocol/sdk/dist/esm/server/webStandardStreamableHttp.js"() {
56672
- init_types3();
57695
+ init_types4();
56673
57696
  WebStandardStreamableHTTPServerTransport = class {
56674
57697
  constructor(options = {}) {
56675
57698
  this._started = false;
@@ -57459,7 +58482,7 @@ async function main3() {
57459
58482
  }
57460
58483
  warmupInBackground();
57461
58484
  }
57462
- var import_dotenv3, import_path5, import_fs5, import_os4, DEFAULT_API_URL5, CREDENTIALS_FILE5, API_URL, TOKEN, contextSchema, isCollecting, lastCollectTime, COLLECT_COOLDOWN_MS, mcpServer, server;
58485
+ var import_dotenv3, import_path5, import_fs5, import_os4, DEFAULT_API_URL3, CREDENTIALS_FILE5, API_URL, AGENT_SOURCE, DEFAULT_SOURCE_TOOL, TOKEN, contextSchema, isCollecting, lastCollectTime, COLLECT_COOLDOWN_MS, mcpServer, server;
57463
58486
  var init_mcp_server2 = __esm({
57464
58487
  "../service-capture/claude-sessions/mcp-server.ts"() {
57465
58488
  "use strict";
@@ -57469,14 +58492,17 @@ var init_mcp_server2 = __esm({
57469
58492
  import_os4 = require("os");
57470
58493
  init_collector();
57471
58494
  init_http_timeout();
57472
- init_src();
58495
+ init_service_urls();
58496
+ init_src3();
57473
58497
  init_mcp();
57474
58498
  init_stdio2();
57475
- init_types3();
58499
+ init_types4();
57476
58500
  (0, import_dotenv3.config)({ path: (0, import_path5.resolve)(__dirname, "../../../.env") });
57477
- DEFAULT_API_URL5 = "https://api.haansi.co";
58501
+ DEFAULT_API_URL3 = SERVICE_URL_DEFAULTS.haansiApiBaseUrl;
57478
58502
  CREDENTIALS_FILE5 = (0, import_path5.join)((0, import_os4.homedir)(), ".haansi", "credentials.json");
57479
- API_URL = process.env.HAANSI_API_URL ?? DEFAULT_API_URL5;
58503
+ API_URL = process.env.HAANSI_API_URL ?? DEFAULT_API_URL3;
58504
+ AGENT_SOURCE = process.env.HAANSI_AGENT_SOURCE?.toLowerCase();
58505
+ DEFAULT_SOURCE_TOOL = AGENT_SOURCE === "codex" ? "codex-mcp" : "claude-code-mcp";
57480
58506
  TOKEN = resolveToken3();
57481
58507
  if (!TOKEN) {
57482
58508
  process.exit(1);
@@ -57616,7 +58642,7 @@ var init_mcp_server2 = __esm({
57616
58642
  },
57617
58643
  source_tool: {
57618
58644
  type: "string",
57619
- description: 'Tool that saved this (default: "claude-code-mcp")'
58645
+ description: `Tool that saved this (default: "${DEFAULT_SOURCE_TOOL}")`
57620
58646
  },
57621
58647
  _context: contextSchema
57622
58648
  },
@@ -57735,7 +58761,7 @@ var init_mcp_server2 = __esm({
57735
58761
  git_commit,
57736
58762
  tags,
57737
58763
  model,
57738
- source_tool
58764
+ source_tool: source_tool ?? DEFAULT_SOURCE_TOOL
57739
58765
  },
57740
58766
  { extraHeaders }
57741
58767
  );
@@ -57830,7 +58856,7 @@ function parseTarget(arg) {
57830
58856
  );
57831
58857
  }
57832
58858
  function exchangeUrl() {
57833
- return `${apiUrl().replace(/\/+$/, "")}/api/v1/access/exchange/mcp`;
58859
+ return `${apiUrl().replace(/\/+$/, "")}/api/v1/memory/exchange/mcp`;
57834
58860
  }
57835
58861
  function setupClaudeMcp(target) {
57836
58862
  let config6 = {};
@@ -57850,12 +58876,13 @@ function setupClaudeMcp(target) {
57850
58876
  const haansiBin = resolveHaansiBin();
57851
58877
  config6.mcpServers["haansi-solutions"] = {
57852
58878
  command: haansiBin,
57853
- args: ["mcp-server"]
58879
+ args: ["mcp-server"],
58880
+ env: { HAANSI_AGENT_SOURCE: "claude-code" }
57854
58881
  };
57855
58882
  installed.push(`haansi-solutions (stdio \u2192 ${haansiBin} mcp-server)`);
57856
58883
  }
57857
58884
  if (target === "all" || target === "exchange") {
57858
- const token = resolveToken2();
58885
+ const token = resolveToken();
57859
58886
  if (!token) {
57860
58887
  warnings.push(
57861
58888
  "haansi-exchange not registered: no token found. Run `haansi auth login` first, or set HAANSI_TOKEN."
@@ -57894,12 +58921,13 @@ function setupCodexMcp(target) {
57894
58921
  const haansiBin = resolveHaansiBin();
57895
58922
  content = upsertTomlTable(content, "mcp_servers.haansi-solutions", {
57896
58923
  command: tomlString(haansiBin),
57897
- args: tomlStringArray(["mcp-server"])
58924
+ args: tomlStringArray(["mcp-server"]),
58925
+ env: tomlInlineTable({ HAANSI_AGENT_SOURCE: "codex" })
57898
58926
  });
57899
58927
  installed.push(`haansi-solutions (stdio \u2192 ${haansiBin} mcp-server)`);
57900
58928
  }
57901
58929
  if (target === "all" || target === "exchange") {
57902
- const token = resolveToken2();
58930
+ const token = resolveToken();
57903
58931
  if (!token) {
57904
58932
  warnings.push(
57905
58933
  "haansi-exchange not registered: no token found. Run `haansi auth login` first, or set HAANSI_TOKEN."
@@ -58096,7 +59124,7 @@ async function config5(args) {
58096
59124
  process.exit(1);
58097
59125
  return;
58098
59126
  }
58099
- const apiUrl2 = process.env.HAANSI_API_URL ?? DEFAULT_API_URL6;
59127
+ const apiUrl2 = apiUrl();
58100
59128
  const subcommand = args[0];
58101
59129
  if (subcommand === "get") {
58102
59130
  const key = args[1];
@@ -58177,14 +59205,14 @@ Supported keys:
58177
59205
  if (subcommand !== void 0) process.exit(1);
58178
59206
  }
58179
59207
  }
58180
- var import_node_fs7, import_node_path6, import_node_os6, DEFAULT_API_URL6, CREDENTIALS_FILE6, VALID_SESSION_MODES;
59208
+ var import_node_fs7, import_node_path6, import_node_os6, CREDENTIALS_FILE6, VALID_SESSION_MODES;
58181
59209
  var init_config = __esm({
58182
59210
  "src/commands/config.ts"() {
58183
59211
  "use strict";
58184
59212
  import_node_fs7 = require("node:fs");
58185
59213
  import_node_path6 = require("node:path");
58186
59214
  import_node_os6 = require("node:os");
58187
- DEFAULT_API_URL6 = "https://api.haansi.co";
59215
+ init_paths();
58188
59216
  CREDENTIALS_FILE6 = (0, import_node_path6.join)((0, import_node_os6.homedir)(), ".haansi", "credentials.json");
58189
59217
  VALID_SESSION_MODES = ["private", "org"];
58190
59218
  }
@@ -58235,7 +59263,7 @@ async function apiPost2(path, body, token, apiUrl2) {
58235
59263
  return response.json();
58236
59264
  }
58237
59265
  async function list(options) {
58238
- const apiUrl2 = process.env.HAANSI_API_URL ?? DEFAULT_API_URL7;
59266
+ const apiUrl2 = apiUrl();
58239
59267
  const token = resolveToken5();
58240
59268
  let data;
58241
59269
  if (options.search) {
@@ -58261,7 +59289,7 @@ async function list(options) {
58261
59289
  ${data.results.length} result(s)`);
58262
59290
  }
58263
59291
  async function searchKnowledge(options) {
58264
- const apiUrl2 = process.env.HAANSI_API_URL ?? DEFAULT_API_URL7;
59292
+ const apiUrl2 = apiUrl();
58265
59293
  const token = resolveToken5();
58266
59294
  let url2 = `/memory/solutions/knowledge/search?q=${encodeURIComponent(options.query)}&limit=${options.limit}`;
58267
59295
  if (options.artifactType) {
@@ -58278,7 +59306,7 @@ async function searchKnowledge(options) {
58278
59306
  ${data.results.length} result(s)`);
58279
59307
  }
58280
59308
  async function saveKnowledge(options) {
58281
- const apiUrl2 = process.env.HAANSI_API_URL ?? DEFAULT_API_URL7;
59309
+ const apiUrl2 = apiUrl();
58282
59310
  const token = resolveToken5();
58283
59311
  const body = {
58284
59312
  problem_description: options.problem,
@@ -58299,19 +59327,20 @@ async function saveKnowledge(options) {
58299
59327
  console.log(` Solution: ${data.solution_summary}`);
58300
59328
  console.log("\nThis is now searchable via `haansi search-solutions`.");
58301
59329
  }
58302
- var import_node_fs8, import_node_path7, import_node_os7, DEFAULT_API_URL7, CREDENTIALS_FILE7;
59330
+ var import_node_fs8, import_node_path7, import_node_os7, CREDENTIALS_FILE7;
58303
59331
  var init_list = __esm({
58304
59332
  "src/commands/list.ts"() {
58305
59333
  "use strict";
58306
59334
  import_node_fs8 = require("node:fs");
58307
59335
  import_node_path7 = require("node:path");
58308
59336
  import_node_os7 = require("node:os");
58309
- DEFAULT_API_URL7 = "https://api.haansi.co";
59337
+ init_paths();
58310
59338
  CREDENTIALS_FILE7 = (0, import_node_path7.join)((0, import_node_os7.homedir)(), ".haansi", "credentials.json");
58311
59339
  }
58312
59340
  });
58313
59341
 
58314
59342
  // src/index.ts
59343
+ init_paths();
58315
59344
  var { version: VERSION } = require_package();
58316
59345
  var command = process.argv[2];
58317
59346
  function getFlag(flag) {
@@ -58535,7 +59564,7 @@ Options for collect:
58535
59564
 
58536
59565
  Environment variables:
58537
59566
  HAANSI_TOKEN API token (or use \`haansi init\` to save it)
58538
- HAANSI_API_URL API base URL (default: https://api.haansi.co)
59567
+ HAANSI_API_URL API base URL (default: ${DEFAULT_API_URL})
58539
59568
  CODEX_HOME Codex home dir (default: ~/.codex)
58540
59569
  HAANSI_AGENTS Daemon: comma-separated agents (claude-code,codex)
58541
59570
  HAANSI_COLLECT_SCHEDULE Cron expression for daemon (default: */30 * * * *)