@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
package/dist/mcp/server.js
CHANGED
|
@@ -47,6 +47,8 @@ const workspace_roots_manager_js_1 = require("./workspace-roots-manager.js");
|
|
|
47
47
|
const index_js_2 = require("../v2/infra/local/directory-listing/index.js");
|
|
48
48
|
const index_js_3 = require("../v2/infra/local/session-summary-provider/index.js");
|
|
49
49
|
const tool_factory_js_1 = require("./tool-factory.js");
|
|
50
|
+
const dev_mode_js_1 = require("./dev-mode.js");
|
|
51
|
+
const tool_call_timing_js_1 = require("./tool-call-timing.js");
|
|
50
52
|
const handler_factory_js_1 = require("./handler-factory.js");
|
|
51
53
|
const workflow_tool_edition_selector_js_1 = require("./workflow-tool-edition-selector.js");
|
|
52
54
|
const tools_js_1 = require("./tools.js");
|
|
@@ -159,8 +161,9 @@ function toMcpTool(tool) {
|
|
|
159
161
|
};
|
|
160
162
|
}
|
|
161
163
|
async function composeServer() {
|
|
162
|
-
await (0, container_js_1.bootstrap)(
|
|
164
|
+
await (0, container_js_1.bootstrap)();
|
|
163
165
|
const ctx = await createToolContext();
|
|
166
|
+
const timingRingBuffer = new tool_call_timing_js_1.ToolCallTimingRingBuffer(tool_call_timing_js_1.DEFAULT_RING_BUFFER_CAPACITY);
|
|
164
167
|
if (ctx.v2 && ctx.httpServer && ctx.v2.dataDir && ctx.v2.directoryListing) {
|
|
165
168
|
const { ConsoleService } = await Promise.resolve().then(() => __importStar(require('../v2/usecases/console-service.js')));
|
|
166
169
|
const { mountConsoleRoutes } = await Promise.resolve().then(() => __importStar(require('../v2/usecases/console-routes.js')));
|
|
@@ -171,7 +174,7 @@ async function composeServer() {
|
|
|
171
174
|
snapshotStore: ctx.v2.snapshotStore,
|
|
172
175
|
pinnedWorkflowStore: ctx.v2.pinnedStore,
|
|
173
176
|
});
|
|
174
|
-
ctx.httpServer.mountRoutes((app) => mountConsoleRoutes(app, consoleService));
|
|
177
|
+
ctx.httpServer.mountRoutes((app) => mountConsoleRoutes(app, consoleService, ctx.workflowService, timingRingBuffer));
|
|
175
178
|
console.error('[Console] v2 Console API routes mounted at /api/v2/');
|
|
176
179
|
}
|
|
177
180
|
ctx.httpServer?.finalize();
|
|
@@ -190,13 +193,14 @@ async function composeServer() {
|
|
|
190
193
|
}
|
|
191
194
|
const rootsManager = new workspace_roots_manager_js_1.WorkspaceRootsManager();
|
|
192
195
|
const { Server } = await Promise.resolve().then(() => __importStar(require('@modelcontextprotocol/sdk/server/index.js')));
|
|
193
|
-
const { CallToolRequestSchema, ListToolsRequestSchema, } = await Promise.resolve().then(() => __importStar(require('@modelcontextprotocol/sdk/types.js')));
|
|
196
|
+
const { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, } = await Promise.resolve().then(() => __importStar(require('@modelcontextprotocol/sdk/types.js')));
|
|
194
197
|
const server = new Server({
|
|
195
198
|
name: 'workrail-server',
|
|
196
199
|
version: '0.1.0',
|
|
197
200
|
}, {
|
|
198
201
|
capabilities: {
|
|
199
202
|
tools: {},
|
|
203
|
+
resources: {},
|
|
200
204
|
},
|
|
201
205
|
});
|
|
202
206
|
const tools = workflowEdition.tools.map(toMcpTool);
|
|
@@ -213,19 +217,80 @@ async function composeServer() {
|
|
|
213
217
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
214
218
|
tools,
|
|
215
219
|
}));
|
|
220
|
+
const timingSink = dev_mode_js_1.DEV_MODE
|
|
221
|
+
? (0, tool_call_timing_js_1.composeSinks)((0, tool_call_timing_js_1.createRingBufferSink)(timingRingBuffer), (0, tool_call_timing_js_1.createDevPerfSink)())
|
|
222
|
+
: (0, tool_call_timing_js_1.createRingBufferSink)(timingRingBuffer);
|
|
223
|
+
if (dev_mode_js_1.DEV_MODE) {
|
|
224
|
+
console.error('[PerfTrace] WORKRAIL_DEV=1 -- tool call timing active');
|
|
225
|
+
}
|
|
216
226
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
217
227
|
const { name, arguments: args } = request.params;
|
|
228
|
+
const handlerStartMs = Date.now();
|
|
229
|
+
const handlerStartHr = performance.now();
|
|
218
230
|
const handler = handlers[name];
|
|
219
231
|
if (!handler) {
|
|
220
|
-
|
|
232
|
+
const unknownResult = {
|
|
221
233
|
content: [{ type: 'text', text: `Unknown tool: ${name}` }],
|
|
222
234
|
isError: true,
|
|
223
235
|
};
|
|
236
|
+
const durationMs = Math.round((performance.now() - handlerStartHr) * 100) / 100;
|
|
237
|
+
try {
|
|
238
|
+
timingSink({ toolName: name ?? '(unknown)', startedAtMs: handlerStartMs, durationMs, outcome: 'unknown_tool' });
|
|
239
|
+
}
|
|
240
|
+
catch {
|
|
241
|
+
}
|
|
242
|
+
return unknownResult;
|
|
224
243
|
}
|
|
225
244
|
const requestCtx = ctx.v2
|
|
226
245
|
? { ...ctx, v2: { ...ctx.v2, resolvedRootUris: rootsManager.getCurrentRootUris() } }
|
|
227
246
|
: ctx;
|
|
228
|
-
return handler(args ?? {}, requestCtx);
|
|
247
|
+
return (0, tool_call_timing_js_1.withToolCallTiming)(name, () => handler(args ?? {}, requestCtx), timingSink);
|
|
248
|
+
});
|
|
249
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => ({
|
|
250
|
+
resources: [
|
|
251
|
+
{
|
|
252
|
+
uri: 'workrail://tags',
|
|
253
|
+
name: 'WorkRail Tag Catalog',
|
|
254
|
+
description: 'Closed-set tag definitions for workflow discovery. ' +
|
|
255
|
+
'Read this before calling list_workflows — it tells you which tags exist ' +
|
|
256
|
+
'and when to use each one, so you can call list_workflows with tags=[...] ' +
|
|
257
|
+
'instead of loading all 36+ workflows into context.',
|
|
258
|
+
mimeType: 'application/json',
|
|
259
|
+
},
|
|
260
|
+
],
|
|
261
|
+
}));
|
|
262
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
263
|
+
const uri = request.params?.uri ?? '';
|
|
264
|
+
if (uri !== 'workrail://tags') {
|
|
265
|
+
return {
|
|
266
|
+
contents: [],
|
|
267
|
+
isError: true,
|
|
268
|
+
_meta: { error: `Unknown resource: ${uri}` },
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
try {
|
|
272
|
+
const fs = await Promise.resolve().then(() => __importStar(require('fs')));
|
|
273
|
+
const path = await Promise.resolve().then(() => __importStar(require('path')));
|
|
274
|
+
const tagsPath = path.resolve(__dirname, '../../spec/workflow-tags.json');
|
|
275
|
+
const raw = fs.readFileSync(tagsPath, 'utf-8');
|
|
276
|
+
return {
|
|
277
|
+
contents: [
|
|
278
|
+
{
|
|
279
|
+
uri: 'workrail://tags',
|
|
280
|
+
mimeType: 'application/json',
|
|
281
|
+
text: raw,
|
|
282
|
+
},
|
|
283
|
+
],
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
catch (err) {
|
|
287
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
288
|
+
return {
|
|
289
|
+
contents: [],
|
|
290
|
+
isError: true,
|
|
291
|
+
_meta: { error: `Failed to read tag catalog: ${message}` },
|
|
292
|
+
};
|
|
293
|
+
}
|
|
229
294
|
});
|
|
230
295
|
return { server, ctx, rootsManager, rootsReader: rootsManager, tools, handlers };
|
|
231
296
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type ToolCallOutcome = 'success' | 'error' | 'unknown_tool';
|
|
2
|
+
export interface ToolCallTiming {
|
|
3
|
+
readonly toolName: string;
|
|
4
|
+
readonly startedAtMs: number;
|
|
5
|
+
readonly durationMs: number;
|
|
6
|
+
readonly outcome: ToolCallOutcome;
|
|
7
|
+
}
|
|
8
|
+
export type ToolCallTimingSink = (timing: ToolCallTiming) => void;
|
|
9
|
+
export declare const noopToolCallTimingSink: ToolCallTimingSink;
|
|
10
|
+
export declare class ToolCallTimingRingBuffer {
|
|
11
|
+
private readonly capacity;
|
|
12
|
+
private readonly buffer;
|
|
13
|
+
private head;
|
|
14
|
+
private count;
|
|
15
|
+
constructor(capacity: number);
|
|
16
|
+
push(timing: ToolCallTiming): void;
|
|
17
|
+
recent(limit?: number): readonly ToolCallTiming[];
|
|
18
|
+
get size(): number;
|
|
19
|
+
}
|
|
20
|
+
export declare const DEFAULT_RING_BUFFER_CAPACITY = 100;
|
|
21
|
+
export declare function createRingBufferSink(buffer: ToolCallTimingRingBuffer): ToolCallTimingSink;
|
|
22
|
+
export declare function createDevPerfSink(): ToolCallTimingSink;
|
|
23
|
+
export declare function composeSinks(...sinks: ToolCallTimingSink[]): ToolCallTimingSink;
|
|
24
|
+
export declare function withToolCallTiming<T>(toolName: string, handler: () => Promise<T>, sink: ToolCallTimingSink): Promise<T>;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_RING_BUFFER_CAPACITY = exports.ToolCallTimingRingBuffer = exports.noopToolCallTimingSink = void 0;
|
|
4
|
+
exports.createRingBufferSink = createRingBufferSink;
|
|
5
|
+
exports.createDevPerfSink = createDevPerfSink;
|
|
6
|
+
exports.composeSinks = composeSinks;
|
|
7
|
+
exports.withToolCallTiming = withToolCallTiming;
|
|
8
|
+
const noopToolCallTimingSink = () => { };
|
|
9
|
+
exports.noopToolCallTimingSink = noopToolCallTimingSink;
|
|
10
|
+
class ToolCallTimingRingBuffer {
|
|
11
|
+
constructor(capacity) {
|
|
12
|
+
this.capacity = capacity;
|
|
13
|
+
this.head = 0;
|
|
14
|
+
this.count = 0;
|
|
15
|
+
if (capacity < 1)
|
|
16
|
+
throw new Error('Ring buffer capacity must be >= 1');
|
|
17
|
+
this.buffer = new Array(capacity).fill(undefined);
|
|
18
|
+
}
|
|
19
|
+
push(timing) {
|
|
20
|
+
this.buffer[this.head] = timing;
|
|
21
|
+
this.head = (this.head + 1) % this.capacity;
|
|
22
|
+
if (this.count < this.capacity)
|
|
23
|
+
this.count++;
|
|
24
|
+
}
|
|
25
|
+
recent(limit) {
|
|
26
|
+
const n = limit !== undefined ? Math.min(limit, this.count) : this.count;
|
|
27
|
+
const results = [];
|
|
28
|
+
for (let i = 1; i <= n; i++) {
|
|
29
|
+
const idx = (this.head - i + this.capacity) % this.capacity;
|
|
30
|
+
const entry = this.buffer[idx];
|
|
31
|
+
if (entry !== undefined)
|
|
32
|
+
results.push(entry);
|
|
33
|
+
}
|
|
34
|
+
return results;
|
|
35
|
+
}
|
|
36
|
+
get size() {
|
|
37
|
+
return this.count;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.ToolCallTimingRingBuffer = ToolCallTimingRingBuffer;
|
|
41
|
+
exports.DEFAULT_RING_BUFFER_CAPACITY = 100;
|
|
42
|
+
function createRingBufferSink(buffer) {
|
|
43
|
+
return (timing) => {
|
|
44
|
+
buffer.push(timing);
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function createDevPerfSink() {
|
|
48
|
+
return (timing) => {
|
|
49
|
+
const outcomeLabel = timing.outcome === 'success' ? 'OK' : timing.outcome.toUpperCase();
|
|
50
|
+
const line = `[PerfTrace] ${timing.toolName} ${timing.durationMs.toFixed(1)}ms [${outcomeLabel}]`;
|
|
51
|
+
console.error(line);
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function composeSinks(...sinks) {
|
|
55
|
+
return (timing) => {
|
|
56
|
+
for (const sink of sinks) {
|
|
57
|
+
try {
|
|
58
|
+
sink(timing);
|
|
59
|
+
}
|
|
60
|
+
catch { }
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
async function withToolCallTiming(toolName, handler, sink) {
|
|
65
|
+
const startedAtMs = Date.now();
|
|
66
|
+
const startHr = performance.now();
|
|
67
|
+
let outcome = 'error';
|
|
68
|
+
try {
|
|
69
|
+
const result = await handler();
|
|
70
|
+
outcome = result?.isError === true ? 'error' : 'success';
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
outcome = 'error';
|
|
75
|
+
throw err;
|
|
76
|
+
}
|
|
77
|
+
finally {
|
|
78
|
+
const durationMs = Math.round((performance.now() - startHr) * 100) / 100;
|
|
79
|
+
try {
|
|
80
|
+
sink({ toolName, startedAtMs, durationMs, outcome });
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -48,12 +48,17 @@ This tool provides:
|
|
|
48
48
|
- Field descriptions and validation rules
|
|
49
49
|
- Examples of valid patterns and formats
|
|
50
50
|
- Schema version and metadata information`,
|
|
51
|
-
list_workflows: `Lists available workflows
|
|
51
|
+
list_workflows: `Lists available workflows. When a workflow exists for the user's request, following it means following the user's structured instructions.
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
Discovery pattern (token-efficient — do this):
|
|
54
|
+
- Preferred: read the workrail://tags MCP resource — tag definitions with no tool call.
|
|
55
|
+
- Or: call with no tags → returns tagSummary (~500 tokens) with when-to-use phrases per tag.
|
|
56
|
+
- Then: call with tags=["<tagId>"] → returns the filtered workflow list for that tag.
|
|
57
|
+
- Shortcut: if a workflow ID in tagSummary examples[] already matches, call start_workflow directly — skip the second list call.
|
|
58
|
+
- Multiple tags: if more than one tag fits, pick the most specific one.
|
|
54
59
|
|
|
55
|
-
Always pass workspacePath so project-scoped workflow variants are resolved against the correct workspace
|
|
56
|
-
inspect_workflow: `Inspect a workflow structure before starting it
|
|
60
|
+
Always pass workspacePath so project-scoped workflow variants are resolved against the correct workspace. Shared MCP servers cannot infer this safely.`,
|
|
61
|
+
inspect_workflow: `Inspect a workflow structure before starting it.
|
|
57
62
|
|
|
58
63
|
Use this to understand what steps the workflow will guide you through. The workflow is a step-by-step plan the user (or workflow author) created for this type of task.
|
|
59
64
|
|
|
@@ -139,14 +144,17 @@ Returns validation result with specific errors and suggestions if invalid.`,
|
|
|
139
144
|
get_workflow_schema: `Get the workflow JSON schema for creating or editing workflows.
|
|
140
145
|
|
|
141
146
|
Returns the complete schema definition including required fields, valid patterns, and constraints. Use this as reference when authoring workflow JSON.`,
|
|
142
|
-
list_workflows: `
|
|
147
|
+
list_workflows: `Lists available workflows. When a workflow exists for the user's request, you MUST use it instead of improvising your own approach.
|
|
143
148
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
149
|
+
Discovery pattern (token-efficient — do this):
|
|
150
|
+
- Preferred: read the workrail://tags MCP resource — tag definitions with no tool call.
|
|
151
|
+
- Or: call with no tags → returns tagSummary (~500 tokens) with when-to-use phrases per tag.
|
|
152
|
+
- Then: call with tags=["<tagId>"] → returns the filtered workflow list for that tag.
|
|
153
|
+
- Shortcut: if a workflow ID in tagSummary examples[] already matches, call start_workflow directly — skip the second list call.
|
|
154
|
+
- Multiple tags: if more than one tag fits, pick the most specific one.
|
|
147
155
|
|
|
148
156
|
Pass workspacePath on every call so project-scoped workflow variants are resolved against the correct workspace. Shared MCP servers cannot infer this safely.`,
|
|
149
|
-
inspect_workflow: `Inspect a workflow you are considering following
|
|
157
|
+
inspect_workflow: `Inspect a workflow you are considering following.
|
|
150
158
|
|
|
151
159
|
Use this to understand the workflow's structure before starting. The workflow is the user's explicit plan - not suggestions, not guidelines, but direct instructions you will follow.
|
|
152
160
|
|
|
@@ -42,9 +42,11 @@ const http_listener_js_1 = require("./http-listener.js");
|
|
|
42
42
|
const shutdown_hooks_js_1 = require("./shutdown-hooks.js");
|
|
43
43
|
const crypto = __importStar(require("crypto"));
|
|
44
44
|
const express_1 = __importDefault(require("express"));
|
|
45
|
+
const HTTP_PORT_SCAN_END = 3199;
|
|
45
46
|
async function startHttpServer(port) {
|
|
46
47
|
const { server, ctx } = await (0, server_js_1.composeServer)();
|
|
47
|
-
const
|
|
48
|
+
const scanEnd = Math.max(port, HTTP_PORT_SCAN_END);
|
|
49
|
+
const listener = await (0, http_listener_js_1.bindWithPortFallback)(port, scanEnd);
|
|
48
50
|
const { StreamableHTTPServerTransport } = await Promise.resolve().then(() => __importStar(require('@modelcontextprotocol/sdk/server/streamableHttp.js')));
|
|
49
51
|
const transport = new StreamableHTTPServerTransport({
|
|
50
52
|
sessionIdGenerator: () => crypto.randomUUID(),
|
|
@@ -54,7 +56,6 @@ async function startHttpServer(port) {
|
|
|
54
56
|
listener.app.post('/mcp', (req, res) => transport.handleRequest(req, res, req.body));
|
|
55
57
|
listener.app.get('/mcp', (req, res) => transport.handleRequest(req, res));
|
|
56
58
|
listener.app.delete('/mcp', (req, res) => transport.handleRequest(req, res));
|
|
57
|
-
await listener.start();
|
|
58
59
|
await server.connect(transport);
|
|
59
60
|
const boundPort = listener.getBoundPort();
|
|
60
61
|
console.error('[Transport] WorkRail MCP Server running on HTTP');
|
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.createHttpListener = createHttpListener;
|
|
7
|
+
exports.bindWithPortFallback = bindWithPortFallback;
|
|
7
8
|
const express_1 = __importDefault(require("express"));
|
|
8
9
|
const http_1 = require("http");
|
|
9
10
|
function createHttpListener(requestedPort) {
|
|
@@ -62,3 +63,27 @@ function createHttpListener(requestedPort) {
|
|
|
62
63
|
},
|
|
63
64
|
};
|
|
64
65
|
}
|
|
66
|
+
async function bindWithPortFallback(startPort, endPort) {
|
|
67
|
+
let lastError;
|
|
68
|
+
for (let port = startPort; port <= endPort; port++) {
|
|
69
|
+
const listener = createHttpListener(port);
|
|
70
|
+
try {
|
|
71
|
+
await listener.start();
|
|
72
|
+
if (port !== startPort) {
|
|
73
|
+
console.error(`[HttpListener] Port ${startPort} unavailable; bound to fallback port ${port}`);
|
|
74
|
+
}
|
|
75
|
+
return listener;
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
const nodeErr = err;
|
|
79
|
+
if (nodeErr.code === 'EADDRINUSE' ||
|
|
80
|
+
(err instanceof Error && err.message.includes('already in use'))) {
|
|
81
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
throw err;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
throw new Error(`[HttpListener] No available port in range ${startPort}-${endPort}. ` +
|
|
88
|
+
`Last error: ${lastError?.message}`);
|
|
89
|
+
}
|
|
@@ -2,4 +2,7 @@ export interface ShutdownHookOptions {
|
|
|
2
2
|
readonly onBeforeTerminate: () => Promise<void>;
|
|
3
3
|
}
|
|
4
4
|
export declare function wireShutdownHooks(opts: ShutdownHookOptions): void;
|
|
5
|
-
export
|
|
5
|
+
export interface StdinShutdownOptions {
|
|
6
|
+
readonly stdin?: NodeJS.ReadableStream;
|
|
7
|
+
}
|
|
8
|
+
export declare function wireStdinShutdown(opts?: StdinShutdownOptions): void;
|
|
@@ -29,9 +29,10 @@ function wireShutdownHooks(opts) {
|
|
|
29
29
|
})();
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
|
-
function wireStdinShutdown() {
|
|
32
|
+
function wireStdinShutdown(opts) {
|
|
33
33
|
const shutdownEvents = container_js_1.container.resolve(tokens_js_1.DI.Runtime.ShutdownEvents);
|
|
34
|
-
|
|
34
|
+
const stdin = opts?.stdin ?? process.stdin;
|
|
35
|
+
stdin.once('end', () => {
|
|
35
36
|
console.error('[MCP] stdin closed, initiating shutdown');
|
|
36
37
|
shutdownEvents.emit({ kind: 'shutdown_requested', signal: 'SIGHUP' });
|
|
37
38
|
});
|
|
@@ -35,8 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.startStdioServer = startStdioServer;
|
|
37
37
|
const server_js_1 = require("../server.js");
|
|
38
|
-
const
|
|
39
|
-
const tokens_js_1 = require("../../di/tokens.js");
|
|
38
|
+
const shutdown_hooks_js_1 = require("./shutdown-hooks.js");
|
|
40
39
|
const INITIAL_ROOTS_TIMEOUT_MS = 1000;
|
|
41
40
|
async function fetchInitialRootsWithTimeout(server) {
|
|
42
41
|
return Promise.race([
|
|
@@ -75,31 +74,10 @@ async function startStdioServer() {
|
|
|
75
74
|
.catch(() => {
|
|
76
75
|
console.error('[Roots] Client does not support roots/list; workspace context will use server CWD fallback');
|
|
77
76
|
});
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
processSignals.on('SIGHUP', () => shutdownEvents.emit({ kind: 'shutdown_requested', signal: 'SIGHUP' }));
|
|
84
|
-
process.stdin.on('end', () => {
|
|
85
|
-
console.error('[MCP] stdin closed, initiating shutdown');
|
|
86
|
-
shutdownEvents.emit({ kind: 'shutdown_requested', signal: 'SIGHUP' });
|
|
87
|
-
});
|
|
88
|
-
let shutdownStarted = false;
|
|
89
|
-
shutdownEvents.onShutdown((event) => {
|
|
90
|
-
if (shutdownStarted)
|
|
91
|
-
return;
|
|
92
|
-
shutdownStarted = true;
|
|
93
|
-
void (async () => {
|
|
94
|
-
try {
|
|
95
|
-
console.error(`[Shutdown] Requested by ${event.signal}. Stopping services...`);
|
|
96
|
-
await ctx.httpServer?.stop();
|
|
97
|
-
terminator.terminate({ kind: 'success' });
|
|
98
|
-
}
|
|
99
|
-
catch (err) {
|
|
100
|
-
console.error('[Shutdown] Error while stopping services:', err);
|
|
101
|
-
terminator.terminate({ kind: 'failure' });
|
|
102
|
-
}
|
|
103
|
-
})();
|
|
77
|
+
(0, shutdown_hooks_js_1.wireStdinShutdown)();
|
|
78
|
+
(0, shutdown_hooks_js_1.wireShutdownHooks)({
|
|
79
|
+
onBeforeTerminate: async () => {
|
|
80
|
+
await ctx.httpServer?.stop();
|
|
81
|
+
},
|
|
104
82
|
});
|
|
105
83
|
}
|
package/dist/mcp/v2/tools.d.ts
CHANGED
|
@@ -3,12 +3,15 @@ import type { ToolAnnotations } from '../tool-factory.js';
|
|
|
3
3
|
export declare const V2ListWorkflowsInput: z.ZodObject<{
|
|
4
4
|
workspacePath: z.ZodEffects<z.ZodString, string, string>;
|
|
5
5
|
includeSources: z.ZodOptional<z.ZodBoolean>;
|
|
6
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
6
7
|
}, "strip", z.ZodTypeAny, {
|
|
7
8
|
workspacePath: string;
|
|
8
9
|
includeSources?: boolean | undefined;
|
|
10
|
+
tags?: string[] | undefined;
|
|
9
11
|
}, {
|
|
10
12
|
workspacePath: string;
|
|
11
13
|
includeSources?: boolean | undefined;
|
|
14
|
+
tags?: string[] | undefined;
|
|
12
15
|
}>;
|
|
13
16
|
export type V2ListWorkflowsInput = z.infer<typeof V2ListWorkflowsInput>;
|
|
14
17
|
export declare const V2InspectWorkflowInput: z.ZodObject<{
|
|
@@ -28,12 +31,15 @@ export type V2InspectWorkflowInput = z.infer<typeof V2InspectWorkflowInput>;
|
|
|
28
31
|
export declare const V2StartWorkflowInput: z.ZodObject<{
|
|
29
32
|
workflowId: z.ZodString;
|
|
30
33
|
workspacePath: z.ZodEffects<z.ZodString, string, string>;
|
|
34
|
+
goal: z.ZodString;
|
|
31
35
|
}, "strip", z.ZodTypeAny, {
|
|
32
36
|
workflowId: string;
|
|
33
37
|
workspacePath: string;
|
|
38
|
+
goal: string;
|
|
34
39
|
}, {
|
|
35
40
|
workflowId: string;
|
|
36
41
|
workspacePath: string;
|
|
42
|
+
goal: string;
|
|
37
43
|
}>;
|
|
38
44
|
export type V2StartWorkflowInput = z.infer<typeof V2StartWorkflowInput>;
|
|
39
45
|
export declare const V2ContinueWorkflowInputShape: z.ZodObject<{
|
package/dist/mcp/v2/tools.js
CHANGED
|
@@ -17,6 +17,7 @@ const optionalWorkspacePathField = workspacePathField.optional();
|
|
|
17
17
|
exports.V2ListWorkflowsInput = zod_1.z.object({
|
|
18
18
|
workspacePath: workspacePathField.describe('Required. Absolute path to your current workspace directory (e.g. the "Workspace:" value from your system parameters). WorkRail uses this to resolve project-scoped workflow variants against the correct workspace for discovery-sensitive workflow listing. Shared MCP servers cannot infer this safely.'),
|
|
19
19
|
includeSources: zod_1.z.boolean().optional().describe('When true, includes a source catalog in the response showing where workflows come from (built-in, project-scoped, rooted-sharing, external), with effective and shadowed workflow counts per source. Omit or set false for the default workflow-list-only response.'),
|
|
20
|
+
tags: zod_1.z.array(zod_1.z.string()).optional().describe('Filter by one or more domain tags (e.g. ["coding"], ["review_audit", "investigation"]). When present, returns the full workflow list for workflows matching any of the specified tags. When absent, returns a compact tagSummary instead of the full list — use this first to discover which tags exist, then call again with a specific tag. Valid tags: coding, review_audit, investigation, design, documentation, tickets, learning, routines, authoring.'),
|
|
20
21
|
});
|
|
21
22
|
exports.V2InspectWorkflowInput = zod_1.z.object({
|
|
22
23
|
workflowId: zod_1.z.string().min(1).regex(/^([a-z0-9_-]+|[a-z][a-z0-9_-]+\.[a-z][a-z0-9_-]+)$/, 'Workflow ID must be a valid legacy ID (e.g. my-workflow) or namespaced ID (e.g. wr.discovery)').describe('The workflow ID to inspect'),
|
|
@@ -26,6 +27,7 @@ exports.V2InspectWorkflowInput = zod_1.z.object({
|
|
|
26
27
|
exports.V2StartWorkflowInput = zod_1.z.object({
|
|
27
28
|
workflowId: zod_1.z.string().min(1).regex(/^([a-z0-9_-]+|[a-z][a-z0-9_-]+\.[a-z][a-z0-9_-]+)$/, 'Workflow ID must be a valid legacy ID (e.g. my-workflow) or namespaced ID (e.g. wr.discovery)').describe('The workflow ID to start'),
|
|
28
29
|
workspacePath: workspacePathField.describe('Required. Absolute path to your current workspace directory (e.g. the "Workspace:" value from your system parameters). WorkRail uses this to resolve the correct project-scoped workflow variant and to anchor the session to the correct repo for future resume_session discovery. Shared MCP servers cannot infer this safely.'),
|
|
30
|
+
goal: zod_1.z.string().min(1).describe('A short sentence describing what you are trying to accomplish (e.g. "implement OAuth refresh token rotation", "review PR #47 before merge", "investigate why the build fails on CI").'),
|
|
29
31
|
});
|
|
30
32
|
exports.V2ContinueWorkflowInputShape = zod_1.z.object({
|
|
31
33
|
workspacePath: optionalWorkspacePathField,
|
|
@@ -4,6 +4,7 @@ exports.formatV2ExecutionResponse = formatV2ExecutionResponse;
|
|
|
4
4
|
exports.formatV2ResumeResponse = formatV2ResumeResponse;
|
|
5
5
|
const render_envelope_js_1 = require("./render-envelope.js");
|
|
6
6
|
const response_supplements_js_1 = require("./response-supplements.js");
|
|
7
|
+
const env_flags_js_1 = require("../env-flags.js");
|
|
7
8
|
function isV2ExecutionResponse(data) {
|
|
8
9
|
if (typeof data !== 'object' || data === null)
|
|
9
10
|
return false;
|
|
@@ -216,9 +217,6 @@ function formatSuccess(data) {
|
|
|
216
217
|
}
|
|
217
218
|
return lines.join('\n');
|
|
218
219
|
}
|
|
219
|
-
function isCleanResponseFormat() {
|
|
220
|
-
return process.env.WORKRAIL_CLEAN_RESPONSE_FORMAT === 'true';
|
|
221
|
-
}
|
|
222
220
|
const CLEAN_ADVANCE_FOOTERS = [
|
|
223
221
|
'WorkRail: when done, call continue_workflow with your notes. Token:',
|
|
224
222
|
'WorkRail: advance with continue_workflow when ready. Include your notes. Token:',
|
|
@@ -354,7 +352,7 @@ function formatV2ExecutionResponse(data) {
|
|
|
354
352
|
const renderInput = deriveRenderInput(data);
|
|
355
353
|
if (!renderInput)
|
|
356
354
|
return null;
|
|
357
|
-
const cleanFormat =
|
|
355
|
+
const cleanFormat = env_flags_js_1.CLEAN_RESPONSE_FORMAT;
|
|
358
356
|
const { response, lifecycle, contentEnvelope } = renderInput;
|
|
359
357
|
const references = renderReferencesSection(contentEnvelope, lifecycle);
|
|
360
358
|
if (cleanFormat) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
export declare function getCachedShape(schema: z.ZodObject<z.ZodRawShape>): z.ZodRawShape;
|
|
2
3
|
export declare function extractExpectedKeys(schema: z.ZodType): readonly string[];
|
|
3
4
|
export declare function extractRequiredKeys(schema: z.ZodType): readonly string[];
|
|
4
5
|
export declare function findUnknownKeys(args: unknown, schema: z.ZodType): readonly string[];
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getCachedShape = getCachedShape;
|
|
3
4
|
exports.extractExpectedKeys = extractExpectedKeys;
|
|
4
5
|
exports.extractRequiredKeys = extractRequiredKeys;
|
|
5
6
|
exports.findUnknownKeys = findUnknownKeys;
|
|
@@ -8,9 +9,18 @@ exports.generateExampleValue = generateExampleValue;
|
|
|
8
9
|
exports.generateTemplate = generateTemplate;
|
|
9
10
|
exports.extractEnumValues = extractEnumValues;
|
|
10
11
|
const zod_1 = require("zod");
|
|
12
|
+
const shapeCache = new WeakMap();
|
|
13
|
+
function getCachedShape(schema) {
|
|
14
|
+
const cached = shapeCache.get(schema);
|
|
15
|
+
if (cached !== undefined)
|
|
16
|
+
return cached;
|
|
17
|
+
const shape = schema._def.shape();
|
|
18
|
+
shapeCache.set(schema, shape);
|
|
19
|
+
return shape;
|
|
20
|
+
}
|
|
11
21
|
function extractExpectedKeys(schema) {
|
|
12
22
|
if (schema instanceof zod_1.z.ZodObject) {
|
|
13
|
-
return Object.keys(schema
|
|
23
|
+
return Object.keys(getCachedShape(schema));
|
|
14
24
|
}
|
|
15
25
|
return [];
|
|
16
26
|
}
|
|
@@ -18,7 +28,7 @@ function extractRequiredKeys(schema) {
|
|
|
18
28
|
if (!(schema instanceof zod_1.z.ZodObject)) {
|
|
19
29
|
return [];
|
|
20
30
|
}
|
|
21
|
-
const shape = schema
|
|
31
|
+
const shape = getCachedShape(schema);
|
|
22
32
|
const required = [];
|
|
23
33
|
for (const [key, value] of Object.entries(shape)) {
|
|
24
34
|
const field = value;
|
|
@@ -55,7 +65,7 @@ function generateExampleValue(schema, depth = 0, maxDepth = 3, includeOptional =
|
|
|
55
65
|
return generateExampleValue(schema._def.innerType, depth, maxDepth, includeOptional);
|
|
56
66
|
}
|
|
57
67
|
if (schema instanceof zod_1.z.ZodObject) {
|
|
58
|
-
const shape = schema
|
|
68
|
+
const shape = getCachedShape(schema);
|
|
59
69
|
const result = {};
|
|
60
70
|
for (const [key, value] of Object.entries(shape)) {
|
|
61
71
|
const field = value;
|
|
@@ -124,7 +134,7 @@ function extractEnumValues(schema, path) {
|
|
|
124
134
|
let current = schema;
|
|
125
135
|
for (const part of parts) {
|
|
126
136
|
if (current instanceof zod_1.z.ZodObject) {
|
|
127
|
-
const shape = current
|
|
137
|
+
const shape = getCachedShape(current);
|
|
128
138
|
const field = shape[part];
|
|
129
139
|
if (!field)
|
|
130
140
|
return [];
|
|
@@ -133,7 +143,7 @@ function extractEnumValues(schema, path) {
|
|
|
133
143
|
else if (current instanceof zod_1.z.ZodOptional) {
|
|
134
144
|
current = current._def.innerType;
|
|
135
145
|
if (current instanceof zod_1.z.ZodObject) {
|
|
136
|
-
const shape = current
|
|
146
|
+
const shape = getCachedShape(current);
|
|
137
147
|
const field = shape[part];
|
|
138
148
|
if (!field)
|
|
139
149
|
return [];
|
|
@@ -38,7 +38,7 @@ function generateMissingRequiredSuggestions(missingKeys, schema, config) {
|
|
|
38
38
|
if (!(schema instanceof zod_1.z.ZodObject)) {
|
|
39
39
|
return [];
|
|
40
40
|
}
|
|
41
|
-
const shape =
|
|
41
|
+
const shape = (0, schema_introspection_js_1.getCachedShape)(schema);
|
|
42
42
|
const suggestions = [];
|
|
43
43
|
for (const key of missingKeys) {
|
|
44
44
|
const field = shape[key];
|
|
@@ -118,7 +118,7 @@ function patchTemplateForFailedOptionals(correctTemplate, args, zodErrors, schem
|
|
|
118
118
|
if (args === null || typeof args !== 'object' || Array.isArray(args))
|
|
119
119
|
return correctTemplate;
|
|
120
120
|
const argsObj = args;
|
|
121
|
-
const shape =
|
|
121
|
+
const shape = (0, schema_introspection_js_1.getCachedShape)(schema);
|
|
122
122
|
const patched = { ...correctTemplate };
|
|
123
123
|
let changed = false;
|
|
124
124
|
for (const error of zodErrors) {
|
|
@@ -46,7 +46,7 @@ function findAliasFieldConflicts(value, aliasMap) {
|
|
|
46
46
|
}
|
|
47
47
|
exports.START_WORKFLOW_PROTOCOL = {
|
|
48
48
|
canonicalParams: {
|
|
49
|
-
required: ['workflowId', 'workspacePath'],
|
|
49
|
+
required: ['workflowId', 'workspacePath', 'goal'],
|
|
50
50
|
optional: [],
|
|
51
51
|
},
|
|
52
52
|
descriptions: {
|
|
@@ -57,11 +57,13 @@ exports.START_WORKFLOW_PROTOCOL = {
|
|
|
57
57
|
'Follow the returned step exactly; treat it as the user\'s current instruction.',
|
|
58
58
|
'When the step is done, call continue_workflow with the returned continueToken.',
|
|
59
59
|
'Always pass workspacePath. Shared MCP servers cannot safely infer which repo/workspace you mean.',
|
|
60
|
+
'Always pass goal. A short sentence describing what you are trying to accomplish (e.g. "implement OAuth refresh token rotation").',
|
|
60
61
|
'Only pass context on later continue_workflow calls if facts changed.',
|
|
61
62
|
],
|
|
62
63
|
examplePayload: {
|
|
63
64
|
workflowId: 'coding-task-workflow-agentic',
|
|
64
65
|
workspacePath: '/Users/you/git/my-project',
|
|
66
|
+
goal: 'implement OAuth refresh token rotation',
|
|
65
67
|
},
|
|
66
68
|
returns: 'Step instructions plus continueToken and checkpointToken in the structured response.',
|
|
67
69
|
},
|
|
@@ -72,10 +74,12 @@ exports.START_WORKFLOW_PROTOCOL = {
|
|
|
72
74
|
'Execute the returned step exactly as written.',
|
|
73
75
|
'When the step is complete, call continue_workflow with the returned continueToken.',
|
|
74
76
|
'Pass workspacePath on every call. Shared MCP servers cannot safely infer the correct workspace.',
|
|
77
|
+
'Pass goal on every call. A short sentence describing what you are trying to accomplish.',
|
|
75
78
|
],
|
|
76
79
|
examplePayload: {
|
|
77
80
|
workflowId: 'coding-task-workflow-agentic',
|
|
78
81
|
workspacePath: '/Users/you/git/my-project',
|
|
82
|
+
goal: 'implement OAuth refresh token rotation',
|
|
79
83
|
},
|
|
80
84
|
returns: 'Step instructions plus continueToken and checkpointToken in the structured response.',
|
|
81
85
|
},
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ProcessSignal, ProcessSignals } from '../ports/process-signals.js';
|
|
2
2
|
export declare class NodeProcessSignals implements ProcessSignals {
|
|
3
3
|
on(signal: ProcessSignal, handler: () => void | Promise<void>): void;
|
|
4
|
+
once(signal: ProcessSignal, handler: () => void | Promise<void>): void;
|
|
4
5
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ProcessSignal, ProcessSignals } from '../ports/process-signals.js';
|
|
2
2
|
export declare class NoopProcessSignals implements ProcessSignals {
|
|
3
3
|
on(_signal: ProcessSignal, _handler: () => void | Promise<void>): void;
|
|
4
|
+
once(_signal: ProcessSignal, _handler: () => void | Promise<void>): void;
|
|
4
5
|
}
|