@nowcrew/daemon 0.6.16 → 0.6.18
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/agent-ability/runtime-context.js +7 -1
- package/dist/atomic-private-write.js +54 -1
- package/dist/automatic-install-target.js +40 -11
- package/dist/console.js +9 -0
- package/dist/control-plane-url.js +2 -2
- package/dist/daemon-migration-controller.js +198 -0
- package/dist/daemon-migration-wiring.js +22 -0
- package/dist/daemon-update-eligibility.js +1 -1
- package/dist/directory-projection-identity.js +32 -0
- package/dist/directory-projection.js +922 -0
- package/dist/execution-protocol.js +78 -11
- package/dist/execution-runner.js +50 -2
- package/dist/i18n.js +1 -0
- package/dist/local-execution-prompt.js +57 -0
- package/dist/local-executor.js +99 -40
- package/dist/machine-info.js +45 -9
- package/dist/main.js +0 -0
- package/dist/normalize.js +5 -0
- package/dist/profile-layout.js +41 -0
- package/dist/project-skills/controller.js +74 -14
- package/dist/project-skills/execution-adapter.js +11 -0
- package/dist/project-skills/initialized-reconciler.js +20 -0
- package/dist/project-skills/projection-set-switch.js +419 -0
- package/dist/project-skills/projection-state-domain.js +153 -0
- package/dist/project-skills/projection-state-store.js +841 -0
- package/dist/project-skills/projection-state-transaction.js +318 -0
- package/dist/project-skills/projection-state.js +3 -0
- package/dist/project-skills/reconciler.js +299 -68
- package/dist/project-skills/runtime-warning.js +6 -0
- package/dist/project-skills/scanner.js +30 -1
- package/dist/project-skills/types.js +9 -0
- package/dist/project-workspaces/resolver.js +179 -0
- package/dist/project-workspaces/types.js +1 -0
- package/dist/prompt.js +40 -0
- package/dist/runtimes/claude.js +235 -4
- package/dist/runtimes/codex-app-server-runner.js +100 -25
- package/dist/runtimes/codex-contract.js +123 -0
- package/dist/runtimes/codex.js +2 -0
- package/dist/serve.js +31 -17
- package/dist/session.js +3 -0
- package/dist/supervised-runtime.js +12 -4
- package/dist/workspace.js +14 -5
- package/package.json +10 -9
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { chmod, link, lstat, mkdir, readlink, rename, symlink } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { appliedProjectSkillManifestPath, projectSkillManifestStoreInternals as store, } from "./projection-state-store.js";
|
|
5
|
+
const manifestsMatch = (left, right) => JSON.stringify(left) === JSON.stringify(right);
|
|
6
|
+
export const projectSkillManifestUpdateRecord = (update) => Object.freeze({
|
|
7
|
+
managedBy: "nowcrew-project-skills-v2-update",
|
|
8
|
+
version: 1,
|
|
9
|
+
operationId: update.operationId,
|
|
10
|
+
previous: update.previous,
|
|
11
|
+
next: update.next,
|
|
12
|
+
});
|
|
13
|
+
export const parseProjectSkillManifestUpdateRecord = (candidate) => {
|
|
14
|
+
if (candidate === null || typeof candidate !== "object")
|
|
15
|
+
return store.pathUnmanaged();
|
|
16
|
+
const record = candidate;
|
|
17
|
+
if (record.managedBy !== "nowcrew-project-skills-v2-update"
|
|
18
|
+
|| record.version !== 1
|
|
19
|
+
|| typeof record.operationId !== "string"
|
|
20
|
+
|| !store.ARTIFACT_ID.test(record.operationId)
|
|
21
|
+
|| !("previous" in record)
|
|
22
|
+
|| !("next" in record)
|
|
23
|
+
|| Object.keys(record).sort().join(",") !== "managedBy,next,operationId,previous,version") {
|
|
24
|
+
return store.pathUnmanaged();
|
|
25
|
+
}
|
|
26
|
+
const previous = record.previous === null
|
|
27
|
+
? null
|
|
28
|
+
: store.parseAppliedProjectSkillManifest(record.previous);
|
|
29
|
+
const next = record.next === null ? null : store.parseAppliedProjectSkillManifest(record.next);
|
|
30
|
+
return Object.freeze({
|
|
31
|
+
managedBy: "nowcrew-project-skills-v2-update",
|
|
32
|
+
version: 1,
|
|
33
|
+
operationId: record.operationId,
|
|
34
|
+
previous,
|
|
35
|
+
next,
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
export const preparedProjectSkillManifestUpdateFromRecord = (agentRoot, candidate) => {
|
|
39
|
+
const record = parseProjectSkillManifestUpdateRecord(candidate);
|
|
40
|
+
return Object.freeze({
|
|
41
|
+
agentRoot,
|
|
42
|
+
operationId: record.operationId,
|
|
43
|
+
previous: record.previous,
|
|
44
|
+
next: record.next,
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
const stateContext = async (agentRoot, options, settle) => {
|
|
48
|
+
const syncDirectory = store.projectionDirectorySync(options);
|
|
49
|
+
await store.realOwnedDirectory(agentRoot, false);
|
|
50
|
+
const stateDirectory = join(agentRoot, ".crew");
|
|
51
|
+
if (!await store.realOwnedDirectory(stateDirectory, true)) {
|
|
52
|
+
try {
|
|
53
|
+
await mkdir(stateDirectory, { mode: 0o700 });
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
if (!store.isExisting(error))
|
|
57
|
+
return store.pathUnmanaged();
|
|
58
|
+
}
|
|
59
|
+
await store.realOwnedDirectory(stateDirectory, false);
|
|
60
|
+
}
|
|
61
|
+
await chmod(stateDirectory, 0o700).catch(() => store.pathUnmanaged());
|
|
62
|
+
const manifestPath = appliedProjectSkillManifestPath(agentRoot);
|
|
63
|
+
if (settle) {
|
|
64
|
+
await store.settleDiscardResidues(stateDirectory, syncDirectory);
|
|
65
|
+
await store.settlePreparingResidues(stateDirectory, syncDirectory);
|
|
66
|
+
await store.settleAnyExistingOperation(manifestPath, stateDirectory, syncDirectory);
|
|
67
|
+
}
|
|
68
|
+
return Object.freeze({ manifestPath, stateDirectory, syncDirectory });
|
|
69
|
+
};
|
|
70
|
+
const operationPath = (stateDirectory, operationId) => {
|
|
71
|
+
if (!store.ARTIFACT_ID.test(operationId))
|
|
72
|
+
return store.pathUnmanaged();
|
|
73
|
+
return join(stateDirectory, `${store.OPERATION_PREFIX}${operationId}${store.OPERATION_SUFFIX}`);
|
|
74
|
+
};
|
|
75
|
+
const loadBoundUpdate = async (update, options) => {
|
|
76
|
+
const context = await stateContext(update.agentRoot, options, false);
|
|
77
|
+
const operation = await store.loadOperation(operationPath(context.stateDirectory, update.operationId));
|
|
78
|
+
if (operation.intent.nonce !== update.operationId || operation.stage === null)
|
|
79
|
+
return store.pathUnmanaged();
|
|
80
|
+
const next = store.isAbsenceMarkerRaw(operation.intent.stage.content)
|
|
81
|
+
? null
|
|
82
|
+
: store.parseManifestRaw(operation.intent.stage.content);
|
|
83
|
+
const previous = operation.intent.previous === null
|
|
84
|
+
? null
|
|
85
|
+
: store.parseManifestRaw(operation.intent.previous.content);
|
|
86
|
+
if (!manifestsMatch(next, update.next) || !manifestsMatch(previous, update.previous)) {
|
|
87
|
+
return store.pathUnmanaged();
|
|
88
|
+
}
|
|
89
|
+
return Object.freeze({ ...context, operation });
|
|
90
|
+
};
|
|
91
|
+
const completedWithoutOperation = async (update, expected, options) => {
|
|
92
|
+
const context = await stateContext(update.agentRoot, options, false);
|
|
93
|
+
const path = operationPath(context.stateDirectory, update.operationId);
|
|
94
|
+
try {
|
|
95
|
+
await lstat(path);
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
if (error.code !== "ENOENT")
|
|
100
|
+
return store.pathUnmanaged();
|
|
101
|
+
}
|
|
102
|
+
await store.settleDiscardResidues(context.stateDirectory, context.syncDirectory);
|
|
103
|
+
const current = await store.readStableFile(context.manifestPath, store.MAX_MANIFEST_BYTES);
|
|
104
|
+
const manifest = current === null ? null : store.parseManifestRaw(current.raw);
|
|
105
|
+
if (!manifestsMatch(manifest, expected))
|
|
106
|
+
return store.pathUnmanaged();
|
|
107
|
+
return true;
|
|
108
|
+
};
|
|
109
|
+
const restoreUnknownClaimNoClobber = async (claimedPath, manifestPath, syncDirectory, stateDirectory, afterSlotChecked) => {
|
|
110
|
+
const claimedIdentity = await lstat(claimedPath, { bigint: true }).catch(() => store.pathUnmanaged());
|
|
111
|
+
if (claimedIdentity.isFile()) {
|
|
112
|
+
try {
|
|
113
|
+
await link(claimedPath, manifestPath);
|
|
114
|
+
await syncDirectory(stateDirectory);
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return store.pathUnmanaged();
|
|
118
|
+
}
|
|
119
|
+
const restored = await lstat(manifestPath, { bigint: true }).catch(() => store.pathUnmanaged());
|
|
120
|
+
if (restored.dev !== claimedIdentity.dev || restored.ino !== claimedIdentity.ino) {
|
|
121
|
+
return store.pathUnmanaged();
|
|
122
|
+
}
|
|
123
|
+
return store.pathUnmanaged();
|
|
124
|
+
}
|
|
125
|
+
try {
|
|
126
|
+
await lstat(manifestPath);
|
|
127
|
+
return store.pathUnmanaged();
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
if (error.code !== "ENOENT")
|
|
131
|
+
return store.pathUnmanaged();
|
|
132
|
+
}
|
|
133
|
+
await afterSlotChecked?.();
|
|
134
|
+
if (!claimedIdentity.isSymbolicLink())
|
|
135
|
+
return store.pathUnmanaged();
|
|
136
|
+
const target = await readlink(claimedPath).catch(() => store.pathUnmanaged());
|
|
137
|
+
const beforeRestore = await lstat(claimedPath, { bigint: true }).catch(() => store.pathUnmanaged());
|
|
138
|
+
if (!beforeRestore.isSymbolicLink()
|
|
139
|
+
|| beforeRestore.dev !== claimedIdentity.dev
|
|
140
|
+
|| beforeRestore.ino !== claimedIdentity.ino) {
|
|
141
|
+
return store.pathUnmanaged();
|
|
142
|
+
}
|
|
143
|
+
try {
|
|
144
|
+
await symlink(target, manifestPath);
|
|
145
|
+
await syncDirectory(stateDirectory);
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
return store.pathUnmanaged();
|
|
149
|
+
}
|
|
150
|
+
const restored = await lstat(manifestPath, { bigint: true }).catch(() => store.pathUnmanaged());
|
|
151
|
+
if (!restored.isSymbolicLink()
|
|
152
|
+
|| await readlink(manifestPath).catch(() => store.pathUnmanaged()) !== target) {
|
|
153
|
+
return store.pathUnmanaged();
|
|
154
|
+
}
|
|
155
|
+
return store.pathUnmanaged();
|
|
156
|
+
};
|
|
157
|
+
const claimPublicManifest = async (context, destinationBasename, expected, beforeClaim, afterClaim, afterRestoreSlotChecked) => {
|
|
158
|
+
const claimedPath = join(context.operation.path, destinationBasename);
|
|
159
|
+
await beforeClaim?.();
|
|
160
|
+
try {
|
|
161
|
+
await rename(context.manifestPath, claimedPath);
|
|
162
|
+
await context.syncDirectory(context.operation.path);
|
|
163
|
+
await context.syncDirectory(context.stateDirectory);
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
return store.pathUnmanaged();
|
|
167
|
+
}
|
|
168
|
+
await afterClaim?.(claimedPath);
|
|
169
|
+
const claimed = await store.readStableFile(claimedPath, store.MAX_MANIFEST_BYTES).catch(() => restoreUnknownClaimNoClobber(claimedPath, context.manifestPath, context.syncDirectory, context.stateDirectory, afterRestoreSlotChecked === undefined ? undefined : () => afterRestoreSlotChecked(claimedPath)));
|
|
170
|
+
if (claimed === null || !store.snapshotMatchesBinding(claimed, expected, true)) {
|
|
171
|
+
return restoreUnknownClaimNoClobber(claimedPath, context.manifestPath, context.syncDirectory, context.stateDirectory, afterRestoreSlotChecked === undefined ? undefined : () => afterRestoreSlotChecked(claimedPath));
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
const prepareManifestTransition = async (agentRoot, next, options = {}) => {
|
|
175
|
+
const context = await stateContext(agentRoot, options, true);
|
|
176
|
+
const current = await store.readStableFile(context.manifestPath, store.MAX_MANIFEST_BYTES);
|
|
177
|
+
const previous = current === null ? null : store.parseManifestRaw(current.raw);
|
|
178
|
+
const content = next === null ? store.ABSENCE_MARKER_RAW : `${JSON.stringify(next)}\n`;
|
|
179
|
+
const operation = await store.createOperation(context.stateDirectory, current, content, options.randomId ?? randomUUID, context.syncDirectory, options.afterIntentDurableBeforeActivate);
|
|
180
|
+
await options.afterStageDurable?.(join(operation.path, store.STAGE_BASENAME));
|
|
181
|
+
const reloaded = await store.loadOperation(operation.path);
|
|
182
|
+
const observed = await store.readStableFile(context.manifestPath, store.MAX_MANIFEST_BYTES);
|
|
183
|
+
if (!store.sameSnapshot(reloaded.intentSnapshot, operation.intentSnapshot)
|
|
184
|
+
|| reloaded.stage === null
|
|
185
|
+
|| !store.snapshotMatchesBinding(reloaded.stage, operation.intent.stage, false)
|
|
186
|
+
|| (current === null ? observed !== null : observed === null || !store.sameSnapshot(current, observed))) {
|
|
187
|
+
await store.cleanupOperation(operation.path, context.syncDirectory);
|
|
188
|
+
return store.pathUnmanaged();
|
|
189
|
+
}
|
|
190
|
+
return Object.freeze({ agentRoot, operationId: operation.intent.nonce, previous, next });
|
|
191
|
+
};
|
|
192
|
+
export async function prepareAppliedProjectSkillManifestUpdate(agentRoot, manifest, options = {}) {
|
|
193
|
+
return prepareManifestTransition(agentRoot, store.parseAppliedProjectSkillManifest(manifest), options);
|
|
194
|
+
}
|
|
195
|
+
export async function prepareAppliedProjectSkillManifestRemoval(agentRoot, options = {}) {
|
|
196
|
+
return prepareManifestTransition(agentRoot, null, options);
|
|
197
|
+
}
|
|
198
|
+
export async function publishPreparedProjectSkillManifestUpdate(update, options = {}) {
|
|
199
|
+
if (await completedWithoutOperation(update, update.next, options))
|
|
200
|
+
return;
|
|
201
|
+
const context = await loadBoundUpdate(update, options);
|
|
202
|
+
const { operation } = context;
|
|
203
|
+
const existing = await store.readStableFile(context.manifestPath, store.MAX_MANIFEST_BYTES);
|
|
204
|
+
if (update.next !== null
|
|
205
|
+
&& existing !== null
|
|
206
|
+
&& store.snapshotMatchesBinding(existing, operation.intent.stage, true))
|
|
207
|
+
return;
|
|
208
|
+
if (operation.intent.previous === null) {
|
|
209
|
+
if (existing !== null || operation.previous !== null)
|
|
210
|
+
return store.pathUnmanaged();
|
|
211
|
+
}
|
|
212
|
+
else if (operation.previous === null) {
|
|
213
|
+
if (existing === null || !store.snapshotMatchesBinding(existing, operation.intent.previous, true)) {
|
|
214
|
+
return store.pathUnmanaged();
|
|
215
|
+
}
|
|
216
|
+
await claimPublicManifest(context, store.PREVIOUS_BASENAME, operation.intent.previous, undefined, options.afterCurrentClaimed);
|
|
217
|
+
}
|
|
218
|
+
else if (existing !== null) {
|
|
219
|
+
return store.pathUnmanaged();
|
|
220
|
+
}
|
|
221
|
+
const publishable = await store.loadOperation(operation.path);
|
|
222
|
+
if (update.next === null && publishable.published !== null) {
|
|
223
|
+
if (existing !== null)
|
|
224
|
+
return store.pathUnmanaged();
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
const stagePath = join(operation.path, store.STAGE_BASENAME);
|
|
228
|
+
const stage = await store.readStableFile(stagePath, store.MAX_MANIFEST_BYTES);
|
|
229
|
+
if (!store.sameSnapshot(publishable.intentSnapshot, operation.intentSnapshot)
|
|
230
|
+
|| stage === null
|
|
231
|
+
|| !store.snapshotMatchesBinding(stage, operation.intent.stage, false))
|
|
232
|
+
return store.pathUnmanaged();
|
|
233
|
+
if (update.next === null) {
|
|
234
|
+
try {
|
|
235
|
+
await link(stagePath, context.manifestPath);
|
|
236
|
+
await context.syncDirectory(context.stateDirectory);
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
if (!store.isExisting(error))
|
|
240
|
+
return store.pathUnmanaged();
|
|
241
|
+
}
|
|
242
|
+
const claim = await store.readStableFile(context.manifestPath, store.MAX_MANIFEST_BYTES);
|
|
243
|
+
if (claim === null || !store.snapshotMatchesBinding(claim, operation.intent.stage, true)) {
|
|
244
|
+
return store.pathUnmanaged();
|
|
245
|
+
}
|
|
246
|
+
await claimPublicManifest(context, store.PUBLISHED_BASENAME, operation.intent.stage, options.afterRemovalMarkerPublished === undefined
|
|
247
|
+
? undefined
|
|
248
|
+
: () => options.afterRemovalMarkerPublished(context.manifestPath));
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
try {
|
|
252
|
+
await link(stagePath, context.manifestPath);
|
|
253
|
+
await context.syncDirectory(context.stateDirectory);
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
if (!store.isExisting(error))
|
|
257
|
+
return store.pathUnmanaged();
|
|
258
|
+
}
|
|
259
|
+
const published = await store.readStableFile(context.manifestPath, store.MAX_MANIFEST_BYTES);
|
|
260
|
+
if (published === null
|
|
261
|
+
|| !store.snapshotMatchesBinding(published, operation.intent.stage, true)
|
|
262
|
+
|| published.identity.dev !== stage.identity.dev
|
|
263
|
+
|| published.identity.ino !== stage.identity.ino)
|
|
264
|
+
return store.pathUnmanaged();
|
|
265
|
+
}
|
|
266
|
+
export async function commitPreparedProjectSkillManifestUpdate(update, options = {}) {
|
|
267
|
+
if (await completedWithoutOperation(update, update.next, options))
|
|
268
|
+
return;
|
|
269
|
+
const context = await loadBoundUpdate(update, options);
|
|
270
|
+
const published = await store.readStableFile(context.manifestPath, store.MAX_MANIFEST_BYTES);
|
|
271
|
+
const removalPublished = update.next === null
|
|
272
|
+
&& published === null
|
|
273
|
+
&& context.operation.published !== null;
|
|
274
|
+
if (!removalPublished && (published === null
|
|
275
|
+
|| !store.snapshotMatchesBinding(published, context.operation.intent.stage, true))) {
|
|
276
|
+
return store.pathUnmanaged();
|
|
277
|
+
}
|
|
278
|
+
await store.cleanupOperation(context.operation.path, context.syncDirectory, options);
|
|
279
|
+
}
|
|
280
|
+
export async function rollbackPreparedProjectSkillManifestUpdate(update, options = {}) {
|
|
281
|
+
if (await completedWithoutOperation(update, update.previous, options))
|
|
282
|
+
return;
|
|
283
|
+
let context = await loadBoundUpdate(update, options);
|
|
284
|
+
let current = await store.readStableFile(context.manifestPath, store.MAX_MANIFEST_BYTES);
|
|
285
|
+
if (current !== null && store.snapshotMatchesBinding(current, context.operation.intent.stage, true)) {
|
|
286
|
+
try {
|
|
287
|
+
await lstat(join(context.operation.path, store.PUBLISHED_BASENAME));
|
|
288
|
+
return store.pathUnmanaged();
|
|
289
|
+
}
|
|
290
|
+
catch (error) {
|
|
291
|
+
if (error.code !== "ENOENT")
|
|
292
|
+
return store.pathUnmanaged();
|
|
293
|
+
}
|
|
294
|
+
await claimPublicManifest(context, store.PUBLISHED_BASENAME, context.operation.intent.stage, options.afterRollbackFinalCheck === undefined
|
|
295
|
+
? undefined
|
|
296
|
+
: () => options.afterRollbackFinalCheck(context.manifestPath), options.afterRollbackUnknownClaimed === undefined
|
|
297
|
+
? undefined
|
|
298
|
+
: (claimedPath) => options.afterRollbackUnknownClaimed(claimedPath, context.manifestPath), options.afterRollbackRestoreSlotChecked === undefined
|
|
299
|
+
? undefined
|
|
300
|
+
: (claimedPath) => options.afterRollbackRestoreSlotChecked(claimedPath, context.manifestPath));
|
|
301
|
+
context = await loadBoundUpdate(update, options);
|
|
302
|
+
if (context.operation.published === null)
|
|
303
|
+
return store.pathUnmanaged();
|
|
304
|
+
current = null;
|
|
305
|
+
}
|
|
306
|
+
const previousBinding = context.operation.intent.previous;
|
|
307
|
+
if (previousBinding === null) {
|
|
308
|
+
if (current !== null)
|
|
309
|
+
return store.pathUnmanaged();
|
|
310
|
+
}
|
|
311
|
+
else if (current === null) {
|
|
312
|
+
await store.restorePreviousNoClobber(context.operation, context.manifestPath, context.stateDirectory, context.syncDirectory);
|
|
313
|
+
}
|
|
314
|
+
else if (!store.snapshotMatchesBinding(current, previousBinding, true)) {
|
|
315
|
+
return store.pathUnmanaged();
|
|
316
|
+
}
|
|
317
|
+
await store.cleanupOperation(context.operation.path, context.syncDirectory, options);
|
|
318
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { computeProjectSkillBindingDigest, computeProjectSkillResolutionDigest, createAppliedProjectSkillManifest, normalizeProjectSkillResolutionRecords, ProjectSkillProjectionStateError, } from "./projection-state-domain.js";
|
|
2
|
+
export { appliedProjectSkillManifestPath, readAppliedProjectSkillManifest, writeAppliedProjectSkillManifest, } from "./projection-state-store.js";
|
|
3
|
+
export { commitPreparedProjectSkillManifestUpdate, parseProjectSkillManifestUpdateRecord, prepareAppliedProjectSkillManifestRemoval, prepareAppliedProjectSkillManifestUpdate, preparedProjectSkillManifestUpdateFromRecord, projectSkillManifestUpdateRecord, publishPreparedProjectSkillManifestUpdate, rollbackPreparedProjectSkillManifestUpdate, } from "./projection-state-transaction.js";
|