@exaudeus/workrail 3.15.0 → 3.17.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/workflow-service.d.ts +2 -0
- package/dist/application/services/workflow-service.js +3 -0
- package/dist/application/use-cases/raw-workflow-file-scanner.js +10 -13
- package/dist/cli/commands/index.d.ts +1 -1
- package/dist/cli/commands/index.js +2 -1
- package/dist/cli/commands/init.d.ts +10 -0
- package/dist/cli/commands/init.js +72 -0
- package/dist/cli.js +13 -1
- package/dist/config/config-file.d.ts +8 -0
- package/dist/config/config-file.js +141 -0
- package/dist/config/feature-flags.js +8 -0
- package/dist/console/assets/index-BZNM03t1.css +1 -0
- package/dist/console/assets/index-BwJelCXK.js +28 -0
- package/dist/console/index.html +2 -2
- package/dist/di/container.d.ts +1 -0
- package/dist/di/container.js +24 -7
- package/dist/infrastructure/session/HttpServer.d.ts +3 -4
- package/dist/infrastructure/session/HttpServer.js +58 -106
- 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 +303 -247
- package/dist/mcp/assert-output.d.ts +37 -0
- package/dist/mcp/assert-output.js +53 -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 +2 -0
- package/dist/mcp/dev-mode.js +16 -0
- package/dist/mcp/handler-factory.d.ts +1 -1
- package/dist/mcp/handler-factory.js +20 -16
- package/dist/mcp/handlers/session.js +8 -9
- package/dist/mcp/handlers/shared/request-workflow-reader.d.ts +1 -0
- package/dist/mcp/handlers/shared/request-workflow-reader.js +90 -20
- 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 +4 -3
- 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 +1 -1
- 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.d.ts +1 -0
- package/dist/mcp/handlers/v2-execution/continue-advance.js +59 -27
- package/dist/mcp/handlers/v2-execution/continue-rehydrate.d.ts +2 -1
- package/dist/mcp/handlers/v2-execution/continue-rehydrate.js +11 -10
- package/dist/mcp/handlers/v2-execution/index.js +2 -0
- package/dist/mcp/handlers/v2-execution/replay.d.ts +8 -4
- package/dist/mcp/handlers/v2-execution/replay.js +50 -30
- package/dist/mcp/handlers/v2-execution/start.d.ts +2 -3
- package/dist/mcp/handlers/v2-execution/start.js +58 -30
- 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 +80 -0
- package/dist/mcp/handlers/v2-workflow.js +40 -23
- package/dist/mcp/handlers/workflow.d.ts +2 -5
- package/dist/mcp/handlers/workflow.js +15 -12
- package/dist/mcp/output-schemas.d.ts +25 -27
- package/dist/mcp/output-schemas.js +7 -7
- package/dist/mcp/server.js +23 -4
- package/dist/mcp/tool-call-timing.d.ts +24 -0
- package/dist/mcp/tool-call-timing.js +85 -0
- 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-response-formatter.d.ts +1 -1
- package/dist/mcp/v2-response-formatter.js +2 -5
- 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/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 +5 -1
- package/dist/types/workflow-definition.js +2 -0
- 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 +2 -0
- package/dist/v2/durable-core/domain/prompt-renderer.js +22 -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/schemas/compiled-workflow/index.js +4 -3
- 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/pinned-workflow-store/index.d.ts +2 -0
- package/dist/v2/infra/local/pinned-workflow-store/index.js +49 -0
- package/dist/v2/infra/local/remembered-roots-store/index.d.ts +3 -1
- package/dist/v2/infra/local/remembered-roots-store/index.js +6 -3
- 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 -2
- package/dist/v2/ports/pinned-workflow-store.port.d.ts +2 -0
- 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 +124 -25
- package/dist/v2/usecases/console-service.d.ts +1 -0
- package/dist/v2/usecases/console-service.js +83 -25
- package/dist/v2/usecases/console-types.d.ts +53 -0
- package/dist/v2/usecases/worktree-service.js +32 -1
- package/package.json +6 -5
- package/spec/workflow.schema.json +18 -0
- package/workflows/adaptive-ticket-creation.json +23 -16
- package/workflows/architecture-scalability-audit.json +29 -22
- package/workflows/bug-investigation.agentic.v2.json +7 -0
- package/workflows/coding-task-workflow-agentic.json +7 -0
- package/workflows/coding-task-workflow-agentic.lean.v2.json +16 -8
- package/workflows/coding-task-workflow-agentic.v2.json +7 -0
- package/workflows/cross-platform-code-conversion.v2.json +7 -0
- package/workflows/document-creation-workflow.json +15 -8
- package/workflows/documentation-update-workflow.json +15 -8
- package/workflows/intelligent-test-case-generation.json +7 -0
- package/workflows/learner-centered-course-workflow.json +9 -2
- package/workflows/mr-review-workflow.agentic.v2.json +7 -0
- package/workflows/personal-learning-materials-creation-branched.json +15 -8
- package/workflows/presentation-creation.json +12 -5
- package/workflows/production-readiness-audit.json +7 -0
- package/workflows/relocation-workflow-us.json +39 -32
- package/workflows/scoped-documentation-workflow.json +33 -26
- package/workflows/ui-ux-design-workflow.json +7 -0
- package/workflows/workflow-diagnose-environment.json +6 -0
- package/workflows/workflow-for-workflows.json +7 -0
- package/workflows/workflow-for-workflows.v2.json +23 -11
- package/workflows/wr.discovery.json +8 -1
- package/dist/console/assets/index-BZYIjrzJ.js +0 -28
- package/dist/console/assets/index-OLCKbDdm.css +0 -1
- package/dist/mcp/handlers/v2-resolve-refs-envelope.d.ts +0 -5
- package/dist/mcp/handlers/v2-resolve-refs-envelope.js +0 -17
|
@@ -13,6 +13,7 @@ const constants_js_1 = require("../constants.js");
|
|
|
13
13
|
const validation_requirements_extractor_js_1 = require("./validation-requirements-extractor.js");
|
|
14
14
|
const index_js_2 = require("../schemas/artifacts/index.js");
|
|
15
15
|
const run_context_js_1 = require("../../projections/run-context.js");
|
|
16
|
+
const sorted_event_log_js_1 = require("../sorted-event-log.js");
|
|
16
17
|
const condition_evaluator_js_1 = require("../../../utils/condition-evaluator.js");
|
|
17
18
|
const context_template_resolver_js_1 = require("./context-template-resolver.js");
|
|
18
19
|
const retrieval_contract_js_1 = require("./retrieval-contract.js");
|
|
@@ -86,15 +87,7 @@ function buildRecoverySegments(args) {
|
|
|
86
87
|
];
|
|
87
88
|
}
|
|
88
89
|
function resolveParentLoopStep(workflow, stepId) {
|
|
89
|
-
|
|
90
|
-
if ((0, workflow_js_1.isLoopStepDefinition)(step) && Array.isArray(step.body)) {
|
|
91
|
-
for (const bodyStep of step.body) {
|
|
92
|
-
if (bodyStep.id === stepId)
|
|
93
|
-
return step;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return undefined;
|
|
90
|
+
return workflow.parentLoopByStepId.get(stepId);
|
|
98
91
|
}
|
|
99
92
|
function buildLoopRenderContext(loopStep, iteration, sessionContext) {
|
|
100
93
|
const iterationVar = loopStep.loop.iterationVar || 'currentIteration';
|
|
@@ -238,11 +231,13 @@ function renderPendingPrompt(args) {
|
|
|
238
231
|
const isExitStep = outputContract?.contractRef === index_js_2.LOOP_CONTROL_CONTRACT_REF;
|
|
239
232
|
const loopStep = resolveParentLoopStep(args.workflow, args.stepId);
|
|
240
233
|
const maxIterations = loopStep?.loop.maxIterations;
|
|
241
|
-
const sessionContext =
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
234
|
+
const sessionContext = args.precomputedIndex
|
|
235
|
+
? (args.precomputedIndex.runContextByRunId.get(String(args.runId)) ?? {})
|
|
236
|
+
: (0, sorted_event_log_js_1.asSortedEventLog)(args.truth.events).andThen((sorted) => (0, run_context_js_1.projectRunContextV2)(sorted)).match((ok) => (ok.byRunId[String(args.runId)]?.context ?? {}), (e) => {
|
|
237
|
+
console.warn(`[prompt-renderer] Context projection failed for step '${args.stepId}' — ` +
|
|
238
|
+
`{{varName}} tokens will render as [unset:...]: ${e.message}`);
|
|
239
|
+
return {};
|
|
240
|
+
});
|
|
246
241
|
const loopIterationFrame = args.loopPath.at(-1);
|
|
247
242
|
const loopRenderContext = loopStep && loopIterationFrame
|
|
248
243
|
? buildLoopRenderContext(loopStep, loopIterationFrame.iteration, sessionContext)
|
|
@@ -250,7 +245,7 @@ function renderPendingPrompt(args) {
|
|
|
250
245
|
const renderContext = { ...sessionContext, ...loopRenderContext };
|
|
251
246
|
const basePrompt = (0, context_template_resolver_js_1.resolveContextTemplates)(step.prompt ?? '', renderContext);
|
|
252
247
|
const baseTitle = (0, context_template_resolver_js_1.resolveContextTemplates)(step.title, renderContext);
|
|
253
|
-
const cleanResponseFormat =
|
|
248
|
+
const cleanResponseFormat = args.cleanResponseFormat ?? false;
|
|
254
249
|
const loopBanner = buildLoopContextBanner({ loopPath: args.loopPath, isExitStep, maxIterations, cleanFormat: cleanResponseFormat });
|
|
255
250
|
const validationCriteria = step.validationCriteria;
|
|
256
251
|
const requirements = (0, validation_requirements_extractor_js_1.extractValidationRequirements)(validationCriteria);
|
|
@@ -279,7 +274,9 @@ function renderPendingPrompt(args) {
|
|
|
279
274
|
if (cleanResponseFormat) {
|
|
280
275
|
return '';
|
|
281
276
|
}
|
|
282
|
-
const hasPriorNotes =
|
|
277
|
+
const hasPriorNotes = args.precomputedIndex
|
|
278
|
+
? args.precomputedIndex.hasPriorNotesByRunId.has(String(args.runId))
|
|
279
|
+
: hasPriorNotesInRun({ truth: args.truth, runId: args.runId });
|
|
283
280
|
if (hasPriorNotes && !args.rehydrateOnly) {
|
|
284
281
|
return '\n\n**NOTES REQUIRED (System):** Include `output.notesMarkdown` when advancing.\n\n' +
|
|
285
282
|
'Scope: this step only — WorkRail concatenates notes automatically.\n' +
|
|
@@ -321,8 +318,15 @@ function renderPendingPrompt(args) {
|
|
|
321
318
|
const fragmentSuffix = promptFragments && promptFragments.length > 0
|
|
322
319
|
? assembleFragmentedPrompt(promptFragments, renderContext)
|
|
323
320
|
: '';
|
|
324
|
-
const enhancedPrompt =
|
|
325
|
-
|
|
321
|
+
const enhancedPrompt = [
|
|
322
|
+
loopBanner,
|
|
323
|
+
basePrompt,
|
|
324
|
+
requirementsSection,
|
|
325
|
+
contractSection,
|
|
326
|
+
assessmentSection,
|
|
327
|
+
notesSection,
|
|
328
|
+
fragmentSuffix ? '\n\n' + fragmentSuffix : '',
|
|
329
|
+
].join('');
|
|
326
330
|
if (!args.rehydrateOnly) {
|
|
327
331
|
return (0, neverthrow_1.ok)({ stepId: args.stepId, title: baseTitle, prompt: enhancedPrompt, agentRole, requireConfirmation });
|
|
328
332
|
}
|
|
@@ -6,18 +6,21 @@ exports.buildChildSummary = buildChildSummary;
|
|
|
6
6
|
const neverthrow_1 = require("neverthrow");
|
|
7
7
|
const constants_js_1 = require("../constants.js");
|
|
8
8
|
function collectAncestryRecap(args) {
|
|
9
|
-
const buildChain = (
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
const buildChain = (start) => {
|
|
10
|
+
const result = [];
|
|
11
|
+
const visited = new Set();
|
|
12
|
+
let cur = start;
|
|
13
|
+
while (cur !== null && !visited.has(cur)) {
|
|
14
|
+
visited.add(cur);
|
|
15
|
+
result.push(cur);
|
|
16
|
+
cur = args.dag.nodesById[cur]?.parentNodeId ?? null;
|
|
17
|
+
}
|
|
18
|
+
return result;
|
|
16
19
|
};
|
|
17
20
|
const startNode = args.includeCurrentNode
|
|
18
21
|
? String(args.nodeId)
|
|
19
22
|
: args.dag.nodesById[String(args.nodeId)]?.parentNodeId ?? null;
|
|
20
|
-
const chain = buildChain(startNode
|
|
23
|
+
const chain = buildChain(startNode);
|
|
21
24
|
const recaps = chain.flatMap((nodeId) => {
|
|
22
25
|
const nodeOutputs = args.outputs.nodesById[nodeId];
|
|
23
26
|
if (!nodeOutputs)
|
|
@@ -35,15 +38,19 @@ function collectAncestryRecap(args) {
|
|
|
35
38
|
return (0, neverthrow_1.ok)([...recaps].reverse());
|
|
36
39
|
}
|
|
37
40
|
function collectDownstreamRecap(args) {
|
|
38
|
-
const buildPathBackward = (
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
const buildPathBackward = (start) => {
|
|
42
|
+
const result = [];
|
|
43
|
+
const visited = new Set();
|
|
44
|
+
const fromId = String(args.fromNodeId);
|
|
45
|
+
let cur = start;
|
|
46
|
+
while (cur !== null && cur !== fromId && !visited.has(cur)) {
|
|
47
|
+
visited.add(cur);
|
|
48
|
+
result.push(cur);
|
|
49
|
+
cur = args.dag.nodesById[cur]?.parentNodeId ?? null;
|
|
50
|
+
}
|
|
51
|
+
return result;
|
|
45
52
|
};
|
|
46
|
-
const pathBackward = buildPathBackward(String(args.toNodeId)
|
|
53
|
+
const pathBackward = buildPathBackward(String(args.toNodeId));
|
|
47
54
|
const recaps = [...pathBackward].reverse().flatMap((nodeId) => {
|
|
48
55
|
const nodeOutputs = args.outputs.nodesById[nodeId];
|
|
49
56
|
if (!nodeOutputs)
|
|
@@ -63,17 +63,21 @@ exports.RESUME_PREVIEW_CONTRACT = {
|
|
|
63
63
|
};
|
|
64
64
|
const encoder = new TextEncoder();
|
|
65
65
|
const decoder = new TextDecoder('utf-8');
|
|
66
|
+
const TIER_PRIORITY = Object.fromEntries(exports.REHYDRATE_RETRIEVAL_CONTRACT.tiers.map((t) => [t.tier, t.priority]));
|
|
67
|
+
const TIER_RETENTION = Object.fromEntries(exports.REHYDRATE_RETRIEVAL_CONTRACT.tiers.map((t) => [t.tier, t.retention]));
|
|
68
|
+
const RESUME_PREVIEW_TIER_PRIORITY = Object.fromEntries(exports.RESUME_PREVIEW_CONTRACT.tiers.map((t) => [t.tier, t.priority]));
|
|
69
|
+
const RESUME_PREVIEW_TIER_MAX_BYTES = Object.fromEntries(exports.RESUME_PREVIEW_CONTRACT.tiers.map((t) => [t.tier, t.maxBytes]));
|
|
66
70
|
function getTierPriority(tier) {
|
|
67
|
-
return
|
|
71
|
+
return TIER_PRIORITY[tier] ?? Number.MAX_SAFE_INTEGER;
|
|
68
72
|
}
|
|
69
73
|
function getTierRetention(tier) {
|
|
70
|
-
return
|
|
74
|
+
return TIER_RETENTION[tier] ?? 'tail';
|
|
71
75
|
}
|
|
72
76
|
function getResumePreviewTierPriority(tier) {
|
|
73
|
-
return
|
|
77
|
+
return RESUME_PREVIEW_TIER_PRIORITY[tier] ?? Number.MAX_SAFE_INTEGER;
|
|
74
78
|
}
|
|
75
79
|
function getResumePreviewTierMaxBytes(tier) {
|
|
76
|
-
return
|
|
80
|
+
return RESUME_PREVIEW_TIER_MAX_BYTES[tier] ?? exports.RESUME_PREVIEW_CONTRACT.budgetBytes;
|
|
77
81
|
}
|
|
78
82
|
function compareAscii(a, b) {
|
|
79
83
|
return a < b ? -1 : a > b ? 1 : 0;
|
|
@@ -283,7 +287,8 @@ function renderBudgetedRehydrateRecovery(args) {
|
|
|
283
287
|
const initiallyIncludedTiers = tiersInOrder.filter((tier) => (sectionsByTier.get(tier) ?? []).length > 0);
|
|
284
288
|
let includedTiers = initiallyIncludedTiers;
|
|
285
289
|
let recoveryText = renderFromTiers(includedTiers);
|
|
286
|
-
|
|
290
|
+
let recoveryBytes = encoder.encode(recoveryText).length;
|
|
291
|
+
while (recoveryBytes > constants_js_1.RECOVERY_BUDGET_BYTES) {
|
|
287
292
|
const droppableTierIndex = [...includedTiers]
|
|
288
293
|
.reverse()
|
|
289
294
|
.findIndex((tier) => getTierRetention(tier) === 'tail');
|
|
@@ -293,9 +298,10 @@ function renderBudgetedRehydrateRecovery(args) {
|
|
|
293
298
|
const actualIndex = includedTiers.length - 1 - droppableTierIndex;
|
|
294
299
|
includedTiers = includedTiers.filter((_, index) => index !== actualIndex);
|
|
295
300
|
recoveryText = renderFromTiers(includedTiers);
|
|
301
|
+
recoveryBytes = encoder.encode(recoveryText).length;
|
|
296
302
|
}
|
|
297
303
|
const omittedTierCount = initiallyIncludedTiers.length - includedTiers.length;
|
|
298
|
-
const needsSuffix = omittedTierCount > 0 ||
|
|
304
|
+
const needsSuffix = omittedTierCount > 0 || recoveryBytes > constants_js_1.RECOVERY_BUDGET_BYTES || includedTiers.length === 0;
|
|
299
305
|
const finalText = recoveryText.length === 0
|
|
300
306
|
? trimFinalRecoveryText(args.header, initiallyIncludedTiers.length)
|
|
301
307
|
: !needsSuffix
|
|
@@ -305,6 +311,6 @@ function renderBudgetedRehydrateRecovery(args) {
|
|
|
305
311
|
text: finalText,
|
|
306
312
|
includedTiers,
|
|
307
313
|
omittedTierCount,
|
|
308
|
-
truncatedWithinTier:
|
|
314
|
+
truncatedWithinTier: recoveryBytes > constants_js_1.RECOVERY_BUDGET_BYTES || includedTiers.length === 0,
|
|
309
315
|
};
|
|
310
316
|
}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.CompiledWorkflowSnapshotSchema = exports.CompiledWorkflowSnapshotV1Schema = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const json_zod_js_1 = require("../../canonical/json-zod.js");
|
|
6
|
+
const workflow_definition_js_1 = require("../../../../types/workflow-definition.js");
|
|
6
7
|
const CompiledWorkflowSnapshotV1PreviewSchema = zod_1.z.object({
|
|
7
8
|
schemaVersion: zod_1.z.literal(1),
|
|
8
9
|
sourceKind: zod_1.z.literal('v1_preview'),
|
|
@@ -33,7 +34,7 @@ const CompiledWorkflowSnapshotV1PinnedSchema = zod_1.z.object({
|
|
|
33
34
|
source: zod_1.z.string().min(1),
|
|
34
35
|
purpose: zod_1.z.string().min(1),
|
|
35
36
|
authoritative: zod_1.z.boolean(),
|
|
36
|
-
resolveFrom: zod_1.z.enum(
|
|
37
|
+
resolveFrom: zod_1.z.enum(workflow_definition_js_1.RESOLVE_FROM_VALUES),
|
|
37
38
|
status: zod_1.z.literal('resolved'),
|
|
38
39
|
resolvedPath: zod_1.z.string().min(1),
|
|
39
40
|
}),
|
|
@@ -43,7 +44,7 @@ const CompiledWorkflowSnapshotV1PinnedSchema = zod_1.z.object({
|
|
|
43
44
|
source: zod_1.z.string().min(1),
|
|
44
45
|
purpose: zod_1.z.string().min(1),
|
|
45
46
|
authoritative: zod_1.z.boolean(),
|
|
46
|
-
resolveFrom: zod_1.z.enum(
|
|
47
|
+
resolveFrom: zod_1.z.enum(workflow_definition_js_1.RESOLVE_FROM_VALUES),
|
|
47
48
|
status: zod_1.z.literal('unresolved'),
|
|
48
49
|
}),
|
|
49
50
|
zod_1.z.object({
|
|
@@ -52,7 +53,7 @@ const CompiledWorkflowSnapshotV1PinnedSchema = zod_1.z.object({
|
|
|
52
53
|
source: zod_1.z.string().min(1),
|
|
53
54
|
purpose: zod_1.z.string().min(1),
|
|
54
55
|
authoritative: zod_1.z.boolean(),
|
|
55
|
-
resolveFrom: zod_1.z.enum(
|
|
56
|
+
resolveFrom: zod_1.z.enum(workflow_definition_js_1.RESOLVE_FROM_VALUES),
|
|
56
57
|
status: zod_1.z.literal('pinned'),
|
|
57
58
|
}),
|
|
58
59
|
])).optional(),
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Brand } from '../../runtime/brand.js';
|
|
2
|
+
import type { SortedEventLog } from './sorted-event-log.js';
|
|
3
|
+
import type { DomainEventV1 } from './schemas/session/index.js';
|
|
4
|
+
import type { JsonObject } from './canonical/json-types.js';
|
|
5
|
+
export interface SessionIndexData {
|
|
6
|
+
readonly sortedEvents: SortedEventLog;
|
|
7
|
+
readonly runStartedByRunId: ReadonlyMap<string, Extract<DomainEventV1, {
|
|
8
|
+
kind: 'run_started';
|
|
9
|
+
}>>;
|
|
10
|
+
readonly nodeCreatedByNodeId: ReadonlyMap<string, Extract<DomainEventV1, {
|
|
11
|
+
kind: 'node_created';
|
|
12
|
+
}>>;
|
|
13
|
+
readonly hasChildEdgeByFromNodeId: ReadonlySet<string>;
|
|
14
|
+
readonly advanceRecordedByDedupeKey: ReadonlyMap<string, Extract<DomainEventV1, {
|
|
15
|
+
kind: 'advance_recorded';
|
|
16
|
+
}>>;
|
|
17
|
+
readonly nextEventIndex: number;
|
|
18
|
+
readonly hasPriorNotesByRunId: ReadonlySet<string>;
|
|
19
|
+
readonly runContextByRunId: ReadonlyMap<string, JsonObject>;
|
|
20
|
+
}
|
|
21
|
+
export type SessionIndex = Brand<SessionIndexData, 'v2.SessionIndex'>;
|
|
22
|
+
export declare function buildSessionIndex(events: SortedEventLog): SessionIndex;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildSessionIndex = buildSessionIndex;
|
|
4
|
+
const constants_js_1 = require("./constants.js");
|
|
5
|
+
function buildSessionIndex(events) {
|
|
6
|
+
const runStartedByRunId = new Map();
|
|
7
|
+
const nodeCreatedByNodeId = new Map();
|
|
8
|
+
const hasChildEdgeByFromNodeId = new Set();
|
|
9
|
+
const advanceRecordedByDedupeKey = new Map();
|
|
10
|
+
const hasPriorNotesByRunId = new Set();
|
|
11
|
+
const runContextByRunId = new Map();
|
|
12
|
+
for (const event of events) {
|
|
13
|
+
switch (event.kind) {
|
|
14
|
+
case 'run_started':
|
|
15
|
+
runStartedByRunId.set(event.scope.runId, event);
|
|
16
|
+
break;
|
|
17
|
+
case 'node_created':
|
|
18
|
+
nodeCreatedByNodeId.set(event.scope.nodeId, event);
|
|
19
|
+
break;
|
|
20
|
+
case 'edge_created':
|
|
21
|
+
hasChildEdgeByFromNodeId.add(event.data.fromNodeId);
|
|
22
|
+
break;
|
|
23
|
+
case 'advance_recorded':
|
|
24
|
+
advanceRecordedByDedupeKey.set(event.dedupeKey, event);
|
|
25
|
+
break;
|
|
26
|
+
case 'node_output_appended': {
|
|
27
|
+
const outputEvt = event;
|
|
28
|
+
if (outputEvt.data.outputChannel === constants_js_1.OUTPUT_CHANNEL.RECAP &&
|
|
29
|
+
outputEvt.data.payload.payloadKind === constants_js_1.PAYLOAD_KIND.NOTES) {
|
|
30
|
+
hasPriorNotesByRunId.add(event.scope.runId);
|
|
31
|
+
}
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
case 'context_set': {
|
|
35
|
+
const ctx = event.data.context;
|
|
36
|
+
if (ctx && typeof ctx === 'object' && !Array.isArray(ctx)) {
|
|
37
|
+
runContextByRunId.set(event.scope.runId, ctx);
|
|
38
|
+
}
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
default:
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const lastEvent = events[events.length - 1];
|
|
46
|
+
const nextEventIndex = lastEvent !== undefined ? lastEvent.eventIndex + 1 : 0;
|
|
47
|
+
const data = {
|
|
48
|
+
sortedEvents: events,
|
|
49
|
+
runStartedByRunId,
|
|
50
|
+
nodeCreatedByNodeId,
|
|
51
|
+
hasChildEdgeByFromNodeId,
|
|
52
|
+
advanceRecordedByDedupeKey,
|
|
53
|
+
nextEventIndex,
|
|
54
|
+
hasPriorNotesByRunId,
|
|
55
|
+
runContextByRunId,
|
|
56
|
+
};
|
|
57
|
+
return data;
|
|
58
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Result } from 'neverthrow';
|
|
2
|
+
import type { Brand } from '../../runtime/brand.js';
|
|
3
|
+
import type { DomainEventV1 } from './schemas/session/index.js';
|
|
4
|
+
import type { ProjectionError } from '../projections/projection-error.js';
|
|
5
|
+
export type SortedEventLog = Brand<readonly DomainEventV1[], 'v2.SortedEventLog'>;
|
|
6
|
+
export declare function asSortedEventLog(events: readonly DomainEventV1[]): Result<SortedEventLog, ProjectionError>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.asSortedEventLog = asSortedEventLog;
|
|
4
|
+
const neverthrow_1 = require("neverthrow");
|
|
5
|
+
function asSortedEventLog(events) {
|
|
6
|
+
for (let i = 1; i < events.length; i++) {
|
|
7
|
+
if (events[i].eventIndex <= events[i - 1].eventIndex) {
|
|
8
|
+
return (0, neverthrow_1.err)({
|
|
9
|
+
code: 'PROJECTION_INVARIANT_VIOLATION',
|
|
10
|
+
message: 'Events must be sorted by eventIndex strictly ascending (no duplicates)',
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return (0, neverthrow_1.ok)(events);
|
|
15
|
+
}
|
|
@@ -166,18 +166,18 @@ class NodeFileSystemV2 {
|
|
|
166
166
|
readdirWithMtime(dirPath) {
|
|
167
167
|
return neverthrow_1.ResultAsync.fromPromise((async () => {
|
|
168
168
|
const entries = await fs.readdir(dirPath);
|
|
169
|
+
const results = await Promise.allSettled(entries.map((name) => fs.stat(path.join(dirPath, name)).then((s) => ({ name, mtimeMs: s.mtimeMs }))));
|
|
169
170
|
const withMtime = [];
|
|
170
171
|
let skipped = 0;
|
|
171
|
-
for (
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
withMtime.push(
|
|
172
|
+
for (let i = 0; i < results.length; i++) {
|
|
173
|
+
const result = results[i];
|
|
174
|
+
if (result.status === 'fulfilled') {
|
|
175
|
+
withMtime.push(result.value);
|
|
175
176
|
}
|
|
176
|
-
|
|
177
|
-
const code = nodeErrorCode(
|
|
177
|
+
else {
|
|
178
|
+
const code = nodeErrorCode(result.reason);
|
|
178
179
|
skipped++;
|
|
179
|
-
console.error(`[workrail:session-enum] Skipping ${
|
|
180
|
-
continue;
|
|
180
|
+
console.error(`[workrail:session-enum] Skipping ${entries[i]}: stat failed (${code ?? 'unknown'}: ${result.reason instanceof Error ? result.reason.message : String(result.reason)})`);
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
183
|
if (skipped > 0) {
|
|
@@ -9,5 +9,7 @@ export declare class LocalPinnedWorkflowStoreV2 implements PinnedWorkflowStorePo
|
|
|
9
9
|
private readonly fs;
|
|
10
10
|
constructor(dataDir: DataDirPortV2, fs: FileSystemPortV2);
|
|
11
11
|
get(workflowHash: WorkflowHash): ResultAsync<CompiledWorkflowSnapshot | null, PinnedWorkflowStoreError>;
|
|
12
|
+
list(): ResultAsync<readonly WorkflowHash[], PinnedWorkflowStoreError>;
|
|
13
|
+
prune(_olderThanMs: number): ResultAsync<number, PinnedWorkflowStoreError>;
|
|
12
14
|
put(workflowHash: WorkflowHash, compiled: CompiledWorkflowSnapshot): ResultAsync<void, PinnedWorkflowStoreError>;
|
|
13
15
|
}
|
|
@@ -1,6 +1,40 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
36
|
exports.LocalPinnedWorkflowStoreV2 = void 0;
|
|
37
|
+
const nodePath = __importStar(require("node:path"));
|
|
4
38
|
const neverthrow_1 = require("neverthrow");
|
|
5
39
|
const index_js_1 = require("../../../durable-core/schemas/compiled-workflow/index.js");
|
|
6
40
|
const jcs_js_1 = require("../../../durable-core/canonical/jcs.js");
|
|
@@ -43,6 +77,21 @@ class LocalPinnedWorkflowStoreV2 {
|
|
|
43
77
|
return (0, neverthrow_1.okAsync)(validated.data);
|
|
44
78
|
});
|
|
45
79
|
}
|
|
80
|
+
list() {
|
|
81
|
+
const dir = this.dataDir.pinnedWorkflowsDir();
|
|
82
|
+
return this.fs.readdir(dir)
|
|
83
|
+
.orElse((e) => {
|
|
84
|
+
if (e.code === 'FS_NOT_FOUND')
|
|
85
|
+
return (0, neverthrow_1.okAsync)([]);
|
|
86
|
+
return (0, neverthrow_1.errAsync)(mapFsToStoreError(e));
|
|
87
|
+
})
|
|
88
|
+
.map((entries) => entries
|
|
89
|
+
.filter((name) => name.endsWith('.json') && !name.endsWith('.tmp'))
|
|
90
|
+
.map((name) => nodePath.basename(name, '.json')));
|
|
91
|
+
}
|
|
92
|
+
prune(_olderThanMs) {
|
|
93
|
+
return (0, neverthrow_1.okAsync)(0);
|
|
94
|
+
}
|
|
46
95
|
put(workflowHash, compiled) {
|
|
47
96
|
const dir = this.dataDir.pinnedWorkflowsDir();
|
|
48
97
|
const filePath = this.dataDir.pinnedWorkflowPath(workflowHash);
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { ResultAsync } from 'neverthrow';
|
|
2
2
|
import type { DataDirPortV2 } from '../../../ports/data-dir.port.js';
|
|
3
3
|
import type { FileSystemPortV2 } from '../../../ports/fs.port.js';
|
|
4
|
+
import type { TimeClockPortV2 } from '../../../ports/time-clock.port.js';
|
|
4
5
|
import type { RememberedRootRecordV2, RememberedRootsStoreError, RememberedRootsStorePortV2 } from '../../../ports/remembered-roots-store.port.js';
|
|
5
6
|
export declare class LocalRememberedRootsStoreV2 implements RememberedRootsStorePortV2 {
|
|
6
7
|
private readonly dataDir;
|
|
7
8
|
private readonly fs;
|
|
8
|
-
|
|
9
|
+
private readonly clock;
|
|
10
|
+
constructor(dataDir: DataDirPortV2, fs: FileSystemPortV2, clock: TimeClockPortV2);
|
|
9
11
|
listRoots(): ResultAsync<readonly string[], RememberedRootsStoreError>;
|
|
10
12
|
listRootRecords(): ResultAsync<readonly RememberedRootRecordV2[], RememberedRootsStoreError>;
|
|
11
13
|
rememberRoot(rootPath: string): ResultAsync<void, RememberedRootsStoreError>;
|
|
@@ -9,6 +9,7 @@ const zod_1 = require("zod");
|
|
|
9
9
|
const neverthrow_1 = require("neverthrow");
|
|
10
10
|
const jcs_js_1 = require("../../../durable-core/canonical/jcs.js");
|
|
11
11
|
const REMEMBERED_ROOTS_LOCK_RETRY_MS = 250;
|
|
12
|
+
const TTL_30_DAYS_MS = 30 * 24 * 60 * 60 * 1000;
|
|
12
13
|
const RememberedRootRecordSchema = zod_1.z.object({
|
|
13
14
|
path: zod_1.z.string(),
|
|
14
15
|
addedAtMs: zod_1.z.number().int().nonnegative(),
|
|
@@ -48,9 +49,10 @@ function normalizeRootRecords(roots) {
|
|
|
48
49
|
return normalized;
|
|
49
50
|
}
|
|
50
51
|
class LocalRememberedRootsStoreV2 {
|
|
51
|
-
constructor(dataDir, fs) {
|
|
52
|
+
constructor(dataDir, fs, clock) {
|
|
52
53
|
this.dataDir = dataDir;
|
|
53
54
|
this.fs = fs;
|
|
55
|
+
this.clock = clock;
|
|
54
56
|
}
|
|
55
57
|
listRoots() {
|
|
56
58
|
return this.listRootRecords().map((roots) => roots.map((root) => root.path));
|
|
@@ -88,7 +90,7 @@ class LocalRememberedRootsStoreV2 {
|
|
|
88
90
|
}
|
|
89
91
|
rememberRoot(rootPath) {
|
|
90
92
|
const normalizedRoot = path_1.default.resolve(rootPath);
|
|
91
|
-
const nowMs =
|
|
93
|
+
const nowMs = this.clock.nowMs();
|
|
92
94
|
return this.withLock(() => this.listRootRecords().andThen((roots) => {
|
|
93
95
|
const existing = roots.find((root) => root.path === normalizedRoot);
|
|
94
96
|
const nextRoots = existing
|
|
@@ -104,7 +106,8 @@ class LocalRememberedRootsStoreV2 {
|
|
|
104
106
|
source: 'explicit_workspace_path',
|
|
105
107
|
},
|
|
106
108
|
];
|
|
107
|
-
|
|
109
|
+
const withEviction = nextRoots.filter((r) => r.lastSeenAtMs >= nowMs - TTL_30_DAYS_MS);
|
|
110
|
+
return this.persist(withEviction);
|
|
108
111
|
}));
|
|
109
112
|
}
|
|
110
113
|
persist(roots) {
|
|
@@ -10,7 +10,7 @@ export declare class LocalSessionEventLogStoreV2 implements SessionEventLogReado
|
|
|
10
10
|
private readonly fs;
|
|
11
11
|
private readonly sha256;
|
|
12
12
|
constructor(dataDir: DataDirPortV2, fs: FileSystemPortV2, sha256: Sha256PortV2);
|
|
13
|
-
append(lock: WithHealthySessionLock, plan: AppendPlanV2): ResultAsync<void, SessionEventLogStoreError>;
|
|
13
|
+
append(lock: WithHealthySessionLock, plan: AppendPlanV2, preloadedTruth?: LoadedSessionTruthV2): ResultAsync<void, SessionEventLogStoreError>;
|
|
14
14
|
load(sessionId: SessionId): ResultAsync<LoadedSessionTruthV2, SessionEventLogStoreError>;
|
|
15
15
|
loadValidatedPrefix(sessionId: SessionId): ResultAsync<LoadedValidatedPrefixV2, SessionEventLogStoreError>;
|
|
16
16
|
private appendImpl;
|