@opengeni/runtime 3.3.0 → 3.4.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/dist/agent-LJT5NPWT.js +9 -0
- package/dist/assets/codemode-client.json +1 -1
- package/dist/browser-current-tab.d.ts +46 -0
- package/dist/browser-model-text.d.ts +126 -0
- package/dist/{chunk-XRX57ZQO.js → chunk-3DFH3ZHU.js} +784 -121
- package/dist/chunk-3DFH3ZHU.js.map +1 -0
- package/dist/{chunk-HJSIPTFA.js → chunk-4XDJ4TJA.js} +2 -2
- package/dist/{chunk-XQ23VCZ4.js → chunk-6FQ6KEII.js} +3 -3
- package/dist/{chunk-7LJ7KDPI.js → chunk-ERD4ICVB.js} +4 -3
- package/dist/{chunk-EK7IW2FR.js → chunk-ETTCGPBT.js} +224 -6
- package/dist/chunk-ETTCGPBT.js.map +1 -0
- package/dist/{chunk-7OUG7WBV.js → chunk-GWRBALGQ.js} +181 -13
- package/dist/chunk-GWRBALGQ.js.map +1 -0
- package/dist/{chunk-YG26XE7B.js → chunk-JYDG2A7H.js} +2 -2
- package/dist/{chunk-RSHQSLEJ.js → chunk-KIL4FGX5.js} +3 -3
- package/dist/{chunk-NWS4HPB7.js → chunk-MIAL5I4O.js} +2 -2
- package/dist/{chunk-Z5U6WE22.js → chunk-PRZPGRIK.js} +2 -2
- package/dist/{chunk-KCPW4K7L.js → chunk-PZQUUBEB.js} +2 -2
- package/dist/{chunk-5WJOPANS.js → chunk-Y5THZH5N.js} +7 -7
- package/dist/codex-tool-search.d.ts +9 -0
- package/dist/gmail-rest-mcp.js +8 -8
- package/dist/index.d.ts +3 -0
- package/dist/index.js +14 -12
- package/dist/interaction-tool-json-schema.d.ts +27 -0
- package/dist/{lazy-manifest-AJ6XPJ4F.js → lazy-manifest-BLZ3UZLX.js} +4 -4
- package/dist/lazy-tool-transport.d.ts +10 -0
- package/dist/{localSources-SSIEH5F5.js → localSources-I6SIQ6CX.js} +6 -6
- package/dist/model-call.js +3 -3
- package/dist/sandbox/browser-control-client.d.ts +77 -0
- package/dist/sandbox/index.d.ts +1 -1
- package/dist/sandbox/index.js +7 -7
- package/dist/sandbox/selfhosted/session.d.ts +3 -0
- package/dist/slack-rest-mcp.js +8 -8
- package/dist/workspace-tool-gateway.js +12 -12
- package/package.json +14 -14
- package/src/browser-current-tab.ts +139 -0
- package/src/browser-model-text.ts +378 -0
- package/src/codex-tool-search.ts +53 -0
- package/src/index.ts +39 -1
- package/src/interaction-tool-json-schema.ts +281 -0
- package/src/interaction-tools.ts +425 -235
- package/src/lazy-tool-transport.ts +229 -10
- package/src/model-input.ts +12 -1
- package/src/sandbox/browser-control-client.ts +336 -0
- package/src/sandbox/index.ts +4 -0
- package/src/sandbox/selfhosted/session.ts +38 -0
- package/dist/agent-CTPLA3HP.js +0 -9
- package/dist/browser-action-json-schema.d.ts +0 -4
- package/dist/chunk-7OUG7WBV.js.map +0 -1
- package/dist/chunk-EK7IW2FR.js.map +0 -1
- package/dist/chunk-XRX57ZQO.js.map +0 -1
- package/src/browser-action-json-schema.ts +0 -10
- /package/dist/{agent-CTPLA3HP.js.map → agent-LJT5NPWT.js.map} +0 -0
- /package/dist/{chunk-HJSIPTFA.js.map → chunk-4XDJ4TJA.js.map} +0 -0
- /package/dist/{chunk-XQ23VCZ4.js.map → chunk-6FQ6KEII.js.map} +0 -0
- /package/dist/{chunk-7LJ7KDPI.js.map → chunk-ERD4ICVB.js.map} +0 -0
- /package/dist/{chunk-YG26XE7B.js.map → chunk-JYDG2A7H.js.map} +0 -0
- /package/dist/{chunk-RSHQSLEJ.js.map → chunk-KIL4FGX5.js.map} +0 -0
- /package/dist/{chunk-NWS4HPB7.js.map → chunk-MIAL5I4O.js.map} +0 -0
- /package/dist/{chunk-Z5U6WE22.js.map → chunk-PRZPGRIK.js.map} +0 -0
- /package/dist/{chunk-KCPW4K7L.js.map → chunk-PZQUUBEB.js.map} +0 -0
- /package/dist/{chunk-5WJOPANS.js.map → chunk-Y5THZH5N.js.map} +0 -0
- /package/dist/{lazy-manifest-AJ6XPJ4F.js.map → lazy-manifest-BLZ3UZLX.js.map} +0 -0
- /package/dist/{localSources-SSIEH5F5.js.map → localSources-I6SIQ6CX.js.map} +0 -0
|
@@ -270,6 +270,8 @@ export type PlacementBrowserSessionReference = {
|
|
|
270
270
|
|
|
271
271
|
export type PlacementBrowserSession = PlacementBrowserSessionReference & {
|
|
272
272
|
observation: BrowserObservationValue;
|
|
273
|
+
/** The tab inventory at creation, when the controller reports it. */
|
|
274
|
+
targets?: BrowserTargetValue[];
|
|
273
275
|
};
|
|
274
276
|
|
|
275
277
|
export type PlacementComputerSessionReference = {
|
|
@@ -415,6 +417,73 @@ export type PlacementBrowserStateCaptureReceipt = PlacementBrowserSessionReferen
|
|
|
415
417
|
};
|
|
416
418
|
};
|
|
417
419
|
|
|
420
|
+
/** The exact controller authority a preserved working copy was launched
|
|
421
|
+
* under; the controller refuses any other. */
|
|
422
|
+
export type PlacementBrowserWorkingCopyAuthority = PlacementBrowserSessionReference & {
|
|
423
|
+
tokenGeneration: number;
|
|
424
|
+
controlToken: string;
|
|
425
|
+
viewToken: string;
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
export const BROWSER_WORKING_COPY_REFUSALS = [
|
|
429
|
+
"unsupported_platform",
|
|
430
|
+
"browser_running",
|
|
431
|
+
"working_copy_invalid",
|
|
432
|
+
"receipt_not_adoptable",
|
|
433
|
+
"authority_changed",
|
|
434
|
+
"process_state_unknown",
|
|
435
|
+
"adoption_not_needed",
|
|
436
|
+
"adoption_unresolved",
|
|
437
|
+
] as const;
|
|
438
|
+
export type PlacementBrowserWorkingCopyRefusal = (typeof BROWSER_WORKING_COPY_REFUSALS)[number];
|
|
439
|
+
|
|
440
|
+
export const BROWSER_WORKING_COPY_ADOPTION_PHASES = [
|
|
441
|
+
"intent",
|
|
442
|
+
"copied",
|
|
443
|
+
"receipt",
|
|
444
|
+
"source_preserved",
|
|
445
|
+
"adopted",
|
|
446
|
+
"interrupted",
|
|
447
|
+
"failed",
|
|
448
|
+
"collision",
|
|
449
|
+
"reverting",
|
|
450
|
+
"reverted",
|
|
451
|
+
] as const;
|
|
452
|
+
export type PlacementBrowserWorkingCopyAdoptionPhase =
|
|
453
|
+
(typeof BROWSER_WORKING_COPY_ADOPTION_PHASES)[number];
|
|
454
|
+
|
|
455
|
+
export type PlacementBrowserWorkingCopyAdoption = PlacementBrowserSessionReference & {
|
|
456
|
+
operationId: string;
|
|
457
|
+
manifestDigest: string;
|
|
458
|
+
phase: PlacementBrowserWorkingCopyAdoptionPhase;
|
|
459
|
+
failureCode: string | null;
|
|
460
|
+
/** Directories this adoption kept beside the browser's own, by name. */
|
|
461
|
+
retainedDirectories: string[];
|
|
462
|
+
createdAt: string;
|
|
463
|
+
updatedAt: string;
|
|
464
|
+
};
|
|
465
|
+
|
|
466
|
+
export type PlacementBrowserWorkingCopyInspection = PlacementBrowserSessionReference & {
|
|
467
|
+
platformSupported: boolean;
|
|
468
|
+
refusal: PlacementBrowserWorkingCopyRefusal | null;
|
|
469
|
+
/** Exact digest of the bytes an adoption would take; null when refused. */
|
|
470
|
+
manifest: { digest: string; entries: number; bytes: number; excluded: string[] } | null;
|
|
471
|
+
profileIdentityMatches: boolean;
|
|
472
|
+
/** false only when no process provably uses the profile. */
|
|
473
|
+
profileInUse: boolean | null;
|
|
474
|
+
receipt: {
|
|
475
|
+
operationId: string;
|
|
476
|
+
intent: "launch" | "suspend" | "retire" | "adopt";
|
|
477
|
+
state: string;
|
|
478
|
+
directoryLaunchAllowed: boolean;
|
|
479
|
+
authorityMatches: boolean;
|
|
480
|
+
/** True when this working copy was first launched from a saved checkpoint. */
|
|
481
|
+
launchedFromCheckpoint: boolean;
|
|
482
|
+
adoption: { operationId: string; manifestDigest: string } | null;
|
|
483
|
+
} | null;
|
|
484
|
+
activeAdoption: PlacementBrowserWorkingCopyAdoption | null;
|
|
485
|
+
};
|
|
486
|
+
|
|
418
487
|
export type ProvisionBrowserControlClientInput = {
|
|
419
488
|
adminToken: string;
|
|
420
489
|
adminTokenFile?: string;
|
|
@@ -652,6 +721,7 @@ export class BrowserControlClient {
|
|
|
652
721
|
return {
|
|
653
722
|
...returnedReference,
|
|
654
723
|
observation: BrowserObservation.parse(data.observation),
|
|
724
|
+
...creationTargets(data.targets, returnedReference),
|
|
655
725
|
};
|
|
656
726
|
}
|
|
657
727
|
|
|
@@ -882,6 +952,103 @@ export class BrowserControlClient {
|
|
|
882
952
|
return receipt;
|
|
883
953
|
}
|
|
884
954
|
|
|
955
|
+
/** Read-only evidence about a preserved working copy whose controller
|
|
956
|
+
* memory was lost: the exact digest of its bytes and whether it can be
|
|
957
|
+
* adopted. Hashing a large profile can take minutes. */
|
|
958
|
+
async inspectWorkingCopy(
|
|
959
|
+
input: PlacementBrowserWorkingCopyAuthority,
|
|
960
|
+
): Promise<PlacementBrowserWorkingCopyInspection> {
|
|
961
|
+
const reference = parseReference(input);
|
|
962
|
+
const data = await this.requestJson({
|
|
963
|
+
method: "POST",
|
|
964
|
+
path: `/v1/browser-sessions/${reference.browserSessionId}/working-copy/inspection`,
|
|
965
|
+
token: this.adminToken,
|
|
966
|
+
body: workingCopyAuthorityBody(reference, input),
|
|
967
|
+
timeoutMs: BROWSER_STATE_TRANSFER_TIMEOUT_MS,
|
|
968
|
+
});
|
|
969
|
+
return parseWorkingCopyInspection(data, reference);
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
/** Adopt the exact inspected bytes of a preserved working copy. A lost reply
|
|
973
|
+
* is checked with {@link workingCopyAdoption}. Sending the same operation id
|
|
974
|
+
* again never repeats a side effect: it only settles what that operation
|
|
975
|
+
* already did, under the authority that approved it. */
|
|
976
|
+
async adoptWorkingCopy(
|
|
977
|
+
input: PlacementBrowserWorkingCopyAuthority & { operationId: string; manifestDigest: string },
|
|
978
|
+
): Promise<PlacementBrowserWorkingCopyAdoption> {
|
|
979
|
+
const reference = parseReference(input);
|
|
980
|
+
const operationId = requireUuid(input.operationId, "working copy adoption id");
|
|
981
|
+
const data = await this.requestJson({
|
|
982
|
+
method: "POST",
|
|
983
|
+
path: `/v1/browser-sessions/${reference.browserSessionId}/working-copy/adoptions`,
|
|
984
|
+
token: this.adminToken,
|
|
985
|
+
body: {
|
|
986
|
+
...workingCopyAuthorityBody(reference, input),
|
|
987
|
+
operationId,
|
|
988
|
+
manifestDigest: sha256(input.manifestDigest, "working copy manifest digest"),
|
|
989
|
+
},
|
|
990
|
+
timeoutMs: BROWSER_STATE_TRANSFER_TIMEOUT_MS,
|
|
991
|
+
});
|
|
992
|
+
const adoption = parseWorkingCopyAdoption(data, reference, "current");
|
|
993
|
+
if (adoption.operationId !== operationId) {
|
|
994
|
+
throw new BrowserControlProtocolError("browser controller returned another adoption");
|
|
995
|
+
}
|
|
996
|
+
return adoption;
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
/** The recorded state of one adoption, read without changing it. */
|
|
1000
|
+
async workingCopyAdoption(
|
|
1001
|
+
reference: PlacementBrowserSessionReference,
|
|
1002
|
+
operationId: string,
|
|
1003
|
+
): Promise<{ inFlight: boolean; adoption: PlacementBrowserWorkingCopyAdoption | null }> {
|
|
1004
|
+
const binding = parseReference(reference);
|
|
1005
|
+
const id = requireUuid(operationId, "working copy adoption id");
|
|
1006
|
+
const data = await this.requestJson({
|
|
1007
|
+
method: "GET",
|
|
1008
|
+
path: `/v1/browser-sessions/${binding.browserSessionId}/working-copy/adoptions/${id}`,
|
|
1009
|
+
token: this.adminToken,
|
|
1010
|
+
});
|
|
1011
|
+
if (!isRecord(data) || typeof data.inFlight !== "boolean") {
|
|
1012
|
+
throw new BrowserControlProtocolError(
|
|
1013
|
+
"browser controller returned malformed adoption status",
|
|
1014
|
+
);
|
|
1015
|
+
}
|
|
1016
|
+
const adoption =
|
|
1017
|
+
data.adoption === null ? null : parseWorkingCopyAdoption(data.adoption, binding, "recorded");
|
|
1018
|
+
if (adoption && adoption.operationId !== id) {
|
|
1019
|
+
throw new BrowserControlProtocolError("browser controller returned another adoption");
|
|
1020
|
+
}
|
|
1021
|
+
return { inFlight: data.inFlight, adoption };
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
/** Revert one unfinished adoption under the browser's current authority:
|
|
1025
|
+
* its own directory goes back to the live path and the staged copy is
|
|
1026
|
+
* kept. Retrying the same revert finishes one that stopped part way. */
|
|
1027
|
+
async revertWorkingCopyAdoption(
|
|
1028
|
+
input: PlacementBrowserWorkingCopyAuthority & { operationId: string },
|
|
1029
|
+
): Promise<{ inFlight: boolean; adoption: PlacementBrowserWorkingCopyAdoption | null }> {
|
|
1030
|
+
const reference = parseReference(input);
|
|
1031
|
+
const id = requireUuid(input.operationId, "working copy adoption id");
|
|
1032
|
+
const data = await this.requestJson({
|
|
1033
|
+
method: "POST",
|
|
1034
|
+
path: `/v1/browser-sessions/${reference.browserSessionId}/working-copy/adoptions/${id}/revert`,
|
|
1035
|
+
token: this.adminToken,
|
|
1036
|
+
body: workingCopyAuthorityBody(reference, input),
|
|
1037
|
+
timeoutMs: BROWSER_STATE_TRANSFER_TIMEOUT_MS,
|
|
1038
|
+
});
|
|
1039
|
+
if (!isRecord(data) || typeof data.inFlight !== "boolean") {
|
|
1040
|
+
throw new BrowserControlProtocolError("browser controller returned malformed revert status");
|
|
1041
|
+
}
|
|
1042
|
+
const adoption =
|
|
1043
|
+
data.adoption === null
|
|
1044
|
+
? null
|
|
1045
|
+
: parseWorkingCopyAdoption(data.adoption, reference, "recorded");
|
|
1046
|
+
if (adoption && adoption.operationId !== id) {
|
|
1047
|
+
throw new BrowserControlProtocolError("browser controller returned another adoption");
|
|
1048
|
+
}
|
|
1049
|
+
return { inFlight: data.inFlight, adoption };
|
|
1050
|
+
}
|
|
1051
|
+
|
|
885
1052
|
sessionClient(input: {
|
|
886
1053
|
reference: PlacementBrowserSessionReference;
|
|
887
1054
|
controlToken: string;
|
|
@@ -2704,6 +2871,28 @@ function parseReference(value: unknown): PlacementBrowserSessionReference {
|
|
|
2704
2871
|
};
|
|
2705
2872
|
}
|
|
2706
2873
|
|
|
2874
|
+
/** A create's tab inventory is a convenience: an older controller omits it,
|
|
2875
|
+
* and an inventory that does not validate, or that belongs to another
|
|
2876
|
+
* binding, is dropped rather than failing a browser that did launch. */
|
|
2877
|
+
function creationTargets(
|
|
2878
|
+
value: unknown,
|
|
2879
|
+
reference: PlacementBrowserSessionReference,
|
|
2880
|
+
): { targets?: BrowserTargetValue[] } {
|
|
2881
|
+
if (!Array.isArray(value) || value.length > 10_000) return {};
|
|
2882
|
+
const targets: BrowserTargetValue[] = [];
|
|
2883
|
+
for (const entry of value) {
|
|
2884
|
+
const parsed = BrowserTarget.safeParse(entry);
|
|
2885
|
+
if (
|
|
2886
|
+
!parsed.success ||
|
|
2887
|
+
parsed.data.browserSessionId !== reference.browserSessionId ||
|
|
2888
|
+
parsed.data.controllerGeneration !== reference.controllerGeneration
|
|
2889
|
+
)
|
|
2890
|
+
return {};
|
|
2891
|
+
targets.push(parsed.data);
|
|
2892
|
+
}
|
|
2893
|
+
return { targets };
|
|
2894
|
+
}
|
|
2895
|
+
|
|
2707
2896
|
function parseComputerReference(value: unknown): PlacementComputerSessionReference {
|
|
2708
2897
|
if (!isRecord(value)) {
|
|
2709
2898
|
throw new BrowserControlProtocolError("computer session binding is invalid");
|
|
@@ -2879,6 +3068,140 @@ function boundedProxyUrl(value: string): string {
|
|
|
2879
3068
|
return url.toString();
|
|
2880
3069
|
}
|
|
2881
3070
|
|
|
3071
|
+
function workingCopyAuthorityBody(
|
|
3072
|
+
reference: PlacementBrowserSessionReference,
|
|
3073
|
+
input: PlacementBrowserWorkingCopyAuthority,
|
|
3074
|
+
) {
|
|
3075
|
+
return {
|
|
3076
|
+
controllerGeneration: reference.controllerGeneration,
|
|
3077
|
+
tokenGeneration: positiveSafeInteger(input.tokenGeneration, "token generation"),
|
|
3078
|
+
controlToken: requireToken(input.controlToken, "control token"),
|
|
3079
|
+
viewToken: requireToken(input.viewToken, "view token"),
|
|
3080
|
+
};
|
|
3081
|
+
}
|
|
3082
|
+
|
|
3083
|
+
/**
|
|
3084
|
+
* An adoption record. `generation: "current"` (a new adoption) requires the
|
|
3085
|
+
* record to belong to the requesting controller generation. `"recorded"`
|
|
3086
|
+
* (status, revert, inspection) keeps the generation the adoption was recorded
|
|
3087
|
+
* under: recovering an unfinished adoption after a controller restart means
|
|
3088
|
+
* reading and reverting a record made by an earlier generation, under the
|
|
3089
|
+
* browser's legitimate current control. The browser and operation always
|
|
3090
|
+
* have to match exactly.
|
|
3091
|
+
*/
|
|
3092
|
+
function parseWorkingCopyAdoption(
|
|
3093
|
+
value: unknown,
|
|
3094
|
+
reference: PlacementBrowserSessionReference,
|
|
3095
|
+
generation: "current" | "recorded",
|
|
3096
|
+
): PlacementBrowserWorkingCopyAdoption {
|
|
3097
|
+
if (
|
|
3098
|
+
!isRecord(value) ||
|
|
3099
|
+
value.browserSessionId !== reference.browserSessionId ||
|
|
3100
|
+
(generation === "current" && value.controllerGeneration !== reference.controllerGeneration) ||
|
|
3101
|
+
!BROWSER_WORKING_COPY_ADOPTION_PHASES.includes(
|
|
3102
|
+
value.phase as PlacementBrowserWorkingCopyAdoptionPhase,
|
|
3103
|
+
) ||
|
|
3104
|
+
!(value.failureCode === null || typeof value.failureCode === "string") ||
|
|
3105
|
+
!Array.isArray(value.retainedDirectories) ||
|
|
3106
|
+
value.retainedDirectories.length > 64 ||
|
|
3107
|
+
!value.retainedDirectories.every(
|
|
3108
|
+
(name) => typeof name === "string" && /^[A-Za-z0-9][A-Za-z0-9._-]{0,255}$/u.test(name),
|
|
3109
|
+
)
|
|
3110
|
+
) {
|
|
3111
|
+
throw new BrowserControlProtocolError("browser controller returned a malformed adoption");
|
|
3112
|
+
}
|
|
3113
|
+
return {
|
|
3114
|
+
browserSessionId: reference.browserSessionId,
|
|
3115
|
+
controllerGeneration:
|
|
3116
|
+
generation === "current"
|
|
3117
|
+
? reference.controllerGeneration
|
|
3118
|
+
: requireGeneration(value.controllerGeneration),
|
|
3119
|
+
operationId: requireUuid(value.operationId, "working copy adoption id"),
|
|
3120
|
+
manifestDigest: sha256(value.manifestDigest, "working copy manifest digest"),
|
|
3121
|
+
phase: value.phase as PlacementBrowserWorkingCopyAdoptionPhase,
|
|
3122
|
+
failureCode:
|
|
3123
|
+
value.failureCode === null ? null : requireOpaqueId(value.failureCode, "failure code"),
|
|
3124
|
+
retainedDirectories: value.retainedDirectories as string[],
|
|
3125
|
+
createdAt: timestamp(value.createdAt, "adoption created at"),
|
|
3126
|
+
updatedAt: timestamp(value.updatedAt, "adoption updated at"),
|
|
3127
|
+
};
|
|
3128
|
+
}
|
|
3129
|
+
|
|
3130
|
+
function parseWorkingCopyInspection(
|
|
3131
|
+
value: unknown,
|
|
3132
|
+
reference: PlacementBrowserSessionReference,
|
|
3133
|
+
): PlacementBrowserWorkingCopyInspection {
|
|
3134
|
+
if (
|
|
3135
|
+
!isRecord(value) ||
|
|
3136
|
+
value.browserSessionId !== reference.browserSessionId ||
|
|
3137
|
+
value.controllerGeneration !== reference.controllerGeneration ||
|
|
3138
|
+
typeof value.platformSupported !== "boolean" ||
|
|
3139
|
+
typeof value.profileIdentityMatches !== "boolean" ||
|
|
3140
|
+
!(value.profileInUse === null || typeof value.profileInUse === "boolean") ||
|
|
3141
|
+
!(
|
|
3142
|
+
value.refusal === null ||
|
|
3143
|
+
BROWSER_WORKING_COPY_REFUSALS.includes(value.refusal as PlacementBrowserWorkingCopyRefusal)
|
|
3144
|
+
)
|
|
3145
|
+
) {
|
|
3146
|
+
throw new BrowserControlProtocolError("browser controller returned a malformed inspection");
|
|
3147
|
+
}
|
|
3148
|
+
let manifest: PlacementBrowserWorkingCopyInspection["manifest"] = null;
|
|
3149
|
+
if (value.manifest !== null) {
|
|
3150
|
+
if (!isRecord(value.manifest)) {
|
|
3151
|
+
throw new BrowserControlProtocolError("browser controller returned a malformed manifest");
|
|
3152
|
+
}
|
|
3153
|
+
manifest = {
|
|
3154
|
+
digest: sha256(value.manifest.digest, "working copy manifest digest"),
|
|
3155
|
+
entries: nonnegativeSafeInteger(value.manifest.entries, "working copy entries"),
|
|
3156
|
+
bytes: nonnegativeSafeInteger(value.manifest.bytes, "working copy bytes"),
|
|
3157
|
+
excluded: excludedWorkingCopyEntries(value.manifest.excluded),
|
|
3158
|
+
};
|
|
3159
|
+
}
|
|
3160
|
+
let receipt: PlacementBrowserWorkingCopyInspection["receipt"] = null;
|
|
3161
|
+
if (value.receipt !== null) {
|
|
3162
|
+
const raw = value.receipt;
|
|
3163
|
+
if (
|
|
3164
|
+
!isRecord(raw) ||
|
|
3165
|
+
!["launch", "suspend", "retire", "adopt"].includes(raw.intent as string) ||
|
|
3166
|
+
typeof raw.state !== "string" ||
|
|
3167
|
+
typeof raw.directoryLaunchAllowed !== "boolean" ||
|
|
3168
|
+
typeof raw.authorityMatches !== "boolean" ||
|
|
3169
|
+
!(raw.restoreAuthorityDigest === null || typeof raw.restoreAuthorityDigest === "string") ||
|
|
3170
|
+
!(raw.adoption === null || isRecord(raw.adoption))
|
|
3171
|
+
) {
|
|
3172
|
+
throw new BrowserControlProtocolError("browser controller returned a malformed receipt");
|
|
3173
|
+
}
|
|
3174
|
+
receipt = {
|
|
3175
|
+
operationId: requireUuid(raw.operationId, "working runtime receipt id"),
|
|
3176
|
+
intent: raw.intent as "launch" | "suspend" | "retire" | "adopt",
|
|
3177
|
+
state: requireOpaqueId(raw.state, "working runtime receipt state"),
|
|
3178
|
+
directoryLaunchAllowed: raw.directoryLaunchAllowed,
|
|
3179
|
+
authorityMatches: raw.authorityMatches,
|
|
3180
|
+
launchedFromCheckpoint: raw.restoreAuthorityDigest !== null,
|
|
3181
|
+
adoption: isRecord(raw.adoption)
|
|
3182
|
+
? {
|
|
3183
|
+
operationId: requireUuid(raw.adoption.operationId, "working copy adoption id"),
|
|
3184
|
+
manifestDigest: sha256(raw.adoption.manifestDigest, "working copy manifest digest"),
|
|
3185
|
+
}
|
|
3186
|
+
: null,
|
|
3187
|
+
};
|
|
3188
|
+
}
|
|
3189
|
+
return {
|
|
3190
|
+
browserSessionId: reference.browserSessionId,
|
|
3191
|
+
controllerGeneration: reference.controllerGeneration,
|
|
3192
|
+
platformSupported: value.platformSupported,
|
|
3193
|
+
refusal: value.refusal as PlacementBrowserWorkingCopyRefusal | null,
|
|
3194
|
+
manifest,
|
|
3195
|
+
profileIdentityMatches: value.profileIdentityMatches,
|
|
3196
|
+
profileInUse: value.profileInUse,
|
|
3197
|
+
receipt,
|
|
3198
|
+
activeAdoption:
|
|
3199
|
+
value.activeAdoption === null || value.activeAdoption === undefined
|
|
3200
|
+
? null
|
|
3201
|
+
: parseWorkingCopyAdoption(value.activeAdoption, reference, "recorded"),
|
|
3202
|
+
};
|
|
3203
|
+
}
|
|
3204
|
+
|
|
2882
3205
|
function parseStateCaptureReceipt(value: unknown): PlacementBrowserStateCaptureReceipt {
|
|
2883
3206
|
if (!isRecord(value) || !isRecord(value.manifest)) {
|
|
2884
3207
|
throw new BrowserControlProtocolError(
|
|
@@ -3687,6 +4010,19 @@ function nonnegativeSafeInteger(value: unknown, label: string): number {
|
|
|
3687
4010
|
return value;
|
|
3688
4011
|
}
|
|
3689
4012
|
|
|
4013
|
+
function excludedWorkingCopyEntries(value: unknown): string[] {
|
|
4014
|
+
if (
|
|
4015
|
+
!Array.isArray(value) ||
|
|
4016
|
+
value.length > 16 ||
|
|
4017
|
+
!value.every((entry) => typeof entry === "string" && entry.length > 0 && entry.length <= 256)
|
|
4018
|
+
) {
|
|
4019
|
+
throw new BrowserControlProtocolError(
|
|
4020
|
+
"browser controller returned malformed working copy exclusions",
|
|
4021
|
+
);
|
|
4022
|
+
}
|
|
4023
|
+
return [...value];
|
|
4024
|
+
}
|
|
4025
|
+
|
|
3690
4026
|
function parseUnsignedInteger(value: string, label: string): number {
|
|
3691
4027
|
const trimmed = value.trim();
|
|
3692
4028
|
if (!/^(0|[1-9][0-9]*)$/u.test(trimmed)) {
|
package/src/sandbox/index.ts
CHANGED
|
@@ -361,6 +361,10 @@ export {
|
|
|
361
361
|
type PlacementBrowserNetworkRoute,
|
|
362
362
|
type PlacementBrowserTransport,
|
|
363
363
|
type PlacementBrowserStateCaptureReceipt,
|
|
364
|
+
type PlacementBrowserWorkingCopyAdoption,
|
|
365
|
+
type PlacementBrowserWorkingCopyAuthority,
|
|
366
|
+
type PlacementBrowserWorkingCopyInspection,
|
|
367
|
+
type PlacementBrowserWorkingCopyRefusal,
|
|
364
368
|
type ComputerControlFrame,
|
|
365
369
|
type ComputerControlFrameMetadata,
|
|
366
370
|
type ComputerFrameEvidenceMismatchReason,
|
|
@@ -284,6 +284,9 @@ export interface SelfhostedBackgroundCommandAdoption {
|
|
|
284
284
|
connectionInstanceId: string;
|
|
285
285
|
opId: string;
|
|
286
286
|
command: string;
|
|
287
|
+
/** The exec already failed because the machine stopped answering. Record it
|
|
288
|
+
* with a stop request instead of as a running background command. */
|
|
289
|
+
abandoned?: boolean;
|
|
287
290
|
}
|
|
288
291
|
|
|
289
292
|
/** Exact command-admission snapshot. A worker resolves this immediately before
|
|
@@ -1359,6 +1362,34 @@ export class SelfhostedSession {
|
|
|
1359
1362
|
reason: null,
|
|
1360
1363
|
retryable: false,
|
|
1361
1364
|
});
|
|
1365
|
+
if (
|
|
1366
|
+
!terminalProof &&
|
|
1367
|
+
!adoptedCommandId &&
|
|
1368
|
+
!controlError.neverSent &&
|
|
1369
|
+
machineStoppedAnswering(controlError) &&
|
|
1370
|
+
this.adoptBackgroundCommand
|
|
1371
|
+
) {
|
|
1372
|
+
// The machine went away mid-operation. The command may still run there,
|
|
1373
|
+
// but only the machine can stop or report it, so this turn must not wait
|
|
1374
|
+
// for it. Hand it to the session's command ledger with a stop request;
|
|
1375
|
+
// the reconciler stops or settles it once the machine returns or its
|
|
1376
|
+
// runner is retired. If recording fails, turn cleanup keeps ownership.
|
|
1377
|
+
try {
|
|
1378
|
+
notifyDurableOpOwnershipTransferStarted(opId);
|
|
1379
|
+
const abandoned = await this.adoptBackgroundCommand({
|
|
1380
|
+
controlWorkspaceId: admission.controlWorkspaceId,
|
|
1381
|
+
enrollmentId: this.agentId,
|
|
1382
|
+
connectionInstanceId: admission.connectionInstanceId,
|
|
1383
|
+
opId,
|
|
1384
|
+
command,
|
|
1385
|
+
abandoned: true,
|
|
1386
|
+
});
|
|
1387
|
+
adoptedCommandId = abandoned.commandId;
|
|
1388
|
+
notifyDurableOpOwnershipTransferred(opId);
|
|
1389
|
+
} catch {
|
|
1390
|
+
notifyDurableOpOwnershipTransferFailed(opId);
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1362
1393
|
this.emitOp({
|
|
1363
1394
|
op: "exec",
|
|
1364
1395
|
outcome: "failed",
|
|
@@ -2703,6 +2734,13 @@ function mediaTypeFromPath(path: string): string | undefined {
|
|
|
2703
2734
|
|
|
2704
2735
|
/** A random uint64-safe numeric nonce (the wire `PingRequest.nonce` is a uint64,
|
|
2705
2736
|
* represented as a numeric string by ts-proto). */
|
|
2737
|
+
/** The machine itself stopped answering (offline, reconnecting past the hold
|
|
2738
|
+
* window, or draining), as opposed to an answer that the operation failed. */
|
|
2739
|
+
function machineStoppedAnswering(error: SelfhostedControlError): boolean {
|
|
2740
|
+
const faultClass = selfhostedFaultClass(error);
|
|
2741
|
+
return faultClass === "offline" || faultClass === "reconnecting" || faultClass === "draining";
|
|
2742
|
+
}
|
|
2743
|
+
|
|
2706
2744
|
function randomNonce(): string {
|
|
2707
2745
|
// 2^53-safe random integer as a decimal string.
|
|
2708
2746
|
return String(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER));
|
package/dist/agent-CTPLA3HP.js
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { AttemptToolJsonSchema } from "@opengeni/contracts";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
/** Keep repeated browser action and locator variants once in the model schema. */
|
|
4
|
-
export declare function browserActionInputJsonSchema(schema: z.ZodType): AttemptToolJsonSchema;
|