@exaudeus/workrail 3.14.0 → 3.16.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.
- package/dist/application/services/validation-engine.js +4 -9
- package/dist/application/services/workflow-compiler.js +4 -6
- package/dist/application/services/workflow-service.d.ts +2 -0
- package/dist/application/services/workflow-service.js +3 -0
- package/dist/console/assets/index-BE5PAgPO.js +28 -0
- package/dist/console/assets/index-BZNM03t1.css +1 -0
- package/dist/console/index.html +2 -2
- package/dist/engine/engine-factory.js +2 -2
- package/dist/engine/types.d.ts +1 -1
- package/dist/env-flags.d.ts +1 -0
- package/dist/env-flags.js +4 -0
- package/dist/infrastructure/session/HttpServer.d.ts +3 -3
- package/dist/infrastructure/session/HttpServer.js +68 -74
- package/dist/infrastructure/storage/caching-workflow-storage.d.ts +2 -0
- package/dist/infrastructure/storage/caching-workflow-storage.js +15 -6
- package/dist/infrastructure/storage/file-workflow-storage.js +3 -4
- package/dist/infrastructure/storage/schema-validating-workflow-storage.js +9 -8
- package/dist/manifest.json +283 -219
- package/dist/mcp/assert-output.d.ts +37 -0
- package/dist/mcp/assert-output.js +52 -0
- package/dist/mcp/boundary-coercion.d.ts +1 -0
- package/dist/mcp/boundary-coercion.js +44 -0
- package/dist/mcp/dev-mode.d.ts +1 -0
- package/dist/mcp/dev-mode.js +4 -0
- package/dist/mcp/handler-factory.js +12 -9
- package/dist/mcp/handlers/session.js +8 -9
- package/dist/mcp/handlers/shared/request-workflow-reader.d.ts +5 -0
- package/dist/mcp/handlers/shared/request-workflow-reader.js +47 -2
- package/dist/mcp/handlers/v2-advance-core/assessment-consequences.d.ts +1 -1
- package/dist/mcp/handlers/v2-advance-core/assessment-consequences.js +4 -5
- package/dist/mcp/handlers/v2-advance-core/event-builders.d.ts +2 -0
- package/dist/mcp/handlers/v2-advance-core/event-builders.js +6 -6
- package/dist/mcp/handlers/v2-advance-core/index.d.ts +2 -0
- package/dist/mcp/handlers/v2-advance-core/index.js +5 -4
- package/dist/mcp/handlers/v2-advance-core/input-validation.d.ts +2 -0
- package/dist/mcp/handlers/v2-advance-core/input-validation.js +32 -9
- package/dist/mcp/handlers/v2-advance-core/outcome-blocked.d.ts +2 -0
- package/dist/mcp/handlers/v2-advance-core/outcome-blocked.js +2 -2
- package/dist/mcp/handlers/v2-advance-core/outcome-success.d.ts +2 -0
- package/dist/mcp/handlers/v2-advance-core/outcome-success.js +1 -1
- package/dist/mcp/handlers/v2-checkpoint.d.ts +1 -1
- package/dist/mcp/handlers/v2-checkpoint.js +5 -6
- package/dist/mcp/handlers/v2-execution/advance.d.ts +4 -2
- package/dist/mcp/handlers/v2-execution/advance.js +5 -7
- package/dist/mcp/handlers/v2-execution/continue-advance.js +56 -26
- package/dist/mcp/handlers/v2-execution/continue-rehydrate.d.ts +1 -1
- package/dist/mcp/handlers/v2-execution/continue-rehydrate.js +9 -9
- package/dist/mcp/handlers/v2-execution/replay.d.ts +6 -4
- package/dist/mcp/handlers/v2-execution/replay.js +47 -30
- package/dist/mcp/handlers/v2-execution/start.d.ts +3 -3
- package/dist/mcp/handlers/v2-execution/start.js +31 -12
- package/dist/mcp/handlers/v2-execution/workflow-object-cache.d.ts +5 -0
- package/dist/mcp/handlers/v2-execution/workflow-object-cache.js +19 -0
- package/dist/mcp/handlers/v2-execution-helpers.d.ts +1 -0
- package/dist/mcp/handlers/v2-execution-helpers.js +23 -7
- package/dist/mcp/handlers/v2-resume.d.ts +1 -1
- package/dist/mcp/handlers/v2-resume.js +3 -4
- package/dist/mcp/handlers/v2-state-conversion.js +5 -1
- package/dist/mcp/handlers/v2-workflow.d.ts +100 -0
- package/dist/mcp/handlers/v2-workflow.js +155 -31
- package/dist/mcp/handlers/workflow.d.ts +2 -5
- package/dist/mcp/handlers/workflow.js +15 -12
- package/dist/mcp/output-schemas.d.ts +123 -29
- package/dist/mcp/output-schemas.js +36 -18
- package/dist/mcp/server.js +70 -5
- package/dist/mcp/tool-call-timing.d.ts +24 -0
- package/dist/mcp/tool-call-timing.js +85 -0
- package/dist/mcp/tool-descriptions.js +17 -9
- package/dist/mcp/transports/http-entry.js +3 -2
- package/dist/mcp/transports/http-listener.d.ts +1 -0
- package/dist/mcp/transports/http-listener.js +25 -0
- package/dist/mcp/transports/shutdown-hooks.d.ts +4 -1
- package/dist/mcp/transports/shutdown-hooks.js +3 -2
- package/dist/mcp/transports/stdio-entry.js +6 -28
- package/dist/mcp/v2/tools.d.ts +6 -0
- package/dist/mcp/v2/tools.js +2 -0
- package/dist/mcp/v2-response-formatter.js +2 -4
- package/dist/mcp/validation/schema-introspection.d.ts +1 -0
- package/dist/mcp/validation/schema-introspection.js +15 -5
- package/dist/mcp/validation/suggestion-generator.js +2 -2
- package/dist/mcp/workflow-protocol-contracts.js +5 -1
- package/dist/runtime/adapters/node-process-signals.d.ts +1 -0
- package/dist/runtime/adapters/node-process-signals.js +5 -0
- package/dist/runtime/adapters/noop-process-signals.d.ts +1 -0
- package/dist/runtime/adapters/noop-process-signals.js +2 -0
- package/dist/runtime/ports/process-signals.d.ts +1 -0
- package/dist/types/workflow-definition.d.ts +3 -2
- package/dist/types/workflow.d.ts +3 -0
- package/dist/types/workflow.js +35 -26
- package/dist/v2/durable-core/domain/context-template-resolver.js +2 -2
- package/dist/v2/durable-core/domain/function-definition-expander.js +2 -17
- package/dist/v2/durable-core/domain/prompt-renderer.d.ts +1 -0
- package/dist/v2/durable-core/domain/prompt-renderer.js +23 -18
- package/dist/v2/durable-core/domain/recap-recovery.js +23 -16
- package/dist/v2/durable-core/domain/retrieval-contract.js +13 -7
- package/dist/v2/durable-core/session-index.d.ts +22 -0
- package/dist/v2/durable-core/session-index.js +58 -0
- package/dist/v2/durable-core/sorted-event-log.d.ts +6 -0
- package/dist/v2/durable-core/sorted-event-log.js +15 -0
- package/dist/v2/infra/local/fs/index.js +8 -8
- package/dist/v2/infra/local/session-store/index.d.ts +1 -1
- package/dist/v2/infra/local/session-store/index.js +71 -61
- package/dist/v2/infra/local/session-summary-provider/index.js +9 -4
- package/dist/v2/infra/local/snapshot-store/index.js +2 -1
- package/dist/v2/infra/local/workspace-anchor/index.js +4 -1
- package/dist/v2/ports/session-event-log-store.port.d.ts +1 -1
- package/dist/v2/projections/assessment-consequences.d.ts +2 -1
- package/dist/v2/projections/assessment-consequences.js +0 -5
- package/dist/v2/projections/assessments.d.ts +2 -1
- package/dist/v2/projections/assessments.js +2 -4
- package/dist/v2/projections/gaps.d.ts +2 -1
- package/dist/v2/projections/gaps.js +0 -5
- package/dist/v2/projections/preferences.d.ts +2 -1
- package/dist/v2/projections/preferences.js +0 -5
- package/dist/v2/projections/run-context.d.ts +2 -2
- package/dist/v2/projections/run-context.js +0 -5
- package/dist/v2/projections/run-dag.js +7 -1
- package/dist/v2/projections/run-execution-trace.d.ts +8 -0
- package/dist/v2/projections/run-execution-trace.js +124 -0
- package/dist/v2/projections/run-status-signals.d.ts +2 -2
- package/dist/v2/usecases/console-routes.d.ts +3 -1
- package/dist/v2/usecases/console-routes.js +149 -3
- package/dist/v2/usecases/console-service.d.ts +2 -0
- package/dist/v2/usecases/console-service.js +87 -26
- package/dist/v2/usecases/console-types.d.ts +65 -0
- package/dist/v2/usecases/worktree-service.js +87 -8
- package/package.json +7 -6
- package/spec/authoring-spec.json +82 -1
- package/spec/workflow-tags.json +132 -0
- package/spec/workflow.schema.json +21 -11
- package/workflows/adaptive-ticket-creation.json +33 -8
- package/workflows/architecture-scalability-audit.json +50 -9
- package/workflows/bug-investigation.agentic.v2.json +43 -14
- package/workflows/coding-task-workflow-agentic.json +57 -38
- package/workflows/coding-task-workflow-agentic.lean.v2.json +129 -34
- package/workflows/coding-task-workflow-agentic.v2.json +97 -30
- package/workflows/cross-platform-code-conversion.v2.json +175 -48
- package/workflows/document-creation-workflow.json +49 -12
- package/workflows/documentation-update-workflow.json +9 -2
- package/workflows/intelligent-test-case-generation.json +9 -2
- package/workflows/learner-centered-course-workflow.json +273 -266
- package/workflows/mr-review-workflow.agentic.v2.json +88 -14
- package/workflows/personal-learning-materials-creation-branched.json +181 -174
- package/workflows/presentation-creation.json +167 -160
- package/workflows/production-readiness-audit.json +61 -15
- package/workflows/relocation-workflow-us.json +21 -5
- package/workflows/routines/tension-driven-design.json +1 -1
- package/workflows/scoped-documentation-workflow.json +9 -2
- package/workflows/test-artifact-loop-control.json +1 -2
- package/workflows/ui-ux-design-workflow.json +334 -0
- package/workflows/workflow-diagnose-environment.json +7 -1
- package/workflows/workflow-for-workflows.json +514 -484
- package/workflows/workflow-for-workflows.v2.json +55 -11
- package/workflows/wr.discovery.json +118 -29
- package/dist/console/assets/index-DW78t31j.css +0 -1
- package/dist/console/assets/index-EsSXrC_a.js +0 -28
|
@@ -39,20 +39,22 @@ const jsonl_js_1 = require("../../../durable-core/canonical/jsonl.js");
|
|
|
39
39
|
const index_js_1 = require("../../../durable-core/schemas/session/index.js");
|
|
40
40
|
const constants_js_1 = require("../../../durable-core/constants.js");
|
|
41
41
|
const path = __importStar(require("path"));
|
|
42
|
+
const _utf8Decoder = new TextDecoder();
|
|
43
|
+
const _createdEventsDirs = new Set();
|
|
42
44
|
class LocalSessionEventLogStoreV2 {
|
|
43
45
|
constructor(dataDir, fs, sha256) {
|
|
44
46
|
this.dataDir = dataDir;
|
|
45
47
|
this.fs = fs;
|
|
46
48
|
this.sha256 = sha256;
|
|
47
49
|
}
|
|
48
|
-
append(lock, plan) {
|
|
50
|
+
append(lock, plan, preloadedTruth) {
|
|
49
51
|
if (!lock.assertHeld()) {
|
|
50
52
|
return (0, neverthrow_1.errAsync)({
|
|
51
53
|
code: 'SESSION_STORE_INVARIANT_VIOLATION',
|
|
52
54
|
message: 'WithHealthySessionLock used after gate callback ended (witness misuse-after-release)',
|
|
53
55
|
});
|
|
54
56
|
}
|
|
55
|
-
return this.appendImpl(lock.sessionId, plan);
|
|
57
|
+
return this.appendImpl(lock.sessionId, plan, preloadedTruth);
|
|
56
58
|
}
|
|
57
59
|
load(sessionId) {
|
|
58
60
|
return this.loadImpl(sessionId);
|
|
@@ -60,13 +62,20 @@ class LocalSessionEventLogStoreV2 {
|
|
|
60
62
|
loadValidatedPrefix(sessionId) {
|
|
61
63
|
return this.loadValidatedPrefixImpl(sessionId);
|
|
62
64
|
}
|
|
63
|
-
appendImpl(sessionId, plan) {
|
|
65
|
+
appendImpl(sessionId, plan, preloadedTruth) {
|
|
64
66
|
const sessionDir = this.dataDir.sessionDir(sessionId);
|
|
65
67
|
const eventsDir = this.dataDir.sessionEventsDir(sessionId);
|
|
66
68
|
const manifestPath = this.dataDir.sessionManifestPath(sessionId);
|
|
67
|
-
|
|
68
|
-
.
|
|
69
|
-
.
|
|
69
|
+
const mkdirpResult = _createdEventsDirs.has(eventsDir)
|
|
70
|
+
? (0, neverthrow_1.okAsync)(undefined)
|
|
71
|
+
: this.fs.mkdirp(eventsDir).mapErr(mapFsToStoreError).map(() => { _createdEventsDirs.add(eventsDir); });
|
|
72
|
+
const truthSource = preloadedTruth !== undefined
|
|
73
|
+
? mkdirpResult.andThen(() => (0, neverthrow_1.okAsync)({
|
|
74
|
+
manifest: preloadedTruth.manifest,
|
|
75
|
+
events: preloadedTruth.events,
|
|
76
|
+
}))
|
|
77
|
+
: mkdirpResult.andThen(() => this.loadTruthOrEmpty(sessionId));
|
|
78
|
+
return truthSource
|
|
70
79
|
.andThen(({ manifest, events: existingEvents }) => {
|
|
71
80
|
const contiguityRes = validateManifestContiguity(manifest);
|
|
72
81
|
if (contiguityRes.isErr())
|
|
@@ -116,24 +125,23 @@ class LocalSessionEventLogStoreV2 {
|
|
|
116
125
|
sha256: digest,
|
|
117
126
|
bytes: segmentBytes.length,
|
|
118
127
|
};
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
snapshotRef: p.snapshotRef,
|
|
132
|
-
createdByEventId: p.createdByEventId,
|
|
133
|
-
}));
|
|
134
|
-
return this.appendManifestRecords(manifestPath, records);
|
|
135
|
-
});
|
|
128
|
+
const pins = sortedPins(plan.snapshotPins);
|
|
129
|
+
const startIndex = segClosed.manifestIndex + 1;
|
|
130
|
+
const pinRecords = pins.map((p, i) => ({
|
|
131
|
+
v: 1,
|
|
132
|
+
manifestIndex: startIndex + i,
|
|
133
|
+
sessionId,
|
|
134
|
+
kind: constants_js_1.MANIFEST_KIND.SNAPSHOT_PINNED,
|
|
135
|
+
eventIndex: p.eventIndex,
|
|
136
|
+
snapshotRef: p.snapshotRef,
|
|
137
|
+
createdByEventId: p.createdByEventId,
|
|
138
|
+
}));
|
|
139
|
+
return this.appendManifestRecords(manifestPath, [segClosed, ...pinRecords]);
|
|
136
140
|
});
|
|
141
|
+
})
|
|
142
|
+
.orElse((error) => {
|
|
143
|
+
_createdEventsDirs.delete(eventsDir);
|
|
144
|
+
return (0, neverthrow_1.errAsync)(error);
|
|
137
145
|
});
|
|
138
146
|
}
|
|
139
147
|
loadImpl(sessionId) {
|
|
@@ -147,7 +155,7 @@ class LocalSessionEventLogStoreV2 {
|
|
|
147
155
|
if (segRes.isErr())
|
|
148
156
|
return (0, neverthrow_1.errAsync)(segRes.error);
|
|
149
157
|
const segments = manifest.filter((m) => m.kind === constants_js_1.MANIFEST_KIND.SEGMENT_CLOSED);
|
|
150
|
-
return
|
|
158
|
+
return loadSegmentsParallel({
|
|
151
159
|
segments,
|
|
152
160
|
sessionDir,
|
|
153
161
|
sha256: this.sha256,
|
|
@@ -334,17 +342,14 @@ function validateAppendPlan(sessionId, plan, expectedFirstEventIndex) {
|
|
|
334
342
|
});
|
|
335
343
|
}
|
|
336
344
|
for (let i = 0; i < plan.events.length; i++) {
|
|
337
|
-
const e =
|
|
338
|
-
if (
|
|
339
|
-
return (0, neverthrow_1.err)({ code: 'SESSION_STORE_INVARIANT_VIOLATION', message: `Invalid domain event at index ${i}` });
|
|
340
|
-
}
|
|
341
|
-
if (e.data.sessionId !== sessionId) {
|
|
345
|
+
const e = plan.events[i];
|
|
346
|
+
if (e.sessionId !== sessionId) {
|
|
342
347
|
return (0, neverthrow_1.err)({
|
|
343
348
|
code: 'SESSION_STORE_INVARIANT_VIOLATION',
|
|
344
349
|
message: `Domain event sessionId mismatch at index ${i}`,
|
|
345
350
|
});
|
|
346
351
|
}
|
|
347
|
-
if (i > 0 &&
|
|
352
|
+
if (i > 0 && e.eventIndex !== plan.events[i - 1].eventIndex + 1) {
|
|
348
353
|
return (0, neverthrow_1.err)({
|
|
349
354
|
code: 'SESSION_STORE_INVARIANT_VIOLATION',
|
|
350
355
|
message: `Non-contiguous eventIndex in AppendPlan at index ${i}`,
|
|
@@ -439,7 +444,7 @@ function parseJsonlText(text, schema) {
|
|
|
439
444
|
return (0, neverthrow_1.ok)(out);
|
|
440
445
|
}
|
|
441
446
|
function parseJsonlLines(bytes, schema) {
|
|
442
|
-
const text =
|
|
447
|
+
const text = _utf8Decoder.decode(bytes);
|
|
443
448
|
return parseJsonlText(text, schema);
|
|
444
449
|
}
|
|
445
450
|
function extractSnapshotPinsFromEvents(events) {
|
|
@@ -573,41 +578,46 @@ function processSegmentForSalvage(args) {
|
|
|
573
578
|
});
|
|
574
579
|
});
|
|
575
580
|
}
|
|
576
|
-
function
|
|
581
|
+
function loadSegmentsParallel(args) {
|
|
577
582
|
if (args.segments.length === 0)
|
|
578
583
|
return (0, neverthrow_1.okAsync)([]);
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
return args.fs.readFileBytes(segmentPath)
|
|
582
|
-
.mapErr((e) => {
|
|
584
|
+
return neverthrow_1.ResultAsync.fromPromise(Promise.all(args.segments.map((seg) => args.fs.readFileBytes(path.join(args.sessionDir, seg.segmentRelPath))
|
|
585
|
+
.match((bytes) => ({ ok: true, bytes, seg }), (e) => {
|
|
583
586
|
if (e.code === 'FS_NOT_FOUND') {
|
|
584
587
|
return {
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
588
|
+
ok: false,
|
|
589
|
+
error: {
|
|
590
|
+
code: 'SESSION_STORE_CORRUPTION_DETECTED',
|
|
591
|
+
location: 'tail',
|
|
592
|
+
reason: { code: 'missing_attested_segment', message: `Missing attested segment: ${seg.segmentRelPath}` },
|
|
593
|
+
message: `Missing attested segment: ${seg.segmentRelPath}`,
|
|
594
|
+
},
|
|
589
595
|
};
|
|
590
596
|
}
|
|
591
|
-
return mapFsToStoreError(e);
|
|
592
|
-
})
|
|
593
|
-
|
|
594
|
-
const
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
597
|
+
return { ok: false, error: mapFsToStoreError(e) };
|
|
598
|
+
}))), (e) => ({ code: 'SESSION_STORE_IO_ERROR', message: String(e) })).andThen((readResults) => {
|
|
599
|
+
const allEvents = [];
|
|
600
|
+
for (const result of readResults) {
|
|
601
|
+
if (!result.ok)
|
|
602
|
+
return (0, neverthrow_1.err)(result.error);
|
|
603
|
+
const { bytes, seg } = result;
|
|
604
|
+
const actual = args.sha256.sha256(bytes);
|
|
605
|
+
if (actual !== seg.sha256) {
|
|
606
|
+
return (0, neverthrow_1.err)({
|
|
607
|
+
code: 'SESSION_STORE_CORRUPTION_DETECTED',
|
|
608
|
+
location: 'tail',
|
|
609
|
+
reason: { code: 'digest_mismatch', message: `Segment digest mismatch: ${seg.segmentRelPath}` },
|
|
610
|
+
message: `Segment digest mismatch: ${seg.segmentRelPath}`,
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
const parsedRes = parseJsonlLines(bytes, index_js_1.DomainEventV1Schema);
|
|
614
|
+
if (parsedRes.isErr())
|
|
615
|
+
return (0, neverthrow_1.err)(parsedRes.error);
|
|
616
|
+
const boundsResult = validateSegmentBounds(parsedRes.value, seg);
|
|
617
|
+
if (boundsResult.isErr())
|
|
618
|
+
return (0, neverthrow_1.err)(boundsResult.error);
|
|
619
|
+
allEvents.push(...parsedRes.value);
|
|
602
620
|
}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
return (0, neverthrow_1.errAsync)(parsedRes.error);
|
|
606
|
-
const parsed = parsedRes.value;
|
|
607
|
-
const boundsResult = validateSegmentBounds(parsed, head);
|
|
608
|
-
if (boundsResult.isErr())
|
|
609
|
-
return (0, neverthrow_1.errAsync)(boundsResult.error);
|
|
610
|
-
return (0, neverthrow_1.okAsync)(parsed);
|
|
611
|
-
})
|
|
612
|
-
.andThen((events) => loadSegmentsRecursive({ ...args, segments: tail }).map((rest) => [...events, ...rest]));
|
|
621
|
+
return (0, neverthrow_1.ok)(allEvents);
|
|
622
|
+
});
|
|
613
623
|
}
|
|
@@ -8,6 +8,7 @@ const session_health_js_1 = require("../../../projections/session-health.js");
|
|
|
8
8
|
const run_dag_js_1 = require("../../../projections/run-dag.js");
|
|
9
9
|
const node_outputs_js_1 = require("../../../projections/node-outputs.js");
|
|
10
10
|
const run_context_js_1 = require("../../../projections/run-context.js");
|
|
11
|
+
const sorted_event_log_js_1 = require("../../../durable-core/sorted-event-log.js");
|
|
11
12
|
const snapshot_state_js_1 = require("../../../durable-core/projections/snapshot-state.js");
|
|
12
13
|
const index_js_1 = require("../../../durable-core/ids/index.js");
|
|
13
14
|
const constants_js_1 = require("../../../durable-core/constants.js");
|
|
@@ -87,6 +88,10 @@ function projectSessionSummary(sessionId, truth, mtimeMs) {
|
|
|
87
88
|
const workflow = extractWorkflowIdentity(truth.events, bestRun.run.runId);
|
|
88
89
|
if (!workflow)
|
|
89
90
|
return null;
|
|
91
|
+
const sortedEventsRes = (0, sorted_event_log_js_1.asSortedEventLog)(truth.events);
|
|
92
|
+
const sessionTitle = sortedEventsRes.isOk()
|
|
93
|
+
? deriveSessionTitle(sortedEventsRes.value, bestRun.run.runId)
|
|
94
|
+
: null;
|
|
90
95
|
const outputsRes = (0, node_outputs_js_1.projectNodeOutputsV2)(truth.events);
|
|
91
96
|
const recapSnippet = outputsRes.isOk()
|
|
92
97
|
? extractAggregateRecap(outputsRes.value, bestRun.run, bestRun.tipNodeId)
|
|
@@ -102,7 +107,7 @@ function projectSessionSummary(sessionId, truth, mtimeMs) {
|
|
|
102
107
|
recapSnippet,
|
|
103
108
|
observations: extractObservations(truth.events),
|
|
104
109
|
workflow,
|
|
105
|
-
sessionTitle
|
|
110
|
+
sessionTitle,
|
|
106
111
|
lastModifiedMs: mtimeMs,
|
|
107
112
|
pendingStepId: null,
|
|
108
113
|
isComplete: false,
|
|
@@ -150,8 +155,8 @@ function extractWorkflowIdentity(events, runId) {
|
|
|
150
155
|
workflowHash: (0, index_js_1.asWorkflowHash)((0, index_js_1.asSha256Digest)(event.data.workflowHash)),
|
|
151
156
|
};
|
|
152
157
|
}
|
|
153
|
-
function deriveSessionTitle(
|
|
154
|
-
const contextRes = (0, run_context_js_1.projectRunContextV2)(
|
|
158
|
+
function deriveSessionTitle(sortedEvents, runId) {
|
|
159
|
+
const contextRes = (0, run_context_js_1.projectRunContextV2)(sortedEvents);
|
|
155
160
|
if (contextRes.isOk()) {
|
|
156
161
|
const runCtx = contextRes.value.byRunId[runId];
|
|
157
162
|
if (runCtx) {
|
|
@@ -163,7 +168,7 @@ function deriveSessionTitle(events, runId) {
|
|
|
163
168
|
}
|
|
164
169
|
}
|
|
165
170
|
}
|
|
166
|
-
return extractTitleFromFirstRecap(
|
|
171
|
+
return extractTitleFromFirstRecap(sortedEvents);
|
|
167
172
|
}
|
|
168
173
|
function extractTitleFromFirstRecap(events) {
|
|
169
174
|
const outputsRes = (0, node_outputs_js_1.projectNodeOutputsV2)(events);
|
|
@@ -5,6 +5,7 @@ const neverthrow_1 = require("neverthrow");
|
|
|
5
5
|
const index_js_1 = require("../../../durable-core/ids/index.js");
|
|
6
6
|
const index_js_2 = require("../../../durable-core/schemas/execution-snapshot/index.js");
|
|
7
7
|
const jcs_js_1 = require("../../../durable-core/canonical/jcs.js");
|
|
8
|
+
const _utf8Decoder = new TextDecoder();
|
|
8
9
|
class LocalSnapshotStoreV2 {
|
|
9
10
|
constructor(dataDir, fs, crypto) {
|
|
10
11
|
this.dataDir = dataDir;
|
|
@@ -41,7 +42,7 @@ class LocalSnapshotStoreV2 {
|
|
|
41
42
|
.andThen((bytes) => {
|
|
42
43
|
let parsed;
|
|
43
44
|
try {
|
|
44
|
-
parsed = JSON.parse(
|
|
45
|
+
parsed = JSON.parse(_utf8Decoder.decode(bytes));
|
|
45
46
|
}
|
|
46
47
|
catch {
|
|
47
48
|
return (0, neverthrow_1.errAsync)({
|
|
@@ -33,7 +33,10 @@ class LocalWorkspaceAnchorV2 {
|
|
|
33
33
|
}
|
|
34
34
|
async runGitCommands(cwd) {
|
|
35
35
|
const anchors = [];
|
|
36
|
-
const
|
|
36
|
+
const gitCommonDir = await this.gitCommand('git rev-parse --path-format=absolute --git-common-dir', cwd);
|
|
37
|
+
if (!gitCommonDir)
|
|
38
|
+
return anchors;
|
|
39
|
+
const repoRoot = gitCommonDir.replace(/\/\.git\/?$/, '').trim() || null;
|
|
37
40
|
if (!repoRoot)
|
|
38
41
|
return anchors;
|
|
39
42
|
const repoRootHash = hashRepoRoot(repoRoot);
|
|
@@ -48,5 +48,5 @@ export interface SessionEventLogReadonlyStorePortV2 {
|
|
|
48
48
|
loadValidatedPrefix(sessionId: SessionId): ResultAsync<LoadedValidatedPrefixV2, SessionEventLogStoreError>;
|
|
49
49
|
}
|
|
50
50
|
export interface SessionEventLogAppendStorePortV2 {
|
|
51
|
-
append(lock: WithHealthySessionLock, plan: AppendPlanV2): ResultAsync<void, SessionEventLogStoreError>;
|
|
51
|
+
append(lock: WithHealthySessionLock, plan: AppendPlanV2, preloadedTruth?: LoadedSessionTruthV2): ResultAsync<void, SessionEventLogStoreError>;
|
|
52
52
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Result } from 'neverthrow';
|
|
2
2
|
import type { DomainEventV1 } from '../durable-core/schemas/session/index.js';
|
|
3
|
+
import type { SortedEventLog } from '../durable-core/sorted-event-log.js';
|
|
3
4
|
import type { ProjectionError } from './projection-error.js';
|
|
4
5
|
type AssessmentConsequenceAppliedEventV1 = Extract<DomainEventV1, {
|
|
5
6
|
kind: 'assessment_consequence_applied';
|
|
@@ -14,6 +15,6 @@ export interface AppliedAssessmentConsequenceViewV2 {
|
|
|
14
15
|
export interface AssessmentConsequencesProjectionV2 {
|
|
15
16
|
readonly byNodeId: Readonly<Record<string, readonly AppliedAssessmentConsequenceViewV2[]>>;
|
|
16
17
|
}
|
|
17
|
-
export declare function projectAssessmentConsequencesV2(events:
|
|
18
|
+
export declare function projectAssessmentConsequencesV2(events: SortedEventLog): Result<AssessmentConsequencesProjectionV2, ProjectionError>;
|
|
18
19
|
export declare function getLatestAssessmentConsequenceForNode(projection: AssessmentConsequencesProjectionV2, nodeId: string): AppliedAssessmentConsequenceViewV2 | undefined;
|
|
19
20
|
export {};
|
|
@@ -5,11 +5,6 @@ exports.getLatestAssessmentConsequenceForNode = getLatestAssessmentConsequenceFo
|
|
|
5
5
|
const neverthrow_1 = require("neverthrow");
|
|
6
6
|
const constants_js_1 = require("../durable-core/constants.js");
|
|
7
7
|
function projectAssessmentConsequencesV2(events) {
|
|
8
|
-
for (let i = 1; i < events.length; i++) {
|
|
9
|
-
if (events[i].eventIndex < events[i - 1].eventIndex) {
|
|
10
|
-
return (0, neverthrow_1.err)({ code: 'PROJECTION_INVARIANT_VIOLATION', message: 'Events must be sorted by eventIndex ascending' });
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
8
|
const byNodeId = {};
|
|
14
9
|
for (const event of events) {
|
|
15
10
|
if (event.kind !== constants_js_1.EVENT_KIND.ASSESSMENT_CONSEQUENCE_APPLIED)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Result } from 'neverthrow';
|
|
2
2
|
import type { DomainEventV1 } from '../durable-core/schemas/session/index.js';
|
|
3
|
+
import type { SortedEventLog } from '../durable-core/sorted-event-log.js';
|
|
3
4
|
import type { ProjectionError } from './projection-error.js';
|
|
4
5
|
type AssessmentRecordedEventV1 = Extract<DomainEventV1, {
|
|
5
6
|
kind: 'assessment_recorded';
|
|
@@ -16,6 +17,6 @@ export interface RecordedAssessmentViewV2 {
|
|
|
16
17
|
export interface AssessmentsProjectionV2 {
|
|
17
18
|
readonly byNodeId: Readonly<Record<string, readonly RecordedAssessmentViewV2[]>>;
|
|
18
19
|
}
|
|
19
|
-
export declare function projectAssessmentsV2(events:
|
|
20
|
+
export declare function projectAssessmentsV2(events: SortedEventLog): Result<AssessmentsProjectionV2, ProjectionError>;
|
|
20
21
|
export declare function getLatestAssessmentForNode(projection: AssessmentsProjectionV2, nodeId: string): RecordedAssessmentViewV2 | undefined;
|
|
21
22
|
export {};
|
|
@@ -5,10 +5,8 @@ exports.getLatestAssessmentForNode = getLatestAssessmentForNode;
|
|
|
5
5
|
const neverthrow_1 = require("neverthrow");
|
|
6
6
|
const constants_js_1 = require("../durable-core/constants.js");
|
|
7
7
|
function projectAssessmentsV2(events) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
return (0, neverthrow_1.err)({ code: 'PROJECTION_INVARIANT_VIOLATION', message: 'Events must be sorted by eventIndex ascending' });
|
|
11
|
-
}
|
|
8
|
+
if (!events.some((e) => e.kind === constants_js_1.EVENT_KIND.ASSESSMENT_RECORDED)) {
|
|
9
|
+
return (0, neverthrow_1.ok)({ byNodeId: {} });
|
|
12
10
|
}
|
|
13
11
|
const byNodeId = {};
|
|
14
12
|
for (const event of events) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Result } from 'neverthrow';
|
|
2
2
|
import type { DomainEventV1 } from '../durable-core/schemas/session/index.js';
|
|
3
|
+
import type { SortedEventLog } from '../durable-core/sorted-event-log.js';
|
|
3
4
|
import type { ProjectionError } from './projection-error.js';
|
|
4
5
|
type GapRecordedEventV1 = Extract<DomainEventV1, {
|
|
5
6
|
kind: 'gap_recorded';
|
|
@@ -19,5 +20,5 @@ export interface GapsProjectionV2 {
|
|
|
19
20
|
readonly resolvedGapIds: ReadonlySet<string>;
|
|
20
21
|
readonly unresolvedCriticalByRunId: Readonly<Record<string, readonly GapV2[]>>;
|
|
21
22
|
}
|
|
22
|
-
export declare function projectGapsV2(events:
|
|
23
|
+
export declare function projectGapsV2(events: SortedEventLog): Result<GapsProjectionV2, ProjectionError>;
|
|
23
24
|
export {};
|
|
@@ -4,11 +4,6 @@ exports.projectGapsV2 = projectGapsV2;
|
|
|
4
4
|
const neverthrow_1 = require("neverthrow");
|
|
5
5
|
const constants_js_1 = require("../durable-core/constants.js");
|
|
6
6
|
function projectGapsV2(events) {
|
|
7
|
-
for (let i = 1; i < events.length; i++) {
|
|
8
|
-
if (events[i].eventIndex < events[i - 1].eventIndex) {
|
|
9
|
-
return (0, neverthrow_1.err)({ code: 'PROJECTION_INVARIANT_VIOLATION', message: 'Events must be sorted by eventIndex ascending' });
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
7
|
const byGapId = {};
|
|
13
8
|
const resolved = new Set();
|
|
14
9
|
for (const e of events) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Result } from 'neverthrow';
|
|
2
2
|
import type { DomainEventV1 } from '../durable-core/schemas/session/index.js';
|
|
3
|
+
import type { SortedEventLog } from '../durable-core/sorted-event-log.js';
|
|
3
4
|
import type { AutonomyV2, RiskPolicyV2 } from '../durable-core/schemas/session/preferences.js';
|
|
4
5
|
import type { ProjectionError } from './projection-error.js';
|
|
5
6
|
type PreferencesChangedEventV1 = Extract<DomainEventV1, {
|
|
@@ -17,5 +18,5 @@ export interface NodePreferencesV2 {
|
|
|
17
18
|
export interface PreferencesProjectionV2 {
|
|
18
19
|
readonly byNodeId: Readonly<Record<string, NodePreferencesV2>>;
|
|
19
20
|
}
|
|
20
|
-
export declare function projectPreferencesV2(events:
|
|
21
|
+
export declare function projectPreferencesV2(events: SortedEventLog, parentByNodeId: Readonly<Record<string, string | null>>): Result<PreferencesProjectionV2, ProjectionError>;
|
|
21
22
|
export {};
|
|
@@ -5,11 +5,6 @@ const neverthrow_1 = require("neverthrow");
|
|
|
5
5
|
const constants_js_1 = require("../durable-core/constants.js");
|
|
6
6
|
const defaultPrefs = { autonomy: 'guided', riskPolicy: 'conservative' };
|
|
7
7
|
function projectPreferencesV2(events, parentByNodeId) {
|
|
8
|
-
for (let i = 1; i < events.length; i++) {
|
|
9
|
-
if (events[i].eventIndex < events[i - 1].eventIndex) {
|
|
10
|
-
return (0, neverthrow_1.err)({ code: 'PROJECTION_INVARIANT_VIOLATION', message: 'Events must be sorted by eventIndex ascending' });
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
8
|
const changesByNodeId = {};
|
|
14
9
|
for (const e of events) {
|
|
15
10
|
if (e.kind !== constants_js_1.EVENT_KIND.PREFERENCES_CHANGED)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Result } from 'neverthrow';
|
|
2
|
-
import type {
|
|
2
|
+
import type { SortedEventLog } from '../durable-core/sorted-event-log.js';
|
|
3
3
|
import type { JsonObject } from '../durable-core/canonical/json-types.js';
|
|
4
4
|
import type { RunId } from '../durable-core/ids/index.js';
|
|
5
5
|
import type { ProjectionError } from './projection-error.js';
|
|
@@ -13,4 +13,4 @@ export interface RunContextV2 {
|
|
|
13
13
|
export interface RunContextProjectionV2 {
|
|
14
14
|
readonly byRunId: Readonly<Record<string, RunContextV2>>;
|
|
15
15
|
}
|
|
16
|
-
export declare function projectRunContextV2(events:
|
|
16
|
+
export declare function projectRunContextV2(events: SortedEventLog): Result<RunContextProjectionV2, ProjectionError>;
|
|
@@ -5,11 +5,6 @@ const neverthrow_1 = require("neverthrow");
|
|
|
5
5
|
const constants_js_1 = require("../durable-core/constants.js");
|
|
6
6
|
const index_js_1 = require("../durable-core/ids/index.js");
|
|
7
7
|
function projectRunContextV2(events) {
|
|
8
|
-
for (let i = 1; i < events.length; i++) {
|
|
9
|
-
if (events[i].eventIndex < events[i - 1].eventIndex) {
|
|
10
|
-
return (0, neverthrow_1.err)({ code: 'PROJECTION_INVARIANT_VIOLATION', message: 'Events must be sorted by eventIndex ascending' });
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
8
|
const byRunId = {};
|
|
14
9
|
for (const e of events) {
|
|
15
10
|
if (e.kind !== constants_js_1.EVENT_KIND.CONTEXT_SET)
|
|
@@ -151,7 +151,13 @@ function projectRunDagV2(events) {
|
|
|
151
151
|
createdAtEventIndex: e.eventIndex,
|
|
152
152
|
};
|
|
153
153
|
if (existing) {
|
|
154
|
-
|
|
154
|
+
const differs = existing.nodeId !== node.nodeId ||
|
|
155
|
+
existing.nodeKind !== node.nodeKind ||
|
|
156
|
+
existing.parentNodeId !== node.parentNodeId ||
|
|
157
|
+
existing.workflowHash !== node.workflowHash ||
|
|
158
|
+
existing.snapshotRef !== node.snapshotRef ||
|
|
159
|
+
existing.createdAtEventIndex !== node.createdAtEventIndex;
|
|
160
|
+
if (differs) {
|
|
155
161
|
return (0, neverthrow_1.err)({
|
|
156
162
|
code: 'PROJECTION_CORRUPTION_DETECTED',
|
|
157
163
|
message: `node_created conflict for runId=${runId} nodeId=${nodeId}`,
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Result } from 'neverthrow';
|
|
2
|
+
import type { DomainEventV1 } from '../durable-core/schemas/session/index.js';
|
|
3
|
+
import type { ProjectionError } from './projection-error.js';
|
|
4
|
+
import type { ConsoleExecutionTraceSummary } from '../usecases/console-types.js';
|
|
5
|
+
export interface RunExecutionTraceProjectionV2 {
|
|
6
|
+
readonly byRunId: Readonly<Record<string, ConsoleExecutionTraceSummary>>;
|
|
7
|
+
}
|
|
8
|
+
export declare function projectRunExecutionTraceV2(events: readonly DomainEventV1[]): Result<RunExecutionTraceProjectionV2, ProjectionError>;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.projectRunExecutionTraceV2 = projectRunExecutionTraceV2;
|
|
4
|
+
const neverthrow_1 = require("neverthrow");
|
|
5
|
+
const constants_js_1 = require("../durable-core/constants.js");
|
|
6
|
+
const CONTEXT_KEYS_TO_ELEVATE = ['taskComplexity'];
|
|
7
|
+
function projectRunExecutionTraceV2(events) {
|
|
8
|
+
for (let i = 1; i < events.length; i++) {
|
|
9
|
+
if (events[i].eventIndex < events[i - 1].eventIndex) {
|
|
10
|
+
return (0, neverthrow_1.err)({
|
|
11
|
+
code: 'PROJECTION_INVARIANT_VIOLATION',
|
|
12
|
+
message: 'Events must be sorted by eventIndex ascending',
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
const itemsByRunId = {};
|
|
17
|
+
const contextFactsByRunId = {};
|
|
18
|
+
const pushItem = (runId, item) => {
|
|
19
|
+
const existing = itemsByRunId[runId] ?? [];
|
|
20
|
+
existing.push(item);
|
|
21
|
+
itemsByRunId[runId] = existing;
|
|
22
|
+
};
|
|
23
|
+
for (const event of events) {
|
|
24
|
+
switch (event.kind) {
|
|
25
|
+
case constants_js_1.EVENT_KIND.DECISION_TRACE_APPENDED: {
|
|
26
|
+
const runId = event.scope.runId;
|
|
27
|
+
const nodeRef = { kind: 'node_id', value: event.scope.nodeId };
|
|
28
|
+
for (const entry of event.data.entries) {
|
|
29
|
+
pushItem(runId, {
|
|
30
|
+
kind: entry.kind,
|
|
31
|
+
summary: entry.summary,
|
|
32
|
+
recordedAtEventIndex: event.eventIndex,
|
|
33
|
+
refs: [nodeRef, ...mapDecisionTraceRefs(entry.refs)],
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
case constants_js_1.EVENT_KIND.DIVERGENCE_RECORDED: {
|
|
39
|
+
const runId = event.scope.runId;
|
|
40
|
+
const refs = [
|
|
41
|
+
{ kind: 'node_id', value: event.scope.nodeId },
|
|
42
|
+
];
|
|
43
|
+
if (event.data.relatedStepId) {
|
|
44
|
+
refs.push({ kind: 'step_id', value: event.data.relatedStepId });
|
|
45
|
+
}
|
|
46
|
+
pushItem(runId, {
|
|
47
|
+
kind: 'divergence',
|
|
48
|
+
summary: event.data.summary,
|
|
49
|
+
recordedAtEventIndex: event.eventIndex,
|
|
50
|
+
refs,
|
|
51
|
+
});
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
case constants_js_1.EVENT_KIND.CONTEXT_SET: {
|
|
55
|
+
const context = event.data.context;
|
|
56
|
+
if (!context || typeof context !== 'object' || Array.isArray(context)) {
|
|
57
|
+
return (0, neverthrow_1.err)({
|
|
58
|
+
code: 'PROJECTION_CORRUPTION_DETECTED',
|
|
59
|
+
message: `context_set event has invalid context type (runId=${event.scope.runId}, eventId=${event.eventId})`,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
const contextObj = context;
|
|
63
|
+
const facts = CONTEXT_KEYS_TO_ELEVATE.flatMap((key) => {
|
|
64
|
+
const value = contextObj[key];
|
|
65
|
+
if (value === undefined || value === null)
|
|
66
|
+
return [];
|
|
67
|
+
return [{ key, value: stringifyContextValue(value) }];
|
|
68
|
+
});
|
|
69
|
+
if (facts.length > 0) {
|
|
70
|
+
contextFactsByRunId[event.scope.runId] = facts;
|
|
71
|
+
}
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
default:
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
const runIds = new Set([
|
|
79
|
+
...Object.keys(itemsByRunId),
|
|
80
|
+
...Object.keys(contextFactsByRunId),
|
|
81
|
+
]);
|
|
82
|
+
const byRunId = {};
|
|
83
|
+
for (const runId of runIds) {
|
|
84
|
+
byRunId[runId] = {
|
|
85
|
+
items: itemsByRunId[runId] ?? [],
|
|
86
|
+
contextFacts: contextFactsByRunId[runId] ?? [],
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
return (0, neverthrow_1.ok)({ byRunId });
|
|
90
|
+
}
|
|
91
|
+
function mapDecisionTraceRefs(refs) {
|
|
92
|
+
if (!refs || refs.length === 0)
|
|
93
|
+
return [];
|
|
94
|
+
const mapped = [];
|
|
95
|
+
for (const ref of refs) {
|
|
96
|
+
switch (ref.kind) {
|
|
97
|
+
case 'step_id':
|
|
98
|
+
if (ref.stepId) {
|
|
99
|
+
mapped.push({ kind: 'step_id', value: ref.stepId });
|
|
100
|
+
}
|
|
101
|
+
break;
|
|
102
|
+
case 'loop_id':
|
|
103
|
+
if (ref.loopId) {
|
|
104
|
+
mapped.push({ kind: 'loop_id', value: ref.loopId });
|
|
105
|
+
}
|
|
106
|
+
break;
|
|
107
|
+
case 'condition_id':
|
|
108
|
+
if (ref.conditionId) {
|
|
109
|
+
mapped.push({ kind: 'condition_id', value: ref.conditionId });
|
|
110
|
+
}
|
|
111
|
+
break;
|
|
112
|
+
default:
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return mapped;
|
|
117
|
+
}
|
|
118
|
+
function stringifyContextValue(value) {
|
|
119
|
+
if (typeof value === 'string')
|
|
120
|
+
return value;
|
|
121
|
+
if (typeof value === 'number' || typeof value === 'boolean')
|
|
122
|
+
return String(value);
|
|
123
|
+
return JSON.stringify(value);
|
|
124
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Result } from 'neverthrow';
|
|
2
|
-
import type {
|
|
2
|
+
import type { SortedEventLog } from '../durable-core/sorted-event-log.js';
|
|
3
3
|
import type { AutonomyV2, RiskPolicyV2 } from '../durable-core/schemas/session/preferences.js';
|
|
4
4
|
import type { ProjectionError } from './projection-error.js';
|
|
5
5
|
export interface PreferencesSnapshotV2 {
|
|
@@ -16,4 +16,4 @@ export interface RunStatusSignalsV2 {
|
|
|
16
16
|
export interface RunStatusSignalsProjectionV2 {
|
|
17
17
|
readonly byRunId: Readonly<Record<string, RunStatusSignalsV2>>;
|
|
18
18
|
}
|
|
19
|
-
export declare function projectRunStatusSignalsV2(events:
|
|
19
|
+
export declare function projectRunStatusSignalsV2(events: SortedEventLog): Result<RunStatusSignalsProjectionV2, ProjectionError>;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { Application } from 'express';
|
|
2
2
|
import type { ConsoleService } from './console-service.js';
|
|
3
|
-
|
|
3
|
+
import type { WorkflowService } from '../../application/services/workflow-service.js';
|
|
4
|
+
import type { ToolCallTimingRingBuffer } from '../../mcp/tool-call-timing.js';
|
|
5
|
+
export declare function mountConsoleRoutes(app: Application, consoleService: ConsoleService, workflowService?: WorkflowService, timingRingBuffer?: ToolCallTimingRingBuffer): () => void;
|