@xfey/tutti 0.1.78 → 0.1.79
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/chat-assistant/index.d.ts +11 -1
- package/dist/chat-assistant/index.js +61 -7
- package/dist/checks/index.d.ts +22 -0
- package/dist/checks/index.js +110 -4
- package/dist/control-plane/follow-up-start.d.ts +1 -0
- package/dist/control-plane/follow-up-start.js +3 -1
- package/dist/control-plane/index.d.ts +6 -1
- package/dist/control-plane/index.js +72 -11
- package/dist/control-plane/procedure-logging.js +24 -67
- package/dist/control-plane/project-context-bootstrap.js +7 -1
- package/dist/control-plane/reference-summary-refresh.js +1 -1
- package/dist/control-plane/run-result-recording.js +2 -1
- package/dist/control-plane/task-compile-start.d.ts +1 -0
- package/dist/control-plane/task-compile-start.js +11 -1
- package/dist/control-plane/workflows/openai.d.ts +6 -0
- package/dist/control-plane/workflows/openai.js +16 -3
- package/dist/procedure-engine/index.d.ts +1 -0
- package/dist/procedure-engine/index.js +7 -1
- package/dist/process-tree.d.ts +25 -0
- package/dist/process-tree.js +121 -0
- package/dist/providers/openai/app-server/invocation-coordinator.d.ts +28 -0
- package/dist/providers/openai/app-server/invocation-coordinator.js +104 -0
- package/dist/providers/openai/app-server/invocation-lifecycle.d.ts +45 -0
- package/dist/providers/openai/app-server/invocation-lifecycle.js +104 -0
- package/dist/providers/openai/app-server/json-rpc.d.ts +1 -1
- package/dist/providers/openai/app-server/json-rpc.js +9 -16
- package/dist/providers/openai/app-server/read-only-procedure.d.ts +8 -2
- package/dist/providers/openai/app-server/read-only-procedure.js +63 -11
- package/dist/providers/openai/app-server/smoke-types.d.ts +4 -2
- package/dist/providers/openai/app-server/smoke.js +41 -12
- package/dist/providers/openai/app-server/stale-temp-cleanup.d.ts +17 -0
- package/dist/providers/openai/app-server/stale-temp-cleanup.js +130 -0
- package/dist/providers/openai/app-server/workspace-write-run.d.ts +8 -2
- package/dist/providers/openai/app-server/workspace-write-run.js +63 -11
- package/dist/providers/openai/chat-assistant.d.ts +6 -0
- package/dist/providers/openai/chat-assistant.js +12 -0
- package/dist/run-engine/index.js +2 -1
- package/dist/run-pipeline/artifact-applicability.js +2 -2
- package/dist/run-pipeline/openai.d.ts +9 -0
- package/dist/run-pipeline/openai.js +26 -26
- package/dist/run-pipeline/task-run-invocation.js +6 -0
- package/dist/runtime-failures.d.ts +3 -0
- package/dist/runtime-failures.js +22 -0
- package/dist/server-shell/cli/host-lifecycle.js +1 -1
- package/dist/server-shell/cli/host-project-runtime-lifecycle.d.ts +43 -0
- package/dist/server-shell/cli/host-project-runtime-lifecycle.js +54 -0
- package/dist/server-shell/cli/host-server-runtime.js +77 -14
- package/dist/server-shell/http/create-server.d.ts +3 -0
- package/dist/server-shell/http/create-server.js +10 -4
- package/package.json +1 -1
- package/web/assets/{homepage-motion-scene-sNI8fBH3.js → homepage-motion-scene-BFQnHtRi.js} +1 -1
- package/web/assets/index-C4cdSaSb.js +69 -0
- package/web/index.html +1 -1
- package/web/assets/index-d-q9yZ09.js +0 -69
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { type CodexAppServerLifecycleIncident } from "./invocation-lifecycle.js";
|
|
2
|
+
import { type CodexAppServerInvocationCoordinator, type CodexAppServerInvocationLease } from "./invocation-coordinator.js";
|
|
1
3
|
import { type CodexAppServerRuntimeTelemetryOptions } from "./runtime-telemetry.js";
|
|
2
4
|
import { type CodexAppServerAgentContextRuntime, type CodexAppServerSkillSelectionName } from "./skills.js";
|
|
3
5
|
import { type OpenAiTokenUsage } from "../token-usage.js";
|
|
@@ -25,6 +27,10 @@ export type CodexAppServerReadOnlyProcedureInput<TOutput> = {
|
|
|
25
27
|
turnTimeoutMs?: number;
|
|
26
28
|
baseEnv?: NodeJS.ProcessEnv;
|
|
27
29
|
runtimeTelemetry?: CodexAppServerRuntimeTelemetryOptions;
|
|
30
|
+
onLifecycleIncident?: (incident: CodexAppServerLifecycleIncident) => void;
|
|
31
|
+
invocationCoordinator?: CodexAppServerInvocationCoordinator;
|
|
32
|
+
/** @internal Set only by the coordinator wrapper. */
|
|
33
|
+
invocationLease?: CodexAppServerInvocationLease;
|
|
28
34
|
};
|
|
29
35
|
export type CodexAppServerReadOnlyProcedureResult<TOutput> = {
|
|
30
36
|
output: TOutput;
|
|
@@ -52,9 +58,9 @@ export type CodexAppServerReadOnlyProcedureErrorDetails = {
|
|
|
52
58
|
stderr_excerpt?: string;
|
|
53
59
|
};
|
|
54
60
|
export declare class CodexAppServerReadOnlyProcedureError extends Error {
|
|
55
|
-
readonly code: "app_server_protocol_error" | "auth_failed" | "thread_start_failed" | "turn_failed" | "turn_timeout" | "unexpected_server_request" | "skill_selection_failed" | "output_parse_failed" | "output_validation_failed" | "write_detected" | "secret_leak_detected";
|
|
61
|
+
readonly code: "app_server_protocol_error" | "auth_failed" | "thread_start_failed" | "turn_failed" | "turn_timeout" | "unexpected_server_request" | "skill_selection_failed" | "output_parse_failed" | "output_validation_failed" | "write_detected" | "secret_leak_detected" | "process_lifecycle_failed" | "admission_unavailable";
|
|
56
62
|
readonly details: CodexAppServerReadOnlyProcedureErrorDetails;
|
|
57
|
-
constructor(code: "app_server_protocol_error" | "auth_failed" | "thread_start_failed" | "turn_failed" | "turn_timeout" | "unexpected_server_request" | "skill_selection_failed" | "output_parse_failed" | "output_validation_failed" | "write_detected" | "secret_leak_detected", message: string, details?: CodexAppServerReadOnlyProcedureErrorDetails);
|
|
63
|
+
constructor(code: "app_server_protocol_error" | "auth_failed" | "thread_start_failed" | "turn_failed" | "turn_timeout" | "unexpected_server_request" | "skill_selection_failed" | "output_parse_failed" | "output_validation_failed" | "write_detected" | "secret_leak_detected" | "process_lifecycle_failed" | "admission_unavailable", message: string, details?: CodexAppServerReadOnlyProcedureErrorDetails);
|
|
58
64
|
}
|
|
59
65
|
export declare function resolveReadOnlyWebSearchMode(input: {
|
|
60
66
|
networkAccess?: boolean;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { execFileSync, spawn } from "node:child_process";
|
|
2
|
-
import { mkdirSync, mkdtempSync
|
|
2
|
+
import { mkdirSync, mkdtempSync } from "node:fs";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { buildCodexAppServerProcessPlan } from "../codex-app-server.js";
|
|
6
6
|
import { DEFAULT_OPENAI_MODEL } from "../model-config.js";
|
|
7
7
|
import { CodexAppServerJsonRpcClient, CodexAppServerProtocolError, } from "./json-rpc.js";
|
|
8
|
+
import { CodexAppServerInvocation, CodexAppServerLifecycleError, createManagedProcess, } from "./invocation-lifecycle.js";
|
|
9
|
+
import { CodexAppServerAdmissionError, } from "./invocation-coordinator.js";
|
|
8
10
|
import { createCodexAppServerRuntimeObserver, } from "./runtime-telemetry.js";
|
|
9
11
|
import { createReadOnlySandboxPolicy } from "./sandbox-policy.js";
|
|
10
12
|
import { buildCodexAppServerProviderConfigOverrides, resolveCodexAppServerModelProvider, } from "./provider-config.js";
|
|
@@ -76,6 +78,26 @@ export function parseCodexAppServerStructuredJson(text) {
|
|
|
76
78
|
throw new CodexAppServerReadOnlyProcedureError("output_parse_failed", "Codex app-server returned malformed JSON.");
|
|
77
79
|
}
|
|
78
80
|
export async function runCodexAppServerReadOnlyProcedure(options) {
|
|
81
|
+
if (options.invocationCoordinator !== undefined && options.invocationLease === undefined) {
|
|
82
|
+
let lease;
|
|
83
|
+
try {
|
|
84
|
+
lease = await options.invocationCoordinator.acquire();
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
throw new CodexAppServerReadOnlyProcedureError("admission_unavailable", error instanceof CodexAppServerAdmissionError
|
|
88
|
+
? error.message
|
|
89
|
+
: "Codex app-server admission is unavailable.");
|
|
90
|
+
}
|
|
91
|
+
try {
|
|
92
|
+
return await runCodexAppServerReadOnlyProcedure({
|
|
93
|
+
...options,
|
|
94
|
+
invocationLease: lease,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
finally {
|
|
98
|
+
lease.release();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
79
101
|
let skillInputs;
|
|
80
102
|
let contextRuntimeHint;
|
|
81
103
|
try {
|
|
@@ -122,11 +144,13 @@ export async function runCodexAppServerReadOnlyProcedure(options) {
|
|
|
122
144
|
configOverrides: buildCodexAppServerProviderConfigOverrides(options),
|
|
123
145
|
...(options.codexCommand === undefined ? {} : { codexCommand: options.codexCommand }),
|
|
124
146
|
});
|
|
125
|
-
const
|
|
147
|
+
const managedProcess = createManagedProcess(spawn(processPlan.command, processPlan.args, {
|
|
126
148
|
cwd: process.cwd(),
|
|
149
|
+
detached: process.platform !== "win32",
|
|
127
150
|
env: createCodexSpawnEnv(codexHome, options.baseEnv ?? process.env),
|
|
128
151
|
stdio: "pipe",
|
|
129
|
-
});
|
|
152
|
+
}));
|
|
153
|
+
const child = managedProcess.child;
|
|
130
154
|
const runtimeObserver = options.runtimeTelemetry === undefined
|
|
131
155
|
? undefined
|
|
132
156
|
: createCodexAppServerRuntimeObserver(options.runtimeTelemetry);
|
|
@@ -138,6 +162,15 @@ export async function runCodexAppServerReadOnlyProcedure(options) {
|
|
|
138
162
|
onServerRequest: runtimeObserver.serverRequest,
|
|
139
163
|
}),
|
|
140
164
|
});
|
|
165
|
+
const invocation = new CodexAppServerInvocation({
|
|
166
|
+
managedProcess,
|
|
167
|
+
tempRoot,
|
|
168
|
+
closeProtocol: () => client.close(),
|
|
169
|
+
...(options.onLifecycleIncident === undefined
|
|
170
|
+
? {}
|
|
171
|
+
: { onIncident: options.onLifecycleIncident }),
|
|
172
|
+
});
|
|
173
|
+
options.invocationLease?.setCloser(() => invocation.close());
|
|
141
174
|
const sensitiveValues = [
|
|
142
175
|
options.apiKey,
|
|
143
176
|
tempRoot,
|
|
@@ -155,6 +188,9 @@ export async function runCodexAppServerReadOnlyProcedure(options) {
|
|
|
155
188
|
options.apiKey,
|
|
156
189
|
...(contextRuntimeHint?.sensitiveValues ?? []),
|
|
157
190
|
];
|
|
191
|
+
let primaryError;
|
|
192
|
+
let procedureResult;
|
|
193
|
+
let lifecycleError;
|
|
158
194
|
try {
|
|
159
195
|
await client.request("initialize", {
|
|
160
196
|
clientInfo: {
|
|
@@ -272,7 +308,7 @@ export async function runCodexAppServerReadOnlyProcedure(options) {
|
|
|
272
308
|
throw new CodexAppServerReadOnlyProcedureError("secret_leak_detected", "Codex app-server output contained a sensitive runtime value.");
|
|
273
309
|
}
|
|
274
310
|
const usage = extractCodexAppServerTokenUsage(client.notifications);
|
|
275
|
-
|
|
311
|
+
procedureResult = {
|
|
276
312
|
output: parsed,
|
|
277
313
|
model,
|
|
278
314
|
turn_status: "completed",
|
|
@@ -288,18 +324,34 @@ export async function runCodexAppServerReadOnlyProcedure(options) {
|
|
|
288
324
|
}
|
|
289
325
|
catch (error) {
|
|
290
326
|
if (error instanceof CodexAppServerReadOnlyProcedureError) {
|
|
291
|
-
|
|
327
|
+
primaryError = error;
|
|
292
328
|
}
|
|
293
|
-
if (error instanceof CodexAppServerProtocolError) {
|
|
294
|
-
|
|
329
|
+
else if (error instanceof CodexAppServerProtocolError) {
|
|
330
|
+
primaryError = new CodexAppServerReadOnlyProcedureError("app_server_protocol_error", redactWithKnownValues(error.message, sensitiveValues));
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
334
|
+
primaryError = new CodexAppServerReadOnlyProcedureError("app_server_protocol_error", redactWithKnownValues(message, sensitiveValues));
|
|
295
335
|
}
|
|
296
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
297
|
-
throw new CodexAppServerReadOnlyProcedureError("app_server_protocol_error", redactWithKnownValues(message, sensitiveValues));
|
|
298
336
|
}
|
|
299
337
|
finally {
|
|
300
338
|
runtimeObserver?.flush();
|
|
301
|
-
|
|
302
|
-
|
|
339
|
+
try {
|
|
340
|
+
await invocation.close();
|
|
341
|
+
}
|
|
342
|
+
catch (error) {
|
|
343
|
+
invocation.reportProcessTerminationFailure(error);
|
|
344
|
+
lifecycleError = error;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
if (primaryError !== undefined) {
|
|
348
|
+
throw primaryError;
|
|
349
|
+
}
|
|
350
|
+
if (lifecycleError !== undefined) {
|
|
351
|
+
throw new CodexAppServerReadOnlyProcedureError("process_lifecycle_failed", lifecycleError instanceof CodexAppServerLifecycleError
|
|
352
|
+
? lifecycleError.message
|
|
353
|
+
: "Codex app-server process lifecycle did not close cleanly.");
|
|
303
354
|
}
|
|
355
|
+
return procedureResult;
|
|
304
356
|
}
|
|
305
357
|
//# sourceMappingURL=read-only-procedure.js.map
|
|
@@ -27,6 +27,7 @@ export type CodexAppServerNoWriteSmokeOptions = CodexAppServerSmokeProviderInput
|
|
|
27
27
|
requestTimeoutMs?: number;
|
|
28
28
|
turnTimeoutMs?: number;
|
|
29
29
|
baseEnv?: NodeJS.ProcessEnv;
|
|
30
|
+
onLifecycleIncident?: (incident: CodexAppServerLifecycleIncident) => void;
|
|
30
31
|
};
|
|
31
32
|
export type CodexAppServerNoWriteSmokeResult = {
|
|
32
33
|
status: "passed";
|
|
@@ -43,7 +44,8 @@ export type CodexAppServerNoWriteSmokeResult = {
|
|
|
43
44
|
stderr_excerpt: string;
|
|
44
45
|
};
|
|
45
46
|
export declare class CodexAppServerSmokeError extends Error {
|
|
46
|
-
readonly code: "missing_provider_credential" | "credential_unavailable" | "app_server_protocol_error" | "auth_failed" | "model_unavailable" | "thread_start_failed" | "turn_failed" | "unexpected_server_request" | "sentinel_missing" | "write_detected" | "secret_leak_detected";
|
|
47
|
-
constructor(code: "missing_provider_credential" | "credential_unavailable" | "app_server_protocol_error" | "auth_failed" | "model_unavailable" | "thread_start_failed" | "turn_failed" | "unexpected_server_request" | "sentinel_missing" | "write_detected" | "secret_leak_detected", message: string);
|
|
47
|
+
readonly code: "missing_provider_credential" | "credential_unavailable" | "app_server_protocol_error" | "auth_failed" | "model_unavailable" | "thread_start_failed" | "turn_failed" | "unexpected_server_request" | "sentinel_missing" | "write_detected" | "secret_leak_detected" | "process_lifecycle_failed";
|
|
48
|
+
constructor(code: "missing_provider_credential" | "credential_unavailable" | "app_server_protocol_error" | "auth_failed" | "model_unavailable" | "thread_start_failed" | "turn_failed" | "unexpected_server_request" | "sentinel_missing" | "write_detected" | "secret_leak_detected" | "process_lifecycle_failed", message: string);
|
|
48
49
|
}
|
|
50
|
+
import type { CodexAppServerLifecycleIncident } from "./invocation-lifecycle.js";
|
|
49
51
|
//# sourceMappingURL=smoke-types.d.ts.map
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
|
-
import { mkdirSync, mkdtempSync
|
|
2
|
+
import { mkdirSync, mkdtempSync } from "node:fs";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { CODEX_APP_SERVER_COMMAND, CODEX_APP_SERVER_LISTEN_URL, buildCodexAppServerProcessPlan, } from "../codex-app-server.js";
|
|
6
6
|
import { DEFAULT_OPENAI_MODEL } from "../model-config.js";
|
|
7
7
|
import { CodexAppServerJsonRpcClient, CodexAppServerProtocolError, } from "./json-rpc.js";
|
|
8
|
+
import { CodexAppServerInvocation, CodexAppServerLifecycleError, createManagedProcess, } from "./invocation-lifecycle.js";
|
|
8
9
|
import { createReadOnlySandboxPolicy } from "./sandbox-policy.js";
|
|
9
10
|
import { buildCodexAppServerProviderConfigOverrides, resolveCodexAppServerModelProvider, } from "./provider-config.js";
|
|
10
11
|
import { containsKnownSecret, countAvailableModels, createCodexSpawnEnv, createSmokeRepo, extractAgentText, extractNotificationMethod, isApiKeyAccount, modelListContains, readAccountType, readGitStatus, readThreadId, readTurnStatus, redactWithKnownValues, renderNoWriteSmokePrompt, } from "./smoke-helpers.js";
|
|
@@ -27,12 +28,26 @@ export async function runCodexAppServerNoWriteSmoke(options) {
|
|
|
27
28
|
configOverrides: buildCodexAppServerProviderConfigOverrides(options),
|
|
28
29
|
...(options.codexCommand === undefined ? {} : { codexCommand: options.codexCommand }),
|
|
29
30
|
});
|
|
30
|
-
const
|
|
31
|
+
const managedProcess = createManagedProcess(spawn(processPlan.command, processPlan.args, {
|
|
31
32
|
cwd: process.cwd(),
|
|
33
|
+
detached: process.platform !== "win32",
|
|
32
34
|
env: createCodexSpawnEnv(codexHome, options.baseEnv ?? process.env),
|
|
33
35
|
stdio: "pipe",
|
|
34
|
-
});
|
|
36
|
+
}));
|
|
37
|
+
const child = managedProcess.child;
|
|
35
38
|
const client = new CodexAppServerJsonRpcClient(child);
|
|
39
|
+
const invocation = new CodexAppServerInvocation({
|
|
40
|
+
managedProcess,
|
|
41
|
+
tempRoot,
|
|
42
|
+
closeProtocol: () => client.close(),
|
|
43
|
+
...(options.keepTemp === true ? { keepTemp: true } : {}),
|
|
44
|
+
...(options.onLifecycleIncident === undefined
|
|
45
|
+
? {}
|
|
46
|
+
: { onIncident: options.onLifecycleIncident }),
|
|
47
|
+
});
|
|
48
|
+
let primaryError;
|
|
49
|
+
let smokeResult;
|
|
50
|
+
let lifecycleError;
|
|
36
51
|
try {
|
|
37
52
|
await client.request("initialize", {
|
|
38
53
|
clientInfo: {
|
|
@@ -121,7 +136,7 @@ export async function runCodexAppServerNoWriteSmoke(options) {
|
|
|
121
136
|
throw new CodexAppServerSmokeError("secret_leak_detected", "Codex app-server output contained the provider API key.");
|
|
122
137
|
}
|
|
123
138
|
const stderrExcerpt = redactWithKnownValues(client.stderr, sensitiveValues).slice(0, 500);
|
|
124
|
-
|
|
139
|
+
smokeResult = {
|
|
125
140
|
status: "passed",
|
|
126
141
|
model,
|
|
127
142
|
account_type: "apiKey",
|
|
@@ -139,19 +154,33 @@ export async function runCodexAppServerNoWriteSmoke(options) {
|
|
|
139
154
|
}
|
|
140
155
|
catch (error) {
|
|
141
156
|
if (error instanceof CodexAppServerSmokeError) {
|
|
142
|
-
|
|
157
|
+
primaryError = error;
|
|
158
|
+
}
|
|
159
|
+
else if (error instanceof CodexAppServerProtocolError) {
|
|
160
|
+
primaryError = new CodexAppServerSmokeError("app_server_protocol_error", redactWithKnownValues(error.message, [options.apiKey, tempRoot, codexHome, repoRoot]));
|
|
143
161
|
}
|
|
144
|
-
|
|
145
|
-
|
|
162
|
+
else {
|
|
163
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
164
|
+
primaryError = new CodexAppServerSmokeError("app_server_protocol_error", redactWithKnownValues(message, [options.apiKey, tempRoot, codexHome, repoRoot]));
|
|
146
165
|
}
|
|
147
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
148
|
-
throw new CodexAppServerSmokeError("app_server_protocol_error", redactWithKnownValues(message, [options.apiKey, tempRoot, codexHome, repoRoot]));
|
|
149
166
|
}
|
|
150
167
|
finally {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
rmSync(tempRoot, { recursive: true, force: true });
|
|
168
|
+
try {
|
|
169
|
+
await invocation.close();
|
|
154
170
|
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
invocation.reportProcessTerminationFailure(error);
|
|
173
|
+
lifecycleError = error;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (primaryError !== undefined) {
|
|
177
|
+
throw primaryError;
|
|
178
|
+
}
|
|
179
|
+
if (lifecycleError !== undefined) {
|
|
180
|
+
throw new CodexAppServerSmokeError("process_lifecycle_failed", lifecycleError instanceof CodexAppServerLifecycleError
|
|
181
|
+
? lifecycleError.message
|
|
182
|
+
: "Codex app-server process lifecycle did not close cleanly.");
|
|
155
183
|
}
|
|
184
|
+
return smokeResult;
|
|
156
185
|
}
|
|
157
186
|
//# sourceMappingURL=smoke.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type StaleCodexTempCleanupResult = {
|
|
2
|
+
scanned_count: number;
|
|
3
|
+
eligible_count: number;
|
|
4
|
+
removed_count: number;
|
|
5
|
+
failed_count: number;
|
|
6
|
+
};
|
|
7
|
+
export declare function cleanupStaleCodexAppServerTempRoots(options?: {
|
|
8
|
+
tempDirectory?: string;
|
|
9
|
+
minimumAgeMs?: number;
|
|
10
|
+
now?: () => Date;
|
|
11
|
+
removeTempRoot?: (root: string) => Promise<void>;
|
|
12
|
+
onIncident?: (incident: {
|
|
13
|
+
code: "stale_temp_cleanup_failed";
|
|
14
|
+
error_code: string;
|
|
15
|
+
}) => void;
|
|
16
|
+
}): Promise<StaleCodexTempCleanupResult>;
|
|
17
|
+
//# sourceMappingURL=stale-temp-cleanup.d.ts.map
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { lstat, readFile, readdir, rm, stat } from "node:fs/promises";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { systemErrorCode } from "../../../process-tree.js";
|
|
5
|
+
import { CODEX_APP_SERVER_OWNER_MARKER_FILE, CODEX_APP_SERVER_TEMP_PREFIXES, } from "./invocation-lifecycle.js";
|
|
6
|
+
const DEFAULT_MINIMUM_AGE_MS = 24 * 60 * 60 * 1_000;
|
|
7
|
+
const MAX_MARKER_BYTES = 4 * 1_024;
|
|
8
|
+
function isRecord(value) {
|
|
9
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10
|
+
}
|
|
11
|
+
function parseMarker(value) {
|
|
12
|
+
if (!isRecord(value) ||
|
|
13
|
+
value.version !== 1 ||
|
|
14
|
+
typeof value.owner_pid !== "number" ||
|
|
15
|
+
!Number.isSafeInteger(value.owner_pid) ||
|
|
16
|
+
value.owner_pid <= 0 ||
|
|
17
|
+
!(value.process_group_id === null ||
|
|
18
|
+
(typeof value.process_group_id === "number" &&
|
|
19
|
+
Number.isSafeInteger(value.process_group_id) &&
|
|
20
|
+
value.process_group_id > 0)) ||
|
|
21
|
+
typeof value.created_at !== "string" ||
|
|
22
|
+
!Number.isFinite(new Date(value.created_at).getTime()) ||
|
|
23
|
+
!(value.keep_temp === undefined || typeof value.keep_temp === "boolean")) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
function processIsAlive(pid) {
|
|
29
|
+
try {
|
|
30
|
+
process.kill(pid, 0);
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
return systemErrorCode(error) !== "ESRCH";
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function processGroupIsAlive(processGroupId) {
|
|
38
|
+
if (process.platform === "win32") {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
process.kill(-processGroupId, 0);
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
return systemErrorCode(error) !== "ESRCH";
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function hasManagedPrefix(name) {
|
|
50
|
+
return CODEX_APP_SERVER_TEMP_PREFIXES.some((prefix) => name.startsWith(prefix));
|
|
51
|
+
}
|
|
52
|
+
async function readOwnerMarker(root) {
|
|
53
|
+
try {
|
|
54
|
+
const markerPath = join(root, CODEX_APP_SERVER_OWNER_MARKER_FILE);
|
|
55
|
+
const markerStat = await stat(markerPath);
|
|
56
|
+
if (!markerStat.isFile() || markerStat.size > MAX_MARKER_BYTES) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
return parseMarker(JSON.parse(await readFile(markerPath, "utf8")));
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export async function cleanupStaleCodexAppServerTempRoots(options = {}) {
|
|
66
|
+
const tempDirectory = options.tempDirectory ?? tmpdir();
|
|
67
|
+
const nowMs = (options.now ?? (() => new Date()))().getTime();
|
|
68
|
+
const minimumAgeMs = options.minimumAgeMs ?? DEFAULT_MINIMUM_AGE_MS;
|
|
69
|
+
const result = {
|
|
70
|
+
scanned_count: 0,
|
|
71
|
+
eligible_count: 0,
|
|
72
|
+
removed_count: 0,
|
|
73
|
+
failed_count: 0,
|
|
74
|
+
};
|
|
75
|
+
let names;
|
|
76
|
+
try {
|
|
77
|
+
names = await readdir(tempDirectory);
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
options.onIncident?.({
|
|
81
|
+
code: "stale_temp_cleanup_failed",
|
|
82
|
+
error_code: systemErrorCode(error),
|
|
83
|
+
});
|
|
84
|
+
return { ...result, failed_count: 1 };
|
|
85
|
+
}
|
|
86
|
+
for (const name of names) {
|
|
87
|
+
if (!hasManagedPrefix(name)) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
result.scanned_count += 1;
|
|
91
|
+
const root = join(tempDirectory, name);
|
|
92
|
+
let rootStat;
|
|
93
|
+
try {
|
|
94
|
+
rootStat = await lstat(root);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
if (!rootStat.isDirectory() || rootStat.isSymbolicLink()) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
const marker = await readOwnerMarker(root);
|
|
103
|
+
if (marker === null || marker.keep_temp === true) {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
const createdAtMs = new Date(marker.created_at).getTime();
|
|
107
|
+
const lastTouchedMs = Math.max(createdAtMs, rootStat.mtimeMs);
|
|
108
|
+
if (nowMs - lastTouchedMs < minimumAgeMs) {
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
if (processIsAlive(marker.owner_pid) ||
|
|
112
|
+
(marker.process_group_id !== null && processGroupIsAlive(marker.process_group_id))) {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
result.eligible_count += 1;
|
|
116
|
+
try {
|
|
117
|
+
await (options.removeTempRoot ?? ((target) => rm(target, { recursive: true, force: true })))(root);
|
|
118
|
+
result.removed_count += 1;
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
result.failed_count += 1;
|
|
122
|
+
options.onIncident?.({
|
|
123
|
+
code: "stale_temp_cleanup_failed",
|
|
124
|
+
error_code: systemErrorCode(error),
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=stale-temp-cleanup.js.map
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { ActivityRef, TaskId } from "@tutti/shared/ids";
|
|
2
2
|
import type { CodexAppServerApprovalPolicy } from "../codex-app-server.js";
|
|
3
3
|
import { type CodexAppServerJsonRpcError, type CodexAppServerJsonRpcServerRequest } from "./json-rpc.js";
|
|
4
|
+
import { type CodexAppServerLifecycleIncident } from "./invocation-lifecycle.js";
|
|
5
|
+
import { type CodexAppServerInvocationCoordinator, type CodexAppServerInvocationLease } from "./invocation-coordinator.js";
|
|
4
6
|
import { type CodexAppServerRuntimeTelemetryOptions } from "./runtime-telemetry.js";
|
|
5
7
|
import { type CodexAppServerAgentContextRuntime, type CodexAppServerSkillSelectionName } from "./skills.js";
|
|
6
8
|
import { type OpenAiTokenUsage } from "../token-usage.js";
|
|
@@ -54,6 +56,10 @@ export type CodexAppServerWorkspaceWriteRunInput<TOutput> = {
|
|
|
54
56
|
turnTimeoutMs?: number;
|
|
55
57
|
baseEnv?: NodeJS.ProcessEnv;
|
|
56
58
|
runtimeTelemetry?: CodexAppServerRuntimeTelemetryOptions;
|
|
59
|
+
onLifecycleIncident?: (incident: CodexAppServerLifecycleIncident) => void;
|
|
60
|
+
invocationCoordinator?: CodexAppServerInvocationCoordinator;
|
|
61
|
+
/** @internal Set only by the coordinator wrapper. */
|
|
62
|
+
invocationLease?: CodexAppServerInvocationLease;
|
|
57
63
|
};
|
|
58
64
|
export type CodexAppServerWorkspaceWriteRunResult<TOutput> = {
|
|
59
65
|
output: TOutput;
|
|
@@ -80,9 +86,9 @@ export type CodexAppServerWorkspaceWriteRunErrorDetails = {
|
|
|
80
86
|
stderr_excerpt?: string;
|
|
81
87
|
};
|
|
82
88
|
export declare class CodexAppServerWorkspaceWriteRunError extends Error {
|
|
83
|
-
readonly code: "app_server_protocol_error" | "auth_failed" | "thread_start_failed" | "turn_failed" | "turn_timeout" | "unexpected_server_request" | "skill_selection_failed" | "output_parse_failed" | "output_validation_failed" | "secret_leak_detected";
|
|
89
|
+
readonly code: "app_server_protocol_error" | "auth_failed" | "thread_start_failed" | "turn_failed" | "turn_timeout" | "unexpected_server_request" | "skill_selection_failed" | "output_parse_failed" | "output_validation_failed" | "secret_leak_detected" | "process_lifecycle_failed" | "admission_unavailable";
|
|
84
90
|
readonly details: CodexAppServerWorkspaceWriteRunErrorDetails;
|
|
85
|
-
constructor(code: "app_server_protocol_error" | "auth_failed" | "thread_start_failed" | "turn_failed" | "turn_timeout" | "unexpected_server_request" | "skill_selection_failed" | "output_parse_failed" | "output_validation_failed" | "secret_leak_detected", message: string, details?: CodexAppServerWorkspaceWriteRunErrorDetails);
|
|
91
|
+
constructor(code: "app_server_protocol_error" | "auth_failed" | "thread_start_failed" | "turn_failed" | "turn_timeout" | "unexpected_server_request" | "skill_selection_failed" | "output_parse_failed" | "output_validation_failed" | "secret_leak_detected" | "process_lifecycle_failed" | "admission_unavailable", message: string, details?: CodexAppServerWorkspaceWriteRunErrorDetails);
|
|
86
92
|
}
|
|
87
93
|
export declare function runCodexAppServerWorkspaceWriteRun<TOutput>(options: CodexAppServerWorkspaceWriteRunInput<TOutput>): Promise<CodexAppServerWorkspaceWriteRunResult<TOutput>>;
|
|
88
94
|
//# sourceMappingURL=workspace-write-run.d.ts.map
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
|
-
import { mkdirSync, mkdtempSync
|
|
2
|
+
import { mkdirSync, mkdtempSync } from "node:fs";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { buildCodexAppServerProcessPlan } from "../codex-app-server.js";
|
|
6
6
|
import { DEFAULT_OPENAI_MODEL } from "../model-config.js";
|
|
7
7
|
import { CodexAppServerJsonRpcClient, CodexAppServerProtocolError, } from "./json-rpc.js";
|
|
8
|
+
import { CodexAppServerInvocation, CodexAppServerLifecycleError, createManagedProcess, } from "./invocation-lifecycle.js";
|
|
9
|
+
import { CodexAppServerAdmissionError, } from "./invocation-coordinator.js";
|
|
8
10
|
import { createCodexAppServerRuntimeObserver, } from "./runtime-telemetry.js";
|
|
9
11
|
import { createWorkspaceWriteSandboxPolicy } from "./sandbox-policy.js";
|
|
10
12
|
import { buildCodexAppServerProviderConfigOverrides, resolveCodexAppServerModelProvider, } from "./provider-config.js";
|
|
@@ -147,6 +149,26 @@ function parseWorkspaceWriteStructuredJson(text) {
|
|
|
147
149
|
throw new CodexAppServerWorkspaceWriteRunError("output_parse_failed", "Codex app-server returned malformed JSON.");
|
|
148
150
|
}
|
|
149
151
|
export async function runCodexAppServerWorkspaceWriteRun(options) {
|
|
152
|
+
if (options.invocationCoordinator !== undefined && options.invocationLease === undefined) {
|
|
153
|
+
let lease;
|
|
154
|
+
try {
|
|
155
|
+
lease = await options.invocationCoordinator.acquire();
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
throw new CodexAppServerWorkspaceWriteRunError("admission_unavailable", error instanceof CodexAppServerAdmissionError
|
|
159
|
+
? error.message
|
|
160
|
+
: "Codex app-server admission is unavailable.");
|
|
161
|
+
}
|
|
162
|
+
try {
|
|
163
|
+
return await runCodexAppServerWorkspaceWriteRun({
|
|
164
|
+
...options,
|
|
165
|
+
invocationLease: lease,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
finally {
|
|
169
|
+
lease.release();
|
|
170
|
+
}
|
|
171
|
+
}
|
|
150
172
|
let skillInputs;
|
|
151
173
|
let skillsListWarmup;
|
|
152
174
|
let contextRuntimeHint;
|
|
@@ -198,11 +220,13 @@ export async function runCodexAppServerWorkspaceWriteRun(options) {
|
|
|
198
220
|
configOverrides: buildCodexAppServerProviderConfigOverrides(options),
|
|
199
221
|
...(options.codexCommand === undefined ? {} : { codexCommand: options.codexCommand }),
|
|
200
222
|
});
|
|
201
|
-
const
|
|
223
|
+
const managedProcess = createManagedProcess(spawn(processPlan.command, processPlan.args, {
|
|
202
224
|
cwd: process.cwd(),
|
|
225
|
+
detached: process.platform !== "win32",
|
|
203
226
|
env: createCodexSpawnEnv(codexHome, options.baseEnv ?? process.env),
|
|
204
227
|
stdio: "pipe",
|
|
205
|
-
});
|
|
228
|
+
}));
|
|
229
|
+
const child = managedProcess.child;
|
|
206
230
|
const runtimeObserver = options.runtimeTelemetry === undefined
|
|
207
231
|
? undefined
|
|
208
232
|
: createCodexAppServerRuntimeObserver(options.runtimeTelemetry);
|
|
@@ -214,6 +238,15 @@ export async function runCodexAppServerWorkspaceWriteRun(options) {
|
|
|
214
238
|
onServerRequest: runtimeObserver.serverRequest,
|
|
215
239
|
}),
|
|
216
240
|
});
|
|
241
|
+
const invocation = new CodexAppServerInvocation({
|
|
242
|
+
managedProcess,
|
|
243
|
+
tempRoot,
|
|
244
|
+
closeProtocol: () => client.close(),
|
|
245
|
+
...(options.onLifecycleIncident === undefined
|
|
246
|
+
? {}
|
|
247
|
+
: { onIncident: options.onLifecycleIncident }),
|
|
248
|
+
});
|
|
249
|
+
options.invocationLease?.setCloser(() => invocation.close());
|
|
217
250
|
const sensitiveValues = [
|
|
218
251
|
options.apiKey,
|
|
219
252
|
tempRoot,
|
|
@@ -233,6 +266,9 @@ export async function runCodexAppServerWorkspaceWriteRun(options) {
|
|
|
233
266
|
options.apiKey,
|
|
234
267
|
...(contextRuntimeHint?.sensitiveValues ?? []),
|
|
235
268
|
];
|
|
269
|
+
let primaryError;
|
|
270
|
+
let runResult;
|
|
271
|
+
let lifecycleError;
|
|
236
272
|
try {
|
|
237
273
|
await client.request("initialize", {
|
|
238
274
|
clientInfo: {
|
|
@@ -358,7 +394,7 @@ export async function runCodexAppServerWorkspaceWriteRun(options) {
|
|
|
358
394
|
throw new CodexAppServerWorkspaceWriteRunError("secret_leak_detected", "Codex app-server output contained a sensitive runtime value.");
|
|
359
395
|
}
|
|
360
396
|
const usage = extractCodexAppServerTokenUsage(client.notifications);
|
|
361
|
-
|
|
397
|
+
runResult = {
|
|
362
398
|
output: parsed,
|
|
363
399
|
model,
|
|
364
400
|
turn_status: "completed",
|
|
@@ -373,18 +409,34 @@ export async function runCodexAppServerWorkspaceWriteRun(options) {
|
|
|
373
409
|
}
|
|
374
410
|
catch (error) {
|
|
375
411
|
if (error instanceof CodexAppServerWorkspaceWriteRunError) {
|
|
376
|
-
|
|
412
|
+
primaryError = error;
|
|
377
413
|
}
|
|
378
|
-
if (error instanceof CodexAppServerProtocolError) {
|
|
379
|
-
|
|
414
|
+
else if (error instanceof CodexAppServerProtocolError) {
|
|
415
|
+
primaryError = new CodexAppServerWorkspaceWriteRunError("app_server_protocol_error", redactWithKnownValues(error.message, sensitiveValues));
|
|
416
|
+
}
|
|
417
|
+
else {
|
|
418
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
419
|
+
primaryError = new CodexAppServerWorkspaceWriteRunError("app_server_protocol_error", redactWithKnownValues(message, sensitiveValues));
|
|
380
420
|
}
|
|
381
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
382
|
-
throw new CodexAppServerWorkspaceWriteRunError("app_server_protocol_error", redactWithKnownValues(message, sensitiveValues));
|
|
383
421
|
}
|
|
384
422
|
finally {
|
|
385
423
|
runtimeObserver?.flush();
|
|
386
|
-
|
|
387
|
-
|
|
424
|
+
try {
|
|
425
|
+
await invocation.close();
|
|
426
|
+
}
|
|
427
|
+
catch (error) {
|
|
428
|
+
invocation.reportProcessTerminationFailure(error);
|
|
429
|
+
lifecycleError = error;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
if (primaryError !== undefined) {
|
|
433
|
+
throw primaryError;
|
|
434
|
+
}
|
|
435
|
+
if (lifecycleError !== undefined) {
|
|
436
|
+
throw new CodexAppServerWorkspaceWriteRunError("process_lifecycle_failed", lifecycleError instanceof CodexAppServerLifecycleError
|
|
437
|
+
? lifecycleError.message
|
|
438
|
+
: "Codex app-server process lifecycle did not close cleanly.");
|
|
388
439
|
}
|
|
440
|
+
return runResult;
|
|
389
441
|
}
|
|
390
442
|
//# sourceMappingURL=workspace-write-run.js.map
|
|
@@ -2,6 +2,8 @@ import type { ProjectId } from "@tutti/shared/ids";
|
|
|
2
2
|
import { type ReadOnlyChatAssistantModel } from "../../chat-assistant/index.js";
|
|
3
3
|
import { type OpenAiProviderConfig } from "./provider-config.js";
|
|
4
4
|
import type { CodexAppServerAgentContextRuntime } from "./app-server/skills.js";
|
|
5
|
+
import type { CodexAppServerInvocationCoordinator } from "./app-server/invocation-coordinator.js";
|
|
6
|
+
import type { CodexAppServerLifecycleIncident } from "./app-server/invocation-lifecycle.js";
|
|
5
7
|
import type { ProviderUsageRecorder } from "../../provider-usage/index.js";
|
|
6
8
|
export type OpenAiReadOnlyChatAssistantModelOptions = {
|
|
7
9
|
config: OpenAiProviderConfig;
|
|
@@ -16,6 +18,8 @@ export type OpenAiReadOnlyChatAssistantModelOptions = {
|
|
|
16
18
|
turnTimeoutMs?: number;
|
|
17
19
|
baseEnv?: NodeJS.ProcessEnv;
|
|
18
20
|
recordUsage?: ProviderUsageRecorder;
|
|
21
|
+
invocationCoordinator?: CodexAppServerInvocationCoordinator;
|
|
22
|
+
onLifecycleIncident?: (incident: CodexAppServerLifecycleIncident) => void;
|
|
19
23
|
};
|
|
20
24
|
export type ProjectOpenAiReadOnlyChatAssistantModelOptions = {
|
|
21
25
|
tuttiHome: string;
|
|
@@ -23,6 +27,8 @@ export type ProjectOpenAiReadOnlyChatAssistantModelOptions = {
|
|
|
23
27
|
workspaceRoot: string;
|
|
24
28
|
agentContext?: CodexAppServerAgentContextRuntime;
|
|
25
29
|
recordUsage?: ProviderUsageRecorder;
|
|
30
|
+
invocationCoordinator?: CodexAppServerInvocationCoordinator;
|
|
31
|
+
onLifecycleIncident?: (incident: CodexAppServerLifecycleIncident) => void;
|
|
26
32
|
};
|
|
27
33
|
export type ReadOnlyChatAssistantModelResolution = {
|
|
28
34
|
kind: "ready";
|
|
@@ -31,6 +31,12 @@ export function createOpenAiReadOnlyChatAssistantModel(options) {
|
|
|
31
31
|
: { requestTimeoutMs: options.requestTimeoutMs }),
|
|
32
32
|
...(options.turnTimeoutMs === undefined ? {} : { turnTimeoutMs: options.turnTimeoutMs }),
|
|
33
33
|
...(options.baseEnv === undefined ? {} : { baseEnv: options.baseEnv }),
|
|
34
|
+
...(options.invocationCoordinator === undefined
|
|
35
|
+
? {}
|
|
36
|
+
: { invocationCoordinator: options.invocationCoordinator }),
|
|
37
|
+
...(options.onLifecycleIncident === undefined
|
|
38
|
+
? {}
|
|
39
|
+
: { onLifecycleIncident: options.onLifecycleIncident }),
|
|
34
40
|
});
|
|
35
41
|
if (options.recordUsage !== undefined && result.usage !== undefined) {
|
|
36
42
|
options.recordUsage({
|
|
@@ -65,6 +71,12 @@ export function resolveProjectOpenAiReadOnlyChatAssistantModel(options) {
|
|
|
65
71
|
userSkillsRoot: getProjectUserSkillsRoot(options.tuttiHome, options.projectId),
|
|
66
72
|
...(options.agentContext === undefined ? {} : { agentContext: options.agentContext }),
|
|
67
73
|
...(options.recordUsage === undefined ? {} : { recordUsage: options.recordUsage }),
|
|
74
|
+
...(options.invocationCoordinator === undefined
|
|
75
|
+
? {}
|
|
76
|
+
: { invocationCoordinator: options.invocationCoordinator }),
|
|
77
|
+
...(options.onLifecycleIncident === undefined
|
|
78
|
+
? {}
|
|
79
|
+
: { onLifecycleIncident: options.onLifecycleIncident }),
|
|
68
80
|
}),
|
|
69
81
|
};
|
|
70
82
|
}
|
package/dist/run-engine/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createActivityRef } from "@tutti/shared/ids";
|
|
2
|
+
import { safeRuntimeFailureSummary } from "../runtime-failures.js";
|
|
2
3
|
export class RunEngine {
|
|
3
4
|
active = null;
|
|
4
5
|
lastConclusion = null;
|
|
@@ -43,7 +44,7 @@ export class RunEngine {
|
|
|
43
44
|
catch (error) {
|
|
44
45
|
this.finishActive(activityRef, {
|
|
45
46
|
kind: "failed",
|
|
46
|
-
summary:
|
|
47
|
+
summary: safeRuntimeFailureSummary("Run", error, "run_failed"),
|
|
47
48
|
}, options.onTransition);
|
|
48
49
|
}
|
|
49
50
|
};
|