@opengeni/runtime 0.7.0 → 0.7.1
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/index.d.ts +4 -1
- package/dist/index.js +99 -30
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +131 -39
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeni/runtime",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"@openai/agents": "0.13.3",
|
|
40
40
|
"@openai/agents-extensions": "0.13.3",
|
|
41
41
|
"@opengeni/agent-proto": "^0.3.0",
|
|
42
|
-
"@opengeni/codex": "^0.2.
|
|
43
|
-
"@opengeni/config": "^0.5.
|
|
42
|
+
"@opengeni/codex": "^0.2.3",
|
|
43
|
+
"@opengeni/config": "^0.5.1",
|
|
44
44
|
"@opengeni/contracts": "^0.10.0",
|
|
45
45
|
"modal": "0.7.6",
|
|
46
46
|
"openai": "6.47.0"
|
package/src/index.ts
CHANGED
|
@@ -249,7 +249,12 @@ export type ResolveConnectionCredentialInput = {
|
|
|
249
249
|
};
|
|
250
250
|
|
|
251
251
|
export type ResolveConnectionCredentialResult =
|
|
252
|
-
| {
|
|
252
|
+
| {
|
|
253
|
+
status: "ok";
|
|
254
|
+
headers: Record<string, string>;
|
|
255
|
+
connectionId: string;
|
|
256
|
+
expiresAt?: Date | null;
|
|
257
|
+
}
|
|
253
258
|
| {
|
|
254
259
|
status: "auth_needed";
|
|
255
260
|
reason: ToolAuthNeededPayload["reason"];
|
|
@@ -1070,7 +1075,6 @@ export type WorkspaceEnvironmentContext = {
|
|
|
1070
1075
|
|
|
1071
1076
|
export type PersistentSessionSettings = {
|
|
1072
1077
|
titleIsSet: boolean;
|
|
1073
|
-
childNotificationsMode?: "digest" | "passive";
|
|
1074
1078
|
};
|
|
1075
1079
|
|
|
1076
1080
|
/**
|
|
@@ -1181,13 +1185,7 @@ export function appendPersistentSessionSettings(
|
|
|
1181
1185
|
if (!settings) {
|
|
1182
1186
|
return composed;
|
|
1183
1187
|
}
|
|
1184
|
-
|
|
1185
|
-
? `; spawned-worker completion notifications are ${settings.childNotificationsMode}`
|
|
1186
|
-
: "";
|
|
1187
|
-
const persistentTools = settings.childNotificationsMode
|
|
1188
|
-
? "opengeni__set_session_title or opengeni__set_child_notifications_mode"
|
|
1189
|
-
: "opengeni__set_session_title";
|
|
1190
|
-
return `${composed} Persistent session settings already in effect: the display title is ${settings.titleIsSet ? "set" : "not set"}${childState}. These settings persist across turns, continuations, and interruptions. Do not call ${persistentTools} merely to reassert an unchanged value; call them only when the current value actually needs to change.`;
|
|
1188
|
+
return `${composed} Persistent session settings already in effect: the display title is ${settings.titleIsSet ? "set" : "not set"}. This setting persists across turns, continuations, and interruptions. Do not call opengeni__set_session_title merely to reassert an unchanged value; call it only when the current value actually needs to change.`;
|
|
1191
1189
|
}
|
|
1192
1190
|
|
|
1193
1191
|
/**
|
|
@@ -1511,7 +1509,10 @@ function mcpToolRequiresApproval(policy: boolean | string[], unprefixedName: str
|
|
|
1511
1509
|
}
|
|
1512
1510
|
|
|
1513
1511
|
/** A per-server approval policy keyed by the server's `<id>__` tool prefix. */
|
|
1514
|
-
type McpApprovalPolicy = {
|
|
1512
|
+
type McpApprovalPolicy = {
|
|
1513
|
+
prefix: string;
|
|
1514
|
+
requireApproval: boolean | string[];
|
|
1515
|
+
};
|
|
1515
1516
|
|
|
1516
1517
|
/** The subset of the agent surface the approval wrap needs — including `clone`. */
|
|
1517
1518
|
type ApprovalCapableAgent = {
|
|
@@ -1829,6 +1830,9 @@ export type PrepareToolsOptions = {
|
|
|
1829
1830
|
// The calling turn's id, signed into the token so tools can classify the
|
|
1830
1831
|
// caller from its own identity instead of the session's live active pointer.
|
|
1831
1832
|
turnId?: string;
|
|
1833
|
+
// The exact executing attempt that owns the MCP call.
|
|
1834
|
+
attemptId?: string;
|
|
1835
|
+
executionGeneration?: number;
|
|
1832
1836
|
subjectId?: string;
|
|
1833
1837
|
subjectLabel?: string;
|
|
1834
1838
|
// Overrides the fixed first-party MCP permission set for this session's
|
|
@@ -2134,7 +2138,9 @@ async function authNeededFetchResponse(
|
|
|
2134
2138
|
if (request.method === "tools/call") {
|
|
2135
2139
|
return mcpToolAuthNeededResponse(request.id);
|
|
2136
2140
|
}
|
|
2137
|
-
return new Response("Authentication required for MCP server connection", {
|
|
2141
|
+
return new Response("Authentication required for MCP server connection", {
|
|
2142
|
+
status: 401,
|
|
2143
|
+
});
|
|
2138
2144
|
}
|
|
2139
2145
|
|
|
2140
2146
|
async function publishAuthNeeded(
|
|
@@ -2295,7 +2301,10 @@ function mcpToolUnavailableMessage(reason: string): string {
|
|
|
2295
2301
|
// transport error carries the raw response BODY in its `.message` (a broker
|
|
2296
2302
|
// 401/403 body can echo request detail), so `.message` is never included; the
|
|
2297
2303
|
// numeric `.code`/`.status` (e.g. 401) is safe and useful.
|
|
2298
|
-
function safeMcpErrorFields(error: unknown): {
|
|
2304
|
+
function safeMcpErrorFields(error: unknown): {
|
|
2305
|
+
errorClass: string;
|
|
2306
|
+
status?: number;
|
|
2307
|
+
} {
|
|
2299
2308
|
const errorClass = error instanceof Error ? error.constructor.name : typeof error;
|
|
2300
2309
|
const raw = (error as { code?: unknown; status?: unknown } | null)?.code;
|
|
2301
2310
|
const status = typeof raw === "number" ? raw : undefined;
|
|
@@ -2383,6 +2392,8 @@ async function signFirstPartyDelegatedBearer(
|
|
|
2383
2392
|
permissions: options.firstPartyPermissions ?? firstPartyMcpPermissions,
|
|
2384
2393
|
...(options.sessionId ? { sessionId: options.sessionId } : {}),
|
|
2385
2394
|
...(options.turnId ? { turnId: options.turnId } : {}),
|
|
2395
|
+
...(options.attemptId ? { attemptId: options.attemptId } : {}),
|
|
2396
|
+
...(options.executionGeneration ? { executionGeneration: options.executionGeneration } : {}),
|
|
2386
2397
|
exp: Math.floor(Date.now() / 1000) + 60 * 60,
|
|
2387
2398
|
});
|
|
2388
2399
|
}
|
|
@@ -2635,7 +2646,10 @@ class PrefixedMcpServer implements MCPServer {
|
|
|
2635
2646
|
}
|
|
2636
2647
|
return tools
|
|
2637
2648
|
.filter((tool) => this.isAllowed(tool.name))
|
|
2638
|
-
.map((tool) => ({
|
|
2649
|
+
.map((tool) => ({
|
|
2650
|
+
...tool,
|
|
2651
|
+
name: prefixedMcpToolName(this.name, tool.name),
|
|
2652
|
+
}));
|
|
2639
2653
|
}
|
|
2640
2654
|
|
|
2641
2655
|
async callTool(
|
|
@@ -2657,7 +2671,10 @@ class PrefixedMcpServer implements MCPServer {
|
|
|
2657
2671
|
// This applies to ANY server — an auth-needed is recoverable once the user
|
|
2658
2672
|
// re-links, so even a required tool degrades gracefully here.
|
|
2659
2673
|
if (isAuthNeededMcpError(error)) {
|
|
2660
|
-
return {
|
|
2674
|
+
return {
|
|
2675
|
+
isError: true,
|
|
2676
|
+
content: [{ type: "text", text: MCP_AUTH_NEEDED_MESSAGE }],
|
|
2677
|
+
};
|
|
2661
2678
|
}
|
|
2662
2679
|
// Best-effort INVOCATION isolation (sibling to the listTools guard). When
|
|
2663
2680
|
// the model calls a best-effort server's tool and the call throws for ANY
|
|
@@ -2679,7 +2696,12 @@ class PrefixedMcpServer implements MCPServer {
|
|
|
2679
2696
|
);
|
|
2680
2697
|
return {
|
|
2681
2698
|
isError: true,
|
|
2682
|
-
content: [
|
|
2699
|
+
content: [
|
|
2700
|
+
{
|
|
2701
|
+
type: "text",
|
|
2702
|
+
text: mcpToolUnavailableMessage(mcpErrorReason(fields)),
|
|
2703
|
+
},
|
|
2704
|
+
],
|
|
2683
2705
|
};
|
|
2684
2706
|
}
|
|
2685
2707
|
throw error;
|
|
@@ -2815,6 +2837,8 @@ export async function prepareRunInput(
|
|
|
2815
2837
|
}
|
|
2816
2838
|
|
|
2817
2839
|
export type RunAgentStreamOptions = {
|
|
2840
|
+
/** Abort the provider/tool loop when the owning activity is cancelled. */
|
|
2841
|
+
signal?: AbortSignal;
|
|
2818
2842
|
sandboxClient?: unknown;
|
|
2819
2843
|
sandboxEnvironment?: Record<string, string>;
|
|
2820
2844
|
onRuntimeEvent?: (event: NormalizedRuntimeEvent) => Promise<void> | void;
|
|
@@ -3129,10 +3153,14 @@ export async function runAgentStream(
|
|
|
3129
3153
|
overrides.contextCompactionSignalTokens || overrides.contextCompactionRequested,
|
|
3130
3154
|
),
|
|
3131
3155
|
...(overrides.contextCompactionSignalTokens
|
|
3132
|
-
? {
|
|
3156
|
+
? {
|
|
3157
|
+
contextCompactionSignalTokens: overrides.contextCompactionSignalTokens,
|
|
3158
|
+
}
|
|
3133
3159
|
: {}),
|
|
3134
3160
|
...(overrides.contextCompactionRequested
|
|
3135
|
-
? {
|
|
3161
|
+
? {
|
|
3162
|
+
contextCompactionRequested: overrides.contextCompactionRequested,
|
|
3163
|
+
}
|
|
3136
3164
|
: {}),
|
|
3137
3165
|
}),
|
|
3138
3166
|
genesisTitleInputFilter,
|
|
@@ -3143,6 +3171,7 @@ export async function runAgentStream(
|
|
|
3143
3171
|
stream: true,
|
|
3144
3172
|
maxTurns: settings.agentMaxModelCallsPerTurn,
|
|
3145
3173
|
callModelInputFilter: ownedFilter,
|
|
3174
|
+
...(overrides.signal ? { signal: overrides.signal } : {}),
|
|
3146
3175
|
};
|
|
3147
3176
|
ownedRunOptions.sandbox = {
|
|
3148
3177
|
client: decoratedClient,
|
|
@@ -3215,7 +3244,9 @@ export async function runAgentStream(
|
|
|
3215
3244
|
overrides.contextCompactionSignalTokens || overrides.contextCompactionRequested,
|
|
3216
3245
|
),
|
|
3217
3246
|
...(overrides.contextCompactionSignalTokens
|
|
3218
|
-
? {
|
|
3247
|
+
? {
|
|
3248
|
+
contextCompactionSignalTokens: overrides.contextCompactionSignalTokens,
|
|
3249
|
+
}
|
|
3219
3250
|
: {}),
|
|
3220
3251
|
...(overrides.contextCompactionRequested
|
|
3221
3252
|
? { contextCompactionRequested: overrides.contextCompactionRequested }
|
|
@@ -3233,6 +3264,7 @@ export async function runAgentStream(
|
|
|
3233
3264
|
// raise the proactive compaction signal. This runs for turn-start replay AND
|
|
3234
3265
|
// every mid-turn follow-up.
|
|
3235
3266
|
callModelInputFilter,
|
|
3267
|
+
...(overrides.signal ? { signal: overrides.signal } : {}),
|
|
3236
3268
|
};
|
|
3237
3269
|
if (client) {
|
|
3238
3270
|
runOptions.sandbox = {
|
|
@@ -3282,7 +3314,9 @@ function appendSandboxFileDownloadFailureNote(
|
|
|
3282
3314
|
* default runner. setDefaultModelProvider remains only as a boot-time fallback.
|
|
3283
3315
|
*/
|
|
3284
3316
|
function runScopedRunner(settings: Settings): Runner {
|
|
3285
|
-
return new Runner({
|
|
3317
|
+
return new Runner({
|
|
3318
|
+
modelProvider: new MultiProviderModelProvider(settings),
|
|
3319
|
+
});
|
|
3286
3320
|
}
|
|
3287
3321
|
|
|
3288
3322
|
export { MaxTurnsExceededError } from "@openai/agents";
|
|
@@ -3338,7 +3372,9 @@ export function withManifestRefreshOnResume(
|
|
|
3338
3372
|
? { supportsDefaultOptions: client.supportsDefaultOptions }
|
|
3339
3373
|
: {}),
|
|
3340
3374
|
...(client.create
|
|
3341
|
-
? {
|
|
3375
|
+
? {
|
|
3376
|
+
create: async (...args: any[]) => await (client.create as any)(...args),
|
|
3377
|
+
}
|
|
3342
3378
|
: {}),
|
|
3343
3379
|
resume: async (state: SandboxSessionState) => {
|
|
3344
3380
|
const session = await client.resume!(state);
|
|
@@ -3346,7 +3382,9 @@ export function withManifestRefreshOnResume(
|
|
|
3346
3382
|
return session;
|
|
3347
3383
|
},
|
|
3348
3384
|
...(client.delete
|
|
3349
|
-
? {
|
|
3385
|
+
? {
|
|
3386
|
+
delete: async (state: SandboxSessionState) => await client.delete!(state),
|
|
3387
|
+
}
|
|
3350
3388
|
: {}),
|
|
3351
3389
|
...(client.serializeSessionState
|
|
3352
3390
|
? {
|
|
@@ -3395,7 +3433,11 @@ export async function applyMissingManifestEntries(
|
|
|
3395
3433
|
state?: {
|
|
3396
3434
|
manifest?:
|
|
3397
3435
|
| Manifest
|
|
3398
|
-
| {
|
|
3436
|
+
| {
|
|
3437
|
+
root?: string;
|
|
3438
|
+
entries?: Record<string, any>;
|
|
3439
|
+
environment?: Record<string, any>;
|
|
3440
|
+
};
|
|
3399
3441
|
};
|
|
3400
3442
|
}
|
|
3401
3443
|
).state?.manifest;
|
|
@@ -3505,7 +3547,11 @@ export function manifestEnvironmentDrift(
|
|
|
3505
3547
|
if (added.length === 0 && removed.length === 0 && changed.length === 0) {
|
|
3506
3548
|
return null;
|
|
3507
3549
|
}
|
|
3508
|
-
return {
|
|
3550
|
+
return {
|
|
3551
|
+
added: added.sort(),
|
|
3552
|
+
removed: removed.sort(),
|
|
3553
|
+
changed: changed.sort(),
|
|
3554
|
+
};
|
|
3509
3555
|
}
|
|
3510
3556
|
|
|
3511
3557
|
async function reportManifestEnvironmentDrift(
|
|
@@ -3520,7 +3566,10 @@ async function reportManifestEnvironmentDrift(
|
|
|
3520
3566
|
// Reporting must never break a resume: the drift itself is benign under the
|
|
3521
3567
|
// env pin (the box keeps running on its baked env); only the SIGNAL matters.
|
|
3522
3568
|
try {
|
|
3523
|
-
await context.onRuntimeEvent?.({
|
|
3569
|
+
await context.onRuntimeEvent?.({
|
|
3570
|
+
type: "sandbox.env.drift",
|
|
3571
|
+
payload: drift,
|
|
3572
|
+
});
|
|
3524
3573
|
} catch {
|
|
3525
3574
|
// Swallow: a failed emit must not fail the turn.
|
|
3526
3575
|
}
|
|
@@ -3549,7 +3598,11 @@ export async function pinProvidedSessionManifestEnvironment(
|
|
|
3549
3598
|
state?: {
|
|
3550
3599
|
manifest?:
|
|
3551
3600
|
| Manifest
|
|
3552
|
-
| {
|
|
3601
|
+
| {
|
|
3602
|
+
root?: string;
|
|
3603
|
+
entries?: Record<string, any>;
|
|
3604
|
+
environment?: Record<string, any>;
|
|
3605
|
+
};
|
|
3553
3606
|
};
|
|
3554
3607
|
}
|
|
3555
3608
|
).state?.manifest;
|
|
@@ -3732,7 +3785,9 @@ export function withSandboxFileDownloads(
|
|
|
3732
3785
|
}
|
|
3733
3786
|
: {}),
|
|
3734
3787
|
...(client.delete
|
|
3735
|
-
? {
|
|
3788
|
+
? {
|
|
3789
|
+
delete: async (state: SandboxSessionState) => await client.delete!(state),
|
|
3790
|
+
}
|
|
3736
3791
|
: {}),
|
|
3737
3792
|
...(client.serializeSessionState
|
|
3738
3793
|
? {
|
|
@@ -3935,7 +3990,11 @@ function structuredImageToDataUrl(value: unknown): string | null {
|
|
|
3935
3990
|
if (v.type !== "image" || !v.image || typeof v.image !== "object") {
|
|
3936
3991
|
return null;
|
|
3937
3992
|
}
|
|
3938
|
-
const image = v.image as {
|
|
3993
|
+
const image = v.image as {
|
|
3994
|
+
data?: unknown;
|
|
3995
|
+
mediaType?: unknown;
|
|
3996
|
+
url?: unknown;
|
|
3997
|
+
};
|
|
3939
3998
|
if (typeof image.url === "string" && image.url.length > 0) {
|
|
3940
3999
|
return image.url;
|
|
3941
4000
|
}
|
|
@@ -4002,7 +4061,10 @@ export function normalizeSdkEvent(event: RunStreamEvent): NormalizedRuntimeEvent
|
|
|
4002
4061
|
return out;
|
|
4003
4062
|
}
|
|
4004
4063
|
if (event.type === "agent_updated_stream_event") {
|
|
4005
|
-
out.push({
|
|
4064
|
+
out.push({
|
|
4065
|
+
type: "agent.updated",
|
|
4066
|
+
payload: { agent: (event as any).agent?.name ?? null },
|
|
4067
|
+
});
|
|
4006
4068
|
return out;
|
|
4007
4069
|
}
|
|
4008
4070
|
if (event.type !== "run_item_stream_event") {
|
|
@@ -4164,7 +4226,9 @@ function inputTokenDetailsProp(raw: Record<string, unknown>): Partial<ModelRespo
|
|
|
4164
4226
|
if (!details || typeof details !== "object") {
|
|
4165
4227
|
return {};
|
|
4166
4228
|
}
|
|
4167
|
-
return {
|
|
4229
|
+
return {
|
|
4230
|
+
inputTokensDetails: details as Record<string, number> | Array<Record<string, number>>,
|
|
4231
|
+
};
|
|
4168
4232
|
}
|
|
4169
4233
|
|
|
4170
4234
|
function outputTokenDetailsProp(
|
|
@@ -4282,7 +4346,9 @@ function objectStorageFileMount(settings: Settings, prefix: string): any {
|
|
|
4282
4346
|
accountKey: config.accountKey,
|
|
4283
4347
|
endpointUrl: config.endpointUrl,
|
|
4284
4348
|
readOnly: true,
|
|
4285
|
-
mountStrategy: inContainerMountStrategy({
|
|
4349
|
+
mountStrategy: inContainerMountStrategy({
|
|
4350
|
+
pattern: { type: "rclone", mode: "fuse" },
|
|
4351
|
+
}),
|
|
4286
4352
|
});
|
|
4287
4353
|
}
|
|
4288
4354
|
if (settings.objectStorageBackend === "aws-s3" || settings.objectStorageBackend === "gcs") {
|
|
@@ -4574,7 +4640,9 @@ export function withSandboxLifecycleHooks(
|
|
|
4574
4640
|
}
|
|
4575
4641
|
: {}),
|
|
4576
4642
|
...(client.delete
|
|
4577
|
-
? {
|
|
4643
|
+
? {
|
|
4644
|
+
delete: async (state: SandboxSessionState) => await client.delete!(state),
|
|
4645
|
+
}
|
|
4578
4646
|
: {}),
|
|
4579
4647
|
...(client.serializeSessionState
|
|
4580
4648
|
? {
|
|
@@ -5272,7 +5340,10 @@ export async function runRigSetupHook(
|
|
|
5272
5340
|
const message = error instanceof Error ? error.message : String(error);
|
|
5273
5341
|
await context.onRuntimeEvent?.({
|
|
5274
5342
|
type: "rig.setup.failed",
|
|
5275
|
-
payload: {
|
|
5343
|
+
payload: {
|
|
5344
|
+
...payload,
|
|
5345
|
+
error: message.slice(-RIG_SETUP_OUTPUT_TAIL_LIMIT),
|
|
5346
|
+
},
|
|
5276
5347
|
});
|
|
5277
5348
|
throw new Error(
|
|
5278
5349
|
`Rig setup failed for rig "${rigSetup.rigName}" (version ${rigSetup.versionId}): ${message}`,
|
|
@@ -5304,7 +5375,10 @@ export async function runRigSetupHook(
|
|
|
5304
5375
|
);
|
|
5305
5376
|
await context.onRuntimeEvent?.({
|
|
5306
5377
|
type: "rig.setup.failed",
|
|
5307
|
-
payload: {
|
|
5378
|
+
payload: {
|
|
5379
|
+
...payload,
|
|
5380
|
+
error: failure.message.slice(-RIG_SETUP_OUTPUT_TAIL_LIMIT),
|
|
5381
|
+
},
|
|
5308
5382
|
});
|
|
5309
5383
|
throw failure;
|
|
5310
5384
|
}
|
|
@@ -5319,8 +5393,14 @@ export async function runRepositoryCloneHook(
|
|
|
5319
5393
|
resources: Extract<ResourceRef, { kind: "repository" }>[],
|
|
5320
5394
|
context: SandboxLifecycleHookContext = { environment: {} },
|
|
5321
5395
|
): Promise<void> {
|
|
5322
|
-
const payload = {
|
|
5323
|
-
|
|
5396
|
+
const payload = {
|
|
5397
|
+
name: "repository-clone",
|
|
5398
|
+
repositoryCount: resources.length,
|
|
5399
|
+
};
|
|
5400
|
+
await context.onRuntimeEvent?.({
|
|
5401
|
+
type: "sandbox.operation.started",
|
|
5402
|
+
payload,
|
|
5403
|
+
});
|
|
5324
5404
|
try {
|
|
5325
5405
|
// TOKEN-BROKER (B1): thread run-scoped provider tokens PER-EXEC, never on
|
|
5326
5406
|
// the manifest. The SDK's ExecCommandArgs has no `environment` field (exec
|
|
@@ -5359,7 +5439,10 @@ export async function runRepositoryCloneHook(
|
|
|
5359
5439
|
} else {
|
|
5360
5440
|
throw new Error("Sandbox session does not support command execution");
|
|
5361
5441
|
}
|
|
5362
|
-
await context.onRuntimeEvent?.({
|
|
5442
|
+
await context.onRuntimeEvent?.({
|
|
5443
|
+
type: "sandbox.operation.completed",
|
|
5444
|
+
payload,
|
|
5445
|
+
});
|
|
5363
5446
|
} catch (error) {
|
|
5364
5447
|
await context.onRuntimeEvent?.({
|
|
5365
5448
|
type: "sandbox.operation.failed",
|
|
@@ -5472,8 +5555,14 @@ export async function runAzureCliLoginHook(
|
|
|
5472
5555
|
session: SandboxSessionLike,
|
|
5473
5556
|
context: SandboxLifecycleHookContext = { environment: {} },
|
|
5474
5557
|
): Promise<void> {
|
|
5475
|
-
const payload = {
|
|
5476
|
-
|
|
5558
|
+
const payload = {
|
|
5559
|
+
name: "azure-cli-login",
|
|
5560
|
+
command: "az login --service-principal",
|
|
5561
|
+
};
|
|
5562
|
+
await context.onRuntimeEvent?.({
|
|
5563
|
+
type: "sandbox.operation.started",
|
|
5564
|
+
payload,
|
|
5565
|
+
});
|
|
5477
5566
|
try {
|
|
5478
5567
|
if (session.exec) {
|
|
5479
5568
|
const result = await session.exec({
|
|
@@ -5496,7 +5585,10 @@ export async function runAzureCliLoginHook(
|
|
|
5496
5585
|
} else {
|
|
5497
5586
|
throw new Error("Sandbox session does not support command execution");
|
|
5498
5587
|
}
|
|
5499
|
-
await context.onRuntimeEvent?.({
|
|
5588
|
+
await context.onRuntimeEvent?.({
|
|
5589
|
+
type: "sandbox.operation.completed",
|
|
5590
|
+
payload,
|
|
5591
|
+
});
|
|
5500
5592
|
} catch (error) {
|
|
5501
5593
|
await context.onRuntimeEvent?.({
|
|
5502
5594
|
type: "sandbox.operation.failed",
|