@bastani/atomic 0.9.34 → 0.9.35-alpha.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/CHANGELOG.md +16 -0
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/CHANGELOG.md +6 -0
- package/dist/builtin/mcp/OAUTH.md +1 -1
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +11 -0
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +209 -77
- package/dist/builtin/workflows/src/index.js +28 -9
- package/dist/core/compaction/utils.d.ts +6 -0
- package/dist/core/compaction/utils.d.ts.map +1 -1
- package/dist/core/compaction/utils.js +6 -7
- package/dist/core/compaction/utils.js.map +1 -1
- package/dist/extensions/codemode/tool.js +1 -1
- package/dist/extensions/codemode/tool.js.map +1 -1
- package/dist/extensions/mcp/client/oauth/errors.d.ts +3 -2
- package/dist/extensions/mcp/client/oauth/errors.d.ts.map +1 -1
- package/dist/extensions/mcp/client/oauth/errors.js +3 -1
- package/dist/extensions/mcp/client/oauth/errors.js.map +1 -1
- package/dist/extensions/mcp/client/oauth/flow.d.ts.map +1 -1
- package/dist/extensions/mcp/client/oauth/flow.js +5 -4
- package/dist/extensions/mcp/client/oauth/flow.js.map +1 -1
- package/docs/codemode.md +1 -1
- package/docs/compaction/reference.md +2 -1
- package/docs/models/reference.md +3 -1
- package/docs/sdk.md +11 -1
- package/docs/workflows/operations.md +3 -1
- package/npm-shrinkwrap.json +32 -32
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.9.35-alpha.1] - 2026-10-12
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- `session.workflows.resume(runId)` now adopts a paused run that was launched through the model-facing `workflow` tool once its owning session has been disposed, in the same process or after the owning process exits. Disposing a session quits its in-flight runs at their last checkpoint and durably records that it released its checkpointed paused runs; the adopting session becomes the owner and the run continues under the same UUID. Runs whose owner is still open, runs whose owner crashed without disposing, and finished runs are still refused ([#3566](https://github.com/bastani-inc/atomic/issues/3566)).
|
|
10
|
+
- Switching sessions with `/new`, `/fork`, or `/resume` now releases the previous session's paused workflow runs, the same way disposing a session does. The model in the new session can inspect them with the `workflow` tool's `status` and `stages` actions and resume them, and `session.workflows.resume(runId)` can adopt them; adoption, including the `/workflow resume <id>` slash command, transfers ownership to the resuming session. The new session lists the released runs with their `/workflow resume <id>` commands, and, in the process that released it, a run another session already adopted now reports that it is owned by another session. `/reload` still keeps runs executing and releases nothing ([#3569](https://github.com/bastani-inc/atomic/issues/3569)).
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Changed `serializeConversation()` (branch summaries, resume-picker session summaries, and the policy-refusal summary fallback) to omit thinking blocks; replayed thinking is often not in the live context, so including it could make a summarization request larger than the context it summarizes and fail. Verbatim line compaction still serializes thinking lines.
|
|
15
|
+
- Changed `openai-codex/gpt-6.1-sol` to a 500,000-token context window (up from 272,000) with no long-context price tier on Standard, Fast, or Ultrafast. OpenAI raised GPT-6.1 Sol's default context to 500k in Codex & Work for ChatGPT subscriptions and does not charge long-context fees when usage draws from the subscription. `openai/gpt-6.1-sol` and the other Codex models are unchanged.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- Fixed the code mode tool description claiming every failed tool call throws; a tool that declares an output schema resolves with its value on failure too (for example `bash` with a non-zero exit), so scripts should check its fields.
|
|
20
|
+
|
|
5
21
|
## [0.9.34] - 2026-10-11
|
|
6
22
|
|
|
7
23
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/intercom",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.35-alpha.1",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension providing a private coordination channel between parent and child agent sessions. Fork of: https://github.com/nicobailon/pi-intercom",
|
|
6
6
|
"contributors": [
|
|
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.9.35-alpha.1] - 2026-10-12
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Fixed OAuth exchanging an authorization code whose `iss` parameter could not be checked because no authorization server metadata was discovered. It now throws `OAuthIssuerMismatchError`, whose `expected` is `undefined` in that case (RFC 9207). Reported by [@AizenvoltPrime](https://github.com/AizenvoltPrime).
|
|
15
|
+
|
|
10
16
|
## [0.9.28] - 2026-10-08
|
|
11
17
|
|
|
12
18
|
### Fixed
|
|
@@ -71,7 +71,7 @@ Atomic normally finds the authorization server through protected resource metada
|
|
|
71
71
|
|
|
72
72
|
The document may use RFC 8414 or OpenID Connect discovery. Atomic trusts it as configured, including its issuer, so only point it at a document you trust. The URL must use HTTPS except for HTTP on `localhost`, `127.0.0.1`, or `[::1]`.
|
|
73
73
|
|
|
74
|
-
An authorization response's `iss` must name the flow's authorization server. If the metadata promises `authorization_response_iss_parameter_supported`, the response must include `iss`. Mismatched or required-but-missing issuers are rejected before code exchange under RFC 9207. Pasted redirect URLs have the same checks as browser callbacks.
|
|
74
|
+
An authorization response's `iss` must name the flow's authorization server. If the metadata promises `authorization_response_iss_parameter_supported`, the response must include `iss`. Mismatched or required-but-missing issuers are rejected before code exchange under RFC 9207, and when no authorization server metadata was discovered any `iss` is rejected because there is no issuer to compare it with. Pasted redirect URLs have the same checks as browser callbacks.
|
|
75
75
|
|
|
76
76
|
## Tokens and refresh
|
|
77
77
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/subagents",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.35-alpha.1",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension for delegating tasks to subagents with parallel execution. Fork of: https://github.com/nicobailon/pi-subagents",
|
|
6
6
|
"contributors": [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/web-access",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.35-alpha.1",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension for web search, URL fetching, GitHub repo cloning, PDF/video extraction. Fork of: https://github.com/nicobailon/pi-web-access",
|
|
6
6
|
"contributors": [
|
|
@@ -6,6 +6,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.9.35-alpha.1] - 2026-10-12
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- `session.workflows.resume(runId)` now adopts a paused run that was launched through the model-facing `workflow` tool once its owning session has been disposed, in the same process or after the owning process exits. Disposing a session quits its in-flight runs at their last checkpoint and durably records that it released its checkpointed paused runs; the adopting session becomes the owner and the run continues under the same UUID. Runs whose owner is still open, runs whose owner crashed without disposing, and finished runs are still refused ([#3566](https://github.com/bastani-inc/atomic/issues/3566)).
|
|
14
|
+
- Switching sessions with `/new`, `/fork`, or `/resume` now releases the previous session's paused workflow runs, the same way disposing a session does. The model in the new session can inspect them with the `workflow` tool's `status` and `stages` actions and resume them, and `session.workflows.resume(runId)` can adopt them; adoption, including the `/workflow resume <id>` slash command, transfers ownership to the resuming session. The new session lists the released runs with their `/workflow resume <id>` commands, and, in the process that released it, a run another session already adopted now reports that it is owned by another session. `/reload` still keeps runs executing and releases nothing ([#3569](https://github.com/bastani-inc/atomic/issues/3569)).
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Fixed an SDK session started after another session in the same process was disposed falling back to non-durable workflows with `Managed Postgres health observer is stopped.`. Releasing the last session now discards the stopped workflow database configuration, so the next session starts a fresh managed Postgres and launches durably ([#3565](https://github.com/bastani-inc/atomic/issues/3565)).
|
|
19
|
+
|
|
9
20
|
## [0.9.33] - 2026-10-10
|
|
10
21
|
|
|
11
22
|
### Fixed
|
|
@@ -1001,6 +1001,7 @@ class InMemoryDurableBackend {
|
|
|
1001
1001
|
...handle.invocationCwd !== undefined ? { invocationCwd: handle.invocationCwd } : existing?.handle.invocationCwd !== undefined ? { invocationCwd: existing.handle.invocationCwd } : {},
|
|
1002
1002
|
...handle.origin !== undefined ? { origin: handle.origin } : existing?.handle.origin !== undefined ? { origin: existing.handle.origin } : {},
|
|
1003
1003
|
modelOwner: authoritativeOwner ? handle.modelOwner : existing?.handle.modelOwner ?? handle.modelOwner,
|
|
1004
|
+
...handle.releasedModelOwner !== undefined ? { releasedModelOwner: handle.releasedModelOwner } : {},
|
|
1004
1005
|
...handle.workflowCwd !== undefined ? { workflowCwd: handle.workflowCwd } : existing?.handle.workflowCwd !== undefined ? { workflowCwd: existing.handle.workflowCwd } : {},
|
|
1005
1006
|
...handle.repositoryRoot !== undefined ? { repositoryRoot: handle.repositoryRoot } : existing?.handle.repositoryRoot !== undefined ? { repositoryRoot: existing.handle.repositoryRoot } : {},
|
|
1006
1007
|
...handle.gitWorktreeRoot !== undefined ? { gitWorktreeRoot: handle.gitWorktreeRoot } : existing?.handle.gitWorktreeRoot !== undefined ? { gitWorktreeRoot: existing.handle.gitWorktreeRoot } : {},
|
|
@@ -1214,14 +1215,20 @@ class InMemoryDurableBackend {
|
|
|
1214
1215
|
if (pendingPrompts !== undefined)
|
|
1215
1216
|
this.promptReservations.delete(workflowId);
|
|
1216
1217
|
}
|
|
1217
|
-
async transitionWorkflowStatus(workflowId, expected, status, pendingPrompts, resumable, expectedUpdatedAt, modelOwner) {
|
|
1218
|
+
async transitionWorkflowStatus(workflowId, expected, status, pendingPrompts, resumable, expectedUpdatedAt, modelOwner, releasedModelOwner) {
|
|
1218
1219
|
const record = this.workflows.get(workflowId);
|
|
1219
1220
|
const current = record?.handle;
|
|
1220
1221
|
if (current === undefined || !expected.includes(current.status) || expectedUpdatedAt !== undefined && current.updatedAt !== expectedUpdatedAt)
|
|
1221
1222
|
return false;
|
|
1222
1223
|
this.setWorkflowStatus(workflowId, status, pendingPrompts, resumable);
|
|
1223
|
-
if (
|
|
1224
|
-
|
|
1224
|
+
if (record !== undefined) {
|
|
1225
|
+
const { releasedModelOwner: _previousRelease, ...settled } = record.handle;
|
|
1226
|
+
record.handle = {
|
|
1227
|
+
...settled,
|
|
1228
|
+
...modelOwner !== undefined ? { modelOwner } : {},
|
|
1229
|
+
...releasedModelOwner !== undefined ? { releasedModelOwner } : {}
|
|
1230
|
+
};
|
|
1231
|
+
}
|
|
1225
1232
|
return true;
|
|
1226
1233
|
}
|
|
1227
1234
|
adjustPendingPrompts(workflowId, delta) {
|
|
@@ -1303,6 +1310,7 @@ class InMemoryDurableBackend {
|
|
|
1303
1310
|
...h.invocationCwd !== undefined ? { invocationCwd: h.invocationCwd } : {},
|
|
1304
1311
|
...h.origin !== undefined ? { origin: h.origin } : {},
|
|
1305
1312
|
modelOwner: h.modelOwner,
|
|
1313
|
+
...h.releasedModelOwner !== undefined ? { releasedModelOwner: h.releasedModelOwner } : {},
|
|
1306
1314
|
...h.workflowCwd !== undefined ? { workflowCwd: h.workflowCwd } : {},
|
|
1307
1315
|
...h.repositoryRoot !== undefined ? { repositoryRoot: h.repositoryRoot } : {},
|
|
1308
1316
|
...h.gitWorktreeRoot !== undefined ? { gitWorktreeRoot: h.gitWorktreeRoot } : {},
|
|
@@ -4344,6 +4352,7 @@ function encodeMetadata(metadata) {
|
|
|
4344
4352
|
...metadata.failedToolNodeId !== undefined ? { failedToolNodeId: metadata.failedToolNodeId } : {},
|
|
4345
4353
|
...metadata.origin !== undefined ? { origin: metadata.origin } : {},
|
|
4346
4354
|
modelOwner: metadata.modelOwner,
|
|
4355
|
+
...metadata.releasedModelOwner !== undefined ? { releasedModelOwner: metadata.releasedModelOwner } : {},
|
|
4347
4356
|
...metadata.invocationCwd !== undefined ? { invocationCwd: metadata.invocationCwd } : {},
|
|
4348
4357
|
...metadata.workflowCwd !== undefined ? { workflowCwd: metadata.workflowCwd } : {},
|
|
4349
4358
|
...metadata.repositoryRoot !== undefined ? { repositoryRoot: metadata.repositoryRoot } : {},
|
|
@@ -4392,7 +4401,7 @@ function parseDurableWorkflowMetadata(value2, workflowId) {
|
|
|
4392
4401
|
return;
|
|
4393
4402
|
const possibleStages = coercePossibleStages(serialized.possibleStages);
|
|
4394
4403
|
const metadata = value2;
|
|
4395
|
-
if (metadata.workflowId !== workflowId || typeof metadata.workflowId !== "string" || typeof metadata.name !== "string" || typeof metadata.inputs !== "object" || metadata.inputs === null || Array.isArray(metadata.inputs) || typeof metadata.status !== "string" || !isDurableWorkflowStatus(metadata.status) || typeof metadata.completedCheckpoints !== "number" || typeof metadata.createdAt !== "number" || typeof metadata.pendingPrompts !== "number" || typeof metadata.promptReservationEpoch !== "string" || typeof metadata.updatedAt !== "number" || metadata.ownerExecutorId !== undefined && typeof metadata.ownerExecutorId !== "string" || metadata.transitionClaimId !== undefined && typeof metadata.transitionClaimId !== "string" || metadata.legacyRecoveryPending !== undefined && metadata.legacyRecoveryPending !== true || metadata.sessionFile !== undefined && typeof metadata.sessionFile !== "string" || metadata.label !== undefined && typeof metadata.label !== "string" || metadata.rootWorkflowId !== undefined && typeof metadata.rootWorkflowId !== "string" || metadata.resumable !== undefined && typeof metadata.resumable !== "boolean" || metadata.exited !== undefined && typeof metadata.exited !== "boolean" || metadata.exitReason !== undefined && typeof metadata.exitReason !== "string" || metadata.error !== undefined && typeof metadata.error !== "string" || metadata.failureKind !== undefined && !isWorkflowFailureKind(metadata.failureKind) || metadata.failureCode !== undefined && !isWorkflowFailureCode(metadata.failureCode) || metadata.failureRecoverability !== undefined && !isWorkflowFailureRecoverability(metadata.failureRecoverability) || metadata.failureDisposition !== undefined && !isWorkflowFailureDisposition(metadata.failureDisposition) || metadata.failedToolNodeId !== undefined && typeof metadata.failedToolNodeId !== "string" || metadata.invocationCwd !== undefined && typeof metadata.invocationCwd !== "string" || metadata.workflowCwd !== undefined && typeof metadata.workflowCwd !== "string" || metadata.repositoryRoot !== undefined && typeof metadata.repositoryRoot !== "string" || metadata.gitWorktreeRoot !== undefined && typeof metadata.gitWorktreeRoot !== "string")
|
|
4404
|
+
if (metadata.workflowId !== workflowId || typeof metadata.workflowId !== "string" || typeof metadata.name !== "string" || typeof metadata.inputs !== "object" || metadata.inputs === null || Array.isArray(metadata.inputs) || typeof metadata.status !== "string" || !isDurableWorkflowStatus(metadata.status) || typeof metadata.completedCheckpoints !== "number" || typeof metadata.createdAt !== "number" || typeof metadata.pendingPrompts !== "number" || typeof metadata.promptReservationEpoch !== "string" || typeof metadata.updatedAt !== "number" || metadata.ownerExecutorId !== undefined && typeof metadata.ownerExecutorId !== "string" || metadata.transitionClaimId !== undefined && typeof metadata.transitionClaimId !== "string" || metadata.legacyRecoveryPending !== undefined && metadata.legacyRecoveryPending !== true || metadata.sessionFile !== undefined && typeof metadata.sessionFile !== "string" || metadata.label !== undefined && typeof metadata.label !== "string" || metadata.rootWorkflowId !== undefined && typeof metadata.rootWorkflowId !== "string" || metadata.resumable !== undefined && typeof metadata.resumable !== "boolean" || metadata.exited !== undefined && typeof metadata.exited !== "boolean" || metadata.exitReason !== undefined && typeof metadata.exitReason !== "string" || metadata.error !== undefined && typeof metadata.error !== "string" || metadata.failureKind !== undefined && !isWorkflowFailureKind(metadata.failureKind) || metadata.failureCode !== undefined && !isWorkflowFailureCode(metadata.failureCode) || metadata.failureRecoverability !== undefined && !isWorkflowFailureRecoverability(metadata.failureRecoverability) || metadata.failureDisposition !== undefined && !isWorkflowFailureDisposition(metadata.failureDisposition) || metadata.failedToolNodeId !== undefined && typeof metadata.failedToolNodeId !== "string" || metadata.releasedModelOwner !== undefined && typeof metadata.releasedModelOwner !== "string" || metadata.invocationCwd !== undefined && typeof metadata.invocationCwd !== "string" || metadata.workflowCwd !== undefined && typeof metadata.workflowCwd !== "string" || metadata.repositoryRoot !== undefined && typeof metadata.repositoryRoot !== "string" || metadata.gitWorktreeRoot !== undefined && typeof metadata.gitWorktreeRoot !== "string")
|
|
4396
4405
|
return;
|
|
4397
4406
|
const { origin, possibleStages: rawPossibleStages, ...metadataWithoutOrigin } = metadata;
|
|
4398
4407
|
return {
|
|
@@ -36438,7 +36447,9 @@ async function configureDbosDurableBackend(config) {
|
|
|
36438
36447
|
throw new Error("Existing workflow executor has no database ownership fence; restart the host before recovering workflows");
|
|
36439
36448
|
let launch = owner.active?.launch ?? (() => sdk.launch());
|
|
36440
36449
|
let checkReady;
|
|
36441
|
-
if (existing === undefined) {
|
|
36450
|
+
if (existing === undefined || owner.active === undefined) {
|
|
36451
|
+
if (owner.executorFence?.closed)
|
|
36452
|
+
owner.executorId = undefined;
|
|
36442
36453
|
const url = effectiveSystemDatabaseUrl(config?.systemDatabaseUrl);
|
|
36443
36454
|
await Promise.resolve().then(() => init_dbos_admission_config());
|
|
36444
36455
|
const database = configureAdmissionDatabase(sdk, {
|
|
@@ -36918,7 +36929,7 @@ class DbosDurableBackend {
|
|
|
36918
36929
|
await this.writeMetadata(workflowId);
|
|
36919
36930
|
});
|
|
36920
36931
|
}
|
|
36921
|
-
async transitionWorkflowStatus(workflowId, expected, status, pendingPrompts, resumable, expectedUpdatedAt, modelOwner) {
|
|
36932
|
+
async transitionWorkflowStatus(workflowId, expected, status, pendingPrompts, resumable, expectedUpdatedAt, modelOwner, releasedModelOwner) {
|
|
36922
36933
|
this.ensureGeneration();
|
|
36923
36934
|
let records = [];
|
|
36924
36935
|
const transition = () => transitionDbosWorkflowStatus({
|
|
@@ -36935,13 +36946,14 @@ class DbosDurableBackend {
|
|
|
36935
36946
|
const pendingPrompts = this.promptReservations.hydrate(workflowId, entry.pendingPrompts, records, entry.promptReservationEpoch);
|
|
36936
36947
|
this.applyMetadata(workflowId, { ...entry, pendingPrompts });
|
|
36937
36948
|
},
|
|
36938
|
-
claim: (authoritative, generation) => this.claimStatusTransition(workflowId, authoritative, generation, status, pendingPrompts, resumable, modelOwner),
|
|
36949
|
+
claim: (authoritative, generation) => this.claimStatusTransition(workflowId, authoritative, generation, status, pendingPrompts, resumable, modelOwner, releasedModelOwner),
|
|
36939
36950
|
write: async () => {
|
|
36940
36951
|
const handle = this.mem.getWorkflow(workflowId);
|
|
36941
36952
|
if (handle !== undefined)
|
|
36942
36953
|
this.mem.registerWorkflow({
|
|
36943
36954
|
...handle,
|
|
36944
36955
|
legacyRecoveryPending: undefined,
|
|
36956
|
+
releasedModelOwner,
|
|
36945
36957
|
...modelOwner !== undefined ? { modelOwner } : {}
|
|
36946
36958
|
}, true);
|
|
36947
36959
|
this.setWorkflowStatus(workflowId, status, pendingPrompts, resumable);
|
|
@@ -36953,7 +36965,7 @@ class DbosDurableBackend {
|
|
|
36953
36965
|
await this.flush(workflowId);
|
|
36954
36966
|
return await this.sdk.withWorkflowClaim(workflowId, transition);
|
|
36955
36967
|
}
|
|
36956
|
-
async claimStatusTransition(workflowId, authoritative, generation, status, pendingPrompts, resumable, modelOwner) {
|
|
36968
|
+
async claimStatusTransition(workflowId, authoritative, generation, status, pendingPrompts, resumable, modelOwner, releasedModelOwner) {
|
|
36957
36969
|
const stepName = claimMetadataStepName(generation);
|
|
36958
36970
|
const transitionClaimId = crypto.randomUUID();
|
|
36959
36971
|
const claim = {
|
|
@@ -36962,6 +36974,7 @@ class DbosDurableBackend {
|
|
|
36962
36974
|
...pendingPrompts !== undefined ? { pendingPrompts } : {},
|
|
36963
36975
|
...resumable !== undefined ? { resumable } : {},
|
|
36964
36976
|
...modelOwner === undefined ? {} : { modelOwner },
|
|
36977
|
+
releasedModelOwner,
|
|
36965
36978
|
legacyRecoveryPending: undefined,
|
|
36966
36979
|
ownerExecutorId: this.executorId,
|
|
36967
36980
|
transitionClaimId,
|
|
@@ -40577,8 +40590,11 @@ async function shutdownDbos() {
|
|
|
40577
40590
|
}
|
|
40578
40591
|
if (errors.length > 0)
|
|
40579
40592
|
throw combinedShutdownFailure(errors);
|
|
40580
|
-
if (wasReady)
|
|
40593
|
+
if (wasReady) {
|
|
40581
40594
|
slot.state = "shut_down";
|
|
40595
|
+
slot.configured = undefined;
|
|
40596
|
+
slot.active = undefined;
|
|
40597
|
+
}
|
|
40582
40598
|
})().catch(async (error) => {
|
|
40583
40599
|
slot.failure = await durabilityFailure("shutdown", error);
|
|
40584
40600
|
slot.state = "failed";
|
|
@@ -91770,6 +91786,44 @@ init_dbos_lifecycle();
|
|
|
91770
91786
|
init_factory();
|
|
91771
91787
|
import { registerExtensionContextRetirementEffect, sessionScopedExtensionState as sessionScopedExtensionState2 } from "@bastani/atomic";
|
|
91772
91788
|
|
|
91789
|
+
// dist/builtin/workflows/src/durable/sdk-owner-release.ts
|
|
91790
|
+
var releasedRuns = new WeakMap;
|
|
91791
|
+
async function releasePausedRunsOwnedBy(backend, modelOwner) {
|
|
91792
|
+
const settled = await Promise.allSettled(backend.listResumableWorkflows().filter((entry) => entry.status === "paused" && entry.modelOwner === modelOwner).map(async (entry) => {
|
|
91793
|
+
const released = await backend.transitionWorkflowStatus(entry.workflowId, ["paused"], "paused", undefined, undefined, undefined, undefined, modelOwner);
|
|
91794
|
+
return released ? entry.workflowId : undefined;
|
|
91795
|
+
}));
|
|
91796
|
+
const failures = settled.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
|
|
91797
|
+
if (failures.length > 0)
|
|
91798
|
+
throw new AggregateError(failures, failures.map(String).join("; "));
|
|
91799
|
+
const releasedIds = settled.flatMap((result) => result.status === "fulfilled" && result.value !== undefined ? [result.value] : []);
|
|
91800
|
+
let remembered = releasedRuns.get(backend);
|
|
91801
|
+
if (remembered === undefined) {
|
|
91802
|
+
remembered = new Set;
|
|
91803
|
+
releasedRuns.set(backend, remembered);
|
|
91804
|
+
}
|
|
91805
|
+
for (const runId of releasedIds)
|
|
91806
|
+
remembered.add(runId);
|
|
91807
|
+
return releasedIds;
|
|
91808
|
+
}
|
|
91809
|
+
async function reclaimReleasedRunsOwnedBy(backend, modelOwner) {
|
|
91810
|
+
const settled = await Promise.allSettled(backend.listResumableWorkflows().filter((entry) => entry.status === "paused" && entry.modelOwner === modelOwner).flatMap((entry) => {
|
|
91811
|
+
const handle = backend.getWorkflow(entry.workflowId);
|
|
91812
|
+
return handle?.releasedModelOwner === modelOwner ? [handle] : [];
|
|
91813
|
+
}).map(async (handle) => {
|
|
91814
|
+
const reclaimed = await backend.transitionWorkflowStatus(handle.workflowId, ["paused"], "paused", undefined, undefined, handle.updatedAt);
|
|
91815
|
+
if (reclaimed)
|
|
91816
|
+
releasedRuns.get(backend)?.delete(handle.workflowId);
|
|
91817
|
+
}));
|
|
91818
|
+
const failures = settled.flatMap((result) => result.status === "rejected" ? [result.reason] : []);
|
|
91819
|
+
if (failures.length > 0)
|
|
91820
|
+
throw new AggregateError(failures, failures.map(String).join("; "));
|
|
91821
|
+
}
|
|
91822
|
+
var FOREIGN_INSTANCE_MESSAGE = "Workflow instance belongs to another caller/session.";
|
|
91823
|
+
function foreignInstanceMessage(backend, runId) {
|
|
91824
|
+
return releasedRuns.get(backend)?.has(runId) === true && backend.getWorkflow(runId)?.releasedModelOwner === undefined ? `Workflow ${runId} is now owned by another session; it was already adopted after its previous session was switched away.` : FOREIGN_INSTANCE_MESSAGE;
|
|
91825
|
+
}
|
|
91826
|
+
|
|
91773
91827
|
// dist/builtin/workflows/src/durable/sdk-recovery-scope.ts
|
|
91774
91828
|
init_dbos_owner_fence();
|
|
91775
91829
|
init_dbos_sdk_handle();
|
|
@@ -91790,6 +91844,12 @@ function isSdkDurableRunInScope(handle, cwd) {
|
|
|
91790
91844
|
function isSdkCrashedRunAdoptable(handle, cwd) {
|
|
91791
91845
|
return isSdkDurableRunInScope(handle, cwd) && handle.status === "running" && handle.ownerExecutorId !== undefined && handle.ownerExecutorId !== getAtomicExecutorId() && !isLiveRunningWorkflow(handle) && isDatabaseExecutor(handle.ownerExecutorId) && handle.ownerLiveness === "dead";
|
|
91792
91846
|
}
|
|
91847
|
+
function isSdkReleasedRunAdoptable(handle, cwd) {
|
|
91848
|
+
return isSdkDurableRunInScope(handle, cwd) && handle.status === "paused" && handle.releasedModelOwner !== undefined && handle.releasedModelOwner === handle.modelOwner;
|
|
91849
|
+
}
|
|
91850
|
+
function isSdkRunAdoptable(handle, cwd) {
|
|
91851
|
+
return isSdkCrashedRunAdoptable(handle, cwd) || isSdkReleasedRunAdoptable(handle, cwd);
|
|
91852
|
+
}
|
|
91793
91853
|
|
|
91794
91854
|
// dist/builtin/workflows/src/engine/run-durable-admission.ts
|
|
91795
91855
|
init_dbos_admission();
|
|
@@ -93721,6 +93781,9 @@ async function markDurableQuit(runId, run, resumable = true) {
|
|
|
93721
93781
|
if (backend === undefined)
|
|
93722
93782
|
return "not_needed";
|
|
93723
93783
|
await backend.settleWorkflowAdmission?.(runId);
|
|
93784
|
+
const durable = backend.getWorkflow(runId);
|
|
93785
|
+
if (durable?.status === "paused" && durable.releasedModelOwner !== undefined)
|
|
93786
|
+
return "not_needed";
|
|
93724
93787
|
const transitioned = await transitionDurableWorkflowStatus(backend, runId, ["running", "paused"], "paused", undefined, resumable);
|
|
93725
93788
|
if (!transitioned)
|
|
93726
93789
|
return "refused";
|
|
@@ -109350,8 +109413,8 @@ async function resumeDurableWorkflowClaimed(workflowId, deps, catalog) {
|
|
|
109350
109413
|
}
|
|
109351
109414
|
const requestedOwner = deps.baseRunOpts.modelOwner;
|
|
109352
109415
|
const adopting = requestedOwner !== undefined && requestedOwner !== handle.modelOwner && (handle.modelOwner !== undefined || handle.origin === "agent");
|
|
109353
|
-
if (adopting && !
|
|
109354
|
-
return { ok: false, reason: "owned_elsewhere", message:
|
|
109416
|
+
if (adopting && !isSdkRunAdoptable(handle, deps.baseRunOpts.cwd)) {
|
|
109417
|
+
return { ok: false, reason: "owned_elsewhere", message: foreignInstanceMessage(backend, resolved.workflowId) };
|
|
109355
109418
|
}
|
|
109356
109419
|
const def = handle.invocationCwd === undefined ? deps.registry.get(handle.name) : await deps.resolveDefinition?.(handle.name, handle.invocationCwd) ?? deps.registry.get(handle.name);
|
|
109357
109420
|
if (def === undefined) {
|
|
@@ -110528,6 +110591,61 @@ function openWorkflowResumeSelector(ui, liveRuns, hydrate, options = {}) {
|
|
|
110528
110591
|
});
|
|
110529
110592
|
}
|
|
110530
110593
|
|
|
110594
|
+
// dist/builtin/workflows/src/extension/workflow-instance-owner.ts
|
|
110595
|
+
init_factory();
|
|
110596
|
+
var anonymousCallers = new WeakMap;
|
|
110597
|
+
|
|
110598
|
+
class WorkflowInstanceOwnershipError extends Error {
|
|
110599
|
+
constructor(message) {
|
|
110600
|
+
super(message);
|
|
110601
|
+
this.name = "WorkflowInstanceOwnershipError";
|
|
110602
|
+
}
|
|
110603
|
+
}
|
|
110604
|
+
function workflowCaller(ctx) {
|
|
110605
|
+
const sessionId = ctx.sessionId ?? ctx.sessionManager?.getSessionId?.();
|
|
110606
|
+
if (sessionId)
|
|
110607
|
+
return sessionId;
|
|
110608
|
+
const caller = ctx.sessionManager ?? ctx;
|
|
110609
|
+
let id = anonymousCallers.get(caller);
|
|
110610
|
+
if (id === undefined) {
|
|
110611
|
+
id = crypto.randomUUID();
|
|
110612
|
+
anonymousCallers.set(caller, id);
|
|
110613
|
+
}
|
|
110614
|
+
return id;
|
|
110615
|
+
}
|
|
110616
|
+
function assertWorkflowInstanceOwner(id, ctx, store) {
|
|
110617
|
+
const runs = store.runs();
|
|
110618
|
+
const backend = getDurableBackend();
|
|
110619
|
+
const seen = new Set;
|
|
110620
|
+
const assertOne = (runId) => {
|
|
110621
|
+
if (seen.has(runId))
|
|
110622
|
+
return;
|
|
110623
|
+
seen.add(runId);
|
|
110624
|
+
const local = runs.find((run) => run.id === runId);
|
|
110625
|
+
const durable = backend.getWorkflow(runId);
|
|
110626
|
+
const modelOwner = durable?.modelOwner ?? local?.modelOwner;
|
|
110627
|
+
if (modelOwner !== undefined) {
|
|
110628
|
+
if (modelOwner !== workflowCaller(ctx))
|
|
110629
|
+
throw new WorkflowInstanceOwnershipError(foreignInstanceMessage(backend, runId));
|
|
110630
|
+
} else if ((durable?.origin ?? local?.origin) === "agent") {
|
|
110631
|
+
throw new WorkflowInstanceOwnershipError("Workflow instance ownership is unavailable; another caller cannot assume authority.");
|
|
110632
|
+
}
|
|
110633
|
+
const parentId = durable?.rootWorkflowId ?? local?.parentRunId;
|
|
110634
|
+
if (parentId !== undefined)
|
|
110635
|
+
assertOne(parentId);
|
|
110636
|
+
};
|
|
110637
|
+
assertOne(id);
|
|
110638
|
+
const descendants = [id];
|
|
110639
|
+
for (const parentId of descendants) {
|
|
110640
|
+
for (const run of runs) {
|
|
110641
|
+
if (run.parentRunId !== parentId || descendants.includes(run.id))
|
|
110642
|
+
continue;
|
|
110643
|
+
assertOne(run.id);
|
|
110644
|
+
descendants.push(run.id);
|
|
110645
|
+
}
|
|
110646
|
+
}
|
|
110647
|
+
}
|
|
110648
|
+
|
|
110531
110649
|
// dist/builtin/workflows/src/shared/types.ts
|
|
110532
110650
|
var INTERACTIVE_WORKFLOW_POLICY = Object.freeze({
|
|
110533
110651
|
mode: "interactive",
|
|
@@ -110605,7 +110723,11 @@ async function handleDurableResume(target, ctx, reporter, deps, preparedCatalog)
|
|
|
110605
110723
|
fail(completedAttempt.message);
|
|
110606
110724
|
return true;
|
|
110607
110725
|
}
|
|
110608
|
-
const result = await runtime.resumeDurableWorkflow(target, {
|
|
110726
|
+
const result = await runtime.resumeDurableWorkflow(target, {
|
|
110727
|
+
policy,
|
|
110728
|
+
actor: "user",
|
|
110729
|
+
...releasedRunAdoption("workflowId" in resolved ? resolved.workflowId : target, ctx)
|
|
110730
|
+
});
|
|
110609
110731
|
if (result.ok) {
|
|
110610
110732
|
print(result.message);
|
|
110611
110733
|
if (policy.allowInputPicker)
|
|
@@ -110680,10 +110802,15 @@ function isExplicitResumeCandidate(run, sessionRuns) {
|
|
|
110680
110802
|
return true;
|
|
110681
110803
|
return isWorkflowRunResumable(workflowRunResumeCandidate(run, sessionRuns)) || run.endedAt === undefined && run.status === "running";
|
|
110682
110804
|
}
|
|
110805
|
+
function releasedRunAdoption(workflowId, ctx) {
|
|
110806
|
+
const handle = getDurableBackend().getLoadableWorkflow(workflowId);
|
|
110807
|
+
return handle !== undefined && isSdkReleasedRunAdoptable(handle, ctx.cwd) ? { modelOwner: workflowCaller(ctx) } : {};
|
|
110808
|
+
}
|
|
110683
110809
|
async function resumeDurableTarget(workflowId, ctx, reporter, deps, runtime) {
|
|
110684
110810
|
const result = await runtime.resumeDurableWorkflow(workflowId, {
|
|
110685
110811
|
policy: workflowPolicyFromContext(ctx),
|
|
110686
|
-
actor: "user"
|
|
110812
|
+
actor: "user",
|
|
110813
|
+
...releasedRunAdoption(workflowId, ctx)
|
|
110687
110814
|
});
|
|
110688
110815
|
if (!result.ok)
|
|
110689
110816
|
reporter.error(result.message);
|
|
@@ -110715,61 +110842,6 @@ function openCompleted(runtime, workflowId, catalog, beforeRestoreCompleted, sto
|
|
|
110715
110842
|
}, catalog);
|
|
110716
110843
|
}
|
|
110717
110844
|
|
|
110718
|
-
// dist/builtin/workflows/src/extension/workflow-instance-owner.ts
|
|
110719
|
-
init_factory();
|
|
110720
|
-
var anonymousCallers = new WeakMap;
|
|
110721
|
-
|
|
110722
|
-
class WorkflowInstanceOwnershipError extends Error {
|
|
110723
|
-
constructor(message) {
|
|
110724
|
-
super(message);
|
|
110725
|
-
this.name = "WorkflowInstanceOwnershipError";
|
|
110726
|
-
}
|
|
110727
|
-
}
|
|
110728
|
-
function workflowCaller(ctx) {
|
|
110729
|
-
const sessionId = ctx.sessionId ?? ctx.sessionManager?.getSessionId?.();
|
|
110730
|
-
if (sessionId)
|
|
110731
|
-
return sessionId;
|
|
110732
|
-
const caller = ctx.sessionManager ?? ctx;
|
|
110733
|
-
let id = anonymousCallers.get(caller);
|
|
110734
|
-
if (id === undefined) {
|
|
110735
|
-
id = crypto.randomUUID();
|
|
110736
|
-
anonymousCallers.set(caller, id);
|
|
110737
|
-
}
|
|
110738
|
-
return id;
|
|
110739
|
-
}
|
|
110740
|
-
function assertWorkflowInstanceOwner(id, ctx, store) {
|
|
110741
|
-
const runs = store.runs();
|
|
110742
|
-
const backend = getDurableBackend();
|
|
110743
|
-
const seen = new Set;
|
|
110744
|
-
const assertOne = (runId) => {
|
|
110745
|
-
if (seen.has(runId))
|
|
110746
|
-
return;
|
|
110747
|
-
seen.add(runId);
|
|
110748
|
-
const local = runs.find((run) => run.id === runId);
|
|
110749
|
-
const durable = backend.getWorkflow(runId);
|
|
110750
|
-
const modelOwner = durable?.modelOwner ?? local?.modelOwner;
|
|
110751
|
-
if (modelOwner !== undefined) {
|
|
110752
|
-
if (modelOwner !== workflowCaller(ctx))
|
|
110753
|
-
throw new WorkflowInstanceOwnershipError("Workflow instance belongs to another caller/session.");
|
|
110754
|
-
} else if ((durable?.origin ?? local?.origin) === "agent") {
|
|
110755
|
-
throw new WorkflowInstanceOwnershipError("Workflow instance ownership is unavailable; another caller cannot assume authority.");
|
|
110756
|
-
}
|
|
110757
|
-
const parentId = durable?.rootWorkflowId ?? local?.parentRunId;
|
|
110758
|
-
if (parentId !== undefined)
|
|
110759
|
-
assertOne(parentId);
|
|
110760
|
-
};
|
|
110761
|
-
assertOne(id);
|
|
110762
|
-
const descendants = [id];
|
|
110763
|
-
for (const parentId of descendants) {
|
|
110764
|
-
for (const run of runs) {
|
|
110765
|
-
if (run.parentRunId !== parentId || descendants.includes(run.id))
|
|
110766
|
-
continue;
|
|
110767
|
-
assertOne(run.id);
|
|
110768
|
-
descendants.push(run.id);
|
|
110769
|
-
}
|
|
110770
|
-
}
|
|
110771
|
-
}
|
|
110772
|
-
|
|
110773
110845
|
// dist/builtin/workflows/src/extension/extension-lifecycle.ts
|
|
110774
110846
|
var startupRecoveries = new Set;
|
|
110775
110847
|
function trackStartupRecovery(recovery) {
|
|
@@ -110809,6 +110881,18 @@ function sessionSwitchQuitConfirmation(reason, inFlightWorkflowCount) {
|
|
|
110809
110881
|
message: `Continuing quits ${runs} now. ${pronoun} stops at its last checkpoint and can be resumed later with /workflow resume.`
|
|
110810
110882
|
};
|
|
110811
110883
|
}
|
|
110884
|
+
async function releasePausedRunsOfSession(sessionCaller) {
|
|
110885
|
+
const backend = getAvailableDurableBackend();
|
|
110886
|
+
return sessionCaller !== undefined && backend !== undefined ? releasePausedRunsOwnedBy(backend, sessionCaller) : [];
|
|
110887
|
+
}
|
|
110888
|
+
function releasedRunsNotice(runs) {
|
|
110889
|
+
const count = runs.length === 1 ? "1 workflow run" : `${runs.length} workflow runs`;
|
|
110890
|
+
return [
|
|
110891
|
+
`Released ${count} from the previous session. Resume ${runs.length === 1 ? "it" : "any"} here:`,
|
|
110892
|
+
...runs.map((run) => ` /workflow resume ${run.id} (${run.name})`)
|
|
110893
|
+
].join(`
|
|
110894
|
+
`);
|
|
110895
|
+
}
|
|
110812
110896
|
function eventReason(event) {
|
|
110813
110897
|
return typeof event === "object" && event !== null && "reason" in event ? event.reason : undefined;
|
|
110814
110898
|
}
|
|
@@ -110958,9 +111042,31 @@ function registerWorkflowLifecycleHandlers(pi, deps) {
|
|
|
110958
111042
|
if (errors.length)
|
|
110959
111043
|
throw new AggregateError(errors, "Workflow observation retirement failed");
|
|
110960
111044
|
};
|
|
111045
|
+
let sessionCaller;
|
|
111046
|
+
let switchHandoff;
|
|
111047
|
+
const handOffRunsToSuccessor = () => {
|
|
111048
|
+
switchHandoff ??= attemptAll([
|
|
111049
|
+
...[...lifetime.generations].map((quitRuns) => () => quitRuns("switch")),
|
|
111050
|
+
async () => {
|
|
111051
|
+
const released = await releasePausedRunsOfSession(sessionCaller);
|
|
111052
|
+
lifetime.releasedRunIds = [...new Set([...lifetime.releasedRunIds ?? [], ...released])];
|
|
111053
|
+
},
|
|
111054
|
+
flushDbos
|
|
111055
|
+
]);
|
|
111056
|
+
lifetime.activeSwitchHandoff = switchHandoff;
|
|
111057
|
+
return switchHandoff;
|
|
111058
|
+
};
|
|
110961
111059
|
pi.on("session_start", async (event, ctx) => {
|
|
110962
|
-
|
|
111060
|
+
const departingHandoff = lifetime.pendingSwitchHandoff;
|
|
111061
|
+
lifetime.pendingSwitchHandoff = handOffRunsToSuccessor;
|
|
111062
|
+
if (ctx) {
|
|
110963
111063
|
registerExtensionContextRetirementEffect(ctx, closeObservation);
|
|
111064
|
+
sessionCaller = workflowCaller(ctx);
|
|
111065
|
+
}
|
|
111066
|
+
if (isSessionSwitch(eventReason(event)) && departingHandoff !== undefined && lifetime.closing === undefined)
|
|
111067
|
+
await departingHandoff().catch(() => {
|
|
111068
|
+
return;
|
|
111069
|
+
});
|
|
110964
111070
|
lifetime.release ??= getDurableBackendProcessOwner().injectedBackend === undefined ? acquireDbosLease() : async () => {};
|
|
110965
111071
|
const reason = typeof event === "object" && event !== null && "reason" in event ? event.reason : undefined;
|
|
110966
111072
|
const stopsWorkflows = replacementStopsWorkflows(reason) && !(reason === "startup" && lifetime.startupStarted);
|
|
@@ -110989,6 +111095,28 @@ function registerWorkflowLifecycleHandlers(pi, deps) {
|
|
|
110989
111095
|
deps.storeWidgetRef.current?.();
|
|
110990
111096
|
deps.storeWidgetRef.current = installStoreWidget({ ui: ctx.ui }, store);
|
|
110991
111097
|
}
|
|
111098
|
+
if (isSessionSwitch(reason) && sessionCaller !== undefined) {
|
|
111099
|
+
const backend = getAvailableDurableBackend();
|
|
111100
|
+
if (backend !== undefined)
|
|
111101
|
+
await reclaimReleasedRunsOwnedBy(backend, sessionCaller).catch(() => {
|
|
111102
|
+
return;
|
|
111103
|
+
});
|
|
111104
|
+
}
|
|
111105
|
+
if (reason !== "reload") {
|
|
111106
|
+
const releasedRunIds = lifetime.releasedRunIds;
|
|
111107
|
+
lifetime.releasedRunIds = undefined;
|
|
111108
|
+
if (isSessionSwitch(reason) && releasedRunIds !== undefined && releasedRunIds.length > 0) {
|
|
111109
|
+
const backend = getAvailableDurableBackend();
|
|
111110
|
+
const cwd = ctx?.cwd ?? ctx?.sessionManager?.getCwd?.() ?? runtimeState.resolveInvocationCwd();
|
|
111111
|
+
const adoptable = releasedRunIds.flatMap((runId) => {
|
|
111112
|
+
const handle = backend?.getWorkflow(runId);
|
|
111113
|
+
return handle !== undefined && isSdkReleasedRunAdoptable(handle, cwd) ? [{ id: runId, name: handle.name }] : [];
|
|
111114
|
+
});
|
|
111115
|
+
lifetime.releasedRunIds = adoptable.map((run) => run.id);
|
|
111116
|
+
if (adoptable.length > 0)
|
|
111117
|
+
ctx?.ui?.notify?.(releasedRunsNotice(adoptable), "info");
|
|
111118
|
+
}
|
|
111119
|
+
}
|
|
110992
111120
|
runtimeState.updateHostStageSessionDir(ctx?.sessionManager ?? pi.sessionManager);
|
|
110993
111121
|
const generation = ++recoveryGeneration;
|
|
110994
111122
|
if (stopsWorkflows)
|
|
@@ -111011,8 +111139,12 @@ function registerWorkflowLifecycleHandlers(pi, deps) {
|
|
|
111011
111139
|
const closeGeneration = closeObservation;
|
|
111012
111140
|
if (replacementStopsWorkflows(reason)) {
|
|
111013
111141
|
lifetime.closing ??= attemptAll([
|
|
111142
|
+
() => lifetime.activeSwitchHandoff?.catch(() => {
|
|
111143
|
+
return;
|
|
111144
|
+
}),
|
|
111014
111145
|
closeGeneration,
|
|
111015
111146
|
...lifetime.generations,
|
|
111147
|
+
() => releasePausedRunsOfSession(sessionCaller),
|
|
111016
111148
|
() => {
|
|
111017
111149
|
lifetime.generations.clear();
|
|
111018
111150
|
},
|
|
@@ -111020,11 +111152,7 @@ function registerWorkflowLifecycleHandlers(pi, deps) {
|
|
|
111020
111152
|
]);
|
|
111021
111153
|
await lifetime.closing;
|
|
111022
111154
|
} else if (isSessionSwitch(reason)) {
|
|
111023
|
-
await attemptAll([
|
|
111024
|
-
closeGeneration,
|
|
111025
|
-
...[...lifetime.generations].map((quitRuns) => () => quitRuns("switch")),
|
|
111026
|
-
flushDbos
|
|
111027
|
-
]);
|
|
111155
|
+
await attemptAll([closeGeneration, handOffRunsToSuccessor]);
|
|
111028
111156
|
} else {
|
|
111029
111157
|
await attemptAll([closeGeneration, () => stageControlRegistry.clearDetached(), flushDbos]);
|
|
111030
111158
|
}
|
|
@@ -124493,8 +124621,14 @@ function makeExecuteWorkflowTool(runtime, reloadWorkflowResources, ensureWorkflo
|
|
|
124493
124621
|
};
|
|
124494
124622
|
}
|
|
124495
124623
|
const recoveryCwd = typeof ctx.cwd === "string" ? ctx.cwd : undefined;
|
|
124624
|
+
const adoptsReleasedRun = (id) => {
|
|
124625
|
+
const handle = getDurableBackend().getLoadableWorkflow(id);
|
|
124626
|
+
return handle !== undefined && isSdkReleasedRunAdoptable(handle, recoveryCwd);
|
|
124627
|
+
};
|
|
124496
124628
|
const authorize = (id) => {
|
|
124497
124629
|
const handle = getDurableBackend().getLoadableWorkflow(id);
|
|
124630
|
+
if ((action === "resume" || action === "status" || action === "stages") && handle !== undefined && isSdkReleasedRunAdoptable(handle, recoveryCwd))
|
|
124631
|
+
return;
|
|
124498
124632
|
if (access === "sdk" && isFullRunId(args.runId?.trim() ?? "") && (action === "status" || action === "stages" || action === "resume" && handle !== undefined && isSdkCrashedRunAdoptable(handle, recoveryCwd)) && !store.runs().some((run) => run.id === id) && handle !== undefined && isSdkDurableRunInScope(handle, recoveryCwd))
|
|
124499
124633
|
return;
|
|
124500
124634
|
assertWorkflowInstanceOwner(id, ctx, store);
|
|
@@ -124516,11 +124650,9 @@ function makeExecuteWorkflowTool(runtime, reloadWorkflowResources, ensureWorkflo
|
|
|
124516
124650
|
const awaitRequest = (operation) => raceAbort(operation, signal);
|
|
124517
124651
|
const getRuntime = () => {
|
|
124518
124652
|
const resolved = typeof runtime === "function" ? runtime(ctx) : runtime;
|
|
124519
|
-
if (access !== "sdk")
|
|
124520
|
-
return resolved;
|
|
124521
124653
|
return {
|
|
124522
124654
|
...resolved,
|
|
124523
|
-
resumeDurableWorkflow: (id, options) => resolved.resumeDurableWorkflow(id, { ...options, modelOwner: workflowCaller(ctx) })
|
|
124655
|
+
resumeDurableWorkflow: (id, options) => resolved.resumeDurableWorkflow(id, access === "sdk" || adoptsReleasedRun(id) ? { ...options, modelOwner: workflowCaller(ctx) } : options)
|
|
124524
124656
|
};
|
|
124525
124657
|
};
|
|
124526
124658
|
const ensureWorkflowResourcesVisible = async () => {
|