@exaudeus/workrail 3.16.0 → 3.18.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 +7 -11
- package/dist/application/services/workflow-compiler.js +9 -11
- 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-BwJelCXK.js +28 -0
- package/dist/console/index.html +1 -1
- package/dist/di/container.d.ts +1 -0
- package/dist/di/container.js +24 -7
- package/dist/infrastructure/session/HttpServer.d.ts +0 -1
- package/dist/infrastructure/session/HttpServer.js +4 -46
- package/dist/manifest.json +120 -128
- package/dist/mcp/assert-output.js +2 -1
- package/dist/mcp/dev-mode.d.ts +1 -0
- package/dist/mcp/dev-mode.js +12 -0
- package/dist/mcp/handler-factory.d.ts +1 -1
- package/dist/mcp/handler-factory.js +8 -7
- 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/assessment-consequences.d.ts +1 -1
- package/dist/mcp/handlers/v2-advance-core/assessment-consequences.js +14 -11
- package/dist/mcp/handlers/v2-advance-core/assessment-validation.d.ts +5 -3
- package/dist/mcp/handlers/v2-advance-core/assessment-validation.js +109 -87
- package/dist/mcp/handlers/v2-advance-core/input-validation.d.ts +0 -4
- package/dist/mcp/handlers/v2-advance-core/input-validation.js +1 -3
- package/dist/mcp/handlers/v2-advance-core/outcome-blocked.js +8 -3
- package/dist/mcp/handlers/v2-advance-core/outcome-success.js +8 -3
- package/dist/mcp/handlers/v2-execution/continue-advance.d.ts +1 -0
- package/dist/mcp/handlers/v2-execution/continue-advance.js +3 -1
- package/dist/mcp/handlers/v2-execution/continue-rehydrate.d.ts +1 -0
- package/dist/mcp/handlers/v2-execution/continue-rehydrate.js +2 -1
- package/dist/mcp/handlers/v2-execution/index.js +2 -0
- package/dist/mcp/handlers/v2-execution/replay.d.ts +2 -0
- package/dist/mcp/handlers/v2-execution/replay.js +7 -4
- package/dist/mcp/handlers/v2-execution/start.js +48 -20
- package/dist/mcp/handlers/v2-workflow.js +4 -2
- package/dist/mcp/output-schemas.d.ts +17 -12
- package/dist/mcp/output-schemas.js +12 -11
- package/dist/mcp/server.js +3 -2
- package/dist/mcp/v2-response-formatter.d.ts +1 -1
- package/dist/mcp/v2-response-formatter.js +2 -3
- package/dist/types/workflow-definition.d.ts +3 -1
- package/dist/types/workflow-definition.js +2 -0
- package/dist/v2/durable-core/domain/prompt-renderer.d.ts +1 -0
- package/dist/v2/durable-core/domain/prompt-renderer.js +5 -2
- package/dist/v2/durable-core/schemas/compiled-workflow/index.js +4 -3
- 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/workspace-anchor/index.js +4 -2
- package/dist/v2/ports/pinned-workflow-store.port.d.ts +2 -0
- package/dist/v2/usecases/console-routes.js +3 -2
- package/package.json +1 -1
- package/spec/authoring-spec.json +3 -3
- package/spec/workflow.schema.json +1 -2
- package/workflows/workflow-for-workflows.json +558 -448
- package/dist/console/assets/index-BE5PAgPO.js +0 -28
- package/dist/env-flags.d.ts +0 -1
- package/dist/env-flags.js +0 -4
- package/dist/mcp/handlers/v2-resolve-refs-envelope.d.ts +0 -5
- package/dist/mcp/handlers/v2-resolve-refs-envelope.js +0 -17
|
@@ -685,24 +685,24 @@ let ValidationEngine = ValidationEngine_1 = class ValidationEngine {
|
|
|
685
685
|
issues.push(`${stepLabel}: assessmentConsequences must not be empty when declared`);
|
|
686
686
|
return;
|
|
687
687
|
}
|
|
688
|
-
if (!step.assessmentRefs || step.assessmentRefs.length
|
|
689
|
-
issues.push(`${stepLabel}: assessmentConsequences require
|
|
690
|
-
suggestions.push(`Add
|
|
688
|
+
if (!step.assessmentRefs || step.assessmentRefs.length === 0) {
|
|
689
|
+
issues.push(`${stepLabel}: assessmentConsequences require at least one assessmentRef on the same step`);
|
|
690
|
+
suggestions.push(`Add at least one assessmentRef to ${stepLabel} before declaring assessmentConsequences`);
|
|
691
691
|
return;
|
|
692
692
|
}
|
|
693
693
|
if (step.assessmentConsequences.length > 1) {
|
|
694
694
|
issues.push(`${stepLabel}: v1 assessment support allows exactly one assessment consequence per step`);
|
|
695
695
|
suggestions.push(`Reduce assessmentConsequences on ${stepLabel} to a single declaration`);
|
|
696
696
|
}
|
|
697
|
-
const
|
|
698
|
-
if (
|
|
697
|
+
const referencedDefinitions = assessments.filter(assessment => step.assessmentRefs.includes(assessment.id));
|
|
698
|
+
if (referencedDefinitions.length === 0)
|
|
699
699
|
return;
|
|
700
700
|
for (const consequence of step.assessmentConsequences) {
|
|
701
701
|
const trigger = consequence.when;
|
|
702
702
|
const effect = consequence.effect;
|
|
703
|
-
const allLevels =
|
|
703
|
+
const allLevels = referencedDefinitions.flatMap(def => def.dimensions.flatMap(d => d.levels));
|
|
704
704
|
if (!allLevels.includes(trigger.anyEqualsLevel)) {
|
|
705
|
-
issues.push(`${stepLabel}: assessment consequence anyEqualsLevel '${trigger.anyEqualsLevel}' is not declared in any dimension of assessment
|
|
705
|
+
issues.push(`${stepLabel}: assessment consequence anyEqualsLevel '${trigger.anyEqualsLevel}' is not declared in any dimension of any referenced assessment`);
|
|
706
706
|
suggestions.push(`Use a level declared in one of the dimensions: ${[...new Set(allLevels)].join(', ')}`);
|
|
707
707
|
}
|
|
708
708
|
if (effect.kind !== 'require_followup') {
|
|
@@ -776,10 +776,6 @@ let ValidationEngine = ValidationEngine_1 = class ValidationEngine {
|
|
|
776
776
|
}
|
|
777
777
|
}
|
|
778
778
|
validateAssessmentRefsForStep(typedStep, `Step '${step.id}'`);
|
|
779
|
-
if (typedStep.assessmentRefs !== undefined && typedStep.assessmentRefs.length > 1) {
|
|
780
|
-
issues.push(`Step '${step.id}': v1 assessment support allows exactly one assessmentRef per step`);
|
|
781
|
-
suggestions.push(`Reduce assessmentRefs on step '${step.id}' to a single assessment id`);
|
|
782
|
-
}
|
|
783
779
|
validateAssessmentConsequencesForStep(typedStep, `Step '${step.id}'`);
|
|
784
780
|
const callValidation = this.validateStepFunctionCalls(step, workflow.definition.functionDefinitions || []);
|
|
785
781
|
if (!callValidation.valid) {
|
|
@@ -140,21 +140,19 @@ let WorkflowCompiler = class WorkflowCompiler {
|
|
|
140
140
|
const assessmentConsequences = typedStep.assessmentConsequences;
|
|
141
141
|
if (!assessmentConsequences)
|
|
142
142
|
continue;
|
|
143
|
-
if (!typedStep.assessmentRefs || typedStep.assessmentRefs.length
|
|
144
|
-
return (0, neverthrow_1.err)(error_1.Err.invalidState(`Step '${step.id}' declares assessmentConsequences but
|
|
145
|
-
}
|
|
146
|
-
const assessment = (workflow.definition.assessments ?? []).find(candidate => candidate.id === typedStep.assessmentRefs?.[0]);
|
|
147
|
-
if (!assessment) {
|
|
148
|
-
return (0, neverthrow_1.err)(error_1.Err.invalidState(`Step '${step.id}' declares assessmentConsequences for unknown assessmentRef '${typedStep.assessmentRefs[0]}'`));
|
|
143
|
+
if (!typedStep.assessmentRefs || typedStep.assessmentRefs.length === 0) {
|
|
144
|
+
return (0, neverthrow_1.err)(error_1.Err.invalidState(`Step '${step.id}' declares assessmentConsequences but declares no assessmentRefs`));
|
|
149
145
|
}
|
|
150
146
|
if (assessmentConsequences.length > 1) {
|
|
151
147
|
return (0, neverthrow_1.err)(error_1.Err.invalidState(`Step '${step.id}' declares ${assessmentConsequences.length} assessment consequences. V1 supports exactly one assessment consequence per step.`));
|
|
152
148
|
}
|
|
149
|
+
const allLevelsAcrossRefs = (workflow.definition.assessments ?? [])
|
|
150
|
+
.filter(candidate => typedStep.assessmentRefs.includes(candidate.id))
|
|
151
|
+
.flatMap(assessment => assessment.dimensions.flatMap(d => d.levels));
|
|
153
152
|
for (const consequence of assessmentConsequences) {
|
|
154
153
|
const trigger = consequence.when;
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
return (0, neverthrow_1.err)(error_1.Err.invalidState(`Step '${step.id}' declares consequence with anyEqualsLevel '${trigger.anyEqualsLevel}' that is not declared in any dimension of assessment '${assessment.id}'`));
|
|
154
|
+
if (!allLevelsAcrossRefs.includes(trigger.anyEqualsLevel)) {
|
|
155
|
+
return (0, neverthrow_1.err)(error_1.Err.invalidState(`Step '${step.id}' declares consequence with anyEqualsLevel '${trigger.anyEqualsLevel}' that is not declared in any dimension of any referenced assessment`));
|
|
158
156
|
}
|
|
159
157
|
if (consequence.effect.kind !== 'require_followup') {
|
|
160
158
|
return (0, neverthrow_1.err)(error_1.Err.invalidState(`Step '${step.id}' declares unsupported assessment consequence effect '${String(consequence.effect.kind)}'`));
|
|
@@ -187,8 +185,8 @@ let WorkflowCompiler = class WorkflowCompiler {
|
|
|
187
185
|
}
|
|
188
186
|
}
|
|
189
187
|
if (bodyStep.assessmentConsequences) {
|
|
190
|
-
if (!bodyStep.assessmentRefs || bodyStep.assessmentRefs.length
|
|
191
|
-
return (0, neverthrow_1.err)(error_1.Err.invalidState(`Loop body step '${bodyStep.id}' in loop '${loop.id}' declares assessmentConsequences but
|
|
188
|
+
if (!bodyStep.assessmentRefs || bodyStep.assessmentRefs.length === 0) {
|
|
189
|
+
return (0, neverthrow_1.err)(error_1.Err.invalidState(`Loop body step '${bodyStep.id}' in loop '${loop.id}' declares assessmentConsequences but declares no assessmentRefs`));
|
|
192
190
|
}
|
|
193
191
|
}
|
|
194
192
|
}
|
|
@@ -6,26 +6,23 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.findWorkflowJsonFiles = findWorkflowJsonFiles;
|
|
7
7
|
exports.scanRawWorkflowFiles = scanRawWorkflowFiles;
|
|
8
8
|
const promises_1 = __importDefault(require("fs/promises"));
|
|
9
|
-
const fs_1 = require("fs");
|
|
10
9
|
const path_1 = __importDefault(require("path"));
|
|
11
10
|
async function findWorkflowJsonFiles(baseDirReal) {
|
|
12
11
|
const files = [];
|
|
13
12
|
async function scan(currentDir) {
|
|
14
13
|
const entries = await promises_1.default.readdir(currentDir, { withFileTypes: true });
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
continue;
|
|
20
|
-
}
|
|
21
|
-
await scan(fullPath);
|
|
22
|
-
}
|
|
23
|
-
else if (entry.isFile() && entry.name.endsWith('.json')) {
|
|
24
|
-
files.push(fullPath);
|
|
25
|
-
}
|
|
14
|
+
const jsonFiles = entries.filter((e) => e.isFile() && e.name.endsWith('.json'));
|
|
15
|
+
const subDirs = entries.filter((e) => e.isDirectory() && e.name !== 'examples');
|
|
16
|
+
for (const f of jsonFiles) {
|
|
17
|
+
files.push(path_1.default.join(currentDir, f.name));
|
|
26
18
|
}
|
|
19
|
+
await Promise.all(subDirs.map((d) => scan(path_1.default.join(currentDir, d.name)).catch((err) => {
|
|
20
|
+
if (err.code !== 'ENOENT')
|
|
21
|
+
throw err;
|
|
22
|
+
})));
|
|
27
23
|
}
|
|
28
24
|
await scan(baseDirReal);
|
|
25
|
+
files.sort();
|
|
29
26
|
return files;
|
|
30
27
|
}
|
|
31
28
|
async function scanRawWorkflowFiles(baseDirReal) {
|
|
@@ -34,7 +31,7 @@ async function scanRawWorkflowFiles(baseDirReal) {
|
|
|
34
31
|
for (const filePath of allJsonFiles) {
|
|
35
32
|
const relativeFilePath = path_1.default.relative(baseDirReal, filePath);
|
|
36
33
|
try {
|
|
37
|
-
const stats =
|
|
34
|
+
const stats = await promises_1.default.stat(filePath);
|
|
38
35
|
if (stats.size > 1000000) {
|
|
39
36
|
results.push({
|
|
40
37
|
kind: 'unparseable',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { executeInitCommand, type InitCommandDeps } from './init.js';
|
|
1
|
+
export { executeInitCommand, executeInitConfigCommand, type InitCommandDeps, type InitConfigCommandDeps } from './init.js';
|
|
2
2
|
export { executeSourcesCommand, getWorkflowSources, type SourcesCommandDeps, type WorkflowSource } from './sources.js';
|
|
3
3
|
export { executeListCommand, type ListCommandDeps, type ListCommandOptions } from './list.js';
|
|
4
4
|
export { executeValidateCommand, type ValidateCommandDeps } from './validate.js';
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.detectWorkflowVersion = exports.migrateWorkflowFile = exports.migrateWorkflow = exports.executeMigrateCommand = exports.executeCleanupCommand = exports.executeStartCommand = exports.executeValidateCommand = exports.executeListCommand = exports.getWorkflowSources = exports.executeSourcesCommand = exports.executeInitCommand = void 0;
|
|
3
|
+
exports.detectWorkflowVersion = exports.migrateWorkflowFile = exports.migrateWorkflow = exports.executeMigrateCommand = exports.executeCleanupCommand = exports.executeStartCommand = exports.executeValidateCommand = exports.executeListCommand = exports.getWorkflowSources = exports.executeSourcesCommand = exports.executeInitConfigCommand = exports.executeInitCommand = void 0;
|
|
4
4
|
var init_js_1 = require("./init.js");
|
|
5
5
|
Object.defineProperty(exports, "executeInitCommand", { enumerable: true, get: function () { return init_js_1.executeInitCommand; } });
|
|
6
|
+
Object.defineProperty(exports, "executeInitConfigCommand", { enumerable: true, get: function () { return init_js_1.executeInitConfigCommand; } });
|
|
6
7
|
var sources_js_1 = require("./sources.js");
|
|
7
8
|
Object.defineProperty(exports, "executeSourcesCommand", { enumerable: true, get: function () { return sources_js_1.executeSourcesCommand; } });
|
|
8
9
|
Object.defineProperty(exports, "getWorkflowSources", { enumerable: true, get: function () { return sources_js_1.getWorkflowSources; } });
|
|
@@ -8,4 +8,14 @@ export interface InitCommandDeps {
|
|
|
8
8
|
readonly homedir: () => string;
|
|
9
9
|
readonly joinPath: (...paths: string[]) => string;
|
|
10
10
|
}
|
|
11
|
+
export interface InitConfigCommandDeps {
|
|
12
|
+
readonly mkdir: (path: string, options: {
|
|
13
|
+
recursive: boolean;
|
|
14
|
+
}) => Promise<string | undefined>;
|
|
15
|
+
readonly readFile: (path: string) => Promise<string>;
|
|
16
|
+
readonly writeFile: (path: string, content: string) => Promise<void>;
|
|
17
|
+
readonly homedir: () => string;
|
|
18
|
+
readonly joinPath: (...paths: string[]) => string;
|
|
19
|
+
}
|
|
11
20
|
export declare function executeInitCommand(deps: InitCommandDeps): Promise<CliResult>;
|
|
21
|
+
export declare function executeInitConfigCommand(deps: InitConfigCommandDeps): Promise<CliResult>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.executeInitCommand = executeInitCommand;
|
|
4
|
+
exports.executeInitConfigCommand = executeInitConfigCommand;
|
|
4
5
|
const cli_result_js_1 = require("../types/cli-result.js");
|
|
5
6
|
const SAMPLE_WORKFLOW = {
|
|
6
7
|
id: 'my-custom-workflow',
|
|
@@ -47,3 +48,74 @@ async function executeInitCommand(deps) {
|
|
|
47
48
|
});
|
|
48
49
|
}
|
|
49
50
|
}
|
|
51
|
+
const CONFIG_FILE_TEMPLATE = `{
|
|
52
|
+
"_comment": "WorkRail configuration file. Uncomment any key to override its default.",
|
|
53
|
+
"_docs": "Full reference: https://github.com/exaudeus/workrail/blob/main/docs/configuration.md",
|
|
54
|
+
|
|
55
|
+
"CACHE_TTL": "300000",
|
|
56
|
+
"WORKRAIL_WORKFLOWS_DIR": "",
|
|
57
|
+
"WORKRAIL_DISABLE_UNIFIED_DASHBOARD": "0",
|
|
58
|
+
"WORKRAIL_DISABLE_AUTO_OPEN": "0",
|
|
59
|
+
"WORKRAIL_DASHBOARD_PORT": "3456",
|
|
60
|
+
|
|
61
|
+
"WORKRAIL_ENABLE_SESSION_TOOLS": "true",
|
|
62
|
+
"WORKRAIL_ENABLE_EXPERIMENTAL_WORKFLOWS": "false",
|
|
63
|
+
"WORKRAIL_VERBOSE_LOGGING": "false",
|
|
64
|
+
"WORKRAIL_ENABLE_AGENTIC_ROUTINES": "true",
|
|
65
|
+
"WORKRAIL_ENABLE_LEAN_WORKFLOWS": "false",
|
|
66
|
+
"WORKRAIL_AUTHORITATIVE_DESCRIPTIONS": "false",
|
|
67
|
+
"WORKRAIL_ENABLE_V2_TOOLS": "true",
|
|
68
|
+
"WORKRAIL_CLEAN_RESPONSE_FORMAT": "false",
|
|
69
|
+
|
|
70
|
+
"WORKFLOW_STORAGE_PATH": "",
|
|
71
|
+
"WORKFLOW_GIT_REPOS": "",
|
|
72
|
+
"WORKFLOW_GIT_REPO_URL": "",
|
|
73
|
+
"WORKFLOW_GIT_REPO_BRANCH": "main",
|
|
74
|
+
"WORKFLOW_GIT_SYNC_INTERVAL": "60",
|
|
75
|
+
|
|
76
|
+
"WORKRAIL_LOG_LEVEL": "SILENT",
|
|
77
|
+
"WORKRAIL_LOG_FORMAT": "human",
|
|
78
|
+
"WORKRAIL_DATA_DIR": "",
|
|
79
|
+
"WORKRAIL_CACHE_DIR": "",
|
|
80
|
+
|
|
81
|
+
"WORKRAIL_JSON_RESPONSES": "false"
|
|
82
|
+
}
|
|
83
|
+
`;
|
|
84
|
+
async function executeInitConfigCommand(deps) {
|
|
85
|
+
const configDir = deps.joinPath(deps.homedir(), '.workrail');
|
|
86
|
+
const configPath = deps.joinPath(configDir, 'config.json');
|
|
87
|
+
try {
|
|
88
|
+
const existing = await deps.readFile(configPath);
|
|
89
|
+
return (0, cli_result_js_1.success)({
|
|
90
|
+
message: `Config file already exists at ${configPath}`,
|
|
91
|
+
details: [
|
|
92
|
+
'Current contents:',
|
|
93
|
+
existing,
|
|
94
|
+
'(File was not modified. Delete it and re-run to regenerate the template.)',
|
|
95
|
+
],
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
await deps.mkdir(configDir, { recursive: true });
|
|
102
|
+
await deps.writeFile(configPath, CONFIG_FILE_TEMPLATE);
|
|
103
|
+
return (0, cli_result_js_1.success)({
|
|
104
|
+
message: `Config file written to ${configPath}`,
|
|
105
|
+
details: [
|
|
106
|
+
'Edit the file to set your preferred defaults.',
|
|
107
|
+
'Environment variables always override values in this file.',
|
|
108
|
+
'Sensitive values (tokens, keys) must still be set as environment variables.',
|
|
109
|
+
],
|
|
110
|
+
suggestions: [
|
|
111
|
+
`Edit: ${configPath}`,
|
|
112
|
+
'Documentation: workrail docs configuration',
|
|
113
|
+
],
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
return (0, cli_result_js_1.failure)(`Failed to write config file: ${error instanceof Error ? error.message : String(error)}`, {
|
|
118
|
+
suggestions: ['Check that you have write permissions to your home directory'],
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
package/dist/cli.js
CHANGED
|
@@ -26,7 +26,19 @@ program
|
|
|
26
26
|
program
|
|
27
27
|
.command('init')
|
|
28
28
|
.description('Initialize user workflow directory with sample workflows')
|
|
29
|
-
.
|
|
29
|
+
.option('--config', 'Write a ~/.workrail/config.json template instead of initializing workflows')
|
|
30
|
+
.action(async (options) => {
|
|
31
|
+
if (options.config) {
|
|
32
|
+
const result = await (0, index_js_1.executeInitConfigCommand)({
|
|
33
|
+
mkdir: (p, opts) => fs_1.default.promises.mkdir(p, opts),
|
|
34
|
+
readFile: (p) => fs_1.default.promises.readFile(p, 'utf-8'),
|
|
35
|
+
writeFile: (p, content) => fs_1.default.promises.writeFile(p, content, 'utf-8'),
|
|
36
|
+
homedir: os_1.default.homedir,
|
|
37
|
+
joinPath: path_1.default.join,
|
|
38
|
+
});
|
|
39
|
+
(0, interpret_result_js_1.interpretCliResultWithoutDI)(result);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
30
42
|
const result = await (0, index_js_1.executeInitCommand)({
|
|
31
43
|
mkdir: (p, opts) => fs_1.default.promises.mkdir(p, opts),
|
|
32
44
|
readdir: (p) => fs_1.default.promises.readdir(p),
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Result } from '../runtime/result.js';
|
|
2
|
+
export type ConfigFileError = {
|
|
3
|
+
readonly _tag: 'ConfigFileError';
|
|
4
|
+
readonly message: string;
|
|
5
|
+
readonly cause?: unknown;
|
|
6
|
+
};
|
|
7
|
+
export declare function ensureWorkrailConfigFile(): void;
|
|
8
|
+
export declare function loadWorkrailConfigFile(): Result<Record<string, string>, ConfigFileError>;
|
|
@@ -0,0 +1,141 @@
|
|
|
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
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.ensureWorkrailConfigFile = ensureWorkrailConfigFile;
|
|
37
|
+
exports.loadWorkrailConfigFile = loadWorkrailConfigFile;
|
|
38
|
+
const os = __importStar(require("os"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const zod_1 = require("zod");
|
|
42
|
+
const result_js_1 = require("../runtime/result.js");
|
|
43
|
+
const ALLOWED_CONFIG_FILE_KEYS = new Set([
|
|
44
|
+
'CACHE_TTL',
|
|
45
|
+
'WORKRAIL_WORKFLOWS_DIR',
|
|
46
|
+
'WORKRAIL_DISABLE_UNIFIED_DASHBOARD',
|
|
47
|
+
'WORKRAIL_DISABLE_AUTO_OPEN',
|
|
48
|
+
'WORKRAIL_DASHBOARD_PORT',
|
|
49
|
+
'WORKRAIL_DEV',
|
|
50
|
+
'WORKRAIL_ENABLE_SESSION_TOOLS',
|
|
51
|
+
'WORKRAIL_ENABLE_EXPERIMENTAL_WORKFLOWS',
|
|
52
|
+
'WORKRAIL_VERBOSE_LOGGING',
|
|
53
|
+
'WORKRAIL_ENABLE_AGENTIC_ROUTINES',
|
|
54
|
+
'WORKRAIL_ENABLE_LEAN_WORKFLOWS',
|
|
55
|
+
'WORKRAIL_AUTHORITATIVE_DESCRIPTIONS',
|
|
56
|
+
'WORKRAIL_ENABLE_V2_TOOLS',
|
|
57
|
+
'WORKRAIL_CLEAN_RESPONSE_FORMAT',
|
|
58
|
+
'WORKFLOW_STORAGE_PATH',
|
|
59
|
+
'WORKFLOW_GIT_REPOS',
|
|
60
|
+
'WORKFLOW_GIT_REPO_URL',
|
|
61
|
+
'WORKFLOW_GIT_REPO_BRANCH',
|
|
62
|
+
'WORKFLOW_GIT_SYNC_INTERVAL',
|
|
63
|
+
'WORKRAIL_LOG_LEVEL',
|
|
64
|
+
'WORKRAIL_LOG_FORMAT',
|
|
65
|
+
'WORKRAIL_DATA_DIR',
|
|
66
|
+
'WORKRAIL_CACHE_DIR',
|
|
67
|
+
'WORKRAIL_JSON_RESPONSES',
|
|
68
|
+
]);
|
|
69
|
+
const ConfigFileSchema = zod_1.z.record(zod_1.z.string(), zod_1.z.string());
|
|
70
|
+
const CONFIG_FILE_TEMPLATE = `{
|
|
71
|
+
"_comment": "WorkRail configuration. Values here are defaults; process.env always wins.",
|
|
72
|
+
"_docs": "https://github.com/exaudeus/workrail/blob/main/docs/configuration.md",
|
|
73
|
+
|
|
74
|
+
"CACHE_TTL": "300000",
|
|
75
|
+
"WORKRAIL_ENABLE_SESSION_TOOLS": "true",
|
|
76
|
+
"WORKRAIL_ENABLE_AGENTIC_ROUTINES": "true",
|
|
77
|
+
"WORKRAIL_ENABLE_V2_TOOLS": "true",
|
|
78
|
+
"WORKRAIL_ENABLE_LEAN_WORKFLOWS": "false",
|
|
79
|
+
"WORKRAIL_AUTHORITATIVE_DESCRIPTIONS": "false",
|
|
80
|
+
"WORKRAIL_CLEAN_RESPONSE_FORMAT": "false",
|
|
81
|
+
"WORKRAIL_VERBOSE_LOGGING": "false",
|
|
82
|
+
|
|
83
|
+
"WORKFLOW_STORAGE_PATH": "",
|
|
84
|
+
"WORKFLOW_GIT_REPOS": "",
|
|
85
|
+
|
|
86
|
+
"WORKRAIL_LOG_LEVEL": "SILENT",
|
|
87
|
+
"WORKRAIL_LOG_FORMAT": "human"
|
|
88
|
+
}
|
|
89
|
+
`;
|
|
90
|
+
function ensureWorkrailConfigFile() {
|
|
91
|
+
if (process.env['VITEST'])
|
|
92
|
+
return;
|
|
93
|
+
const configPath = path.join(os.homedir(), '.workrail', 'config.json');
|
|
94
|
+
try {
|
|
95
|
+
fs.accessSync(configPath);
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
try {
|
|
99
|
+
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
100
|
+
fs.writeFileSync(configPath, CONFIG_FILE_TEMPLATE, 'utf-8');
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function loadWorkrailConfigFile() {
|
|
107
|
+
const configPath = path.join(os.homedir(), '.workrail', 'config.json');
|
|
108
|
+
let rawContent;
|
|
109
|
+
try {
|
|
110
|
+
rawContent = fs.readFileSync(configPath, 'utf-8');
|
|
111
|
+
}
|
|
112
|
+
catch (e) {
|
|
113
|
+
const code = e.code;
|
|
114
|
+
if (code !== 'ENOENT') {
|
|
115
|
+
console.warn(`[WorkRail] Could not read config file at ${configPath}: ${e.message}`);
|
|
116
|
+
}
|
|
117
|
+
return (0, result_js_1.ok)({});
|
|
118
|
+
}
|
|
119
|
+
let parsed;
|
|
120
|
+
try {
|
|
121
|
+
parsed = JSON.parse(rawContent);
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
console.warn(`[WorkRail] config file at ${configPath} contains invalid JSON -- ignoring it. Fix or regenerate with "workrail init --config".`);
|
|
125
|
+
return (0, result_js_1.ok)({});
|
|
126
|
+
}
|
|
127
|
+
const result = ConfigFileSchema.safeParse(parsed);
|
|
128
|
+
if (!result.success) {
|
|
129
|
+
console.warn(`[WorkRail] config file at ${configPath} has an unexpected shape -- ignoring it. Expected a flat JSON object with string values.`);
|
|
130
|
+
return (0, result_js_1.ok)({});
|
|
131
|
+
}
|
|
132
|
+
const validated = {};
|
|
133
|
+
for (const [key, value] of Object.entries(result.data)) {
|
|
134
|
+
if (!ALLOWED_CONFIG_FILE_KEYS.has(key)) {
|
|
135
|
+
console.warn(`[WorkRail] config file: unknown key "${key}" -- ignored. See "workrail init --config" for supported keys.`);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
validated[key] = value;
|
|
139
|
+
}
|
|
140
|
+
return (0, result_js_1.ok)(validated);
|
|
141
|
+
}
|
|
@@ -77,6 +77,14 @@ exports.FEATURE_FLAG_DEFINITIONS = [
|
|
|
77
77
|
since: '0.11.0',
|
|
78
78
|
stable: false,
|
|
79
79
|
},
|
|
80
|
+
{
|
|
81
|
+
key: 'devMode',
|
|
82
|
+
envVar: 'WORKRAIL_DEV',
|
|
83
|
+
defaultValue: false,
|
|
84
|
+
description: 'Enable development features: staleness visibility for all workflow categories, structured tool-call timing on stderr, and /api/v2/perf/tool-calls endpoint',
|
|
85
|
+
since: '0.11.0',
|
|
86
|
+
stable: false,
|
|
87
|
+
},
|
|
80
88
|
];
|
|
81
89
|
function parseBoolean(value, defaultValue) {
|
|
82
90
|
if (value === undefined) {
|