sdl-mcp 0.11.13 → 0.12.1

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.
Files changed (211) hide show
  1. package/README.md +4 -4
  2. package/config/sdlmcp.config.example.json +3 -3
  3. package/config/sdlmcp.config.schema.json +11 -7
  4. package/dist/.tsbuildinfo +1 -1
  5. package/dist/agent/context-seeding.d.ts +14 -0
  6. package/dist/agent/context-seeding.d.ts.map +1 -1
  7. package/dist/agent/context-seeding.js +118 -4
  8. package/dist/agent/context-seeding.js.map +1 -1
  9. package/dist/cli/commands/index.d.ts +10 -0
  10. package/dist/cli/commands/index.d.ts.map +1 -1
  11. package/dist/cli/commands/index.js +20 -3
  12. package/dist/cli/commands/index.js.map +1 -1
  13. package/dist/cli/commands/init.d.ts +1 -1
  14. package/dist/cli/commands/init.js +7 -7
  15. package/dist/cli/commands/tool-actions.d.ts.map +1 -1
  16. package/dist/cli/commands/tool-actions.js +58 -3
  17. package/dist/cli/commands/tool-actions.js.map +1 -1
  18. package/dist/code-mode/action-catalog.d.ts +9 -0
  19. package/dist/code-mode/action-catalog.d.ts.map +1 -1
  20. package/dist/code-mode/action-catalog.js +18 -4
  21. package/dist/code-mode/action-catalog.js.map +1 -1
  22. package/dist/code-mode/descriptions.d.ts +1 -0
  23. package/dist/code-mode/descriptions.d.ts.map +1 -1
  24. package/dist/code-mode/descriptions.js +5 -1
  25. package/dist/code-mode/descriptions.js.map +1 -1
  26. package/dist/code-mode/etag-cache.d.ts +9 -2
  27. package/dist/code-mode/etag-cache.d.ts.map +1 -1
  28. package/dist/code-mode/etag-cache.js +45 -2
  29. package/dist/code-mode/etag-cache.js.map +1 -1
  30. package/dist/code-mode/index.d.ts +8 -0
  31. package/dist/code-mode/index.d.ts.map +1 -1
  32. package/dist/code-mode/index.js +39 -8
  33. package/dist/code-mode/index.js.map +1 -1
  34. package/dist/code-mode/manual-generator.d.ts.map +1 -1
  35. package/dist/code-mode/manual-generator.js +24 -21
  36. package/dist/code-mode/manual-generator.js.map +1 -1
  37. package/dist/code-mode/ref-resolver.d.ts.map +1 -1
  38. package/dist/code-mode/ref-resolver.js +30 -6
  39. package/dist/code-mode/ref-resolver.js.map +1 -1
  40. package/dist/code-mode/retrieve.d.ts +44 -0
  41. package/dist/code-mode/retrieve.d.ts.map +1 -0
  42. package/dist/code-mode/retrieve.js +68 -0
  43. package/dist/code-mode/retrieve.js.map +1 -0
  44. package/dist/code-mode/types.d.ts +7 -3
  45. package/dist/code-mode/types.d.ts.map +1 -1
  46. package/dist/code-mode/types.js +4 -2
  47. package/dist/code-mode/types.js.map +1 -1
  48. package/dist/code-mode/workflow-executor.d.ts.map +1 -1
  49. package/dist/code-mode/workflow-executor.js +88 -11
  50. package/dist/code-mode/workflow-executor.js.map +1 -1
  51. package/dist/code-mode/workflow-parser.d.ts +1 -1
  52. package/dist/code-mode/workflow-parser.d.ts.map +1 -1
  53. package/dist/code-mode/workflow-parser.js +32 -3
  54. package/dist/code-mode/workflow-parser.js.map +1 -1
  55. package/dist/code-mode/workflow-truncation.d.ts +0 -5
  56. package/dist/code-mode/workflow-truncation.d.ts.map +1 -1
  57. package/dist/code-mode/workflow-truncation.js +53 -1
  58. package/dist/code-mode/workflow-truncation.js.map +1 -1
  59. package/dist/config/types.d.ts +7 -7
  60. package/dist/config/types.d.ts.map +1 -1
  61. package/dist/config/types.js +6 -6
  62. package/dist/config/types.js.map +1 -1
  63. package/dist/db/ladybug-edges.d.ts +12 -0
  64. package/dist/db/ladybug-edges.d.ts.map +1 -1
  65. package/dist/db/ladybug-edges.js +26 -0
  66. package/dist/db/ladybug-edges.js.map +1 -1
  67. package/dist/domain/types.d.ts +4 -0
  68. package/dist/domain/types.d.ts.map +1 -1
  69. package/dist/gateway/descriptions.d.ts.map +1 -1
  70. package/dist/gateway/descriptions.js +5 -5
  71. package/dist/gateway/descriptions.js.map +1 -1
  72. package/dist/gateway/schemas.d.ts +46 -2
  73. package/dist/gateway/schemas.d.ts.map +1 -1
  74. package/dist/gateway/schemas.js +25 -8
  75. package/dist/gateway/schemas.js.map +1 -1
  76. package/dist/graph/overview.js +9 -1
  77. package/dist/graph/overview.js.map +1 -1
  78. package/dist/graph/prefetch.d.ts +1 -0
  79. package/dist/graph/prefetch.d.ts.map +1 -1
  80. package/dist/graph/prefetch.js +5 -1
  81. package/dist/graph/prefetch.js.map +1 -1
  82. package/dist/indexer/summary-generator.d.ts +6 -0
  83. package/dist/indexer/summary-generator.d.ts.map +1 -1
  84. package/dist/indexer/summary-generator.js +241 -86
  85. package/dist/indexer/summary-generator.js.map +1 -1
  86. package/dist/indexer/symbol-embedding-text.d.ts +5 -10
  87. package/dist/indexer/symbol-embedding-text.d.ts.map +1 -1
  88. package/dist/indexer/symbol-embedding-text.js +200 -0
  89. package/dist/indexer/symbol-embedding-text.js.map +1 -1
  90. package/dist/live-index/coordinator.js +1 -1
  91. package/dist/live-index/coordinator.js.map +1 -1
  92. package/dist/mcp/context-response-projection.d.ts +0 -10
  93. package/dist/mcp/context-response-projection.d.ts.map +1 -1
  94. package/dist/mcp/context-response-projection.js +536 -35
  95. package/dist/mcp/context-response-projection.js.map +1 -1
  96. package/dist/mcp/response-compression.d.ts +3 -0
  97. package/dist/mcp/response-compression.d.ts.map +1 -1
  98. package/dist/mcp/response-compression.js +21 -14
  99. package/dist/mcp/response-compression.js.map +1 -1
  100. package/dist/mcp/server-instructions.js +7 -7
  101. package/dist/mcp/server-instructions.js.map +1 -1
  102. package/dist/mcp/token-usage.d.ts +5 -0
  103. package/dist/mcp/token-usage.d.ts.map +1 -1
  104. package/dist/mcp/token-usage.js +17 -0
  105. package/dist/mcp/token-usage.js.map +1 -1
  106. package/dist/mcp/tool-call-formatter.d.ts.map +1 -1
  107. package/dist/mcp/tool-call-formatter.js +42 -12
  108. package/dist/mcp/tool-call-formatter.js.map +1 -1
  109. package/dist/mcp/tools/buffer.d.ts +1 -0
  110. package/dist/mcp/tools/buffer.d.ts.map +1 -1
  111. package/dist/mcp/tools/buffer.js +33 -1
  112. package/dist/mcp/tools/buffer.js.map +1 -1
  113. package/dist/mcp/tools/code.d.ts +6 -0
  114. package/dist/mcp/tools/code.d.ts.map +1 -1
  115. package/dist/mcp/tools/code.js +92 -13
  116. package/dist/mcp/tools/code.js.map +1 -1
  117. package/dist/mcp/tools/file-gateway.d.ts +50 -4
  118. package/dist/mcp/tools/file-gateway.d.ts.map +1 -1
  119. package/dist/mcp/tools/file-gateway.js +11 -10
  120. package/dist/mcp/tools/file-gateway.js.map +1 -1
  121. package/dist/mcp/tools/policy.d.ts +17 -0
  122. package/dist/mcp/tools/policy.d.ts.map +1 -1
  123. package/dist/mcp/tools/policy.js +18 -6
  124. package/dist/mcp/tools/policy.js.map +1 -1
  125. package/dist/mcp/tools/prRisk.d.ts +18 -1
  126. package/dist/mcp/tools/prRisk.d.ts.map +1 -1
  127. package/dist/mcp/tools/prRisk.js +95 -7
  128. package/dist/mcp/tools/prRisk.js.map +1 -1
  129. package/dist/mcp/tools/repo.d.ts.map +1 -1
  130. package/dist/mcp/tools/repo.js +73 -25
  131. package/dist/mcp/tools/repo.js.map +1 -1
  132. package/dist/mcp/tools/response.d.ts.map +1 -1
  133. package/dist/mcp/tools/response.js +17 -2
  134. package/dist/mcp/tools/response.js.map +1 -1
  135. package/dist/mcp/tools/runtime.d.ts +8 -1
  136. package/dist/mcp/tools/runtime.d.ts.map +1 -1
  137. package/dist/mcp/tools/runtime.js +84 -15
  138. package/dist/mcp/tools/runtime.js.map +1 -1
  139. package/dist/mcp/tools/search-edit/index.d.ts.map +1 -1
  140. package/dist/mcp/tools/search-edit/index.js +32 -8
  141. package/dist/mcp/tools/search-edit/index.js.map +1 -1
  142. package/dist/mcp/tools/search-edit/planner.d.ts +52 -2
  143. package/dist/mcp/tools/search-edit/planner.d.ts.map +1 -1
  144. package/dist/mcp/tools/search-edit/planner.js +48 -17
  145. package/dist/mcp/tools/search-edit/planner.js.map +1 -1
  146. package/dist/mcp/tools/search-edit/rename.d.ts +20 -0
  147. package/dist/mcp/tools/search-edit/rename.d.ts.map +1 -0
  148. package/dist/mcp/tools/search-edit/rename.js +107 -0
  149. package/dist/mcp/tools/search-edit/rename.js.map +1 -0
  150. package/dist/mcp/tools/search-edit/signature.d.ts +26 -0
  151. package/dist/mcp/tools/search-edit/signature.d.ts.map +1 -0
  152. package/dist/mcp/tools/search-edit/signature.js +421 -0
  153. package/dist/mcp/tools/search-edit/signature.js.map +1 -0
  154. package/dist/mcp/tools/search-edit/structural.d.ts +6 -0
  155. package/dist/mcp/tools/search-edit/structural.d.ts.map +1 -1
  156. package/dist/mcp/tools/search-edit/structural.js +10 -0
  157. package/dist/mcp/tools/search-edit/structural.js.map +1 -1
  158. package/dist/mcp/tools/semantic-enrichment.d.ts +2 -0
  159. package/dist/mcp/tools/semantic-enrichment.d.ts.map +1 -1
  160. package/dist/mcp/tools/semantic-enrichment.js +37 -1
  161. package/dist/mcp/tools/semantic-enrichment.js.map +1 -1
  162. package/dist/mcp/tools/symbol-edit/ast.d.ts.map +1 -1
  163. package/dist/mcp/tools/symbol-edit/ast.js +4 -1
  164. package/dist/mcp/tools/symbol-edit/ast.js.map +1 -1
  165. package/dist/mcp/tools/symbol-edit/index.d.ts.map +1 -1
  166. package/dist/mcp/tools/symbol-edit/index.js +0 -1
  167. package/dist/mcp/tools/symbol-edit/index.js.map +1 -1
  168. package/dist/mcp/tools/symbol.d.ts.map +1 -1
  169. package/dist/mcp/tools/symbol.js +23 -3
  170. package/dist/mcp/tools/symbol.js.map +1 -1
  171. package/dist/mcp/tools/tool-descriptors.d.ts +1 -0
  172. package/dist/mcp/tools/tool-descriptors.d.ts.map +1 -1
  173. package/dist/mcp/tools/tool-descriptors.js +6 -3
  174. package/dist/mcp/tools/tool-descriptors.js.map +1 -1
  175. package/dist/mcp/tools/usage.d.ts.map +1 -1
  176. package/dist/mcp/tools/usage.js +5 -0
  177. package/dist/mcp/tools/usage.js.map +1 -1
  178. package/dist/mcp/tools.d.ts +259 -156
  179. package/dist/mcp/tools.d.ts.map +1 -1
  180. package/dist/mcp/tools.js +210 -75
  181. package/dist/mcp/tools.js.map +1 -1
  182. package/dist/observability/aggregator.d.ts +3 -0
  183. package/dist/observability/aggregator.d.ts.map +1 -1
  184. package/dist/observability/aggregator.js +27 -0
  185. package/dist/observability/aggregator.js.map +1 -1
  186. package/dist/observability/event-tap.d.ts +6 -0
  187. package/dist/observability/event-tap.d.ts.map +1 -1
  188. package/dist/observability/event-tap.js.map +1 -1
  189. package/dist/observability/types.d.ts +9 -0
  190. package/dist/observability/types.d.ts.map +1 -1
  191. package/dist/observability/types.js.map +1 -1
  192. package/dist/runtime/executor.d.ts +6 -0
  193. package/dist/runtime/executor.d.ts.map +1 -1
  194. package/dist/runtime/executor.js +16 -8
  195. package/dist/runtime/executor.js.map +1 -1
  196. package/dist/runtime/response-artifacts.d.ts +14 -2
  197. package/dist/runtime/response-artifacts.d.ts.map +1 -1
  198. package/dist/runtime/response-artifacts.js +66 -17
  199. package/dist/runtime/response-artifacts.js.map +1 -1
  200. package/dist/runtime/runtimes.d.ts.map +1 -1
  201. package/dist/runtime/runtimes.js +15 -0
  202. package/dist/runtime/runtimes.js.map +1 -1
  203. package/dist/semantic/enrichment.d.ts +2 -0
  204. package/dist/semantic/enrichment.d.ts.map +1 -1
  205. package/dist/semantic/enrichment.js.map +1 -1
  206. package/dist/server.d.ts +2 -2
  207. package/dist/server.d.ts.map +1 -1
  208. package/dist/server.js +123 -25
  209. package/dist/server.js.map +1 -1
  210. package/package.json +14 -8
  211. package/templates/SDL.md +25 -16
@@ -4,30 +4,32 @@
4
4
  */
5
5
  /** Fields kept in the compact broad response before final model-content projection.
6
6
  * Shared with context-engine.ts for pre-truncation compaction. */
7
- export const BROAD_VISIBLE_FIELDS = new Set([
8
- "taskId",
7
+ const BROAD_MODEL_VISIBLE_FIELDS = new Set([
9
8
  "taskType",
10
9
  "success",
11
10
  "summary",
12
11
  "answer",
13
12
  "finalEvidence",
14
13
  "nextBestAction",
15
- "retrievalEvidence",
16
- "diagnostics",
17
14
  "error",
18
15
  "truncation",
16
+ ]);
17
+ export const BROAD_VISIBLE_FIELDS = new Set([
18
+ ...BROAD_MODEL_VISIBLE_FIELDS,
19
19
  "etag",
20
- "_displayFooter",
20
+ "diagnostics",
21
+ "retrievalEvidence",
21
22
  ]);
22
23
  /** Tool names eligible for context-specific compaction. */
23
24
  const CONTEXT_TOOLS = new Set(["sdl.context"]);
25
+ const HIDDEN_ETAG_MODEL_FIELDS = new Set(["etag", "etagCache", "sliceEtag"]);
24
26
  const ALWAYS_INTERNAL_MODEL_FIELDS = new Set([
25
27
  "_displayFooter",
28
+ "_packedPayload",
26
29
  "_packedStats",
27
30
  "_rawContext",
28
31
  "_tokenUsage",
29
32
  "actionsTaken",
30
- "backupPath",
31
33
  "indexUpdate",
32
34
  "metrics",
33
35
  "packedStats",
@@ -36,12 +38,148 @@ const ALWAYS_INTERNAL_MODEL_FIELDS = new Set([
36
38
  "serverDiagnostics",
37
39
  "taskId",
38
40
  "timings",
41
+ "tokenEstimate",
39
42
  "totalTokens",
40
- "trace",
43
+ "etagCache",
44
+ "sliceEtag",
45
+ ]);
46
+ const NO_OP_FALSE_FIELDS = new Set([
47
+ "truncated",
48
+ "truncation",
49
+ "blastRadiusTruncated",
50
+ ]);
51
+ const NO_OP_NULL_FIELDS = new Set([
52
+ "signal",
41
53
  ]);
54
+ const NO_OP_EMPTY_ARRAY_FIELDS = new Set([
55
+ "warnings",
56
+ "quotingWarnings",
57
+ "serverDriftWarnings",
58
+ "filesSkipped",
59
+ "filesSkippedByReason",
60
+ "staleSymbols",
61
+ "missedIdentifiers",
62
+ ]);
63
+ const COMPACT_FAILURE_TRACE_FIELDS = new Set([
64
+ "stepIndex",
65
+ "fn",
66
+ "action",
67
+ "kind",
68
+ "status",
69
+ "message",
70
+ "fallbackTools",
71
+ ]);
72
+ const COMPACT_DEBUG_MODEL_FIELDS = new Set([
73
+ "aggregateStats",
74
+ "amplifiers",
75
+ "astFingerprint",
76
+ "bytes",
77
+ "bytesWritten",
78
+ "callResolution",
79
+ "clustersHint",
80
+ "confidenceDistribution",
81
+ "created",
82
+ "deduplicated",
83
+ "detailLevel",
84
+ "detailLevelMetadata",
85
+ "diagnostics",
86
+ "entryPoints",
87
+ "expiresAt",
88
+ "hotspots",
89
+ "lease",
90
+ "ledgerVersion",
91
+ "linesWritten",
92
+ "matchCount",
93
+ "matchedLineNumbers",
94
+ "mtimeMs",
95
+ "originalLines",
96
+ "pprBoosts",
97
+ "processes",
98
+ "relevance",
99
+ "returnedLines",
100
+ "searchedStreams",
101
+ "sessionDelta",
102
+ "sha256",
103
+ "shortId",
104
+ "sliceEtag",
105
+ "stderrPreview",
106
+ "stdinBytes",
107
+ "stdinSha256",
108
+ "stdoutPreview",
109
+ "symbolsRecorded",
110
+ "symbolIndex",
111
+ "symptomType",
112
+ "totalBytes",
113
+ "totalLines",
114
+ "truncationWarning",
115
+ "versionId",
116
+ "visibility",
117
+ "whyApproved",
118
+ ]);
119
+ const REPO_ID_VISIBLE_TOOLS = new Set([
120
+ "repo.status",
121
+ "sdl.repo.status",
122
+ "repo.overview",
123
+ "sdl.repo.overview",
124
+ "delta.get",
125
+ "sdl.delta.get",
126
+ "sdl.workflow",
127
+ "workflow",
128
+ ]);
129
+ const PRECONDITION_MODEL_FIELDS = new Set([
130
+ "astFingerprint",
131
+ "expectedAstFingerprint",
132
+ "expectedRange",
133
+ "mtimeMs",
134
+ "preconditionSnapshot",
135
+ "sha256",
136
+ ]);
137
+ const WORKFLOW_CHILD_TOOL_NAMES = {
138
+ actionSearch: "action.search",
139
+ codeHotPath: "code.getHotPath",
140
+ codeNeedWindow: "code.needWindow",
141
+ codeSkeleton: "code.getSkeleton",
142
+ deltaGet: "delta.get",
143
+ file: "sdl.file",
144
+ sdlFile: "sdl.file",
145
+ fileRead: "file.read",
146
+ fileWrite: "file.write",
147
+ indexRefresh: "index.refresh",
148
+ policyGet: "policy.get",
149
+ policySet: "policy.set",
150
+ prRiskAnalyze: "pr.risk.analyze",
151
+ repoOverview: "repo.overview",
152
+ repoStatus: "repo.status",
153
+ runtimeExecute: "runtime.execute",
154
+ runtimeQueryOutput: "runtime.queryOutput",
155
+ searchEdit: "search.edit",
156
+ sliceBuild: "slice.build",
157
+ sliceRefresh: "slice.refresh",
158
+ symbolEdit: "symbol.edit",
159
+ symbolGetCard: "symbol.getCard",
160
+ symbolGetCards: "symbol.getCards",
161
+ symbolSearch: "symbol.search",
162
+ usageStats: "usage.stats",
163
+ };
42
164
  function isRecord(value) {
43
165
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
44
166
  }
167
+ function stripFullDetailHiddenFieldsForModel(value) {
168
+ if (Array.isArray(value)) {
169
+ return value.map(stripFullDetailHiddenFieldsForModel);
170
+ }
171
+ if (!isRecord(value)) {
172
+ return value;
173
+ }
174
+ const projected = {};
175
+ for (const [key, itemValue] of Object.entries(value)) {
176
+ if (HIDDEN_ETAG_MODEL_FIELDS.has(key) || PRECONDITION_MODEL_FIELDS.has(key)) {
177
+ continue;
178
+ }
179
+ projected[key] = stripFullDetailHiddenFieldsForModel(itemValue);
180
+ }
181
+ return projected;
182
+ }
45
183
  function copyIfPresent(source, target, key) {
46
184
  if (key in source) {
47
185
  target[key] = source[key];
@@ -64,27 +202,115 @@ function projectEvidenceForModel(value) {
64
202
  return projected;
65
203
  });
66
204
  }
205
+ function normalizedDetail(value) {
206
+ return value === "full" || value === "standard" ? value : "compact";
207
+ }
67
208
  function modelOptionsFromArgs(args) {
68
209
  const options = isRecord(args.options) ? args.options : {};
69
210
  return {
70
- includeDiagnostics: args.includeDiagnostics === true,
211
+ detail: normalizedDetail(args.detail ?? options.detail),
212
+ includeDiagnostics: args.includeDiagnostics === true
213
+ || options.includeDiagnostics === true,
71
214
  includeRetrievalEvidence: args.includeRetrievalEvidence === true
72
215
  || options.includeRetrievalEvidence === true,
216
+ includeTelemetry: args.includeTelemetry === true
217
+ || options.includeTelemetry === true,
218
+ includeTrace: args.trace !== undefined,
219
+ includeProcesses: args.includeProcesses === true,
220
+ includeResolutionMetadata: args.includeResolutionMetadata === true,
221
+ fileOp: typeof args.op === "string" ? args.op : undefined,
73
222
  };
74
223
  }
224
+ function isFullDetail(options) {
225
+ return options.detail === "full";
226
+ }
227
+ function isNoOpTruncationObject(value) {
228
+ if (!isRecord(value)) {
229
+ return false;
230
+ }
231
+ if (value.truncated === true
232
+ || value.stdoutTruncated === true
233
+ || value.stderrTruncated === true) {
234
+ return false;
235
+ }
236
+ return Object.keys(value).every((key) => key === "truncated"
237
+ || key === "stdoutTruncated"
238
+ || key === "stderrTruncated"
239
+ || key === "totalStdoutBytes"
240
+ || key === "totalStderrBytes");
241
+ }
242
+ function shouldDropNoOpField(key, value) {
243
+ if (value === false && NO_OP_FALSE_FIELDS.has(key)) {
244
+ return true;
245
+ }
246
+ if (key === "truncation" && isNoOpTruncationObject(value)) {
247
+ return true;
248
+ }
249
+ if (value === null && NO_OP_NULL_FIELDS.has(key)) {
250
+ return true;
251
+ }
252
+ if (Array.isArray(value)
253
+ && value.length === 0
254
+ && NO_OP_EMPTY_ARRAY_FIELDS.has(key)) {
255
+ return true;
256
+ }
257
+ if (key === "rollback" && isRecord(value)) {
258
+ return Object.keys(value).length === 0 || value.triggered === false;
259
+ }
260
+ return false;
261
+ }
75
262
  function shouldKeepModelField(toolName, key, options) {
76
- if (toolName === "sdl.workflow" && key === "trace") {
263
+ if (PRECONDITION_MODEL_FIELDS.has(key)) {
264
+ return false;
265
+ }
266
+ if (isFullDetail(options)) {
77
267
  return true;
78
268
  }
269
+ if (key === "trace") {
270
+ return toolName === "sdl.workflow" && options.includeTrace;
271
+ }
79
272
  if (ALWAYS_INTERNAL_MODEL_FIELDS.has(key)) {
80
273
  return false;
81
274
  }
275
+ if (key === "repoId") {
276
+ return REPO_ID_VISIBLE_TOOLS.has(toolName);
277
+ }
278
+ if (key === "processes") {
279
+ return options.includeProcesses;
280
+ }
281
+ if (key === "callResolution") {
282
+ return options.includeResolutionMetadata;
283
+ }
284
+ if (COMPACT_DEBUG_MODEL_FIELDS.has(key)) {
285
+ return false;
286
+ }
287
+ if (toolName === "slice.build" && key === "budget") {
288
+ return false;
289
+ }
290
+ if ((toolName === "symbol.search" || toolName === "sdl.symbol.search") && key === "symbols") {
291
+ return false;
292
+ }
82
293
  if (key === "diagnostics") {
83
294
  return options.includeDiagnostics;
84
295
  }
85
296
  if (key === "retrievalEvidence") {
86
297
  return options.includeRetrievalEvidence;
87
298
  }
299
+ if (key === "estimatedTokens"
300
+ || key === "originalLines"
301
+ || key === "matchedLineNumbers"
302
+ || key === "generatedAt"
303
+ || key === "tokenMetrics") {
304
+ return false;
305
+ }
306
+ if (options.detail === "compact"
307
+ && !options.includeTelemetry
308
+ && (key === "prefetchStats"
309
+ || key === "strategyMetrics"
310
+ || key === "topStrategies"
311
+ || key === "healthComponents")) {
312
+ return false;
313
+ }
88
314
  return true;
89
315
  }
90
316
  function projectGenericValueForModel(toolName, value, options) {
@@ -96,6 +322,12 @@ function projectGenericValueForModel(toolName, value, options) {
96
322
  }
97
323
  const projected = {};
98
324
  for (const [key, itemValue] of Object.entries(value)) {
325
+ if (HIDDEN_ETAG_MODEL_FIELDS.has(key)) {
326
+ continue;
327
+ }
328
+ if (shouldDropNoOpField(key, itemValue)) {
329
+ continue;
330
+ }
99
331
  if (key === "diagnostics" && options.includeDiagnostics) {
100
332
  projected[key] = itemValue;
101
333
  continue;
@@ -106,7 +338,7 @@ function projectGenericValueForModel(toolName, value, options) {
106
338
  }
107
339
  if (key === "policyDecision") {
108
340
  const decision = isRecord(itemValue) ? itemValue : {};
109
- if (Array.isArray(decision.deniedReasons)) {
341
+ if (Array.isArray(decision.deniedReasons) && decision.deniedReasons.length > 0) {
110
342
  projected.policyDecision = { deniedReasons: decision.deniedReasons };
111
343
  }
112
344
  continue;
@@ -114,7 +346,11 @@ function projectGenericValueForModel(toolName, value, options) {
114
346
  if (!shouldKeepModelField(toolName, key, options)) {
115
347
  continue;
116
348
  }
117
- projected[key] = projectGenericValueForModel(toolName, itemValue, options);
349
+ const projectedValue = projectGenericValueForModel(toolName, itemValue, options);
350
+ if (isRecord(projectedValue) && Object.keys(projectedValue).length === 0) {
351
+ continue;
352
+ }
353
+ projected[key] = projectedValue;
118
354
  }
119
355
  return projected;
120
356
  }
@@ -131,8 +367,9 @@ function projectContextResultForModel(result, options) {
131
367
  }
132
368
  copyIfPresent(result, projected, "nextBestAction");
133
369
  copyIfPresent(result, projected, "error");
134
- copyIfPresent(result, projected, "truncation");
135
- copyIfPresent(result, projected, "etag");
370
+ if (result.truncation !== false) {
371
+ copyIfPresent(result, projected, "truncation");
372
+ }
136
373
  if (options.includeRetrievalEvidence) {
137
374
  copyIfPresent(result, projected, "retrievalEvidence");
138
375
  }
@@ -141,57 +378,302 @@ function projectContextResultForModel(result, options) {
141
378
  }
142
379
  return projected;
143
380
  }
381
+ function projectCompactFailureTrace(value) {
382
+ if (!isRecord(value)) {
383
+ return value;
384
+ }
385
+ const projected = {};
386
+ for (const [key, itemValue] of Object.entries(value)) {
387
+ if (COMPACT_FAILURE_TRACE_FIELDS.has(key)) {
388
+ projected[key] = itemValue;
389
+ }
390
+ }
391
+ return projected;
392
+ }
393
+ function workflowStepArgsAt(workflowArgs, stepIndex) {
394
+ const steps = workflowArgs.steps;
395
+ if (!Array.isArray(steps)) {
396
+ return undefined;
397
+ }
398
+ const step = steps[stepIndex];
399
+ return isRecord(step) ? step.args : undefined;
400
+ }
401
+ function inferWorkflowFileOp(childToolName, result, args) {
402
+ if (isRecord(args) && typeof args.op === "string") {
403
+ return args.op;
404
+ }
405
+ if (childToolName === "sdl.file" && isRecord(result) && "preconditionSnapshot" in result) {
406
+ return "searchEditPreview";
407
+ }
408
+ return undefined;
409
+ }
410
+ function projectWorkflowStepResultForModel(fn, result, options, args) {
411
+ const childToolName = typeof fn === "string"
412
+ ? WORKFLOW_CHILD_TOOL_NAMES[fn] ?? "sdl.workflow"
413
+ : "sdl.workflow";
414
+ const childArgOptions = isRecord(args) ? modelOptionsFromArgs(args) : undefined;
415
+ const fileOp = inferWorkflowFileOp(childToolName, result, args);
416
+ if (isFullDetail(options)) {
417
+ return stripFullDetailHiddenFieldsForModel(result);
418
+ }
419
+ const childOptions = {
420
+ ...options,
421
+ detail: "compact",
422
+ includeDiagnostics: false,
423
+ includeRetrievalEvidence: false,
424
+ includeTelemetry: false,
425
+ includeTrace: false,
426
+ ...(childArgOptions ?? {}),
427
+ fileOp: fileOp ?? childArgOptions?.fileOp ?? options.fileOp,
428
+ };
429
+ if (isFullDetail(childOptions)) {
430
+ return stripFullDetailHiddenFieldsForModel(result);
431
+ }
432
+ if (childToolName === "repo.status") {
433
+ if (childOptions.detail === "compact" && !childOptions.includeTelemetry) {
434
+ return isRecord(result) ? projectRepoStatusForModel(result, childOptions) : result;
435
+ }
436
+ return projectGenericValueForModel(childToolName, result, childOptions);
437
+ }
438
+ if (childToolName === "action.search" && childOptions.detail === "compact") {
439
+ return isRecord(result) ? projectActionSearchForModel(result) : result;
440
+ }
441
+ if (childToolName === "usage.stats") {
442
+ return isRecord(result) ? projectUsageStatsForModel(result) : result;
443
+ }
444
+ return projectGenericValueForModel(childToolName, result, childOptions);
445
+ }
446
+ function projectWorkflowResultForModel(result, options, workflowArgs = {}) {
447
+ const includeWorkflowTelemetry = options.includeTrace
448
+ || options.includeDiagnostics
449
+ || options.includeTelemetry
450
+ || isFullDetail(options);
451
+ const projected = {};
452
+ const rawResults = Array.isArray(result.results) ? result.results : [];
453
+ projected.results = rawResults.map((item, index) => {
454
+ if (!isRecord(item)) {
455
+ return item;
456
+ }
457
+ const status = typeof item.status === "string" ? item.status : "ok";
458
+ const stepIndex = typeof item.stepIndex === "number" ? item.stepIndex : index;
459
+ const stepArgs = workflowStepArgsAt(workflowArgs, stepIndex) ?? item.args;
460
+ if (status === "ok") {
461
+ const successStep = { fn: item.fn };
462
+ if (includeWorkflowTelemetry) {
463
+ copyIfPresent(item, successStep, "stepIndex");
464
+ copyIfPresent(item, successStep, "tokens");
465
+ copyIfPresent(item, successStep, "durationMs");
466
+ copyIfPresent(item, successStep, "status");
467
+ }
468
+ if ("result" in item) {
469
+ successStep.result = projectWorkflowStepResultForModel(item.fn, item.result, options, stepArgs);
470
+ }
471
+ if (item.truncatedResponse) {
472
+ successStep.truncatedResponse = item.truncatedResponse;
473
+ }
474
+ return successStep;
475
+ }
476
+ const failureStep = { fn: item.fn, status };
477
+ copyIfPresent(item, failureStep, "error");
478
+ copyIfPresent(item, failureStep, "fallbackTools");
479
+ copyIfPresent(item, failureStep, "blockedByStep");
480
+ copyIfPresent(item, failureStep, "blockedByFn");
481
+ copyIfPresent(item, failureStep, "blockedByError");
482
+ if ("failureTrace" in item) {
483
+ failureStep.failureTrace = projectCompactFailureTrace(item.failureTrace);
484
+ }
485
+ if ("result" in item && item.result !== null && item.result !== undefined) {
486
+ failureStep.result = projectWorkflowStepResultForModel(item.fn, item.result, options, stepArgs);
487
+ }
488
+ return failureStep;
489
+ });
490
+ if (includeWorkflowTelemetry) {
491
+ copyIfPresent(result, projected, "durationMs");
492
+ copyIfPresent(result, projected, "totalTokens");
493
+ }
494
+ if (result.truncated === true) {
495
+ projected.truncated = true;
496
+ }
497
+ if (options.includeTrace) {
498
+ copyIfPresent(result, projected, "trace");
499
+ }
500
+ if (options.includeDiagnostics) {
501
+ copyIfPresent(result, projected, "diagnostics");
502
+ }
503
+ return projected;
504
+ }
505
+ function projectUsageStatsForModel(result) {
506
+ const projected = {};
507
+ copyIfPresent(result, projected, "formattedSummary");
508
+ return projected;
509
+ }
510
+ function projectDerivedStateForModel(value) {
511
+ if (!isRecord(value)) {
512
+ return value;
513
+ }
514
+ const projected = {};
515
+ copyIfPresent(value, projected, "stale");
516
+ for (const key of [
517
+ "clustersDirty",
518
+ "processesDirty",
519
+ "algorithmsDirty",
520
+ "summariesDirty",
521
+ "embeddingsDirty",
522
+ ]) {
523
+ if (value[key] === true) {
524
+ projected[key] = true;
525
+ }
526
+ }
527
+ copyIfPresent(value, projected, "lastError");
528
+ copyIfPresent(value, projected, "nextBestAction");
529
+ return projected;
530
+ }
531
+ function watcherNeedsAttention(value) {
532
+ return value.running === false
533
+ || value.stale === true
534
+ || (typeof value.errors === "number" && value.errors > 0)
535
+ || Boolean(value.fallbackReason);
536
+ }
537
+ function projectWatcherHealthForModel(value) {
538
+ if (!isRecord(value) || !watcherNeedsAttention(value)) {
539
+ return undefined;
540
+ }
541
+ const projected = {};
542
+ for (const key of [
543
+ "enabled",
544
+ "running",
545
+ "provider",
546
+ "fallbackReason",
547
+ "errors",
548
+ "queueDepth",
549
+ "stale",
550
+ ]) {
551
+ copyIfPresent(value, projected, key);
552
+ }
553
+ return projected;
554
+ }
555
+ function projectRepoStatusForModel(result, options) {
556
+ const projected = {};
557
+ for (const key of [
558
+ "repoId",
559
+ "rootPath",
560
+ "latestVersionId",
561
+ "filesIndexed",
562
+ "symbolsIndexed",
563
+ "lastIndexedAt",
564
+ ]) {
565
+ copyIfPresent(result, projected, key);
566
+ }
567
+ if (result.healthAvailable === true || result.healthScore !== undefined) {
568
+ copyIfPresent(result, projected, "healthAvailable");
569
+ copyIfPresent(result, projected, "healthScore");
570
+ }
571
+ if ("derivedState" in result) {
572
+ projected.derivedState = projectDerivedStateForModel(result.derivedState);
573
+ }
574
+ const compactWatcher = projectWatcherHealthForModel(result.watcherHealth);
575
+ if (compactWatcher !== undefined) {
576
+ projected.watcherHealth = compactWatcher;
577
+ }
578
+ copyIfPresent(result, projected, "nextBestAction");
579
+ if (options.includeDiagnostics) {
580
+ copyIfPresent(result, projected, "diagnostics");
581
+ }
582
+ if (options.includeRetrievalEvidence) {
583
+ copyIfPresent(result, projected, "retrievalEvidence");
584
+ }
585
+ return projected;
586
+ }
587
+ function compactSchemaSummary(value) {
588
+ if (!Array.isArray(value)) {
589
+ return value;
590
+ }
591
+ return value.map((field) => {
592
+ if (!isRecord(field)) {
593
+ return field;
594
+ }
595
+ const projected = {};
596
+ for (const key of ["name", "type", "required", "default", "enumValues", "subFields"]) {
597
+ if (key === "subFields") {
598
+ if ("subFields" in field) {
599
+ projected.subFields = compactSchemaSummary(field.subFields);
600
+ }
601
+ }
602
+ else {
603
+ copyIfPresent(field, projected, key);
604
+ }
605
+ }
606
+ return projected;
607
+ });
608
+ }
609
+ function projectActionSearchForModel(result) {
610
+ const projected = {};
611
+ if (Array.isArray(result.actions)) {
612
+ projected.actions = result.actions.map((action) => {
613
+ if (!isRecord(action)) {
614
+ return action;
615
+ }
616
+ const compact = {};
617
+ copyIfPresent(action, compact, "action");
618
+ copyIfPresent(action, compact, "fn");
619
+ copyIfPresent(action, compact, "requiredParams");
620
+ copyIfPresent(action, compact, "disabled");
621
+ copyIfPresent(action, compact, "disabledReason");
622
+ if (isRecord(action.schemaSummary) && Array.isArray(action.schemaSummary.fields)) {
623
+ compact.schemaSummary = {
624
+ fields: compactSchemaSummary(action.schemaSummary.fields),
625
+ };
626
+ }
627
+ return compact;
628
+ });
629
+ }
630
+ copyIfPresent(result, projected, "summary");
631
+ copyIfPresent(result, projected, "total");
632
+ copyIfPresent(result, projected, "hasMore");
633
+ copyIfPresent(result, projected, "nextCursor");
634
+ copyIfPresent(result, projected, "disabledHint");
635
+ copyIfPresent(result, projected, "schemaHint");
636
+ return projected;
637
+ }
144
638
  /**
145
639
  * Returns true when the result looks like a broad context response that
146
640
  * should be compacted.
147
641
  */
148
642
  export function isBroadContextResult(toolName, result) {
149
- if (!CONTEXT_TOOLS.has(toolName))
643
+ if (!CONTEXT_TOOLS.has(toolName)) {
150
644
  return false;
151
- if (!isRecord(result))
645
+ }
646
+ if (!isRecord(result)) {
152
647
  return false;
648
+ }
153
649
  const r = result;
154
- // Broad results have actionsTaken + path + metrics (precise mode strips some of these
155
- // but still has actionsTaken). The key differentiator: broad mode has `answer` field.
156
- // Also check it's not an error result (which should pass through unchanged).
157
650
  return ("taskId" in r &&
158
651
  "actionsTaken" in r &&
159
652
  "answer" in r &&
160
653
  r.success !== undefined);
161
654
  }
162
- /**
163
- * Project a broad context result to its compact internal response form.
164
- * Returns the original result unchanged if it doesn't qualify.
165
- */
166
655
  export function projectBroadContextResult(toolName, result) {
167
- if (!isBroadContextResult(toolName, result))
656
+ if (!isBroadContextResult(toolName, result)) {
168
657
  return result;
658
+ }
169
659
  const r = result;
170
660
  const projected = {};
171
661
  for (const key of Object.keys(r)) {
172
- if (BROAD_VISIBLE_FIELDS.has(key)) {
662
+ if (BROAD_MODEL_VISIBLE_FIELDS.has(key)) {
173
663
  projected[key] = r[key];
174
664
  }
175
665
  }
176
666
  return projected;
177
667
  }
178
- /**
179
- * Project tool responses before token accounting while keeping the internal raw
180
- * baseline hint that `computeTokenUsage()` needs.
181
- */
182
668
  export function projectContextResultForUsageAccounting(toolName, result, args = {}) {
183
669
  const projected = projectToolResultForModelContent(toolName, result, args);
184
- if (!isRecord(projected) || projected === result) {
670
+ if (!isRecord(projected)) {
185
671
  return result;
186
672
  }
187
- const accountingResult = projected;
188
673
  if ("_rawContext" in result) {
189
- return {
190
- ...accountingResult,
191
- _rawContext: result._rawContext,
192
- };
674
+ return { ...projected, _rawContext: result._rawContext };
193
675
  }
194
- return accountingResult;
676
+ return projected;
195
677
  }
196
678
  /**
197
679
  * Project the payload serialized into MCP text content for the model/user.
@@ -203,9 +685,28 @@ export function projectToolResultForModelContent(toolName, result, args = {}) {
203
685
  return result;
204
686
  }
205
687
  const options = modelOptionsFromArgs(args);
688
+ if (toolName === "sdl.workflow" || toolName === "workflow") {
689
+ return projectWorkflowResultForModel(result, options, args);
690
+ }
691
+ if (isFullDetail(options)) {
692
+ return stripFullDetailHiddenFieldsForModel(result);
693
+ }
206
694
  if (CONTEXT_TOOLS.has(toolName) && ("answer" in result || "finalEvidence" in result)) {
207
695
  return projectContextResultForModel(result, options);
208
696
  }
697
+ if (toolName === "usage.stats" || toolName === "sdl.usage.stats") {
698
+ return projectUsageStatsForModel(result);
699
+ }
700
+ if (toolName === "repo.status" || toolName === "sdl.repo.status") {
701
+ if (options.detail === "compact" && !options.includeTelemetry) {
702
+ return projectRepoStatusForModel(result, options);
703
+ }
704
+ }
705
+ if (toolName === "action.search" || toolName === "sdl.action.search") {
706
+ if (options.detail === "compact") {
707
+ return projectActionSearchForModel(result);
708
+ }
709
+ }
209
710
  return projectGenericValueForModel(toolName, result, options);
210
711
  }
211
712
  //# sourceMappingURL=context-response-projection.js.map