@mindfoldhq/runtime-manager 0.1.5 → 0.1.7-hotfix.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/README.md +1 -1
- package/dist/vine-runtime-manager.js +200 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ VINE_REMOTE_SANDBOX_PROVIDER='e2b' \
|
|
|
16
16
|
VINE_RUNNER_LINK_HOST='0.0.0.0' \
|
|
17
17
|
VINE_RUNNER_LINK_PORT='8788' \
|
|
18
18
|
VINE_RUNNER_LINK_PUBLIC_URL='<public-runner-link-wss-url>' \
|
|
19
|
-
npx @mindfoldhq/runtime-manager serve
|
|
19
|
+
npx -y @mindfoldhq/runtime-manager serve
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
`VINE_MANAGER_TOKEN` is created in Vine Web Settings -> Runtime managers. The
|
|
@@ -1739,7 +1739,11 @@ var WRITABLE_TASK_DOCS = [
|
|
|
1739
1739
|
"implement_md"
|
|
1740
1740
|
];
|
|
1741
1741
|
var WritableTaskDoc = z8.enum(WRITABLE_TASK_DOCS);
|
|
1742
|
-
var TASK_MUTATIONS = [
|
|
1742
|
+
var TASK_MUTATIONS = [
|
|
1743
|
+
"create",
|
|
1744
|
+
"update_status",
|
|
1745
|
+
"review_request"
|
|
1746
|
+
];
|
|
1743
1747
|
var TaskMutationCapability = z8.enum(TASK_MUTATIONS);
|
|
1744
1748
|
var contextPolicyFields = {
|
|
1745
1749
|
channelHistory: ChannelHistoryMode,
|
|
@@ -3026,6 +3030,16 @@ var AgentSessionStatePayload = z20.object({
|
|
|
3026
3030
|
last_error: z20.string().nullable(),
|
|
3027
3031
|
metadata: z20.record(z20.string(), z20.unknown()).optional()
|
|
3028
3032
|
});
|
|
3033
|
+
var ManagerTurnStartedPayload = z20.object({
|
|
3034
|
+
agent_turn_id: z20.string().min(1),
|
|
3035
|
+
organization_id: z20.string().min(1),
|
|
3036
|
+
session_id: z20.string().min(1),
|
|
3037
|
+
runner_id: z20.string().min(1),
|
|
3038
|
+
agent_session_id: z20.string().min(1),
|
|
3039
|
+
agent_profile_id: z20.string().min(1),
|
|
3040
|
+
project_agent_profile_id: z20.string().nullable(),
|
|
3041
|
+
backend_kind: ManagerBackendKind
|
|
3042
|
+
});
|
|
3029
3043
|
var ManagerTurnEventPayload = z20.object({
|
|
3030
3044
|
agent_turn_id: z20.string().min(1),
|
|
3031
3045
|
kind: ManagerTurnEventKind,
|
|
@@ -3077,6 +3091,15 @@ var TaskCliStatusUpdatePayload = z20.object({
|
|
|
3077
3091
|
status: TaskStatus,
|
|
3078
3092
|
expected_version: z20.number().int().optional()
|
|
3079
3093
|
}).strict();
|
|
3094
|
+
var TaskCliReviewRequestCreatePayload = z20.object({
|
|
3095
|
+
request_id: z20.string().min(1),
|
|
3096
|
+
session_id: z20.string().min(1),
|
|
3097
|
+
agent_turn_id: z20.string().min(1),
|
|
3098
|
+
project_repository_id: z20.string().min(1).optional(),
|
|
3099
|
+
repo_slug: z20.string().min(1).optional(),
|
|
3100
|
+
title: z20.string().min(1).max(256).optional(),
|
|
3101
|
+
body: z20.string().max(65000).optional()
|
|
3102
|
+
}).strict();
|
|
3080
3103
|
var ManagerTaskRefsSnapshotPayload = TaskRefsSnapshotPayload;
|
|
3081
3104
|
var AgentQuestionCreatePayload = z20.object({
|
|
3082
3105
|
request_id: z20.string().min(1),
|
|
@@ -3237,6 +3260,15 @@ var TaskCliStatusUpdateResultPayload = z20.object({
|
|
|
3237
3260
|
message: z20.string().min(1)
|
|
3238
3261
|
}).optional()
|
|
3239
3262
|
});
|
|
3263
|
+
var TaskCliReviewRequestCreateResultPayload = z20.object({
|
|
3264
|
+
request_id: z20.string().min(1),
|
|
3265
|
+
status: z20.enum(["ok", "error"]),
|
|
3266
|
+
review_request: TaskReviewRequestDto.optional(),
|
|
3267
|
+
error: z20.object({
|
|
3268
|
+
code: z20.string().min(1),
|
|
3269
|
+
message: z20.string().min(1)
|
|
3270
|
+
}).optional()
|
|
3271
|
+
});
|
|
3240
3272
|
var AgentQuestionCreateResultPayload = z20.object({
|
|
3241
3273
|
request_id: z20.string().min(1),
|
|
3242
3274
|
status: z20.enum(["ok", "error"]),
|
|
@@ -3395,6 +3427,10 @@ var ManagerToServerMessage = z20.discriminatedUnion("type", [
|
|
|
3395
3427
|
type: z20.literal("agent_session.state"),
|
|
3396
3428
|
payload: AgentSessionStatePayload
|
|
3397
3429
|
}),
|
|
3430
|
+
z20.object({
|
|
3431
|
+
type: z20.literal("turn.started"),
|
|
3432
|
+
payload: ManagerTurnStartedPayload
|
|
3433
|
+
}),
|
|
3398
3434
|
z20.object({ type: z20.literal("turn.event"), payload: ManagerTurnEventPayload }),
|
|
3399
3435
|
z20.object({
|
|
3400
3436
|
type: z20.literal("turn.finished"),
|
|
@@ -3420,6 +3456,10 @@ var ManagerToServerMessage = z20.discriminatedUnion("type", [
|
|
|
3420
3456
|
type: z20.literal("task.cli_status_update"),
|
|
3421
3457
|
payload: TaskCliStatusUpdatePayload
|
|
3422
3458
|
}),
|
|
3459
|
+
z20.object({
|
|
3460
|
+
type: z20.literal("task.cli_review_request_create"),
|
|
3461
|
+
payload: TaskCliReviewRequestCreatePayload
|
|
3462
|
+
}),
|
|
3423
3463
|
z20.object({
|
|
3424
3464
|
type: z20.literal("task.refs_snapshot"),
|
|
3425
3465
|
payload: ManagerTaskRefsSnapshotPayload
|
|
@@ -3511,6 +3551,10 @@ var ServerToManagerMessage = z20.discriminatedUnion("type", [
|
|
|
3511
3551
|
type: z20.literal("task.cli_status_update.result"),
|
|
3512
3552
|
payload: TaskCliStatusUpdateResultPayload
|
|
3513
3553
|
}),
|
|
3554
|
+
z20.object({
|
|
3555
|
+
type: z20.literal("task.cli_review_request_create.result"),
|
|
3556
|
+
payload: TaskCliReviewRequestCreateResultPayload
|
|
3557
|
+
}),
|
|
3514
3558
|
z20.object({
|
|
3515
3559
|
type: z20.literal("agent.question.create.result"),
|
|
3516
3560
|
payload: AgentQuestionCreateResultPayload
|
|
@@ -6679,6 +6723,7 @@ var VineCliCommandName = z44.enum([
|
|
|
6679
6723
|
"task.update_implement",
|
|
6680
6724
|
"task.create",
|
|
6681
6725
|
"task.update_status",
|
|
6726
|
+
"task.create_review_request",
|
|
6682
6727
|
"task.ask"
|
|
6683
6728
|
]);
|
|
6684
6729
|
var VineCliTaskUpdateArgs = z44.object({
|
|
@@ -6719,6 +6764,19 @@ var VineCliTaskStatusUpdateCommand = z44.object({
|
|
|
6719
6764
|
command: z44.literal("task.update_status"),
|
|
6720
6765
|
args: VineCliTaskStatusUpdateArgs
|
|
6721
6766
|
});
|
|
6767
|
+
var VineCliTaskReviewRequestCreateArgs = z44.object({
|
|
6768
|
+
project_repository_id: z44.string().min(1).optional(),
|
|
6769
|
+
repo_slug: z44.string().min(1).optional(),
|
|
6770
|
+
title: z44.string().min(1).max(256).optional(),
|
|
6771
|
+
body: z44.string().max(65000).optional()
|
|
6772
|
+
}).strict().refine((args) => !(args.project_repository_id && args.repo_slug), {
|
|
6773
|
+
message: "pass either project_repository_id or repo_slug, not both",
|
|
6774
|
+
path: ["repo_slug"]
|
|
6775
|
+
});
|
|
6776
|
+
var VineCliTaskReviewRequestCreateCommand = z44.object({
|
|
6777
|
+
command: z44.literal("task.create_review_request"),
|
|
6778
|
+
args: VineCliTaskReviewRequestCreateArgs
|
|
6779
|
+
});
|
|
6722
6780
|
var VineCliAskArgs = z44.object({
|
|
6723
6781
|
questions: z44.array(AgentQuestionSpec).min(1)
|
|
6724
6782
|
});
|
|
@@ -6735,6 +6793,7 @@ var VineCliCommand = z44.discriminatedUnion("command", [
|
|
|
6735
6793
|
VineCliTaskUpdateImplementCommand,
|
|
6736
6794
|
VineCliTaskCreateCommand,
|
|
6737
6795
|
VineCliTaskStatusUpdateCommand,
|
|
6796
|
+
VineCliTaskReviewRequestCreateCommand,
|
|
6738
6797
|
VineCliAskCommand
|
|
6739
6798
|
]);
|
|
6740
6799
|
var TASK_DOC_WRITEBACK = {
|
|
@@ -8355,6 +8414,50 @@ async function handleTaskStatusUpdateCommand(input, command, deps) {
|
|
|
8355
8414
|
}
|
|
8356
8415
|
};
|
|
8357
8416
|
}
|
|
8417
|
+
async function handleTaskReviewRequestCreateCommand(input, command, deps) {
|
|
8418
|
+
const args = VineCliTaskReviewRequestCreateArgs.safeParse(command.args);
|
|
8419
|
+
if (!args.success) {
|
|
8420
|
+
return errorResponse2(input.request.request_id, "VALIDATION_MALFORMED_PAYLOAD", "task review request command args are malformed");
|
|
8421
|
+
}
|
|
8422
|
+
const binding = deps.sessionBinding(input.sessionId);
|
|
8423
|
+
if (!binding) {
|
|
8424
|
+
return errorResponse2(input.request.request_id, "RUNTIME_SESSION_NOT_FOUND", "runtime session is not active");
|
|
8425
|
+
}
|
|
8426
|
+
if (binding.taskId === null) {
|
|
8427
|
+
return errorResponse2(input.request.request_id, "AUTH_FORBIDDEN", "runtime session is not linked to a task");
|
|
8428
|
+
}
|
|
8429
|
+
const activeTurn = deps.resolveActiveTurn(input.sessionId);
|
|
8430
|
+
if (!activeTurn.ok) {
|
|
8431
|
+
return activeTurnError2(input.request.request_id, activeTurn.code);
|
|
8432
|
+
}
|
|
8433
|
+
const result = await deps.taskClient.createTaskReviewRequestFromCli({
|
|
8434
|
+
request_id: input.request.request_id,
|
|
8435
|
+
session_id: input.sessionId,
|
|
8436
|
+
agent_turn_id: activeTurn.turnId,
|
|
8437
|
+
...args.data.project_repository_id === undefined ? {} : { project_repository_id: args.data.project_repository_id },
|
|
8438
|
+
...args.data.repo_slug === undefined ? {} : { repo_slug: args.data.repo_slug },
|
|
8439
|
+
...args.data.title === undefined ? {} : { title: args.data.title },
|
|
8440
|
+
...args.data.body === undefined ? {} : { body: args.data.body }
|
|
8441
|
+
});
|
|
8442
|
+
if (result.status === "ok") {
|
|
8443
|
+
if (result.review_request === undefined) {
|
|
8444
|
+
return errorResponse2(input.request.request_id, "INTERNAL_BUG", "task review request succeeded without review request details");
|
|
8445
|
+
}
|
|
8446
|
+
return {
|
|
8447
|
+
request_id: input.request.request_id,
|
|
8448
|
+
status: "ok",
|
|
8449
|
+
body: result.review_request
|
|
8450
|
+
};
|
|
8451
|
+
}
|
|
8452
|
+
return {
|
|
8453
|
+
request_id: input.request.request_id,
|
|
8454
|
+
status: "error",
|
|
8455
|
+
error: result.error ?? {
|
|
8456
|
+
code: "INTERNAL_BUG",
|
|
8457
|
+
message: "task review request failed"
|
|
8458
|
+
}
|
|
8459
|
+
};
|
|
8460
|
+
}
|
|
8358
8461
|
function activeTurnError2(requestId, code) {
|
|
8359
8462
|
return errorResponse2(requestId, code, code === "ASK_AMBIGUOUS_ACTIVE_TURN" ? "runtime session has multiple active turns" : "runtime session has no active turn");
|
|
8360
8463
|
}
|
|
@@ -8450,6 +8553,8 @@ async function routeCliRequest(input, deps) {
|
|
|
8450
8553
|
return handleTaskCreateCommand(input, parsed.data, deps);
|
|
8451
8554
|
case "task.update_status":
|
|
8452
8555
|
return handleTaskStatusUpdateCommand(input, parsed.data, deps);
|
|
8556
|
+
case "task.create_review_request":
|
|
8557
|
+
return handleTaskReviewRequestCreateCommand(input, parsed.data, deps);
|
|
8453
8558
|
case "task.update_prd":
|
|
8454
8559
|
case "task.update_design":
|
|
8455
8560
|
case "task.update_implement":
|
|
@@ -8929,6 +9034,7 @@ class E2BProvider {
|
|
|
8929
9034
|
await this.killTrackedRunnerCommand(tracked, "respawn");
|
|
8930
9035
|
let command;
|
|
8931
9036
|
try {
|
|
9037
|
+
await this.cleanupPersistedRunnerState(tracked.sandbox, workspaceRoot, tracked, "respawn");
|
|
8932
9038
|
tracked.reposFilePath = reposFilePath;
|
|
8933
9039
|
if (reposFilePath) {
|
|
8934
9040
|
await tracked.sandbox.files.write(reposFilePath, serializeRuntimeReposManifest(remoteRepos));
|
|
@@ -9043,7 +9149,10 @@ class E2BProvider {
|
|
|
9043
9149
|
return result;
|
|
9044
9150
|
}
|
|
9045
9151
|
async prepareRestoredSandbox(sandbox, workspaceRoot, tracked) {
|
|
9046
|
-
|
|
9152
|
+
await this.cleanupPersistedRunnerState(sandbox, workspaceRoot, tracked, "restore");
|
|
9153
|
+
}
|
|
9154
|
+
async cleanupPersistedRunnerState(sandbox, workspaceRoot, tracked, reason) {
|
|
9155
|
+
const result = await sandbox.commands.run(this.persistedRunnerCleanupCommand(workspaceRoot), {
|
|
9047
9156
|
cwd: "/",
|
|
9048
9157
|
timeoutMs: DEFAULT_CLEANUP_TIMEOUT_MS,
|
|
9049
9158
|
onStdout: (data) => {
|
|
@@ -9054,13 +9163,14 @@ class E2BProvider {
|
|
|
9054
9163
|
}
|
|
9055
9164
|
});
|
|
9056
9165
|
if (isCommandHandle(result)) {
|
|
9057
|
-
throw new Error(
|
|
9166
|
+
throw new Error(`E2B ${reason} cleanup unexpectedly ran in background`);
|
|
9058
9167
|
}
|
|
9059
9168
|
if (result.exitCode !== 0) {
|
|
9060
|
-
throw new Error(`E2B
|
|
9169
|
+
throw new Error(`E2B ${reason} cleanup exited ${result.exitCode}: ${redactDiagnosticString(result.stderr)}`);
|
|
9061
9170
|
}
|
|
9171
|
+
log8.info({ sandbox_id: sandbox.sandboxId, reason }, "E2B persisted runner cleanup completed");
|
|
9062
9172
|
}
|
|
9063
|
-
|
|
9173
|
+
persistedRunnerCleanupCommand(workspaceRoot) {
|
|
9064
9174
|
const socketPath = shellQuote2(`${workspaceRoot}/.vine/vine.sock`);
|
|
9065
9175
|
return [
|
|
9066
9176
|
"set -eu;",
|
|
@@ -10868,6 +10978,15 @@ class SessionLifecycle {
|
|
|
10868
10978
|
dirty_files: 0
|
|
10869
10979
|
};
|
|
10870
10980
|
if (!this.m.runnerLink.hasRunner(session.sessionId)) {
|
|
10981
|
+
if (session.providerKind === "remote_sandbox" && session.repos.length > 0) {
|
|
10982
|
+
log11.warn({
|
|
10983
|
+
session_id: session.sessionId,
|
|
10984
|
+
provider_key: session.providerKey,
|
|
10985
|
+
repo_count: session.repos.length
|
|
10986
|
+
}, "no runner connected for remote repo workspace — treating dirty state as unknown/dirty");
|
|
10987
|
+
resolve3(conservativeDirty);
|
|
10988
|
+
return;
|
|
10989
|
+
}
|
|
10871
10990
|
log11.info({ session_id: session.sessionId }, "no runner connected — skipping dirty probe, treating workspace as clean");
|
|
10872
10991
|
resolve3({
|
|
10873
10992
|
session_id: session.sessionId,
|
|
@@ -11573,10 +11692,23 @@ class TaskProjectionBridge {
|
|
|
11573
11692
|
const agentKey = session.turnToAgentKey.get(turnStart.turn_id);
|
|
11574
11693
|
const agentSession = agentKey ? session.agentSessions.get(agentKey) : undefined;
|
|
11575
11694
|
if (agentSession) {
|
|
11695
|
+
this.emitTurnStarted(session, turnStart, agentSession);
|
|
11576
11696
|
this.m.emitAgentSessionState(session, agentSession, "active");
|
|
11577
11697
|
}
|
|
11578
11698
|
}
|
|
11579
11699
|
}
|
|
11700
|
+
emitTurnStarted(session, turnStart, agentSession) {
|
|
11701
|
+
this.m.serverClient.emitTurnStarted({
|
|
11702
|
+
agent_turn_id: turnStart.turn_id,
|
|
11703
|
+
organization_id: session.organizationId,
|
|
11704
|
+
session_id: session.sessionId,
|
|
11705
|
+
runner_id: session.runnerId,
|
|
11706
|
+
agent_session_id: agentSession.agentSessionId,
|
|
11707
|
+
agent_profile_id: agentSession.agentProfileId,
|
|
11708
|
+
project_agent_profile_id: agentSession.projectAgentProfileId,
|
|
11709
|
+
backend_kind: agentSession.backendKind
|
|
11710
|
+
});
|
|
11711
|
+
}
|
|
11580
11712
|
}
|
|
11581
11713
|
|
|
11582
11714
|
// src/runtime-manager-terminal-relay.ts
|
|
@@ -12256,6 +12388,16 @@ class TurnRouter {
|
|
|
12256
12388
|
this.m.maybeRespawnDisconnectedSession(session, "turn_dispatch");
|
|
12257
12389
|
return;
|
|
12258
12390
|
}
|
|
12391
|
+
this.m.serverClient.emitTurnStarted({
|
|
12392
|
+
agent_turn_id: dispatch.agent_turn_id,
|
|
12393
|
+
organization_id: session.organizationId,
|
|
12394
|
+
session_id: session.sessionId,
|
|
12395
|
+
runner_id: session.runnerId,
|
|
12396
|
+
agent_session_id: agentSession.agentSessionId,
|
|
12397
|
+
agent_profile_id: agentSession.agentProfileId,
|
|
12398
|
+
project_agent_profile_id: agentSession.projectAgentProfileId,
|
|
12399
|
+
backend_kind: agentSession.backendKind
|
|
12400
|
+
});
|
|
12259
12401
|
this.m.emitAgentSessionState(session, agentSession, "active");
|
|
12260
12402
|
log15.info({
|
|
12261
12403
|
agent_turn_id: dispatch.agent_turn_id,
|
|
@@ -12559,6 +12701,7 @@ class ServerClient {
|
|
|
12559
12701
|
pendingTaskCliUpdates = new Map;
|
|
12560
12702
|
pendingTaskCliCreates = new Map;
|
|
12561
12703
|
pendingTaskCliStatusUpdates = new Map;
|
|
12704
|
+
pendingTaskCliReviewRequestCreates = new Map;
|
|
12562
12705
|
pendingQuestionCreates = new Map;
|
|
12563
12706
|
pendingTerminalFrames = [];
|
|
12564
12707
|
constructor(opts) {
|
|
@@ -12809,6 +12952,10 @@ class ServerClient {
|
|
|
12809
12952
|
this.settleTaskCliStatusUpdate(parsed.payload);
|
|
12810
12953
|
return;
|
|
12811
12954
|
}
|
|
12955
|
+
case "task.cli_review_request_create.result": {
|
|
12956
|
+
this.settleTaskCliReviewRequestCreate(parsed.payload);
|
|
12957
|
+
return;
|
|
12958
|
+
}
|
|
12812
12959
|
case "agent.question.create.result": {
|
|
12813
12960
|
this.settleQuestionCreate(parsed.payload);
|
|
12814
12961
|
return;
|
|
@@ -12950,6 +13097,13 @@ class ServerClient {
|
|
|
12950
13097
|
payload: { ...payload, request_id: requestId }
|
|
12951
13098
|
}));
|
|
12952
13099
|
}
|
|
13100
|
+
requestTaskCliReviewRequestCreate(payload) {
|
|
13101
|
+
const requestId = payload.request_id ?? randomUUID6();
|
|
13102
|
+
return this.trackTaskRequest(this.pendingTaskCliReviewRequestCreates, requestId, () => this.send({
|
|
13103
|
+
type: "task.cli_review_request_create",
|
|
13104
|
+
payload: { ...payload, request_id: requestId }
|
|
13105
|
+
}));
|
|
13106
|
+
}
|
|
12953
13107
|
requestQuestionCreate(payload) {
|
|
12954
13108
|
const requestId = payload.request_id ?? randomUUID6();
|
|
12955
13109
|
return this.trackTaskRequest(this.pendingQuestionCreates, requestId, () => this.send({
|
|
@@ -12988,6 +13142,9 @@ class ServerClient {
|
|
|
12988
13142
|
settleTaskCliStatusUpdate(payload) {
|
|
12989
13143
|
this.settleTaskRequest(this.pendingTaskCliStatusUpdates, payload.request_id, payload);
|
|
12990
13144
|
}
|
|
13145
|
+
settleTaskCliReviewRequestCreate(payload) {
|
|
13146
|
+
this.settleTaskRequest(this.pendingTaskCliReviewRequestCreates, payload.request_id, payload);
|
|
13147
|
+
}
|
|
12991
13148
|
settleQuestionCreate(payload) {
|
|
12992
13149
|
this.settleTaskRequest(this.pendingQuestionCreates, payload.request_id, payload);
|
|
12993
13150
|
}
|
|
@@ -13007,6 +13164,7 @@ class ServerClient {
|
|
|
13007
13164
|
this.pendingTaskCliUpdates,
|
|
13008
13165
|
this.pendingTaskCliCreates,
|
|
13009
13166
|
this.pendingTaskCliStatusUpdates,
|
|
13167
|
+
this.pendingTaskCliReviewRequestCreates,
|
|
13010
13168
|
this.pendingQuestionCreates
|
|
13011
13169
|
]) {
|
|
13012
13170
|
for (const request of pending.values()) {
|
|
@@ -13025,6 +13183,9 @@ class ServerClient {
|
|
|
13025
13183
|
emitAgentSessionState(payload) {
|
|
13026
13184
|
return this.send({ type: "agent_session.state", payload });
|
|
13027
13185
|
}
|
|
13186
|
+
emitTurnStarted(payload) {
|
|
13187
|
+
return this.send({ type: "turn.started", payload });
|
|
13188
|
+
}
|
|
13028
13189
|
}
|
|
13029
13190
|
function unrefTimer(timer) {
|
|
13030
13191
|
const maybeTimer = timer;
|
|
@@ -13479,6 +13640,7 @@ class RuntimeManager {
|
|
|
13479
13640
|
taskClient: {
|
|
13480
13641
|
createTaskFromCli: (payload) => this.serverClient.requestTaskCliCreate(payload),
|
|
13481
13642
|
updateTaskStatusFromCli: (payload) => this.serverClient.requestTaskCliStatusUpdate(payload),
|
|
13643
|
+
createTaskReviewRequestFromCli: (payload) => this.serverClient.requestTaskCliReviewRequestCreate(payload),
|
|
13482
13644
|
updateTaskFromCli: (payload) => this.serverClient.requestTaskCliUpdate(payload)
|
|
13483
13645
|
},
|
|
13484
13646
|
questionClient: {
|
|
@@ -13546,15 +13708,22 @@ class RuntimeManager {
|
|
|
13546
13708
|
}
|
|
13547
13709
|
this.clearRunnerBootTimer(session);
|
|
13548
13710
|
}
|
|
13549
|
-
this.runnerLink.stop();
|
|
13550
13711
|
const releases = sessions.map(async (session) => {
|
|
13551
13712
|
if (!session.provisioned) {
|
|
13552
13713
|
this.emitReleasedState(session);
|
|
13553
|
-
return;
|
|
13714
|
+
return "released";
|
|
13715
|
+
}
|
|
13716
|
+
if (session.lastStatus !== "idle_checkpointed" && await this.sessionLifecycle.dirtyProbeHoldsRelease(session)) {
|
|
13717
|
+
log17.info({
|
|
13718
|
+
session_id: session.sessionId,
|
|
13719
|
+
provider_key: session.providerKey
|
|
13720
|
+
}, "shutdown release blocked by dirty workspace — preserving provider runtime");
|
|
13721
|
+
return "preserved";
|
|
13554
13722
|
}
|
|
13555
13723
|
try {
|
|
13556
13724
|
await providerForSession(this, session).releaseSession(session.provisioned);
|
|
13557
13725
|
this.emitReleasedState(session);
|
|
13726
|
+
return "released";
|
|
13558
13727
|
} catch (err) {
|
|
13559
13728
|
log17.warn({ err, session_id: session.sessionId }, "session release failed during shutdown — marking failed");
|
|
13560
13729
|
const detail = err instanceof Error ? err.message : String(err);
|
|
@@ -13563,12 +13732,17 @@ class RuntimeManager {
|
|
|
13563
13732
|
}
|
|
13564
13733
|
this.emitRunnerStateFailed(session, detail);
|
|
13565
13734
|
this.emitSessionStateFailed(session, detail);
|
|
13735
|
+
return "failed";
|
|
13566
13736
|
}
|
|
13567
13737
|
});
|
|
13738
|
+
const results = await Promise.allSettled(releases);
|
|
13739
|
+
this.runnerLink.stop();
|
|
13568
13740
|
this.sessions.clear();
|
|
13569
13741
|
this.sessionsById.clear();
|
|
13570
|
-
|
|
13571
|
-
|
|
13742
|
+
const released = results.filter((result) => result.status === "fulfilled" && result.value === "released").length;
|
|
13743
|
+
const preserved = results.filter((result) => result.status === "fulfilled" && result.value === "preserved").length;
|
|
13744
|
+
const failed = results.length - released - preserved;
|
|
13745
|
+
log17.info({ released, preserved, failed }, "shutdown session release drain finished");
|
|
13572
13746
|
this.serverClient.stop();
|
|
13573
13747
|
}
|
|
13574
13748
|
emitReleasedState(session) {
|
|
@@ -14356,6 +14530,7 @@ class RuntimeManager2 {
|
|
|
14356
14530
|
taskClient: {
|
|
14357
14531
|
createTaskFromCli: (payload) => this.serverClient.requestTaskCliCreate(payload),
|
|
14358
14532
|
updateTaskStatusFromCli: (payload) => this.serverClient.requestTaskCliStatusUpdate(payload),
|
|
14533
|
+
createTaskReviewRequestFromCli: (payload) => this.serverClient.requestTaskCliReviewRequestCreate(payload),
|
|
14359
14534
|
updateTaskFromCli: (payload) => this.serverClient.requestTaskCliUpdate(payload)
|
|
14360
14535
|
},
|
|
14361
14536
|
questionClient: {
|
|
@@ -14423,15 +14598,22 @@ class RuntimeManager2 {
|
|
|
14423
14598
|
}
|
|
14424
14599
|
this.clearRunnerBootTimer(session);
|
|
14425
14600
|
}
|
|
14426
|
-
this.runnerLink.stop();
|
|
14427
14601
|
const releases = sessions.map(async (session) => {
|
|
14428
14602
|
if (!session.provisioned) {
|
|
14429
14603
|
this.emitReleasedState(session);
|
|
14430
|
-
return;
|
|
14604
|
+
return "released";
|
|
14605
|
+
}
|
|
14606
|
+
if (session.lastStatus !== "idle_checkpointed" && await this.sessionLifecycle.dirtyProbeHoldsRelease(session)) {
|
|
14607
|
+
log19.info({
|
|
14608
|
+
session_id: session.sessionId,
|
|
14609
|
+
provider_key: session.providerKey
|
|
14610
|
+
}, "shutdown release blocked by dirty workspace — preserving provider runtime");
|
|
14611
|
+
return "preserved";
|
|
14431
14612
|
}
|
|
14432
14613
|
try {
|
|
14433
14614
|
await providerForSession(this, session).releaseSession(session.provisioned);
|
|
14434
14615
|
this.emitReleasedState(session);
|
|
14616
|
+
return "released";
|
|
14435
14617
|
} catch (err) {
|
|
14436
14618
|
log19.warn({ err, session_id: session.sessionId }, "session release failed during shutdown — marking failed");
|
|
14437
14619
|
const detail = err instanceof Error ? err.message : String(err);
|
|
@@ -14440,12 +14622,17 @@ class RuntimeManager2 {
|
|
|
14440
14622
|
}
|
|
14441
14623
|
this.emitRunnerStateFailed(session, detail);
|
|
14442
14624
|
this.emitSessionStateFailed(session, detail);
|
|
14625
|
+
return "failed";
|
|
14443
14626
|
}
|
|
14444
14627
|
});
|
|
14628
|
+
const results = await Promise.allSettled(releases);
|
|
14629
|
+
this.runnerLink.stop();
|
|
14445
14630
|
this.sessions.clear();
|
|
14446
14631
|
this.sessionsById.clear();
|
|
14447
|
-
|
|
14448
|
-
|
|
14632
|
+
const released = results.filter((result) => result.status === "fulfilled" && result.value === "released").length;
|
|
14633
|
+
const preserved = results.filter((result) => result.status === "fulfilled" && result.value === "preserved").length;
|
|
14634
|
+
const failed = results.length - released - preserved;
|
|
14635
|
+
log19.info({ released, preserved, failed }, "shutdown session release drain finished");
|
|
14449
14636
|
this.serverClient.stop();
|
|
14450
14637
|
}
|
|
14451
14638
|
emitReleasedState(session) {
|