hoi4-agent-tools 3.0.9 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/CHANGELOG.md +32 -1
  2. package/README.md +10 -2
  3. package/dist/bin/stdio.js +23 -12
  4. package/dist/hoi4_agent_tools/core/analysis-checkpoints.js +82 -0
  5. package/dist/hoi4_agent_tools/core/analysis-evidence.js +9 -0
  6. package/dist/hoi4_agent_tools/core/analysis-job-operations.js +38 -0
  7. package/dist/hoi4_agent_tools/core/artifact-resource.js +173 -0
  8. package/dist/hoi4_agent_tools/core/artifacts.js +84 -2
  9. package/dist/hoi4_agent_tools/core/condition-evaluator.js +16 -0
  10. package/dist/hoi4_agent_tools/core/dependency-pages.js +216 -0
  11. package/dist/hoi4_agent_tools/core/dependency-walk.js +266 -0
  12. package/dist/hoi4_agent_tools/core/domain-validation.js +188 -0
  13. package/dist/hoi4_agent_tools/core/engine.js +48 -5
  14. package/dist/hoi4_agent_tools/core/helper-expansion.js +186 -0
  15. package/dist/hoi4_agent_tools/core/impact-comparison.js +49 -0
  16. package/dist/hoi4_agent_tools/core/impact-graph.js +301 -0
  17. package/dist/hoi4_agent_tools/core/impact-semantic.js +256 -0
  18. package/dist/hoi4_agent_tools/core/index-segments.js +137 -0
  19. package/dist/hoi4_agent_tools/core/index.js +47 -4
  20. package/dist/hoi4_agent_tools/core/job-controls.js +109 -0
  21. package/dist/hoi4_agent_tools/core/job-executor.js +190 -0
  22. package/dist/hoi4_agent_tools/core/job-service.js +112 -0
  23. package/dist/hoi4_agent_tools/core/job-store.js +641 -0
  24. package/dist/hoi4_agent_tools/core/job-transactions.js +126 -0
  25. package/dist/hoi4_agent_tools/core/job-worker-host.js +202 -0
  26. package/dist/hoi4_agent_tools/core/job-worker.js +64 -0
  27. package/dist/hoi4_agent_tools/core/operation-context.js +31 -0
  28. package/dist/hoi4_agent_tools/core/operation-result.js +412 -0
  29. package/dist/hoi4_agent_tools/core/operation-tasks.js +387 -0
  30. package/dist/hoi4_agent_tools/core/persistent-analysis-cache.js +383 -0
  31. package/dist/hoi4_agent_tools/core/result.js +1 -0
  32. package/dist/hoi4_agent_tools/core/scanner.js +15 -75
  33. package/dist/hoi4_agent_tools/core/semantic-dependencies.js +233 -0
  34. package/dist/hoi4_agent_tools/core/shared-request-capacity.js +43 -11
  35. package/dist/hoi4_agent_tools/core/source/cache.js +107 -0
  36. package/dist/hoi4_agent_tools/core/source/parser.js +11 -1
  37. package/dist/hoi4_agent_tools/core/source-overlay.js +125 -0
  38. package/dist/hoi4_agent_tools/core/transaction-execution.js +134 -0
  39. package/dist/hoi4_agent_tools/core/transactions.js +80 -27
  40. package/dist/hoi4_agent_tools/decision/ai.js +104 -0
  41. package/dist/hoi4_agent_tools/decision/comparison.js +106 -0
  42. package/dist/hoi4_agent_tools/decision/cost.js +177 -0
  43. package/dist/hoi4_agent_tools/decision/evaluation.js +256 -0
  44. package/dist/hoi4_agent_tools/decision/lifecycle.js +114 -0
  45. package/dist/hoi4_agent_tools/decision/service.js +172 -0
  46. package/dist/hoi4_agent_tools/decision/source-inventory.js +182 -0
  47. package/dist/hoi4_agent_tools/event/graph.js +214 -290
  48. package/dist/hoi4_agent_tools/event/helper-expansion.js +33 -0
  49. package/dist/hoi4_agent_tools/event/job-operations.js +51 -0
  50. package/dist/hoi4_agent_tools/event/operations.js +179 -0
  51. package/dist/hoi4_agent_tools/event/service.js +67 -15
  52. package/dist/hoi4_agent_tools/event/source-analysis.js +5 -4
  53. package/dist/hoi4_agent_tools/focus/job-operations.js +77 -0
  54. package/dist/hoi4_agent_tools/focus/tool-operations.js +669 -0
  55. package/dist/hoi4_agent_tools/focus/tool-support.js +123 -0
  56. package/dist/hoi4_agent_tools/gui/job-operations.js +81 -0
  57. package/dist/hoi4_agent_tools/gui/tool-operations.js +270 -0
  58. package/dist/hoi4_agent_tools/impact/scenario-suites.js +74 -0
  59. package/dist/hoi4_agent_tools/impact/service.js +127 -0
  60. package/dist/hoi4_agent_tools/map/job-operations.js +76 -0
  61. package/dist/hoi4_agent_tools/map/tool-operations.js +493 -0
  62. package/dist/hoi4_agent_tools/mcp/prompts/probability.js +25 -0
  63. package/dist/hoi4_agent_tools/mcp/prompts/register-modern.js +29 -0
  64. package/dist/hoi4_agent_tools/mcp/resources/register-modern.js +34 -0
  65. package/dist/hoi4_agent_tools/mcp/resources/register.js +4 -150
  66. package/dist/hoi4_agent_tools/mcp/server/base-tools.js +3 -219
  67. package/dist/hoi4_agent_tools/mcp/server/create-modern-operations.js +188 -0
  68. package/dist/hoi4_agent_tools/mcp/server/create.js +18 -6
  69. package/dist/hoi4_agent_tools/mcp/server/instructions.js +2 -0
  70. package/dist/hoi4_agent_tools/mcp/server/job-task-store.js +67 -0
  71. package/dist/hoi4_agent_tools/mcp/server/legacy-task-tools.js +20 -0
  72. package/dist/hoi4_agent_tools/mcp/server/modern-tasks.js +168 -0
  73. package/dist/hoi4_agent_tools/mcp/server/progress.js +17 -15
  74. package/dist/hoi4_agent_tools/mcp/server/request-lifecycle.js +45 -0
  75. package/dist/hoi4_agent_tools/mcp/server/result.js +2 -412
  76. package/dist/hoi4_agent_tools/mcp/server/task-request-context.js +9 -0
  77. package/dist/hoi4_agent_tools/mcp/server/task-tool-catalog.js +16 -0
  78. package/dist/hoi4_agent_tools/mcp/server/task-tool-definition.js +1 -0
  79. package/dist/hoi4_agent_tools/mcp/server/transaction-execution.js +1 -123
  80. package/dist/hoi4_agent_tools/mcp/tools/analysis.js +65 -0
  81. package/dist/hoi4_agent_tools/mcp/tools/chaosx.js +38 -21
  82. package/dist/hoi4_agent_tools/mcp/tools/event.js +24 -315
  83. package/dist/hoi4_agent_tools/mcp/tools/focus.js +34 -1039
  84. package/dist/hoi4_agent_tools/mcp/tools/gui.js +19 -504
  85. package/dist/hoi4_agent_tools/mcp/tools/job.js +46 -0
  86. package/dist/hoi4_agent_tools/mcp/tools/map.js +21 -600
  87. package/dist/hoi4_agent_tools/mcp/tools/probability.js +39 -463
  88. package/dist/hoi4_agent_tools/mcp/tools/technology.js +40 -304
  89. package/dist/hoi4_agent_tools/mcp/transports/http.js +58 -1
  90. package/dist/hoi4_agent_tools/mcp/transports/modern-task-routing.js +109 -0
  91. package/dist/hoi4_agent_tools/mcp/transports/negotiated-stdio.js +121 -0
  92. package/dist/hoi4_agent_tools/probability/job-operations.js +58 -0
  93. package/dist/hoi4_agent_tools/probability/operations.js +183 -0
  94. package/dist/hoi4_agent_tools/probability/service.js +24 -3
  95. package/dist/hoi4_agent_tools/schemas/analysis.js +228 -0
  96. package/dist/hoi4_agent_tools/schemas/common.js +2 -0
  97. package/dist/hoi4_agent_tools/schemas/event.js +72 -1
  98. package/dist/hoi4_agent_tools/schemas/focus-requests.js +189 -0
  99. package/dist/hoi4_agent_tools/schemas/gui-requests.js +193 -0
  100. package/dist/hoi4_agent_tools/schemas/helper-expansion.js +58 -0
  101. package/dist/hoi4_agent_tools/schemas/map-requests.js +85 -0
  102. package/dist/hoi4_agent_tools/schemas/probability-requests.js +168 -0
  103. package/dist/hoi4_agent_tools/schemas/technology.js +90 -1
  104. package/dist/hoi4_agent_tools/schemas/transaction.js +1 -0
  105. package/dist/hoi4_agent_tools/technology/graph.js +83 -78
  106. package/dist/hoi4_agent_tools/technology/helper-expansion.js +33 -0
  107. package/dist/hoi4_agent_tools/technology/job-operations.js +60 -0
  108. package/dist/hoi4_agent_tools/technology/operations.js +125 -0
  109. package/dist/hoi4_agent_tools/technology/service.js +89 -15
  110. package/dist/hoi4_agent_tools/technology/source-analysis.js +2 -1
  111. package/dist/hoi4_agent_tools/version.js +1 -1
  112. package/docs/README.md +3 -0
  113. package/docs/analysis.md +100 -0
  114. package/docs/development.md +2 -0
  115. package/docs/events.md +7 -2
  116. package/docs/helper-expansion.md +78 -0
  117. package/docs/http.md +2 -0
  118. package/docs/jobs.md +86 -0
  119. package/docs/technology.md +6 -2
  120. package/package.json +15 -6
  121. package/schemas/configuration.schema.json +1 -1
  122. package/schemas/continuous-focus-palette.schema.json +1 -1
  123. package/schemas/custom-weighted-pool.schema.json +1 -1
  124. package/schemas/decision-inspect-input.schema.json +290 -0
  125. package/schemas/event-feature-manifest.schema.json +1 -1
  126. package/schemas/focus-plan.schema.json +1 -1
  127. package/schemas/focus-planning-sidecar.schema.json +1 -1
  128. package/schemas/gui-animation-source.schema.json +1 -1
  129. package/schemas/gui-helper.schema.json +1 -1
  130. package/schemas/gui-scenario.schema.json +1 -1
  131. package/schemas/helper-expansion-request.schema.json +44 -0
  132. package/schemas/helper-expansion-summary.schema.json +70 -0
  133. package/schemas/impact-inspect-input.schema.json +203 -0
  134. package/schemas/map-operation.schema.json +1 -1
  135. package/schemas/operation-result.schema.json +1 -1
  136. package/schemas/probability-analysis-result.schema.json +1 -1
  137. package/schemas/probability-compare-input.schema.json +1 -1
  138. package/schemas/probability-evaluate-input.schema.json +1 -1
  139. package/schemas/probability-inspect-input.schema.json +1 -1
  140. package/schemas/probability-render-input.schema.json +1 -1
  141. package/schemas/probability-scenario-set.schema.json +1 -1
  142. package/schemas/probability-sequence-input.schema.json +1 -1
  143. package/schemas/probability-simulate-input.schema.json +1 -1
  144. package/schemas/probability-sweep-input.schema.json +1 -1
  145. package/server.json +3 -3
@@ -0,0 +1,190 @@
1
+ import { setTimeout as delay } from 'node:timers/promises';
2
+ import { z } from 'zod/v4';
3
+ import { currentJobOwner } from './job-store.js';
4
+ import { JobTransactions } from './job-transactions.js';
5
+ import { ServiceError } from './result.js';
6
+ import { PACKAGE_VERSION } from '../version.js';
7
+ import { hashCanonical } from './canonical.js';
8
+ import { jobAnalysisCheckpoints, withAnalysisCheckpoints } from './analysis-checkpoints.js';
9
+ const jsonObject = z.record(z.string(), z.json());
10
+ function defaultWriteResult(execution, reconciled) {
11
+ const artifacts = [
12
+ ...execution.artifacts,
13
+ ...(execution.transaction.executionArtifacts ?? []),
14
+ ...execution.transaction.artifacts,
15
+ ];
16
+ return jsonObject.parse({
17
+ execution: execution.outcome,
18
+ reconciled,
19
+ validationPassed: execution.transaction.validation.passed,
20
+ artifacts,
21
+ changedFiles: execution.outcome === 'applied'
22
+ ? execution.transaction.files.map(({ relativePath }) => relativePath)
23
+ : [],
24
+ });
25
+ }
26
+ /** Typed core operations shared by a worker host, never MCP handlers or command strings. */
27
+ export class JobOperations {
28
+ operations = new Map();
29
+ registerRead(name, schema, run) {
30
+ this.add(name, { mutation: false, run: (input, context) => run(schema.parse(input), context) });
31
+ }
32
+ registerWrite(name, schema, prepare, complete = (_input, execution, reconciled) => Promise.resolve(defaultWriteResult(execution, reconciled))) {
33
+ this.add(name, {
34
+ mutation: true,
35
+ prepare: async (input, context) => {
36
+ const prepared = await prepare(schema.parse(input), context);
37
+ if (!('transaction' in prepared))
38
+ return { transaction: prepared };
39
+ return {
40
+ transaction: prepared.transaction,
41
+ ...(prepared.recipe === undefined ? {} : { recipe: jsonObject.parse(prepared.recipe) }),
42
+ };
43
+ },
44
+ complete: (input, execution, reconciled, recipe, context) => complete(schema.parse(input), execution, reconciled, recipe, context),
45
+ });
46
+ }
47
+ get(name) {
48
+ const operation = this.operations.get(name);
49
+ if (operation === undefined)
50
+ throw new ServiceError('JOB_OPERATION_UNAVAILABLE', 'No typed core operation is registered for this job');
51
+ return operation;
52
+ }
53
+ add(name, operation) {
54
+ if (this.operations.has(name))
55
+ throw new Error(`Duplicate job operation: ${name}`);
56
+ this.operations.set(name, operation);
57
+ }
58
+ }
59
+ /** Durable execution coordination; CPU/process isolation is supplied by its worker host. */
60
+ export class JobExecutor {
61
+ engine;
62
+ jobs;
63
+ operations;
64
+ admissionOwner = {};
65
+ constructor(engine, jobs, operations) {
66
+ this.engine = engine;
67
+ this.jobs = jobs;
68
+ this.operations = operations;
69
+ }
70
+ async run(workspaceId, id, principal) {
71
+ const initial = await this.jobs.get(workspaceId, id, principal);
72
+ if (['completed', 'failed', 'cancelled'].includes(initial.status))
73
+ return initial;
74
+ const operation = this.operations.get(initial.request.toolName);
75
+ if (operation.mutation !== initial.request.mutation)
76
+ throw new ServiceError('JOB_OPERATION_MISMATCH', 'The registered operation does not match the persisted write policy');
77
+ if (initial.toolVersion !== PACKAGE_VERSION)
78
+ throw new ServiceError('JOB_VERSION_MISMATCH', 'This job requires its recorded tool version for execution');
79
+ const scope = this.jobs.scope(workspaceId, principal);
80
+ const owner = currentJobOwner();
81
+ let claimed;
82
+ try {
83
+ claimed = await this.jobs.store.claim(scope, id, owner);
84
+ }
85
+ catch (error) {
86
+ if (error instanceof ServiceError &&
87
+ ['JOB_OWNER_ACTIVE', 'JOB_TERMINAL'].includes(error.code))
88
+ return this.jobs.get(workspaceId, id, principal);
89
+ throw error;
90
+ }
91
+ if (claimed.record.status === 'cancelled')
92
+ return claimed.record;
93
+ if (!operation.mutation &&
94
+ claimed.record.result !== undefined &&
95
+ claimed.record.checkpoint?.cursor === 'result-ready' &&
96
+ claimed.record.checkpoint.resultHash === hashCanonical(claimed.record.result))
97
+ return this.jobs.store.updateOwned(scope, id, owner.token, {
98
+ status: 'completed',
99
+ result: claimed.record.result,
100
+ });
101
+ const controller = new AbortController();
102
+ const watchStop = new AbortController();
103
+ let watchFailure;
104
+ const watch = (async () => {
105
+ while (!watchStop.signal.aborted) {
106
+ const current = await this.jobs.get(workspaceId, id, principal);
107
+ if (current.cancelRequested) {
108
+ controller.abort(new DOMException('Job cancelled', 'AbortError'));
109
+ return;
110
+ }
111
+ if (current.owner?.token !== owner.token)
112
+ throw new ServiceError('JOB_OWNER_CHANGED', 'The execution attempt lost ownership');
113
+ await delay(250, undefined, { signal: watchStop.signal });
114
+ }
115
+ })().catch((error) => {
116
+ if (watchStop.signal.aborted)
117
+ return;
118
+ watchFailure = error;
119
+ controller.abort(error);
120
+ });
121
+ const context = {
122
+ engine: this.engine,
123
+ workspaceId,
124
+ principal,
125
+ signal: controller.signal,
126
+ checkpoint: claimed.record.checkpoint,
127
+ progress: async (progress) => {
128
+ await this.jobs.store.updateOwned(scope, id, owner.token, { progress }, controller.signal);
129
+ },
130
+ saveCheckpoint: async (checkpoint) => {
131
+ await this.jobs.store.updateOwned(scope, id, owner.token, { checkpoint }, controller.signal);
132
+ },
133
+ stageResult: async (result, checkpoint) => {
134
+ await this.jobs.store.updateOwned(scope, id, owner.token, {
135
+ result,
136
+ checkpoint: {
137
+ ...checkpoint,
138
+ cursor: 'result-ready',
139
+ resultHash: hashCanonical(result),
140
+ },
141
+ }, controller.signal);
142
+ },
143
+ };
144
+ try {
145
+ return await this.engine.requests.run(this.admissionOwner, Buffer.byteLength(JSON.stringify(initial.request)), controller.signal, () => this.engine.sharedRequests.run(controller.signal, async () => {
146
+ if (operation.mutation) {
147
+ const writes = new JobTransactions(this.engine, this.jobs);
148
+ if (claimed.record.transaction !== undefined)
149
+ return writes.reconcile(workspaceId, id, owner.token, principal, undefined, true, (execution, reconciled, recipe) => operation.complete(initial.request.arguments, execution, reconciled, recipe, context));
150
+ const prepared = await operation.prepare(initial.request.arguments, context);
151
+ return writes.execute(workspaceId, id, owner.token, prepared.transaction, principal, controller.signal, prepared.recipe, (execution, reconciled, recipe) => operation.complete(initial.request.arguments, execution, reconciled, recipe, context));
152
+ }
153
+ const result = jsonObject.parse(await withAnalysisCheckpoints(jobAnalysisCheckpoints(context), () => operation.run(initial.request.arguments, context)));
154
+ controller.signal.throwIfAborted();
155
+ return this.jobs.store.updateOwned(scope, id, owner.token, {
156
+ status: 'completed',
157
+ result,
158
+ });
159
+ }));
160
+ }
161
+ catch (error) {
162
+ const current = await this.jobs.get(workspaceId, id, principal);
163
+ if (['completed', 'failed', 'cancelled'].includes(current.status))
164
+ return current;
165
+ if (current.owner?.token !== owner.token)
166
+ throw error;
167
+ if (operation.mutation && current.transaction !== undefined)
168
+ return await new JobTransactions(this.engine, this.jobs).reconcile(workspaceId, id, owner.token, principal, undefined, false, (execution, reconciled, recipe) => operation.complete(initial.request.arguments, execution, reconciled, recipe, context));
169
+ if (current.cancelRequested && watchFailure === undefined)
170
+ return await this.jobs.store.updateOwned(scope, id, owner.token, {
171
+ status: 'cancelled',
172
+ cancelRequested: true,
173
+ });
174
+ const cause = watchFailure ?? error;
175
+ return await this.jobs.store.updateOwned(scope, id, owner.token, {
176
+ status: 'failed',
177
+ failure: {
178
+ code: cause instanceof ServiceError ? cause.code : 'JOB_EXECUTION_FAILED',
179
+ message: cause instanceof ServiceError
180
+ ? cause.message
181
+ : 'The typed operation failed; no completed result was recorded',
182
+ },
183
+ });
184
+ }
185
+ finally {
186
+ watchStop.abort();
187
+ await watch;
188
+ }
189
+ }
190
+ }
@@ -0,0 +1,112 @@
1
+ import { currentJobOwner, jobRetentionExpired, jobOwnerLiveness, JobStore, } from './job-store.js';
2
+ import { ServiceError } from './result.js';
3
+ import { transactionRootFingerprint } from './transactions.js';
4
+ /** Authorization boundary for persistent jobs; transport inputs never supply an ownership scope. */
5
+ export class JobService {
6
+ resolver;
7
+ store;
8
+ constructor(resolver, store) {
9
+ this.resolver = resolver;
10
+ this.store = store;
11
+ }
12
+ static async create(resolver) {
13
+ const state = resolver.serverState();
14
+ if (state === undefined)
15
+ throw new ServiceError('JOB_STORAGE_UNAVAILABLE', 'Persistent jobs require operator-owned server state');
16
+ return new JobService(resolver, await JobStore.create(state));
17
+ }
18
+ scope(workspaceId, principal) {
19
+ const workspace = this.resolver.get(workspaceId, principal);
20
+ return {
21
+ workspaceId: workspace.id,
22
+ workspaceIdentity: workspace.workspaceIdentity,
23
+ rootFingerprint: transactionRootFingerprint(workspace),
24
+ principal: principal ?? null,
25
+ };
26
+ }
27
+ async submit(workspaceId, request, principal, signal) {
28
+ const scope = this.scope(workspaceId, principal);
29
+ if (request.mutation && !this.resolver.get(workspaceId, principal).writeEnabled)
30
+ throw new ServiceError('WORKSPACE_WRITE_DISABLED', 'Background rewrites require an enabled workspace write policy');
31
+ return this.store.submit(scope, request, signal);
32
+ }
33
+ async get(workspaceId, id, principal, signal) {
34
+ const scope = this.scope(workspaceId, principal);
35
+ const record = await this.store.get(scope, id, signal);
36
+ if (jobRetentionExpired(record) && !record.request.mutation) {
37
+ await this.store.removeTerminal(scope, id, signal);
38
+ throw new ServiceError('JOB_NOT_FOUND', 'The retained job result has expired in the authorized scope');
39
+ }
40
+ return record;
41
+ }
42
+ async list(workspaceId, principal, options = {}) {
43
+ const scope = this.scope(workspaceId, principal);
44
+ const page = await this.store.list(scope, options);
45
+ const records = [];
46
+ for (const record of page.records) {
47
+ if (!jobRetentionExpired(record)) {
48
+ records.push(record);
49
+ continue;
50
+ }
51
+ if (!record.request.mutation)
52
+ await this.store.removeTerminal(scope, record.id, options.signal);
53
+ }
54
+ return { records, ...(page.next === undefined ? {} : { next: page.next }) };
55
+ }
56
+ async cancel(workspaceId, id, principal, signal) {
57
+ const scope = this.scope(workspaceId, principal);
58
+ for (;;) {
59
+ signal?.throwIfAborted();
60
+ const record = await this.store.get(scope, id, signal);
61
+ if (['completed', 'failed', 'cancelled'].includes(record.status) || record.cancelRequested)
62
+ return record;
63
+ try {
64
+ return await this.store.update(scope, id, record.revision, {
65
+ cancelRequested: true,
66
+ ...(record.status === 'queued' ? { status: 'cancelled' } : {}),
67
+ }, signal);
68
+ }
69
+ catch (error) {
70
+ if (!(error instanceof ServiceError) || error.code !== 'JOB_REVISION_CONFLICT')
71
+ throw error;
72
+ }
73
+ }
74
+ }
75
+ /** Settle a stopped attempt only when no uncertain write outcome can exist. */
76
+ async failInterrupted(workspaceId, id, failure, principal, signal) {
77
+ const scope = this.scope(workspaceId, principal);
78
+ for (;;) {
79
+ signal?.throwIfAborted();
80
+ const current = await this.store.get(scope, id, signal);
81
+ if (['completed', 'failed', 'cancelled'].includes(current.status))
82
+ return current;
83
+ if (current.request.mutation && current.transaction !== undefined)
84
+ throw new ServiceError('JOB_RECONCILIATION_REQUIRED', 'An interrupted rewrite must be reconciled from its bound transaction journal');
85
+ if (current.status === 'queued') {
86
+ try {
87
+ return await this.store.update(scope, id, current.revision, { status: 'failed', failure }, signal);
88
+ }
89
+ catch (error) {
90
+ if (!(error instanceof ServiceError) || error.code !== 'JOB_REVISION_CONFLICT')
91
+ throw error;
92
+ continue;
93
+ }
94
+ }
95
+ if (current.owner === undefined || jobOwnerLiveness(current.owner) !== 'dead')
96
+ throw new ServiceError('JOB_OWNER_UNRESOLVED', 'The interrupted execution owner has not been proven stopped');
97
+ const owner = currentJobOwner();
98
+ try {
99
+ const claimed = await this.store.claim(scope, id, owner, signal);
100
+ if (claimed.record.status === 'cancelled')
101
+ return claimed.record;
102
+ return await this.store.updateOwned(scope, id, owner.token, claimed.record.cancelRequested ? { status: 'cancelled' } : { status: 'failed', failure }, signal);
103
+ }
104
+ catch (error) {
105
+ if (error instanceof ServiceError &&
106
+ ['JOB_OWNER_ACTIVE', 'JOB_REVISION_CONFLICT'].includes(error.code))
107
+ continue;
108
+ throw error;
109
+ }
110
+ }
111
+ }
112
+ }