@exaudeus/workrail 1.6.0 → 1.7.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.
@@ -558,8 +558,8 @@
558
558
  "bytes": 2464
559
559
  },
560
560
  "mcp/handlers/v2-advance-core/event-builders.js": {
561
- "sha256": "6a8f51c9723ce0486f20749e392c1ec8e3fc9ccf83de43df6658d0a9c9d06441",
562
- "bytes": 5722
561
+ "sha256": "cb510635b173965f6cb2af312289f0903600a7483376b8b7156351f5bcf1fbd2",
562
+ "bytes": 5774
563
563
  },
564
564
  "mcp/handlers/v2-advance-core/index.d.ts": {
565
565
  "sha256": "a927c7e13912cfcad6340922a24f5b9331d513ce25191049aabdce96a7a86a68",
@@ -614,8 +614,8 @@
614
614
  "bytes": 674
615
615
  },
616
616
  "mcp/handlers/v2-context-budget.js": {
617
- "sha256": "41633eaf3b61838a62457768393dd0134cf4ffb1b201af28e048bfb711f6f01d",
618
- "bytes": 7173
617
+ "sha256": "5450c08d25900fd639090ba0090fc4c866e02295ee11aa52c187447424fdc4c2",
618
+ "bytes": 7199
619
619
  },
620
620
  "mcp/handlers/v2-error-mapping.d.ts": {
621
621
  "sha256": "bbaf580dfc22ca6b5ef1d57036fb549c640d6f37bd7d525f1a805b4d14c4d75c",
@@ -686,16 +686,16 @@
686
686
  "bytes": 2789
687
687
  },
688
688
  "mcp/handlers/v2-execution/start.js": {
689
- "sha256": "5eab7a7a5fdf021f7e4bc656de1dbfe791e6610ab9e1bacb15dad4f6423f1d58",
690
- "bytes": 15248
689
+ "sha256": "aeee2ba6b1cc0d461d2421eed0f99ca22f4006baa7f5663cc28855d00c950d87",
690
+ "bytes": 15015
691
691
  },
692
692
  "mcp/handlers/v2-resume.d.ts": {
693
693
  "sha256": "d88f6c35bcaf946666c837b72fda3702a2ebab5e478eb90f7b4b672a0e5fa24f",
694
694
  "bytes": 471
695
695
  },
696
696
  "mcp/handlers/v2-resume.js": {
697
- "sha256": "a8f51a680eec031e23148bd64f6d647d765c79eec738cbd6182650533248f16f",
698
- "bytes": 2929
697
+ "sha256": "74d66519764615780c556828c23ada5fa7df887c8263793de4323322aef14408",
698
+ "bytes": 2826
699
699
  },
700
700
  "mcp/handlers/v2-state-conversion.d.ts": {
701
701
  "sha256": "94bd06904ef58dd210ff17ffb75c2492beea8937eb06d99749e5d860c0e0d96b",
@@ -721,6 +721,14 @@
721
721
  "sha256": "bed0ffc401958c14343158e142e4be344bad49cabc95f99a811d872bc76989a7",
722
722
  "bytes": 6027
723
723
  },
724
+ "mcp/handlers/v2-workspace-resolution.d.ts": {
725
+ "sha256": "45cdf30b7989d16201b4569c6c109e9ccea04c76fd044af1471fe57faa49da3a",
726
+ "bytes": 483
727
+ },
728
+ "mcp/handlers/v2-workspace-resolution.js": {
729
+ "sha256": "4c6765112c49ade9c04b5f0606026e5058071ce278a6fb9c3b8207b7ca79c697",
730
+ "bytes": 909
731
+ },
724
732
  "mcp/handlers/workflow.d.ts": {
725
733
  "sha256": "050565039a20af3f7fc8311337ff4547438ecc59433e5744aacce8f203326774",
726
734
  "bytes": 1748
@@ -766,8 +774,8 @@
766
774
  "bytes": 132
767
775
  },
768
776
  "mcp/tool-descriptions.js": {
769
- "sha256": "a14ecf27cea136307d6016862f6897d1ba776f51f713e8c9cc65281f4ab7be4e",
770
- "bytes": 16654
777
+ "sha256": "1444469a7f3ac328573cc8af0cca347754e17fb184a832f78405fd4f21ed6350",
778
+ "bytes": 17534
771
779
  },
772
780
  "mcp/tool-factory.d.ts": {
773
781
  "sha256": "0fe3c6b863b2d7aef0c3d659ff54f3a9ee8a0a3c2005b6565d2f8ad517bc7211",
@@ -826,12 +834,12 @@
826
834
  "bytes": 3078
827
835
  },
828
836
  "mcp/v2/tools.d.ts": {
829
- "sha256": "a6fc8e1feb02807a4f7984dcd00358081a4b63b6b9ec9b88bb2bff833c280322",
830
- "bytes": 5172
837
+ "sha256": "8d37b32d7a00d534b2ecbdc71018e3849714531ec3021862427494be85909eab",
838
+ "bytes": 5486
831
839
  },
832
840
  "mcp/v2/tools.js": {
833
- "sha256": "7460146a5d0d3a0f67d4d42e512d467455169d22bb99f69ad812848da862b8a4",
834
- "bytes": 6721
841
+ "sha256": "0d26b75a7e038f494570f5fdc1d624f5bb28bfa7e368ea4d3259ae27dc889301",
842
+ "bytes": 7748
835
843
  },
836
844
  "mcp/validation/bounded-json.d.ts": {
837
845
  "sha256": "82203ac6123d5c6989606c3b5405aaea99ab829c8958835f9ae3ba45b8bc8fd5",
@@ -1162,12 +1170,12 @@
1162
1170
  "bytes": 447
1163
1171
  },
1164
1172
  "v2/durable-core/constants.d.ts": {
1165
- "sha256": "73121ae0a507f2ceb073c29e5f156e7958db47a47a034589c7534baa7769faa9",
1166
- "bytes": 3511
1173
+ "sha256": "2cdc1fe66cb2024e17977e024c73b9bb50845b70c9ac3925c2635e843a94f7f8",
1174
+ "bytes": 3699
1167
1175
  },
1168
1176
  "v2/durable-core/constants.js": {
1169
- "sha256": "67a2be5aa35498610cd199edec0f6558fef6efbdd0739e53c53f1f9198d66067",
1170
- "bytes": 3453
1177
+ "sha256": "29372d3e7f868b5c40d6270a1f39477a680524688e73b03613305fafef4a9553",
1178
+ "bytes": 3558
1171
1179
  },
1172
1180
  "v2/durable-core/domain/ack-advance-append-plan.d.ts": {
1173
1181
  "sha256": "2e802606656a0c1938192e5533aa46c74bc42789b5c315c79f6de4850017b30e",
@@ -1310,8 +1318,8 @@
1310
1318
  "bytes": 983
1311
1319
  },
1312
1320
  "v2/durable-core/domain/recap-recovery.js": {
1313
- "sha256": "d0145878abcf5b71fa1fdf87faacb7dee861217450947b6420422c1371d36fad",
1314
- "bytes": 2879
1321
+ "sha256": "4829d21e589ce5ed35beb9118eb07ffe05f6c1f18f6a20d7830b29ccc2da4e89",
1322
+ "bytes": 3034
1315
1323
  },
1316
1324
  "v2/durable-core/domain/recommendation-warnings.d.ts": {
1317
1325
  "sha256": "a9f9e4c09f2ab72e858d8f4045201448a62cbf7b4b1070d0448498f858331222",
@@ -1614,8 +1622,8 @@
1614
1622
  "bytes": 4285
1615
1623
  },
1616
1624
  "v2/durable-core/schemas/session/outputs.js": {
1617
- "sha256": "d41959a26236e75ab4a323619df2f8ea79f002b448504045a908dfeacfade378",
1618
- "bytes": 2050
1625
+ "sha256": "8ec5056762f2a0000ab2b1caf01b468f39695b778039c68ea85a9f42fccf3986",
1626
+ "bytes": 2156
1619
1627
  },
1620
1628
  "v2/durable-core/schemas/session/preferences.d.ts": {
1621
1629
  "sha256": "763697078bda9fa8fb7a499978a94d85d1852f0fd8fc07af295ac895d25dba66",
@@ -1810,12 +1818,12 @@
1810
1818
  "bytes": 28456
1811
1819
  },
1812
1820
  "v2/infra/local/session-summary-provider/index.d.ts": {
1813
- "sha256": "8843c26694d12147c322a4ff1f220cef53774c1ea7087241cb6badd12a360fda",
1814
- "bytes": 1069
1821
+ "sha256": "59db8bf5e38f983eedd21ff902a24324f7bedbb5f3eade1e4b0d5742b28447c2",
1822
+ "bytes": 1004
1815
1823
  },
1816
1824
  "v2/infra/local/session-summary-provider/index.js": {
1817
- "sha256": "5dadd21632795d624d0be4be1957329242df6c105ccf507e024e397ab3e63e7f",
1818
- "bytes": 5728
1825
+ "sha256": "f6c0df4a3355241ee3eb83c0013f9a252479f27f4c9172e0607464339fba6920",
1826
+ "bytes": 5655
1819
1827
  },
1820
1828
  "v2/infra/local/sha256/index.d.ts": {
1821
1829
  "sha256": "8a727b7e54a38275ca6f9f1b8730f97cfc0a212df035df1bdc58e716e6824230",
@@ -1850,12 +1858,12 @@
1850
1858
  "bytes": 304
1851
1859
  },
1852
1860
  "v2/infra/local/workspace-anchor/index.d.ts": {
1853
- "sha256": "90515ae92ac0230a279a28b82e26bc8be8f62c4cd6f6999630dc07f9a64e3296",
1854
- "bytes": 705
1861
+ "sha256": "ac5cfe8d36fab1bcff8ee1e4c13cd4b8f20b7cf109647b76bfb74e720b9eda41",
1862
+ "bytes": 537
1855
1863
  },
1856
1864
  "v2/infra/local/workspace-anchor/index.js": {
1857
- "sha256": "69541a7f2a6837ff0790c99740000a71521a60671b4fd7c4a2245a48e56bb9b7",
1858
- "bytes": 2102
1865
+ "sha256": "a0fe032a9205606c6d592221f1300a3113c7d0cb3e126e458fef3dc8fa6e823c",
1866
+ "bytes": 2272
1859
1867
  },
1860
1868
  "v2/ports/base32.port.d.ts": {
1861
1869
  "sha256": "64aa2f2003a552917cbf71474472fc5e4afffaa29577204bbcbe5ffa989ceb82",
@@ -1994,8 +2002,8 @@
1994
2002
  "bytes": 77
1995
2003
  },
1996
2004
  "v2/ports/workspace-anchor.port.d.ts": {
1997
- "sha256": "228cce9bff3cbaa430bf38be3a1bc326885ec07c7952af2824735bc7adbf9af3",
1998
- "bytes": 759
2005
+ "sha256": "8614bc27a958291d53d6a24ffc30fdf5352d98f02b79470993d6c134e72d83eb",
2006
+ "bytes": 751
1999
2007
  },
2000
2008
  "v2/ports/workspace-anchor.port.js": {
2001
2009
  "sha256": "d43aa81f5bc89faa359e0f97c814ba25155591ff078fbb9bfd40f8c7c9683230",
@@ -2014,8 +2022,8 @@
2014
2022
  "bytes": 955
2015
2023
  },
2016
2024
  "v2/projections/artifacts.js": {
2017
- "sha256": "e20ae7c41813de53701dc5993b4ead5e09af9eb724340dfd8d7a0b2670857217",
2018
- "bytes": 2007
2025
+ "sha256": "eb06aff128112850fdc8b3bfafae759500ca65aed279f096a077e000a9a1bf99",
2026
+ "bytes": 2033
2019
2027
  },
2020
2028
  "v2/projections/capabilities.d.ts": {
2021
2029
  "sha256": "ee4c4bb728b5fc7343a43c9bb13a981a9bf0bd1b39e68ff8c866b4119012eac1",
@@ -84,7 +84,7 @@ function buildNotesOutputs(allowNotesAppend, attemptId, inputOutput) {
84
84
  outputId: String((0, index_js_1.asOutputId)(`out_recap_${String(attemptId)}`)),
85
85
  outputChannel: constants_js_1.OUTPUT_CHANNEL.RECAP,
86
86
  payload: {
87
- payloadKind: 'notes',
87
+ payloadKind: constants_js_1.PAYLOAD_KIND.NOTES,
88
88
  notesMarkdown: (0, notes_markdown_js_1.toNotesMarkdownV1)(inputOutput.notesMarkdown),
89
89
  },
90
90
  }];
@@ -102,7 +102,7 @@ function buildArtifactOutputs(inputArtifacts, attemptId, sha256) {
102
102
  outputId: (0, index_js_1.asOutputId)(`out_artifact_${String(attemptId)}_${idx}`),
103
103
  outputChannel: constants_js_1.OUTPUT_CHANNEL.ARTIFACT,
104
104
  payload: {
105
- payloadKind: 'artifact_ref',
105
+ payloadKind: constants_js_1.PAYLOAD_KIND.ARTIFACT_REF,
106
106
  sha256: sha256.sha256(canonicalBytes),
107
107
  contentType: 'application/json',
108
108
  byteLength: canonicalBytes.length,
@@ -158,7 +158,7 @@ function collectArtifactsForEvaluation(args) {
158
158
  continue;
159
159
  if (e.data.outputChannel !== constants_js_1.OUTPUT_CHANNEL.ARTIFACT)
160
160
  continue;
161
- if (e.data.payload.payloadKind !== 'artifact_ref')
161
+ if (e.data.payload.payloadKind !== constants_js_1.PAYLOAD_KIND.ARTIFACT_REF)
162
162
  continue;
163
163
  const payload = e.data.payload;
164
164
  if (payload.content === undefined)
@@ -16,6 +16,7 @@ const observation_builder_js_1 = require("../../../v2/durable-core/domain/observ
16
16
  const workflow_source_js_1 = require("../../../types/workflow-source.js");
17
17
  const workflow_definition_js_1 = require("../../../types/workflow-definition.js");
18
18
  const v2_execution_helpers_js_1 = require("../v2-execution-helpers.js");
19
+ const v2_workspace_resolution_js_1 = require("../v2-workspace-resolution.js");
19
20
  const v2_token_ops_js_1 = require("../v2-token-ops.js");
20
21
  const v2_state_conversion_js_1 = require("../v2-state-conversion.js");
21
22
  const v2_execution_helpers_js_2 = require("../v2-execution-helpers.js");
@@ -229,15 +230,8 @@ function executeStartWorkflow(input, ctx) {
229
230
  pinnedStore,
230
231
  })
231
232
  .andThen(({ workflow, firstStep, workflowHash, pinnedWorkflow }) => {
232
- const workspaceResolver = ctx.v2.workspaceResolver;
233
- const primaryRootUri = ctx.v2.resolvedRootUris?.[0];
234
- const anchorsRA = workspaceResolver
235
- ? (primaryRootUri
236
- ? workspaceResolver.resolveFromUri(primaryRootUri)
237
- : workspaceResolver.resolveFromCwd())
238
- .map((anchors) => (0, observation_builder_js_1.anchorsToObservations)(anchors))
239
- .orElse(() => (0, neverthrow_1.okAsync)([]))
240
- : (0, neverthrow_1.okAsync)([]);
233
+ const anchorsRA = (0, v2_workspace_resolution_js_1.resolveWorkspaceAnchors)(ctx.v2, input.workspacePath)
234
+ .map((anchors) => (0, observation_builder_js_1.anchorsToObservations)(anchors));
241
235
  return anchorsRA.andThen((observations) => {
242
236
  const sessionId = idFactory.mintSessionId();
243
237
  const runId = idFactory.mintRunId();
@@ -6,6 +6,7 @@ const output_schemas_js_1 = require("../output-schemas.js");
6
6
  const v2_token_ops_js_1 = require("./v2-token-ops.js");
7
7
  const index_js_1 = require("../../v2/durable-core/ids/index.js");
8
8
  const resume_session_js_1 = require("../../v2/usecases/resume-session.js");
9
+ const v2_workspace_resolution_js_1 = require("./v2-workspace-resolution.js");
9
10
  function anchorValue(anchors, key) {
10
11
  const anchor = anchors.find((a) => a.key === key);
11
12
  return anchor?.value;
@@ -18,16 +19,8 @@ async function handleV2ResumeSession(input, ctx) {
18
19
  if (!v2.sessionSummaryProvider) {
19
20
  return (0, types_js_1.errNotRetryable)('INTERNAL_ERROR', 'resume_session requires sessionSummaryProvider port');
20
21
  }
21
- let anchors = [];
22
- if (v2.workspaceResolver) {
23
- const primaryRootUri = v2.resolvedRootUris?.[0];
24
- const anchorRes = await (primaryRootUri
25
- ? v2.workspaceResolver.resolveFromUri(primaryRootUri)
26
- : v2.workspaceResolver.resolveFromCwd());
27
- if (anchorRes.isOk()) {
28
- anchors = anchorRes.value;
29
- }
30
- }
22
+ const anchorsResult = await (0, v2_workspace_resolution_js_1.resolveWorkspaceAnchors)(v2, input.workspacePath);
23
+ const anchors = anchorsResult.isOk() ? anchorsResult.value : [];
31
24
  const query = {
32
25
  gitHeadSha: input.gitHeadSha ?? anchorValue(anchors, 'git_head_sha'),
33
26
  gitBranch: input.gitBranch ?? anchorValue(anchors, 'git_branch'),
@@ -0,0 +1,5 @@
1
+ import type { ResultAsync } from 'neverthrow';
2
+ import type { WorkspaceAnchor, WorkspaceSource } from '../../v2/ports/workspace-anchor.port.js';
3
+ import type { V2Dependencies } from '../types.js';
4
+ export declare function selectWorkspaceSource(workspacePath: string | undefined, resolvedRootUris: readonly string[]): WorkspaceSource;
5
+ export declare function resolveWorkspaceAnchors(v2: V2Dependencies, workspacePath: string | undefined): ResultAsync<readonly WorkspaceAnchor[], never>;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.selectWorkspaceSource = selectWorkspaceSource;
4
+ exports.resolveWorkspaceAnchors = resolveWorkspaceAnchors;
5
+ const neverthrow_1 = require("neverthrow");
6
+ function selectWorkspaceSource(workspacePath, resolvedRootUris) {
7
+ if (workspacePath !== undefined) {
8
+ return { kind: 'explicit_path', path: workspacePath };
9
+ }
10
+ const primaryUri = resolvedRootUris[0];
11
+ if (primaryUri !== undefined) {
12
+ return { kind: 'mcp_root_uri', uri: primaryUri };
13
+ }
14
+ return { kind: 'server_cwd' };
15
+ }
16
+ function resolveWorkspaceAnchors(v2, workspacePath) {
17
+ if (!v2.workspaceResolver)
18
+ return (0, neverthrow_1.okAsync)([]);
19
+ const source = selectWorkspaceSource(workspacePath, v2.resolvedRootUris ?? []);
20
+ return v2.workspaceResolver.resolve(source)
21
+ .orElse(() => (0, neverthrow_1.okAsync)([]));
22
+ }
@@ -75,6 +75,8 @@ What to do:
75
75
  3. Optionally add output.notesMarkdown summarizing your work
76
76
  4. Don't predict what comes next - the workflow will tell you
77
77
 
78
+ Workspace anchoring: Pass workspacePath (the "Workspace:" path from your system parameters) so this session can be found by resume_session in future chats. Without it, session discovery may not work.
79
+
78
80
  Context auto-loads: If you provide context at start, WorkRail remembers it. On future continue_workflow calls, only pass context if you have NEW information to add.`,
79
81
  continue_workflow: `Get the next step in the workflow (WorkRail v2, feature-flagged).
80
82
 
@@ -130,6 +132,8 @@ Returns: checkpointNodeId + a fresh stateToken.`,
130
132
 
131
133
  Use this when you need to resume a previously started workflow but don't have the stateToken (e.g., new chat, lost context).
132
134
 
135
+ Pass workspacePath (the "Workspace:" path from your system parameters) to match sessions anchored to your current workspace. Without it, git-based tier matching won't work.
136
+
133
137
  WorkRail ranks sessions using a 5-tier matching algorithm:
134
138
  1. Exact git HEAD SHA match
135
139
  2. Git branch match (exact or prefix)
@@ -225,6 +229,11 @@ REQUIRED BEHAVIOR:
225
229
  4. Round-trip tokens UNCHANGED (don't decode, inspect, or modify them)
226
230
  5. Follow the workflow to completion - don't improvise alternative approaches
227
231
 
232
+ Workspace anchoring (IMPORTANT):
233
+ - Pass workspacePath set to the "Workspace:" value from your system parameters
234
+ - This anchors the session to your workspace so resume_session can find it in future chats
235
+ - Example: workspacePath: "/Users/you/git/my-project"
236
+
228
237
  Context handling:
229
238
  - Pass context at start to establish baseline facts
230
239
  - WorkRail auto-loads context on subsequent calls
@@ -295,6 +304,10 @@ Call this when resuming a workflow without a stateToken. WorkRail ranks sessions
295
304
  4. Workflow ID match (tier 4)
296
305
  5. Recency (tier 5)
297
306
 
307
+ IMPORTANT: Pass workspacePath set to the "Workspace:" value from your system parameters.
308
+ Without it, tier 1 and tier 2 matching won't work (git context defaults to server directory, not yours).
309
+ Example: workspacePath: "/Users/you/git/my-project"
310
+
298
311
  Returns: Up to 5 candidates with stateTokens. Use the best match's stateToken with continue_workflow.`,
299
312
  },
300
313
  };
@@ -16,12 +16,15 @@ export type V2InspectWorkflowInput = z.infer<typeof V2InspectWorkflowInput>;
16
16
  export declare const V2StartWorkflowInput: z.ZodObject<{
17
17
  workflowId: z.ZodString;
18
18
  context: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
19
+ workspacePath: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
19
20
  }, "strip", z.ZodTypeAny, {
20
21
  workflowId: string;
21
22
  context?: Record<string, unknown> | undefined;
23
+ workspacePath?: string | undefined;
22
24
  }, {
23
25
  workflowId: string;
24
26
  context?: Record<string, unknown> | undefined;
27
+ workspacePath?: string | undefined;
25
28
  }>;
26
29
  export type V2StartWorkflowInput = z.infer<typeof V2StartWorkflowInput>;
27
30
  export declare const V2ContinueWorkflowInput: z.ZodPipeline<z.ZodEffects<z.ZodObject<{
@@ -119,12 +122,15 @@ export declare const V2ResumeSessionInput: z.ZodObject<{
119
122
  query: z.ZodOptional<z.ZodString>;
120
123
  gitBranch: z.ZodOptional<z.ZodString>;
121
124
  gitHeadSha: z.ZodOptional<z.ZodString>;
125
+ workspacePath: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
122
126
  }, "strict", z.ZodTypeAny, {
123
127
  query?: string | undefined;
128
+ workspacePath?: string | undefined;
124
129
  gitBranch?: string | undefined;
125
130
  gitHeadSha?: string | undefined;
126
131
  }, {
127
132
  query?: string | undefined;
133
+ workspacePath?: string | undefined;
128
134
  gitBranch?: string | undefined;
129
135
  gitHeadSha?: string | undefined;
130
136
  }>;
@@ -10,6 +10,10 @@ exports.V2InspectWorkflowInput = zod_1.z.object({
10
10
  exports.V2StartWorkflowInput = zod_1.z.object({
11
11
  workflowId: zod_1.z.string().min(1).regex(/^[A-Za-z0-9_-]+$/, 'Workflow ID must contain only letters, numbers, hyphens, and underscores').describe('The workflow ID to start'),
12
12
  context: zod_1.z.record(zod_1.z.unknown()).optional().describe('External facts influencing execution (ticketId, branch, constraints). Pass once at start to establish baseline. WorkRail auto-loads context on subsequent continue_workflow calls. Only pass context again if facts have CHANGED (e.g., user provided new information). Do NOT re-pass unchanged values.'),
13
+ workspacePath: zod_1.z.string()
14
+ .refine((p) => p.startsWith('/'), 'workspacePath must be an absolute path (starting with /)')
15
+ .optional()
16
+ .describe('Absolute path to your current workspace directory (e.g. the "Workspace:" value from your system parameters). Used to anchor this session to your workspace for future resume_session discovery. Pass this on every start_workflow call. If omitted, WorkRail uses the server process directory which may not match your workspace.'),
13
17
  });
14
18
  exports.V2ContinueWorkflowInput = zod_1.z.object({
15
19
  intent: zod_1.z.enum(['advance', 'rehydrate']).optional().describe('What you want to do. Auto-inferred from ackToken if omitted: ' +
@@ -62,6 +66,10 @@ exports.V2ResumeSessionInput = zod_1.z.object({
62
66
  query: zod_1.z.string().max(256).optional().describe('Free text search to find a relevant session. Matches against recap notes and workflow IDs.'),
63
67
  gitBranch: zod_1.z.string().max(256).optional().describe('Git branch name to match against session observations. Overrides auto-detected branch.'),
64
68
  gitHeadSha: zod_1.z.string().regex(/^[0-9a-f]{40}$/).optional().describe('Git HEAD SHA to match against session observations. Overrides auto-detected HEAD.'),
69
+ workspacePath: zod_1.z.string()
70
+ .refine((p) => p.startsWith('/'), 'workspacePath must be an absolute path (starting with /)')
71
+ .optional()
72
+ .describe('Absolute path to your current workspace directory (e.g. the "Workspace:" value from your system parameters). Used to resolve your git branch and HEAD SHA for workspace-aware session matching. Pass the same path used in the original start_workflow call. If omitted, WorkRail uses the server process directory which may not match your workspace.'),
65
73
  }).strict();
66
74
  exports.V2CheckpointWorkflowInput = zod_1.z.object({
67
75
  checkpointToken: zod_1.z.string().min(1).describe('The checkpoint token from the most recent start_workflow or continue_workflow response. ' +
@@ -40,6 +40,11 @@ export declare const OUTPUT_CHANNEL: {
40
40
  readonly ARTIFACT: "artifact";
41
41
  };
42
42
  export type OutputChannelV1 = typeof OUTPUT_CHANNEL[keyof typeof OUTPUT_CHANNEL];
43
+ export declare const PAYLOAD_KIND: {
44
+ readonly NOTES: "notes";
45
+ readonly ARTIFACT_REF: "artifact_ref";
46
+ };
47
+ export type PayloadKindV1 = typeof PAYLOAD_KIND[keyof typeof PAYLOAD_KIND];
43
48
  export declare const EDGE_KIND: {
44
49
  readonly ACKED_STEP: "acked_step";
45
50
  readonly CHECKPOINT: "checkpoint";
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AUTONOMY_MODE = exports.ADVANCE_INTENT = exports.MANIFEST_KIND = exports.EDGE_CAUSE = exports.ADVANCE_OUTCOME = exports.ENGINE_STATE = exports.EDGE_KIND = exports.OUTPUT_CHANNEL = exports.EVENT_KIND = exports.DELIMITER_SAFE_ID_PATTERN = exports.SHA256_DIGEST_PATTERN = exports.RECOVERY_BUDGET_BYTES = exports.TRUNCATION_MARKER = exports.DEFAULT_RETRY_AFTER_MS = exports.SESSION_LOCK_RETRY_AFTER_MS = exports.MAX_OBSERVATION_SHORT_STRING_LENGTH = exports.MAX_CONTEXT_DEPTH = exports.MAX_CONTEXT_BYTES = exports.MAX_VALIDATION_SUGGESTIONS_BYTES = exports.MAX_VALIDATION_ISSUES_BYTES = exports.MAX_VALIDATION_SUGGESTION_ITEM_BYTES = exports.MAX_VALIDATION_ISSUE_ITEM_BYTES = exports.MAX_OUTPUT_NOTES_MARKDOWN_BYTES = exports.MAX_DECISION_TRACE_TOTAL_BYTES = exports.MAX_DECISION_TRACE_ENTRY_SUMMARY_BYTES = exports.MAX_DECISION_TRACE_ENTRIES = exports.MAX_BLOCKER_SUGGESTED_FIX_BYTES = exports.MAX_BLOCKER_MESSAGE_BYTES = exports.MAX_BLOCKERS = void 0;
3
+ exports.AUTONOMY_MODE = exports.ADVANCE_INTENT = exports.MANIFEST_KIND = exports.EDGE_CAUSE = exports.ADVANCE_OUTCOME = exports.ENGINE_STATE = exports.EDGE_KIND = exports.PAYLOAD_KIND = exports.OUTPUT_CHANNEL = exports.EVENT_KIND = exports.DELIMITER_SAFE_ID_PATTERN = exports.SHA256_DIGEST_PATTERN = exports.RECOVERY_BUDGET_BYTES = exports.TRUNCATION_MARKER = exports.DEFAULT_RETRY_AFTER_MS = exports.SESSION_LOCK_RETRY_AFTER_MS = exports.MAX_OBSERVATION_SHORT_STRING_LENGTH = exports.MAX_CONTEXT_DEPTH = exports.MAX_CONTEXT_BYTES = exports.MAX_VALIDATION_SUGGESTIONS_BYTES = exports.MAX_VALIDATION_ISSUES_BYTES = exports.MAX_VALIDATION_SUGGESTION_ITEM_BYTES = exports.MAX_VALIDATION_ISSUE_ITEM_BYTES = exports.MAX_OUTPUT_NOTES_MARKDOWN_BYTES = exports.MAX_DECISION_TRACE_TOTAL_BYTES = exports.MAX_DECISION_TRACE_ENTRY_SUMMARY_BYTES = exports.MAX_DECISION_TRACE_ENTRIES = exports.MAX_BLOCKER_SUGGESTED_FIX_BYTES = exports.MAX_BLOCKER_MESSAGE_BYTES = exports.MAX_BLOCKERS = void 0;
4
4
  exports.MAX_BLOCKERS = 10;
5
5
  exports.MAX_BLOCKER_MESSAGE_BYTES = 512;
6
6
  exports.MAX_BLOCKER_SUGGESTED_FIX_BYTES = 1024;
@@ -41,6 +41,10 @@ exports.OUTPUT_CHANNEL = {
41
41
  RECAP: 'recap',
42
42
  ARTIFACT: 'artifact',
43
43
  };
44
+ exports.PAYLOAD_KIND = {
45
+ NOTES: 'notes',
46
+ ARTIFACT_REF: 'artifact_ref',
47
+ };
44
48
  exports.EDGE_KIND = {
45
49
  ACKED_STEP: 'acked_step',
46
50
  CHECKPOINT: 'checkpoint',
@@ -4,6 +4,7 @@ exports.collectAncestryRecap = collectAncestryRecap;
4
4
  exports.collectDownstreamRecap = collectDownstreamRecap;
5
5
  exports.buildChildSummary = buildChildSummary;
6
6
  const neverthrow_1 = require("neverthrow");
7
+ const constants_js_1 = require("../constants.js");
7
8
  function collectAncestryRecap(args) {
8
9
  const buildChain = (cur, visited) => {
9
10
  if (!cur || visited.has(cur))
@@ -22,9 +23,9 @@ function collectAncestryRecap(args) {
22
23
  if (!nodeOutputs)
23
24
  return [];
24
25
  return nodeOutputs.currentByChannel.recap
25
- .filter(r => r.payload.payloadKind === 'notes')
26
+ .filter(r => r.payload.payloadKind === constants_js_1.PAYLOAD_KIND.NOTES)
26
27
  .map(r => {
27
- if (r.payload.payloadKind === 'notes') {
28
+ if (r.payload.payloadKind === constants_js_1.PAYLOAD_KIND.NOTES) {
28
29
  return r.payload.notesMarkdown;
29
30
  }
30
31
  return '';
@@ -48,9 +49,9 @@ function collectDownstreamRecap(args) {
48
49
  if (!nodeOutputs)
49
50
  return [];
50
51
  return nodeOutputs.currentByChannel.recap
51
- .filter(r => r.payload.payloadKind === 'notes')
52
+ .filter(r => r.payload.payloadKind === constants_js_1.PAYLOAD_KIND.NOTES)
52
53
  .map(r => {
53
- if (r.payload.payloadKind === 'notes') {
54
+ if (r.payload.payloadKind === constants_js_1.PAYLOAD_KIND.NOTES) {
54
55
  return r.payload.notesMarkdown;
55
56
  }
56
57
  return '';
@@ -10,7 +10,7 @@ const sha256DigestSchema = zod_1.z
10
10
  .describe('sha256 digest in WorkRail v2 format');
11
11
  exports.OutputChannelSchema = zod_1.z.enum(['recap', 'artifact']);
12
12
  exports.NotesPayloadV1Schema = zod_1.z.object({
13
- payloadKind: zod_1.z.literal('notes'),
13
+ payloadKind: zod_1.z.literal(constants_js_1.PAYLOAD_KIND.NOTES),
14
14
  notesMarkdown: zod_1.z
15
15
  .string()
16
16
  .min(1)
@@ -19,7 +19,7 @@ exports.NotesPayloadV1Schema = zod_1.z.object({
19
19
  }),
20
20
  });
21
21
  exports.ArtifactRefPayloadV1Schema = zod_1.z.object({
22
- payloadKind: zod_1.z.literal('artifact_ref'),
22
+ payloadKind: zod_1.z.literal(constants_js_1.PAYLOAD_KIND.ARTIFACT_REF),
23
23
  sha256: sha256DigestSchema,
24
24
  contentType: zod_1.z.string().min(1),
25
25
  byteLength: zod_1.z.number().int().nonnegative(),
@@ -34,7 +34,7 @@ exports.NodeOutputAppendedDataV1Schema = zod_1.z
34
34
  payload: exports.OutputPayloadV1Schema,
35
35
  })
36
36
  .superRefine((v, ctx) => {
37
- if (v.outputChannel === 'recap' && v.payload.payloadKind !== 'notes') {
37
+ if (v.outputChannel === constants_js_1.OUTPUT_CHANNEL.RECAP && v.payload.payloadKind !== constants_js_1.PAYLOAD_KIND.NOTES) {
38
38
  ctx.addIssue({
39
39
  code: zod_1.z.ZodIssueCode.custom,
40
40
  message: 'outputChannel=recap requires payloadKind=notes',
@@ -13,6 +13,4 @@ export declare class LocalSessionSummaryProviderV2 implements SessionSummaryProv
13
13
  private readonly ports;
14
14
  constructor(ports: LocalSessionSummaryProviderPorts);
15
15
  loadHealthySummaries(): ResultAsync<readonly HealthySessionSummary[], SessionSummaryError>;
16
- private collectHealthySummaries;
17
- private tryLoadSummary;
18
16
  }
@@ -9,6 +9,16 @@ const run_dag_js_1 = require("../../../projections/run-dag.js");
9
9
  const node_outputs_js_1 = require("../../../projections/node-outputs.js");
10
10
  const constants_js_1 = require("../../../durable-core/constants.js");
11
11
  const MAX_SESSIONS_TO_SCAN = 50;
12
+ const MAX_RECAP_ANCESTOR_DEPTH = 100;
13
+ const EMPTY_OBSERVATIONS = {
14
+ gitHeadSha: null,
15
+ gitBranch: null,
16
+ repoRootHash: null,
17
+ };
18
+ const UNKNOWN_WORKFLOW = {
19
+ workflowId: null,
20
+ workflowName: null,
21
+ };
12
22
  class LocalSessionSummaryProviderV2 {
13
23
  constructor(ports) {
14
24
  this.ports = ports;
@@ -22,123 +32,107 @@ class LocalSessionSummaryProviderV2 {
22
32
  code: 'SESSION_SUMMARY_ENUMERATION_FAILED',
23
33
  message: `Failed to enumerate sessions: ${fsErr.message}`,
24
34
  }))
25
- .andThen((sessionIds) => {
26
- const capped = sessionIds.slice(0, MAX_SESSIONS_TO_SCAN);
27
- return this.collectHealthySummaries(capped);
28
- });
29
- }
30
- collectHealthySummaries(sessionIds) {
31
- const summaries = [];
32
- let chain = (0, neverthrow_1.okAsync)(undefined);
33
- for (const sessionId of sessionIds) {
34
- chain = chain.andThen(() => this.tryLoadSummary(sessionId).map((summary) => {
35
- if (summary !== null) {
36
- summaries.push(summary);
37
- }
38
- }));
39
- }
40
- return chain.map(() => summaries);
41
- }
42
- tryLoadSummary(sessionId) {
43
- return this.ports.sessionStore
44
- .load(sessionId)
45
- .map((truth) => {
46
- const healthRes = (0, session_health_js_1.projectSessionHealthV2)(truth);
47
- if (healthRes.isErr())
48
- return null;
49
- if (healthRes.value.kind !== 'healthy')
50
- return null;
51
- const dagRes = (0, run_dag_js_1.projectRunDagV2)(truth.events);
52
- if (dagRes.isErr())
53
- return null;
54
- const runs = Object.values(dagRes.value.runsById);
55
- if (runs.length === 0)
56
- return null;
57
- const runsWithActivity = runs
58
- .filter((r) => r.preferredTipNodeId !== null)
59
- .map((r) => {
60
- const tipNode = r.nodesById[r.preferredTipNodeId];
61
- const maxEventIndex = tipNode ? tipNode.createdAtEventIndex : 0;
62
- return { run: r, lastActivityEventIndex: maxEventIndex };
63
- })
64
- .sort((a, b) => b.lastActivityEventIndex - a.lastActivityEventIndex);
65
- if (runsWithActivity.length === 0)
66
- return null;
67
- const bestRun = runsWithActivity[0];
68
- const run = bestRun.run;
69
- const outputsRes = (0, node_outputs_js_1.projectNodeOutputsV2)(truth.events);
70
- const recapSnippet = outputsRes.isOk() && run.preferredTipNodeId
71
- ? extractRecapFromOutputs(outputsRes.value, run.preferredTipNodeId)
72
- : null;
73
- const observations = extractObservations(truth.events);
74
- const workflow = extractWorkflowIdentity(truth.events, run.runId);
75
- return {
76
- sessionId,
77
- runId: run.runId,
78
- preferredTip: {
79
- nodeId: run.preferredTipNodeId,
80
- lastActivityEventIndex: bestRun.lastActivityEventIndex,
81
- },
82
- recapSnippet,
83
- observations,
84
- workflow,
85
- };
86
- })
87
- .orElse(() => (0, neverthrow_1.okAsync)(null));
35
+ .andThen((sessionIds) => collectHealthySummaries(sessionIds.slice(0, MAX_SESSIONS_TO_SCAN), this.ports.sessionStore));
88
36
  }
89
37
  }
90
38
  exports.LocalSessionSummaryProviderV2 = LocalSessionSummaryProviderV2;
91
- function extractRecapFromOutputs(outputs, nodeId) {
92
- const nodeView = outputs.nodesById[nodeId];
93
- if (!nodeView)
39
+ function collectHealthySummaries(sessionIds, sessionStore) {
40
+ return sessionIds.reduce((acc, sessionId) => acc.andThen((summaries) => loadSessionSummary(sessionId, sessionStore).map((summary) => summary !== null ? [...summaries, summary] : summaries)), (0, neverthrow_1.okAsync)([]));
41
+ }
42
+ function loadSessionSummary(sessionId, sessionStore) {
43
+ return sessionStore
44
+ .load(sessionId)
45
+ .map((truth) => projectSessionSummary(sessionId, truth))
46
+ .orElse(() => (0, neverthrow_1.okAsync)(null));
47
+ }
48
+ function projectSessionSummary(sessionId, truth) {
49
+ const health = (0, session_health_js_1.projectSessionHealthV2)(truth);
50
+ if (health.isErr() || health.value.kind !== 'healthy')
94
51
  return null;
95
- const recapOutputs = nodeView.currentByChannel['recap'];
96
- if (!recapOutputs || recapOutputs.length === 0)
52
+ const dag = (0, run_dag_js_1.projectRunDagV2)(truth.events);
53
+ if (dag.isErr())
97
54
  return null;
98
- const latest = recapOutputs[recapOutputs.length - 1];
99
- if (latest.payload.payloadKind !== 'notes')
55
+ const bestRun = selectBestRun(Object.values(dag.value.runsById));
56
+ if (!bestRun)
100
57
  return null;
101
- const markdown = latest.payload.notesMarkdown;
102
- if (!markdown || typeof markdown !== 'string')
58
+ const outputsRes = (0, node_outputs_js_1.projectNodeOutputsV2)(truth.events);
59
+ const recapSnippet = outputsRes.isOk()
60
+ ? extractAggregateRecap(outputsRes.value, bestRun.run, bestRun.tipNodeId)
61
+ : null;
62
+ return {
63
+ sessionId,
64
+ runId: bestRun.run.runId,
65
+ preferredTip: {
66
+ nodeId: bestRun.tipNodeId,
67
+ lastActivityEventIndex: bestRun.lastActivityEventIndex,
68
+ },
69
+ recapSnippet,
70
+ observations: extractObservations(truth.events),
71
+ workflow: extractWorkflowIdentity(truth.events, bestRun.run.runId),
72
+ };
73
+ }
74
+ function selectBestRun(runs) {
75
+ const runsWithTip = runs.flatMap((r) => {
76
+ const tipNodeId = r.preferredTipNodeId;
77
+ if (!tipNodeId)
78
+ return [];
79
+ const tipNode = r.nodesById[tipNodeId];
80
+ return [{ run: r, tipNodeId, lastActivityEventIndex: tipNode?.createdAtEventIndex ?? 0 }];
81
+ });
82
+ if (runsWithTip.length === 0)
103
83
  return null;
104
- return (0, resume_ranking_js_1.asRecapSnippet)(markdown);
84
+ return runsWithTip.reduce((best, r) => r.lastActivityEventIndex > best.lastActivityEventIndex ? r : best);
105
85
  }
106
86
  function extractObservations(events) {
107
- let gitHeadSha = null;
108
- let gitBranch = null;
109
- let repoRootHash = null;
110
- for (const event of events) {
111
- if (event.kind !== constants_js_1.EVENT_KIND.OBSERVATION_RECORDED)
112
- continue;
113
- const data = event.data;
114
- switch (data.key) {
115
- case 'git_head_sha':
116
- gitHeadSha = data.value.value;
117
- break;
118
- case 'git_branch':
119
- gitBranch = data.value.value;
120
- break;
121
- case 'repo_root_hash':
122
- repoRootHash = data.value.value;
123
- break;
124
- default:
125
- break;
87
+ return events
88
+ .filter((e) => e.kind === constants_js_1.EVENT_KIND.OBSERVATION_RECORDED)
89
+ .reduce((acc, e) => {
90
+ switch (e.data.key) {
91
+ case 'git_head_sha': return { ...acc, gitHeadSha: e.data.value.value };
92
+ case 'git_branch': return { ...acc, gitBranch: e.data.value.value };
93
+ case 'repo_root_hash': return { ...acc, repoRootHash: e.data.value.value };
126
94
  }
127
- }
128
- return { gitHeadSha, gitBranch, repoRootHash };
95
+ }, EMPTY_OBSERVATIONS);
129
96
  }
130
97
  function extractWorkflowIdentity(events, runId) {
131
- for (const event of events) {
132
- if (event.kind !== constants_js_1.EVENT_KIND.RUN_STARTED)
133
- continue;
134
- const scope = event.scope;
135
- if (scope?.runId !== runId)
136
- continue;
137
- const data = event.data;
138
- return {
139
- workflowId: data.workflowId ?? null,
140
- workflowName: null,
141
- };
142
- }
143
- return { workflowId: null, workflowName: null };
98
+ const event = events
99
+ .filter((e) => e.kind === constants_js_1.EVENT_KIND.RUN_STARTED)
100
+ .find((e) => e.scope.runId === runId);
101
+ if (!event)
102
+ return UNKNOWN_WORKFLOW;
103
+ return {
104
+ workflowId: event.data.workflowId,
105
+ workflowName: null,
106
+ };
107
+ }
108
+ function collectAncestorNodeIds(nodesById, nodeId, remainingDepth) {
109
+ if (remainingDepth === 0)
110
+ return [nodeId];
111
+ const node = nodesById[nodeId];
112
+ if (!node)
113
+ return [nodeId];
114
+ const parentIds = node.parentNodeId
115
+ ? collectAncestorNodeIds(nodesById, node.parentNodeId, remainingDepth - 1)
116
+ : [];
117
+ return [nodeId, ...parentIds];
118
+ }
119
+ function extractNodeRecapMarkdown(outputs, nodeId) {
120
+ const nodeView = outputs.nodesById[nodeId];
121
+ if (!nodeView)
122
+ return null;
123
+ const recapOutputs = nodeView.currentByChannel[constants_js_1.OUTPUT_CHANNEL.RECAP];
124
+ if (!recapOutputs || recapOutputs.length === 0)
125
+ return null;
126
+ const latest = recapOutputs.at(-1);
127
+ if (!latest || latest.payload.payloadKind !== constants_js_1.PAYLOAD_KIND.NOTES)
128
+ return null;
129
+ return latest.payload.notesMarkdown;
130
+ }
131
+ function extractAggregateRecap(outputs, run, tipNodeId) {
132
+ const parts = collectAncestorNodeIds(run.nodesById, tipNodeId, MAX_RECAP_ANCESTOR_DEPTH)
133
+ .map((nodeId) => extractNodeRecapMarkdown(outputs, nodeId))
134
+ .filter((md) => md !== null);
135
+ if (parts.length === 0)
136
+ return null;
137
+ return (0, resume_ranking_js_1.asRecapSnippet)(parts.join('\n\n'));
144
138
  }
@@ -1,12 +1,10 @@
1
1
  import { ResultAsync as RA } from 'neverthrow';
2
- import type { WorkspaceAnchorPortV2, WorkspaceContextResolverPortV2, WorkspaceAnchor, WorkspaceAnchorError } from '../../../ports/workspace-anchor.port.js';
3
- export declare class LocalWorkspaceAnchorV2 implements WorkspaceAnchorPortV2, WorkspaceContextResolverPortV2 {
2
+ import type { WorkspaceContextResolverPortV2, WorkspaceSource, WorkspaceAnchor, WorkspaceAnchorError } from '../../../ports/workspace-anchor.port.js';
3
+ export declare class LocalWorkspaceAnchorV2 implements WorkspaceContextResolverPortV2 {
4
4
  private readonly defaultCwd;
5
5
  constructor(defaultCwd: string);
6
- resolveAnchors(): RA<readonly WorkspaceAnchor[], WorkspaceAnchorError>;
7
- resolveFromUri(rootUri: string): RA<readonly WorkspaceAnchor[], WorkspaceAnchorError>;
8
- resolveFromCwd(): RA<readonly WorkspaceAnchor[], WorkspaceAnchorError>;
9
- private resolveFromPath;
10
- private resolve;
6
+ resolve(source: WorkspaceSource): RA<readonly WorkspaceAnchor[], WorkspaceAnchorError>;
7
+ private resolveGitIdentityAt;
8
+ private runGitCommands;
11
9
  private gitCommand;
12
10
  }
@@ -10,25 +10,27 @@ class LocalWorkspaceAnchorV2 {
10
10
  constructor(defaultCwd) {
11
11
  this.defaultCwd = defaultCwd;
12
12
  }
13
- resolveAnchors() {
14
- return this.resolveFromPath(this.defaultCwd);
15
- }
16
- resolveFromUri(rootUri) {
17
- const fsPath = uriToFsPath(rootUri);
18
- if (fsPath === null)
19
- return (0, neverthrow_1.okAsync)([]);
20
- return this.resolveFromPath(fsPath);
21
- }
22
- resolveFromCwd() {
23
- return this.resolveFromPath(this.defaultCwd);
13
+ resolve(source) {
14
+ switch (source.kind) {
15
+ case 'explicit_path':
16
+ return this.resolveGitIdentityAt(source.path);
17
+ case 'mcp_root_uri': {
18
+ const fsPath = uriToFsPath(source.uri);
19
+ if (fsPath === null)
20
+ return (0, neverthrow_1.okAsync)([]);
21
+ return this.resolveGitIdentityAt(fsPath);
22
+ }
23
+ case 'server_cwd':
24
+ return this.resolveGitIdentityAt(this.defaultCwd);
25
+ }
24
26
  }
25
- resolveFromPath(cwd) {
26
- return neverthrow_1.ResultAsync.fromPromise(this.resolve(cwd), (cause) => ({
27
+ resolveGitIdentityAt(cwd) {
28
+ return neverthrow_1.ResultAsync.fromPromise(this.runGitCommands(cwd), (cause) => ({
27
29
  code: 'ANCHOR_RESOLVE_FAILED',
28
30
  message: `Failed to resolve workspace anchors: ${String(cause)}`,
29
31
  }));
30
32
  }
31
- async resolve(cwd) {
33
+ async runGitCommands(cwd) {
32
34
  const anchors = [];
33
35
  const branch = await this.gitCommand('git rev-parse --abbrev-ref HEAD', cwd);
34
36
  if (branch && branch !== 'HEAD') {
@@ -13,10 +13,15 @@ export type WorkspaceAnchorError = {
13
13
  readonly code: 'ANCHOR_RESOLVE_FAILED';
14
14
  readonly message: string;
15
15
  };
16
- export interface WorkspaceAnchorPortV2 {
17
- resolveAnchors(): ResultAsync<readonly WorkspaceAnchor[], WorkspaceAnchorError>;
18
- }
16
+ export type WorkspaceSource = {
17
+ readonly kind: 'explicit_path';
18
+ readonly path: string;
19
+ } | {
20
+ readonly kind: 'mcp_root_uri';
21
+ readonly uri: string;
22
+ } | {
23
+ readonly kind: 'server_cwd';
24
+ };
19
25
  export interface WorkspaceContextResolverPortV2 {
20
- resolveFromUri(rootUri: string): ResultAsync<readonly WorkspaceAnchor[], WorkspaceAnchorError>;
21
- resolveFromCwd(): ResultAsync<readonly WorkspaceAnchor[], WorkspaceAnchorError>;
26
+ resolve(source: WorkspaceSource): ResultAsync<readonly WorkspaceAnchor[], WorkspaceAnchorError>;
22
27
  }
@@ -20,7 +20,7 @@ function projectArtifactsV2(events) {
20
20
  if (e.data.outputChannel !== constants_js_1.OUTPUT_CHANNEL.ARTIFACT)
21
21
  continue;
22
22
  const payload = e.data.payload;
23
- if (payload.payloadKind !== 'artifact_ref')
23
+ if (payload.payloadKind !== constants_js_1.PAYLOAD_KIND.ARTIFACT_REF)
24
24
  continue;
25
25
  const contentPayload = payload;
26
26
  if (contentPayload.content === undefined)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exaudeus/workrail",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "description": "Step-by-step workflow enforcement for AI agents via MCP",
5
5
  "license": "MIT",
6
6
  "repository": {