@modelprofile.com/browser-runtime 4.3.0 → 5.0.0
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/changelog.md +34 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.runtime.d.ts +43 -11
- package/dist_ts/classes.runtime.js +574 -570
- package/dist_ts/classes.runtimeownership.d.ts +3 -1
- package/dist_ts/classes.runtimeownership.js +27 -7
- package/dist_ts/index.d.ts +2 -2
- package/dist_ts/interfaces.d.ts +8 -3
- package/dist_ts/mcp.js +5 -3
- package/package.json +2 -2
- package/readme.hints.md +13 -10
- package/readme.md +22 -8
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.runtime.ts +620 -638
- package/ts/classes.runtimeownership.ts +23 -6
- package/ts/index.ts +5 -1
- package/ts/interfaces.ts +9 -3
- package/ts/mcp.ts +5 -2
|
@@ -40,6 +40,7 @@ export interface IBrowserRuntimeOwnershipTestingOptions {
|
|
|
40
40
|
now?(): number;
|
|
41
41
|
beforeMetadataPublication?(): Promise<void>;
|
|
42
42
|
afterLegacyLockProbe?(): Promise<void>;
|
|
43
|
+
afterEmptyProcessCmdline?(pid: number): Promise<void>;
|
|
43
44
|
beforeGenerationRemoval?(reason: TOwnershipGenerationRemovalReason): Promise<void>;
|
|
44
45
|
}
|
|
45
46
|
|
|
@@ -118,6 +119,7 @@ export class BrowserRuntimeOwnership {
|
|
|
118
119
|
private readonly now: () => number;
|
|
119
120
|
private readonly beforeMetadataPublication?: () => Promise<void>;
|
|
120
121
|
private readonly afterLegacyLockProbe?: () => Promise<void>;
|
|
122
|
+
private readonly afterEmptyProcessCmdline?: (pid: number) => Promise<void>;
|
|
121
123
|
private readonly beforeGenerationRemoval?: (
|
|
122
124
|
reason: TOwnershipGenerationRemovalReason,
|
|
123
125
|
) => Promise<void>;
|
|
@@ -150,6 +152,7 @@ export class BrowserRuntimeOwnership {
|
|
|
150
152
|
this.now = optionsArg.testing?.now ?? Date.now;
|
|
151
153
|
this.beforeMetadataPublication = optionsArg.testing?.beforeMetadataPublication;
|
|
152
154
|
this.afterLegacyLockProbe = optionsArg.testing?.afterLegacyLockProbe;
|
|
155
|
+
this.afterEmptyProcessCmdline = optionsArg.testing?.afterEmptyProcessCmdline;
|
|
153
156
|
this.beforeGenerationRemoval = optionsArg.testing?.beforeGenerationRemoval;
|
|
154
157
|
this.onOwnershipLost = optionsArg.onOwnershipLost;
|
|
155
158
|
}
|
|
@@ -1098,7 +1101,8 @@ export class BrowserRuntimeOwnership {
|
|
|
1098
1101
|
continue;
|
|
1099
1102
|
}
|
|
1100
1103
|
if (cmdline.byteLength === 0) {
|
|
1101
|
-
|
|
1104
|
+
await this.afterEmptyProcessCmdline?.(pid);
|
|
1105
|
+
if (!await this.emptyCommandProcessIsClear(pid)) indeterminate = true;
|
|
1102
1106
|
continue;
|
|
1103
1107
|
}
|
|
1104
1108
|
let cmdlineText: string;
|
|
@@ -1204,15 +1208,28 @@ export class BrowserRuntimeOwnership {
|
|
|
1204
1208
|
return 'indeterminate';
|
|
1205
1209
|
}
|
|
1206
1210
|
|
|
1207
|
-
private async
|
|
1211
|
+
private async emptyCommandProcessIsClear(pidArg: number): Promise<boolean> {
|
|
1212
|
+
const processPath = plugins.path.join(this.procRoot, String(pidArg));
|
|
1208
1213
|
try {
|
|
1209
1214
|
const status = await this.readBoundedFile(
|
|
1210
|
-
plugins.path.join(
|
|
1215
|
+
plugins.path.join(processPath, 'status'),
|
|
1211
1216
|
64 * 1024,
|
|
1212
1217
|
);
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
return false;
|
|
1218
|
+
const uidState = this.parseProcessUidState(status);
|
|
1219
|
+
if (uidState === 'other') return true;
|
|
1220
|
+
if (uidState !== 'same') return false;
|
|
1221
|
+
const stateLines = status.split('\n').filter((line) => line.startsWith('State:'));
|
|
1222
|
+
return stateLines.length === 1 && /^State:[\t ]+Z(?:[\t ]|$)/u.test(stateLines[0]!);
|
|
1223
|
+
} catch (error) {
|
|
1224
|
+
if (!isMissingError(error)) return false;
|
|
1225
|
+
// An empty command line can precede process exit. A missing status file
|
|
1226
|
+
// alone is insufficient: the PID directory must also have disappeared.
|
|
1227
|
+
try {
|
|
1228
|
+
await plugins.fsPromises.lstat(processPath, { bigint: true });
|
|
1229
|
+
return false;
|
|
1230
|
+
} catch (statError) {
|
|
1231
|
+
return isMissingError(statError);
|
|
1232
|
+
}
|
|
1216
1233
|
}
|
|
1217
1234
|
}
|
|
1218
1235
|
|
package/ts/index.ts
CHANGED
|
@@ -10,7 +10,10 @@ export { BrowserRuntime, BrowserRuntimeLease } from './classes.runtime.js';
|
|
|
10
10
|
export { BrowserRuntimeError } from './errors.js';
|
|
11
11
|
export { createBrowserRuntimeMcpHttpHandler } from './mcp.js';
|
|
12
12
|
|
|
13
|
-
export type {
|
|
13
|
+
export type {
|
|
14
|
+
TAcquireBrowserRuntimeLeaseOptions,
|
|
15
|
+
IBrowserRuntimeLeaseRenewalOptions,
|
|
16
|
+
} from './classes.runtime.js';
|
|
14
17
|
export type { TBrowserRuntimeErrorCode } from './errors.js';
|
|
15
18
|
export type {
|
|
16
19
|
IAttachTrustedFramedPeerOptions,
|
|
@@ -48,6 +51,7 @@ export type {
|
|
|
48
51
|
IBrowserResourceKey,
|
|
49
52
|
IBrowserResourceRegistration,
|
|
50
53
|
IBrowserRuntimeState,
|
|
54
|
+
IBrowserRuntimeViewportResult,
|
|
51
55
|
IBrowserRuntimeTabState,
|
|
52
56
|
IBrowserScreenshotAction,
|
|
53
57
|
IBrowserScreenshotResult,
|
package/ts/interfaces.ts
CHANGED
|
@@ -83,7 +83,7 @@ export interface IBrowserFlexCapabilityBinding extends IBrowserCapabilityBinding
|
|
|
83
83
|
export interface IBrowserMcpCapabilityBinding extends IBrowserCapabilityBindingBase {
|
|
84
84
|
role: 'agent';
|
|
85
85
|
source: 'mcp';
|
|
86
|
-
sessionId:
|
|
86
|
+
sessionId: TQualifiedBrowserSessionId;
|
|
87
87
|
scopeId?: never;
|
|
88
88
|
channelId?: never;
|
|
89
89
|
runId?: never;
|
|
@@ -118,7 +118,7 @@ type TReadonlyBrowserCapabilityAuthorizationRequest =
|
|
|
118
118
|
readonly sessionId: Readonly<IBrowserFlexSessionId>;
|
|
119
119
|
})
|
|
120
120
|
| (Omit<Readonly<IBrowserMcpCapabilityBinding>, 'sessionId'> & {
|
|
121
|
-
readonly sessionId: Readonly<
|
|
121
|
+
readonly sessionId: Readonly<TQualifiedBrowserSessionId>;
|
|
122
122
|
});
|
|
123
123
|
|
|
124
124
|
export type TBrowserRuntimeOperationIdentity = TReadonlyBrowserCapabilityAuthorizationRequest & {
|
|
@@ -138,6 +138,12 @@ export type TBrowserRuntimeOperationClassification =
|
|
|
138
138
|
| 'tab'
|
|
139
139
|
| 'agent-action';
|
|
140
140
|
|
|
141
|
+
/** The viewport accepted by the shared resource, which may be smaller than one viewer's request. */
|
|
142
|
+
export interface IBrowserRuntimeViewportResult {
|
|
143
|
+
viewport: plugins.smartpuppeteer.ILiveBrowserViewport;
|
|
144
|
+
viewportRevision: number;
|
|
145
|
+
}
|
|
146
|
+
|
|
141
147
|
export type TBrowserRuntimeLeaseAuthority = TReadonlyBrowserCapabilityAuthorizationRequest & {
|
|
142
148
|
readonly runtimeAuthorityId: string;
|
|
143
149
|
readonly authorityGeneration: number;
|
|
@@ -503,7 +509,7 @@ extends Omit<
|
|
|
503
509
|
export interface IBrowserMcpAuthenticatedBinding extends IBrowserCapabilityBindingBase {
|
|
504
510
|
role: 'agent';
|
|
505
511
|
source: 'mcp';
|
|
506
|
-
sessionId:
|
|
512
|
+
sessionId: TQualifiedBrowserSessionId;
|
|
507
513
|
scopeId?: never;
|
|
508
514
|
channelId?: never;
|
|
509
515
|
}
|
package/ts/mcp.ts
CHANGED
|
@@ -231,7 +231,10 @@ const validateMcpBinding = (value: unknown): IBrowserMcpAuthenticatedBinding =>
|
|
|
231
231
|
throw new BrowserRuntimeError('CAPABILITY_INVALID');
|
|
232
232
|
}
|
|
233
233
|
const session = binding.sessionId as Record<string, unknown> | undefined;
|
|
234
|
-
if (session?.harnessId !== 'opencode'
|
|
234
|
+
if (session?.harnessId !== 'opencode' && session?.harnessId !== 'codex'
|
|
235
|
+
&& session?.harnessId !== 'flex') {
|
|
236
|
+
throw new BrowserRuntimeError('CAPABILITY_INVALID');
|
|
237
|
+
}
|
|
235
238
|
return {
|
|
236
239
|
projectId: validateBoundedString(binding.projectId, 'projectId', 1, 256),
|
|
237
240
|
browserResourceId: validateBoundedString(
|
|
@@ -257,7 +260,7 @@ const validateMcpBinding = (value: unknown): IBrowserMcpAuthenticatedBinding =>
|
|
|
257
260
|
peerId: validateBoundedString(binding.peerId, 'peerId', 1, 256),
|
|
258
261
|
source: 'mcp',
|
|
259
262
|
sessionId: {
|
|
260
|
-
harnessId:
|
|
263
|
+
harnessId: session.harnessId,
|
|
261
264
|
nativeId: validateBoundedString(session.nativeId, 'sessionId.nativeId', 1, 256),
|
|
262
265
|
},
|
|
263
266
|
};
|