opensteer 0.8.8 → 0.8.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/{chunk-3QJGBVWT.js → chunk-F3X6UOEN.js} +3338 -822
- package/dist/chunk-F3X6UOEN.js.map +1 -0
- package/dist/cli/bin.cjs +3591 -885
- package/dist/cli/bin.cjs.map +1 -1
- package/dist/cli/bin.js +293 -78
- package/dist/cli/bin.js.map +1 -1
- package/dist/index.cjs +1770 -855
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +206 -15
- package/dist/index.d.ts +206 -15
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/skills/opensteer/SKILL.md +47 -71
- package/skills/opensteer/references/cli-reference.md +2 -0
- package/skills/opensteer/references/request-workflow.md +309 -203
- package/skills/opensteer/references/sdk-reference.md +104 -14
- package/skills/recorder/SKILL.md +54 -0
- package/skills/recorder/references/recorder-reference.md +71 -0
- package/dist/chunk-3QJGBVWT.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var path7 = require('path');
|
|
4
4
|
var crypto = require('crypto');
|
|
5
5
|
var promises = require('fs/promises');
|
|
6
6
|
var url = require('url');
|
|
@@ -10,6 +10,7 @@ var os = require('os');
|
|
|
10
10
|
var enginePlaywright = require('@opensteer/engine-playwright');
|
|
11
11
|
var util = require('util');
|
|
12
12
|
var fs = require('fs');
|
|
13
|
+
var async_hooks = require('async_hooks');
|
|
13
14
|
var module$1 = require('module');
|
|
14
15
|
var sharp = require('sharp');
|
|
15
16
|
var cheerio = require('cheerio');
|
|
@@ -39,14 +40,19 @@ function _interopNamespace(e) {
|
|
|
39
40
|
return Object.freeze(n);
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
var
|
|
43
|
+
var path7__default = /*#__PURE__*/_interopDefault(path7);
|
|
43
44
|
var sharp__default = /*#__PURE__*/_interopDefault(sharp);
|
|
44
45
|
var cheerio__namespace = /*#__PURE__*/_interopNamespace(cheerio);
|
|
45
46
|
var prettier__namespace = /*#__PURE__*/_interopNamespace(prettier);
|
|
46
47
|
var vm__default = /*#__PURE__*/_interopDefault(vm);
|
|
47
48
|
var WebSocket2__default = /*#__PURE__*/_interopDefault(WebSocket2);
|
|
48
49
|
|
|
49
|
-
|
|
50
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
51
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
52
|
+
}) : x)(function(x) {
|
|
53
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
54
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
55
|
+
});
|
|
50
56
|
|
|
51
57
|
// ../runtime-core/src/json.ts
|
|
52
58
|
function isPlainObject(value) {
|
|
@@ -56,30 +62,30 @@ function isPlainObject(value) {
|
|
|
56
62
|
const prototype = Object.getPrototypeOf(value);
|
|
57
63
|
return prototype === Object.prototype || prototype === null;
|
|
58
64
|
}
|
|
59
|
-
function canonicalizeJsonValue(value,
|
|
65
|
+
function canonicalizeJsonValue(value, path15) {
|
|
60
66
|
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
61
67
|
return value;
|
|
62
68
|
}
|
|
63
69
|
if (typeof value === "number") {
|
|
64
70
|
if (!Number.isFinite(value)) {
|
|
65
|
-
throw new TypeError(`${
|
|
71
|
+
throw new TypeError(`${path15} must be a finite JSON number`);
|
|
66
72
|
}
|
|
67
73
|
return value;
|
|
68
74
|
}
|
|
69
75
|
if (Array.isArray(value)) {
|
|
70
|
-
return value.map((entry, index) => canonicalizeJsonValue(entry, `${
|
|
76
|
+
return value.map((entry, index) => canonicalizeJsonValue(entry, `${path15}[${index}]`));
|
|
71
77
|
}
|
|
72
78
|
if (!isPlainObject(value)) {
|
|
73
|
-
throw new TypeError(`${
|
|
79
|
+
throw new TypeError(`${path15} must be a plain JSON object`);
|
|
74
80
|
}
|
|
75
81
|
const sorted = Object.keys(value).sort((left, right) => left.localeCompare(right));
|
|
76
82
|
const result = {};
|
|
77
83
|
for (const key of sorted) {
|
|
78
84
|
const entry = value[key];
|
|
79
85
|
if (entry === void 0) {
|
|
80
|
-
throw new TypeError(`${
|
|
86
|
+
throw new TypeError(`${path15}.${key} must not be undefined`);
|
|
81
87
|
}
|
|
82
|
-
result[key] = canonicalizeJsonValue(entry, `${
|
|
88
|
+
result[key] = canonicalizeJsonValue(entry, `${path15}.${key}`);
|
|
83
89
|
}
|
|
84
90
|
return result;
|
|
85
91
|
}
|
|
@@ -116,7 +122,7 @@ function joinStoragePath(...segments) {
|
|
|
116
122
|
return segments.join("/");
|
|
117
123
|
}
|
|
118
124
|
function resolveStoragePath(rootPath, relativePath) {
|
|
119
|
-
if (
|
|
125
|
+
if (path7__default.default.isAbsolute(relativePath)) {
|
|
120
126
|
throw new TypeError(`storage path ${relativePath} must be relative`);
|
|
121
127
|
}
|
|
122
128
|
const segments = relativePath.split("/");
|
|
@@ -128,7 +134,7 @@ function resolveStoragePath(rootPath, relativePath) {
|
|
|
128
134
|
throw new TypeError(`storage path ${relativePath} must not contain path traversal`);
|
|
129
135
|
}
|
|
130
136
|
}
|
|
131
|
-
return
|
|
137
|
+
return path7__default.default.join(rootPath, ...segments);
|
|
132
138
|
}
|
|
133
139
|
async function ensureDirectory(directoryPath) {
|
|
134
140
|
await promises.mkdir(directoryPath, { recursive: true });
|
|
@@ -148,7 +154,7 @@ async function writeJsonFileAtomic(filePath, value) {
|
|
|
148
154
|
await writeTextFileAtomic(filePath, stableJsonString(value));
|
|
149
155
|
}
|
|
150
156
|
async function writeTextFileAtomic(filePath, value) {
|
|
151
|
-
await ensureDirectory(
|
|
157
|
+
await ensureDirectory(path7__default.default.dirname(filePath));
|
|
152
158
|
const temporaryPath = `${filePath}.${crypto.randomUUID()}.tmp`;
|
|
153
159
|
await promises.writeFile(temporaryPath, value, "utf8");
|
|
154
160
|
await promises.rename(temporaryPath, filePath);
|
|
@@ -157,7 +163,7 @@ async function writeJsonFileExclusive(filePath, value) {
|
|
|
157
163
|
await writeTextFileExclusive(filePath, stableJsonString(value));
|
|
158
164
|
}
|
|
159
165
|
async function writeTextFileExclusive(filePath, value) {
|
|
160
|
-
await ensureDirectory(
|
|
166
|
+
await ensureDirectory(path7__default.default.dirname(filePath));
|
|
161
167
|
const handle = await promises.open(filePath, "wx");
|
|
162
168
|
try {
|
|
163
169
|
await handle.writeFile(value, "utf8");
|
|
@@ -166,7 +172,7 @@ async function writeTextFileExclusive(filePath, value) {
|
|
|
166
172
|
}
|
|
167
173
|
}
|
|
168
174
|
async function writeBufferIfMissing(filePath, value) {
|
|
169
|
-
await ensureDirectory(
|
|
175
|
+
await ensureDirectory(path7__default.default.dirname(filePath));
|
|
170
176
|
try {
|
|
171
177
|
const handle = await promises.open(filePath, "wx");
|
|
172
178
|
try {
|
|
@@ -200,7 +206,7 @@ function isAlreadyExistsError(error) {
|
|
|
200
206
|
return error?.code === "EEXIST";
|
|
201
207
|
}
|
|
202
208
|
async function withFilesystemLock(lockPath, task) {
|
|
203
|
-
await ensureDirectory(
|
|
209
|
+
await ensureDirectory(path7__default.default.dirname(lockPath));
|
|
204
210
|
let attempt = 0;
|
|
205
211
|
while (true) {
|
|
206
212
|
try {
|
|
@@ -212,7 +218,7 @@ async function withFilesystemLock(lockPath, task) {
|
|
|
212
218
|
}
|
|
213
219
|
const delayMs = LOCK_RETRY_DELAYS_MS[Math.min(attempt, LOCK_RETRY_DELAYS_MS.length - 1)];
|
|
214
220
|
attempt += 1;
|
|
215
|
-
await new Promise((
|
|
221
|
+
await new Promise((resolve4) => setTimeout(resolve4, delayMs));
|
|
216
222
|
}
|
|
217
223
|
}
|
|
218
224
|
try {
|
|
@@ -255,8 +261,8 @@ async function readStructuredPayload(objectPath) {
|
|
|
255
261
|
var FilesystemArtifactStore = class {
|
|
256
262
|
constructor(rootPath) {
|
|
257
263
|
this.rootPath = rootPath;
|
|
258
|
-
this.manifestsDirectory =
|
|
259
|
-
this.objectsDirectory =
|
|
264
|
+
this.manifestsDirectory = path7__default.default.join(this.rootPath, "artifacts", "manifests");
|
|
265
|
+
this.objectsDirectory = path7__default.default.join(this.rootPath, "artifacts", "objects", "sha256");
|
|
260
266
|
}
|
|
261
267
|
manifestsDirectory;
|
|
262
268
|
objectsDirectory;
|
|
@@ -481,7 +487,7 @@ var FilesystemArtifactStore = class {
|
|
|
481
487
|
}
|
|
482
488
|
}
|
|
483
489
|
manifestPath(artifactId) {
|
|
484
|
-
return
|
|
490
|
+
return path7__default.default.join(this.manifestsDirectory, `${encodePathSegment(artifactId)}.json`);
|
|
485
491
|
}
|
|
486
492
|
};
|
|
487
493
|
function createArtifactStore(rootPath) {
|
|
@@ -576,31 +582,31 @@ function oneOfSchema(members, options = {}) {
|
|
|
576
582
|
}
|
|
577
583
|
|
|
578
584
|
// ../protocol/src/validation.ts
|
|
579
|
-
function validateJsonSchema(schema, value,
|
|
580
|
-
return validateSchemaNode(schema, value,
|
|
585
|
+
function validateJsonSchema(schema, value, path15 = "$") {
|
|
586
|
+
return validateSchemaNode(schema, value, path15);
|
|
581
587
|
}
|
|
582
|
-
function validateSchemaNode(schema, value,
|
|
588
|
+
function validateSchemaNode(schema, value, path15) {
|
|
583
589
|
const issues = [];
|
|
584
590
|
if ("const" in schema && !isJsonValueEqual(schema.const, value)) {
|
|
585
591
|
issues.push({
|
|
586
|
-
path:
|
|
592
|
+
path: path15,
|
|
587
593
|
message: `must equal ${JSON.stringify(schema.const)}`
|
|
588
594
|
});
|
|
589
595
|
return issues;
|
|
590
596
|
}
|
|
591
597
|
if (schema.enum !== void 0 && !schema.enum.some((candidate) => isJsonValueEqual(candidate, value))) {
|
|
592
598
|
issues.push({
|
|
593
|
-
path:
|
|
599
|
+
path: path15,
|
|
594
600
|
message: `must be one of ${schema.enum.map((candidate) => JSON.stringify(candidate)).join(", ")}`
|
|
595
601
|
});
|
|
596
602
|
return issues;
|
|
597
603
|
}
|
|
598
604
|
if (schema.oneOf !== void 0) {
|
|
599
|
-
const branchIssues = schema.oneOf.map((member) => validateSchemaNode(member, value,
|
|
605
|
+
const branchIssues = schema.oneOf.map((member) => validateSchemaNode(member, value, path15));
|
|
600
606
|
const validBranches = branchIssues.filter((current) => current.length === 0).length;
|
|
601
607
|
if (validBranches !== 1) {
|
|
602
608
|
issues.push({
|
|
603
|
-
path:
|
|
609
|
+
path: path15,
|
|
604
610
|
message: validBranches === 0 ? "must match exactly one supported shape" : "matches multiple supported shapes"
|
|
605
611
|
});
|
|
606
612
|
return issues;
|
|
@@ -608,11 +614,11 @@ function validateSchemaNode(schema, value, path13) {
|
|
|
608
614
|
}
|
|
609
615
|
if (schema.anyOf !== void 0) {
|
|
610
616
|
const hasMatch = schema.anyOf.some(
|
|
611
|
-
(member) => validateSchemaNode(member, value,
|
|
617
|
+
(member) => validateSchemaNode(member, value, path15).length === 0
|
|
612
618
|
);
|
|
613
619
|
if (!hasMatch) {
|
|
614
620
|
issues.push({
|
|
615
|
-
path:
|
|
621
|
+
path: path15,
|
|
616
622
|
message: "must match at least one supported shape"
|
|
617
623
|
});
|
|
618
624
|
return issues;
|
|
@@ -620,7 +626,7 @@ function validateSchemaNode(schema, value, path13) {
|
|
|
620
626
|
}
|
|
621
627
|
if (schema.allOf !== void 0) {
|
|
622
628
|
for (const member of schema.allOf) {
|
|
623
|
-
issues.push(...validateSchemaNode(member, value,
|
|
629
|
+
issues.push(...validateSchemaNode(member, value, path15));
|
|
624
630
|
}
|
|
625
631
|
if (issues.length > 0) {
|
|
626
632
|
return issues;
|
|
@@ -628,7 +634,7 @@ function validateSchemaNode(schema, value, path13) {
|
|
|
628
634
|
}
|
|
629
635
|
if (schema.type !== void 0 && !matchesSchemaType(schema.type, value)) {
|
|
630
636
|
issues.push({
|
|
631
|
-
path:
|
|
637
|
+
path: path15,
|
|
632
638
|
message: `must be ${describeSchemaType(schema.type)}`
|
|
633
639
|
});
|
|
634
640
|
return issues;
|
|
@@ -636,19 +642,19 @@ function validateSchemaNode(schema, value, path13) {
|
|
|
636
642
|
if (typeof value === "string") {
|
|
637
643
|
if (schema.minLength !== void 0 && value.length < schema.minLength) {
|
|
638
644
|
issues.push({
|
|
639
|
-
path:
|
|
645
|
+
path: path15,
|
|
640
646
|
message: `must have length >= ${String(schema.minLength)}`
|
|
641
647
|
});
|
|
642
648
|
}
|
|
643
649
|
if (schema.maxLength !== void 0 && value.length > schema.maxLength) {
|
|
644
650
|
issues.push({
|
|
645
|
-
path:
|
|
651
|
+
path: path15,
|
|
646
652
|
message: `must have length <= ${String(schema.maxLength)}`
|
|
647
653
|
});
|
|
648
654
|
}
|
|
649
655
|
if (schema.pattern !== void 0 && !new RegExp(schema.pattern).test(value)) {
|
|
650
656
|
issues.push({
|
|
651
|
-
path:
|
|
657
|
+
path: path15,
|
|
652
658
|
message: `must match pattern ${schema.pattern}`
|
|
653
659
|
});
|
|
654
660
|
}
|
|
@@ -657,25 +663,25 @@ function validateSchemaNode(schema, value, path13) {
|
|
|
657
663
|
if (typeof value === "number") {
|
|
658
664
|
if (schema.minimum !== void 0 && value < schema.minimum) {
|
|
659
665
|
issues.push({
|
|
660
|
-
path:
|
|
666
|
+
path: path15,
|
|
661
667
|
message: `must be >= ${String(schema.minimum)}`
|
|
662
668
|
});
|
|
663
669
|
}
|
|
664
670
|
if (schema.maximum !== void 0 && value > schema.maximum) {
|
|
665
671
|
issues.push({
|
|
666
|
-
path:
|
|
672
|
+
path: path15,
|
|
667
673
|
message: `must be <= ${String(schema.maximum)}`
|
|
668
674
|
});
|
|
669
675
|
}
|
|
670
676
|
if (schema.exclusiveMinimum !== void 0 && value <= schema.exclusiveMinimum) {
|
|
671
677
|
issues.push({
|
|
672
|
-
path:
|
|
678
|
+
path: path15,
|
|
673
679
|
message: `must be > ${String(schema.exclusiveMinimum)}`
|
|
674
680
|
});
|
|
675
681
|
}
|
|
676
682
|
if (schema.exclusiveMaximum !== void 0 && value >= schema.exclusiveMaximum) {
|
|
677
683
|
issues.push({
|
|
678
|
-
path:
|
|
684
|
+
path: path15,
|
|
679
685
|
message: `must be < ${String(schema.exclusiveMaximum)}`
|
|
680
686
|
});
|
|
681
687
|
}
|
|
@@ -684,13 +690,13 @@ function validateSchemaNode(schema, value, path13) {
|
|
|
684
690
|
if (Array.isArray(value)) {
|
|
685
691
|
if (schema.minItems !== void 0 && value.length < schema.minItems) {
|
|
686
692
|
issues.push({
|
|
687
|
-
path:
|
|
693
|
+
path: path15,
|
|
688
694
|
message: `must have at least ${String(schema.minItems)} items`
|
|
689
695
|
});
|
|
690
696
|
}
|
|
691
697
|
if (schema.maxItems !== void 0 && value.length > schema.maxItems) {
|
|
692
698
|
issues.push({
|
|
693
|
-
path:
|
|
699
|
+
path: path15,
|
|
694
700
|
message: `must have at most ${String(schema.maxItems)} items`
|
|
695
701
|
});
|
|
696
702
|
}
|
|
@@ -700,7 +706,7 @@ function validateSchemaNode(schema, value, path13) {
|
|
|
700
706
|
const key = JSON.stringify(item);
|
|
701
707
|
if (seen.has(key)) {
|
|
702
708
|
issues.push({
|
|
703
|
-
path:
|
|
709
|
+
path: path15,
|
|
704
710
|
message: "must not contain duplicate items"
|
|
705
711
|
});
|
|
706
712
|
break;
|
|
@@ -710,7 +716,7 @@ function validateSchemaNode(schema, value, path13) {
|
|
|
710
716
|
}
|
|
711
717
|
if (schema.items !== void 0) {
|
|
712
718
|
for (let index = 0; index < value.length; index += 1) {
|
|
713
|
-
issues.push(...validateSchemaNode(schema.items, value[index], `${
|
|
719
|
+
issues.push(...validateSchemaNode(schema.items, value[index], `${path15}[${String(index)}]`));
|
|
714
720
|
}
|
|
715
721
|
}
|
|
716
722
|
return issues;
|
|
@@ -720,7 +726,7 @@ function validateSchemaNode(schema, value, path13) {
|
|
|
720
726
|
for (const requiredKey of schema.required ?? []) {
|
|
721
727
|
if (!(requiredKey in value)) {
|
|
722
728
|
issues.push({
|
|
723
|
-
path: joinObjectPath(
|
|
729
|
+
path: joinObjectPath(path15, requiredKey),
|
|
724
730
|
message: "is required"
|
|
725
731
|
});
|
|
726
732
|
}
|
|
@@ -729,13 +735,13 @@ function validateSchemaNode(schema, value, path13) {
|
|
|
729
735
|
const propertySchema = properties[key];
|
|
730
736
|
if (propertySchema !== void 0) {
|
|
731
737
|
issues.push(
|
|
732
|
-
...validateSchemaNode(propertySchema, propertyValue, joinObjectPath(
|
|
738
|
+
...validateSchemaNode(propertySchema, propertyValue, joinObjectPath(path15, key))
|
|
733
739
|
);
|
|
734
740
|
continue;
|
|
735
741
|
}
|
|
736
742
|
if (schema.additionalProperties === false) {
|
|
737
743
|
issues.push({
|
|
738
|
-
path: joinObjectPath(
|
|
744
|
+
path: joinObjectPath(path15, key),
|
|
739
745
|
message: "is not allowed"
|
|
740
746
|
});
|
|
741
747
|
continue;
|
|
@@ -745,7 +751,7 @@ function validateSchemaNode(schema, value, path13) {
|
|
|
745
751
|
...validateSchemaNode(
|
|
746
752
|
schema.additionalProperties,
|
|
747
753
|
propertyValue,
|
|
748
|
-
joinObjectPath(
|
|
754
|
+
joinObjectPath(path15, key)
|
|
749
755
|
)
|
|
750
756
|
);
|
|
751
757
|
}
|
|
@@ -989,8 +995,8 @@ function matchesNetworkRecordFilters(record, filters) {
|
|
|
989
995
|
}
|
|
990
996
|
}
|
|
991
997
|
if (filters.path !== void 0) {
|
|
992
|
-
const
|
|
993
|
-
if (!includesCaseInsensitive(
|
|
998
|
+
const path15 = getParsedUrl().pathname;
|
|
999
|
+
if (!includesCaseInsensitive(path15, filters.path)) {
|
|
994
1000
|
return false;
|
|
995
1001
|
}
|
|
996
1002
|
}
|
|
@@ -7080,9 +7086,9 @@ function compareByCreatedAtAndId(left, right) {
|
|
|
7080
7086
|
var FilesystemRegistryStore = class {
|
|
7081
7087
|
constructor(rootPath, registryRelativePath) {
|
|
7082
7088
|
this.registryRelativePath = registryRelativePath;
|
|
7083
|
-
const basePath =
|
|
7084
|
-
this.recordsDirectory =
|
|
7085
|
-
this.indexesDirectory =
|
|
7089
|
+
const basePath = path7__default.default.join(rootPath, ...registryRelativePath);
|
|
7090
|
+
this.recordsDirectory = path7__default.default.join(basePath, "records");
|
|
7091
|
+
this.indexesDirectory = path7__default.default.join(basePath, "indexes", "by-key");
|
|
7086
7092
|
}
|
|
7087
7093
|
recordsDirectory;
|
|
7088
7094
|
indexesDirectory;
|
|
@@ -7151,7 +7157,7 @@ var FilesystemRegistryStore = class {
|
|
|
7151
7157
|
async readRecordsFromDirectory() {
|
|
7152
7158
|
const files = await listJsonFiles(this.recordsDirectory);
|
|
7153
7159
|
const records = await Promise.all(
|
|
7154
|
-
files.map((fileName) => readJsonFile(
|
|
7160
|
+
files.map((fileName) => readJsonFile(path7__default.default.join(this.recordsDirectory, fileName)))
|
|
7155
7161
|
);
|
|
7156
7162
|
records.sort(compareByCreatedAtAndId);
|
|
7157
7163
|
return records;
|
|
@@ -7183,17 +7189,17 @@ var FilesystemRegistryStore = class {
|
|
|
7183
7189
|
return record;
|
|
7184
7190
|
}
|
|
7185
7191
|
recordPath(id) {
|
|
7186
|
-
return
|
|
7192
|
+
return path7__default.default.join(this.recordsDirectory, `${encodePathSegment(id)}.json`);
|
|
7187
7193
|
}
|
|
7188
7194
|
indexPath(key, version) {
|
|
7189
|
-
return
|
|
7195
|
+
return path7__default.default.join(
|
|
7190
7196
|
this.indexesDirectory,
|
|
7191
7197
|
encodePathSegment(key),
|
|
7192
7198
|
`${encodePathSegment(version)}.json`
|
|
7193
7199
|
);
|
|
7194
7200
|
}
|
|
7195
7201
|
writeLockPath() {
|
|
7196
|
-
return
|
|
7202
|
+
return path7__default.default.join(path7__default.default.dirname(this.recordsDirectory), ".write.lock");
|
|
7197
7203
|
}
|
|
7198
7204
|
};
|
|
7199
7205
|
var FilesystemDescriptorRegistry = class extends FilesystemRegistryStore {
|
|
@@ -7563,7 +7569,7 @@ var SqliteSavedNetworkStore = class {
|
|
|
7563
7569
|
directoryInitialization;
|
|
7564
7570
|
databaseInitialization;
|
|
7565
7571
|
constructor(rootPath) {
|
|
7566
|
-
this.databasePath =
|
|
7572
|
+
this.databasePath = path7__default.default.join(rootPath, "registry", "saved-network.sqlite");
|
|
7567
7573
|
}
|
|
7568
7574
|
async initialize() {
|
|
7569
7575
|
await this.ensureDatabaseDirectory();
|
|
@@ -7773,7 +7779,7 @@ var SqliteSavedNetworkStore = class {
|
|
|
7773
7779
|
}
|
|
7774
7780
|
}
|
|
7775
7781
|
async ensureDatabaseDirectory() {
|
|
7776
|
-
this.directoryInitialization ??= ensureDirectory(
|
|
7782
|
+
this.directoryInitialization ??= ensureDirectory(path7__default.default.dirname(this.databasePath)).catch(
|
|
7777
7783
|
(error) => {
|
|
7778
7784
|
this.directoryInitialization = void 0;
|
|
7779
7785
|
throw error;
|
|
@@ -8163,6 +8169,546 @@ function withSqliteTransaction(database, task) {
|
|
|
8163
8169
|
function createSavedNetworkStore(rootPath) {
|
|
8164
8170
|
return new SqliteSavedNetworkStore(rootPath);
|
|
8165
8171
|
}
|
|
8172
|
+
|
|
8173
|
+
// ../runtime-core/src/observation-utils.ts
|
|
8174
|
+
var REDACTED = "[REDACTED]";
|
|
8175
|
+
var SENSITIVE_KEY_PATTERN = /(authorization|proxy[_-]?authorization|cookie|set-cookie|api[_-]?key|access[_-]?token|refresh[_-]?token|auth[_-]?token|token|secret|password|passwd|private[_-]?key|database[_-]?url|db[_-]?url|session(?:id)?|csrf(?:token)?)/i;
|
|
8176
|
+
var SENSITIVE_VALUE_PATTERNS = [
|
|
8177
|
+
/\bsk-[A-Za-z0-9_-]{20,}\b/g,
|
|
8178
|
+
/\bAIza[0-9A-Za-z_-]{20,}\b/g,
|
|
8179
|
+
/\b(?:gh[pousr]_[A-Za-z0-9]{20,}|github_pat_[A-Za-z0-9_]{20,})\b/g,
|
|
8180
|
+
/\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g,
|
|
8181
|
+
/\bBearer\s+[A-Za-z0-9._~+/=-]{16,}\b/gi
|
|
8182
|
+
];
|
|
8183
|
+
function normalizeObservationContext(context) {
|
|
8184
|
+
if (context === void 0) {
|
|
8185
|
+
return void 0;
|
|
8186
|
+
}
|
|
8187
|
+
const normalized = {
|
|
8188
|
+
...context.sessionRef === void 0 ? {} : { sessionRef: context.sessionRef },
|
|
8189
|
+
...context.pageRef === void 0 ? {} : { pageRef: context.pageRef },
|
|
8190
|
+
...context.frameRef === void 0 ? {} : { frameRef: context.frameRef },
|
|
8191
|
+
...context.documentRef === void 0 ? {} : { documentRef: context.documentRef },
|
|
8192
|
+
...context.documentEpoch === void 0 ? {} : { documentEpoch: context.documentEpoch }
|
|
8193
|
+
};
|
|
8194
|
+
return Object.keys(normalized).length === 0 ? void 0 : normalized;
|
|
8195
|
+
}
|
|
8196
|
+
function createObservationRedactor(config) {
|
|
8197
|
+
const state = createRedactionState(config);
|
|
8198
|
+
return {
|
|
8199
|
+
redactText(value) {
|
|
8200
|
+
return redactString(value, state);
|
|
8201
|
+
},
|
|
8202
|
+
redactJson(value) {
|
|
8203
|
+
return value === void 0 ? void 0 : redactUnknown(value, state, /* @__PURE__ */ new WeakSet());
|
|
8204
|
+
},
|
|
8205
|
+
redactError(error) {
|
|
8206
|
+
if (error === void 0) {
|
|
8207
|
+
return void 0;
|
|
8208
|
+
}
|
|
8209
|
+
return {
|
|
8210
|
+
...error.code === void 0 ? {} : { code: redactString(error.code, state) },
|
|
8211
|
+
message: redactString(error.message, state),
|
|
8212
|
+
...error.retriable === void 0 ? {} : { retriable: error.retriable },
|
|
8213
|
+
...error.details === void 0 ? {} : { details: toCanonicalJsonValue(redactUnknown(error.details, state, /* @__PURE__ */ new WeakSet())) }
|
|
8214
|
+
};
|
|
8215
|
+
},
|
|
8216
|
+
redactLabels(labels) {
|
|
8217
|
+
if (labels === void 0) {
|
|
8218
|
+
return void 0;
|
|
8219
|
+
}
|
|
8220
|
+
const next = Object.entries(labels).reduce(
|
|
8221
|
+
(accumulator, [key, value]) => {
|
|
8222
|
+
accumulator[key] = isSensitiveKey(key, state) ? REDACTED : redactString(value, state);
|
|
8223
|
+
return accumulator;
|
|
8224
|
+
},
|
|
8225
|
+
{}
|
|
8226
|
+
);
|
|
8227
|
+
return Object.keys(next).length === 0 ? void 0 : next;
|
|
8228
|
+
},
|
|
8229
|
+
redactTraceContext(traceContext) {
|
|
8230
|
+
if (traceContext === void 0) {
|
|
8231
|
+
return void 0;
|
|
8232
|
+
}
|
|
8233
|
+
const next = {
|
|
8234
|
+
...traceContext.traceparent === void 0 ? {} : { traceparent: redactString(traceContext.traceparent, state) },
|
|
8235
|
+
...traceContext.baggage === void 0 ? {} : { baggage: redactString(traceContext.baggage, state) }
|
|
8236
|
+
};
|
|
8237
|
+
return Object.keys(next).length === 0 ? void 0 : next;
|
|
8238
|
+
}
|
|
8239
|
+
};
|
|
8240
|
+
}
|
|
8241
|
+
function createRedactionState(config) {
|
|
8242
|
+
return {
|
|
8243
|
+
sensitiveKeys: new Set(
|
|
8244
|
+
(config?.redaction?.sensitiveKeys ?? []).map((value) => value.trim().toLowerCase()).filter((value) => value.length > 0)
|
|
8245
|
+
),
|
|
8246
|
+
sensitiveValues: [
|
|
8247
|
+
...new Set(
|
|
8248
|
+
(config?.redaction?.sensitiveValues ?? []).map((value) => value.trim()).filter((value) => value.length > 0)
|
|
8249
|
+
)
|
|
8250
|
+
]
|
|
8251
|
+
};
|
|
8252
|
+
}
|
|
8253
|
+
function redactUnknown(value, state, seen) {
|
|
8254
|
+
if (value === null || value === void 0) {
|
|
8255
|
+
return value;
|
|
8256
|
+
}
|
|
8257
|
+
if (typeof value === "string") {
|
|
8258
|
+
return redactString(value, state);
|
|
8259
|
+
}
|
|
8260
|
+
if (typeof value !== "object") {
|
|
8261
|
+
return value;
|
|
8262
|
+
}
|
|
8263
|
+
if (seen.has(value)) {
|
|
8264
|
+
return REDACTED;
|
|
8265
|
+
}
|
|
8266
|
+
seen.add(value);
|
|
8267
|
+
if (Array.isArray(value)) {
|
|
8268
|
+
return value.map((entry) => redactUnknown(entry, state, seen));
|
|
8269
|
+
}
|
|
8270
|
+
const next = {};
|
|
8271
|
+
for (const [key, nestedValue] of Object.entries(value)) {
|
|
8272
|
+
next[key] = isSensitiveKey(key, state) ? REDACTED : redactUnknown(nestedValue, state, seen);
|
|
8273
|
+
}
|
|
8274
|
+
return next;
|
|
8275
|
+
}
|
|
8276
|
+
function redactString(value, state) {
|
|
8277
|
+
let next = value;
|
|
8278
|
+
for (const secret of state.sensitiveValues) {
|
|
8279
|
+
next = next.split(secret).join(REDACTED);
|
|
8280
|
+
}
|
|
8281
|
+
for (const pattern of SENSITIVE_VALUE_PATTERNS) {
|
|
8282
|
+
next = next.replace(pattern, REDACTED);
|
|
8283
|
+
}
|
|
8284
|
+
return redactUrlString(next, state);
|
|
8285
|
+
}
|
|
8286
|
+
function redactUrlString(value, state) {
|
|
8287
|
+
let parsed;
|
|
8288
|
+
try {
|
|
8289
|
+
parsed = new URL(value);
|
|
8290
|
+
} catch {
|
|
8291
|
+
return value;
|
|
8292
|
+
}
|
|
8293
|
+
let changed = false;
|
|
8294
|
+
if (parsed.username) {
|
|
8295
|
+
parsed.username = REDACTED;
|
|
8296
|
+
changed = true;
|
|
8297
|
+
}
|
|
8298
|
+
if (parsed.password) {
|
|
8299
|
+
parsed.password = REDACTED;
|
|
8300
|
+
changed = true;
|
|
8301
|
+
}
|
|
8302
|
+
for (const [key] of parsed.searchParams) {
|
|
8303
|
+
if (!isSensitiveKey(key, state)) {
|
|
8304
|
+
continue;
|
|
8305
|
+
}
|
|
8306
|
+
parsed.searchParams.set(key, REDACTED);
|
|
8307
|
+
changed = true;
|
|
8308
|
+
}
|
|
8309
|
+
return changed ? parsed.toString() : value;
|
|
8310
|
+
}
|
|
8311
|
+
function isSensitiveKey(key, state) {
|
|
8312
|
+
return state.sensitiveKeys.has(key.trim().toLowerCase()) || SENSITIVE_KEY_PATTERN.test(key);
|
|
8313
|
+
}
|
|
8314
|
+
|
|
8315
|
+
// ../runtime-core/src/observations.ts
|
|
8316
|
+
function normalizeObservabilityConfig(input) {
|
|
8317
|
+
const profile = input?.profile ?? "diagnostic";
|
|
8318
|
+
const labels = input?.labels === void 0 ? void 0 : Object.entries(input.labels).reduce((accumulator, [key, value]) => {
|
|
8319
|
+
const normalizedKey = key.trim();
|
|
8320
|
+
const normalizedValue = value.trim();
|
|
8321
|
+
if (normalizedKey.length === 0 || normalizedValue.length === 0) {
|
|
8322
|
+
return accumulator;
|
|
8323
|
+
}
|
|
8324
|
+
if (Object.keys(accumulator).length >= 20) {
|
|
8325
|
+
return accumulator;
|
|
8326
|
+
}
|
|
8327
|
+
accumulator[normalizedKey] = normalizedValue;
|
|
8328
|
+
return accumulator;
|
|
8329
|
+
}, {});
|
|
8330
|
+
const redaction = input?.redaction === void 0 ? void 0 : {
|
|
8331
|
+
...input.redaction.sensitiveKeys === void 0 ? {} : {
|
|
8332
|
+
sensitiveKeys: input.redaction.sensitiveKeys.map((value) => value.trim()).filter((value) => value.length > 0)
|
|
8333
|
+
},
|
|
8334
|
+
...input.redaction.sensitiveValues === void 0 ? {} : {
|
|
8335
|
+
sensitiveValues: input.redaction.sensitiveValues.map((value) => value.trim()).filter((value) => value.length > 0)
|
|
8336
|
+
}
|
|
8337
|
+
};
|
|
8338
|
+
return {
|
|
8339
|
+
profile,
|
|
8340
|
+
...labels === void 0 || Object.keys(labels).length === 0 ? {} : { labels },
|
|
8341
|
+
...input?.traceContext === void 0 ? {} : {
|
|
8342
|
+
traceContext: {
|
|
8343
|
+
...input.traceContext.traceparent === void 0 ? {} : { traceparent: input.traceContext.traceparent.trim() },
|
|
8344
|
+
...input.traceContext.baggage === void 0 ? {} : { baggage: input.traceContext.baggage.trim() }
|
|
8345
|
+
}
|
|
8346
|
+
},
|
|
8347
|
+
...redaction === void 0 ? {} : { redaction }
|
|
8348
|
+
};
|
|
8349
|
+
}
|
|
8350
|
+
function eventFileName(sequence) {
|
|
8351
|
+
return `${String(sequence).padStart(12, "0")}.json`;
|
|
8352
|
+
}
|
|
8353
|
+
var FilesystemSessionSink = class {
|
|
8354
|
+
constructor(store, sessionId) {
|
|
8355
|
+
this.store = store;
|
|
8356
|
+
this.sessionId = sessionId;
|
|
8357
|
+
}
|
|
8358
|
+
append(input) {
|
|
8359
|
+
return this.store.appendEvent(this.sessionId, input);
|
|
8360
|
+
}
|
|
8361
|
+
appendBatch(input) {
|
|
8362
|
+
return this.store.appendEvents(this.sessionId, input);
|
|
8363
|
+
}
|
|
8364
|
+
writeArtifact(input) {
|
|
8365
|
+
return this.store.writeArtifact(this.sessionId, input);
|
|
8366
|
+
}
|
|
8367
|
+
async flush() {
|
|
8368
|
+
}
|
|
8369
|
+
close(reason) {
|
|
8370
|
+
return this.store.closeSession(this.sessionId, reason);
|
|
8371
|
+
}
|
|
8372
|
+
};
|
|
8373
|
+
var FilesystemObservationStoreImpl = class {
|
|
8374
|
+
constructor(rootPath, artifacts) {
|
|
8375
|
+
this.rootPath = rootPath;
|
|
8376
|
+
this.artifacts = artifacts;
|
|
8377
|
+
this.sessionsDirectory = path7__default.default.join(this.rootPath, "observations", "sessions");
|
|
8378
|
+
}
|
|
8379
|
+
sessionsDirectory;
|
|
8380
|
+
redactors = /* @__PURE__ */ new Map();
|
|
8381
|
+
async initialize() {
|
|
8382
|
+
await ensureDirectory(this.sessionsDirectory);
|
|
8383
|
+
}
|
|
8384
|
+
async openSession(input) {
|
|
8385
|
+
const sessionId = normalizeNonEmptyString("sessionId", input.sessionId);
|
|
8386
|
+
const openedAt = normalizeTimestamp("openedAt", input.openedAt ?? Date.now());
|
|
8387
|
+
const config = normalizeObservabilityConfig(input.config);
|
|
8388
|
+
const redactor = createObservationRedactor(config);
|
|
8389
|
+
this.redactors.set(sessionId, redactor);
|
|
8390
|
+
const redactedLabels = redactor.redactLabels(config.labels);
|
|
8391
|
+
const redactedTraceContext = redactor.redactTraceContext(config.traceContext);
|
|
8392
|
+
await withFilesystemLock(this.sessionLockPath(sessionId), async () => {
|
|
8393
|
+
const existing = await this.reconcileSessionManifest(sessionId);
|
|
8394
|
+
if (existing === void 0) {
|
|
8395
|
+
await ensureDirectory(this.sessionEventsDirectory(sessionId));
|
|
8396
|
+
await ensureDirectory(this.sessionArtifactsDirectory(sessionId));
|
|
8397
|
+
const session = {
|
|
8398
|
+
sessionId,
|
|
8399
|
+
profile: config.profile,
|
|
8400
|
+
...redactedLabels === void 0 ? {} : { labels: redactedLabels },
|
|
8401
|
+
...redactedTraceContext === void 0 ? {} : { traceContext: redactedTraceContext },
|
|
8402
|
+
openedAt,
|
|
8403
|
+
updatedAt: openedAt,
|
|
8404
|
+
currentSequence: 0,
|
|
8405
|
+
eventCount: 0,
|
|
8406
|
+
artifactCount: 0
|
|
8407
|
+
};
|
|
8408
|
+
await writeJsonFileExclusive(this.sessionManifestPath(sessionId), session);
|
|
8409
|
+
return;
|
|
8410
|
+
}
|
|
8411
|
+
const patched = {
|
|
8412
|
+
...existing,
|
|
8413
|
+
profile: config.profile,
|
|
8414
|
+
...redactedLabels === void 0 ? {} : { labels: redactedLabels },
|
|
8415
|
+
...redactedTraceContext === void 0 ? {} : { traceContext: redactedTraceContext },
|
|
8416
|
+
updatedAt: Math.max(existing.updatedAt, openedAt)
|
|
8417
|
+
};
|
|
8418
|
+
await writeJsonFileAtomic(this.sessionManifestPath(sessionId), patched);
|
|
8419
|
+
});
|
|
8420
|
+
return new FilesystemSessionSink(this, sessionId);
|
|
8421
|
+
}
|
|
8422
|
+
async getSession(sessionId) {
|
|
8423
|
+
const manifestPath = this.sessionManifestPath(sessionId);
|
|
8424
|
+
if (!await pathExists(manifestPath)) {
|
|
8425
|
+
return void 0;
|
|
8426
|
+
}
|
|
8427
|
+
return readJsonFile(manifestPath);
|
|
8428
|
+
}
|
|
8429
|
+
async appendEvent(sessionId, input) {
|
|
8430
|
+
const [event] = await this.appendEvents(sessionId, [input]);
|
|
8431
|
+
if (event === void 0) {
|
|
8432
|
+
throw new Error(`failed to append observation event for session ${sessionId}`);
|
|
8433
|
+
}
|
|
8434
|
+
return event;
|
|
8435
|
+
}
|
|
8436
|
+
async appendEvents(sessionId, input) {
|
|
8437
|
+
if (input.length === 0) {
|
|
8438
|
+
return [];
|
|
8439
|
+
}
|
|
8440
|
+
return withFilesystemLock(this.sessionLockPath(sessionId), async () => {
|
|
8441
|
+
const session = await this.reconcileSessionManifest(sessionId);
|
|
8442
|
+
if (session === void 0) {
|
|
8443
|
+
throw new Error(`observation session ${sessionId} was not found`);
|
|
8444
|
+
}
|
|
8445
|
+
const redactor = this.redactors.get(sessionId) ?? createObservationRedactor(void 0);
|
|
8446
|
+
const events = [];
|
|
8447
|
+
let sequence = session.currentSequence;
|
|
8448
|
+
let updatedAt = session.updatedAt;
|
|
8449
|
+
for (const raw of input) {
|
|
8450
|
+
sequence += 1;
|
|
8451
|
+
const createdAt = normalizeTimestamp("createdAt", raw.createdAt);
|
|
8452
|
+
const context = normalizeObservationContext(raw.context);
|
|
8453
|
+
const redactedData = raw.data === void 0 ? void 0 : redactor.redactJson(toCanonicalJsonValue(raw.data));
|
|
8454
|
+
const redactedError = redactor.redactError(raw.error);
|
|
8455
|
+
const event = {
|
|
8456
|
+
eventId: normalizeNonEmptyString(
|
|
8457
|
+
"eventId",
|
|
8458
|
+
raw.eventId ?? `observation:${sessionId}:${String(sequence).padStart(12, "0")}`
|
|
8459
|
+
),
|
|
8460
|
+
sessionId,
|
|
8461
|
+
sequence,
|
|
8462
|
+
kind: raw.kind,
|
|
8463
|
+
phase: raw.phase,
|
|
8464
|
+
createdAt,
|
|
8465
|
+
correlationId: normalizeNonEmptyString("correlationId", raw.correlationId),
|
|
8466
|
+
...raw.spanId === void 0 ? {} : { spanId: normalizeNonEmptyString("spanId", raw.spanId) },
|
|
8467
|
+
...raw.parentSpanId === void 0 ? {} : { parentSpanId: normalizeNonEmptyString("parentSpanId", raw.parentSpanId) },
|
|
8468
|
+
...context === void 0 ? {} : { context },
|
|
8469
|
+
...redactedData === void 0 ? {} : { data: redactedData },
|
|
8470
|
+
...redactedError === void 0 ? {} : { error: redactedError },
|
|
8471
|
+
...raw.artifactIds === void 0 || raw.artifactIds.length === 0 ? {} : { artifactIds: [...raw.artifactIds] }
|
|
8472
|
+
};
|
|
8473
|
+
await writeJsonFileExclusive(
|
|
8474
|
+
path7__default.default.join(this.sessionEventsDirectory(sessionId), eventFileName(sequence)),
|
|
8475
|
+
event
|
|
8476
|
+
);
|
|
8477
|
+
updatedAt = Math.max(updatedAt, createdAt);
|
|
8478
|
+
events.push(event);
|
|
8479
|
+
}
|
|
8480
|
+
await writeJsonFileAtomic(this.sessionManifestPath(sessionId), {
|
|
8481
|
+
...session,
|
|
8482
|
+
currentSequence: sequence,
|
|
8483
|
+
eventCount: session.eventCount + events.length,
|
|
8484
|
+
updatedAt
|
|
8485
|
+
});
|
|
8486
|
+
return events;
|
|
8487
|
+
});
|
|
8488
|
+
}
|
|
8489
|
+
async writeArtifact(sessionId, input) {
|
|
8490
|
+
return withFilesystemLock(this.sessionLockPath(sessionId), async () => {
|
|
8491
|
+
const session = await this.reconcileSessionManifest(sessionId);
|
|
8492
|
+
if (session === void 0) {
|
|
8493
|
+
throw new Error(`observation session ${sessionId} was not found`);
|
|
8494
|
+
}
|
|
8495
|
+
const redactor = this.redactors.get(sessionId) ?? createObservationRedactor(void 0);
|
|
8496
|
+
const createdAt = normalizeTimestamp("createdAt", input.createdAt);
|
|
8497
|
+
const context = normalizeObservationContext(input.context);
|
|
8498
|
+
const redactedStorageKey = input.storageKey === void 0 ? void 0 : redactor.redactText(input.storageKey);
|
|
8499
|
+
const redactedMetadata = input.metadata === void 0 ? void 0 : redactor.redactJson(toCanonicalJsonValue(input.metadata));
|
|
8500
|
+
const artifact = {
|
|
8501
|
+
artifactId: normalizeNonEmptyString("artifactId", input.artifactId),
|
|
8502
|
+
sessionId,
|
|
8503
|
+
kind: input.kind,
|
|
8504
|
+
createdAt,
|
|
8505
|
+
...context === void 0 ? {} : { context },
|
|
8506
|
+
...input.mediaType === void 0 ? {} : { mediaType: input.mediaType },
|
|
8507
|
+
...input.byteLength === void 0 ? {} : { byteLength: input.byteLength },
|
|
8508
|
+
...input.sha256 === void 0 ? {} : { sha256: input.sha256 },
|
|
8509
|
+
...input.opensteerArtifactId === void 0 ? {} : { opensteerArtifactId: input.opensteerArtifactId },
|
|
8510
|
+
...redactedStorageKey === void 0 ? {} : { storageKey: redactedStorageKey },
|
|
8511
|
+
...redactedMetadata === void 0 ? {} : { metadata: redactedMetadata }
|
|
8512
|
+
};
|
|
8513
|
+
const artifactPath = this.sessionArtifactPath(sessionId, artifact.artifactId);
|
|
8514
|
+
if (!await pathExists(artifactPath)) {
|
|
8515
|
+
await writeJsonFileExclusive(artifactPath, artifact);
|
|
8516
|
+
await writeJsonFileAtomic(this.sessionManifestPath(sessionId), {
|
|
8517
|
+
...session,
|
|
8518
|
+
artifactCount: session.artifactCount + 1,
|
|
8519
|
+
updatedAt: Math.max(session.updatedAt, createdAt)
|
|
8520
|
+
});
|
|
8521
|
+
}
|
|
8522
|
+
return artifact;
|
|
8523
|
+
});
|
|
8524
|
+
}
|
|
8525
|
+
async listEvents(sessionId, input = {}) {
|
|
8526
|
+
const directoryPath = this.sessionEventsDirectory(sessionId);
|
|
8527
|
+
if (!await pathExists(directoryPath)) {
|
|
8528
|
+
return [];
|
|
8529
|
+
}
|
|
8530
|
+
const files = await listJsonFiles(directoryPath);
|
|
8531
|
+
const events = await Promise.all(
|
|
8532
|
+
files.map((fileName) => readJsonFile(path7__default.default.join(directoryPath, fileName)))
|
|
8533
|
+
);
|
|
8534
|
+
const filtered = events.filter((event) => {
|
|
8535
|
+
if (input.kind !== void 0 && event.kind !== input.kind) return false;
|
|
8536
|
+
if (input.phase !== void 0 && event.phase !== input.phase) return false;
|
|
8537
|
+
if (input.correlationId !== void 0 && event.correlationId !== input.correlationId) {
|
|
8538
|
+
return false;
|
|
8539
|
+
}
|
|
8540
|
+
if (input.pageRef !== void 0 && event.context?.pageRef !== input.pageRef) return false;
|
|
8541
|
+
if (input.afterSequence !== void 0 && event.sequence <= input.afterSequence) return false;
|
|
8542
|
+
if (input.from !== void 0 && event.createdAt < input.from) return false;
|
|
8543
|
+
if (input.to !== void 0 && event.createdAt > input.to) return false;
|
|
8544
|
+
return true;
|
|
8545
|
+
});
|
|
8546
|
+
if (input.limit === void 0 || filtered.length <= input.limit) {
|
|
8547
|
+
return filtered;
|
|
8548
|
+
}
|
|
8549
|
+
return filtered.slice(-input.limit);
|
|
8550
|
+
}
|
|
8551
|
+
async listArtifacts(sessionId, input = {}) {
|
|
8552
|
+
const directoryPath = this.sessionArtifactsDirectory(sessionId);
|
|
8553
|
+
if (!await pathExists(directoryPath)) {
|
|
8554
|
+
return [];
|
|
8555
|
+
}
|
|
8556
|
+
const files = await listJsonFiles(directoryPath);
|
|
8557
|
+
const artifacts = await Promise.all(
|
|
8558
|
+
files.map(
|
|
8559
|
+
(fileName) => readJsonFile(path7__default.default.join(directoryPath, fileName))
|
|
8560
|
+
)
|
|
8561
|
+
);
|
|
8562
|
+
const filtered = artifacts.filter((artifact) => {
|
|
8563
|
+
if (input.kind !== void 0 && artifact.kind !== input.kind) return false;
|
|
8564
|
+
if (input.pageRef !== void 0 && artifact.context?.pageRef !== input.pageRef) return false;
|
|
8565
|
+
return true;
|
|
8566
|
+
});
|
|
8567
|
+
if (input.limit === void 0 || filtered.length <= input.limit) {
|
|
8568
|
+
return filtered;
|
|
8569
|
+
}
|
|
8570
|
+
return filtered.slice(-input.limit);
|
|
8571
|
+
}
|
|
8572
|
+
async getArtifact(sessionId, artifactId) {
|
|
8573
|
+
const artifactPath = this.sessionArtifactPath(sessionId, artifactId);
|
|
8574
|
+
if (!await pathExists(artifactPath)) {
|
|
8575
|
+
return void 0;
|
|
8576
|
+
}
|
|
8577
|
+
return readJsonFile(artifactPath);
|
|
8578
|
+
}
|
|
8579
|
+
async closeSession(sessionId, _reason) {
|
|
8580
|
+
await withFilesystemLock(this.sessionLockPath(sessionId), async () => {
|
|
8581
|
+
const session = await this.reconcileSessionManifest(sessionId);
|
|
8582
|
+
if (session === void 0 || session.closedAt !== void 0) {
|
|
8583
|
+
return;
|
|
8584
|
+
}
|
|
8585
|
+
const now = Date.now();
|
|
8586
|
+
await writeJsonFileAtomic(this.sessionManifestPath(sessionId), {
|
|
8587
|
+
...session,
|
|
8588
|
+
updatedAt: Math.max(session.updatedAt, now),
|
|
8589
|
+
closedAt: now
|
|
8590
|
+
});
|
|
8591
|
+
});
|
|
8592
|
+
this.redactors.delete(sessionId);
|
|
8593
|
+
}
|
|
8594
|
+
async writeArtifactFromManifest(sessionId, manifest, kind, metadata) {
|
|
8595
|
+
return this.writeArtifact(sessionId, {
|
|
8596
|
+
artifactId: manifest.artifactId,
|
|
8597
|
+
kind,
|
|
8598
|
+
createdAt: manifest.createdAt,
|
|
8599
|
+
context: manifest.scope,
|
|
8600
|
+
mediaType: manifest.mediaType,
|
|
8601
|
+
byteLength: manifest.byteLength,
|
|
8602
|
+
sha256: manifest.sha256,
|
|
8603
|
+
opensteerArtifactId: manifest.artifactId,
|
|
8604
|
+
storageKey: manifestToExternalBinaryLocation(this.rootPath, manifest).uri,
|
|
8605
|
+
...metadata === void 0 ? {} : { metadata }
|
|
8606
|
+
});
|
|
8607
|
+
}
|
|
8608
|
+
async ensureArtifactLinked(sessionId, manifest) {
|
|
8609
|
+
const existing = await this.getArtifact(sessionId, manifest.artifactId);
|
|
8610
|
+
if (existing !== void 0) {
|
|
8611
|
+
return existing;
|
|
8612
|
+
}
|
|
8613
|
+
const kind = toObservationArtifactKind(manifest.kind);
|
|
8614
|
+
return this.writeArtifactFromManifest(sessionId, manifest, kind);
|
|
8615
|
+
}
|
|
8616
|
+
async hydrateArtifactManifests(artifactIds) {
|
|
8617
|
+
return (await Promise.all(
|
|
8618
|
+
artifactIds.map(async (artifactId) => this.artifacts.getManifest(artifactId))
|
|
8619
|
+
)).filter((value) => value !== void 0);
|
|
8620
|
+
}
|
|
8621
|
+
sessionDirectory(sessionId) {
|
|
8622
|
+
return path7__default.default.join(this.sessionsDirectory, encodePathSegment(sessionId));
|
|
8623
|
+
}
|
|
8624
|
+
sessionManifestPath(sessionId) {
|
|
8625
|
+
return path7__default.default.join(this.sessionDirectory(sessionId), "session.json");
|
|
8626
|
+
}
|
|
8627
|
+
sessionEventsDirectory(sessionId) {
|
|
8628
|
+
return path7__default.default.join(this.sessionDirectory(sessionId), "events");
|
|
8629
|
+
}
|
|
8630
|
+
sessionArtifactsDirectory(sessionId) {
|
|
8631
|
+
return path7__default.default.join(this.sessionDirectory(sessionId), "artifacts");
|
|
8632
|
+
}
|
|
8633
|
+
sessionArtifactPath(sessionId, artifactId) {
|
|
8634
|
+
return path7__default.default.join(
|
|
8635
|
+
this.sessionArtifactsDirectory(sessionId),
|
|
8636
|
+
`${encodePathSegment(artifactId)}.json`
|
|
8637
|
+
);
|
|
8638
|
+
}
|
|
8639
|
+
sessionLockPath(sessionId) {
|
|
8640
|
+
return path7__default.default.join(this.sessionDirectory(sessionId), ".lock");
|
|
8641
|
+
}
|
|
8642
|
+
async reconcileSessionManifest(sessionId) {
|
|
8643
|
+
const session = await this.getSession(sessionId);
|
|
8644
|
+
if (session === void 0) {
|
|
8645
|
+
return void 0;
|
|
8646
|
+
}
|
|
8647
|
+
const [hasEventDirectory, hasArtifactDirectory] = await Promise.all([
|
|
8648
|
+
pathExists(this.sessionEventsDirectory(sessionId)),
|
|
8649
|
+
pathExists(this.sessionArtifactsDirectory(sessionId))
|
|
8650
|
+
]);
|
|
8651
|
+
const [eventFiles, artifactFiles] = await Promise.all([
|
|
8652
|
+
hasEventDirectory ? listJsonFiles(this.sessionEventsDirectory(sessionId)) : Promise.resolve([]),
|
|
8653
|
+
hasArtifactDirectory ? listJsonFiles(this.sessionArtifactsDirectory(sessionId)) : Promise.resolve([])
|
|
8654
|
+
]);
|
|
8655
|
+
const currentSequence = eventFiles.reduce((maxSequence, fileName) => {
|
|
8656
|
+
const parsed = Number.parseInt(fileName.replace(/\.json$/u, ""), 10);
|
|
8657
|
+
return Number.isFinite(parsed) ? Math.max(maxSequence, parsed) : maxSequence;
|
|
8658
|
+
}, 0);
|
|
8659
|
+
const eventCount = eventFiles.length;
|
|
8660
|
+
const artifactCount = artifactFiles.length;
|
|
8661
|
+
if (session.currentSequence === currentSequence && session.eventCount === eventCount && session.artifactCount === artifactCount) {
|
|
8662
|
+
return session;
|
|
8663
|
+
}
|
|
8664
|
+
const [events, artifacts] = await Promise.all([
|
|
8665
|
+
Promise.all(
|
|
8666
|
+
eventFiles.map(
|
|
8667
|
+
(fileName) => readJsonFile(
|
|
8668
|
+
path7__default.default.join(this.sessionEventsDirectory(sessionId), fileName)
|
|
8669
|
+
)
|
|
8670
|
+
)
|
|
8671
|
+
),
|
|
8672
|
+
Promise.all(
|
|
8673
|
+
artifactFiles.map(
|
|
8674
|
+
(fileName) => readJsonFile(
|
|
8675
|
+
path7__default.default.join(this.sessionArtifactsDirectory(sessionId), fileName)
|
|
8676
|
+
)
|
|
8677
|
+
)
|
|
8678
|
+
)
|
|
8679
|
+
]);
|
|
8680
|
+
const updatedAt = Math.max(
|
|
8681
|
+
session.openedAt,
|
|
8682
|
+
session.closedAt ?? 0,
|
|
8683
|
+
...events.map((event) => event.createdAt),
|
|
8684
|
+
...artifacts.map((artifact) => artifact.createdAt)
|
|
8685
|
+
);
|
|
8686
|
+
const reconciled = {
|
|
8687
|
+
...session,
|
|
8688
|
+
currentSequence,
|
|
8689
|
+
eventCount,
|
|
8690
|
+
artifactCount,
|
|
8691
|
+
updatedAt
|
|
8692
|
+
};
|
|
8693
|
+
await writeJsonFileAtomic(this.sessionManifestPath(sessionId), reconciled);
|
|
8694
|
+
return reconciled;
|
|
8695
|
+
}
|
|
8696
|
+
};
|
|
8697
|
+
function toObservationArtifactKind(kind) {
|
|
8698
|
+
switch (kind) {
|
|
8699
|
+
case "screenshot":
|
|
8700
|
+
return "screenshot";
|
|
8701
|
+
case "dom-snapshot":
|
|
8702
|
+
return "dom-snapshot";
|
|
8703
|
+
case "html-snapshot":
|
|
8704
|
+
return "html-snapshot";
|
|
8705
|
+
default:
|
|
8706
|
+
return "other";
|
|
8707
|
+
}
|
|
8708
|
+
}
|
|
8709
|
+
function createObservationStore(rootPath, artifacts) {
|
|
8710
|
+
return new FilesystemObservationStoreImpl(rootPath, artifacts);
|
|
8711
|
+
}
|
|
8166
8712
|
function normalizeContext(context) {
|
|
8167
8713
|
return {
|
|
8168
8714
|
...context?.sessionRef === void 0 ? {} : { sessionRef: context.sessionRef },
|
|
@@ -8179,7 +8725,7 @@ var FilesystemTraceStore = class {
|
|
|
8179
8725
|
constructor(rootPath, artifacts) {
|
|
8180
8726
|
this.rootPath = rootPath;
|
|
8181
8727
|
this.artifacts = artifacts;
|
|
8182
|
-
this.runsDirectory =
|
|
8728
|
+
this.runsDirectory = path7__default.default.join(this.rootPath, "traces", "runs");
|
|
8183
8729
|
}
|
|
8184
8730
|
runsDirectory;
|
|
8185
8731
|
async initialize() {
|
|
@@ -8256,7 +8802,7 @@ var FilesystemTraceStore = class {
|
|
|
8256
8802
|
...input.error === void 0 ? {} : { error: input.error }
|
|
8257
8803
|
};
|
|
8258
8804
|
await writeJsonFileExclusive(
|
|
8259
|
-
|
|
8805
|
+
path7__default.default.join(this.runEntriesDirectory(runId), sequenceFileName(sequence)),
|
|
8260
8806
|
entry
|
|
8261
8807
|
);
|
|
8262
8808
|
await writeJsonFileAtomic(this.runManifestPath(runId), {
|
|
@@ -8275,7 +8821,7 @@ var FilesystemTraceStore = class {
|
|
|
8275
8821
|
const files = await listJsonFiles(entriesDirectory);
|
|
8276
8822
|
return Promise.all(
|
|
8277
8823
|
files.map(
|
|
8278
|
-
(fileName) => readJsonFile(
|
|
8824
|
+
(fileName) => readJsonFile(path7__default.default.join(entriesDirectory, fileName))
|
|
8279
8825
|
)
|
|
8280
8826
|
);
|
|
8281
8827
|
}
|
|
@@ -8321,16 +8867,16 @@ var FilesystemTraceStore = class {
|
|
|
8321
8867
|
return { trace, artifacts };
|
|
8322
8868
|
}
|
|
8323
8869
|
runDirectory(runId) {
|
|
8324
|
-
return
|
|
8870
|
+
return path7__default.default.join(this.runsDirectory, encodeURIComponent(runId));
|
|
8325
8871
|
}
|
|
8326
8872
|
runEntriesDirectory(runId) {
|
|
8327
|
-
return
|
|
8873
|
+
return path7__default.default.join(this.runDirectory(runId), "entries");
|
|
8328
8874
|
}
|
|
8329
8875
|
runManifestPath(runId) {
|
|
8330
|
-
return
|
|
8876
|
+
return path7__default.default.join(this.runDirectory(runId), "manifest.json");
|
|
8331
8877
|
}
|
|
8332
8878
|
runWriteLockPath(runId) {
|
|
8333
|
-
return
|
|
8879
|
+
return path7__default.default.join(this.runDirectory(runId), ".append.lock");
|
|
8334
8880
|
}
|
|
8335
8881
|
};
|
|
8336
8882
|
function createTraceStore(rootPath, artifacts) {
|
|
@@ -8344,7 +8890,7 @@ function normalizeWorkspaceId(workspace) {
|
|
|
8344
8890
|
return encodePathSegment(workspace);
|
|
8345
8891
|
}
|
|
8346
8892
|
function resolveFilesystemWorkspacePath(input) {
|
|
8347
|
-
return
|
|
8893
|
+
return path7__default.default.join(
|
|
8348
8894
|
input.rootDir,
|
|
8349
8895
|
".opensteer",
|
|
8350
8896
|
"workspaces",
|
|
@@ -8353,17 +8899,18 @@ function resolveFilesystemWorkspacePath(input) {
|
|
|
8353
8899
|
}
|
|
8354
8900
|
async function createFilesystemOpensteerWorkspace(options) {
|
|
8355
8901
|
await ensureDirectory(options.rootPath);
|
|
8356
|
-
const manifestPath =
|
|
8357
|
-
const browserPath =
|
|
8358
|
-
const browserManifestPath =
|
|
8359
|
-
const browserUserDataDir =
|
|
8360
|
-
const livePath =
|
|
8361
|
-
const liveLocalPath =
|
|
8362
|
-
const liveCloudPath =
|
|
8363
|
-
const artifactsPath =
|
|
8364
|
-
const tracesPath =
|
|
8365
|
-
const
|
|
8366
|
-
const
|
|
8902
|
+
const manifestPath = path7__default.default.join(options.rootPath, "workspace.json");
|
|
8903
|
+
const browserPath = path7__default.default.join(options.rootPath, "browser");
|
|
8904
|
+
const browserManifestPath = path7__default.default.join(browserPath, "manifest.json");
|
|
8905
|
+
const browserUserDataDir = path7__default.default.join(browserPath, "user-data");
|
|
8906
|
+
const livePath = path7__default.default.join(options.rootPath, "live");
|
|
8907
|
+
const liveLocalPath = path7__default.default.join(livePath, "local.json");
|
|
8908
|
+
const liveCloudPath = path7__default.default.join(livePath, "cloud.json");
|
|
8909
|
+
const artifactsPath = path7__default.default.join(options.rootPath, "artifacts");
|
|
8910
|
+
const tracesPath = path7__default.default.join(options.rootPath, "traces");
|
|
8911
|
+
const observationsPath = path7__default.default.join(options.rootPath, "observations");
|
|
8912
|
+
const registryPath = path7__default.default.join(options.rootPath, "registry");
|
|
8913
|
+
const lockPath = path7__default.default.join(options.rootPath, ".lock");
|
|
8367
8914
|
let manifest;
|
|
8368
8915
|
if (await pathExists(manifestPath)) {
|
|
8369
8916
|
manifest = await readJsonFile(manifestPath);
|
|
@@ -8377,6 +8924,17 @@ async function createFilesystemOpensteerWorkspace(options) {
|
|
|
8377
8924
|
`workspace ${options.rootPath} uses unsupported version ${String(manifest.version)}`
|
|
8378
8925
|
);
|
|
8379
8926
|
}
|
|
8927
|
+
if (manifest.paths.observations === void 0) {
|
|
8928
|
+
manifest = {
|
|
8929
|
+
...manifest,
|
|
8930
|
+
updatedAt: Date.now(),
|
|
8931
|
+
paths: {
|
|
8932
|
+
...manifest.paths,
|
|
8933
|
+
observations: "observations"
|
|
8934
|
+
}
|
|
8935
|
+
};
|
|
8936
|
+
await writeJsonFileAtomic(manifestPath, manifest);
|
|
8937
|
+
}
|
|
8380
8938
|
} else {
|
|
8381
8939
|
const createdAt = normalizeTimestamp("createdAt", options.createdAt ?? Date.now());
|
|
8382
8940
|
manifest = {
|
|
@@ -8391,6 +8949,7 @@ async function createFilesystemOpensteerWorkspace(options) {
|
|
|
8391
8949
|
live: "live",
|
|
8392
8950
|
artifacts: "artifacts",
|
|
8393
8951
|
traces: "traces",
|
|
8952
|
+
observations: "observations",
|
|
8394
8953
|
registry: "registry"
|
|
8395
8954
|
}
|
|
8396
8955
|
};
|
|
@@ -8402,6 +8961,7 @@ async function createFilesystemOpensteerWorkspace(options) {
|
|
|
8402
8961
|
ensureDirectory(livePath),
|
|
8403
8962
|
ensureDirectory(artifactsPath),
|
|
8404
8963
|
ensureDirectory(tracesPath),
|
|
8964
|
+
ensureDirectory(observationsPath),
|
|
8405
8965
|
ensureDirectory(registryPath)
|
|
8406
8966
|
]);
|
|
8407
8967
|
const artifacts = createArtifactStore(options.rootPath);
|
|
@@ -8426,6 +8986,8 @@ async function createFilesystemOpensteerWorkspace(options) {
|
|
|
8426
8986
|
await reverseReports.initialize();
|
|
8427
8987
|
const traces = createTraceStore(options.rootPath, artifacts);
|
|
8428
8988
|
await traces.initialize();
|
|
8989
|
+
const observations = createObservationStore(options.rootPath, artifacts);
|
|
8990
|
+
await observations.initialize();
|
|
8429
8991
|
return {
|
|
8430
8992
|
rootPath: options.rootPath,
|
|
8431
8993
|
manifestPath,
|
|
@@ -8438,10 +9000,12 @@ async function createFilesystemOpensteerWorkspace(options) {
|
|
|
8438
9000
|
liveCloudPath,
|
|
8439
9001
|
artifactsPath,
|
|
8440
9002
|
tracesPath,
|
|
9003
|
+
observationsPath,
|
|
8441
9004
|
registryPath,
|
|
8442
9005
|
lockPath,
|
|
8443
9006
|
artifacts,
|
|
8444
9007
|
traces,
|
|
9008
|
+
observations,
|
|
8445
9009
|
registry: {
|
|
8446
9010
|
descriptors,
|
|
8447
9011
|
requestPlans,
|
|
@@ -8628,10 +9192,10 @@ function delayWithSignal(delayMs, signal) {
|
|
|
8628
9192
|
if (signal.aborted) {
|
|
8629
9193
|
return Promise.reject(signal.reason ?? abortError());
|
|
8630
9194
|
}
|
|
8631
|
-
return new Promise((
|
|
9195
|
+
return new Promise((resolve4, reject) => {
|
|
8632
9196
|
const timer = setTimeout(() => {
|
|
8633
9197
|
signal.removeEventListener("abort", onAbort);
|
|
8634
|
-
|
|
9198
|
+
resolve4();
|
|
8635
9199
|
}, delayMs);
|
|
8636
9200
|
const onAbort = () => {
|
|
8637
9201
|
clearTimeout(timer);
|
|
@@ -9096,9 +9660,9 @@ var IFRAME_URL_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
|
9096
9660
|
"poster",
|
|
9097
9661
|
"ping"
|
|
9098
9662
|
]);
|
|
9099
|
-
function buildArrayFieldPathCandidates(
|
|
9100
|
-
const strict =
|
|
9101
|
-
const relaxedNodes = stripPositionClauses(
|
|
9663
|
+
function buildArrayFieldPathCandidates(path15) {
|
|
9664
|
+
const strict = path15.nodes.length ? buildPathCandidates(path15.nodes) : [];
|
|
9665
|
+
const relaxedNodes = stripPositionClauses(path15.nodes);
|
|
9102
9666
|
const relaxed = relaxedNodes.length ? buildPathCandidates(relaxedNodes) : [];
|
|
9103
9667
|
return dedupeSelectors([...strict, ...relaxed]);
|
|
9104
9668
|
}
|
|
@@ -9628,18 +10192,18 @@ function cloneStructuralElementAnchor(anchor) {
|
|
|
9628
10192
|
nodes: anchor.nodes.map(clonePathNode)
|
|
9629
10193
|
};
|
|
9630
10194
|
}
|
|
9631
|
-
function cloneReplayElementPath(
|
|
10195
|
+
function cloneReplayElementPath(path15) {
|
|
9632
10196
|
return {
|
|
9633
10197
|
resolution: "deterministic",
|
|
9634
|
-
context: cloneContext(
|
|
9635
|
-
nodes:
|
|
10198
|
+
context: cloneContext(path15.context),
|
|
10199
|
+
nodes: path15.nodes.map(clonePathNode)
|
|
9636
10200
|
};
|
|
9637
10201
|
}
|
|
9638
|
-
function cloneElementPath(
|
|
9639
|
-
return cloneReplayElementPath(
|
|
10202
|
+
function cloneElementPath(path15) {
|
|
10203
|
+
return cloneReplayElementPath(path15);
|
|
9640
10204
|
}
|
|
9641
|
-
function buildPathSelectorHint(
|
|
9642
|
-
const nodes =
|
|
10205
|
+
function buildPathSelectorHint(path15) {
|
|
10206
|
+
const nodes = path15?.nodes || [];
|
|
9643
10207
|
const last = nodes[nodes.length - 1];
|
|
9644
10208
|
if (!last) {
|
|
9645
10209
|
return "*";
|
|
@@ -9688,15 +10252,15 @@ function sanitizeStructuralElementAnchor(anchor) {
|
|
|
9688
10252
|
nodes: sanitizeNodes(anchor.nodes)
|
|
9689
10253
|
};
|
|
9690
10254
|
}
|
|
9691
|
-
function sanitizeReplayElementPath(
|
|
10255
|
+
function sanitizeReplayElementPath(path15) {
|
|
9692
10256
|
return {
|
|
9693
10257
|
resolution: "deterministic",
|
|
9694
|
-
context: sanitizeContext(
|
|
9695
|
-
nodes: sanitizeNodes(
|
|
10258
|
+
context: sanitizeContext(path15.context),
|
|
10259
|
+
nodes: sanitizeNodes(path15.nodes)
|
|
9696
10260
|
};
|
|
9697
10261
|
}
|
|
9698
|
-
function sanitizeElementPath(
|
|
9699
|
-
return sanitizeReplayElementPath(
|
|
10262
|
+
function sanitizeElementPath(path15) {
|
|
10263
|
+
return sanitizeReplayElementPath(path15);
|
|
9700
10264
|
}
|
|
9701
10265
|
function buildLocalStructuralElementAnchor(index, rawTargetNode) {
|
|
9702
10266
|
const targetNode = requireElementNode(index, rawTargetNode);
|
|
@@ -9819,8 +10383,8 @@ function buildTargetNotFoundMessage(domPath, diagnostics) {
|
|
|
9819
10383
|
}
|
|
9820
10384
|
return `${base} Target depth ${String(depth)}. Candidate counts: ${sample}.`;
|
|
9821
10385
|
}
|
|
9822
|
-
function buildArrayFieldCandidates(
|
|
9823
|
-
return buildArrayFieldPathCandidates(
|
|
10386
|
+
function buildArrayFieldCandidates(path15) {
|
|
10387
|
+
return buildArrayFieldPathCandidates(path15);
|
|
9824
10388
|
}
|
|
9825
10389
|
function firstDefinedAttribute(node, keys) {
|
|
9826
10390
|
for (const key of keys) {
|
|
@@ -10274,7 +10838,8 @@ async function captureActionBoundarySnapshot(engine, pageRef) {
|
|
|
10274
10838
|
}
|
|
10275
10839
|
return {
|
|
10276
10840
|
pageRef,
|
|
10277
|
-
documentRef: mainFrame.documentRef
|
|
10841
|
+
documentRef: mainFrame.documentRef,
|
|
10842
|
+
url: mainFrame.url
|
|
10278
10843
|
};
|
|
10279
10844
|
}
|
|
10280
10845
|
function createActionBoundaryDiagnostics(input) {
|
|
@@ -10329,14 +10894,16 @@ var DomActionExecutor = class {
|
|
|
10329
10894
|
...input.timeout === void 0 ? {} : { timeout: input.timeout }
|
|
10330
10895
|
},
|
|
10331
10896
|
async (pointerTarget, point, timeout) => {
|
|
10332
|
-
|
|
10897
|
+
const events = [];
|
|
10898
|
+
const moved = await timeout.runStep(
|
|
10333
10899
|
() => this.options.engine.mouseMove({
|
|
10334
10900
|
pageRef: pointerTarget.resolved.pageRef,
|
|
10335
10901
|
point,
|
|
10336
10902
|
coordinateSpace: "document-css"
|
|
10337
10903
|
})
|
|
10338
10904
|
);
|
|
10339
|
-
|
|
10905
|
+
events.push(...moved.events);
|
|
10906
|
+
const clicked = await timeout.runStep(
|
|
10340
10907
|
() => this.options.engine.mouseClick({
|
|
10341
10908
|
pageRef: pointerTarget.resolved.pageRef,
|
|
10342
10909
|
point,
|
|
@@ -10346,7 +10913,12 @@ var DomActionExecutor = class {
|
|
|
10346
10913
|
...input.modifiers === void 0 ? {} : { modifiers: input.modifiers }
|
|
10347
10914
|
})
|
|
10348
10915
|
);
|
|
10349
|
-
|
|
10916
|
+
events.push(...clicked.events);
|
|
10917
|
+
return {
|
|
10918
|
+
resolved: pointerTarget.original,
|
|
10919
|
+
point,
|
|
10920
|
+
...events.length === 0 ? {} : { events }
|
|
10921
|
+
};
|
|
10350
10922
|
}
|
|
10351
10923
|
);
|
|
10352
10924
|
}
|
|
@@ -10360,14 +10932,18 @@ var DomActionExecutor = class {
|
|
|
10360
10932
|
...input.timeout === void 0 ? {} : { timeout: input.timeout }
|
|
10361
10933
|
},
|
|
10362
10934
|
async (pointerTarget, point, timeout) => {
|
|
10363
|
-
await timeout.runStep(
|
|
10935
|
+
const moved = await timeout.runStep(
|
|
10364
10936
|
() => this.options.engine.mouseMove({
|
|
10365
10937
|
pageRef: pointerTarget.resolved.pageRef,
|
|
10366
10938
|
point,
|
|
10367
10939
|
coordinateSpace: "document-css"
|
|
10368
10940
|
})
|
|
10369
10941
|
);
|
|
10370
|
-
return {
|
|
10942
|
+
return {
|
|
10943
|
+
resolved: pointerTarget.original,
|
|
10944
|
+
point,
|
|
10945
|
+
...moved.events.length === 0 ? {} : { events: moved.events }
|
|
10946
|
+
};
|
|
10371
10947
|
}
|
|
10372
10948
|
);
|
|
10373
10949
|
}
|
|
@@ -10381,14 +10957,16 @@ var DomActionExecutor = class {
|
|
|
10381
10957
|
...input.timeout === void 0 ? {} : { timeout: input.timeout }
|
|
10382
10958
|
},
|
|
10383
10959
|
async (pointerTarget, point, timeout) => {
|
|
10384
|
-
|
|
10960
|
+
const events = [];
|
|
10961
|
+
const moved = await timeout.runStep(
|
|
10385
10962
|
() => this.options.engine.mouseMove({
|
|
10386
10963
|
pageRef: pointerTarget.resolved.pageRef,
|
|
10387
10964
|
point,
|
|
10388
10965
|
coordinateSpace: "document-css"
|
|
10389
10966
|
})
|
|
10390
10967
|
);
|
|
10391
|
-
|
|
10968
|
+
events.push(...moved.events);
|
|
10969
|
+
const scrolled = await timeout.runStep(
|
|
10392
10970
|
() => this.options.engine.mouseScroll({
|
|
10393
10971
|
pageRef: pointerTarget.resolved.pageRef,
|
|
10394
10972
|
point,
|
|
@@ -10396,7 +10974,12 @@ var DomActionExecutor = class {
|
|
|
10396
10974
|
delta: input.delta
|
|
10397
10975
|
})
|
|
10398
10976
|
);
|
|
10399
|
-
|
|
10977
|
+
events.push(...scrolled.events);
|
|
10978
|
+
return {
|
|
10979
|
+
resolved: pointerTarget.original,
|
|
10980
|
+
point,
|
|
10981
|
+
...events.length === 0 ? {} : { events }
|
|
10982
|
+
};
|
|
10400
10983
|
}
|
|
10401
10984
|
);
|
|
10402
10985
|
}
|
|
@@ -11322,21 +11905,21 @@ var DefaultDomRuntime = class {
|
|
|
11322
11905
|
return match;
|
|
11323
11906
|
}
|
|
11324
11907
|
async resolvePathTarget(session, pageRef, rawPath, source, description, descriptor) {
|
|
11325
|
-
const
|
|
11326
|
-
const context = await this.resolvePathContext(session, pageRef,
|
|
11327
|
-
const target = resolveDomPathInScope(context.index,
|
|
11908
|
+
const path15 = sanitizeReplayElementPath(rawPath);
|
|
11909
|
+
const context = await this.resolvePathContext(session, pageRef, path15.context);
|
|
11910
|
+
const target = resolveDomPathInScope(context.index, path15.nodes, context.scope);
|
|
11328
11911
|
if (!target) {
|
|
11329
|
-
throwTargetNotFound(context.index,
|
|
11912
|
+
throwTargetNotFound(context.index, path15.nodes, context.scope);
|
|
11330
11913
|
}
|
|
11331
11914
|
if (target.node.nodeRef === void 0) {
|
|
11332
11915
|
throw new Error(
|
|
11333
|
-
`resolved path "${buildPathSelectorHint(
|
|
11916
|
+
`resolved path "${buildPathSelectorHint(path15)}" does not point to a live element`
|
|
11334
11917
|
);
|
|
11335
11918
|
}
|
|
11336
11919
|
const anchor = await this.buildAnchorFromSnapshotNode(session, context.snapshot, target.node);
|
|
11337
11920
|
return this.createResolvedTarget(source, context.snapshot, target.node, anchor, {
|
|
11338
11921
|
...description === void 0 ? {} : { description },
|
|
11339
|
-
replayPath:
|
|
11922
|
+
replayPath: path15,
|
|
11340
11923
|
...source === "path" || source === "descriptor" ? { selectorUsed: target.selector } : {},
|
|
11341
11924
|
...descriptor === void 0 ? {} : { descriptor }
|
|
11342
11925
|
});
|
|
@@ -11357,9 +11940,9 @@ var DefaultDomRuntime = class {
|
|
|
11357
11940
|
});
|
|
11358
11941
|
}
|
|
11359
11942
|
async queryAllByElementPath(session, pageRef, rawPath) {
|
|
11360
|
-
const
|
|
11361
|
-
const context = await this.resolvePathContext(session, pageRef,
|
|
11362
|
-
return queryAllDomPathInScope(context.index,
|
|
11943
|
+
const path15 = sanitizeReplayElementPath(rawPath);
|
|
11944
|
+
const context = await this.resolvePathContext(session, pageRef, path15.context);
|
|
11945
|
+
return queryAllDomPathInScope(context.index, path15.nodes, context.scope).filter(
|
|
11363
11946
|
(node) => node.nodeRef !== void 0
|
|
11364
11947
|
).map((node) => this.createSnapshotTarget(context.snapshot, node));
|
|
11365
11948
|
}
|
|
@@ -11545,16 +12128,16 @@ var DefaultDomRuntime = class {
|
|
|
11545
12128
|
const index = createSnapshotIndex(item.snapshot);
|
|
11546
12129
|
return this.resolveFirstArrayFieldTargetInNode(index, item.node, field.path);
|
|
11547
12130
|
}
|
|
11548
|
-
resolveFirstArrayFieldTargetInNode(index, rootNode,
|
|
11549
|
-
const normalizedPath = sanitizeElementPath(
|
|
12131
|
+
resolveFirstArrayFieldTargetInNode(index, rootNode, path15) {
|
|
12132
|
+
const normalizedPath = sanitizeElementPath(path15);
|
|
11550
12133
|
const selectors = buildArrayFieldCandidates(normalizedPath);
|
|
11551
12134
|
if (!selectors.length) {
|
|
11552
12135
|
return rootNode;
|
|
11553
12136
|
}
|
|
11554
12137
|
return resolveFirstWithinNodeBySelectors(index, rootNode, selectors);
|
|
11555
12138
|
}
|
|
11556
|
-
resolveUniqueArrayFieldTargetInNode(index, rootNode,
|
|
11557
|
-
const normalizedPath = sanitizeElementPath(
|
|
12139
|
+
resolveUniqueArrayFieldTargetInNode(index, rootNode, path15) {
|
|
12140
|
+
const normalizedPath = sanitizeElementPath(path15);
|
|
11558
12141
|
const selectors = buildArrayFieldCandidates(normalizedPath);
|
|
11559
12142
|
if (!selectors.length) {
|
|
11560
12143
|
return rootNode;
|
|
@@ -11643,8 +12226,8 @@ function encodeDataPath(tokens) {
|
|
|
11643
12226
|
}
|
|
11644
12227
|
return out;
|
|
11645
12228
|
}
|
|
11646
|
-
function parseDataPath(
|
|
11647
|
-
const input =
|
|
12229
|
+
function parseDataPath(path15) {
|
|
12230
|
+
const input = path15.trim();
|
|
11648
12231
|
if (input.length === 0) {
|
|
11649
12232
|
return [];
|
|
11650
12233
|
}
|
|
@@ -11694,8 +12277,8 @@ function parseDataPath(path13) {
|
|
|
11694
12277
|
function inflateDataPathObject(flat) {
|
|
11695
12278
|
let root = {};
|
|
11696
12279
|
let initialized = false;
|
|
11697
|
-
for (const [
|
|
11698
|
-
const tokens = parseDataPath(
|
|
12280
|
+
for (const [path15, value] of Object.entries(flat)) {
|
|
12281
|
+
const tokens = parseDataPath(path15);
|
|
11699
12282
|
if (!tokens || tokens.length === 0) {
|
|
11700
12283
|
continue;
|
|
11701
12284
|
}
|
|
@@ -12027,8 +12610,8 @@ function buildVariantDescriptorFromCluster(descriptors) {
|
|
|
12027
12610
|
fields: mergedFields
|
|
12028
12611
|
};
|
|
12029
12612
|
}
|
|
12030
|
-
function minimizePathMatchClauses(
|
|
12031
|
-
const normalized = sanitizeElementPath(
|
|
12613
|
+
function minimizePathMatchClauses(path15, mode) {
|
|
12614
|
+
const normalized = sanitizeElementPath(path15);
|
|
12032
12615
|
const nodes = normalized.nodes.map((node, index) => {
|
|
12033
12616
|
const isLast = index === normalized.nodes.length - 1;
|
|
12034
12617
|
const attrs = node.attrs || {};
|
|
@@ -12132,8 +12715,8 @@ function seedMinimalAttrClause(attrs) {
|
|
|
12132
12715
|
}
|
|
12133
12716
|
return null;
|
|
12134
12717
|
}
|
|
12135
|
-
function relaxPathForSingleSample(
|
|
12136
|
-
const normalized = sanitizeElementPath(
|
|
12718
|
+
function relaxPathForSingleSample(path15, mode) {
|
|
12719
|
+
const normalized = sanitizeElementPath(path15);
|
|
12137
12720
|
const relaxedNodes = normalized.nodes.map((node, index) => {
|
|
12138
12721
|
const isLast = index === normalized.nodes.length - 1;
|
|
12139
12722
|
const attrs = normalizeAttrsForSingleSample(node.attrs || {});
|
|
@@ -12218,8 +12801,8 @@ function shouldKeepAttrForSingleSample(key) {
|
|
|
12218
12801
|
}
|
|
12219
12802
|
return true;
|
|
12220
12803
|
}
|
|
12221
|
-
function buildPathStructureKey(
|
|
12222
|
-
const normalized = sanitizeElementPath(
|
|
12804
|
+
function buildPathStructureKey(path15) {
|
|
12805
|
+
const normalized = sanitizeElementPath(path15);
|
|
12223
12806
|
return canonicalJsonString({
|
|
12224
12807
|
context: (normalized.context || []).map((hop) => ({
|
|
12225
12808
|
kind: hop.kind,
|
|
@@ -12346,30 +12929,30 @@ function buildArrayItemNode(fields) {
|
|
|
12346
12929
|
}
|
|
12347
12930
|
return node;
|
|
12348
12931
|
}
|
|
12349
|
-
function insertNodeAtPath(root,
|
|
12350
|
-
const tokens = parseDataPath(
|
|
12932
|
+
function insertNodeAtPath(root, path15, node) {
|
|
12933
|
+
const tokens = parseDataPath(path15);
|
|
12351
12934
|
if (!tokens || !tokens.length) {
|
|
12352
12935
|
throw new Error(
|
|
12353
|
-
`Invalid persisted extraction path "${
|
|
12936
|
+
`Invalid persisted extraction path "${path15}": expected a non-empty object path.`
|
|
12354
12937
|
);
|
|
12355
12938
|
}
|
|
12356
12939
|
if (tokens.some((token) => token.kind === "index")) {
|
|
12357
12940
|
throw new Error(
|
|
12358
|
-
`Invalid persisted extraction path "${
|
|
12941
|
+
`Invalid persisted extraction path "${path15}": nested array indices are not supported in cached descriptors.`
|
|
12359
12942
|
);
|
|
12360
12943
|
}
|
|
12361
12944
|
let current = root;
|
|
12362
12945
|
for (let index = 0; index < tokens.length; index += 1) {
|
|
12363
12946
|
const token = tokens[index];
|
|
12364
12947
|
if (!token || token.kind !== "prop") {
|
|
12365
|
-
throw new Error(`Invalid persisted extraction path "${
|
|
12948
|
+
throw new Error(`Invalid persisted extraction path "${path15}": expected object segment.`);
|
|
12366
12949
|
}
|
|
12367
12950
|
const isLast = index === tokens.length - 1;
|
|
12368
12951
|
if (isLast) {
|
|
12369
12952
|
const existing = current[token.key];
|
|
12370
12953
|
if (existing) {
|
|
12371
12954
|
throw new Error(
|
|
12372
|
-
`Conflicting persisted extraction path "${
|
|
12955
|
+
`Conflicting persisted extraction path "${path15}" detected while building descriptor tree.`
|
|
12373
12956
|
);
|
|
12374
12957
|
}
|
|
12375
12958
|
current[token.key] = node;
|
|
@@ -12384,7 +12967,7 @@ function insertNodeAtPath(root, path13, node) {
|
|
|
12384
12967
|
}
|
|
12385
12968
|
if (!isPersistedObjectNode(next)) {
|
|
12386
12969
|
throw new Error(
|
|
12387
|
-
`Conflicting persisted extraction path "${
|
|
12970
|
+
`Conflicting persisted extraction path "${path15}" detected at "${token.key}".`
|
|
12388
12971
|
);
|
|
12389
12972
|
}
|
|
12390
12973
|
current = next;
|
|
@@ -12419,7 +13002,7 @@ function buildItemRootForArrayIndex(entries) {
|
|
|
12419
13002
|
}
|
|
12420
13003
|
const paths = entries.map(
|
|
12421
13004
|
(entry) => isPersistablePathField(entry.source) ? sanitizeElementPath(entry.source.path) : null
|
|
12422
|
-
).filter((
|
|
13005
|
+
).filter((path15) => path15 !== null);
|
|
12423
13006
|
if (!paths.length) {
|
|
12424
13007
|
return null;
|
|
12425
13008
|
}
|
|
@@ -12440,7 +13023,7 @@ function getCommonPathPrefixLength(paths) {
|
|
|
12440
13023
|
if (!paths.length) {
|
|
12441
13024
|
return 0;
|
|
12442
13025
|
}
|
|
12443
|
-
const nodeChains = paths.map((
|
|
13026
|
+
const nodeChains = paths.map((path15) => path15.nodes);
|
|
12444
13027
|
const minLength = Math.min(...nodeChains.map((nodes) => nodes.length));
|
|
12445
13028
|
if (!Number.isFinite(minLength) || minLength <= 0) {
|
|
12446
13029
|
return 0;
|
|
@@ -12509,30 +13092,30 @@ function mergeElementPathsByMajority(paths) {
|
|
|
12509
13092
|
if (!paths.length) {
|
|
12510
13093
|
return null;
|
|
12511
13094
|
}
|
|
12512
|
-
const normalized = paths.map((
|
|
13095
|
+
const normalized = paths.map((path15) => sanitizeElementPath(path15));
|
|
12513
13096
|
const contextKey = pickModeString(
|
|
12514
|
-
normalized.map((
|
|
13097
|
+
normalized.map((path15) => canonicalJsonString(path15.context)),
|
|
12515
13098
|
1
|
|
12516
13099
|
);
|
|
12517
13100
|
if (!contextKey) {
|
|
12518
13101
|
return null;
|
|
12519
13102
|
}
|
|
12520
|
-
const sameContext = normalized.filter((
|
|
13103
|
+
const sameContext = normalized.filter((path15) => canonicalJsonString(path15.context) === contextKey);
|
|
12521
13104
|
if (!sameContext.length) {
|
|
12522
13105
|
return null;
|
|
12523
13106
|
}
|
|
12524
13107
|
const targetLength = pickModeNumber(
|
|
12525
|
-
sameContext.map((
|
|
13108
|
+
sameContext.map((path15) => path15.nodes.length),
|
|
12526
13109
|
1
|
|
12527
13110
|
) ?? sameContext[0]?.nodes.length ?? 0;
|
|
12528
|
-
const aligned = sameContext.filter((
|
|
13111
|
+
const aligned = sameContext.filter((path15) => path15.nodes.length === targetLength);
|
|
12529
13112
|
if (!aligned.length) {
|
|
12530
13113
|
return null;
|
|
12531
13114
|
}
|
|
12532
13115
|
const threshold = majorityThreshold(aligned.length);
|
|
12533
13116
|
const nodes = [];
|
|
12534
13117
|
for (let index = 0; index < targetLength; index += 1) {
|
|
12535
|
-
const nodesAtIndex = aligned.map((
|
|
13118
|
+
const nodesAtIndex = aligned.map((path15) => path15.nodes[index]).filter((node) => node !== void 0);
|
|
12536
13119
|
if (!nodesAtIndex.length) {
|
|
12537
13120
|
return null;
|
|
12538
13121
|
}
|
|
@@ -12778,8 +13361,8 @@ function clonePathContext(context) {
|
|
|
12778
13361
|
function clonePathNodes(nodes) {
|
|
12779
13362
|
return JSON.parse(JSON.stringify(nodes || []));
|
|
12780
13363
|
}
|
|
12781
|
-
function cloneElementPath2(
|
|
12782
|
-
return JSON.parse(JSON.stringify(
|
|
13364
|
+
function cloneElementPath2(path15) {
|
|
13365
|
+
return JSON.parse(JSON.stringify(path15));
|
|
12783
13366
|
}
|
|
12784
13367
|
function clonePersistedOpensteerExtractionNode(node) {
|
|
12785
13368
|
return JSON.parse(JSON.stringify(node));
|
|
@@ -13097,8 +13680,8 @@ function collectPersistedValueNodeRefs(node) {
|
|
|
13097
13680
|
return [
|
|
13098
13681
|
{
|
|
13099
13682
|
path: sanitizeElementPath(node.$path),
|
|
13100
|
-
replacePath: (
|
|
13101
|
-
node.$path = sanitizeElementPath(
|
|
13683
|
+
replacePath: (path15) => {
|
|
13684
|
+
node.$path = sanitizeElementPath(path15);
|
|
13102
13685
|
}
|
|
13103
13686
|
}
|
|
13104
13687
|
];
|
|
@@ -13112,13 +13695,13 @@ function collectPersistedValueNodeRefs(node) {
|
|
|
13112
13695
|
}
|
|
13113
13696
|
return refs;
|
|
13114
13697
|
}
|
|
13115
|
-
function hasPositionClause(
|
|
13116
|
-
return
|
|
13698
|
+
function hasPositionClause(path15) {
|
|
13699
|
+
return path15.nodes.some((node) => node.match.some((clause) => clause.kind === "position"));
|
|
13117
13700
|
}
|
|
13118
|
-
function stripPositionClauses2(
|
|
13701
|
+
function stripPositionClauses2(path15) {
|
|
13119
13702
|
return sanitizeElementPath({
|
|
13120
|
-
context:
|
|
13121
|
-
nodes:
|
|
13703
|
+
context: path15.context,
|
|
13704
|
+
nodes: path15.nodes.map((node) => ({
|
|
13122
13705
|
...node,
|
|
13123
13706
|
match: node.match.filter((clause) => clause.kind !== "position")
|
|
13124
13707
|
}))
|
|
@@ -13528,8 +14111,8 @@ function normalizeNonEmptyString2(name, value) {
|
|
|
13528
14111
|
function normalizeKey(value) {
|
|
13529
14112
|
return String(value ?? "").trim();
|
|
13530
14113
|
}
|
|
13531
|
-
function labelForPath(
|
|
13532
|
-
return
|
|
14114
|
+
function labelForPath(path15) {
|
|
14115
|
+
return path15.trim().length === 0 ? "$" : path15;
|
|
13533
14116
|
}
|
|
13534
14117
|
function sha256Hex3(value) {
|
|
13535
14118
|
return crypto.createHash("sha256").update(value).digest("hex");
|
|
@@ -13558,7 +14141,7 @@ var CHROME_SINGLETON_ARTIFACTS = [
|
|
|
13558
14141
|
async function clearChromeSingletonEntries(userDataDir) {
|
|
13559
14142
|
await Promise.all(
|
|
13560
14143
|
CHROME_SINGLETON_ARTIFACTS.map(
|
|
13561
|
-
(entry) => promises.rm(
|
|
14144
|
+
(entry) => promises.rm(path7.join(userDataDir, entry), {
|
|
13562
14145
|
recursive: true,
|
|
13563
14146
|
force: true
|
|
13564
14147
|
}).catch(() => void 0)
|
|
@@ -13573,7 +14156,7 @@ async function sanitizeChromeProfile(userDataDir) {
|
|
|
13573
14156
|
await Promise.all(profileDirs.map((dir) => sanitizeProfilePreferences(userDataDir, dir)));
|
|
13574
14157
|
}
|
|
13575
14158
|
async function sanitizeProfilePreferences(userDataDir, profileDir) {
|
|
13576
|
-
const prefsPath =
|
|
14159
|
+
const prefsPath = path7.join(userDataDir, profileDir, "Preferences");
|
|
13577
14160
|
try {
|
|
13578
14161
|
const raw = await promises.readFile(prefsPath, "utf8");
|
|
13579
14162
|
const prefs = JSON.parse(raw);
|
|
@@ -13585,14 +14168,13 @@ async function sanitizeProfilePreferences(userDataDir, profileDir) {
|
|
|
13585
14168
|
profile.exited_cleanly = true;
|
|
13586
14169
|
prefs.profile = profile;
|
|
13587
14170
|
await promises.writeFile(prefsPath, JSON.stringify(prefs), "utf8");
|
|
13588
|
-
await promises.rm(
|
|
14171
|
+
await promises.rm(path7.join(userDataDir, profileDir, "Secure Preferences"), { force: true }).catch(
|
|
13589
14172
|
() => void 0
|
|
13590
14173
|
);
|
|
13591
14174
|
} catch {
|
|
13592
14175
|
}
|
|
13593
14176
|
}
|
|
13594
|
-
|
|
13595
|
-
var PS_COMMAND_ENV2 = { ...process.env, LC_ALL: "C" };
|
|
14177
|
+
({ ...process.env});
|
|
13596
14178
|
var WINDOWS_PROGRAM_FILES = process.env.PROGRAMFILES ?? "C:\\Program Files";
|
|
13597
14179
|
var WINDOWS_PROGRAM_FILES_X86 = process.env["PROGRAMFILES(X86)"] ?? "C:\\Program Files (x86)";
|
|
13598
14180
|
var BROWSER_BRANDS = [
|
|
@@ -13607,9 +14189,9 @@ var BROWSER_BRANDS = [
|
|
|
13607
14189
|
},
|
|
13608
14190
|
win32: {
|
|
13609
14191
|
executableCandidates: [
|
|
13610
|
-
|
|
13611
|
-
|
|
13612
|
-
|
|
14192
|
+
path7.join(WINDOWS_PROGRAM_FILES, "Google", "Chrome", "Application", "chrome.exe"),
|
|
14193
|
+
path7.join(WINDOWS_PROGRAM_FILES_X86, "Google", "Chrome", "Application", "chrome.exe"),
|
|
14194
|
+
path7.join("~", "AppData", "Local", "Google", "Chrome", "Application", "chrome.exe")
|
|
13613
14195
|
],
|
|
13614
14196
|
userDataDir: "~/AppData/Local/Google/Chrome/User Data",
|
|
13615
14197
|
processNames: ["/google/chrome/application/chrome.exe"]
|
|
@@ -13639,7 +14221,7 @@ var BROWSER_BRANDS = [
|
|
|
13639
14221
|
},
|
|
13640
14222
|
win32: {
|
|
13641
14223
|
executableCandidates: [
|
|
13642
|
-
|
|
14224
|
+
path7.join("~", "AppData", "Local", "Google", "Chrome SxS", "Application", "chrome.exe")
|
|
13643
14225
|
],
|
|
13644
14226
|
userDataDir: "~/AppData/Local/Google/Chrome SxS/User Data",
|
|
13645
14227
|
processNames: ["/google/chrome sxs/application/chrome.exe"]
|
|
@@ -13656,9 +14238,9 @@ var BROWSER_BRANDS = [
|
|
|
13656
14238
|
},
|
|
13657
14239
|
win32: {
|
|
13658
14240
|
executableCandidates: [
|
|
13659
|
-
|
|
13660
|
-
|
|
13661
|
-
|
|
14241
|
+
path7.join(WINDOWS_PROGRAM_FILES, "Chromium", "Application", "chrome.exe"),
|
|
14242
|
+
path7.join(WINDOWS_PROGRAM_FILES_X86, "Chromium", "Application", "chrome.exe"),
|
|
14243
|
+
path7.join("~", "AppData", "Local", "Chromium", "Application", "chrome.exe")
|
|
13662
14244
|
],
|
|
13663
14245
|
userDataDir: "~/AppData/Local/Chromium/User Data",
|
|
13664
14246
|
processNames: ["/chromium/application/chrome.exe"]
|
|
@@ -13685,15 +14267,15 @@ var BROWSER_BRANDS = [
|
|
|
13685
14267
|
},
|
|
13686
14268
|
win32: {
|
|
13687
14269
|
executableCandidates: [
|
|
13688
|
-
|
|
13689
|
-
|
|
14270
|
+
path7.join(WINDOWS_PROGRAM_FILES, "BraveSoftware", "Brave-Browser", "Application", "brave.exe"),
|
|
14271
|
+
path7.join(
|
|
13690
14272
|
WINDOWS_PROGRAM_FILES_X86,
|
|
13691
14273
|
"BraveSoftware",
|
|
13692
14274
|
"Brave-Browser",
|
|
13693
14275
|
"Application",
|
|
13694
14276
|
"brave.exe"
|
|
13695
14277
|
),
|
|
13696
|
-
|
|
14278
|
+
path7.join("~", "AppData", "Local", "BraveSoftware", "Brave-Browser", "Application", "brave.exe")
|
|
13697
14279
|
],
|
|
13698
14280
|
userDataDir: "~/AppData/Local/BraveSoftware/Brave-Browser/User Data",
|
|
13699
14281
|
processNames: ["/bravesoftware/brave-browser/application/brave.exe"]
|
|
@@ -13719,9 +14301,9 @@ var BROWSER_BRANDS = [
|
|
|
13719
14301
|
},
|
|
13720
14302
|
win32: {
|
|
13721
14303
|
executableCandidates: [
|
|
13722
|
-
|
|
13723
|
-
|
|
13724
|
-
|
|
14304
|
+
path7.join(WINDOWS_PROGRAM_FILES, "Microsoft", "Edge", "Application", "msedge.exe"),
|
|
14305
|
+
path7.join(WINDOWS_PROGRAM_FILES_X86, "Microsoft", "Edge", "Application", "msedge.exe"),
|
|
14306
|
+
path7.join("~", "AppData", "Local", "Microsoft", "Edge", "Application", "msedge.exe")
|
|
13725
14307
|
],
|
|
13726
14308
|
userDataDir: "~/AppData/Local/Microsoft/Edge/User Data",
|
|
13727
14309
|
processNames: ["/microsoft/edge/application/msedge.exe"]
|
|
@@ -13749,9 +14331,9 @@ var BROWSER_BRANDS = [
|
|
|
13749
14331
|
},
|
|
13750
14332
|
win32: {
|
|
13751
14333
|
executableCandidates: [
|
|
13752
|
-
|
|
13753
|
-
|
|
13754
|
-
|
|
14334
|
+
path7.join(WINDOWS_PROGRAM_FILES, "Vivaldi", "Application", "vivaldi.exe"),
|
|
14335
|
+
path7.join(WINDOWS_PROGRAM_FILES_X86, "Vivaldi", "Application", "vivaldi.exe"),
|
|
14336
|
+
path7.join("~", "AppData", "Local", "Vivaldi", "Application", "vivaldi.exe")
|
|
13755
14337
|
],
|
|
13756
14338
|
userDataDir: "~/AppData/Local/Vivaldi/User Data",
|
|
13757
14339
|
processNames: ["/vivaldi/application/vivaldi.exe"]
|
|
@@ -13778,9 +14360,6 @@ var BROWSER_BRANDS = [
|
|
|
13778
14360
|
}
|
|
13779
14361
|
}
|
|
13780
14362
|
];
|
|
13781
|
-
function getAllBrowserBrands() {
|
|
13782
|
-
return BROWSER_BRANDS;
|
|
13783
|
-
}
|
|
13784
14363
|
function getBrowserBrand(id) {
|
|
13785
14364
|
const brand2 = BROWSER_BRANDS.find((candidate) => candidate.id === id);
|
|
13786
14365
|
if (!brand2) {
|
|
@@ -13818,177 +14397,35 @@ function detectInstalledBrowserBrands() {
|
|
|
13818
14397
|
brandId: brand2.id,
|
|
13819
14398
|
displayName: brand2.displayName,
|
|
13820
14399
|
executablePath,
|
|
13821
|
-
userDataDir:
|
|
14400
|
+
userDataDir: path7.resolve(expandHome(platformConfig.userDataDir))
|
|
13822
14401
|
});
|
|
13823
14402
|
}
|
|
13824
14403
|
return installations;
|
|
13825
14404
|
}
|
|
13826
|
-
function resolveBrandExecutablePath(brand2, explicitPath) {
|
|
13827
|
-
if (explicitPath !== void 0) {
|
|
13828
|
-
const resolvedPath2 = path6.resolve(expandHome(explicitPath));
|
|
13829
|
-
if (!fs.existsSync(resolvedPath2)) {
|
|
13830
|
-
throw new Error(`${brand2.displayName} executable was not found at "${resolvedPath2}".`);
|
|
13831
|
-
}
|
|
13832
|
-
return resolvedPath2;
|
|
13833
|
-
}
|
|
13834
|
-
const platformConfig = resolveBrandPlatformConfig(brand2);
|
|
13835
|
-
if (!platformConfig) {
|
|
13836
|
-
throw new Error(`${brand2.displayName} is not supported on ${process.platform}.`);
|
|
13837
|
-
}
|
|
13838
|
-
const resolvedPath = firstExistingPath(
|
|
13839
|
-
resolveExecutableCandidates(platformConfig.executableCandidates)
|
|
13840
|
-
);
|
|
13841
|
-
if (!resolvedPath) {
|
|
13842
|
-
throw new Error(
|
|
13843
|
-
`Could not find a ${brand2.displayName} executable. Pass --executable-path or browser.executablePath.`
|
|
13844
|
-
);
|
|
13845
|
-
}
|
|
13846
|
-
return resolvedPath;
|
|
13847
|
-
}
|
|
13848
14405
|
function resolveBrandUserDataDir(brand2, explicitDir) {
|
|
13849
14406
|
if (explicitDir !== void 0) {
|
|
13850
|
-
return
|
|
14407
|
+
return path7.resolve(expandHome(explicitDir));
|
|
13851
14408
|
}
|
|
13852
14409
|
const platformConfig = resolveBrandPlatformConfig(brand2);
|
|
13853
14410
|
if (!platformConfig) {
|
|
13854
14411
|
throw new Error(`${brand2.displayName} is not supported on ${process.platform}.`);
|
|
13855
14412
|
}
|
|
13856
|
-
return
|
|
13857
|
-
}
|
|
13858
|
-
function isBrandProcess(brand2, commandLine) {
|
|
13859
|
-
const normalizedCommand = normalizeCommand(commandLine);
|
|
13860
|
-
if (!normalizedCommand) {
|
|
13861
|
-
return false;
|
|
13862
|
-
}
|
|
13863
|
-
if (normalizedCommand.includes("crashpad_handler")) {
|
|
13864
|
-
return false;
|
|
13865
|
-
}
|
|
13866
|
-
if (/\s--type=/.test(normalizedCommand)) {
|
|
13867
|
-
return false;
|
|
13868
|
-
}
|
|
13869
|
-
return getBrandProcessMarkers(brand2).some((marker) => normalizedCommand.includes(marker));
|
|
13870
|
-
}
|
|
13871
|
-
function findBrandProcess(brand2) {
|
|
13872
|
-
for (const processEntry of listProcesses()) {
|
|
13873
|
-
if (isBrandProcess(brand2, processEntry.commandLine)) {
|
|
13874
|
-
return { pid: processEntry.pid };
|
|
13875
|
-
}
|
|
13876
|
-
}
|
|
13877
|
-
return null;
|
|
13878
|
-
}
|
|
13879
|
-
function getBrandProcessMarkers(brand2) {
|
|
13880
|
-
const markers = /* @__PURE__ */ new Set();
|
|
13881
|
-
for (const config of [brand2.darwin, brand2.win32, brand2.linux]) {
|
|
13882
|
-
if (!config) {
|
|
13883
|
-
continue;
|
|
13884
|
-
}
|
|
13885
|
-
for (const processName of config.processNames) {
|
|
13886
|
-
const normalized = normalizeCommand(processName);
|
|
13887
|
-
if (normalized) {
|
|
13888
|
-
markers.add(normalized);
|
|
13889
|
-
}
|
|
13890
|
-
}
|
|
13891
|
-
for (const candidate of config.executableCandidates) {
|
|
13892
|
-
if (!candidate) {
|
|
13893
|
-
continue;
|
|
13894
|
-
}
|
|
13895
|
-
const normalized = normalizeCommand(path6.resolve(expandHome(candidate)));
|
|
13896
|
-
if (normalized) {
|
|
13897
|
-
markers.add(normalized);
|
|
13898
|
-
}
|
|
13899
|
-
}
|
|
13900
|
-
}
|
|
13901
|
-
return [...markers];
|
|
14413
|
+
return path7.resolve(expandHome(platformConfig.userDataDir));
|
|
13902
14414
|
}
|
|
13903
14415
|
function resolveExecutableCandidates(candidates) {
|
|
13904
|
-
return candidates.map((candidate) => candidate ?
|
|
13905
|
-
}
|
|
13906
|
-
function listProcesses() {
|
|
13907
|
-
if (process.platform === "win32") {
|
|
13908
|
-
return listWindowsProcesses();
|
|
13909
|
-
}
|
|
13910
|
-
return listUnixProcesses();
|
|
13911
|
-
}
|
|
13912
|
-
function listUnixProcesses() {
|
|
13913
|
-
try {
|
|
13914
|
-
const output = child_process.execFileSync("ps", ["-A", "-o", "pid=,command="], {
|
|
13915
|
-
encoding: "utf8",
|
|
13916
|
-
env: PS_COMMAND_ENV2,
|
|
13917
|
-
maxBuffer: PROCESS_LIST_MAX_BUFFER_BYTES2,
|
|
13918
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
13919
|
-
});
|
|
13920
|
-
return output.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0).map((line) => {
|
|
13921
|
-
const match = /^(\d+)\s+(.*)$/.exec(line);
|
|
13922
|
-
if (!match) {
|
|
13923
|
-
return null;
|
|
13924
|
-
}
|
|
13925
|
-
const pid = Number.parseInt(match[1] ?? "", 10);
|
|
13926
|
-
const commandLine = match[2]?.trim() ?? "";
|
|
13927
|
-
if (!Number.isInteger(pid) || pid <= 0 || commandLine.length === 0) {
|
|
13928
|
-
return null;
|
|
13929
|
-
}
|
|
13930
|
-
return {
|
|
13931
|
-
pid,
|
|
13932
|
-
commandLine
|
|
13933
|
-
};
|
|
13934
|
-
}).filter(
|
|
13935
|
-
(entry) => entry !== null
|
|
13936
|
-
).sort((left, right) => left.pid - right.pid);
|
|
13937
|
-
} catch {
|
|
13938
|
-
return [];
|
|
13939
|
-
}
|
|
13940
|
-
}
|
|
13941
|
-
function listWindowsProcesses() {
|
|
13942
|
-
try {
|
|
13943
|
-
const output = child_process.execFileSync(
|
|
13944
|
-
"powershell.exe",
|
|
13945
|
-
[
|
|
13946
|
-
"-NoProfile",
|
|
13947
|
-
"-Command",
|
|
13948
|
-
"Get-CimInstance Win32_Process | Select-Object ProcessId,CommandLine | ConvertTo-Json -Compress"
|
|
13949
|
-
],
|
|
13950
|
-
{
|
|
13951
|
-
encoding: "utf8",
|
|
13952
|
-
maxBuffer: PROCESS_LIST_MAX_BUFFER_BYTES2,
|
|
13953
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
13954
|
-
}
|
|
13955
|
-
).trim();
|
|
13956
|
-
if (!output) {
|
|
13957
|
-
return [];
|
|
13958
|
-
}
|
|
13959
|
-
const parsed = JSON.parse(output);
|
|
13960
|
-
const records = Array.isArray(parsed) ? parsed : [parsed];
|
|
13961
|
-
return records.map((record) => {
|
|
13962
|
-
const pid = Number(record.ProcessId);
|
|
13963
|
-
const commandLine = typeof record.CommandLine === "string" ? record.CommandLine.trim() : "";
|
|
13964
|
-
if (!Number.isInteger(pid) || pid <= 0 || commandLine.length === 0) {
|
|
13965
|
-
return null;
|
|
13966
|
-
}
|
|
13967
|
-
return {
|
|
13968
|
-
pid,
|
|
13969
|
-
commandLine
|
|
13970
|
-
};
|
|
13971
|
-
}).filter(
|
|
13972
|
-
(entry) => entry !== null
|
|
13973
|
-
).sort((left, right) => left.pid - right.pid);
|
|
13974
|
-
} catch {
|
|
13975
|
-
return [];
|
|
13976
|
-
}
|
|
13977
|
-
}
|
|
13978
|
-
function normalizeCommand(value) {
|
|
13979
|
-
return value.trim().replaceAll("\\", "/").toLowerCase();
|
|
14416
|
+
return candidates.map((candidate) => candidate ? path7.resolve(expandHome(candidate)) : null);
|
|
13980
14417
|
}
|
|
13981
14418
|
|
|
13982
14419
|
// src/local-browser/chrome-discovery.ts
|
|
13983
14420
|
function expandHome(value) {
|
|
13984
14421
|
if (value === "~" || value.startsWith("~/")) {
|
|
13985
|
-
return
|
|
14422
|
+
return path7.join(os.homedir(), value.slice(1));
|
|
13986
14423
|
}
|
|
13987
14424
|
return value;
|
|
13988
14425
|
}
|
|
13989
14426
|
function resolveChromeUserDataDir(userDataDir) {
|
|
13990
14427
|
const installation = detectLocalChromeInstallations().find(
|
|
13991
|
-
(candidate) => fs.existsSync(
|
|
14428
|
+
(candidate) => fs.existsSync(path7.join(candidate.userDataDir, "Local State")) || candidate.executablePath !== null
|
|
13992
14429
|
);
|
|
13993
14430
|
if (!installation) {
|
|
13994
14431
|
throw new Error("Could not find a local Chrome or Chromium profile directory.");
|
|
@@ -13997,7 +14434,7 @@ function resolveChromeUserDataDir(userDataDir) {
|
|
|
13997
14434
|
}
|
|
13998
14435
|
function resolveChromeExecutablePath(executablePath) {
|
|
13999
14436
|
if (executablePath !== void 0) {
|
|
14000
|
-
const resolvedPath =
|
|
14437
|
+
const resolvedPath = path7.resolve(expandHome(executablePath));
|
|
14001
14438
|
if (!fs.existsSync(resolvedPath)) {
|
|
14002
14439
|
throw new Error(`Chrome executable was not found at "${resolvedPath}".`);
|
|
14003
14440
|
}
|
|
@@ -14021,37 +14458,37 @@ function detectLocalChromeInstallations() {
|
|
|
14021
14458
|
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
|
14022
14459
|
"/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary"
|
|
14023
14460
|
]),
|
|
14024
|
-
userDataDir:
|
|
14461
|
+
userDataDir: path7.join(os.homedir(), "Library", "Application Support", "Google", "Chrome")
|
|
14025
14462
|
},
|
|
14026
14463
|
{
|
|
14027
14464
|
brand: "chromium",
|
|
14028
14465
|
executablePath: firstExistingPath(["/Applications/Chromium.app/Contents/MacOS/Chromium"]),
|
|
14029
|
-
userDataDir:
|
|
14466
|
+
userDataDir: path7.join(os.homedir(), "Library", "Application Support", "Chromium")
|
|
14030
14467
|
}
|
|
14031
14468
|
];
|
|
14032
14469
|
}
|
|
14033
14470
|
if (process.platform === "win32") {
|
|
14034
14471
|
const programFiles = process.env.PROGRAMFILES ?? "C:\\Program Files";
|
|
14035
14472
|
const programFilesX86 = process.env["PROGRAMFILES(X86)"] ?? "C:\\Program Files (x86)";
|
|
14036
|
-
const localAppData = process.env.LOCALAPPDATA ??
|
|
14473
|
+
const localAppData = process.env.LOCALAPPDATA ?? path7.join(os.homedir(), "AppData", "Local");
|
|
14037
14474
|
return [
|
|
14038
14475
|
{
|
|
14039
14476
|
brand: "chrome",
|
|
14040
14477
|
executablePath: firstExistingPath([
|
|
14041
|
-
|
|
14042
|
-
|
|
14043
|
-
|
|
14478
|
+
path7.join(programFiles, "Google", "Chrome", "Application", "chrome.exe"),
|
|
14479
|
+
path7.join(programFilesX86, "Google", "Chrome", "Application", "chrome.exe"),
|
|
14480
|
+
path7.join(localAppData, "Google", "Chrome", "Application", "chrome.exe")
|
|
14044
14481
|
]),
|
|
14045
|
-
userDataDir:
|
|
14482
|
+
userDataDir: path7.join(localAppData, "Google", "Chrome", "User Data")
|
|
14046
14483
|
},
|
|
14047
14484
|
{
|
|
14048
14485
|
brand: "chromium",
|
|
14049
14486
|
executablePath: firstExistingPath([
|
|
14050
|
-
|
|
14051
|
-
|
|
14052
|
-
|
|
14487
|
+
path7.join(programFiles, "Chromium", "Application", "chrome.exe"),
|
|
14488
|
+
path7.join(programFilesX86, "Chromium", "Application", "chrome.exe"),
|
|
14489
|
+
path7.join(localAppData, "Chromium", "Application", "chrome.exe")
|
|
14053
14490
|
]),
|
|
14054
|
-
userDataDir:
|
|
14491
|
+
userDataDir: path7.join(localAppData, "Chromium", "User Data")
|
|
14055
14492
|
}
|
|
14056
14493
|
];
|
|
14057
14494
|
}
|
|
@@ -14064,7 +14501,7 @@ function detectLocalChromeInstallations() {
|
|
|
14064
14501
|
resolveBinaryFromPath("google-chrome"),
|
|
14065
14502
|
resolveBinaryFromPath("google-chrome-stable")
|
|
14066
14503
|
]),
|
|
14067
|
-
userDataDir:
|
|
14504
|
+
userDataDir: path7.join(os.homedir(), ".config", "google-chrome")
|
|
14068
14505
|
},
|
|
14069
14506
|
{
|
|
14070
14507
|
brand: "chromium",
|
|
@@ -14074,7 +14511,7 @@ function detectLocalChromeInstallations() {
|
|
|
14074
14511
|
resolveBinaryFromPath("chromium"),
|
|
14075
14512
|
resolveBinaryFromPath("chromium-browser")
|
|
14076
14513
|
]),
|
|
14077
|
-
userDataDir:
|
|
14514
|
+
userDataDir: path7.join(os.homedir(), ".config", "chromium")
|
|
14078
14515
|
}
|
|
14079
14516
|
];
|
|
14080
14517
|
}
|
|
@@ -14086,8 +14523,8 @@ function detectLocalBrowserInstallations() {
|
|
|
14086
14523
|
}));
|
|
14087
14524
|
}
|
|
14088
14525
|
function listLocalChromeProfiles(userDataDir = resolveChromeUserDataDir()) {
|
|
14089
|
-
const resolvedUserDataDir =
|
|
14090
|
-
const localStatePath =
|
|
14526
|
+
const resolvedUserDataDir = path7.resolve(expandHome(userDataDir));
|
|
14527
|
+
const localStatePath = path7.join(resolvedUserDataDir, "Local State");
|
|
14091
14528
|
if (!fs.existsSync(localStatePath)) {
|
|
14092
14529
|
return [];
|
|
14093
14530
|
}
|
|
@@ -14099,7 +14536,7 @@ function listLocalChromeProfiles(userDataDir = resolveChromeUserDataDir()) {
|
|
|
14099
14536
|
}
|
|
14100
14537
|
return Object.entries(infoCache).map(([directory, info]) => {
|
|
14101
14538
|
const record = info && typeof info === "object" && !Array.isArray(info) ? info : {};
|
|
14102
|
-
const name = typeof record.name === "string" && record.name.trim().length > 0 ? record.name.trim() : directory ||
|
|
14539
|
+
const name = typeof record.name === "string" && record.name.trim().length > 0 ? record.name.trim() : directory || path7.basename(directory);
|
|
14103
14540
|
return {
|
|
14104
14541
|
directory,
|
|
14105
14542
|
name,
|
|
@@ -14111,7 +14548,7 @@ function listLocalChromeProfiles(userDataDir = resolveChromeUserDataDir()) {
|
|
|
14111
14548
|
}
|
|
14112
14549
|
}
|
|
14113
14550
|
function readDevToolsActivePort(userDataDir) {
|
|
14114
|
-
const devToolsPath =
|
|
14551
|
+
const devToolsPath = path7.join(userDataDir, "DevToolsActivePort");
|
|
14115
14552
|
if (!fs.existsSync(devToolsPath)) {
|
|
14116
14553
|
return null;
|
|
14117
14554
|
}
|
|
@@ -14344,8 +14781,8 @@ function buildBrowserWebSocketUrl(httpUrl, webSocketPath) {
|
|
|
14344
14781
|
const protocol = httpUrl.protocol === "https:" ? "wss:" : "ws:";
|
|
14345
14782
|
return `${protocol}//${httpUrl.host}${normalizeWebSocketPath(webSocketPath)}`;
|
|
14346
14783
|
}
|
|
14347
|
-
function normalizeWebSocketPath(
|
|
14348
|
-
return
|
|
14784
|
+
function normalizeWebSocketPath(path15) {
|
|
14785
|
+
return path15.startsWith("/") ? path15 : `/${path15}`;
|
|
14349
14786
|
}
|
|
14350
14787
|
function rewriteBrowserWebSocketHost(browserWsUrl, requestedUrl) {
|
|
14351
14788
|
try {
|
|
@@ -14391,20 +14828,20 @@ var SESSION_SKIPPED_PROFILE_DIRECTORIES = /* @__PURE__ */ new Set([
|
|
|
14391
14828
|
"Network"
|
|
14392
14829
|
]);
|
|
14393
14830
|
async function createBrowserProfileSnapshot(input) {
|
|
14394
|
-
const sourceUserDataDir =
|
|
14395
|
-
const targetUserDataDir =
|
|
14831
|
+
const sourceUserDataDir = path7.resolve(expandHome(input.sourceUserDataDir));
|
|
14832
|
+
const targetUserDataDir = path7.resolve(expandHome(input.targetUserDataDir));
|
|
14396
14833
|
const profileDirectory = input.profileDirectory?.trim();
|
|
14397
14834
|
const copyMode = input.copyMode;
|
|
14398
14835
|
await promises.mkdir(targetUserDataDir, { recursive: true });
|
|
14399
14836
|
await clearChromeSingletonEntries(targetUserDataDir);
|
|
14400
14837
|
if (profileDirectory) {
|
|
14401
|
-
const sourceProfileDir =
|
|
14838
|
+
const sourceProfileDir = path7.join(sourceUserDataDir, profileDirectory);
|
|
14402
14839
|
if (!fs.existsSync(sourceProfileDir)) {
|
|
14403
14840
|
throw new Error(
|
|
14404
14841
|
`Chrome profile "${profileDirectory}" was not found in "${sourceUserDataDir}".`
|
|
14405
14842
|
);
|
|
14406
14843
|
}
|
|
14407
|
-
await promises.cp(sourceProfileDir,
|
|
14844
|
+
await promises.cp(sourceProfileDir, path7.join(targetUserDataDir, profileDirectory), {
|
|
14408
14845
|
recursive: true,
|
|
14409
14846
|
filter: (candidate) => shouldCopyEntry({
|
|
14410
14847
|
candidatePath: candidate,
|
|
@@ -14428,8 +14865,8 @@ async function copyRootLevelEntries(input) {
|
|
|
14428
14865
|
if (CHROME_SINGLETON_ENTRIES.has(entry) || entry === input.selectedProfileDirectory) {
|
|
14429
14866
|
continue;
|
|
14430
14867
|
}
|
|
14431
|
-
const sourcePath =
|
|
14432
|
-
const targetPath =
|
|
14868
|
+
const sourcePath = path7.join(input.sourceUserDataDir, entry);
|
|
14869
|
+
const targetPath = path7.join(input.targetUserDataDir, entry);
|
|
14433
14870
|
const entryStat = await promises.stat(sourcePath).catch(() => null);
|
|
14434
14871
|
if (!entryStat) {
|
|
14435
14872
|
continue;
|
|
@@ -14461,7 +14898,7 @@ async function copyRootLevelEntries(input) {
|
|
|
14461
14898
|
}
|
|
14462
14899
|
}
|
|
14463
14900
|
function isProfileDirectory(userDataDir, entry) {
|
|
14464
|
-
return fs.existsSync(
|
|
14901
|
+
return fs.existsSync(path7.join(userDataDir, entry, "Preferences"));
|
|
14465
14902
|
}
|
|
14466
14903
|
function shouldCopyEntry(input) {
|
|
14467
14904
|
const entryName = input.candidatePath.split("/").at(-1)?.split("\\").at(-1) ?? input.candidatePath;
|
|
@@ -14471,7 +14908,7 @@ function shouldCopyEntry(input) {
|
|
|
14471
14908
|
if (input.copyMode !== "session") {
|
|
14472
14909
|
return true;
|
|
14473
14910
|
}
|
|
14474
|
-
const relativePath =
|
|
14911
|
+
const relativePath = path7.relative(input.rootPath, input.candidatePath);
|
|
14475
14912
|
if (relativePath.length === 0) {
|
|
14476
14913
|
return true;
|
|
14477
14914
|
}
|
|
@@ -14953,7 +15390,7 @@ function pickStealthProfilePreset(overrides) {
|
|
|
14953
15390
|
var OPENSTEER_LIVE_SESSION_LAYOUT = "opensteer-session";
|
|
14954
15391
|
var OPENSTEER_LIVE_SESSION_VERSION = 1;
|
|
14955
15392
|
function resolveLiveSessionRecordPath(rootPath, provider) {
|
|
14956
|
-
return
|
|
15393
|
+
return path7__default.default.join(rootPath, "live", provider === "local" ? "local.json" : "cloud.json");
|
|
14957
15394
|
}
|
|
14958
15395
|
function resolveLocalSessionRecordPath(rootPath) {
|
|
14959
15396
|
return resolveLiveSessionRecordPath(rootPath, "local");
|
|
@@ -14990,7 +15427,7 @@ async function clearPersistedSessionRecord(rootPath, provider) {
|
|
|
14990
15427
|
await promises.rm(resolveLiveSessionRecordPath(rootPath, provider), { force: true });
|
|
14991
15428
|
}
|
|
14992
15429
|
function isPersistedCloudSessionRecord(value) {
|
|
14993
|
-
return value.layout === OPENSTEER_LIVE_SESSION_LAYOUT && value.version === OPENSTEER_LIVE_SESSION_VERSION && value.provider === "cloud" && typeof value.sessionId === "string" && value.sessionId.length > 0 && typeof value.
|
|
15430
|
+
return value.layout === OPENSTEER_LIVE_SESSION_LAYOUT && value.version === OPENSTEER_LIVE_SESSION_VERSION && value.provider === "cloud" && typeof value.sessionId === "string" && value.sessionId.length > 0 && typeof value.startedAt === "number" && Number.isFinite(value.startedAt) && typeof value.updatedAt === "number" && Number.isFinite(value.updatedAt);
|
|
14994
15431
|
}
|
|
14995
15432
|
function isPersistedLocalBrowserSessionRecord(value) {
|
|
14996
15433
|
return value.layout === OPENSTEER_LIVE_SESSION_LAYOUT && value.version === OPENSTEER_LIVE_SESSION_VERSION && value.provider === "local" && (value.engine === "playwright" || value.engine === "abp") && typeof value.pid === "number" && Number.isFinite(value.pid) && typeof value.startedAt === "number" && Number.isFinite(value.startedAt) && typeof value.updatedAt === "number" && Number.isFinite(value.updatedAt) && typeof value.userDataDir === "string" && value.userDataDir.length > 0;
|
|
@@ -15113,8 +15550,8 @@ var OpensteerBrowserManager = class {
|
|
|
15113
15550
|
...options.browser === void 0 ? {} : { browser: options.browser },
|
|
15114
15551
|
...this.contextOptions === void 0 ? {} : { context: this.contextOptions }
|
|
15115
15552
|
});
|
|
15116
|
-
this.rootPath = options.rootPath ?? (this.workspace === void 0 ?
|
|
15117
|
-
rootDir:
|
|
15553
|
+
this.rootPath = options.rootPath ?? (this.workspace === void 0 ? path7__default.default.join(os.tmpdir(), `${TEMPORARY_WORKSPACE_PREFIX}${crypto.randomUUID()}`) : resolveFilesystemWorkspacePath({
|
|
15554
|
+
rootDir: path7__default.default.resolve(options.rootDir ?? process.cwd()),
|
|
15118
15555
|
workspace: this.workspace
|
|
15119
15556
|
}));
|
|
15120
15557
|
this.cleanupRootOnDisconnect = this.workspace === void 0;
|
|
@@ -15184,7 +15621,7 @@ var OpensteerBrowserManager = class {
|
|
|
15184
15621
|
userDataDir: "browser/user-data",
|
|
15185
15622
|
bootstrap: {
|
|
15186
15623
|
kind: "cloneLocalProfile",
|
|
15187
|
-
sourceUserDataDir:
|
|
15624
|
+
sourceUserDataDir: path7__default.default.resolve(input.sourceUserDataDir),
|
|
15188
15625
|
...input.sourceProfileDirectory === void 0 ? {} : { sourceProfileDirectory: input.sourceProfileDirectory }
|
|
15189
15626
|
}
|
|
15190
15627
|
};
|
|
@@ -15311,7 +15748,7 @@ var OpensteerBrowserManager = class {
|
|
|
15311
15748
|
});
|
|
15312
15749
|
}
|
|
15313
15750
|
async createTemporaryEngine() {
|
|
15314
|
-
const userDataDir = await promises.mkdtemp(
|
|
15751
|
+
const userDataDir = await promises.mkdtemp(path7__default.default.join(os.tmpdir(), "opensteer-temporary-browser-"));
|
|
15315
15752
|
await clearChromeSingletonEntries(userDataDir);
|
|
15316
15753
|
const launched = await launchOwnedBrowser({
|
|
15317
15754
|
userDataDir,
|
|
@@ -15758,7 +16195,7 @@ async function terminateProcess(pid) {
|
|
|
15758
16195
|
}
|
|
15759
16196
|
}
|
|
15760
16197
|
async function requestBrowserClose(endpoint) {
|
|
15761
|
-
await new Promise((
|
|
16198
|
+
await new Promise((resolve4, reject) => {
|
|
15762
16199
|
const socket = new WebSocket(endpoint);
|
|
15763
16200
|
const timeout = setTimeout(() => {
|
|
15764
16201
|
socket.close();
|
|
@@ -15775,7 +16212,7 @@ async function requestBrowserClose(endpoint) {
|
|
|
15775
16212
|
reject(error);
|
|
15776
16213
|
return;
|
|
15777
16214
|
}
|
|
15778
|
-
|
|
16215
|
+
resolve4();
|
|
15779
16216
|
};
|
|
15780
16217
|
socket.addEventListener("open", () => {
|
|
15781
16218
|
socket.send(JSON.stringify({ id: 1, method: "Browser.close" }));
|
|
@@ -15813,7 +16250,7 @@ async function waitForProcessExit(pid, timeoutMs) {
|
|
|
15813
16250
|
return !isProcessRunning(pid);
|
|
15814
16251
|
}
|
|
15815
16252
|
function resolveAbpSessionDir(workspace) {
|
|
15816
|
-
return
|
|
16253
|
+
return path7__default.default.join(workspace.livePath, "abp-session");
|
|
15817
16254
|
}
|
|
15818
16255
|
async function allocateEphemeralPort() {
|
|
15819
16256
|
const { allocatePort } = await loadAbpModule();
|
|
@@ -15871,7 +16308,103 @@ function isStealthProfile(input) {
|
|
|
15871
16308
|
return input.id !== void 0 && input.platform !== void 0 && input.browserBrand !== void 0 && input.browserVersion !== void 0 && input.userAgent !== void 0 && input.viewport !== void 0 && input.screenResolution !== void 0 && input.devicePixelRatio !== void 0 && input.maxTouchPoints !== void 0 && input.webglVendor !== void 0 && input.webglRenderer !== void 0 && input.fonts !== void 0 && input.canvasNoiseSeed !== void 0 && input.audioNoiseSeed !== void 0 && input.locale !== void 0 && input.timezoneId !== void 0;
|
|
15872
16309
|
}
|
|
15873
16310
|
async function sleep(ms) {
|
|
15874
|
-
await new Promise((
|
|
16311
|
+
await new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
16312
|
+
}
|
|
16313
|
+
var ENV_FILENAMES = [".env", ".env.local"];
|
|
16314
|
+
var OPENSTEER_ENV_PREFIX = "OPENSTEER_";
|
|
16315
|
+
var opensteerEnvironmentCache = /* @__PURE__ */ new Map();
|
|
16316
|
+
function resolveOpensteerEnvironment(cwd = process.cwd(), baseEnv = process.env) {
|
|
16317
|
+
const resolvedCwd = path7__default.default.resolve(cwd);
|
|
16318
|
+
const signature = buildEnvironmentSignature(baseEnv, isOpensteerEnvironmentKey);
|
|
16319
|
+
const cached = opensteerEnvironmentCache.get(resolvedCwd);
|
|
16320
|
+
if (cached && cached.signature === signature) {
|
|
16321
|
+
return { ...cached.values };
|
|
16322
|
+
}
|
|
16323
|
+
const resolved = resolveEnvironmentFiles(resolvedCwd, baseEnv, isOpensteerEnvironmentKey);
|
|
16324
|
+
opensteerEnvironmentCache.set(resolvedCwd, {
|
|
16325
|
+
signature,
|
|
16326
|
+
values: { ...resolved }
|
|
16327
|
+
});
|
|
16328
|
+
return { ...resolved };
|
|
16329
|
+
}
|
|
16330
|
+
function collectDirectories(cwd) {
|
|
16331
|
+
const directories = [];
|
|
16332
|
+
let current = path7__default.default.resolve(cwd);
|
|
16333
|
+
for (; ; ) {
|
|
16334
|
+
directories.unshift(current);
|
|
16335
|
+
const parent = path7__default.default.dirname(current);
|
|
16336
|
+
if (parent === current) {
|
|
16337
|
+
return directories;
|
|
16338
|
+
}
|
|
16339
|
+
current = parent;
|
|
16340
|
+
}
|
|
16341
|
+
}
|
|
16342
|
+
function parseEnvFile(contents) {
|
|
16343
|
+
const parsed = {};
|
|
16344
|
+
for (const rawLine of contents.split(/\r?\n/u)) {
|
|
16345
|
+
const trimmed = rawLine.trim();
|
|
16346
|
+
if (!trimmed || trimmed.startsWith("#")) {
|
|
16347
|
+
continue;
|
|
16348
|
+
}
|
|
16349
|
+
const line = trimmed.startsWith("export ") ? trimmed.slice("export ".length) : trimmed;
|
|
16350
|
+
const separatorIndex = line.indexOf("=");
|
|
16351
|
+
if (separatorIndex <= 0) {
|
|
16352
|
+
continue;
|
|
16353
|
+
}
|
|
16354
|
+
const key = line.slice(0, separatorIndex).trim();
|
|
16355
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/u.test(key)) {
|
|
16356
|
+
continue;
|
|
16357
|
+
}
|
|
16358
|
+
const rawValue = line.slice(separatorIndex + 1).trim();
|
|
16359
|
+
parsed[key] = parseEnvValue(rawValue);
|
|
16360
|
+
}
|
|
16361
|
+
return parsed;
|
|
16362
|
+
}
|
|
16363
|
+
function parseEnvValue(rawValue) {
|
|
16364
|
+
if (rawValue.length >= 2 && rawValue.startsWith('"') && rawValue.endsWith('"')) {
|
|
16365
|
+
return rawValue.slice(1, -1).replace(/\\n/g, "\n").replace(/\\r/g, "\r").replace(/\\t/g, " ").replace(/\\"/g, '"');
|
|
16366
|
+
}
|
|
16367
|
+
if (rawValue.length >= 2 && rawValue.startsWith("'") && rawValue.endsWith("'")) {
|
|
16368
|
+
return rawValue.slice(1, -1);
|
|
16369
|
+
}
|
|
16370
|
+
return rawValue.replace(/\s+#.*$/u, "").trimEnd();
|
|
16371
|
+
}
|
|
16372
|
+
function resolveEnvironmentFiles(cwd, baseEnv, predicate) {
|
|
16373
|
+
const resolved = collectEnvironment(baseEnv, predicate);
|
|
16374
|
+
const protectedKeys = new Set(Object.keys(resolved));
|
|
16375
|
+
const directories = collectDirectories(cwd);
|
|
16376
|
+
for (const directory of directories) {
|
|
16377
|
+
for (const filename of ENV_FILENAMES) {
|
|
16378
|
+
const filePath = path7__default.default.join(directory, filename);
|
|
16379
|
+
if (!fs.existsSync(filePath)) {
|
|
16380
|
+
continue;
|
|
16381
|
+
}
|
|
16382
|
+
const parsed = parseEnvFile(fs.readFileSync(filePath, "utf8"));
|
|
16383
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
16384
|
+
if (predicate && !predicate(key) || protectedKeys.has(key)) {
|
|
16385
|
+
continue;
|
|
16386
|
+
}
|
|
16387
|
+
resolved[key] = value;
|
|
16388
|
+
}
|
|
16389
|
+
}
|
|
16390
|
+
}
|
|
16391
|
+
return resolved;
|
|
16392
|
+
}
|
|
16393
|
+
function collectEnvironment(baseEnv, predicate) {
|
|
16394
|
+
const resolved = {};
|
|
16395
|
+
for (const [key, value] of Object.entries(baseEnv)) {
|
|
16396
|
+
if (predicate && !predicate(key) || value === void 0) {
|
|
16397
|
+
continue;
|
|
16398
|
+
}
|
|
16399
|
+
resolved[key] = value;
|
|
16400
|
+
}
|
|
16401
|
+
return resolved;
|
|
16402
|
+
}
|
|
16403
|
+
function buildEnvironmentSignature(baseEnv, predicate) {
|
|
16404
|
+
return Object.entries(baseEnv).filter(([key, value]) => predicate(key) && value !== void 0).sort(([leftKey], [rightKey]) => leftKey.localeCompare(rightKey)).map(([key, value]) => `${key}=${value}`).join("\n");
|
|
16405
|
+
}
|
|
16406
|
+
function isOpensteerEnvironmentKey(key) {
|
|
16407
|
+
return key.startsWith(OPENSTEER_ENV_PREFIX);
|
|
15875
16408
|
}
|
|
15876
16409
|
|
|
15877
16410
|
// ../runtime-core/package.json
|
|
@@ -17485,7 +18018,7 @@ function diffStringMap(prefix, left, right, includeUnchanged, output) {
|
|
|
17485
18018
|
diffScalarField(`${prefix}.${key}`, left[key], right[key], includeUnchanged, output);
|
|
17486
18019
|
}
|
|
17487
18020
|
}
|
|
17488
|
-
function diffScalarField(
|
|
18021
|
+
function diffScalarField(path15, left, right, includeUnchanged, output) {
|
|
17489
18022
|
const leftValue = stringifyFieldValue(left);
|
|
17490
18023
|
const rightValue = stringifyFieldValue(right);
|
|
17491
18024
|
const kind = leftValue === void 0 ? rightValue === void 0 ? "unchanged" : "added" : rightValue === void 0 ? "removed" : leftValue === rightValue ? "unchanged" : "changed";
|
|
@@ -17493,7 +18026,7 @@ function diffScalarField(path13, left, right, includeUnchanged, output) {
|
|
|
17493
18026
|
return;
|
|
17494
18027
|
}
|
|
17495
18028
|
output.push({
|
|
17496
|
-
path:
|
|
18029
|
+
path: path15,
|
|
17497
18030
|
kind,
|
|
17498
18031
|
...leftValue === void 0 ? {} : { leftValue },
|
|
17499
18032
|
...rightValue === void 0 ? {} : { rightValue },
|
|
@@ -18499,9 +19032,9 @@ function matchReverseTargetHints(channel, codec, targetHints) {
|
|
|
18499
19032
|
matches.add(`host:${host}`);
|
|
18500
19033
|
}
|
|
18501
19034
|
}
|
|
18502
|
-
for (const
|
|
18503
|
-
if (url.pathname.includes(
|
|
18504
|
-
matches.add(`path:${
|
|
19035
|
+
for (const path15 of targetHints.paths ?? []) {
|
|
19036
|
+
if (url.pathname.includes(path15)) {
|
|
19037
|
+
matches.add(`path:${path15}`);
|
|
18505
19038
|
}
|
|
18506
19039
|
}
|
|
18507
19040
|
for (const operationName of targetHints.operationNames ?? []) {
|
|
@@ -19462,11 +19995,11 @@ function inferClusterRelationship(seed, record) {
|
|
|
19462
19995
|
var MATCHED_TLS_BINARY_NAMES = ["curl-impersonate-chrome", "curl_chrome"];
|
|
19463
19996
|
async function executeMatchedTlsTransportRequest(input) {
|
|
19464
19997
|
const binary = await resolveMatchedTlsBinary();
|
|
19465
|
-
const workingDirectory = await promises.mkdtemp(
|
|
19466
|
-
const headersPath =
|
|
19467
|
-
const bodyPath =
|
|
19468
|
-
const cookiesPath =
|
|
19469
|
-
const requestBodyPath =
|
|
19998
|
+
const workingDirectory = await promises.mkdtemp(path7__default.default.join(os.tmpdir(), "opensteer-matched-tls-"));
|
|
19999
|
+
const headersPath = path7__default.default.join(workingDirectory, "headers.txt");
|
|
20000
|
+
const bodyPath = path7__default.default.join(workingDirectory, "body.bin");
|
|
20001
|
+
const cookiesPath = path7__default.default.join(workingDirectory, "cookies.txt");
|
|
20002
|
+
const requestBodyPath = path7__default.default.join(workingDirectory, "request-body.bin");
|
|
19470
20003
|
try {
|
|
19471
20004
|
await promises.writeFile(cookiesPath, toNetscapeCookieJar(input.cookies ?? []), "utf8");
|
|
19472
20005
|
if (input.request.body !== void 0) {
|
|
@@ -19523,10 +20056,10 @@ async function executeMatchedTlsTransportRequest(input) {
|
|
|
19523
20056
|
}
|
|
19524
20057
|
}
|
|
19525
20058
|
async function resolveMatchedTlsBinary() {
|
|
19526
|
-
const pathEntries = (process.env.PATH ?? "").split(
|
|
20059
|
+
const pathEntries = (process.env.PATH ?? "").split(path7__default.default.delimiter).filter((entry) => entry.length > 0);
|
|
19527
20060
|
for (const directory of pathEntries) {
|
|
19528
20061
|
for (const name of MATCHED_TLS_BINARY_NAMES) {
|
|
19529
|
-
const candidate =
|
|
20062
|
+
const candidate = path7__default.default.join(directory, name);
|
|
19530
20063
|
if (await isExecutable(candidate)) {
|
|
19531
20064
|
return candidate;
|
|
19532
20065
|
}
|
|
@@ -19534,7 +20067,7 @@ async function resolveMatchedTlsBinary() {
|
|
|
19534
20067
|
const files = await readDirSafe(directory);
|
|
19535
20068
|
const discovered = files.find((file) => file.startsWith("curl_chrome"));
|
|
19536
20069
|
if (discovered !== void 0) {
|
|
19537
|
-
const candidate =
|
|
20070
|
+
const candidate = path7__default.default.join(directory, discovered);
|
|
19538
20071
|
if (await isExecutable(candidate)) {
|
|
19539
20072
|
return candidate;
|
|
19540
20073
|
}
|
|
@@ -19545,7 +20078,7 @@ async function resolveMatchedTlsBinary() {
|
|
|
19545
20078
|
);
|
|
19546
20079
|
}
|
|
19547
20080
|
async function spawnAndCollect(command, args, signal) {
|
|
19548
|
-
return await new Promise((
|
|
20081
|
+
return await new Promise((resolve4, reject) => {
|
|
19549
20082
|
const child = child_process.spawn(command, args, {
|
|
19550
20083
|
stdio: ["ignore", "pipe", "pipe"]
|
|
19551
20084
|
});
|
|
@@ -19578,7 +20111,7 @@ async function spawnAndCollect(command, args, signal) {
|
|
|
19578
20111
|
);
|
|
19579
20112
|
return;
|
|
19580
20113
|
}
|
|
19581
|
-
|
|
20114
|
+
resolve4({ stdout, stderr });
|
|
19582
20115
|
});
|
|
19583
20116
|
});
|
|
19584
20117
|
}
|
|
@@ -22240,8 +22773,8 @@ function readString(value) {
|
|
|
22240
22773
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
22241
22774
|
}
|
|
22242
22775
|
function sleep2(ms, signal) {
|
|
22243
|
-
return new Promise((
|
|
22244
|
-
const timeout = setTimeout(
|
|
22776
|
+
return new Promise((resolve4, reject) => {
|
|
22777
|
+
const timeout = setTimeout(resolve4, ms);
|
|
22245
22778
|
const abort = () => {
|
|
22246
22779
|
clearTimeout(timeout);
|
|
22247
22780
|
reject(new Error("captcha solve aborted"));
|
|
@@ -22338,8 +22871,8 @@ function readString2(value) {
|
|
|
22338
22871
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
22339
22872
|
}
|
|
22340
22873
|
function sleep3(ms, signal) {
|
|
22341
|
-
return new Promise((
|
|
22342
|
-
const timeout = setTimeout(
|
|
22874
|
+
return new Promise((resolve4, reject) => {
|
|
22875
|
+
const timeout = setTimeout(resolve4, ms);
|
|
22343
22876
|
const abort = () => {
|
|
22344
22877
|
clearTimeout(timeout);
|
|
22345
22878
|
reject(new Error("captcha solve aborted"));
|
|
@@ -22538,6 +23071,9 @@ function diffInteractionTraces(left, right) {
|
|
|
22538
23071
|
// ../runtime-core/src/sdk/runtime.ts
|
|
22539
23072
|
var requireForAuthRecipeHook = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
|
|
22540
23073
|
var MUTATION_CAPTURE_FINALIZE_TIMEOUT_MS = 5e3;
|
|
23074
|
+
var PERSISTED_NETWORK_FLUSH_TIMEOUT_MS = 5e3;
|
|
23075
|
+
var PENDING_OPERATION_EVENT_CAPTURE_LIMIT = 64;
|
|
23076
|
+
var PENDING_OPERATION_EVENT_CAPTURE_SKEW_MS = 1e3;
|
|
22541
23077
|
var OpensteerSessionRuntime = class {
|
|
22542
23078
|
workspace;
|
|
22543
23079
|
rootPath;
|
|
@@ -22550,6 +23086,9 @@ var OpensteerSessionRuntime = class {
|
|
|
22550
23086
|
registryOverrides;
|
|
22551
23087
|
cleanupRootOnClose;
|
|
22552
23088
|
sessionInfoBase;
|
|
23089
|
+
observationConfig;
|
|
23090
|
+
observationSessionId;
|
|
23091
|
+
injectedObservationSink;
|
|
22553
23092
|
root;
|
|
22554
23093
|
engine;
|
|
22555
23094
|
dom;
|
|
@@ -22559,6 +23098,9 @@ var OpensteerSessionRuntime = class {
|
|
|
22559
23098
|
sessionRef;
|
|
22560
23099
|
pageRef;
|
|
22561
23100
|
runId;
|
|
23101
|
+
observations;
|
|
23102
|
+
operationEventStorage = new async_hooks.AsyncLocalStorage();
|
|
23103
|
+
pendingOperationEventCaptures = [];
|
|
22562
23104
|
cookieJars = /* @__PURE__ */ new Map();
|
|
22563
23105
|
recipeCache = /* @__PURE__ */ new Map();
|
|
22564
23106
|
ownsEngine = false;
|
|
@@ -22566,7 +23108,7 @@ var OpensteerSessionRuntime = class {
|
|
|
22566
23108
|
this.workspace = normalizeNamespace2(options.name);
|
|
22567
23109
|
this.workspaceName = options.workspaceName?.trim() === void 0 || options.workspaceName?.trim().length === 0 ? void 0 : options.workspaceName.trim();
|
|
22568
23110
|
this.root = options.workspace;
|
|
22569
|
-
this.rootPath = options.workspace?.rootPath ?? options.rootPath ??
|
|
23111
|
+
this.rootPath = options.workspace?.rootPath ?? options.rootPath ?? path7__default.default.resolve(process.cwd(), ".opensteer", "temporary", crypto.randomUUID());
|
|
22570
23112
|
this.injectedEngine = options.engine;
|
|
22571
23113
|
this.engineFactory = options.engineFactory;
|
|
22572
23114
|
this.policy = options.policy ?? defaultPolicy();
|
|
@@ -22575,6 +23117,9 @@ var OpensteerSessionRuntime = class {
|
|
|
22575
23117
|
this.registryOverrides = options.registryOverrides;
|
|
22576
23118
|
this.cleanupRootOnClose = options.cleanupRootOnClose ?? options.workspace === void 0;
|
|
22577
23119
|
this.sessionInfoBase = options.sessionInfo ?? {};
|
|
23120
|
+
this.observationConfig = normalizeObservabilityConfig(options.observability);
|
|
23121
|
+
this.observationSessionId = options.observationSessionId;
|
|
23122
|
+
this.injectedObservationSink = options.observationSink;
|
|
22578
23123
|
if (this.injectedEngine === void 0 && this.engineFactory === void 0) {
|
|
22579
23124
|
throw new Error("OpensteerSessionRuntime requires an engine or engineFactory.");
|
|
22580
23125
|
}
|
|
@@ -22606,6 +23151,20 @@ var OpensteerSessionRuntime = class {
|
|
|
22606
23151
|
}
|
|
22607
23152
|
};
|
|
22608
23153
|
}
|
|
23154
|
+
async setObservabilityConfig(input) {
|
|
23155
|
+
this.observationConfig = normalizeObservabilityConfig(input);
|
|
23156
|
+
const observationSessionId = this.resolveObservationSessionId();
|
|
23157
|
+
if (observationSessionId === void 0) {
|
|
23158
|
+
return this.observationConfig;
|
|
23159
|
+
}
|
|
23160
|
+
const sink = this.injectedObservationSink ?? (await this.ensureRoot()).observations;
|
|
23161
|
+
this.observations = await sink.openSession({
|
|
23162
|
+
sessionId: observationSessionId,
|
|
23163
|
+
openedAt: Date.now(),
|
|
23164
|
+
config: this.observationConfig
|
|
23165
|
+
});
|
|
23166
|
+
return this.observationConfig;
|
|
23167
|
+
}
|
|
22609
23168
|
async open(input = {}, options = {}) {
|
|
22610
23169
|
assertValidSemanticOperationInput("session.open", input);
|
|
22611
23170
|
if (input.workspace !== void 0 && normalizeNamespace2(input.workspace) !== this.workspace) {
|
|
@@ -22704,6 +23263,10 @@ var OpensteerSessionRuntime = class {
|
|
|
22704
23263
|
return { pages: [] };
|
|
22705
23264
|
}
|
|
22706
23265
|
const startedAt = Date.now();
|
|
23266
|
+
const context = buildRuntimeTraceContext({
|
|
23267
|
+
sessionRef: this.sessionRef,
|
|
23268
|
+
pageRef: this.pageRef
|
|
23269
|
+
});
|
|
22707
23270
|
try {
|
|
22708
23271
|
const output = await this.runWithOperationTimeout(
|
|
22709
23272
|
"page.list",
|
|
@@ -22718,19 +23281,18 @@ var OpensteerSessionRuntime = class {
|
|
|
22718
23281
|
},
|
|
22719
23282
|
options
|
|
22720
23283
|
);
|
|
23284
|
+
const events = await this.drainPendingEngineEvents(context);
|
|
22721
23285
|
await this.appendTrace({
|
|
22722
23286
|
operation: "page.list",
|
|
22723
23287
|
startedAt,
|
|
22724
23288
|
completedAt: Date.now(),
|
|
22725
23289
|
outcome: "ok",
|
|
23290
|
+
...events === void 0 ? {} : { events },
|
|
22726
23291
|
data: {
|
|
22727
23292
|
count: output.pages.length,
|
|
22728
23293
|
...output.activePageRef === void 0 ? {} : { activePageRef: output.activePageRef }
|
|
22729
23294
|
},
|
|
22730
|
-
context
|
|
22731
|
-
sessionRef: this.sessionRef,
|
|
22732
|
-
pageRef: this.pageRef
|
|
22733
|
-
})
|
|
23295
|
+
context
|
|
22734
23296
|
});
|
|
22735
23297
|
return output;
|
|
22736
23298
|
} catch (error) {
|
|
@@ -22740,10 +23302,7 @@ var OpensteerSessionRuntime = class {
|
|
|
22740
23302
|
completedAt: Date.now(),
|
|
22741
23303
|
outcome: "error",
|
|
22742
23304
|
error,
|
|
22743
|
-
context
|
|
22744
|
-
sessionRef: this.sessionRef,
|
|
22745
|
-
pageRef: this.pageRef
|
|
22746
|
-
})
|
|
23305
|
+
context
|
|
22747
23306
|
});
|
|
22748
23307
|
throw error;
|
|
22749
23308
|
}
|
|
@@ -23131,22 +23690,25 @@ var OpensteerSessionRuntime = class {
|
|
|
23131
23690
|
},
|
|
23132
23691
|
options
|
|
23133
23692
|
);
|
|
23693
|
+
const context = buildRuntimeTraceContext({
|
|
23694
|
+
sessionRef: this.sessionRef,
|
|
23695
|
+
pageRef
|
|
23696
|
+
});
|
|
23697
|
+
const events = await this.drainPendingEngineEvents(context);
|
|
23134
23698
|
await this.appendTrace({
|
|
23135
23699
|
operation: "page.snapshot",
|
|
23136
23700
|
startedAt,
|
|
23137
23701
|
completedAt: Date.now(),
|
|
23138
23702
|
outcome: "ok",
|
|
23139
23703
|
artifacts,
|
|
23704
|
+
...events === void 0 ? {} : { events },
|
|
23140
23705
|
data: {
|
|
23141
23706
|
mode,
|
|
23142
23707
|
url: output.url,
|
|
23143
23708
|
title: output.title,
|
|
23144
23709
|
counterCount: output.counters.length
|
|
23145
23710
|
},
|
|
23146
|
-
context
|
|
23147
|
-
sessionRef: this.sessionRef,
|
|
23148
|
-
pageRef
|
|
23149
|
-
})
|
|
23711
|
+
context
|
|
23150
23712
|
});
|
|
23151
23713
|
return output;
|
|
23152
23714
|
} catch (error) {
|
|
@@ -26571,11 +27133,13 @@ var OpensteerSessionRuntime = class {
|
|
|
26571
27133
|
}
|
|
26572
27134
|
);
|
|
26573
27135
|
const output = toOpensteerActionResult(executed.result, preparedTarget.persistedDescription);
|
|
27136
|
+
const actionEvents = "events" in executed.result ? executed.result.events : void 0;
|
|
26574
27137
|
await this.appendTrace({
|
|
26575
27138
|
operation,
|
|
26576
27139
|
startedAt,
|
|
26577
27140
|
completedAt: Date.now(),
|
|
26578
27141
|
outcome: "ok",
|
|
27142
|
+
...actionEvents === void 0 ? {} : { events: actionEvents },
|
|
26579
27143
|
data: {
|
|
26580
27144
|
target: output.target,
|
|
26581
27145
|
...output.point === void 0 ? {} : { point: output.point },
|
|
@@ -28325,7 +28889,7 @@ var OpensteerSessionRuntime = class {
|
|
|
28325
28889
|
}
|
|
28326
28890
|
async executeAuthRecipeHook(step, variables) {
|
|
28327
28891
|
const resolved = requireForAuthRecipeHook.resolve(step.hook.specifier, {
|
|
28328
|
-
paths: [
|
|
28892
|
+
paths: [path7__default.default.dirname(this.rootPath)]
|
|
28329
28893
|
});
|
|
28330
28894
|
const module = await import(url.pathToFileURL(resolved).href);
|
|
28331
28895
|
const handler = module[step.hook.export];
|
|
@@ -28647,6 +29211,29 @@ var OpensteerSessionRuntime = class {
|
|
|
28647
29211
|
return snapshot.sessionStorage?.filter((entry) => entry.origin === origin).find((entry) => pageUrl === void 0 || entry.origin === new URL(pageUrl).origin)?.entries.find((entry) => entry.key === key)?.value;
|
|
28648
29212
|
}
|
|
28649
29213
|
async flushPersistedNetworkHistory() {
|
|
29214
|
+
if (this.sessionRef === void 0) {
|
|
29215
|
+
return;
|
|
29216
|
+
}
|
|
29217
|
+
const root = await this.ensureRoot();
|
|
29218
|
+
try {
|
|
29219
|
+
await withDetachedTimeoutSignal(PERSISTED_NETWORK_FLUSH_TIMEOUT_MS, async (signal) => {
|
|
29220
|
+
const browserRecords = await this.readBrowserNetworkRecords(
|
|
29221
|
+
{
|
|
29222
|
+
includeBodies: true,
|
|
29223
|
+
includeCurrentPageOnly: false
|
|
29224
|
+
},
|
|
29225
|
+
signal
|
|
29226
|
+
);
|
|
29227
|
+
await this.networkHistory.persist(browserRecords, root.registry.savedNetwork, {
|
|
29228
|
+
bodyWriteMode: "authoritative",
|
|
29229
|
+
redactSecretHeaders: false
|
|
29230
|
+
});
|
|
29231
|
+
});
|
|
29232
|
+
} catch (error) {
|
|
29233
|
+
if (!isIgnorableRuntimeBindingError(error)) {
|
|
29234
|
+
throw error;
|
|
29235
|
+
}
|
|
29236
|
+
}
|
|
28650
29237
|
}
|
|
28651
29238
|
toDomTargetRef(target) {
|
|
28652
29239
|
if (target.kind === "description") {
|
|
@@ -28697,14 +29284,18 @@ var OpensteerSessionRuntime = class {
|
|
|
28697
29284
|
return this.engine;
|
|
28698
29285
|
}
|
|
28699
29286
|
if (this.injectedEngine) {
|
|
28700
|
-
this.engine = this.
|
|
29287
|
+
this.engine = this.wrapEngineWithObservationCapture(
|
|
29288
|
+
this.injectedEngine
|
|
29289
|
+
);
|
|
28701
29290
|
this.ownsEngine = false;
|
|
28702
29291
|
return this.engine;
|
|
28703
29292
|
}
|
|
28704
29293
|
if (this.engineFactory === void 0) {
|
|
28705
29294
|
throw new Error("Opensteer engine factory is not initialized");
|
|
28706
29295
|
}
|
|
28707
|
-
this.engine =
|
|
29296
|
+
this.engine = this.wrapEngineWithObservationCapture(
|
|
29297
|
+
await this.engineFactory(overrides)
|
|
29298
|
+
);
|
|
28708
29299
|
this.ownsEngine = true;
|
|
28709
29300
|
return this.engine;
|
|
28710
29301
|
}
|
|
@@ -28799,6 +29390,12 @@ var OpensteerSessionRuntime = class {
|
|
|
28799
29390
|
return "live";
|
|
28800
29391
|
} catch (error) {
|
|
28801
29392
|
if (isIgnorableRuntimeBindingError(error)) {
|
|
29393
|
+
const remainingPages = await engine.listPages({ sessionRef }).catch(() => void 0);
|
|
29394
|
+
const replacementPageRef = remainingPages?.[0]?.pageRef;
|
|
29395
|
+
if (replacementPageRef !== void 0) {
|
|
29396
|
+
this.pageRef = replacementPageRef;
|
|
29397
|
+
return "live";
|
|
29398
|
+
}
|
|
28802
29399
|
return "invalid";
|
|
28803
29400
|
}
|
|
28804
29401
|
throw error;
|
|
@@ -28904,6 +29501,15 @@ var OpensteerSessionRuntime = class {
|
|
|
28904
29501
|
return;
|
|
28905
29502
|
}
|
|
28906
29503
|
const root = await this.ensureRoot();
|
|
29504
|
+
const capturedStepEvents = input.events ?? this.consumePendingOperationEventCapture(
|
|
29505
|
+
input.operation,
|
|
29506
|
+
input.startedAt,
|
|
29507
|
+
input.completedAt
|
|
29508
|
+
);
|
|
29509
|
+
const drainedStepEvents = input.events === void 0 ? await this.drainPendingEngineEvents(input.context) : void 0;
|
|
29510
|
+
const stepEvents = mergeObservedStepEvents(capturedStepEvents, drainedStepEvents);
|
|
29511
|
+
const normalizedData = input.data === void 0 ? void 0 : toCanonicalJsonValue(input.data);
|
|
29512
|
+
const normalizedError = input.error === void 0 ? void 0 : normalizeOpensteerError(input.error);
|
|
28907
29513
|
const artifacts = input.artifacts === void 0 ? void 0 : await Promise.all(
|
|
28908
29514
|
input.artifacts.manifests.map(async (manifest) => {
|
|
28909
29515
|
const reference = await root.artifacts.toProtocolArtifactReference(
|
|
@@ -28916,19 +29522,56 @@ var OpensteerSessionRuntime = class {
|
|
|
28916
29522
|
return reference;
|
|
28917
29523
|
})
|
|
28918
29524
|
);
|
|
28919
|
-
await root.traces.append(runId, {
|
|
29525
|
+
const traceEntry = await root.traces.append(runId, {
|
|
28920
29526
|
operation: input.operation,
|
|
28921
29527
|
outcome: input.outcome,
|
|
28922
29528
|
startedAt: input.startedAt,
|
|
28923
29529
|
completedAt: input.completedAt,
|
|
28924
29530
|
...input.context === void 0 ? {} : { context: input.context },
|
|
28925
|
-
...
|
|
29531
|
+
...stepEvents === void 0 ? {} : { events: stepEvents },
|
|
28926
29532
|
...artifacts === void 0 ? {} : { artifacts },
|
|
28927
|
-
...
|
|
28928
|
-
...
|
|
28929
|
-
error:
|
|
29533
|
+
...normalizedData === void 0 ? {} : { data: normalizedData },
|
|
29534
|
+
...normalizedError === void 0 ? {} : {
|
|
29535
|
+
error: normalizedError
|
|
28930
29536
|
}
|
|
28931
29537
|
});
|
|
29538
|
+
const observationSession = await this.ensureObservationSession().catch(() => void 0);
|
|
29539
|
+
if (observationSession === void 0 || this.observationConfig.profile === "off") {
|
|
29540
|
+
return;
|
|
29541
|
+
}
|
|
29542
|
+
const observationArtifactIds = input.artifacts === void 0 ? void 0 : (await Promise.allSettled(
|
|
29543
|
+
input.artifacts.manifests.map(async (manifest) => {
|
|
29544
|
+
const artifact = await observationSession.writeArtifact({
|
|
29545
|
+
artifactId: manifest.artifactId,
|
|
29546
|
+
kind: observationArtifactKindFromManifest(manifest.kind),
|
|
29547
|
+
createdAt: manifest.createdAt,
|
|
29548
|
+
context: manifest.scope,
|
|
29549
|
+
mediaType: manifest.mediaType,
|
|
29550
|
+
byteLength: manifest.byteLength,
|
|
29551
|
+
sha256: manifest.sha256,
|
|
29552
|
+
opensteerArtifactId: manifest.artifactId,
|
|
29553
|
+
storageKey: manifestToExternalBinaryLocation(root.rootPath, manifest).uri
|
|
29554
|
+
});
|
|
29555
|
+
return artifact.artifactId;
|
|
29556
|
+
})
|
|
29557
|
+
)).flatMap((result) => result.status === "fulfilled" ? [result.value] : []);
|
|
29558
|
+
const observationEvents = buildObservationEventsFromTrace({
|
|
29559
|
+
traceId: traceEntry.traceId,
|
|
29560
|
+
stepId: traceEntry.stepId,
|
|
29561
|
+
operation: input.operation,
|
|
29562
|
+
outcome: input.outcome,
|
|
29563
|
+
startedAt: input.startedAt,
|
|
29564
|
+
completedAt: input.completedAt,
|
|
29565
|
+
...input.context === void 0 ? {} : { context: input.context },
|
|
29566
|
+
...stepEvents === void 0 ? {} : { events: stepEvents },
|
|
29567
|
+
...normalizedData === void 0 ? {} : { data: normalizedData },
|
|
29568
|
+
...normalizedError === void 0 ? {} : { error: normalizedError },
|
|
29569
|
+
...observationArtifactIds === void 0 ? {} : { artifactIds: observationArtifactIds },
|
|
29570
|
+
profile: this.observationConfig.profile
|
|
29571
|
+
});
|
|
29572
|
+
if (observationEvents.length > 0) {
|
|
29573
|
+
await observationSession.appendBatch(observationEvents).catch(() => void 0);
|
|
29574
|
+
}
|
|
28932
29575
|
}
|
|
28933
29576
|
async cleanupSessionResources(engine, pageRef, sessionRef) {
|
|
28934
29577
|
if (pageRef !== void 0) {
|
|
@@ -28940,6 +29583,7 @@ var OpensteerSessionRuntime = class {
|
|
|
28940
29583
|
}
|
|
28941
29584
|
async resetRuntimeState(options) {
|
|
28942
29585
|
const engine = this.engine;
|
|
29586
|
+
const observations = this.observations;
|
|
28943
29587
|
this.networkHistory.clear();
|
|
28944
29588
|
this.sessionRef = void 0;
|
|
28945
29589
|
this.pageRef = void 0;
|
|
@@ -28948,20 +29592,140 @@ var OpensteerSessionRuntime = class {
|
|
|
28948
29592
|
this.computer = void 0;
|
|
28949
29593
|
this.extractionDescriptors = void 0;
|
|
28950
29594
|
this.engine = void 0;
|
|
29595
|
+
this.observations = void 0;
|
|
29596
|
+
this.pendingOperationEventCaptures.length = 0;
|
|
29597
|
+
await observations?.close("runtime_reset").catch(() => void 0);
|
|
28951
29598
|
if (options.disposeEngine && this.ownsEngine && engine?.dispose) {
|
|
28952
29599
|
await engine.dispose();
|
|
28953
29600
|
}
|
|
28954
29601
|
this.ownsEngine = false;
|
|
28955
29602
|
}
|
|
29603
|
+
async ensureObservationSession() {
|
|
29604
|
+
if (this.observationConfig.profile === "off") {
|
|
29605
|
+
return void 0;
|
|
29606
|
+
}
|
|
29607
|
+
if (this.observations !== void 0) {
|
|
29608
|
+
return this.observations;
|
|
29609
|
+
}
|
|
29610
|
+
const observationSessionId = this.resolveObservationSessionId();
|
|
29611
|
+
if (observationSessionId === void 0) {
|
|
29612
|
+
return void 0;
|
|
29613
|
+
}
|
|
29614
|
+
const sink = this.injectedObservationSink ?? (await this.ensureRoot()).observations;
|
|
29615
|
+
this.observations = await sink.openSession({
|
|
29616
|
+
sessionId: observationSessionId,
|
|
29617
|
+
openedAt: Date.now(),
|
|
29618
|
+
config: this.observationConfig
|
|
29619
|
+
});
|
|
29620
|
+
return this.observations;
|
|
29621
|
+
}
|
|
29622
|
+
resolveObservationSessionId() {
|
|
29623
|
+
return this.observationSessionId ?? this.sessionRef;
|
|
29624
|
+
}
|
|
28956
29625
|
runWithOperationTimeout(operation, callback, options = {}) {
|
|
28957
|
-
|
|
28958
|
-
|
|
28959
|
-
|
|
28960
|
-
|
|
28961
|
-
|
|
28962
|
-
|
|
28963
|
-
|
|
28964
|
-
|
|
29626
|
+
const existingCollector = this.operationEventStorage.getStore();
|
|
29627
|
+
if (existingCollector !== void 0) {
|
|
29628
|
+
return runWithPolicyTimeout(
|
|
29629
|
+
this.policy.timeout,
|
|
29630
|
+
{
|
|
29631
|
+
operation,
|
|
29632
|
+
...options.signal === void 0 ? {} : { signal: options.signal }
|
|
29633
|
+
},
|
|
29634
|
+
callback
|
|
29635
|
+
);
|
|
29636
|
+
}
|
|
29637
|
+
const collector = [];
|
|
29638
|
+
const startedAt = Date.now();
|
|
29639
|
+
return this.operationEventStorage.run(collector, async () => {
|
|
29640
|
+
try {
|
|
29641
|
+
return await runWithPolicyTimeout(
|
|
29642
|
+
this.policy.timeout,
|
|
29643
|
+
{
|
|
29644
|
+
operation,
|
|
29645
|
+
...options.signal === void 0 ? {} : { signal: options.signal }
|
|
29646
|
+
},
|
|
29647
|
+
callback
|
|
29648
|
+
);
|
|
29649
|
+
} finally {
|
|
29650
|
+
this.recordPendingOperationEventCapture({
|
|
29651
|
+
operation,
|
|
29652
|
+
startedAt,
|
|
29653
|
+
completedAt: Date.now(),
|
|
29654
|
+
events: collector
|
|
29655
|
+
});
|
|
29656
|
+
}
|
|
29657
|
+
});
|
|
29658
|
+
}
|
|
29659
|
+
wrapEngineWithObservationCapture(engine) {
|
|
29660
|
+
return new Proxy(engine, {
|
|
29661
|
+
get: (target, property, receiver) => {
|
|
29662
|
+
const value = Reflect.get(target, property, receiver);
|
|
29663
|
+
if (typeof value !== "function") {
|
|
29664
|
+
return value;
|
|
29665
|
+
}
|
|
29666
|
+
return (...args) => {
|
|
29667
|
+
const result = Reflect.apply(value, target, args);
|
|
29668
|
+
if (!(result instanceof Promise)) {
|
|
29669
|
+
return result;
|
|
29670
|
+
}
|
|
29671
|
+
return result.then((resolved) => {
|
|
29672
|
+
this.captureObservedStepEvents(resolved);
|
|
29673
|
+
return resolved;
|
|
29674
|
+
});
|
|
29675
|
+
};
|
|
29676
|
+
}
|
|
29677
|
+
});
|
|
29678
|
+
}
|
|
29679
|
+
captureObservedStepEvents(value) {
|
|
29680
|
+
const collector = this.operationEventStorage.getStore();
|
|
29681
|
+
if (collector === void 0) {
|
|
29682
|
+
return;
|
|
29683
|
+
}
|
|
29684
|
+
const events = readStepResultEvents(value);
|
|
29685
|
+
if (events === void 0 || events.length === 0) {
|
|
29686
|
+
return;
|
|
29687
|
+
}
|
|
29688
|
+
collector.push(...events);
|
|
29689
|
+
}
|
|
29690
|
+
recordPendingOperationEventCapture(capture) {
|
|
29691
|
+
if (capture.events.length === 0) {
|
|
29692
|
+
return;
|
|
29693
|
+
}
|
|
29694
|
+
this.pendingOperationEventCaptures.push({
|
|
29695
|
+
...capture,
|
|
29696
|
+
events: [...capture.events]
|
|
29697
|
+
});
|
|
29698
|
+
if (this.pendingOperationEventCaptures.length > PENDING_OPERATION_EVENT_CAPTURE_LIMIT) {
|
|
29699
|
+
this.pendingOperationEventCaptures.splice(
|
|
29700
|
+
0,
|
|
29701
|
+
this.pendingOperationEventCaptures.length - PENDING_OPERATION_EVENT_CAPTURE_LIMIT
|
|
29702
|
+
);
|
|
29703
|
+
}
|
|
29704
|
+
}
|
|
29705
|
+
consumePendingOperationEventCapture(operation, startedAt, completedAt) {
|
|
29706
|
+
for (let index = this.pendingOperationEventCaptures.length - 1; index >= 0; index -= 1) {
|
|
29707
|
+
const capture = this.pendingOperationEventCaptures[index];
|
|
29708
|
+
if (capture === void 0) {
|
|
29709
|
+
continue;
|
|
29710
|
+
}
|
|
29711
|
+
if (capture.operation !== operation) {
|
|
29712
|
+
continue;
|
|
29713
|
+
}
|
|
29714
|
+
if (capture.startedAt < startedAt - PENDING_OPERATION_EVENT_CAPTURE_SKEW_MS || capture.completedAt > completedAt + PENDING_OPERATION_EVENT_CAPTURE_SKEW_MS) {
|
|
29715
|
+
continue;
|
|
29716
|
+
}
|
|
29717
|
+
this.pendingOperationEventCaptures.splice(index, 1);
|
|
29718
|
+
return capture.events;
|
|
29719
|
+
}
|
|
29720
|
+
return void 0;
|
|
29721
|
+
}
|
|
29722
|
+
async drainPendingEngineEvents(context) {
|
|
29723
|
+
const pageRef = context?.pageRef ?? this.pageRef;
|
|
29724
|
+
if (pageRef === void 0 || this.engine === void 0) {
|
|
29725
|
+
return void 0;
|
|
29726
|
+
}
|
|
29727
|
+
const events = await this.engine.drainEvents({ pageRef }).catch(() => []);
|
|
29728
|
+
return events.length > 0 ? events : void 0;
|
|
28965
29729
|
}
|
|
28966
29730
|
async navigatePage(input, timeout) {
|
|
28967
29731
|
const remainingMs = timeout.remainingMs();
|
|
@@ -28997,6 +29761,34 @@ function buildRuntimeTraceContext(input) {
|
|
|
28997
29761
|
function buildArtifactScope(input) {
|
|
28998
29762
|
return buildRuntimeTraceContext(input);
|
|
28999
29763
|
}
|
|
29764
|
+
function readStepResultEvents(value) {
|
|
29765
|
+
if (value === null || typeof value !== "object") {
|
|
29766
|
+
return void 0;
|
|
29767
|
+
}
|
|
29768
|
+
if (!("events" in value)) {
|
|
29769
|
+
return void 0;
|
|
29770
|
+
}
|
|
29771
|
+
const events = value.events;
|
|
29772
|
+
return Array.isArray(events) ? events : void 0;
|
|
29773
|
+
}
|
|
29774
|
+
function mergeObservedStepEvents(primary, secondary) {
|
|
29775
|
+
if (primary === void 0 || primary.length === 0) {
|
|
29776
|
+
return secondary === void 0 || secondary.length === 0 ? void 0 : secondary;
|
|
29777
|
+
}
|
|
29778
|
+
if (secondary === void 0 || secondary.length === 0) {
|
|
29779
|
+
return primary;
|
|
29780
|
+
}
|
|
29781
|
+
const merged = /* @__PURE__ */ new Map();
|
|
29782
|
+
for (const event of primary) {
|
|
29783
|
+
merged.set(event.eventId, event);
|
|
29784
|
+
}
|
|
29785
|
+
for (const event of secondary) {
|
|
29786
|
+
merged.set(event.eventId, event);
|
|
29787
|
+
}
|
|
29788
|
+
return [...merged.values()].sort(
|
|
29789
|
+
(left, right) => (left.timestamp ?? 0) - (right.timestamp ?? 0)
|
|
29790
|
+
);
|
|
29791
|
+
}
|
|
29000
29792
|
function selectLiveQueryPageRef(input, currentPageRef) {
|
|
29001
29793
|
if (input.pageRef !== void 0) {
|
|
29002
29794
|
return input.pageRef;
|
|
@@ -29959,12 +30751,12 @@ function extractReverseRuntimeValue(value, pointer) {
|
|
|
29959
30751
|
}
|
|
29960
30752
|
return readDotPath(value, pointer);
|
|
29961
30753
|
}
|
|
29962
|
-
function readDotPath(value,
|
|
29963
|
-
if (
|
|
30754
|
+
function readDotPath(value, path15) {
|
|
30755
|
+
if (path15.length === 0) {
|
|
29964
30756
|
return value;
|
|
29965
30757
|
}
|
|
29966
30758
|
let current = value;
|
|
29967
|
-
for (const segment of
|
|
30759
|
+
for (const segment of path15.split(".").filter((entry) => entry.length > 0)) {
|
|
29968
30760
|
if (current === null || current === void 0) {
|
|
29969
30761
|
return void 0;
|
|
29970
30762
|
}
|
|
@@ -30333,7 +31125,7 @@ function normalizeRuntimeErrorMessage(error) {
|
|
|
30333
31125
|
return error instanceof Error ? error.message : String(error);
|
|
30334
31126
|
}
|
|
30335
31127
|
function runtimeDelay(ms) {
|
|
30336
|
-
return new Promise((
|
|
31128
|
+
return new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
30337
31129
|
}
|
|
30338
31130
|
function applyBrowserCookiesToTransportRequest(request, cookies) {
|
|
30339
31131
|
if (cookies.length === 0) {
|
|
@@ -30437,7 +31229,7 @@ function parseSetCookieHeader(value, requestUrl) {
|
|
|
30437
31229
|
}
|
|
30438
31230
|
const url = new URL(requestUrl);
|
|
30439
31231
|
let domain = url.hostname;
|
|
30440
|
-
let
|
|
31232
|
+
let path15 = defaultCookiePath(url.pathname);
|
|
30441
31233
|
let secure = url.protocol === "https:";
|
|
30442
31234
|
let expiresAt;
|
|
30443
31235
|
const cookieValue = rawValueParts.join("=").trim();
|
|
@@ -30450,7 +31242,7 @@ function parseSetCookieHeader(value, requestUrl) {
|
|
|
30450
31242
|
continue;
|
|
30451
31243
|
}
|
|
30452
31244
|
if (key === "path" && attributeValue.length > 0) {
|
|
30453
|
-
|
|
31245
|
+
path15 = attributeValue;
|
|
30454
31246
|
continue;
|
|
30455
31247
|
}
|
|
30456
31248
|
if (key === "secure") {
|
|
@@ -30476,7 +31268,7 @@ function parseSetCookieHeader(value, requestUrl) {
|
|
|
30476
31268
|
name,
|
|
30477
31269
|
value: cookieValue,
|
|
30478
31270
|
domain,
|
|
30479
|
-
path:
|
|
31271
|
+
path: path15,
|
|
30480
31272
|
secure,
|
|
30481
31273
|
...expiresAt === void 0 ? {} : { expiresAt }
|
|
30482
31274
|
}
|
|
@@ -31428,7 +32220,7 @@ async function pollUntilResult(timeout, producer) {
|
|
|
31428
32220
|
if (produced !== void 0) {
|
|
31429
32221
|
return produced;
|
|
31430
32222
|
}
|
|
31431
|
-
await new Promise((
|
|
32223
|
+
await new Promise((resolve4) => setTimeout(resolve4, 100));
|
|
31432
32224
|
}
|
|
31433
32225
|
}
|
|
31434
32226
|
async function getMainFrame(engine, pageRef) {
|
|
@@ -31486,6 +32278,133 @@ function toOpensteerResolvedTarget2(target) {
|
|
|
31486
32278
|
function normalizeOpensteerError(error) {
|
|
31487
32279
|
return normalizeThrownOpensteerError(error, "Unknown Opensteer runtime failure");
|
|
31488
32280
|
}
|
|
32281
|
+
function observationArtifactKindFromManifest(kind) {
|
|
32282
|
+
switch (kind) {
|
|
32283
|
+
case "screenshot":
|
|
32284
|
+
return "screenshot";
|
|
32285
|
+
case "dom-snapshot":
|
|
32286
|
+
return "dom-snapshot";
|
|
32287
|
+
case "html-snapshot":
|
|
32288
|
+
return "html-snapshot";
|
|
32289
|
+
default:
|
|
32290
|
+
return "other";
|
|
32291
|
+
}
|
|
32292
|
+
}
|
|
32293
|
+
function buildObservationEventsFromTrace(input) {
|
|
32294
|
+
const context = normalizeObservationContext(input.context);
|
|
32295
|
+
const baseCorrelationId = input.traceId;
|
|
32296
|
+
const startedEvent = {
|
|
32297
|
+
kind: input.operation === "session.open" || input.operation === "session.close" ? "session" : "operation",
|
|
32298
|
+
phase: "started",
|
|
32299
|
+
createdAt: input.startedAt,
|
|
32300
|
+
correlationId: baseCorrelationId,
|
|
32301
|
+
spanId: input.stepId,
|
|
32302
|
+
...context === void 0 ? {} : { context },
|
|
32303
|
+
data: {
|
|
32304
|
+
operation: input.operation
|
|
32305
|
+
}
|
|
32306
|
+
};
|
|
32307
|
+
const stepEvents = (input.events ?? []).filter((event) => shouldCaptureObservationStepEvent(event, input.profile)).map((event) => {
|
|
32308
|
+
const eventContext = buildObservationContextFromEvent(event);
|
|
32309
|
+
return {
|
|
32310
|
+
kind: observationKindForStepEvent(event),
|
|
32311
|
+
phase: "occurred",
|
|
32312
|
+
createdAt: event.timestamp,
|
|
32313
|
+
correlationId: baseCorrelationId,
|
|
32314
|
+
parentSpanId: input.stepId,
|
|
32315
|
+
...eventContext === void 0 ? {} : { context: eventContext },
|
|
32316
|
+
data: stripObservationStepEvent(event),
|
|
32317
|
+
...event.kind === "page-error" ? {
|
|
32318
|
+
error: {
|
|
32319
|
+
message: event.message,
|
|
32320
|
+
...event.stack === void 0 ? {} : { details: { stack: event.stack } }
|
|
32321
|
+
}
|
|
32322
|
+
} : {}
|
|
32323
|
+
};
|
|
32324
|
+
});
|
|
32325
|
+
const completedEvent = {
|
|
32326
|
+
kind: input.operation === "session.open" || input.operation === "session.close" ? "session" : "operation",
|
|
32327
|
+
phase: input.outcome === "ok" ? "completed" : "failed",
|
|
32328
|
+
createdAt: input.completedAt,
|
|
32329
|
+
correlationId: baseCorrelationId,
|
|
32330
|
+
spanId: input.stepId,
|
|
32331
|
+
...context === void 0 ? {} : { context },
|
|
32332
|
+
data: {
|
|
32333
|
+
operation: input.operation,
|
|
32334
|
+
startedAt: input.startedAt,
|
|
32335
|
+
completedAt: input.completedAt,
|
|
32336
|
+
durationMs: input.completedAt - input.startedAt,
|
|
32337
|
+
...input.data === void 0 ? {} : { output: input.data }
|
|
32338
|
+
},
|
|
32339
|
+
...input.error === void 0 ? {} : {
|
|
32340
|
+
error: {
|
|
32341
|
+
...input.error.code === void 0 ? {} : { code: input.error.code },
|
|
32342
|
+
message: input.error.message,
|
|
32343
|
+
...input.error.retriable === void 0 ? {} : { retriable: input.error.retriable },
|
|
32344
|
+
...input.error.details === void 0 ? {} : { details: toCanonicalJsonValue(input.error.details) }
|
|
32345
|
+
}
|
|
32346
|
+
},
|
|
32347
|
+
...input.artifactIds === void 0 || input.artifactIds.length === 0 ? {} : { artifactIds: input.artifactIds }
|
|
32348
|
+
};
|
|
32349
|
+
return [startedEvent, ...stepEvents, completedEvent];
|
|
32350
|
+
}
|
|
32351
|
+
function buildObservationContextFromEvent(event) {
|
|
32352
|
+
return normalizeObservationContext({
|
|
32353
|
+
sessionRef: event.sessionRef,
|
|
32354
|
+
...event.pageRef === void 0 ? {} : { pageRef: event.pageRef },
|
|
32355
|
+
...event.frameRef === void 0 ? {} : { frameRef: event.frameRef },
|
|
32356
|
+
...event.documentRef === void 0 ? {} : { documentRef: event.documentRef },
|
|
32357
|
+
...event.documentEpoch === void 0 ? {} : { documentEpoch: event.documentEpoch }
|
|
32358
|
+
});
|
|
32359
|
+
}
|
|
32360
|
+
function shouldCaptureObservationStepEvent(event, profile) {
|
|
32361
|
+
if (profile === "diagnostic") {
|
|
32362
|
+
return true;
|
|
32363
|
+
}
|
|
32364
|
+
switch (event.kind) {
|
|
32365
|
+
case "page-created":
|
|
32366
|
+
case "popup-opened":
|
|
32367
|
+
case "page-closed":
|
|
32368
|
+
case "page-error":
|
|
32369
|
+
return true;
|
|
32370
|
+
case "console":
|
|
32371
|
+
return event.level === "warn" || event.level === "error";
|
|
32372
|
+
default:
|
|
32373
|
+
return false;
|
|
32374
|
+
}
|
|
32375
|
+
}
|
|
32376
|
+
function observationKindForStepEvent(event) {
|
|
32377
|
+
switch (event.kind) {
|
|
32378
|
+
case "console":
|
|
32379
|
+
return "console";
|
|
32380
|
+
case "page-error":
|
|
32381
|
+
return "error";
|
|
32382
|
+
case "paused":
|
|
32383
|
+
case "resumed":
|
|
32384
|
+
case "frozen":
|
|
32385
|
+
return "runtime";
|
|
32386
|
+
default:
|
|
32387
|
+
return "page";
|
|
32388
|
+
}
|
|
32389
|
+
}
|
|
32390
|
+
function stripObservationStepEvent(event) {
|
|
32391
|
+
const {
|
|
32392
|
+
eventId: _eventId,
|
|
32393
|
+
kind,
|
|
32394
|
+
timestamp,
|
|
32395
|
+
sessionRef: _sessionRef,
|
|
32396
|
+
pageRef: _pageRef,
|
|
32397
|
+
frameRef: _frameRef,
|
|
32398
|
+
documentRef: _documentRef,
|
|
32399
|
+
documentEpoch: _documentEpoch,
|
|
32400
|
+
...rest
|
|
32401
|
+
} = event;
|
|
32402
|
+
return toCanonicalJsonValue({
|
|
32403
|
+
eventKind: kind,
|
|
32404
|
+
timestamp,
|
|
32405
|
+
...rest
|
|
32406
|
+
});
|
|
32407
|
+
}
|
|
31489
32408
|
function buildMutationCaptureTraceData(diagnostics) {
|
|
31490
32409
|
if (diagnostics?.finalizeError === void 0) {
|
|
31491
32410
|
return {};
|
|
@@ -31535,8 +32454,8 @@ function screenshotMediaType(format2) {
|
|
|
31535
32454
|
var OpensteerRuntime = class extends OpensteerSessionRuntime {
|
|
31536
32455
|
constructor(options = {}) {
|
|
31537
32456
|
const publicWorkspace = normalizeWorkspace2(options.workspace);
|
|
31538
|
-
const rootPath = options.rootPath ?? (publicWorkspace === void 0 ?
|
|
31539
|
-
rootDir:
|
|
32457
|
+
const rootPath = options.rootPath ?? (publicWorkspace === void 0 ? path7__default.default.resolve(options.rootDir ?? process.cwd(), ".opensteer", "temporary", crypto.randomUUID()) : resolveFilesystemWorkspacePath({
|
|
32458
|
+
rootDir: path7__default.default.resolve(options.rootDir ?? process.cwd()),
|
|
31540
32459
|
workspace: publicWorkspace
|
|
31541
32460
|
}));
|
|
31542
32461
|
const cleanupRootOnClose = options.cleanupRootOnClose ?? publicWorkspace === void 0;
|
|
@@ -31561,14 +32480,17 @@ var OpensteerRuntime = class extends OpensteerSessionRuntime {
|
|
|
31561
32480
|
...options.descriptorStore === void 0 ? {} : { descriptorStore: options.descriptorStore },
|
|
31562
32481
|
...options.extractionDescriptorStore === void 0 ? {} : { extractionDescriptorStore: options.extractionDescriptorStore },
|
|
31563
32482
|
...options.registryOverrides === void 0 ? {} : { registryOverrides: options.registryOverrides },
|
|
31564
|
-
cleanupRootOnClose
|
|
32483
|
+
cleanupRootOnClose,
|
|
32484
|
+
...options.observability === void 0 ? {} : { observability: options.observability },
|
|
32485
|
+
...options.observationSessionId === void 0 ? {} : { observationSessionId: options.observationSessionId },
|
|
32486
|
+
...options.observationSink === void 0 ? {} : { observationSink: options.observationSink }
|
|
31565
32487
|
})
|
|
31566
32488
|
);
|
|
31567
32489
|
}
|
|
31568
32490
|
};
|
|
31569
32491
|
var OpensteerSessionRuntime2 = class extends OpensteerSessionRuntime {
|
|
31570
32492
|
constructor(options) {
|
|
31571
|
-
const rootPath = options.rootPath ??
|
|
32493
|
+
const rootPath = options.rootPath ?? path7__default.default.resolve(options.rootDir ?? process.cwd());
|
|
31572
32494
|
const cleanupRootOnClose = options.cleanupRootOnClose ?? false;
|
|
31573
32495
|
const engineName = options.engineName ?? DEFAULT_OPENSTEER_ENGINE;
|
|
31574
32496
|
assertSupportedEngineOptions({
|
|
@@ -31590,7 +32512,10 @@ var OpensteerSessionRuntime2 = class extends OpensteerSessionRuntime {
|
|
|
31590
32512
|
...options.descriptorStore === void 0 ? {} : { descriptorStore: options.descriptorStore },
|
|
31591
32513
|
...options.extractionDescriptorStore === void 0 ? {} : { extractionDescriptorStore: options.extractionDescriptorStore },
|
|
31592
32514
|
...options.registryOverrides === void 0 ? {} : { registryOverrides: options.registryOverrides },
|
|
31593
|
-
cleanupRootOnClose
|
|
32515
|
+
cleanupRootOnClose,
|
|
32516
|
+
...options.observability === void 0 ? {} : { observability: options.observability },
|
|
32517
|
+
...options.observationSessionId === void 0 ? {} : { observationSessionId: options.observationSessionId },
|
|
32518
|
+
...options.observationSink === void 0 ? {} : { observationSink: options.observationSink }
|
|
31594
32519
|
})
|
|
31595
32520
|
);
|
|
31596
32521
|
}
|
|
@@ -31616,6 +32541,9 @@ function buildSharedRuntimeOptions(input) {
|
|
|
31616
32541
|
...input.extractionDescriptorStore === void 0 ? {} : { extractionDescriptorStore: input.extractionDescriptorStore },
|
|
31617
32542
|
...input.registryOverrides === void 0 ? {} : { registryOverrides: input.registryOverrides },
|
|
31618
32543
|
cleanupRootOnClose: input.cleanupRootOnClose,
|
|
32544
|
+
...input.observability === void 0 ? {} : { observability: input.observability },
|
|
32545
|
+
...input.observationSessionId === void 0 ? {} : { observationSessionId: input.observationSessionId },
|
|
32546
|
+
...input.observationSink === void 0 ? {} : { observationSink: input.observationSink },
|
|
31619
32547
|
sessionInfo: {
|
|
31620
32548
|
provider: {
|
|
31621
32549
|
mode: "local",
|
|
@@ -31678,345 +32606,281 @@ function resolveOpensteerProvider(input = {}) {
|
|
|
31678
32606
|
};
|
|
31679
32607
|
}
|
|
31680
32608
|
var execFile2 = util.promisify(child_process.execFile);
|
|
31681
|
-
var
|
|
31682
|
-
var
|
|
31683
|
-
var
|
|
31684
|
-
|
|
31685
|
-
async function resolveCookieCaptureStrategy(input = {}) {
|
|
31686
|
-
const timeoutMs = input.timeoutMs ?? DEFAULT_CAPTURE_TIMEOUT_MS;
|
|
31687
|
-
if (input.attachEndpoint !== void 0) {
|
|
31688
|
-
if (input.strategy !== void 0 && input.strategy !== "attach") {
|
|
31689
|
-
throw new Error(
|
|
31690
|
-
`Strategy "${input.strategy}" is incompatible with an explicit attach endpoint.`
|
|
31691
|
-
);
|
|
31692
|
-
}
|
|
31693
|
-
return {
|
|
31694
|
-
strategy: "attach",
|
|
31695
|
-
attachEndpoint: input.attachEndpoint,
|
|
31696
|
-
...input.profileDirectory === void 0 ? {} : { profileDirectory: input.profileDirectory },
|
|
31697
|
-
timeoutMs
|
|
31698
|
-
};
|
|
31699
|
-
}
|
|
32609
|
+
var NODE_SQLITE_SPECIFIER2 = `node:${"sqlite"}`;
|
|
32610
|
+
var CHROME_EPOCH_OFFSET = 11644473600000000n;
|
|
32611
|
+
var CHROME_HMAC_PREFIX_LENGTH = 32;
|
|
32612
|
+
async function readBrowserCookies(input = {}) {
|
|
31700
32613
|
const brand2 = resolveRequestedBrand(input);
|
|
31701
|
-
const executablePath = resolveBrandExecutablePath(brand2, input.executablePath);
|
|
31702
32614
|
const userDataDir = resolveBrandUserDataDir(brand2, input.userDataDir);
|
|
31703
|
-
const profileDirectory = input.profileDirectory;
|
|
31704
|
-
const
|
|
31705
|
-
|
|
31706
|
-
const autoStrategy = attachEndpoint !== void 0 ? "attach" : runningProcess !== null ? "managed-relaunch" : "headless";
|
|
31707
|
-
const strategy = input.strategy ?? autoStrategy;
|
|
31708
|
-
validateRequestedStrategy({
|
|
31709
|
-
strategy,
|
|
31710
|
-
brand: brand2,
|
|
31711
|
-
...attachEndpoint === void 0 ? {} : { attachEndpoint },
|
|
31712
|
-
...runningProcess?.pid === void 0 ? {} : { runningPid: runningProcess.pid }
|
|
31713
|
-
});
|
|
31714
|
-
return {
|
|
31715
|
-
strategy,
|
|
31716
|
-
brandId: brand2.id,
|
|
31717
|
-
brandDisplayName: brand2.displayName,
|
|
31718
|
-
executablePath,
|
|
31719
|
-
userDataDir,
|
|
31720
|
-
...profileDirectory === void 0 ? {} : { profileDirectory },
|
|
31721
|
-
...attachEndpoint === void 0 ? {} : { attachEndpoint },
|
|
31722
|
-
...runningProcess === null ? {} : { runningPid: runningProcess.pid },
|
|
31723
|
-
timeoutMs
|
|
31724
|
-
};
|
|
31725
|
-
}
|
|
31726
|
-
async function acquireCdpEndpoint(resolved) {
|
|
31727
|
-
if (resolved.strategy === "attach") {
|
|
31728
|
-
if (!resolved.attachEndpoint) {
|
|
31729
|
-
throw new Error("Attach capture requires a debuggable browser endpoint.");
|
|
31730
|
-
}
|
|
31731
|
-
const inspected = await inspectCdpEndpoint({
|
|
31732
|
-
endpoint: resolved.attachEndpoint,
|
|
31733
|
-
timeoutMs: Math.min(2e3, resolved.timeoutMs)
|
|
31734
|
-
});
|
|
31735
|
-
return {
|
|
31736
|
-
strategy: "attach",
|
|
31737
|
-
cdpEndpoint: inspected.endpoint,
|
|
31738
|
-
...resolved.brandId === void 0 ? {} : { brandId: resolved.brandId },
|
|
31739
|
-
...resolved.brandDisplayName === void 0 ? {} : { brandDisplayName: resolved.brandDisplayName },
|
|
31740
|
-
...resolved.userDataDir === void 0 ? {} : { userDataDir: resolved.userDataDir },
|
|
31741
|
-
...resolved.profileDirectory === void 0 ? {} : { profileDirectory: resolved.profileDirectory },
|
|
31742
|
-
cleanup: async () => void 0
|
|
31743
|
-
};
|
|
31744
|
-
}
|
|
31745
|
-
if (!resolved.brandId || !resolved.brandDisplayName || !resolved.executablePath || !resolved.userDataDir) {
|
|
32615
|
+
const profileDirectory = input.profileDirectory ?? "Default";
|
|
32616
|
+
const cookiesPath = path7.join(userDataDir, profileDirectory, "Cookies");
|
|
32617
|
+
if (!fs.existsSync(cookiesPath)) {
|
|
31746
32618
|
throw new Error(
|
|
31747
|
-
|
|
32619
|
+
`Cookies database not found at "${cookiesPath}". Verify the browser brand, user-data-dir, and profile-directory are correct.`
|
|
31748
32620
|
);
|
|
31749
32621
|
}
|
|
31750
|
-
const
|
|
31751
|
-
if (resolved.strategy === "managed-relaunch") {
|
|
31752
|
-
if (resolved.runningPid === void 0) {
|
|
31753
|
-
throw new Error("Managed relaunch requires a running browser process.");
|
|
31754
|
-
}
|
|
31755
|
-
await gracefullyStopBrowser(
|
|
31756
|
-
getBrowserBrand(resolved.brandId),
|
|
31757
|
-
resolved.runningPid,
|
|
31758
|
-
resolved.timeoutMs
|
|
31759
|
-
);
|
|
31760
|
-
}
|
|
31761
|
-
await clearChromeSingletonEntries(userDataDir);
|
|
32622
|
+
const tempDir = await promises.mkdtemp(path7.join(os.tmpdir(), "opensteer-cookies-"));
|
|
31762
32623
|
try {
|
|
31763
|
-
|
|
31764
|
-
|
|
31765
|
-
|
|
31766
|
-
|
|
31767
|
-
...resolved.profileDirectory === void 0 ? {} : { profileDirectory: resolved.profileDirectory },
|
|
31768
|
-
timeoutMs: resolved.timeoutMs
|
|
31769
|
-
});
|
|
32624
|
+
await copyCookiesDatabase(cookiesPath, tempDir);
|
|
32625
|
+
const decryptionKey = await resolveDecryptionKey(brand2.id, userDataDir);
|
|
32626
|
+
const rows = queryAllCookies(path7.join(tempDir, "Cookies"));
|
|
32627
|
+
const cookies = decryptCookieRows(rows, decryptionKey);
|
|
31770
32628
|
return {
|
|
31771
|
-
|
|
31772
|
-
|
|
31773
|
-
|
|
31774
|
-
|
|
31775
|
-
|
|
31776
|
-
...resolved.profileDirectory === void 0 ? {} : { profileDirectory: resolved.profileDirectory },
|
|
31777
|
-
cleanup: async () => {
|
|
31778
|
-
await capture.kill().catch(() => void 0);
|
|
31779
|
-
await clearChromeSingletonEntries(userDataDir).catch(() => void 0);
|
|
31780
|
-
}
|
|
31781
|
-
};
|
|
31782
|
-
} catch (error) {
|
|
31783
|
-
await clearChromeSingletonEntries(userDataDir).catch(() => void 0);
|
|
31784
|
-
throw error;
|
|
31785
|
-
}
|
|
31786
|
-
}
|
|
31787
|
-
async function gracefullyStopBrowser(brand2, pid, timeoutMs = DEFAULT_STOP_TIMEOUT_MS) {
|
|
31788
|
-
if (pid <= 0) {
|
|
31789
|
-
return;
|
|
31790
|
-
}
|
|
31791
|
-
const platformConfig = resolveBrandPlatformConfig(brand2);
|
|
31792
|
-
if (process.platform === "darwin" && platformConfig?.bundleId) {
|
|
31793
|
-
await execFile2(
|
|
31794
|
-
"osascript",
|
|
31795
|
-
["-e", `tell application id "${platformConfig.bundleId}" to quit`],
|
|
31796
|
-
{
|
|
31797
|
-
maxBuffer: PROCESS_LIST_MAX_BUFFER_BYTES3
|
|
31798
|
-
}
|
|
31799
|
-
).catch(() => void 0);
|
|
31800
|
-
} else if (process.platform === "win32") {
|
|
31801
|
-
await execFile2("taskkill", ["/PID", String(pid)], {
|
|
31802
|
-
maxBuffer: PROCESS_LIST_MAX_BUFFER_BYTES3
|
|
31803
|
-
}).catch(() => void 0);
|
|
31804
|
-
} else {
|
|
31805
|
-
try {
|
|
31806
|
-
process.kill(pid, "SIGTERM");
|
|
31807
|
-
} catch {
|
|
31808
|
-
}
|
|
31809
|
-
}
|
|
31810
|
-
if (await waitForProcessExit2(pid, timeoutMs)) {
|
|
31811
|
-
return;
|
|
31812
|
-
}
|
|
31813
|
-
if (process.platform === "win32") {
|
|
31814
|
-
await execFile2("taskkill", ["/F", "/PID", String(pid)], {
|
|
31815
|
-
maxBuffer: PROCESS_LIST_MAX_BUFFER_BYTES3
|
|
31816
|
-
}).catch(() => void 0);
|
|
31817
|
-
} else {
|
|
31818
|
-
try {
|
|
31819
|
-
process.kill(pid, "SIGKILL");
|
|
31820
|
-
} catch {
|
|
31821
|
-
}
|
|
31822
|
-
}
|
|
31823
|
-
await waitForProcessExit2(pid, Math.min(5e3, timeoutMs));
|
|
31824
|
-
}
|
|
31825
|
-
async function launchCaptureChrome(input) {
|
|
31826
|
-
const stderrLines = [];
|
|
31827
|
-
const child = child_process.spawn(input.executablePath, buildCaptureChromeArgs(input), {
|
|
31828
|
-
detached: process.platform !== "win32",
|
|
31829
|
-
stdio: ["ignore", "ignore", "pipe"]
|
|
31830
|
-
});
|
|
31831
|
-
child.unref();
|
|
31832
|
-
child.stderr?.setEncoding("utf8");
|
|
31833
|
-
child.stderr?.on("data", (chunk) => {
|
|
31834
|
-
stderrLines.push(String(chunk));
|
|
31835
|
-
});
|
|
31836
|
-
try {
|
|
31837
|
-
const endpoint = await waitForCaptureEndpoint({
|
|
31838
|
-
brandDisplayName: input.brandDisplayName,
|
|
31839
|
-
child,
|
|
31840
|
-
stderrLines,
|
|
31841
|
-
timeoutMs: input.timeoutMs,
|
|
31842
|
-
userDataDir: input.userDataDir
|
|
31843
|
-
});
|
|
31844
|
-
return {
|
|
31845
|
-
endpoint,
|
|
31846
|
-
kill: async () => {
|
|
31847
|
-
await terminateChild(child);
|
|
31848
|
-
}
|
|
32629
|
+
cookies,
|
|
32630
|
+
brandId: brand2.id,
|
|
32631
|
+
brandDisplayName: brand2.displayName,
|
|
32632
|
+
userDataDir,
|
|
32633
|
+
profileDirectory
|
|
31849
32634
|
};
|
|
31850
|
-
}
|
|
31851
|
-
await
|
|
31852
|
-
throw error;
|
|
32635
|
+
} finally {
|
|
32636
|
+
await promises.rm(tempDir, { recursive: true, force: true }).catch(() => void 0);
|
|
31853
32637
|
}
|
|
31854
32638
|
}
|
|
31855
|
-
function relaunchBrowserNormally(executablePath) {
|
|
31856
|
-
const child = child_process.spawn(executablePath, [], {
|
|
31857
|
-
detached: true,
|
|
31858
|
-
stdio: "ignore"
|
|
31859
|
-
});
|
|
31860
|
-
child.unref();
|
|
31861
|
-
}
|
|
31862
32639
|
function resolveRequestedBrand(input) {
|
|
31863
32640
|
if (input.brandId !== void 0) {
|
|
31864
32641
|
return getBrowserBrand(input.brandId);
|
|
31865
32642
|
}
|
|
31866
|
-
if (input.userDataDir !== void 0) {
|
|
31867
|
-
const inferred = inferBrandFromUserDataDir(input.userDataDir);
|
|
31868
|
-
if (!inferred) {
|
|
31869
|
-
throw new Error(
|
|
31870
|
-
`Could not infer a browser brand from user-data-dir "${input.userDataDir}". Pass --browser explicitly.`
|
|
31871
|
-
);
|
|
31872
|
-
}
|
|
31873
|
-
return inferred;
|
|
31874
|
-
}
|
|
31875
|
-
if (input.executablePath !== void 0) {
|
|
31876
|
-
const inferred = inferBrandFromExecutablePath(input.executablePath);
|
|
31877
|
-
if (!inferred) {
|
|
31878
|
-
throw new Error(
|
|
31879
|
-
`Could not infer a browser brand from executable path "${input.executablePath}". Pass --browser explicitly.`
|
|
31880
|
-
);
|
|
31881
|
-
}
|
|
31882
|
-
return inferred;
|
|
31883
|
-
}
|
|
31884
32643
|
const installed = detectInstalledBrowserBrands()[0];
|
|
31885
32644
|
if (!installed) {
|
|
31886
32645
|
throw new Error(
|
|
31887
|
-
"No Chromium browser found. Install a supported browser or pass
|
|
32646
|
+
"No Chromium browser found. Install a supported browser or pass brandId explicitly."
|
|
31888
32647
|
);
|
|
31889
32648
|
}
|
|
31890
32649
|
return installed.brand;
|
|
31891
32650
|
}
|
|
31892
|
-
async function
|
|
31893
|
-
|
|
31894
|
-
|
|
31895
|
-
|
|
32651
|
+
async function copyCookiesDatabase(cookiesPath, destDir) {
|
|
32652
|
+
await promises.copyFile(cookiesPath, path7.join(destDir, "Cookies"));
|
|
32653
|
+
for (const suffix of ["-wal", "-journal", "-shm"]) {
|
|
32654
|
+
const src = cookiesPath + suffix;
|
|
32655
|
+
if (fs.existsSync(src)) {
|
|
32656
|
+
await promises.copyFile(src, path7.join(destDir, "Cookies" + suffix)).catch(() => void 0);
|
|
32657
|
+
}
|
|
31896
32658
|
}
|
|
32659
|
+
}
|
|
32660
|
+
function queryAllCookies(dbPath) {
|
|
32661
|
+
let DatabaseSync;
|
|
31897
32662
|
try {
|
|
31898
|
-
|
|
31899
|
-
endpoint: `http://127.0.0.1:${String(activePort.port)}`,
|
|
31900
|
-
timeoutMs: Math.min(2e3, timeoutMs)
|
|
31901
|
-
})).endpoint;
|
|
32663
|
+
({ DatabaseSync } = __require(NODE_SQLITE_SPECIFIER2));
|
|
31902
32664
|
} catch {
|
|
31903
|
-
|
|
32665
|
+
throw new Error(
|
|
32666
|
+
"Reading browser cookies requires Node's built-in SQLite support. Use Node 22.5+ or a build with node:sqlite enabled."
|
|
32667
|
+
);
|
|
31904
32668
|
}
|
|
32669
|
+
const database = new DatabaseSync(dbPath, { readOnly: true });
|
|
32670
|
+
try {
|
|
32671
|
+
const stmt = database.prepare(
|
|
32672
|
+
`SELECT host_key, name, value, encrypted_value, path,
|
|
32673
|
+
expires_utc, is_secure, is_httponly, samesite, is_persistent
|
|
32674
|
+
FROM cookies`
|
|
32675
|
+
);
|
|
32676
|
+
stmt.setReadBigInts(true);
|
|
32677
|
+
return stmt.all().map(toRawCookieRow);
|
|
32678
|
+
} finally {
|
|
32679
|
+
database.close();
|
|
32680
|
+
}
|
|
32681
|
+
}
|
|
32682
|
+
function toRawCookieRow(row) {
|
|
32683
|
+
return {
|
|
32684
|
+
host_key: row.host_key,
|
|
32685
|
+
name: row.name,
|
|
32686
|
+
value: row.value,
|
|
32687
|
+
encrypted_value: row.encrypted_value,
|
|
32688
|
+
path: row.path,
|
|
32689
|
+
expires_utc: row.expires_utc,
|
|
32690
|
+
is_secure: row.is_secure,
|
|
32691
|
+
is_httponly: row.is_httponly,
|
|
32692
|
+
samesite: row.samesite,
|
|
32693
|
+
is_persistent: row.is_persistent
|
|
32694
|
+
};
|
|
31905
32695
|
}
|
|
31906
|
-
function
|
|
31907
|
-
if (
|
|
32696
|
+
async function resolveDecryptionKey(brandId, userDataDir) {
|
|
32697
|
+
if (process.platform === "darwin") {
|
|
32698
|
+
const password = await resolveKeychainPassword(brandId);
|
|
32699
|
+
const key = crypto.pbkdf2Sync(password, "saltysalt", 1003, 16, "sha1");
|
|
32700
|
+
return { platform: "darwin", key, algorithm: "aes-128-cbc" };
|
|
32701
|
+
}
|
|
32702
|
+
if (process.platform === "linux") {
|
|
32703
|
+
const key = crypto.pbkdf2Sync("peanuts", "saltysalt", 1, 16, "sha1");
|
|
32704
|
+
return { platform: "linux", key, algorithm: "aes-128-cbc" };
|
|
32705
|
+
}
|
|
32706
|
+
if (process.platform === "win32") {
|
|
32707
|
+
const key = await resolveWindowsMasterKey(userDataDir);
|
|
32708
|
+
return { platform: "win32", key, algorithm: "aes-256-gcm" };
|
|
32709
|
+
}
|
|
32710
|
+
throw new Error(`Unsupported platform "${process.platform}" for cookie decryption.`);
|
|
32711
|
+
}
|
|
32712
|
+
var BRAND_KEYCHAIN_SERVICE = {
|
|
32713
|
+
chrome: "Chrome Safe Storage",
|
|
32714
|
+
"chrome-canary": "Chrome Safe Storage",
|
|
32715
|
+
chromium: "Chromium Safe Storage",
|
|
32716
|
+
brave: "Brave Safe Storage",
|
|
32717
|
+
edge: "Microsoft Edge Safe Storage",
|
|
32718
|
+
vivaldi: "Chrome Safe Storage",
|
|
32719
|
+
helium: "Chrome Safe Storage"
|
|
32720
|
+
};
|
|
32721
|
+
async function resolveKeychainPassword(brandId) {
|
|
32722
|
+
const service = BRAND_KEYCHAIN_SERVICE[brandId];
|
|
32723
|
+
try {
|
|
32724
|
+
const { stdout } = await execFile2("security", [
|
|
32725
|
+
"find-generic-password",
|
|
32726
|
+
"-s",
|
|
32727
|
+
service,
|
|
32728
|
+
"-w"
|
|
32729
|
+
]);
|
|
32730
|
+
return stdout.trim();
|
|
32731
|
+
} catch {
|
|
31908
32732
|
throw new Error(
|
|
31909
|
-
|
|
32733
|
+
`Failed to retrieve "${service}" from macOS Keychain. Ensure the browser has been opened at least once and Keychain access is allowed.`
|
|
31910
32734
|
);
|
|
31911
32735
|
}
|
|
31912
|
-
|
|
32736
|
+
}
|
|
32737
|
+
async function resolveWindowsMasterKey(userDataDir) {
|
|
32738
|
+
const localStatePath = path7.join(userDataDir, "Local State");
|
|
32739
|
+
let localState;
|
|
32740
|
+
try {
|
|
32741
|
+
localState = JSON.parse(await promises.readFile(localStatePath, "utf8"));
|
|
32742
|
+
} catch {
|
|
31913
32743
|
throw new Error(
|
|
31914
|
-
|
|
32744
|
+
`Failed to read "${localStatePath}". Ensure the browser has been opened at least once.`
|
|
31915
32745
|
);
|
|
31916
32746
|
}
|
|
31917
|
-
|
|
32747
|
+
const encodedKey = localState.os_crypt?.encrypted_key;
|
|
32748
|
+
if (!encodedKey) {
|
|
32749
|
+
throw new Error(`No encrypted key found in "${localStatePath}".`);
|
|
32750
|
+
}
|
|
32751
|
+
const rawKey = Buffer.from(encodedKey, "base64").subarray(5);
|
|
32752
|
+
const psScript = `
|
|
32753
|
+
Add-Type -AssemblyName System.Security
|
|
32754
|
+
$bytes = [byte[]]@(${Array.from(rawKey).join(",")})
|
|
32755
|
+
$decrypted = [System.Security.Cryptography.ProtectedData]::Unprotect($bytes, $null, 'CurrentUser')
|
|
32756
|
+
[Convert]::ToBase64String($decrypted)
|
|
32757
|
+
`;
|
|
32758
|
+
try {
|
|
32759
|
+
const { stdout } = await execFile2("powershell", [
|
|
32760
|
+
"-NoProfile",
|
|
32761
|
+
"-NonInteractive",
|
|
32762
|
+
"-Command",
|
|
32763
|
+
psScript
|
|
32764
|
+
]);
|
|
32765
|
+
return Buffer.from(stdout.trim(), "base64");
|
|
32766
|
+
} catch {
|
|
31918
32767
|
throw new Error(
|
|
31919
|
-
|
|
32768
|
+
"Failed to decrypt browser master key via Windows DPAPI. Ensure you are running as the same user who owns the browser profile."
|
|
31920
32769
|
);
|
|
31921
32770
|
}
|
|
31922
32771
|
}
|
|
31923
|
-
function
|
|
31924
|
-
const
|
|
31925
|
-
|
|
31926
|
-
|
|
31927
|
-
|
|
31928
|
-
|
|
32772
|
+
function decryptCookieRows(rows, decryptionKey) {
|
|
32773
|
+
const cookies = [];
|
|
32774
|
+
const nowSeconds = Math.floor(Date.now() / 1e3);
|
|
32775
|
+
for (const row of rows) {
|
|
32776
|
+
const name = row.name.trim();
|
|
32777
|
+
const domain = row.host_key.trim();
|
|
32778
|
+
if (!name || !domain) {
|
|
32779
|
+
continue;
|
|
31929
32780
|
}
|
|
31930
|
-
const
|
|
31931
|
-
|
|
31932
|
-
|
|
31933
|
-
}
|
|
31934
|
-
function inferBrandFromExecutablePath(executablePath) {
|
|
31935
|
-
const normalized = normalizePath(executablePath);
|
|
31936
|
-
return getAllBrowserBrands().find((brand2) => {
|
|
31937
|
-
const config = resolveBrandPlatformConfig(brand2);
|
|
31938
|
-
if (!config) {
|
|
31939
|
-
return false;
|
|
32781
|
+
const value = decryptCookieValue(row, decryptionKey);
|
|
32782
|
+
if (value === null) {
|
|
32783
|
+
continue;
|
|
31940
32784
|
}
|
|
31941
|
-
|
|
31942
|
-
|
|
31943
|
-
)
|
|
31944
|
-
|
|
31945
|
-
}
|
|
31946
|
-
function buildCaptureChromeArgs(input) {
|
|
31947
|
-
const args = [
|
|
31948
|
-
"--remote-debugging-port=0",
|
|
31949
|
-
"--headless=new",
|
|
31950
|
-
"--no-first-run",
|
|
31951
|
-
"--no-default-browser-check",
|
|
31952
|
-
"--disable-background-networking",
|
|
31953
|
-
"--disable-sync",
|
|
31954
|
-
"--disable-component-update",
|
|
31955
|
-
`--user-data-dir=${input.userDataDir}`
|
|
31956
|
-
];
|
|
31957
|
-
if (input.profileDirectory !== void 0) {
|
|
31958
|
-
args.push(`--profile-directory=${input.profileDirectory}`);
|
|
31959
|
-
}
|
|
31960
|
-
return args;
|
|
31961
|
-
}
|
|
31962
|
-
async function waitForCaptureEndpoint(input) {
|
|
31963
|
-
const deadline = Date.now() + input.timeoutMs;
|
|
31964
|
-
while (Date.now() < deadline) {
|
|
31965
|
-
const activePort = readDevToolsActivePort(input.userDataDir);
|
|
31966
|
-
if (activePort) {
|
|
31967
|
-
try {
|
|
31968
|
-
return (await inspectCdpEndpoint({
|
|
31969
|
-
endpoint: `http://127.0.0.1:${String(activePort.port)}`,
|
|
31970
|
-
timeoutMs: Math.min(2e3, input.timeoutMs)
|
|
31971
|
-
})).endpoint;
|
|
31972
|
-
} catch {
|
|
31973
|
-
return `ws://127.0.0.1:${String(activePort.port)}${activePort.webSocketPath}`;
|
|
31974
|
-
}
|
|
32785
|
+
const expiresSeconds = chromeDateToUnixSeconds(row.expires_utc);
|
|
32786
|
+
const isSession = expiresSeconds <= 0;
|
|
32787
|
+
if (!isSession && expiresSeconds < nowSeconds) {
|
|
32788
|
+
continue;
|
|
31975
32789
|
}
|
|
31976
|
-
|
|
31977
|
-
|
|
32790
|
+
const sameSite = chromeSameSiteToString(row.samesite);
|
|
32791
|
+
let secure = Number(row.is_secure) === 1;
|
|
32792
|
+
if (sameSite === "None") {
|
|
32793
|
+
secure = true;
|
|
31978
32794
|
}
|
|
31979
|
-
|
|
32795
|
+
cookies.push({
|
|
32796
|
+
name,
|
|
32797
|
+
value,
|
|
32798
|
+
domain,
|
|
32799
|
+
path: row.path || "/",
|
|
32800
|
+
secure,
|
|
32801
|
+
httpOnly: Number(row.is_httponly) === 1,
|
|
32802
|
+
...isSession ? {} : { expires: expiresSeconds },
|
|
32803
|
+
...sameSite !== void 0 ? { sameSite } : {}
|
|
32804
|
+
});
|
|
31980
32805
|
}
|
|
31981
|
-
|
|
32806
|
+
return cookies;
|
|
31982
32807
|
}
|
|
31983
|
-
function
|
|
31984
|
-
|
|
31985
|
-
|
|
31986
|
-
return `${brandDisplayName} failed to launch before exposing a DevTools endpoint.`;
|
|
32808
|
+
function decryptCookieValue(row, decryptionKey) {
|
|
32809
|
+
if (row.value && row.value.length > 0) {
|
|
32810
|
+
return row.value;
|
|
31987
32811
|
}
|
|
31988
|
-
const
|
|
31989
|
-
|
|
31990
|
-
|
|
31991
|
-
|
|
31992
|
-
|
|
32812
|
+
const encrypted = Buffer.isBuffer(row.encrypted_value) ? row.encrypted_value : Buffer.from(row.encrypted_value);
|
|
32813
|
+
if (encrypted.length === 0) {
|
|
32814
|
+
return "";
|
|
32815
|
+
}
|
|
32816
|
+
const prefix = encrypted.subarray(0, 3).toString("ascii");
|
|
32817
|
+
if (prefix !== "v10" && prefix !== "v11") {
|
|
32818
|
+
return encrypted.toString("utf8");
|
|
32819
|
+
}
|
|
32820
|
+
const ciphertext = encrypted.subarray(3);
|
|
32821
|
+
if (decryptionKey.algorithm === "aes-128-cbc") {
|
|
32822
|
+
return decryptAes128Cbc(ciphertext, decryptionKey.key);
|
|
32823
|
+
}
|
|
32824
|
+
if (decryptionKey.algorithm === "aes-256-gcm") {
|
|
32825
|
+
return decryptAes256Gcm(ciphertext, decryptionKey.key);
|
|
32826
|
+
}
|
|
32827
|
+
return null;
|
|
31993
32828
|
}
|
|
31994
|
-
|
|
31995
|
-
|
|
31996
|
-
|
|
32829
|
+
function decryptAes128Cbc(ciphertext, key) {
|
|
32830
|
+
try {
|
|
32831
|
+
const iv = Buffer.alloc(16, 32);
|
|
32832
|
+
const decipher = crypto.createDecipheriv("aes-128-cbc", key, iv);
|
|
32833
|
+
let decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
|
|
32834
|
+
if (decrypted.length > CHROME_HMAC_PREFIX_LENGTH && containsNonPrintableAscii(decrypted, CHROME_HMAC_PREFIX_LENGTH)) {
|
|
32835
|
+
decrypted = decrypted.subarray(CHROME_HMAC_PREFIX_LENGTH);
|
|
32836
|
+
}
|
|
32837
|
+
if (containsNonPrintableAscii(decrypted, decrypted.length)) {
|
|
32838
|
+
return null;
|
|
32839
|
+
}
|
|
32840
|
+
return decrypted.toString("utf8");
|
|
32841
|
+
} catch {
|
|
32842
|
+
return null;
|
|
31997
32843
|
}
|
|
32844
|
+
}
|
|
32845
|
+
function decryptAes256Gcm(ciphertext, key) {
|
|
31998
32846
|
try {
|
|
31999
|
-
|
|
32847
|
+
const nonce = ciphertext.subarray(0, 12);
|
|
32848
|
+
const authTag = ciphertext.subarray(ciphertext.length - 16);
|
|
32849
|
+
const encrypted = ciphertext.subarray(12, ciphertext.length - 16);
|
|
32850
|
+
const decipher = crypto.createDecipheriv("aes-256-gcm", key, nonce);
|
|
32851
|
+
decipher.setAuthTag(authTag);
|
|
32852
|
+
const decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]);
|
|
32853
|
+
if (containsNonPrintableAscii(decrypted, decrypted.length)) {
|
|
32854
|
+
return null;
|
|
32855
|
+
}
|
|
32856
|
+
return decrypted.toString("utf8");
|
|
32000
32857
|
} catch {
|
|
32001
|
-
return;
|
|
32858
|
+
return null;
|
|
32002
32859
|
}
|
|
32003
|
-
await sleep4(50);
|
|
32004
32860
|
}
|
|
32005
|
-
|
|
32006
|
-
const
|
|
32007
|
-
|
|
32008
|
-
|
|
32861
|
+
function containsNonPrintableAscii(buffer, length) {
|
|
32862
|
+
const end = Math.min(length, buffer.length);
|
|
32863
|
+
for (let i = 0; i < end; i++) {
|
|
32864
|
+
const byte = buffer[i];
|
|
32865
|
+
if (byte < 32 || byte > 126) {
|
|
32009
32866
|
return true;
|
|
32010
32867
|
}
|
|
32011
|
-
await sleep4(50);
|
|
32012
32868
|
}
|
|
32013
|
-
return
|
|
32869
|
+
return false;
|
|
32014
32870
|
}
|
|
32015
|
-
function
|
|
32016
|
-
|
|
32871
|
+
function chromeDateToUnixSeconds(chromeTimestamp) {
|
|
32872
|
+
const ts = BigInt(chromeTimestamp);
|
|
32873
|
+
if (ts <= 0n) {
|
|
32874
|
+
return -1;
|
|
32875
|
+
}
|
|
32876
|
+
return Number((ts - CHROME_EPOCH_OFFSET) / 1000000n);
|
|
32017
32877
|
}
|
|
32018
|
-
|
|
32019
|
-
|
|
32878
|
+
function chromeSameSiteToString(value) {
|
|
32879
|
+
const v = Number(value);
|
|
32880
|
+
if (v === 0) return "None";
|
|
32881
|
+
if (v === 1) return "Lax";
|
|
32882
|
+
if (v === 2) return "Strict";
|
|
32883
|
+
return void 0;
|
|
32020
32884
|
}
|
|
32021
32885
|
|
|
32022
32886
|
// src/cloud/cookie-sync.ts
|
|
@@ -32072,14 +32936,14 @@ function toPortableBrowserProfileCookieRecord(cookie) {
|
|
|
32072
32936
|
if (!name || !domain) {
|
|
32073
32937
|
return null;
|
|
32074
32938
|
}
|
|
32075
|
-
const
|
|
32939
|
+
const path15 = typeof cookie.path === "string" && cookie.path.trim().length > 0 ? cookie.path : "/";
|
|
32076
32940
|
const expiresAt = typeof cookie.expires === "number" && Number.isFinite(cookie.expires) && cookie.expires > 0 ? Math.floor(cookie.expires * 1e3) : null;
|
|
32077
32941
|
const sameSite = normalizeSameSite(cookie.sameSite);
|
|
32078
32942
|
return {
|
|
32079
32943
|
name,
|
|
32080
32944
|
value: cookie.value,
|
|
32081
32945
|
domain,
|
|
32082
|
-
path:
|
|
32946
|
+
path: path15,
|
|
32083
32947
|
secure: cookie.secure,
|
|
32084
32948
|
httpOnly: cookie.httpOnly,
|
|
32085
32949
|
...sameSite === void 0 ? {} : { sameSite },
|
|
@@ -32095,114 +32959,48 @@ function normalizeSameSite(value) {
|
|
|
32095
32959
|
return void 0;
|
|
32096
32960
|
}
|
|
32097
32961
|
|
|
32098
|
-
// src/cloud/portable-cookie-snapshot.ts
|
|
32099
|
-
var gzip = util.promisify(zlib.gzip);
|
|
32100
|
-
async function capturePortableBrowserProfileSnapshot(input = {}) {
|
|
32101
|
-
const attached = input.attachEndpoint ? await inspectCdpEndpoint({
|
|
32102
|
-
endpoint: input.attachEndpoint,
|
|
32103
|
-
...input.timeoutMs === void 0 ? {} : { timeoutMs: input.timeoutMs }
|
|
32104
|
-
}) : await selectAttachBrowserCandidate({
|
|
32105
|
-
...input.timeoutMs === void 0 ? {} : { timeoutMs: input.timeoutMs }
|
|
32106
|
-
});
|
|
32107
|
-
const browser = await enginePlaywright.connectPlaywrightChromiumBrowser({
|
|
32108
|
-
url: attached.endpoint
|
|
32109
|
-
});
|
|
32110
|
-
try {
|
|
32111
|
-
const context = browser.contexts()[0];
|
|
32112
|
-
if (!context) {
|
|
32113
|
-
throw new Error("Attached browser did not expose a default browser context.");
|
|
32114
|
-
}
|
|
32115
|
-
const prepared = prepareBrowserProfileSyncCookies({
|
|
32116
|
-
cookies: await context.cookies(),
|
|
32117
|
-
...input.domains === void 0 ? {} : { domains: input.domains }
|
|
32118
|
-
});
|
|
32119
|
-
if (prepared.cookies.length === 0) {
|
|
32120
|
-
throw new Error("No syncable cookies found for the selected browser and scope.");
|
|
32121
|
-
}
|
|
32122
|
-
const browserVersion = browser.version();
|
|
32123
|
-
const source = parseSnapshotSource(attached.browser ?? browserVersion);
|
|
32124
|
-
return {
|
|
32125
|
-
version: "portable-cookies-v1",
|
|
32126
|
-
source: {
|
|
32127
|
-
browserFamily: "chromium",
|
|
32128
|
-
...source.browserName === void 0 ? {} : { browserName: source.browserName },
|
|
32129
|
-
...source.browserMajor === void 0 ? {} : { browserMajor: source.browserMajor },
|
|
32130
|
-
...input.browserBrand === void 0 ? {} : { browserBrand: input.browserBrand },
|
|
32131
|
-
...input.captureMethod === void 0 ? {} : { captureMethod: input.captureMethod },
|
|
32132
|
-
platform: normalizePlatform(process.platform),
|
|
32133
|
-
capturedAt: Date.now()
|
|
32134
|
-
},
|
|
32135
|
-
cookies: prepared.cookies
|
|
32136
|
-
};
|
|
32137
|
-
} finally {
|
|
32138
|
-
await browser.close().catch(() => void 0);
|
|
32139
|
-
}
|
|
32140
|
-
}
|
|
32141
|
-
async function encodePortableBrowserProfileSnapshot(snapshot) {
|
|
32142
|
-
return gzip(Buffer.from(JSON.stringify(snapshot), "utf8"));
|
|
32143
|
-
}
|
|
32144
|
-
function parseSnapshotSource(value) {
|
|
32145
|
-
if (!value) {
|
|
32146
|
-
return {};
|
|
32147
|
-
}
|
|
32148
|
-
const trimmed = value.trim();
|
|
32149
|
-
const browserName = trimmed.split("/")[0]?.trim() || void 0;
|
|
32150
|
-
const majorMatch = trimmed.match(/(\d+)/);
|
|
32151
|
-
return {
|
|
32152
|
-
...browserName === void 0 ? {} : { browserName },
|
|
32153
|
-
...majorMatch?.[1] === void 0 ? {} : { browserMajor: majorMatch[1] }
|
|
32154
|
-
};
|
|
32155
|
-
}
|
|
32156
|
-
function normalizePlatform(platform) {
|
|
32157
|
-
if (platform === "darwin") return "macos";
|
|
32158
|
-
if (platform === "win32") return "windows";
|
|
32159
|
-
return platform;
|
|
32160
|
-
}
|
|
32161
|
-
|
|
32162
32962
|
// src/cloud/profile-sync.ts
|
|
32963
|
+
var gzip = util.promisify(zlib.gzip);
|
|
32163
32964
|
var DEFAULT_POLL_INTERVAL_MS = 1e3;
|
|
32164
32965
|
var DEFAULT_POLL_TIMEOUT_MS = 5 * 6e4;
|
|
32165
32966
|
async function syncBrowserProfileCookies(client, input) {
|
|
32166
|
-
const
|
|
32167
|
-
...input.attachEndpoint === void 0 ? {} : { attachEndpoint: input.attachEndpoint },
|
|
32967
|
+
const result = await readBrowserCookies({
|
|
32168
32968
|
...input.brandId === void 0 ? {} : { brandId: input.brandId },
|
|
32169
32969
|
...input.userDataDir === void 0 ? {} : { userDataDir: input.userDataDir },
|
|
32170
|
-
...input.profileDirectory === void 0 ? {} : { profileDirectory: input.profileDirectory }
|
|
32171
|
-
...input.executablePath === void 0 ? {} : { executablePath: input.executablePath },
|
|
32172
|
-
...input.strategy === void 0 ? {} : { strategy: input.strategy },
|
|
32173
|
-
...input.timeoutMs === void 0 ? {} : { timeoutMs: input.timeoutMs }
|
|
32970
|
+
...input.profileDirectory === void 0 ? {} : { profileDirectory: input.profileDirectory }
|
|
32174
32971
|
});
|
|
32175
|
-
const
|
|
32176
|
-
|
|
32177
|
-
|
|
32178
|
-
|
|
32179
|
-
|
|
32180
|
-
|
|
32181
|
-
|
|
32182
|
-
|
|
32183
|
-
|
|
32184
|
-
|
|
32185
|
-
|
|
32186
|
-
|
|
32187
|
-
|
|
32188
|
-
|
|
32189
|
-
|
|
32190
|
-
|
|
32191
|
-
|
|
32192
|
-
|
|
32193
|
-
|
|
32194
|
-
|
|
32195
|
-
|
|
32196
|
-
|
|
32197
|
-
|
|
32198
|
-
|
|
32199
|
-
|
|
32200
|
-
|
|
32201
|
-
await captureSource?.cleanup().catch(() => void 0);
|
|
32202
|
-
if (shouldRestoreBrowser && resolved.executablePath !== void 0) {
|
|
32203
|
-
relaunchBrowserNormally(resolved.executablePath);
|
|
32204
|
-
}
|
|
32972
|
+
const prepared = prepareBrowserProfileSyncCookies({
|
|
32973
|
+
cookies: result.cookies,
|
|
32974
|
+
...input.domains === void 0 ? {} : { domains: input.domains }
|
|
32975
|
+
});
|
|
32976
|
+
if (prepared.cookies.length === 0) {
|
|
32977
|
+
throw new Error("No syncable cookies found for the selected browser and scope.");
|
|
32978
|
+
}
|
|
32979
|
+
const snapshot = {
|
|
32980
|
+
version: "portable-cookies-v1",
|
|
32981
|
+
source: {
|
|
32982
|
+
browserFamily: "chromium",
|
|
32983
|
+
browserBrand: result.brandId,
|
|
32984
|
+
captureMethod: "sqlite",
|
|
32985
|
+
platform: normalizePlatform(process.platform),
|
|
32986
|
+
capturedAt: Date.now()
|
|
32987
|
+
},
|
|
32988
|
+
cookies: prepared.cookies
|
|
32989
|
+
};
|
|
32990
|
+
const payload = await gzip(Buffer.from(JSON.stringify(snapshot), "utf8"));
|
|
32991
|
+
const created = await client.createBrowserProfileImport({
|
|
32992
|
+
profileId: input.profileId
|
|
32993
|
+
});
|
|
32994
|
+
if (payload.length > created.maxUploadBytes) {
|
|
32995
|
+
throw new Error(
|
|
32996
|
+
`Compressed cookie snapshot is ${String(payload.length)} bytes, exceeding the ${String(created.maxUploadBytes)} byte upload limit.`
|
|
32997
|
+
);
|
|
32205
32998
|
}
|
|
32999
|
+
const uploaded = await client.uploadBrowserProfileImportPayload({
|
|
33000
|
+
uploadUrl: created.uploadUrl,
|
|
33001
|
+
payload
|
|
33002
|
+
});
|
|
33003
|
+
return uploaded.status === "ready" ? uploaded : waitForBrowserProfileImport(client, created.importId);
|
|
32206
33004
|
}
|
|
32207
33005
|
async function waitForBrowserProfileImport(client, importId) {
|
|
32208
33006
|
const deadline = Date.now() + DEFAULT_POLL_TIMEOUT_MS;
|
|
@@ -32214,12 +33012,17 @@ async function waitForBrowserProfileImport(client, importId) {
|
|
|
32214
33012
|
if (current.status === "failed") {
|
|
32215
33013
|
throw new Error(current.error ?? "Browser profile sync failed.");
|
|
32216
33014
|
}
|
|
32217
|
-
await
|
|
33015
|
+
await sleep4(DEFAULT_POLL_INTERVAL_MS);
|
|
32218
33016
|
}
|
|
32219
33017
|
throw new Error(`Timed out waiting for browser profile sync "${importId}" to finish.`);
|
|
32220
33018
|
}
|
|
32221
|
-
|
|
32222
|
-
|
|
33019
|
+
function normalizePlatform(platform) {
|
|
33020
|
+
if (platform === "darwin") return "macos";
|
|
33021
|
+
if (platform === "win32") return "windows";
|
|
33022
|
+
return platform;
|
|
33023
|
+
}
|
|
33024
|
+
async function sleep4(ms) {
|
|
33025
|
+
await new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
32223
33026
|
}
|
|
32224
33027
|
|
|
32225
33028
|
// src/cloud/client.ts
|
|
@@ -32239,7 +33042,12 @@ var OpensteerCloudClient = class {
|
|
|
32239
33042
|
...input.name === void 0 ? {} : { name: input.name },
|
|
32240
33043
|
...input.browser === void 0 ? {} : { browser: input.browser },
|
|
32241
33044
|
...input.context === void 0 ? {} : { context: input.context },
|
|
32242
|
-
...input.browserProfile === void 0 ? {} : { browserProfile: input.browserProfile }
|
|
33045
|
+
...input.browserProfile === void 0 ? {} : { browserProfile: input.browserProfile },
|
|
33046
|
+
...input.observability === void 0 ? {} : { observability: input.observability },
|
|
33047
|
+
...input.sourceType === void 0 ? {} : { sourceType: input.sourceType },
|
|
33048
|
+
...input.sourceRef === void 0 ? {} : { sourceRef: input.sourceRef },
|
|
33049
|
+
...input.localWorkspaceRootPath === void 0 ? {} : { localWorkspaceRootPath: input.localWorkspaceRootPath },
|
|
33050
|
+
...input.locality === void 0 ? {} : { locality: input.locality }
|
|
32243
33051
|
}
|
|
32244
33052
|
});
|
|
32245
33053
|
return await response.json();
|
|
@@ -32417,8 +33225,8 @@ var OpensteerCloudClient = class {
|
|
|
32417
33225
|
}
|
|
32418
33226
|
};
|
|
32419
33227
|
function delay(ms) {
|
|
32420
|
-
return new Promise((
|
|
32421
|
-
setTimeout(
|
|
33228
|
+
return new Promise((resolve4) => {
|
|
33229
|
+
setTimeout(resolve4, ms);
|
|
32422
33230
|
});
|
|
32423
33231
|
}
|
|
32424
33232
|
function wrapCloudFetchError(error, input) {
|
|
@@ -32441,17 +33249,17 @@ function wrapCloudFetchError(error, input) {
|
|
|
32441
33249
|
function resolveCloudConfig(input = {}) {
|
|
32442
33250
|
const provider = resolveOpensteerProvider({
|
|
32443
33251
|
...input.provider === void 0 ? {} : { provider: input.provider },
|
|
32444
|
-
...input.
|
|
33252
|
+
...input.environment?.OPENSTEER_PROVIDER === void 0 ? {} : { environmentProvider: input.environment.OPENSTEER_PROVIDER }
|
|
32445
33253
|
});
|
|
32446
33254
|
if (provider.mode !== "cloud") {
|
|
32447
33255
|
return void 0;
|
|
32448
33256
|
}
|
|
32449
33257
|
const cloudProvider = input.provider?.mode === "cloud" ? input.provider : void 0;
|
|
32450
|
-
const apiKey = cloudProvider?.apiKey ??
|
|
33258
|
+
const apiKey = cloudProvider?.apiKey ?? input.environment?.OPENSTEER_API_KEY;
|
|
32451
33259
|
if (!apiKey || apiKey.trim().length === 0) {
|
|
32452
33260
|
throw new Error("provider=cloud requires OPENSTEER_API_KEY or provider.apiKey.");
|
|
32453
33261
|
}
|
|
32454
|
-
const baseUrl = cloudProvider?.baseUrl ??
|
|
33262
|
+
const baseUrl = cloudProvider?.baseUrl ?? input.environment?.OPENSTEER_BASE_URL;
|
|
32455
33263
|
if (!baseUrl || baseUrl.trim().length === 0) {
|
|
32456
33264
|
throw new Error("provider=cloud requires OPENSTEER_BASE_URL or provider.baseUrl.");
|
|
32457
33265
|
}
|
|
@@ -32476,6 +33284,9 @@ var OpensteerSemanticRestClient = class {
|
|
|
32476
33284
|
this.connection = connection;
|
|
32477
33285
|
}
|
|
32478
33286
|
async invoke(operation, input) {
|
|
33287
|
+
return this.invokeInternal(operation, input, false);
|
|
33288
|
+
}
|
|
33289
|
+
async invokeInternal(operation, input, hasRetried) {
|
|
32479
33290
|
const endpoint = opensteerSemanticRestEndpoints.find((entry) => entry.name === operation);
|
|
32480
33291
|
if (!endpoint) {
|
|
32481
33292
|
throw new Error(`unsupported semantic operation ${operation}`);
|
|
@@ -32485,7 +33296,7 @@ var OpensteerSemanticRestClient = class {
|
|
|
32485
33296
|
});
|
|
32486
33297
|
let response;
|
|
32487
33298
|
try {
|
|
32488
|
-
response = await fetch(`${this.connection.
|
|
33299
|
+
response = await fetch(`${await this.connection.getBaseUrl()}${endpoint.path}`, {
|
|
32489
33300
|
method: "POST",
|
|
32490
33301
|
headers: {
|
|
32491
33302
|
authorization: await this.connection.getAuthorizationHeader(),
|
|
@@ -32507,6 +33318,9 @@ var OpensteerSemanticRestClient = class {
|
|
|
32507
33318
|
}
|
|
32508
33319
|
return envelope.data;
|
|
32509
33320
|
} catch (error) {
|
|
33321
|
+
if (!hasRetried && this.connection.handleError && await this.connection.handleError(error, { operation })) {
|
|
33322
|
+
return this.invokeInternal(operation, input, true);
|
|
33323
|
+
}
|
|
32510
33324
|
if (operation === "session.close" && isFetchFailure(error)) {
|
|
32511
33325
|
return { closed: true };
|
|
32512
33326
|
}
|
|
@@ -32553,9 +33367,9 @@ var OpensteerCloudAutomationClient = class {
|
|
|
32553
33367
|
sentAt: Date.now(),
|
|
32554
33368
|
...input === void 0 ? {} : { input }
|
|
32555
33369
|
};
|
|
32556
|
-
return new Promise((
|
|
33370
|
+
return new Promise((resolve4, reject) => {
|
|
32557
33371
|
this.pending.set(requestId, {
|
|
32558
|
-
resolve: (value) =>
|
|
33372
|
+
resolve: (value) => resolve4(value),
|
|
32559
33373
|
reject
|
|
32560
33374
|
});
|
|
32561
33375
|
try {
|
|
@@ -32618,8 +33432,8 @@ var OpensteerCloudAutomationClient = class {
|
|
|
32618
33432
|
pending.reject(new Error(`automation connection closed before ${requestId} completed`));
|
|
32619
33433
|
}
|
|
32620
33434
|
this.pending.clear();
|
|
32621
|
-
await new Promise((
|
|
32622
|
-
socket.once("close", () =>
|
|
33435
|
+
await new Promise((resolve4) => {
|
|
33436
|
+
socket.once("close", () => resolve4());
|
|
32623
33437
|
socket.close();
|
|
32624
33438
|
}).catch(() => void 0);
|
|
32625
33439
|
}
|
|
@@ -32640,7 +33454,10 @@ var OpensteerCloudAutomationClient = class {
|
|
|
32640
33454
|
}
|
|
32641
33455
|
async connect() {
|
|
32642
33456
|
const grant = await this.issueGrant("automation");
|
|
32643
|
-
|
|
33457
|
+
if (grant.transport !== "ws") {
|
|
33458
|
+
throw new Error(`cloud issued an invalid ${grant.kind} grant transport`);
|
|
33459
|
+
}
|
|
33460
|
+
const wsUrl = new URL(grant.url);
|
|
32644
33461
|
wsUrl.searchParams.set("token", grant.token);
|
|
32645
33462
|
const socket = new WebSocket2__default.default(wsUrl);
|
|
32646
33463
|
this.socket = socket;
|
|
@@ -32661,8 +33478,8 @@ var OpensteerCloudAutomationClient = class {
|
|
|
32661
33478
|
}
|
|
32662
33479
|
this.pending.clear();
|
|
32663
33480
|
});
|
|
32664
|
-
await new Promise((
|
|
32665
|
-
socket.once("open", () =>
|
|
33481
|
+
await new Promise((resolve4, reject) => {
|
|
33482
|
+
socket.once("open", () => resolve4());
|
|
32666
33483
|
socket.once("error", reject);
|
|
32667
33484
|
});
|
|
32668
33485
|
this.send({
|
|
@@ -33003,16 +33820,18 @@ var CloudSessionProxy = class {
|
|
|
33003
33820
|
workspace;
|
|
33004
33821
|
cleanupRootOnClose;
|
|
33005
33822
|
cloud;
|
|
33823
|
+
observability;
|
|
33006
33824
|
sessionId;
|
|
33007
|
-
|
|
33825
|
+
semanticGrant;
|
|
33008
33826
|
client;
|
|
33009
33827
|
automation;
|
|
33010
33828
|
workspaceStore;
|
|
33011
33829
|
constructor(cloud, options = {}) {
|
|
33012
33830
|
this.cloud = cloud;
|
|
33013
33831
|
this.workspace = options.workspace;
|
|
33014
|
-
this.
|
|
33015
|
-
|
|
33832
|
+
this.observability = options.observability;
|
|
33833
|
+
this.rootPath = options.rootPath ?? (this.workspace === void 0 ? path7__default.default.join(os.tmpdir(), `${TEMPORARY_CLOUD_WORKSPACE_PREFIX}${crypto.randomUUID()}`) : resolveFilesystemWorkspacePath({
|
|
33834
|
+
rootDir: path7__default.default.resolve(options.rootDir ?? process.cwd()),
|
|
33016
33835
|
workspace: this.workspace
|
|
33017
33836
|
}));
|
|
33018
33837
|
this.cleanupRootOnClose = options.cleanupRootOnClose ?? this.workspace === void 0;
|
|
@@ -33054,7 +33873,7 @@ var CloudSessionProxy = class {
|
|
|
33054
33873
|
reconnectable: this.workspace !== void 0 || this.sessionId !== void 0 || persisted !== void 0,
|
|
33055
33874
|
capabilities: {
|
|
33056
33875
|
semanticOperations: opensteerSemanticOperationNames,
|
|
33057
|
-
sessionGrants: ["automation", "view", "cdp"],
|
|
33876
|
+
sessionGrants: ["semantic", "automation", "view", "cdp"],
|
|
33058
33877
|
instrumentation: {
|
|
33059
33878
|
route: true,
|
|
33060
33879
|
interceptScript: true,
|
|
@@ -33296,13 +34115,12 @@ var CloudSessionProxy = class {
|
|
|
33296
34115
|
return this.requireClient().invoke("computer.execute", input);
|
|
33297
34116
|
}
|
|
33298
34117
|
async close() {
|
|
33299
|
-
const session = await this.loadPersistedSession() ?? (this.sessionId === void 0
|
|
34118
|
+
const session = await this.loadPersistedSession() ?? (this.sessionId === void 0 ? void 0 : {
|
|
33300
34119
|
layout: "opensteer-session",
|
|
33301
34120
|
version: 1,
|
|
33302
34121
|
provider: "cloud",
|
|
33303
34122
|
...this.workspace === void 0 ? {} : { workspace: this.workspace },
|
|
33304
34123
|
sessionId: this.sessionId,
|
|
33305
|
-
baseUrl: this.sessionBaseUrl,
|
|
33306
34124
|
startedAt: Date.now(),
|
|
33307
34125
|
updatedAt: Date.now()
|
|
33308
34126
|
});
|
|
@@ -33321,7 +34139,7 @@ var CloudSessionProxy = class {
|
|
|
33321
34139
|
this.automation = void 0;
|
|
33322
34140
|
this.client = void 0;
|
|
33323
34141
|
this.sessionId = void 0;
|
|
33324
|
-
this.
|
|
34142
|
+
this.semanticGrant = void 0;
|
|
33325
34143
|
if (this.cleanupRootOnClose) {
|
|
33326
34144
|
await promises.rm(this.rootPath, { recursive: true, force: true }).catch(() => void 0);
|
|
33327
34145
|
}
|
|
@@ -33337,38 +34155,56 @@ var CloudSessionProxy = class {
|
|
|
33337
34155
|
await this.automation?.close().catch(() => void 0);
|
|
33338
34156
|
this.automation = void 0;
|
|
33339
34157
|
this.sessionId = void 0;
|
|
33340
|
-
this.
|
|
34158
|
+
this.semanticGrant = void 0;
|
|
33341
34159
|
}
|
|
33342
34160
|
async ensureSession(input = {}) {
|
|
33343
34161
|
if (this.client) {
|
|
33344
34162
|
return;
|
|
33345
34163
|
}
|
|
33346
34164
|
assertSupportedCloudBrowserMode(input.browser);
|
|
34165
|
+
const localCloud = this.shouldUseLocalCloudTransport();
|
|
34166
|
+
const browserProfile = resolveCloudBrowserProfile(this.cloud, input);
|
|
33347
34167
|
const persisted = await this.loadPersistedSession();
|
|
33348
34168
|
if (persisted !== void 0 && await this.isReusableCloudSession(persisted.sessionId)) {
|
|
33349
|
-
|
|
34169
|
+
if (localCloud) {
|
|
34170
|
+
void this.syncRegistryToCloud();
|
|
34171
|
+
} else {
|
|
34172
|
+
await this.syncRegistryToCloud();
|
|
34173
|
+
}
|
|
33350
34174
|
this.bindClient(persisted);
|
|
33351
34175
|
return;
|
|
33352
34176
|
}
|
|
33353
|
-
|
|
33354
|
-
|
|
34177
|
+
if (localCloud) {
|
|
34178
|
+
void this.syncRegistryToCloud();
|
|
34179
|
+
} else {
|
|
34180
|
+
await this.syncRegistryToCloud();
|
|
34181
|
+
}
|
|
34182
|
+
const baseCreateInput = {
|
|
33355
34183
|
...this.workspace === void 0 ? {} : { name: this.workspace },
|
|
33356
34184
|
...input.launch === void 0 ? {} : { browser: input.launch },
|
|
33357
34185
|
...input.context === void 0 ? {} : { context: input.context },
|
|
33358
|
-
...
|
|
33359
|
-
|
|
34186
|
+
...this.observability === void 0 ? {} : { observability: this.observability },
|
|
34187
|
+
...browserProfile === void 0 ? {} : { browserProfile }
|
|
34188
|
+
};
|
|
34189
|
+
const createInput = localCloud && this.workspace !== void 0 ? {
|
|
34190
|
+
...baseCreateInput,
|
|
34191
|
+
sourceType: "local-cloud",
|
|
34192
|
+
sourceRef: this.workspace,
|
|
34193
|
+
localWorkspaceRootPath: this.rootPath,
|
|
34194
|
+
locality: "auto"
|
|
34195
|
+
} : baseCreateInput;
|
|
34196
|
+
const session = await this.cloud.createSession(createInput);
|
|
33360
34197
|
const record = {
|
|
33361
34198
|
layout: "opensteer-session",
|
|
33362
34199
|
version: 1,
|
|
33363
34200
|
provider: "cloud",
|
|
33364
34201
|
...this.workspace === void 0 ? {} : { workspace: this.workspace },
|
|
33365
34202
|
sessionId: session.sessionId,
|
|
33366
|
-
baseUrl: session.baseUrl,
|
|
33367
34203
|
startedAt: Date.now(),
|
|
33368
34204
|
updatedAt: Date.now()
|
|
33369
34205
|
};
|
|
33370
34206
|
await this.writePersistedSession(record);
|
|
33371
|
-
this.bindClient(record);
|
|
34207
|
+
this.bindClient(record, session.initialGrants?.semantic);
|
|
33372
34208
|
}
|
|
33373
34209
|
async syncRegistryToCloud() {
|
|
33374
34210
|
if (this.workspace === void 0) {
|
|
@@ -33377,15 +34213,16 @@ var CloudSessionProxy = class {
|
|
|
33377
34213
|
try {
|
|
33378
34214
|
const workspaceStore = await this.ensureWorkspaceStore();
|
|
33379
34215
|
await syncLocalRegistryToCloud(this.cloud, this.workspace, workspaceStore);
|
|
33380
|
-
} catch
|
|
34216
|
+
} catch {
|
|
33381
34217
|
}
|
|
33382
34218
|
}
|
|
33383
|
-
bindClient(record) {
|
|
34219
|
+
bindClient(record, initialSemanticGrant) {
|
|
33384
34220
|
this.sessionId = record.sessionId;
|
|
33385
|
-
this.
|
|
34221
|
+
this.semanticGrant = initialSemanticGrant?.kind === "semantic" ? initialSemanticGrant : void 0;
|
|
33386
34222
|
this.client = new OpensteerSemanticRestClient({
|
|
33387
|
-
|
|
33388
|
-
getAuthorizationHeader: async () => this.
|
|
34223
|
+
getBaseUrl: async () => (await this.ensureSemanticGrant()).url,
|
|
34224
|
+
getAuthorizationHeader: async () => `Bearer ${(await this.ensureSemanticGrant()).token}`,
|
|
34225
|
+
handleError: (error) => this.handleSemanticClientError(error)
|
|
33389
34226
|
});
|
|
33390
34227
|
this.automation = new OpensteerCloudAutomationClient(this.cloud, record.sessionId);
|
|
33391
34228
|
}
|
|
@@ -33434,6 +34271,43 @@ var CloudSessionProxy = class {
|
|
|
33434
34271
|
}
|
|
33435
34272
|
return this.automation;
|
|
33436
34273
|
}
|
|
34274
|
+
async ensureSemanticGrant(forceRefresh = false) {
|
|
34275
|
+
if (!forceRefresh && this.semanticGrant?.kind === "semantic" && this.semanticGrant.expiresAt > Date.now() + 1e4) {
|
|
34276
|
+
return this.semanticGrant;
|
|
34277
|
+
}
|
|
34278
|
+
if (!this.sessionId) {
|
|
34279
|
+
throw new Error("Cloud session has not been initialized.");
|
|
34280
|
+
}
|
|
34281
|
+
const issued = await this.cloud.issueAccess(this.sessionId, ["semantic"]);
|
|
34282
|
+
const grant = issued.grants.semantic;
|
|
34283
|
+
if (!grant || grant.transport !== "http") {
|
|
34284
|
+
throw new Error("cloud did not issue a valid semantic grant");
|
|
34285
|
+
}
|
|
34286
|
+
this.semanticGrant = grant;
|
|
34287
|
+
return grant;
|
|
34288
|
+
}
|
|
34289
|
+
async handleSemanticClientError(error) {
|
|
34290
|
+
if (!(error instanceof OpensteerSemanticRestError)) {
|
|
34291
|
+
return false;
|
|
34292
|
+
}
|
|
34293
|
+
if (error.statusCode !== 401 && error.statusCode !== 404) {
|
|
34294
|
+
return false;
|
|
34295
|
+
}
|
|
34296
|
+
this.semanticGrant = void 0;
|
|
34297
|
+
try {
|
|
34298
|
+
await this.ensureSemanticGrant(true);
|
|
34299
|
+
return true;
|
|
34300
|
+
} catch {
|
|
34301
|
+
return false;
|
|
34302
|
+
}
|
|
34303
|
+
}
|
|
34304
|
+
shouldUseLocalCloudTransport() {
|
|
34305
|
+
if (this.workspace === void 0) {
|
|
34306
|
+
return false;
|
|
34307
|
+
}
|
|
34308
|
+
const config = this.cloud.getConfig();
|
|
34309
|
+
return isLoopbackBaseUrl(config.baseUrl);
|
|
34310
|
+
}
|
|
33437
34311
|
};
|
|
33438
34312
|
function resolveCloudBrowserProfile(cloud, input) {
|
|
33439
34313
|
return input.browserProfile ?? cloud.getConfig().browserProfile;
|
|
@@ -33449,19 +34323,41 @@ function assertSupportedCloudBrowserMode(browser) {
|
|
|
33449
34323
|
function isMissingCloudSessionError(error) {
|
|
33450
34324
|
return error instanceof Error && /\b404\b/.test(error.message);
|
|
33451
34325
|
}
|
|
34326
|
+
function isLoopbackBaseUrl(baseUrl) {
|
|
34327
|
+
let url;
|
|
34328
|
+
try {
|
|
34329
|
+
url = new URL(baseUrl);
|
|
34330
|
+
} catch {
|
|
34331
|
+
return false;
|
|
34332
|
+
}
|
|
34333
|
+
return url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "::1" || url.hostname === "[::1]";
|
|
34334
|
+
}
|
|
33452
34335
|
|
|
33453
34336
|
// src/sdk/runtime-resolution.ts
|
|
34337
|
+
var LOCAL_ONLY_RUNTIME_OPTION_KEYS = [
|
|
34338
|
+
"launch",
|
|
34339
|
+
"context",
|
|
34340
|
+
"engine",
|
|
34341
|
+
"engineFactory",
|
|
34342
|
+
"policy",
|
|
34343
|
+
"descriptorStore",
|
|
34344
|
+
"extractionDescriptorStore",
|
|
34345
|
+
"registryOverrides",
|
|
34346
|
+
"observationSessionId",
|
|
34347
|
+
"observationSink"
|
|
34348
|
+
];
|
|
33454
34349
|
function resolveOpensteerRuntimeConfig(input = {}) {
|
|
34350
|
+
const environment = input.environment ?? process.env;
|
|
33455
34351
|
const provider = resolveOpensteerProvider({
|
|
33456
34352
|
...input.provider === void 0 ? {} : { provider: input.provider },
|
|
33457
|
-
...
|
|
34353
|
+
...environment.OPENSTEER_PROVIDER === void 0 ? {} : { environmentProvider: environment.OPENSTEER_PROVIDER }
|
|
33458
34354
|
});
|
|
33459
34355
|
if (provider.mode === "cloud") {
|
|
33460
34356
|
return {
|
|
33461
34357
|
provider,
|
|
33462
34358
|
cloud: resolveCloudConfig({
|
|
33463
34359
|
...input.provider === void 0 ? {} : { provider: input.provider },
|
|
33464
|
-
|
|
34360
|
+
environment
|
|
33465
34361
|
})
|
|
33466
34362
|
};
|
|
33467
34363
|
}
|
|
@@ -33472,15 +34368,23 @@ function createOpensteerSemanticRuntime(input = {}) {
|
|
|
33472
34368
|
const engine = input.engine ?? runtimeOptions.engineName ?? DEFAULT_OPENSTEER_ENGINE;
|
|
33473
34369
|
const config = resolveOpensteerRuntimeConfig({
|
|
33474
34370
|
...input.provider === void 0 ? {} : { provider: input.provider },
|
|
33475
|
-
...
|
|
34371
|
+
...input.environment === void 0 ? {} : { environment: input.environment }
|
|
33476
34372
|
});
|
|
33477
|
-
|
|
33478
|
-
|
|
34373
|
+
const localOnlyRuntimeOptions = listLocalOnlyRuntimeOptions(runtimeOptions);
|
|
34374
|
+
const providerMode = config.provider.mode === "cloud" && config.provider.source !== "explicit" && localOnlyRuntimeOptions.length > 0 ? "local" : config.provider.mode;
|
|
34375
|
+
if (config.provider.mode === "cloud" && config.provider.source === "explicit" && localOnlyRuntimeOptions.length > 0) {
|
|
34376
|
+
throw new Error(
|
|
34377
|
+
`provider=cloud does not support local runtime options: ${localOnlyRuntimeOptions.join(", ")}.`
|
|
34378
|
+
);
|
|
34379
|
+
}
|
|
34380
|
+
assertProviderSupportsEngine(providerMode, engine);
|
|
34381
|
+
if (providerMode === "cloud") {
|
|
33479
34382
|
return new CloudSessionProxy(new OpensteerCloudClient(config.cloud), {
|
|
33480
34383
|
...runtimeOptions.rootDir === void 0 ? {} : { rootDir: runtimeOptions.rootDir },
|
|
33481
34384
|
...runtimeOptions.rootPath === void 0 ? {} : { rootPath: runtimeOptions.rootPath },
|
|
33482
34385
|
...runtimeOptions.workspace === void 0 ? {} : { workspace: runtimeOptions.workspace },
|
|
33483
|
-
...runtimeOptions.cleanupRootOnClose === void 0 ? {} : { cleanupRootOnClose: runtimeOptions.cleanupRootOnClose }
|
|
34386
|
+
...runtimeOptions.cleanupRootOnClose === void 0 ? {} : { cleanupRootOnClose: runtimeOptions.cleanupRootOnClose },
|
|
34387
|
+
...runtimeOptions.observability === void 0 ? {} : { observability: runtimeOptions.observability }
|
|
33484
34388
|
});
|
|
33485
34389
|
}
|
|
33486
34390
|
return new OpensteerRuntime({
|
|
@@ -33488,6 +34392,9 @@ function createOpensteerSemanticRuntime(input = {}) {
|
|
|
33488
34392
|
engineName: engine
|
|
33489
34393
|
});
|
|
33490
34394
|
}
|
|
34395
|
+
function listLocalOnlyRuntimeOptions(runtimeOptions) {
|
|
34396
|
+
return LOCAL_ONLY_RUNTIME_OPTION_KEYS.filter((key) => runtimeOptions[key] !== void 0);
|
|
34397
|
+
}
|
|
33491
34398
|
|
|
33492
34399
|
// src/sdk/opensteer.ts
|
|
33493
34400
|
var Opensteer = class {
|
|
@@ -33495,16 +34402,18 @@ var Opensteer = class {
|
|
|
33495
34402
|
browserManager;
|
|
33496
34403
|
browser;
|
|
33497
34404
|
constructor(options = {}) {
|
|
34405
|
+
const environment = resolveOpensteerEnvironment(options.rootDir);
|
|
33498
34406
|
const { provider, engineName, ...runtimeOptions } = options;
|
|
33499
34407
|
const runtimeConfig = resolveOpensteerRuntimeConfig({
|
|
33500
34408
|
...provider === void 0 ? {} : { provider },
|
|
33501
|
-
|
|
34409
|
+
environment
|
|
33502
34410
|
});
|
|
33503
34411
|
if (runtimeConfig.provider.mode === "cloud") {
|
|
33504
34412
|
this.browserManager = void 0;
|
|
33505
34413
|
this.runtime = createOpensteerSemanticRuntime({
|
|
33506
34414
|
...provider === void 0 ? {} : { provider },
|
|
33507
34415
|
...engineName === void 0 ? {} : { engine: engineName },
|
|
34416
|
+
environment,
|
|
33508
34417
|
runtimeOptions: {
|
|
33509
34418
|
...runtimeOptions
|
|
33510
34419
|
}
|
|
@@ -33524,6 +34433,7 @@ var Opensteer = class {
|
|
|
33524
34433
|
this.runtime = createOpensteerSemanticRuntime({
|
|
33525
34434
|
...provider === void 0 ? {} : { provider },
|
|
33526
34435
|
...engineName === void 0 ? {} : { engine: engineName },
|
|
34436
|
+
environment,
|
|
33527
34437
|
runtimeOptions: {
|
|
33528
34438
|
...runtimeOptions,
|
|
33529
34439
|
rootPath: this.browserManager.rootPath,
|
|
@@ -33865,7 +34775,7 @@ function normalizeTargetOptions(input) {
|
|
|
33865
34775
|
};
|
|
33866
34776
|
}
|
|
33867
34777
|
function delay2(ms) {
|
|
33868
|
-
return new Promise((
|
|
34778
|
+
return new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
33869
34779
|
}
|
|
33870
34780
|
|
|
33871
34781
|
exports.CloudSessionProxy = CloudSessionProxy;
|
|
@@ -33896,8 +34806,11 @@ exports.clearPersistedSessionRecord = clearPersistedSessionRecord;
|
|
|
33896
34806
|
exports.cloneElementPath = cloneElementPath;
|
|
33897
34807
|
exports.cloneReplayElementPath = cloneReplayElementPath;
|
|
33898
34808
|
exports.cloneStructuralElementAnchor = cloneStructuralElementAnchor;
|
|
34809
|
+
exports.createArtifactStore = createArtifactStore;
|
|
34810
|
+
exports.createDomDescriptorStore = createDomDescriptorStore;
|
|
33899
34811
|
exports.createDomRuntime = createDomRuntime;
|
|
33900
34812
|
exports.createFilesystemOpensteerWorkspace = createFilesystemOpensteerWorkspace;
|
|
34813
|
+
exports.createObservationStore = createObservationStore;
|
|
33901
34814
|
exports.createOpensteerExtractionDescriptorStore = createOpensteerExtractionDescriptorStore;
|
|
33902
34815
|
exports.createOpensteerSemanticRuntime = createOpensteerSemanticRuntime;
|
|
33903
34816
|
exports.defaultFallbackPolicy = defaultFallbackPolicy;
|
|
@@ -33913,7 +34826,9 @@ exports.inspectCdpEndpoint = inspectCdpEndpoint;
|
|
|
33913
34826
|
exports.isCurrentUrlField = isCurrentUrlField;
|
|
33914
34827
|
exports.isValidCssAttributeKey = isValidCssAttributeKey;
|
|
33915
34828
|
exports.listLocalChromeProfiles = listLocalChromeProfiles;
|
|
34829
|
+
exports.manifestToExternalBinaryLocation = manifestToExternalBinaryLocation;
|
|
33916
34830
|
exports.normalizeExtractedValue = normalizeExtractedValue;
|
|
34831
|
+
exports.normalizeObservabilityConfig = normalizeObservabilityConfig;
|
|
33917
34832
|
exports.normalizeOpensteerEngineName = normalizeOpensteerEngineName;
|
|
33918
34833
|
exports.normalizeOpensteerProviderMode = normalizeOpensteerProviderMode;
|
|
33919
34834
|
exports.normalizeWorkspaceId = normalizeWorkspaceId;
|