@lazyingart/agintiflow 0.20.205 → 0.20.206
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/docs/supervision-campaign-ledger.md +0 -5
- package/package.json +1 -1
- package/scripts/smoke-supervision-ledger.js +1 -20
- package/scripts/supervision-ledger.js +11 -45
- package/src/agent-runner.js +2 -5
- package/src/integration-core-event-projector.js +32 -116
- package/src/integration-native-executor.js +15 -90
- package/src/integration-runtime-authority.js +94 -965
- package/src/session-store.js +416 -503
- package/src/integration-session-persistence.js +0 -504
|
@@ -38,11 +38,6 @@ Create, start, and finish a concrete run with `test`, `start`, `event`, and
|
|
|
38
38
|
idempotent or append-only SQLite operation suitable for a persistent tmux
|
|
39
39
|
campaign.
|
|
40
40
|
|
|
41
|
-
Test registration validates that any named capability and scenario belong to
|
|
42
|
-
the same campaign. Finishing a test updates the test, capability, and scenario
|
|
43
|
-
status in one SQLite transaction, so a typo cannot silently leave the campaign
|
|
44
|
-
matrix stale or split across contradictory states.
|
|
45
|
-
|
|
46
41
|
Inspect current coverage:
|
|
47
42
|
|
|
48
43
|
```bash
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazyingart/agintiflow",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.206",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "AgInTiFlow is a project-aware agent workspace for hybrid wet-dry R&D, hardware-aware intelligence, software automation, and industrial workflows.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -19,17 +19,6 @@ function run(command, args = []) {
|
|
|
19
19
|
}));
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
function runFails(command, args, expected) {
|
|
23
|
-
try {
|
|
24
|
-
run(command, args);
|
|
25
|
-
} catch (error) {
|
|
26
|
-
const output = `${error?.stdout || ""}\n${error?.stderr || ""}\n${error?.message || ""}`;
|
|
27
|
-
assert(expected.test(output), `unexpected ${command} failure: ${output}`);
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
throw new Error(`${command} unexpectedly succeeded`);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
22
|
function assert(condition, message) {
|
|
34
23
|
if (!condition) throw new Error(message);
|
|
35
24
|
}
|
|
@@ -44,14 +33,6 @@ run("scenario", [
|
|
|
44
33
|
"--prompt-quality", "normal", "--prompt", "Prepare the media chain without publishing.",
|
|
45
34
|
"--expected-outputs", "[\"readiness.md\"]", "--validation", "Verify routine paths and no external write.",
|
|
46
35
|
]);
|
|
47
|
-
runFails("test", [
|
|
48
|
-
"--id", "missing-capability", "--capability", "not-registered", "--scenario", "media-dry-run",
|
|
49
|
-
"--title", "Invalid capability reference", "--validation", "Must fail before insertion.",
|
|
50
|
-
], /Unknown capability/);
|
|
51
|
-
runFails("test", [
|
|
52
|
-
"--id", "missing-scenario", "--capability", "media-chain", "--scenario", "not-registered",
|
|
53
|
-
"--title", "Invalid scenario reference", "--validation", "Must fail before insertion.",
|
|
54
|
-
], /Unknown scenario/);
|
|
55
36
|
run("test", [
|
|
56
37
|
"--id", "media-dry-run-001", "--capability", "media-chain", "--scenario", "media-dry-run",
|
|
57
38
|
"--title", "Read-only established media routine probe", "--prompt-path", "TASK.md",
|
|
@@ -79,7 +60,7 @@ assert(status.ok, "ledger status did not succeed");
|
|
|
79
60
|
assert(fs.statSync(db).size > 0, "ledger database is empty");
|
|
80
61
|
assert(status.campaign?.id === "smoke", "campaign row was not preserved");
|
|
81
62
|
assert(status.capability_counts.some((row) => row.status === "passed_after_fix" && row.count === 1), "capability status was not updated");
|
|
82
|
-
assert(status.scenario_counts.some((row) => row.status === "
|
|
63
|
+
assert(status.scenario_counts.some((row) => row.status === "backlog" && row.count === 1), "scenario was not recorded");
|
|
83
64
|
assert(status.test_counts.some((row) => row.status === "passed_after_fix" && row.count === 1), "test result was not recorded");
|
|
84
65
|
assert(status.recent_tests[0]?.session_id === "session-smoke", "session evidence was not retained");
|
|
85
66
|
|
|
@@ -32,24 +32,6 @@ function jsonValue(value, fallback = []) {
|
|
|
32
32
|
return JSON.stringify(JSON.parse(String(value)));
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
function assertCampaignReference(db, table, id, campaignId, label) {
|
|
36
|
-
if (!id) return;
|
|
37
|
-
const row = db.prepare(`SELECT id FROM ${table} WHERE id=? AND campaign_id=?`).get(id, campaignId);
|
|
38
|
-
if (!row) throw new Error(`Unknown ${label} for campaign ${campaignId}: ${id}`);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function runTransaction(db, operation) {
|
|
42
|
-
db.exec("BEGIN IMMEDIATE");
|
|
43
|
-
try {
|
|
44
|
-
const result = operation();
|
|
45
|
-
db.exec("COMMIT");
|
|
46
|
-
return result;
|
|
47
|
-
} catch (error) {
|
|
48
|
-
db.exec("ROLLBACK");
|
|
49
|
-
throw error;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
35
|
function openLedger(dbPath) {
|
|
54
36
|
const resolved = path.resolve(dbPath);
|
|
55
37
|
fs.mkdirSync(path.dirname(resolved), { recursive: true });
|
|
@@ -149,10 +131,6 @@ function main() {
|
|
|
149
131
|
result = { scenario: id };
|
|
150
132
|
} else if (command === "test") {
|
|
151
133
|
const id = required(options, "id");
|
|
152
|
-
const capabilityId = String(options.capability || "");
|
|
153
|
-
const scenarioId = String(options.scenario || "");
|
|
154
|
-
assertCampaignReference(db, "capabilities", capabilityId, campaignId, "capability");
|
|
155
|
-
assertCampaignReference(db, "scenarios", scenarioId, campaignId, "scenario");
|
|
156
134
|
db.prepare(`INSERT INTO test_items
|
|
157
135
|
(id, campaign_id, capability_id, scenario_id, title, profile, prompt_quality,
|
|
158
136
|
prompt_path, expected_outputs_json, validation_plan, status, updated_at)
|
|
@@ -161,7 +139,7 @@ function main() {
|
|
|
161
139
|
title=excluded.title, profile=excluded.profile, prompt_quality=excluded.prompt_quality,
|
|
162
140
|
prompt_path=excluded.prompt_path, expected_outputs_json=excluded.expected_outputs_json,
|
|
163
141
|
validation_plan=excluded.validation_plan, updated_at=excluded.updated_at`).run(
|
|
164
|
-
id, campaignId,
|
|
142
|
+
id, campaignId, String(options.capability || ""), String(options.scenario || ""),
|
|
165
143
|
required(options, "title"), String(options.profile || "auto"),
|
|
166
144
|
String(options.prompt_quality || "normal"), String(options.prompt_path || ""),
|
|
167
145
|
jsonValue(options.expected_outputs), String(options.validation || ""),
|
|
@@ -188,28 +166,16 @@ function main() {
|
|
|
188
166
|
} else if (command === "finish") {
|
|
189
167
|
const id = required(options, "id");
|
|
190
168
|
const status = required(options, "status");
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
)
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
finished_at=?, updated_at=? WHERE id=? AND campaign_id=?`).run(
|
|
202
|
-
status, summary, evidence, timestamp, timestamp, id, campaignId
|
|
203
|
-
);
|
|
204
|
-
if (item.capability_id) {
|
|
205
|
-
db.prepare(`UPDATE capabilities SET status=?, last_test_id=?, updated_at=?
|
|
206
|
-
WHERE id=? AND campaign_id=?`).run(status, id, timestamp, item.capability_id, campaignId);
|
|
207
|
-
}
|
|
208
|
-
if (item.scenario_id) {
|
|
209
|
-
db.prepare("UPDATE scenarios SET status=?, updated_at=? WHERE id=? AND campaign_id=?")
|
|
210
|
-
.run(status, timestamp, item.scenario_id, campaignId);
|
|
211
|
-
}
|
|
212
|
-
});
|
|
169
|
+
const changed = db.prepare(`UPDATE test_items SET status=?, result_summary=?, evidence_json=?,
|
|
170
|
+
finished_at=?, updated_at=? WHERE id=? AND campaign_id=?`).run(
|
|
171
|
+
status, required(options, "summary"), jsonValue(options.evidence), timestamp, timestamp, id, campaignId
|
|
172
|
+
);
|
|
173
|
+
if (Number(changed.changes || 0) !== 1) throw new Error(`Unknown test item: ${id}`);
|
|
174
|
+
const item = db.prepare("SELECT capability_id FROM test_items WHERE id=?").get(id);
|
|
175
|
+
if (item?.capability_id) {
|
|
176
|
+
db.prepare("UPDATE capabilities SET status=?, last_test_id=?, updated_at=? WHERE id=?")
|
|
177
|
+
.run(status, id, timestamp, item.capability_id);
|
|
178
|
+
}
|
|
213
179
|
result = { test: id, status };
|
|
214
180
|
} else if (command === "fix") {
|
|
215
181
|
const id = required(options, "id");
|
package/src/agent-runner.js
CHANGED
|
@@ -7,7 +7,6 @@ import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
7
7
|
import { chromium } from "playwright";
|
|
8
8
|
import { createClient, createPlan, requestNextStep } from "./model-client.js";
|
|
9
9
|
import { SessionStore } from "./session-store.js";
|
|
10
|
-
import { assertIntegrationRunAgentInvocation } from "./integration-session-persistence.js";
|
|
11
10
|
import { captureSnapshot } from "./snapshot.js";
|
|
12
11
|
import { checkToolUse } from "./guardrails.js";
|
|
13
12
|
import { ensureDockerSandboxReady, runDockerSandboxCommand } from "./docker-sandbox.js";
|
|
@@ -237,9 +236,8 @@ function withSelectedSkillReadOnlyRoots(config = {}, state = {}) {
|
|
|
237
236
|
function throwIfAborted(config) {
|
|
238
237
|
if (config.abortSignal?.aborted) {
|
|
239
238
|
const reason = config.abortSignal.reason;
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
error.name = "AbortError";
|
|
239
|
+
const error = reason instanceof Error ? reason : new Error("Run interrupted by user.");
|
|
240
|
+
error.name = error.name || "AbortError";
|
|
243
241
|
throw error;
|
|
244
242
|
}
|
|
245
243
|
}
|
|
@@ -4526,7 +4524,6 @@ async function recordPreInferenceFailure({ error, config, state, store, observer
|
|
|
4526
4524
|
}
|
|
4527
4525
|
|
|
4528
4526
|
export async function runAgent(config) {
|
|
4529
|
-
assertIntegrationRunAgentInvocation(config);
|
|
4530
4527
|
const incomingConfig = config;
|
|
4531
4528
|
const sessionId = config.resume || config.sessionId || `web-agent-${crypto.randomUUID()}`;
|
|
4532
4529
|
const store = new SessionStore(config.sessionsDir, sessionId, {
|
|
@@ -59,7 +59,7 @@ const FORBIDDEN_KEYS = new Set([
|
|
|
59
59
|
"url",
|
|
60
60
|
]);
|
|
61
61
|
const ABSOLUTE_PATH_OR_SECRET_PATTERN =
|
|
62
|
-
/(?:^|[\s("'
|
|
62
|
+
/(?:^|[\s("'`])(?:\/(?:workspace|home|users|root|etc|usr|var|opt|srv|run|tmp|proc|sys|dev|mnt|media|aginti-(?:home|cache|env))(?:\/|\b)|[A-Za-z]:\\|(?:api[_-]?key|token|secret|password)\s*[:=])/iu;
|
|
63
63
|
const EVENT_LEDGER_STORE_REQUIRED_KEYS = Object.freeze([
|
|
64
64
|
"owner",
|
|
65
65
|
"authority",
|
|
@@ -383,103 +383,29 @@ export function createIntegrationCoreEventProjector(options = {}) {
|
|
|
383
383
|
}
|
|
384
384
|
}
|
|
385
385
|
|
|
386
|
-
function toolStateKey(scope) {
|
|
387
|
-
return `${scope.principalId}\n${scope.browserSessionId}\n${scope.threadId}\n${scope.runId}`;
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
function validateLedgerHeadCursor(headInput, label) {
|
|
391
|
-
const seq = Number(headInput?.seq ?? 0);
|
|
392
|
-
const hash = String(headInput?.hash ?? "0".repeat(64));
|
|
393
|
-
if (
|
|
394
|
-
!Number.isSafeInteger(seq) ||
|
|
395
|
-
seq < 0 ||
|
|
396
|
-
!/^[a-f0-9]{64}$/u.test(hash) ||
|
|
397
|
-
((seq === 0) !== (hash === "0".repeat(64)))
|
|
398
|
-
) {
|
|
399
|
-
authorityFail("PUBLIC_EVENT_LEDGER_CORRUPT", `${label} cursor is invalid.`);
|
|
400
|
-
}
|
|
401
|
-
return Object.freeze({ seq, hash });
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
function assertPublicEventEnvelopeHash(event, label) {
|
|
405
|
-
const checked = createPublicIntegrationEvent({
|
|
406
|
-
threadId: event.threadId,
|
|
407
|
-
runId: event.runId,
|
|
408
|
-
seq: event.seq,
|
|
409
|
-
type: event.type,
|
|
410
|
-
payload: event.payload,
|
|
411
|
-
createdAt: event.createdAt,
|
|
412
|
-
previousHash: event.previousHash,
|
|
413
|
-
});
|
|
414
|
-
if (
|
|
415
|
-
event.schemaVersion !== checked.schemaVersion ||
|
|
416
|
-
event.id !== checked.id ||
|
|
417
|
-
event.hash !== checked.hash ||
|
|
418
|
-
contractDigest(event) !== contractDigest(checked)
|
|
419
|
-
) {
|
|
420
|
-
authorityFail("PUBLIC_EVENT_LEDGER_CORRUPT", `${label} hash is invalid.`);
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
async function loadLedgerHeadAndLastEvent(ledger, scope) {
|
|
425
|
-
if (
|
|
426
|
-
!ledger ||
|
|
427
|
-
typeof ledger.loadHead !== "function" ||
|
|
428
|
-
typeof ledger.loadCursor !== "function" ||
|
|
429
|
-
typeof ledger.loadEventsAfter !== "function"
|
|
430
|
-
) {
|
|
431
|
-
authorityFail("PUBLIC_EVENT_LEDGER_UNAVAILABLE", "Public event ledger head is unavailable.");
|
|
432
|
-
}
|
|
433
|
-
const head = validateLedgerHeadCursor(await ledger.loadHead(), "Public event ledger head");
|
|
434
|
-
if (head.seq === 0) return Object.freeze({ head, lastEvent: null });
|
|
435
|
-
const cursor = validateLedgerHeadCursor(await ledger.loadCursor(head.seq), "Public event ledger head event");
|
|
436
|
-
if (cursor.seq !== head.seq || cursor.hash !== head.hash) {
|
|
437
|
-
authorityFail("PUBLIC_EVENT_LEDGER_CORRUPT", "Public event ledger head cursor does not match the last event.");
|
|
438
|
-
}
|
|
439
|
-
const events = await ledger.loadEventsAfter(head.seq - 1);
|
|
440
|
-
if (!Array.isArray(events) || events.length !== 1) {
|
|
441
|
-
authorityFail("PUBLIC_EVENT_LEDGER_CORRUPT", "Public event ledger did not return the exact last event.");
|
|
442
|
-
}
|
|
443
|
-
const [lastEvent] = events;
|
|
444
|
-
assertExactPublicEventView(lastEvent, "Public event ledger last event");
|
|
445
|
-
if (
|
|
446
|
-
lastEvent.threadId !== scope.threadId ||
|
|
447
|
-
lastEvent.runId !== scope.runId ||
|
|
448
|
-
lastEvent.seq !== head.seq ||
|
|
449
|
-
lastEvent.hash !== head.hash
|
|
450
|
-
) {
|
|
451
|
-
authorityFail("PUBLIC_EVENT_LEDGER_CORRUPT", "Public event ledger last event does not match the requested head.");
|
|
452
|
-
}
|
|
453
|
-
if (
|
|
454
|
-
(lastEvent.principalId !== undefined && lastEvent.principalId !== scope.principalId) ||
|
|
455
|
-
(lastEvent.browserSessionId !== undefined && lastEvent.browserSessionId !== scope.browserSessionId)
|
|
456
|
-
) {
|
|
457
|
-
authorityFail("PUBLIC_EVENT_LEDGER_CORRUPT", "Public event ledger last event substituted scope.");
|
|
458
|
-
}
|
|
459
|
-
assertPublicEventEnvelopeHash(lastEvent, "Public event ledger last event");
|
|
460
|
-
return Object.freeze({ head, lastEvent });
|
|
461
|
-
}
|
|
462
|
-
|
|
463
386
|
async function appendProjectedEvent(projectedInput, scopeInput) {
|
|
464
387
|
const scope = assertScope(scopeInput);
|
|
465
388
|
const projected = projectedInput;
|
|
466
389
|
if (!projected) return null;
|
|
467
|
-
const projectedIsTerminal = TERMINAL_TYPES.has(projected.type);
|
|
468
|
-
if ((projected.terminal === true) !== projectedIsTerminal) {
|
|
469
|
-
authorityFail("UNSUPPORTED_CORE_EVENT", "Projected event terminal flag does not match its public type.", { status: 400 });
|
|
470
|
-
}
|
|
471
|
-
const stateKey = toolStateKey(scope);
|
|
472
390
|
const ledger =
|
|
473
391
|
typeof eventLedgerStore.ledgerForRun === "function"
|
|
474
392
|
? eventLedgerStore.ledgerForRun(scope)
|
|
475
393
|
: null;
|
|
476
394
|
assertLedgerScope(ledger || {}, scope);
|
|
477
|
-
const
|
|
478
|
-
|
|
479
|
-
|
|
395
|
+
const head =
|
|
396
|
+
ledger && typeof ledger.loadHead === "function"
|
|
397
|
+
? await ledger.loadHead()
|
|
398
|
+
: { seq: 0, hash: "0".repeat(64) };
|
|
399
|
+
const previousSeq = Number(head?.seq || 0);
|
|
400
|
+
const previousHash = String(head?.hash || "0".repeat(64));
|
|
401
|
+
if (
|
|
402
|
+
!Number.isSafeInteger(previousSeq) ||
|
|
403
|
+
previousSeq < 0 ||
|
|
404
|
+
!/^[a-f0-9]{64}$/u.test(previousHash) ||
|
|
405
|
+
((previousSeq === 0) !== (previousHash === "0".repeat(64)))
|
|
406
|
+
) {
|
|
407
|
+
authorityFail("PUBLIC_EVENT_LEDGER_CORRUPT", "Public event ledger head cursor is invalid.");
|
|
480
408
|
}
|
|
481
|
-
const previousSeq = head.seq;
|
|
482
|
-
const previousHash = head.hash;
|
|
483
409
|
if (
|
|
484
410
|
projected.expectedPreviousSeq !== undefined &&
|
|
485
411
|
(projected.expectedPreviousSeq !== previousSeq || projected.expectedPreviousHash !== previousHash)
|
|
@@ -492,23 +418,11 @@ export function createIntegrationCoreEventProjector(options = {}) {
|
|
|
492
418
|
createdAt: projected.createdAt,
|
|
493
419
|
});
|
|
494
420
|
assertExactPublicEventView(event, "Public event ledger append");
|
|
495
|
-
const checked = createPublicIntegrationEvent({
|
|
496
|
-
threadId: event.threadId,
|
|
497
|
-
runId: event.runId,
|
|
498
|
-
seq: event.seq,
|
|
499
|
-
type: event.type,
|
|
500
|
-
payload: event.payload,
|
|
501
|
-
createdAt: event.createdAt,
|
|
502
|
-
previousHash: event.previousHash,
|
|
503
|
-
});
|
|
504
421
|
if (
|
|
505
422
|
event.threadId !== scope.threadId ||
|
|
506
423
|
event.runId !== scope.runId ||
|
|
507
|
-
event.schemaVersion !== checked.schemaVersion ||
|
|
508
|
-
event.id !== checked.id ||
|
|
509
424
|
event.seq !== previousSeq + 1 ||
|
|
510
425
|
event.previousHash !== previousHash ||
|
|
511
|
-
event.hash !== checked.hash ||
|
|
512
426
|
event.type !== projected.type ||
|
|
513
427
|
event.createdAt !== projected.createdAt ||
|
|
514
428
|
contractDigest(event.payload) !== contractDigest(projected.payload)
|
|
@@ -521,7 +435,16 @@ export function createIntegrationCoreEventProjector(options = {}) {
|
|
|
521
435
|
) {
|
|
522
436
|
authorityFail("PUBLIC_EVENT_LEDGER_CORRUPT", "Public event ledger append substituted the requested scope.");
|
|
523
437
|
}
|
|
524
|
-
|
|
438
|
+
const checked = createPublicIntegrationEvent({
|
|
439
|
+
threadId: event.threadId,
|
|
440
|
+
runId: event.runId,
|
|
441
|
+
seq: event.seq,
|
|
442
|
+
type: event.type,
|
|
443
|
+
payload: event.payload,
|
|
444
|
+
createdAt: event.createdAt,
|
|
445
|
+
previousHash: event.previousHash,
|
|
446
|
+
});
|
|
447
|
+
if (checked.hash !== event.hash) {
|
|
525
448
|
authorityFail("PUBLIC_EVENT_LEDGER_CORRUPT", "Appended public event hash is invalid.");
|
|
526
449
|
}
|
|
527
450
|
if (ledger && typeof ledger.loadHead === "function") {
|
|
@@ -530,39 +453,36 @@ export function createIntegrationCoreEventProjector(options = {}) {
|
|
|
530
453
|
authorityFail("PUBLIC_EVENT_LEDGER_CORRUPT", "Public event ledger head did not advance to the appended event.");
|
|
531
454
|
}
|
|
532
455
|
}
|
|
533
|
-
if (projected.terminal)
|
|
534
|
-
toolStateByRun.delete(stateKey);
|
|
535
|
-
}
|
|
456
|
+
if (projected.terminal) toolStateByRun.delete(scope.runId);
|
|
536
457
|
return Object.freeze({ ...checked, terminal: projected.terminal });
|
|
537
458
|
}
|
|
538
459
|
|
|
539
460
|
async function appendCoreEvent(type, data, scopeInput) {
|
|
540
461
|
const scope = assertScope(scopeInput);
|
|
541
462
|
const rawType = String(type || "");
|
|
542
|
-
const stateKey = toolStateKey(scope);
|
|
543
463
|
const needsToolState = TOOL_EVENT_TYPES.has(rawType);
|
|
544
|
-
const hadState = toolStateByRun.has(
|
|
545
|
-
let toolState = needsToolState ? toolStateByRun.get(
|
|
464
|
+
const hadState = toolStateByRun.has(scope.runId);
|
|
465
|
+
let toolState = needsToolState ? toolStateByRun.get(scope.runId) : undefined;
|
|
546
466
|
if (needsToolState && !toolState) {
|
|
547
467
|
toolState = { nextOrdinal: 0, activeByTool: new Map() };
|
|
548
|
-
toolStateByRun.set(
|
|
468
|
+
toolStateByRun.set(scope.runId, toolState);
|
|
549
469
|
}
|
|
550
470
|
const snapshot = needsToolState ? snapshotToolState(toolState) : null;
|
|
551
471
|
let projected = null;
|
|
552
472
|
try {
|
|
553
473
|
projected = projectCoreEvent(type, data, { now, runId: scope.runId, ...(needsToolState ? { toolState } : {}) });
|
|
554
474
|
} catch (error) {
|
|
555
|
-
if (needsToolState) restoreToolState(
|
|
475
|
+
if (needsToolState) restoreToolState(scope.runId, hadState, snapshot);
|
|
556
476
|
throw error;
|
|
557
477
|
}
|
|
558
478
|
if (!projected) {
|
|
559
|
-
if (needsToolState) restoreToolState(
|
|
479
|
+
if (needsToolState) restoreToolState(scope.runId, hadState, snapshot);
|
|
560
480
|
return null;
|
|
561
481
|
}
|
|
562
482
|
try {
|
|
563
483
|
return await appendProjectedEvent(projected, scope);
|
|
564
484
|
} catch (error) {
|
|
565
|
-
if (needsToolState) restoreToolState(
|
|
485
|
+
if (needsToolState) restoreToolState(scope.runId, hadState, snapshot);
|
|
566
486
|
throw error;
|
|
567
487
|
}
|
|
568
488
|
}
|
|
@@ -576,12 +496,8 @@ export function createIntegrationCoreEventProjector(options = {}) {
|
|
|
576
496
|
owner: "aginti",
|
|
577
497
|
authority: "aginti",
|
|
578
498
|
appendCoreEvent,
|
|
499
|
+
appendProjectedEvent,
|
|
579
500
|
appendAuthorityTerminalEvent,
|
|
580
|
-
clearRun(scopeInput, options = {}) {
|
|
581
|
-
const scope = assertScope(scopeInput);
|
|
582
|
-
const stateKey = toolStateKey(scope);
|
|
583
|
-
toolStateByRun.delete(stateKey);
|
|
584
|
-
},
|
|
585
501
|
projectCoreEvent(type, data, scope = {}) {
|
|
586
502
|
return projectCoreEvent(type, data, { now, runId: scope.runId || "" });
|
|
587
503
|
},
|