@hasna/recordings 0.1.33 → 0.1.35
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/dist/cli/index.js +325 -98
- package/dist/index.js +62 -50
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/mcp/index.js +65 -53
- package/dist/storage.js +62 -50
- package/dist/version.d.ts +1 -1
- package/package.json +2 -2
package/dist/cli/index.js
CHANGED
|
@@ -2955,7 +2955,7 @@ var require_dist = __commonJS((exports) => {
|
|
|
2955
2955
|
function parse(stream, callback) {
|
|
2956
2956
|
const parser = new parser_1.Parser;
|
|
2957
2957
|
stream.on("data", (buffer) => parser.parse(buffer, callback));
|
|
2958
|
-
return new Promise((
|
|
2958
|
+
return new Promise((resolve2) => stream.on("end", () => resolve2()));
|
|
2959
2959
|
}
|
|
2960
2960
|
exports.parse = parse;
|
|
2961
2961
|
});
|
|
@@ -3634,12 +3634,12 @@ var require_client = __commonJS((exports, module) => {
|
|
|
3634
3634
|
this._connect(callback);
|
|
3635
3635
|
return;
|
|
3636
3636
|
}
|
|
3637
|
-
return new this._Promise((
|
|
3637
|
+
return new this._Promise((resolve2, reject) => {
|
|
3638
3638
|
this._connect((error) => {
|
|
3639
3639
|
if (error) {
|
|
3640
3640
|
reject(error);
|
|
3641
3641
|
} else {
|
|
3642
|
-
|
|
3642
|
+
resolve2(this);
|
|
3643
3643
|
}
|
|
3644
3644
|
});
|
|
3645
3645
|
});
|
|
@@ -3971,8 +3971,8 @@ var require_client = __commonJS((exports, module) => {
|
|
|
3971
3971
|
readTimeout = config.query_timeout || this.connectionParameters.query_timeout;
|
|
3972
3972
|
query = new Query(config, values, callback);
|
|
3973
3973
|
if (!query.callback) {
|
|
3974
|
-
result = new this._Promise((
|
|
3975
|
-
query.callback = (err, res) => err ? reject(err) :
|
|
3974
|
+
result = new this._Promise((resolve2, reject) => {
|
|
3975
|
+
query.callback = (err, res) => err ? reject(err) : resolve2(res);
|
|
3976
3976
|
}).catch((err) => {
|
|
3977
3977
|
Error.captureStackTrace(err);
|
|
3978
3978
|
throw err;
|
|
@@ -4047,8 +4047,8 @@ var require_client = __commonJS((exports, module) => {
|
|
|
4047
4047
|
if (cb) {
|
|
4048
4048
|
this.connection.once("end", cb);
|
|
4049
4049
|
} else {
|
|
4050
|
-
return new this._Promise((
|
|
4051
|
-
this.connection.once("end",
|
|
4050
|
+
return new this._Promise((resolve2) => {
|
|
4051
|
+
this.connection.once("end", resolve2);
|
|
4052
4052
|
});
|
|
4053
4053
|
}
|
|
4054
4054
|
}
|
|
@@ -4095,8 +4095,8 @@ var require_pg_pool = __commonJS((exports, module) => {
|
|
|
4095
4095
|
const cb = function(err, client) {
|
|
4096
4096
|
err ? rej(err) : res(client);
|
|
4097
4097
|
};
|
|
4098
|
-
const result = new Promise2(function(
|
|
4099
|
-
res =
|
|
4098
|
+
const result = new Promise2(function(resolve2, reject) {
|
|
4099
|
+
res = resolve2;
|
|
4100
4100
|
rej = reject;
|
|
4101
4101
|
}).catch((err) => {
|
|
4102
4102
|
Error.captureStackTrace(err);
|
|
@@ -4157,7 +4157,7 @@ var require_pg_pool = __commonJS((exports, module) => {
|
|
|
4157
4157
|
if (typeof Promise2.try === "function") {
|
|
4158
4158
|
return Promise2.try(f);
|
|
4159
4159
|
}
|
|
4160
|
-
return new Promise2((
|
|
4160
|
+
return new Promise2((resolve2) => resolve2(f()));
|
|
4161
4161
|
}
|
|
4162
4162
|
_isFull() {
|
|
4163
4163
|
return this._clients.length >= this.options.max;
|
|
@@ -4533,8 +4533,8 @@ var require_query2 = __commonJS((exports, module) => {
|
|
|
4533
4533
|
NativeQuery.prototype._getPromise = function() {
|
|
4534
4534
|
if (this._promise)
|
|
4535
4535
|
return this._promise;
|
|
4536
|
-
this._promise = new Promise(function(
|
|
4537
|
-
this._once("end",
|
|
4536
|
+
this._promise = new Promise(function(resolve2, reject) {
|
|
4537
|
+
this._once("end", resolve2);
|
|
4538
4538
|
this._once("error", reject);
|
|
4539
4539
|
}.bind(this));
|
|
4540
4540
|
return this._promise;
|
|
@@ -4708,12 +4708,12 @@ var require_client2 = __commonJS((exports, module) => {
|
|
|
4708
4708
|
this._connect(callback);
|
|
4709
4709
|
return;
|
|
4710
4710
|
}
|
|
4711
|
-
return new this._Promise((
|
|
4711
|
+
return new this._Promise((resolve2, reject) => {
|
|
4712
4712
|
this._connect((error) => {
|
|
4713
4713
|
if (error) {
|
|
4714
4714
|
reject(error);
|
|
4715
4715
|
} else {
|
|
4716
|
-
|
|
4716
|
+
resolve2(this);
|
|
4717
4717
|
}
|
|
4718
4718
|
});
|
|
4719
4719
|
});
|
|
@@ -4737,8 +4737,8 @@ var require_client2 = __commonJS((exports, module) => {
|
|
|
4737
4737
|
query = new NativeQuery(config, values, callback);
|
|
4738
4738
|
if (!query.callback) {
|
|
4739
4739
|
let resolveOut, rejectOut;
|
|
4740
|
-
result = new this._Promise((
|
|
4741
|
-
resolveOut =
|
|
4740
|
+
result = new this._Promise((resolve2, reject) => {
|
|
4741
|
+
resolveOut = resolve2;
|
|
4742
4742
|
rejectOut = reject;
|
|
4743
4743
|
}).catch((err) => {
|
|
4744
4744
|
Error.captureStackTrace(err);
|
|
@@ -4796,8 +4796,8 @@ var require_client2 = __commonJS((exports, module) => {
|
|
|
4796
4796
|
}
|
|
4797
4797
|
let result;
|
|
4798
4798
|
if (!cb) {
|
|
4799
|
-
result = new this._Promise(function(
|
|
4800
|
-
cb = (err) => err ? reject(err) :
|
|
4799
|
+
result = new this._Promise(function(resolve2, reject) {
|
|
4800
|
+
cb = (err) => err ? reject(err) : resolve2();
|
|
4801
4801
|
});
|
|
4802
4802
|
}
|
|
4803
4803
|
this.native.end(function() {
|
|
@@ -5098,7 +5098,7 @@ var init_pg_migrate = __esm(() => {
|
|
|
5098
5098
|
var require_package = __commonJS((exports, module) => {
|
|
5099
5099
|
module.exports = {
|
|
5100
5100
|
name: "@hasna/recordings",
|
|
5101
|
-
version: "0.1.
|
|
5101
|
+
version: "0.1.35",
|
|
5102
5102
|
type: "module",
|
|
5103
5103
|
description: "Speech-to-text recording tool with MCP and CLI \u2014 records, transcribes, and optionally enhances text using AI",
|
|
5104
5104
|
repository: {
|
|
@@ -5148,7 +5148,7 @@ var require_package = __commonJS((exports, module) => {
|
|
|
5148
5148
|
"LICENSE"
|
|
5149
5149
|
],
|
|
5150
5150
|
dependencies: {
|
|
5151
|
-
"@hasna/events": "^0.1.
|
|
5151
|
+
"@hasna/events": "^0.1.11",
|
|
5152
5152
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
5153
5153
|
chalk: "^5.4.1",
|
|
5154
5154
|
commander: "^13.1.0",
|
|
@@ -5190,29 +5190,83 @@ function getPathValue(input, path) {
|
|
|
5190
5190
|
return;
|
|
5191
5191
|
}, input);
|
|
5192
5192
|
}
|
|
5193
|
-
function
|
|
5194
|
-
const
|
|
5195
|
-
|
|
5193
|
+
function getFieldValues(input, path) {
|
|
5194
|
+
const values = [];
|
|
5195
|
+
const push = (value) => {
|
|
5196
|
+
if (!values.some((item) => Object.is(item, value)))
|
|
5197
|
+
values.push(value);
|
|
5198
|
+
};
|
|
5199
|
+
if (path.includes(".") && path in input)
|
|
5200
|
+
push(input[path]);
|
|
5201
|
+
const nestedValue = getPathValue(input, path);
|
|
5202
|
+
if (nestedValue !== undefined || !path.includes("."))
|
|
5203
|
+
push(nestedValue);
|
|
5204
|
+
return values;
|
|
5196
5205
|
}
|
|
5197
|
-
function
|
|
5206
|
+
function wildcardToRegExp(pattern, options = {}) {
|
|
5207
|
+
let body = "";
|
|
5208
|
+
for (let index = 0;index < pattern.length; index += 1) {
|
|
5209
|
+
const char = pattern[index];
|
|
5210
|
+
if (char === "*") {
|
|
5211
|
+
if (pattern[index + 1] === "*") {
|
|
5212
|
+
body += ".*";
|
|
5213
|
+
index += 1;
|
|
5214
|
+
} else {
|
|
5215
|
+
body += options.segmentSafe ? "[^/]*" : ".*";
|
|
5216
|
+
}
|
|
5217
|
+
} else {
|
|
5218
|
+
body += char.replace(/[|\\{}()[\]^$+?.]/g, "\\$&");
|
|
5219
|
+
}
|
|
5220
|
+
}
|
|
5221
|
+
return new RegExp(`^${body}$`);
|
|
5222
|
+
}
|
|
5223
|
+
function matchString(value, matcher, options = {}) {
|
|
5198
5224
|
if (matcher === undefined)
|
|
5199
5225
|
return true;
|
|
5200
5226
|
if (value === undefined)
|
|
5201
5227
|
return false;
|
|
5202
5228
|
const matchers = Array.isArray(matcher) ? matcher : [matcher];
|
|
5203
|
-
return matchers.some((item) => wildcardToRegExp(item).test(value));
|
|
5229
|
+
return matchers.some((item) => wildcardToRegExp(item, options).test(value));
|
|
5204
5230
|
}
|
|
5205
5231
|
function matchRecord(input, matcher) {
|
|
5206
5232
|
if (!matcher)
|
|
5207
5233
|
return true;
|
|
5208
5234
|
return Object.entries(matcher).every(([path, expected]) => {
|
|
5209
|
-
const
|
|
5210
|
-
|
|
5211
|
-
return matchString(actual === undefined ? undefined : String(actual), expected);
|
|
5212
|
-
}
|
|
5213
|
-
return actual === expected;
|
|
5235
|
+
const actualValues = getFieldValues(input, path);
|
|
5236
|
+
return matchField(actualValues, expected, path);
|
|
5214
5237
|
});
|
|
5215
5238
|
}
|
|
5239
|
+
function matchField(actualValues, expected, path) {
|
|
5240
|
+
if (isNegativeMatcher(expected)) {
|
|
5241
|
+
return !actualValues.some((actual) => matchPositiveField(actual, expected.not, path));
|
|
5242
|
+
}
|
|
5243
|
+
return actualValues.some((actual) => matchPositiveField(actual, expected, path));
|
|
5244
|
+
}
|
|
5245
|
+
function matchPositiveField(actual, expected, path) {
|
|
5246
|
+
if (typeof expected === "string" || Array.isArray(expected)) {
|
|
5247
|
+
return stringCandidates(actual).some((candidate) => matchString(candidate, expected, {
|
|
5248
|
+
segmentSafe: path.endsWith("_path") || path.endsWith(".path")
|
|
5249
|
+
}));
|
|
5250
|
+
}
|
|
5251
|
+
if (Array.isArray(actual)) {
|
|
5252
|
+
return actual.some((item) => item === expected);
|
|
5253
|
+
}
|
|
5254
|
+
return actual === expected;
|
|
5255
|
+
}
|
|
5256
|
+
function stringCandidates(actual) {
|
|
5257
|
+
if (actual === undefined)
|
|
5258
|
+
return [];
|
|
5259
|
+
if (Array.isArray(actual)) {
|
|
5260
|
+
return actual.flatMap((item) => isPrimitiveFieldValue(item) ? [String(item)] : []);
|
|
5261
|
+
}
|
|
5262
|
+
return [String(actual)];
|
|
5263
|
+
}
|
|
5264
|
+
function isPrimitiveFieldValue(value) {
|
|
5265
|
+
return value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
5266
|
+
}
|
|
5267
|
+
function isNegativeMatcher(value) {
|
|
5268
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value) && "not" in value);
|
|
5269
|
+
}
|
|
5216
5270
|
function eventMatchesFilter(event, filter) {
|
|
5217
5271
|
return matchString(event.source, filter.source) && matchString(event.type, filter.type) && matchString(event.subject, filter.subject) && matchString(event.severity, filter.severity) && matchRecord(event.data, filter.data) && matchRecord(event.metadata, filter.metadata);
|
|
5218
5272
|
}
|
|
@@ -5228,6 +5282,13 @@ var HASNA_EVENTS_HOME_ENV = "HASNA_EVENTS_HOME";
|
|
|
5228
5282
|
function getEventsDataDir(override) {
|
|
5229
5283
|
return override || process.env[HASNA_EVENTS_DIR_ENV] || process.env[HASNA_EVENTS_HOME_ENV] || join(homedir(), ".hasna", "events");
|
|
5230
5284
|
}
|
|
5285
|
+
function getActiveEventsDirEnv() {
|
|
5286
|
+
if (process.env[HASNA_EVENTS_DIR_ENV])
|
|
5287
|
+
return HASNA_EVENTS_DIR_ENV;
|
|
5288
|
+
if (process.env[HASNA_EVENTS_HOME_ENV])
|
|
5289
|
+
return HASNA_EVENTS_HOME_ENV;
|
|
5290
|
+
return null;
|
|
5291
|
+
}
|
|
5231
5292
|
|
|
5232
5293
|
class JsonEventsStore {
|
|
5233
5294
|
dataDir;
|
|
@@ -5340,6 +5401,52 @@ class JsonEventsStore {
|
|
|
5340
5401
|
});
|
|
5341
5402
|
}
|
|
5342
5403
|
}
|
|
5404
|
+
async function getEventsStatus(dataDir) {
|
|
5405
|
+
const store = new JsonEventsStore(dataDir);
|
|
5406
|
+
await store.init();
|
|
5407
|
+
const [channels, events, deliveries] = await Promise.all([
|
|
5408
|
+
store.listChannels(),
|
|
5409
|
+
store.listEvents(),
|
|
5410
|
+
store.listDeliveries()
|
|
5411
|
+
]);
|
|
5412
|
+
const transports = channels.reduce((counts, channel) => {
|
|
5413
|
+
counts[channel.transport] = (counts[channel.transport] ?? 0) + 1;
|
|
5414
|
+
return counts;
|
|
5415
|
+
}, {});
|
|
5416
|
+
return {
|
|
5417
|
+
service: "events",
|
|
5418
|
+
schemaVersion: "1.0",
|
|
5419
|
+
dataDir: store.dataDir,
|
|
5420
|
+
env: {
|
|
5421
|
+
primary: HASNA_EVENTS_DIR_ENV,
|
|
5422
|
+
fallback: HASNA_EVENTS_HOME_ENV,
|
|
5423
|
+
active: getActiveEventsDirEnv()
|
|
5424
|
+
},
|
|
5425
|
+
files: {
|
|
5426
|
+
channels: statusFile(store.dataDir, "channels.json", channels.length),
|
|
5427
|
+
events: statusFile(store.dataDir, "events.json", events.length),
|
|
5428
|
+
deliveries: statusFile(store.dataDir, "deliveries.json", deliveries.length)
|
|
5429
|
+
},
|
|
5430
|
+
counts: {
|
|
5431
|
+
channels: channels.length,
|
|
5432
|
+
enabledChannels: channels.filter((channel) => channel.enabled).length,
|
|
5433
|
+
disabledChannels: channels.filter((channel) => !channel.enabled).length,
|
|
5434
|
+
events: events.length,
|
|
5435
|
+
deliveries: deliveries.length
|
|
5436
|
+
},
|
|
5437
|
+
transports,
|
|
5438
|
+
safety: {
|
|
5439
|
+
includesEventPayloads: false,
|
|
5440
|
+
includesWebhookSecrets: false,
|
|
5441
|
+
listOutputsRedactSecrets: true,
|
|
5442
|
+
statusOutputIsMetadataOnly: true
|
|
5443
|
+
}
|
|
5444
|
+
};
|
|
5445
|
+
}
|
|
5446
|
+
function statusFile(dataDir, fileName, records) {
|
|
5447
|
+
const path = join(dataDir, fileName);
|
|
5448
|
+
return { path, exists: existsSync(path), records };
|
|
5449
|
+
}
|
|
5343
5450
|
var DEFAULT_SIGNATURE_TOLERANCE_MS = 5 * 60 * 1000;
|
|
5344
5451
|
function buildSignatureBase(timestamp, body) {
|
|
5345
5452
|
return `${timestamp}.${body}`;
|
|
@@ -5565,7 +5672,7 @@ class EventsClient {
|
|
|
5565
5672
|
}
|
|
5566
5673
|
return deliveries;
|
|
5567
5674
|
}
|
|
5568
|
-
async
|
|
5675
|
+
async matchChannel(id, input = {}) {
|
|
5569
5676
|
const channel = await this.store.getChannel(id);
|
|
5570
5677
|
if (!channel)
|
|
5571
5678
|
throw new Error(`Channel not found: ${id}`);
|
|
@@ -5582,6 +5689,34 @@ class EventsClient {
|
|
|
5582
5689
|
time: input.time,
|
|
5583
5690
|
id: input.id
|
|
5584
5691
|
});
|
|
5692
|
+
const matched = channelMatchesEvent(channel, event);
|
|
5693
|
+
return {
|
|
5694
|
+
channelId: channel.id,
|
|
5695
|
+
matched,
|
|
5696
|
+
event,
|
|
5697
|
+
filters: channel.filters,
|
|
5698
|
+
reason: matched ? undefined : channel.enabled ? "event did not match channel filters" : "channel is disabled"
|
|
5699
|
+
};
|
|
5700
|
+
}
|
|
5701
|
+
async testChannel(id, input = {}, options = {}) {
|
|
5702
|
+
const channel = await this.store.getChannel(id);
|
|
5703
|
+
if (!channel)
|
|
5704
|
+
throw new Error(`Channel not found: ${id}`);
|
|
5705
|
+
const match = await this.matchChannel(id, input);
|
|
5706
|
+
const event = match.event;
|
|
5707
|
+
if (options.honorFilters && !match.matched) {
|
|
5708
|
+
const timestamp = new Date().toISOString();
|
|
5709
|
+
const result2 = createDeliveryResult(event, channel, [{
|
|
5710
|
+
attempt: 1,
|
|
5711
|
+
status: "skipped",
|
|
5712
|
+
startedAt: timestamp,
|
|
5713
|
+
completedAt: timestamp,
|
|
5714
|
+
error: match.reason
|
|
5715
|
+
}]);
|
|
5716
|
+
result2.metadata = { reason: "filter_mismatch" };
|
|
5717
|
+
await this.store.appendDelivery(result2);
|
|
5718
|
+
return result2;
|
|
5719
|
+
}
|
|
5585
5720
|
const eventForChannel = await this.applyRedaction(event, channel);
|
|
5586
5721
|
const result = await this.deliverWithRetry(eventForChannel, channel);
|
|
5587
5722
|
await this.store.appendDelivery(result);
|
|
@@ -5692,6 +5827,76 @@ function normalizeRetryPolicy(policy) {
|
|
|
5692
5827
|
multiplier: Math.max(1, policy?.multiplier ?? 2)
|
|
5693
5828
|
};
|
|
5694
5829
|
}
|
|
5830
|
+
function parseFieldMatchers(values, label, typed = false) {
|
|
5831
|
+
if (!values?.length)
|
|
5832
|
+
return;
|
|
5833
|
+
const result = {};
|
|
5834
|
+
for (const value of values) {
|
|
5835
|
+
const parsed = parseMatcherExpression(value, label);
|
|
5836
|
+
const path = parsed.path;
|
|
5837
|
+
if (path in result)
|
|
5838
|
+
throw new Error(`Duplicate ${label} filter path: ${path}`);
|
|
5839
|
+
const matcherValue = typed ? parseTypedMatcherValue(parsed.rawValue, label) : parsed.rawValue;
|
|
5840
|
+
result[path] = parsed.negated ? { not: matcherValue } : matcherValue;
|
|
5841
|
+
}
|
|
5842
|
+
return result;
|
|
5843
|
+
}
|
|
5844
|
+
function parseFilterOptions(options) {
|
|
5845
|
+
const filter2 = {};
|
|
5846
|
+
if (options.source)
|
|
5847
|
+
filter2.source = options.source;
|
|
5848
|
+
if (options.type)
|
|
5849
|
+
filter2.type = options.type;
|
|
5850
|
+
if (options.subject)
|
|
5851
|
+
filter2.subject = options.subject;
|
|
5852
|
+
if (options.severity)
|
|
5853
|
+
filter2.severity = options.severity;
|
|
5854
|
+
const data = mergeMatchers(parseFieldMatchers(options.data, "data"), parseFieldMatchers(options.dataJson, "data-json", true));
|
|
5855
|
+
const metadata = mergeMatchers(parseFieldMatchers(options.metadata, "metadata"), parseFieldMatchers(options.metadataJson, "metadata-json", true));
|
|
5856
|
+
if (Object.keys(data).length > 0)
|
|
5857
|
+
filter2.data = data;
|
|
5858
|
+
if (Object.keys(metadata).length > 0)
|
|
5859
|
+
filter2.metadata = metadata;
|
|
5860
|
+
return Object.keys(filter2).length > 0 ? [filter2] : undefined;
|
|
5861
|
+
}
|
|
5862
|
+
function mergeMatchers(...records) {
|
|
5863
|
+
const result = {};
|
|
5864
|
+
for (const record of records) {
|
|
5865
|
+
if (!record)
|
|
5866
|
+
continue;
|
|
5867
|
+
for (const [path, value] of Object.entries(record)) {
|
|
5868
|
+
if (path in result)
|
|
5869
|
+
throw new Error(`Duplicate filter path: ${path}`);
|
|
5870
|
+
result[path] = value;
|
|
5871
|
+
}
|
|
5872
|
+
}
|
|
5873
|
+
return result;
|
|
5874
|
+
}
|
|
5875
|
+
function parseTypedMatcherValue(value, label) {
|
|
5876
|
+
const parsed = JSON.parse(value);
|
|
5877
|
+
if (parsed === null || typeof parsed === "string" || typeof parsed === "number" || typeof parsed === "boolean" || Array.isArray(parsed) && parsed.every((item) => typeof item === "string")) {
|
|
5878
|
+
return parsed;
|
|
5879
|
+
}
|
|
5880
|
+
throw new Error(`${label} filter JSON values must be string, string[], number, boolean, or null`);
|
|
5881
|
+
}
|
|
5882
|
+
function parseMatcherExpression(value, label) {
|
|
5883
|
+
const negativeSeparator = value.indexOf("!=");
|
|
5884
|
+
if (negativeSeparator > 0) {
|
|
5885
|
+
return {
|
|
5886
|
+
path: value.slice(0, negativeSeparator),
|
|
5887
|
+
rawValue: value.slice(negativeSeparator + 2),
|
|
5888
|
+
negated: true
|
|
5889
|
+
};
|
|
5890
|
+
}
|
|
5891
|
+
const separator = value.indexOf("=");
|
|
5892
|
+
if (separator <= 0)
|
|
5893
|
+
throw new Error(`Invalid ${label} filter, expected path=value or path!=value: ${value}`);
|
|
5894
|
+
return {
|
|
5895
|
+
path: value.slice(0, separator),
|
|
5896
|
+
rawValue: value.slice(separator + 1),
|
|
5897
|
+
negated: false
|
|
5898
|
+
};
|
|
5899
|
+
}
|
|
5695
5900
|
function parseJsonObject(value, fallback) {
|
|
5696
5901
|
if (!value)
|
|
5697
5902
|
return fallback;
|
|
@@ -5713,18 +5918,6 @@ function parseHeaders(values) {
|
|
|
5713
5918
|
}
|
|
5714
5919
|
return headers;
|
|
5715
5920
|
}
|
|
5716
|
-
function parseFilter(options) {
|
|
5717
|
-
const filter2 = {};
|
|
5718
|
-
if (options.source)
|
|
5719
|
-
filter2.source = options.source;
|
|
5720
|
-
if (options.type)
|
|
5721
|
-
filter2.type = options.type;
|
|
5722
|
-
if (options.subject)
|
|
5723
|
-
filter2.subject = options.subject;
|
|
5724
|
-
if (options.severity)
|
|
5725
|
-
filter2.severity = options.severity;
|
|
5726
|
-
return Object.keys(filter2).length > 0 ? [filter2] : undefined;
|
|
5727
|
-
}
|
|
5728
5921
|
function createClient(options) {
|
|
5729
5922
|
if (options.createClient)
|
|
5730
5923
|
return options.createClient();
|
|
@@ -5736,16 +5929,22 @@ function print(value, json, text) {
|
|
|
5736
5929
|
else
|
|
5737
5930
|
console.log(text);
|
|
5738
5931
|
}
|
|
5932
|
+
function hasJsonOption(options) {
|
|
5933
|
+
return Boolean(options?.json || options?.opts?.().json || options?.optsWithGlobals?.().json || options?.parent?.opts?.().json || options?.parent?.optsWithGlobals?.().json);
|
|
5934
|
+
}
|
|
5935
|
+
function wantsJson(actionOptions, command) {
|
|
5936
|
+
return hasJsonOption(actionOptions) || hasJsonOption(command);
|
|
5937
|
+
}
|
|
5739
5938
|
function registerWebhookCommands(program, options) {
|
|
5740
5939
|
const webhooks = program.command(options.webhooksCommandName ?? "webhooks").description("Manage Hasna event webhook subscriptions");
|
|
5741
|
-
webhooks.command("add").description("Add or replace a webhook or command subscription").argument("<target>", "Webhook URL or command binary").requiredOption("--id <id>", "Subscription/channel identifier").option("--transport <kind>", "Transport kind: webhook or command", "webhook").option("--name <name>", "Display name").option("--type <pattern>", "Event type filter, e.g. todos.task.*").option("--source <pattern>", "Event source filter").option("--subject <pattern>", "Event subject filter").option("--severity <pattern>", "Event severity filter").option("--secret <secret>", "Webhook HMAC secret").option("--header <name=value...>", "Webhook header", collectValues, []).option("--arg <arg...>", "Command argument", collectValues, []).option("--timeout-ms <ms>", "Transport timeout in milliseconds", parseNumber).option("--retry-attempts <n>", "Maximum delivery attempts", parseNumber).option("--retry-backoff-ms <ms>", "Initial retry backoff in milliseconds", parseNumber).option("--redact <path...>", "Event field path to redact before delivery", collectValues, []).option("--disabled", "Create channel disabled", false).option("-j, --json", "Print JSON output", false).action(async (target, actionOptions) => {
|
|
5940
|
+
webhooks.command("add").description("Add or replace a webhook or command subscription").argument("<target>", "Webhook URL or command binary").requiredOption("--id <id>", "Subscription/channel identifier").option("--transport <kind>", "Transport kind: webhook or command", "webhook").option("--name <name>", "Display name").option("--type <pattern>", "Event type filter, e.g. todos.task.*").option("--source <pattern>", "Event source filter").option("--subject <pattern>", "Event subject filter").option("--severity <pattern>", "Event severity filter").option("--data <path=value...>", "Event data field filter; string values, path!=value negatives, array-member matching, dot paths, * segment wildcard, ** recursive wildcard", collectValues, []).option("--metadata <path=value...>", "Event metadata field filter; string values, path!=value negatives, array-member matching, dot paths, * segment wildcard, ** recursive wildcard", collectValues, []).option("--data-json <path=json...>", "Event data field filter with typed JSON value; path!=json negatives supported", collectValues, []).option("--metadata-json <path=json...>", "Event metadata field filter with typed JSON value; path!=json negatives supported", collectValues, []).option("--secret <secret>", "Webhook HMAC secret").option("--header <name=value...>", "Webhook header", collectValues, []).option("--arg <arg...>", "Command argument", collectValues, []).option("--timeout-ms <ms>", "Transport timeout in milliseconds", parseNumber).option("--retry-attempts <n>", "Maximum delivery attempts", parseNumber).option("--retry-backoff-ms <ms>", "Initial retry backoff in milliseconds", parseNumber).option("--redact <path...>", "Event field path to redact before delivery", collectValues, []).option("--disabled", "Create channel disabled", false).option("-j, --json", "Print JSON output", false).action(async (target, actionOptions, command) => {
|
|
5742
5941
|
const timestamp = new Date().toISOString();
|
|
5743
5942
|
const channel = {
|
|
5744
5943
|
id: actionOptions.id,
|
|
5745
5944
|
name: actionOptions.name,
|
|
5746
5945
|
enabled: !actionOptions.disabled,
|
|
5747
5946
|
transport: actionOptions.transport,
|
|
5748
|
-
filters:
|
|
5947
|
+
filters: parseFilterOptions(actionOptions),
|
|
5749
5948
|
retry: actionOptions.retryAttempts || actionOptions.retryBackoffMs ? { maxAttempts: actionOptions.retryAttempts, backoffMs: actionOptions.retryBackoffMs } : undefined,
|
|
5750
5949
|
redact: actionOptions.redact?.length ? { paths: actionOptions.redact } : undefined,
|
|
5751
5950
|
createdAt: timestamp,
|
|
@@ -5759,11 +5958,11 @@ function registerWebhookCommands(program, options) {
|
|
|
5759
5958
|
throw new Error(`Transport ${actionOptions.transport} is reserved for future use and cannot be added yet`);
|
|
5760
5959
|
}
|
|
5761
5960
|
const saved = await createClient(options).addChannel(channel);
|
|
5762
|
-
print(sanitizeChannelForOutput(saved),
|
|
5961
|
+
print(sanitizeChannelForOutput(saved), wantsJson(actionOptions, command), `Added ${saved.transport} channel ${saved.id}`);
|
|
5763
5962
|
});
|
|
5764
|
-
webhooks.command("list").description("List configured subscriptions").option("-j, --json", "Print JSON output", false).action(async (actionOptions) => {
|
|
5963
|
+
webhooks.command("list").description("List configured subscriptions").option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
|
|
5765
5964
|
const channels = await createClient(options).listChannels();
|
|
5766
|
-
if (actionOptions
|
|
5965
|
+
if (wantsJson(actionOptions, command)) {
|
|
5767
5966
|
console.log(JSON.stringify(sanitizeChannelsForOutput(channels), null, 2));
|
|
5768
5967
|
return;
|
|
5769
5968
|
}
|
|
@@ -5775,25 +5974,41 @@ function registerWebhookCommands(program, options) {
|
|
|
5775
5974
|
console.log(`${channel.id} ${channel.enabled ? "enabled" : "disabled"} ${channel.transport} ${channel.webhook?.url ?? channel.command?.command ?? channel.transport}`);
|
|
5776
5975
|
}
|
|
5777
5976
|
});
|
|
5778
|
-
webhooks.command("
|
|
5977
|
+
webhooks.command("status").description("Show events webhook storage status").option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
|
|
5978
|
+
const status = await getEventsStatus(options.dataDir);
|
|
5979
|
+
print(status, wantsJson(actionOptions, command), `events dataDir: ${status.dataDir}`);
|
|
5980
|
+
});
|
|
5981
|
+
webhooks.command("remove").description("Remove a subscription").argument("<id>", "Subscription/channel identifier").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
|
|
5779
5982
|
const removed = await createClient(options).removeChannel(id);
|
|
5780
|
-
print({ removed },
|
|
5983
|
+
print({ removed }, wantsJson(actionOptions, command), removed ? `Removed ${id}` : `Channel not found: ${id}`);
|
|
5781
5984
|
});
|
|
5782
|
-
webhooks.command("test").description("Send a test event to one subscription").argument("<id>", "Subscription/channel identifier").option("--type <type>", "Event type", "events.test").option("--subject <subject>", "Event subject").option("--message <message>", "Event message", "Hasna events test delivery").option("--data <json>", "Event data JSON object").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions) => {
|
|
5985
|
+
webhooks.command("test").description("Send a test event to one subscription").argument("<id>", "Subscription/channel identifier").option("--source <source>", "Event source override").option("--type <type>", "Event type", "events.test").option("--subject <subject>", "Event subject").option("--message <message>", "Event message", "Hasna events test delivery").option("--data <json>", "Event data JSON object").option("--metadata <json>", "Event metadata JSON object").option("--honor-filters", "Skip delivery when the sample event does not match channel filters", false).option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
|
|
5783
5986
|
const result = await createClient(options).testChannel(id, {
|
|
5784
|
-
source: options.source,
|
|
5987
|
+
source: actionOptions.source ?? options.source,
|
|
5785
5988
|
type: actionOptions.type,
|
|
5786
5989
|
subject: actionOptions.subject ?? id,
|
|
5787
5990
|
message: actionOptions.message,
|
|
5788
|
-
data: parseJsonObject(actionOptions.data, { test: true })
|
|
5991
|
+
data: parseJsonObject(actionOptions.data, { test: true }),
|
|
5992
|
+
metadata: parseJsonObject(actionOptions.metadata, {})
|
|
5993
|
+
}, { honorFilters: actionOptions.honorFilters });
|
|
5994
|
+
print(result, wantsJson(actionOptions, command), `${result.status}: ${result.channelId}`);
|
|
5995
|
+
});
|
|
5996
|
+
webhooks.command("match").description("Check whether a sample event matches one subscription without delivering").argument("<id>", "Subscription/channel identifier").option("--source <source>", "Event source override").option("--type <type>", "Event type", "events.test").option("--subject <subject>", "Event subject").option("--message <message>", "Event message", "Hasna events match preview").option("--data <json>", "Event data JSON object").option("--metadata <json>", "Event metadata JSON object").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions, command) => {
|
|
5997
|
+
const result = await createClient(options).matchChannel(id, {
|
|
5998
|
+
source: actionOptions.source ?? options.source,
|
|
5999
|
+
type: actionOptions.type,
|
|
6000
|
+
subject: actionOptions.subject ?? id,
|
|
6001
|
+
message: actionOptions.message,
|
|
6002
|
+
data: parseJsonObject(actionOptions.data, { test: true }),
|
|
6003
|
+
metadata: parseJsonObject(actionOptions.metadata, {})
|
|
5789
6004
|
});
|
|
5790
|
-
print(result,
|
|
6005
|
+
print(result, wantsJson(actionOptions, command), `${result.matched ? "matched" : "skipped"}: ${result.channelId}`);
|
|
5791
6006
|
});
|
|
5792
6007
|
return webhooks;
|
|
5793
6008
|
}
|
|
5794
6009
|
function registerEventCommands(program, options) {
|
|
5795
6010
|
const events = program.command(options.eventsCommandName ?? "events").description("Emit, list, and replay Hasna events");
|
|
5796
|
-
events.command("emit").description("Emit an event from this app").argument("<type>", "Event type").option("--source <source>", "Event source override").option("--subject <subject>", "Event subject").option("--severity <severity>", "Event severity", "info").option("--message <message>", "Event message").option("--dedupe-key <key>", "Dedupe key").option("--data <json>", "Event data JSON object").option("--metadata <json>", "Event metadata JSON object").option("--no-deliver", "Record without delivering").option("--no-dedupe", "Allow duplicate id/dedupeKey events").option("-j, --json", "Print JSON output", false).action(async (type, actionOptions) => {
|
|
6011
|
+
events.command("emit").description("Emit an event from this app").argument("<type>", "Event type").option("--source <source>", "Event source override").option("--subject <subject>", "Event subject").option("--severity <severity>", "Event severity", "info").option("--message <message>", "Event message").option("--dedupe-key <key>", "Dedupe key").option("--data <json>", "Event data JSON object").option("--metadata <json>", "Event metadata JSON object").option("--no-deliver", "Record without delivering").option("--no-dedupe", "Allow duplicate id/dedupeKey events").option("-j, --json", "Print JSON output", false).action(async (type, actionOptions, command) => {
|
|
5797
6012
|
const result = await createClient(options).emit({
|
|
5798
6013
|
source: actionOptions.source ?? options.source,
|
|
5799
6014
|
type,
|
|
@@ -5804,9 +6019,9 @@ function registerEventCommands(program, options) {
|
|
|
5804
6019
|
data: parseJsonObject(actionOptions.data, {}),
|
|
5805
6020
|
metadata: parseJsonObject(actionOptions.metadata, {})
|
|
5806
6021
|
}, { deliver: actionOptions.deliver, dedupe: actionOptions.dedupe });
|
|
5807
|
-
print(result,
|
|
6022
|
+
print(result, wantsJson(actionOptions, command), `${result.deduped ? "Deduped" : "Emitted"} ${result.event.id} to ${result.deliveries.length} channel(s)`);
|
|
5808
6023
|
});
|
|
5809
|
-
events.command("list").description("List recorded events").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--limit <n>", "Limit results", parseNumber).option("-j, --json", "Print JSON output", false).action(async (actionOptions) => {
|
|
6024
|
+
events.command("list").description("List recorded events").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--limit <n>", "Limit results", parseNumber).option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
|
|
5810
6025
|
let rows = await createClient(options).listEvents();
|
|
5811
6026
|
if (actionOptions.source)
|
|
5812
6027
|
rows = rows.filter((event) => event.source === actionOptions.source);
|
|
@@ -5814,7 +6029,7 @@ function registerEventCommands(program, options) {
|
|
|
5814
6029
|
rows = rows.filter((event) => event.type === actionOptions.type);
|
|
5815
6030
|
if (actionOptions.limit)
|
|
5816
6031
|
rows = rows.slice(-actionOptions.limit);
|
|
5817
|
-
if (actionOptions
|
|
6032
|
+
if (wantsJson(actionOptions, command)) {
|
|
5818
6033
|
console.log(JSON.stringify(rows, null, 2));
|
|
5819
6034
|
return;
|
|
5820
6035
|
}
|
|
@@ -5825,14 +6040,14 @@ function registerEventCommands(program, options) {
|
|
|
5825
6040
|
for (const event of rows)
|
|
5826
6041
|
console.log(`${event.time} ${event.id} ${event.source} ${event.type} ${event.severity}`);
|
|
5827
6042
|
});
|
|
5828
|
-
events.command("replay").description("Replay recorded events").option("--id <id>", "Replay one event id").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--dry-run", "Preview without delivery", false).option("-j, --json", "Print JSON output", false).action(async (actionOptions) => {
|
|
6043
|
+
events.command("replay").description("Replay recorded events").option("--id <id>", "Replay one event id").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--dry-run", "Preview without delivery", false).option("-j, --json", "Print JSON output", false).action(async (actionOptions, command) => {
|
|
5829
6044
|
const result = await createClient(options).replay({
|
|
5830
6045
|
eventId: actionOptions.id,
|
|
5831
6046
|
source: actionOptions.source,
|
|
5832
6047
|
type: actionOptions.type,
|
|
5833
6048
|
dryRun: actionOptions.dryRun
|
|
5834
6049
|
});
|
|
5835
|
-
print(result,
|
|
6050
|
+
print(result, wantsJson(actionOptions, command), `Replayed ${result.events.length} event(s), ${result.deliveries.length} delivery result(s)`);
|
|
5836
6051
|
});
|
|
5837
6052
|
return events;
|
|
5838
6053
|
}
|
|
@@ -5855,12 +6070,12 @@ function collectValues(value, previous) {
|
|
|
5855
6070
|
import chalk2 from "chalk";
|
|
5856
6071
|
import { spawnSync } from "child_process";
|
|
5857
6072
|
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
|
|
5858
|
-
import { dirname as
|
|
6073
|
+
import { dirname as dirname3, join as pathJoin } from "path";
|
|
5859
6074
|
import { fileURLToPath } from "url";
|
|
5860
6075
|
|
|
5861
6076
|
// src/lib/config.ts
|
|
5862
|
-
import { existsSync as existsSync2, readFileSync, mkdirSync,
|
|
5863
|
-
import { join as join2 } from "path";
|
|
6077
|
+
import { copyFileSync, existsSync as existsSync2, readFileSync, mkdirSync, readdirSync, statSync } from "fs";
|
|
6078
|
+
import { dirname, join as join2, resolve } from "path";
|
|
5864
6079
|
import { homedir as homedir2 } from "os";
|
|
5865
6080
|
var DEFAULT_CONFIG = {
|
|
5866
6081
|
openai_api_key: "",
|
|
@@ -5954,44 +6169,53 @@ function expandEnvBackedConfig(config) {
|
|
|
5954
6169
|
return expanded;
|
|
5955
6170
|
}
|
|
5956
6171
|
function findConfigFile() {
|
|
5957
|
-
|
|
5958
|
-
const root = "/";
|
|
5959
|
-
while (dir !== root) {
|
|
5960
|
-
const candidate = join2(dir, ".recordings", "config.json");
|
|
5961
|
-
if (existsSync2(candidate))
|
|
5962
|
-
return candidate;
|
|
5963
|
-
const parent = join2(dir, "..");
|
|
5964
|
-
if (parent === dir)
|
|
5965
|
-
break;
|
|
5966
|
-
dir = parent;
|
|
5967
|
-
}
|
|
5968
|
-
return null;
|
|
6172
|
+
return findProjectRecordingsPath("config.json");
|
|
5969
6173
|
}
|
|
5970
6174
|
function getDataDir() {
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
if (existsSync2(candidate))
|
|
5976
|
-
return candidate;
|
|
5977
|
-
const parent = join2(dir, "..");
|
|
5978
|
-
if (parent === dir)
|
|
5979
|
-
break;
|
|
5980
|
-
dir = parent;
|
|
5981
|
-
}
|
|
5982
|
-
const home = homedir2();
|
|
6175
|
+
const projectLocalDir = findProjectRecordingsPath();
|
|
6176
|
+
if (projectLocalDir)
|
|
6177
|
+
return projectLocalDir;
|
|
6178
|
+
const home = getHomeDir();
|
|
5983
6179
|
const newDir = join2(home, ".hasna", "recordings");
|
|
5984
6180
|
const oldDir = join2(home, ".recordings");
|
|
5985
|
-
if (
|
|
6181
|
+
if (existsSync2(oldDir)) {
|
|
5986
6182
|
try {
|
|
5987
|
-
|
|
5988
|
-
cpSync(oldDir, newDir, { recursive: true });
|
|
6183
|
+
mergeDirectoryContents(oldDir, newDir);
|
|
5989
6184
|
} catch {}
|
|
5990
6185
|
}
|
|
5991
6186
|
return newDir;
|
|
5992
6187
|
}
|
|
6188
|
+
function findProjectRecordingsPath(entry) {
|
|
6189
|
+
const home = resolve(getHomeDir());
|
|
6190
|
+
let dir = resolve(process.cwd());
|
|
6191
|
+
while (true) {
|
|
6192
|
+
if (dir !== home) {
|
|
6193
|
+
const candidate = entry ? join2(dir, ".recordings", entry) : join2(dir, ".recordings");
|
|
6194
|
+
if (existsSync2(candidate))
|
|
6195
|
+
return candidate;
|
|
6196
|
+
}
|
|
6197
|
+
const parent = dirname(dir);
|
|
6198
|
+
if (parent === dir)
|
|
6199
|
+
break;
|
|
6200
|
+
dir = parent;
|
|
6201
|
+
}
|
|
6202
|
+
return null;
|
|
6203
|
+
}
|
|
6204
|
+
function mergeDirectoryContents(sourceDir, targetDir) {
|
|
6205
|
+
mkdirSync(targetDir, { recursive: true });
|
|
6206
|
+
for (const entry of readdirSync(sourceDir)) {
|
|
6207
|
+
const sourcePath = join2(sourceDir, entry);
|
|
6208
|
+
const targetPath = join2(targetDir, entry);
|
|
6209
|
+
const sourceStats = statSync(sourcePath);
|
|
6210
|
+
if (sourceStats.isDirectory()) {
|
|
6211
|
+
mergeDirectoryContents(sourcePath, targetPath);
|
|
6212
|
+
} else if (!existsSync2(targetPath)) {
|
|
6213
|
+
copyFileSync(sourcePath, targetPath);
|
|
6214
|
+
}
|
|
6215
|
+
}
|
|
6216
|
+
}
|
|
5993
6217
|
function loadSecretKey(keyName) {
|
|
5994
|
-
const secretsPath = join2(
|
|
6218
|
+
const secretsPath = join2(getHomeDir(), ".secrets");
|
|
5995
6219
|
if (!existsSync2(secretsPath))
|
|
5996
6220
|
return "";
|
|
5997
6221
|
for (const candidate of listSecretFiles(secretsPath)) {
|
|
@@ -6032,6 +6256,9 @@ function listSecretFiles(path) {
|
|
|
6032
6256
|
return [];
|
|
6033
6257
|
}
|
|
6034
6258
|
}
|
|
6259
|
+
function getHomeDir() {
|
|
6260
|
+
return process.env["HOME"] || process.env["USERPROFILE"] || homedir2();
|
|
6261
|
+
}
|
|
6035
6262
|
function ensureDataDir(config) {
|
|
6036
6263
|
const { mkdirSync: mkdirSync2 } = __require("fs");
|
|
6037
6264
|
mkdirSync2(config.audio_dir, { recursive: true });
|
|
@@ -6073,7 +6300,7 @@ class SqliteAdapter {
|
|
|
6073
6300
|
|
|
6074
6301
|
// src/db/database.ts
|
|
6075
6302
|
import { mkdirSync as mkdirSync2 } from "fs";
|
|
6076
|
-
import { dirname } from "path";
|
|
6303
|
+
import { dirname as dirname2 } from "path";
|
|
6077
6304
|
var _db = null;
|
|
6078
6305
|
var _adapter = null;
|
|
6079
6306
|
var MIGRATIONS = [
|
|
@@ -6159,7 +6386,7 @@ function getDatabase(dbPath) {
|
|
|
6159
6386
|
if (_db)
|
|
6160
6387
|
return _db;
|
|
6161
6388
|
const path = dbPath || loadConfig().db_path;
|
|
6162
|
-
const dir =
|
|
6389
|
+
const dir = dirname2(path);
|
|
6163
6390
|
mkdirSync2(dir, { recursive: true });
|
|
6164
6391
|
_adapter = new SqliteAdapter(path);
|
|
6165
6392
|
_db = _adapter.raw;
|
|
@@ -6762,7 +6989,7 @@ async function processText(rawText, config, systemPrompt) {
|
|
|
6762
6989
|
}
|
|
6763
6990
|
|
|
6764
6991
|
// src/version.ts
|
|
6765
|
-
var VERSION = "0.1.
|
|
6992
|
+
var VERSION = "0.1.35";
|
|
6766
6993
|
|
|
6767
6994
|
// src/cli/storage.ts
|
|
6768
6995
|
import chalk from "chalk";
|
|
@@ -7156,13 +7383,13 @@ program.command("record").description("Record from microphone, transcribe, and o
|
|
|
7156
7383
|
} else {
|
|
7157
7384
|
console.log(chalk2.blue("Recording... Press") + chalk2.yellow(" Enter ") + chalk2.blue("to stop."));
|
|
7158
7385
|
audioPath = startRecording(config);
|
|
7159
|
-
await new Promise((
|
|
7386
|
+
await new Promise((resolve2) => {
|
|
7160
7387
|
process.stdin.setRawMode?.(true);
|
|
7161
7388
|
process.stdin.resume();
|
|
7162
7389
|
process.stdin.once("data", () => {
|
|
7163
7390
|
process.stdin.setRawMode?.(false);
|
|
7164
7391
|
process.stdin.pause();
|
|
7165
|
-
|
|
7392
|
+
resolve2();
|
|
7166
7393
|
});
|
|
7167
7394
|
});
|
|
7168
7395
|
stopRecording();
|
|
@@ -8086,7 +8313,7 @@ function tccAuthValueLabel(value) {
|
|
|
8086
8313
|
}
|
|
8087
8314
|
}
|
|
8088
8315
|
function findPackageRoot() {
|
|
8089
|
-
let current =
|
|
8316
|
+
let current = dirname3(fileURLToPath(import.meta.url));
|
|
8090
8317
|
while (true) {
|
|
8091
8318
|
const packagePath = pathJoin(current, "package.json");
|
|
8092
8319
|
if (existsSync5(packagePath)) {
|
|
@@ -8097,7 +8324,7 @@ function findPackageRoot() {
|
|
|
8097
8324
|
}
|
|
8098
8325
|
} catch {}
|
|
8099
8326
|
}
|
|
8100
|
-
const parent =
|
|
8327
|
+
const parent = dirname3(current);
|
|
8101
8328
|
if (parent === current) {
|
|
8102
8329
|
return process.cwd();
|
|
8103
8330
|
}
|