stitchkit 0.91.1 → 0.92.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.
Files changed (87) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/dist/agent-runtime-coding-tools.js +3 -3
  3. package/dist/agent-runtime-harness.js +6 -6
  4. package/dist/agent-runtime-sandbox.js +3 -3
  5. package/dist/agent-runtime.js +9 -9
  6. package/dist/cli.d.ts +6 -3
  7. package/dist/cli.d.ts.map +1 -1
  8. package/dist/cli.js +371 -50
  9. package/dist/contract/define.d.ts +84 -2
  10. package/dist/contract/define.d.ts.map +1 -1
  11. package/dist/contract/index.d.ts +1 -1
  12. package/dist/contract/index.d.ts.map +1 -1
  13. package/dist/{index-qrbdq8jk.js → index-2c2bjw3s.js} +3 -3
  14. package/dist/{index-ya611vx3.js → index-7n145nbe.js} +183 -109
  15. package/dist/{index-bh70rk41.js → index-bx75zwt7.js} +3 -3
  16. package/dist/{index-709nh7z7.js → index-cxqhvq21.js} +2 -1
  17. package/dist/{index-13cjtmrw.js → index-e0znv5gn.js} +31 -8
  18. package/dist/{index-f4p4b8f6.js → index-e42wzzz5.js} +3 -3
  19. package/dist/{index-13e1k7v9.js → index-f477k430.js} +1 -1
  20. package/dist/{index-qjeyx5t2.js → index-fq77yfzc.js} +1 -1
  21. package/dist/{index-fenaekmk.js → index-h9etkkyk.js} +37 -27
  22. package/dist/{index-1qvdwnp2.js → index-mzvgxp0n.js} +2 -2
  23. package/dist/{index-zsqy3xfn.js → index-n0f51dfn.js} +4 -4
  24. package/dist/{index-bv7mytab.js → index-sr93cwf9.js} +1 -1
  25. package/dist/{index-vsbzgd7b.js → index-tmwcrptx.js} +1 -0
  26. package/dist/{index-b971qjes.js → index-v5573g1k.js} +1 -1
  27. package/dist/{index-8z9we758.js → index-vjpvjqpn.js} +1 -1
  28. package/dist/{index-bx6yq2m4.js → index-vk3kq9sb.js} +1 -1
  29. package/dist/{index-137jjs4v.js → index-yewwh1w4.js} +1 -1
  30. package/dist/{index-mqhjmadk.js → index-yn8remb1.js} +61 -57
  31. package/dist/index.js +4 -4
  32. package/dist/internal/atomic-file.d.ts +21 -0
  33. package/dist/internal/atomic-file.d.ts.map +1 -0
  34. package/dist/internal/errors.d.ts +10 -0
  35. package/dist/internal/errors.d.ts.map +1 -1
  36. package/dist/node.js +5 -5
  37. package/dist/observability/audit.d.ts +5 -1
  38. package/dist/observability/audit.d.ts.map +1 -1
  39. package/dist/observability/changes.d.ts.map +1 -1
  40. package/dist/observability/context.d.ts +27 -6
  41. package/dist/observability/context.d.ts.map +1 -1
  42. package/dist/observability/event.d.ts +34 -6
  43. package/dist/observability/event.d.ts.map +1 -1
  44. package/dist/observability/index.d.ts +2 -1
  45. package/dist/observability/index.d.ts.map +1 -1
  46. package/dist/observability/index.js +51 -7
  47. package/dist/observability/work.d.ts +55 -0
  48. package/dist/observability/work.d.ts.map +1 -0
  49. package/dist/remote.js +3 -3
  50. package/dist/server/context-contribution.d.ts.map +1 -1
  51. package/dist/server/index.js +7 -7
  52. package/dist/server/types.d.ts +20 -6
  53. package/dist/server/types.d.ts.map +1 -1
  54. package/dist/testing/surface-manifest.d.ts.map +1 -1
  55. package/dist/testing.js +9 -7
  56. package/dist/tool-invoker.js +6 -6
  57. package/dist/tools/cli-checkpoint.d.ts +24 -0
  58. package/dist/tools/cli-checkpoint.d.ts.map +1 -0
  59. package/dist/tools/cli-format.d.ts +10 -0
  60. package/dist/tools/cli-format.d.ts.map +1 -1
  61. package/dist/tools/cli-invoke.d.ts +118 -0
  62. package/dist/tools/cli-invoke.d.ts.map +1 -0
  63. package/dist/tools/cli-manifest.d.ts +6 -9
  64. package/dist/tools/cli-manifest.d.ts.map +1 -1
  65. package/dist/tools/cli-signature.d.ts +81 -0
  66. package/dist/tools/cli-signature.d.ts.map +1 -0
  67. package/dist/tools/cli-stream.d.ts +93 -0
  68. package/dist/tools/cli-stream.d.ts.map +1 -0
  69. package/dist/tools/cli-update.d.ts +62 -0
  70. package/dist/tools/cli-update.d.ts.map +1 -1
  71. package/dist/tools/cli.d.ts +4 -13
  72. package/dist/tools/cli.d.ts.map +1 -1
  73. package/dist/tools/connections/index.js +2 -2
  74. package/dist/tools/execute.d.ts +21 -0
  75. package/dist/tools/execute.d.ts.map +1 -1
  76. package/dist/tools/mcp-progress.d.ts +46 -0
  77. package/dist/tools/mcp-progress.d.ts.map +1 -0
  78. package/dist/tools/mcp-round-policy.d.ts +25 -1
  79. package/dist/tools/mcp-round-policy.d.ts.map +1 -1
  80. package/dist/tools/mcp-round.d.ts +20 -1
  81. package/dist/tools/mcp-round.d.ts.map +1 -1
  82. package/dist/tools/mcp-trace.d.ts +9 -1
  83. package/dist/tools/mcp-trace.d.ts.map +1 -1
  84. package/dist/tools/mount-wait.d.ts.map +1 -1
  85. package/dist/tools.js +160 -51
  86. package/llms-full.txt +358 -8
  87. package/package.json +1 -1
package/dist/tools.js CHANGED
@@ -1,14 +1,10 @@
1
- import {
2
- compareCodepoints,
3
- serializeCanonicalJson
4
- } from "./index-0j3vcp5m.js";
5
1
  import {
6
2
  ManagedFileError
7
3
  } from "./index-actkayzn.js";
8
4
  import {
9
5
  signJwt,
10
6
  verifyPkce
11
- } from "./index-bv7mytab.js";
7
+ } from "./index-sr93cwf9.js";
12
8
  import"./index-hr4tzbwq.js";
13
9
  import {
14
10
  DEFAULT_CORS_ALLOW_HEADERS,
@@ -18,7 +14,7 @@ import {
18
14
  guardSignalCallback,
19
15
  mediaTypeEssence,
20
16
  reportSignalError
21
- } from "./index-709nh7z7.js";
17
+ } from "./index-cxqhvq21.js";
22
18
  import {
23
19
  redact
24
20
  } from "./index-6kyksz9y.js";
@@ -26,15 +22,12 @@ import {
26
22
  buildToolManifest,
27
23
  describeToolCatalog,
28
24
  mountAgent
29
- } from "./index-f4p4b8f6.js";
25
+ } from "./index-e42wzzz5.js";
30
26
  import {
31
27
  AgentToolError,
32
28
  createLocalStepDurability,
33
29
  isAgentToolError
34
30
  } from "./index-kw9t5ayn.js";
35
- import {
36
- argumentsDigest
37
- } from "./index-a916km3r.js";
38
31
  import {
39
32
  AsyncOperationCancelResultSchema,
40
33
  McpAnnotationsSchema,
@@ -46,7 +39,7 @@ import {
46
39
  } from "./index-4fpa9dy2.js";
47
40
  import {
48
41
  createToolInvoker
49
- } from "./index-bh70rk41.js";
42
+ } from "./index-bx75zwt7.js";
50
43
  import {
51
44
  WaitTimeoutError,
52
45
  createCli,
@@ -55,31 +48,39 @@ import {
55
48
  fetchPinnedDocument,
56
49
  readCapped,
57
50
  runWaitOperation
58
- } from "./index-ya611vx3.js";
51
+ } from "./index-7n145nbe.js";
52
+ import {
53
+ compareCodepoints,
54
+ serializeCanonicalJson
55
+ } from "./index-0j3vcp5m.js";
59
56
  import"./index-sbdmyz75.js";
60
57
  import {
61
58
  collectToolSurface
62
- } from "./index-qrbdq8jk.js";
59
+ } from "./index-2c2bjw3s.js";
60
+ import {
61
+ argumentsDigest
62
+ } from "./index-a916km3r.js";
63
63
  import {
64
64
  collectTools,
65
65
  createToolRunner,
66
66
  formatToolError
67
- } from "./index-1qvdwnp2.js";
67
+ } from "./index-mzvgxp0n.js";
68
68
  import {
69
69
  ToolExecutionControlError,
70
70
  executeToolMethod,
71
71
  isToolExecutionControlError,
72
+ parseToolCallArguments,
72
73
  toolResultFromError
73
- } from "./index-mqhjmadk.js";
74
+ } from "./index-yn8remb1.js";
74
75
  import {
75
76
  getRequestContext,
76
77
  getTraceId,
77
78
  runWithRequestContext
78
- } from "./index-vsbzgd7b.js";
79
+ } from "./index-tmwcrptx.js";
79
80
  import"./index-f9mb610r.js";
80
81
  import {
81
82
  normalizeError
82
- } from "./index-13cjtmrw.js";
83
+ } from "./index-e0znv5gn.js";
83
84
  import {
84
85
  defineContract
85
86
  } from "./index-0a349c33.js";
@@ -97,7 +98,7 @@ import {
97
98
  import {
98
99
  createRuntimeToolFactory,
99
100
  defineRuntimeTool
100
- } from "./index-8z9we758.js";
101
+ } from "./index-vjpvjqpn.js";
101
102
  import {
102
103
  PORTABLE_JSON_SCHEMA_FORMATS,
103
104
  assertToolName,
@@ -107,8 +108,10 @@ import {
107
108
  flattenToolJsonSchema,
108
109
  prepareProjectedMcpTools,
109
110
  presentationMetadata,
110
- validateMcpRoundPolicy
111
- } from "./index-fenaekmk.js";
111
+ staticInputRounds,
112
+ validateMcpRoundPolicy,
113
+ validateResolvedInputRounds
114
+ } from "./index-h9etkkyk.js";
112
115
  import {
113
116
  toJsonSchema
114
117
  } from "./index-cby4ar3v.js";
@@ -933,7 +936,7 @@ import {
933
936
  createRequestStateCodec,
934
937
  McpServer
935
938
  } from "@modelcontextprotocol/server";
936
- import { z as z4 } from "zod";
939
+ import { z as z5 } from "zod";
937
940
 
938
941
  // src/tools/mcp-app.ts
939
942
  import { readFileSync } from "node:fs";
@@ -1110,11 +1113,46 @@ import {
1110
1113
  inputResponse,
1111
1114
  PROTOCOL_VERSION_META_KEY
1112
1115
  } from "@modelcontextprotocol/server";
1116
+ import { z as z3 } from "zod";
1117
+
1118
+ // src/tools/mcp-progress.ts
1119
+ function mcpProgressToken(context) {
1120
+ const token = context.mcpReq._meta?.progressToken;
1121
+ return typeof token === "string" || typeof token === "number" ? token : undefined;
1122
+ }
1123
+ function createMcpProgressReporter(context) {
1124
+ const token = mcpProgressToken(context);
1125
+ if (token === undefined)
1126
+ return async () => {
1127
+ return;
1128
+ };
1129
+ let sent = 0;
1130
+ let highWater = 0;
1131
+ return async (update) => {
1132
+ sent += 1;
1133
+ const value = update.progress ?? Math.max(sent, highWater + 1);
1134
+ highWater = Math.max(highWater, value);
1135
+ try {
1136
+ await context.mcpReq.notify({
1137
+ method: "notifications/progress",
1138
+ params: {
1139
+ progressToken: token,
1140
+ progress: value,
1141
+ ...update.total !== undefined && { total: update.total },
1142
+ ...update.message !== undefined && { message: update.message }
1143
+ }
1144
+ });
1145
+ } catch {}
1146
+ };
1147
+ }
1148
+
1149
+ // src/tools/mcp-round.ts
1113
1150
  function transportContext(context, toolName, outcome, round) {
1114
1151
  const protocolVersionValue = isRecord(context.mcpReq.envelope) ? Reflect.get(context.mcpReq.envelope, PROTOCOL_VERSION_META_KEY) : undefined;
1115
1152
  const protocolVersion = typeof protocolVersionValue === "string" ? protocolVersionValue : undefined;
1116
1153
  const clientInfoValue = isRecord(context.mcpReq.envelope) ? Reflect.get(context.mcpReq.envelope, CLIENT_INFO_META_KEY) : undefined;
1117
1154
  const clientInfo = isRecord(clientInfoValue) && typeof clientInfoValue.name === "string" && typeof clientInfoValue.version === "string" ? { name: clientInfoValue.name, version: clientInfoValue.version } : undefined;
1155
+ const token = mcpProgressToken(context);
1118
1156
  return {
1119
1157
  signal: context.mcpReq.signal,
1120
1158
  mcp: {
@@ -1124,8 +1162,10 @@ function transportContext(context, toolName, outcome, round) {
1124
1162
  ...protocolVersion !== undefined && { protocolVersion },
1125
1163
  ...clientInfo !== undefined && { clientInfo },
1126
1164
  ...outcome !== undefined && { outcome },
1127
- ...round !== undefined && { round }
1128
- }
1165
+ ...round !== undefined && { round },
1166
+ ...token !== undefined && { progressToken: token }
1167
+ },
1168
+ reportProgress: createMcpProgressReporter(context)
1129
1169
  };
1130
1170
  }
1131
1171
  function operationIdentity(tool) {
@@ -1168,6 +1208,28 @@ async function failedResolution(options) {
1168
1208
  const result = await runRoundFailure(options.tool, options.rawArgs, options.runTool, options.context, options.code, options.message);
1169
1209
  return { kind: "response", response: options.formatFailure(result) };
1170
1210
  }
1211
+ function roundPlanDigest(requests) {
1212
+ return argumentsDigest({
1213
+ plan: requests.map((request) => ({
1214
+ key: request.key,
1215
+ message: request.message,
1216
+ schema: z3.toJSONSchema(request.schema, { io: "input", unrepresentable: "any" })
1217
+ }))
1218
+ });
1219
+ }
1220
+ async function resolveRequests(options, policy) {
1221
+ const declared = staticInputRounds(policy);
1222
+ if (declared)
1223
+ return { requests: declared, guarded: false };
1224
+ const parsed = parseToolCallArguments(options.tool.method, options.rawArgs, options.coerceJsonArgs ?? true);
1225
+ if (!parsed.ok) {
1226
+ return { requests: [], guarded: false };
1227
+ }
1228
+ const resolver = policy.inputRequired;
1229
+ const resolved = await resolver({ params: parsed.params, input: parsed.input });
1230
+ validateResolvedInputRounds(options.tool, resolved, options.runtime?.maxRounds ?? 1);
1231
+ return { requests: resolved, guarded: false };
1232
+ }
1171
1233
  async function resolveMcpRound(options) {
1172
1234
  const { policy } = options;
1173
1235
  if (!policy) {
@@ -1183,9 +1245,37 @@ async function resolveMcpRound(options) {
1183
1245
  stateConfigured: true,
1184
1246
  maxRounds: options.runtime.maxRounds
1185
1247
  });
1186
- const requests = policy.inputRequired;
1187
1248
  const state = options.context.mcpReq.requestState();
1188
1249
  const digest = argumentsDigest(options.rawArgs);
1250
+ if (state) {
1251
+ const mismatched = !sameIdentity(state.identity, operationIdentity(options.tool)) || state.argumentsDigest !== digest || !Number.isInteger(state.round) || state.round < 0 || state.round >= options.runtime.maxRounds || !isRecord(state.accepted);
1252
+ if (mismatched) {
1253
+ return failedResolution({
1254
+ ...options,
1255
+ context: transportContext(options.context, options.tool.name, "invalid", Number.isInteger(state.round) ? state.round : 0),
1256
+ code: "INVALID_REQUEST_STATE",
1257
+ message: "Continuation state does not match this operation, arguments or round"
1258
+ });
1259
+ }
1260
+ }
1261
+ const dynamic = staticInputRounds(policy) === undefined;
1262
+ if (dynamic) {
1263
+ const guarded = await runRoundSuccess(options.tool, options.rawArgs, options.runTool, transportContext(options.context, options.tool.name, "input_required", state?.round ?? 0));
1264
+ if (!guarded.ok)
1265
+ return { kind: "response", response: options.formatFailure(guarded) };
1266
+ }
1267
+ const resolution = await resolveRequests(options, policy);
1268
+ if ("failure" in resolution)
1269
+ return resolution.failure;
1270
+ const requests = resolution.requests;
1271
+ const alreadyGuarded = dynamic;
1272
+ const planDigest = roundPlanDigest(requests);
1273
+ if (requests.length === 0 && !state) {
1274
+ return {
1275
+ kind: "continue",
1276
+ context: transportContext(options.context, options.tool.name)
1277
+ };
1278
+ }
1189
1279
  if (!state) {
1190
1280
  if (isRecord(options.context.mcpReq.inputResponses)) {
1191
1281
  return failedResolution({
@@ -1195,9 +1285,11 @@ async function resolveMcpRound(options) {
1195
1285
  message: "Input responses require a valid continuation state"
1196
1286
  });
1197
1287
  }
1198
- const guarded = await runRoundSuccess(options.tool, options.rawArgs, options.runTool, transportContext(options.context, options.tool.name, "input_required", 0));
1199
- if (!guarded.ok) {
1200
- return { kind: "response", response: options.formatFailure(guarded) };
1288
+ if (!alreadyGuarded) {
1289
+ const guarded = await runRoundSuccess(options.tool, options.rawArgs, options.runTool, transportContext(options.context, options.tool.name, "input_required", 0));
1290
+ if (!guarded.ok) {
1291
+ return { kind: "response", response: options.formatFailure(guarded) };
1292
+ }
1201
1293
  }
1202
1294
  const request2 = requests[0];
1203
1295
  if (!request2)
@@ -1206,7 +1298,8 @@ async function resolveMcpRound(options) {
1206
1298
  identity: operationIdentity(options.tool),
1207
1299
  argumentsDigest: digest,
1208
1300
  round: 0,
1209
- accepted: {}
1301
+ accepted: {},
1302
+ planDigest
1210
1303
  }, options.context);
1211
1304
  return {
1212
1305
  kind: "response",
@@ -1221,13 +1314,12 @@ async function resolveMcpRound(options) {
1221
1314
  })
1222
1315
  };
1223
1316
  }
1224
- const invalidState = !sameIdentity(state.identity, operationIdentity(options.tool)) || state.argumentsDigest !== digest || !Number.isInteger(state.round) || state.round < 0 || state.round >= requests.length || state.round >= options.runtime.maxRounds || !isRecord(state.accepted);
1225
- if (invalidState) {
1317
+ if (state.planDigest !== planDigest || state.round >= requests.length) {
1226
1318
  return failedResolution({
1227
1319
  ...options,
1228
1320
  context: transportContext(options.context, options.tool.name, "invalid", state.round),
1229
1321
  code: "INVALID_REQUEST_STATE",
1230
- message: "Continuation state does not match this operation, arguments or round"
1322
+ message: state.round >= requests.length ? "Continuation state does not match this operation, arguments or round" : "The questions for this call changed between rounds"
1231
1323
  });
1232
1324
  }
1233
1325
  const request = requests[state.round];
@@ -1264,15 +1356,18 @@ async function resolveMcpRound(options) {
1264
1356
  const nextRound = state.round + 1;
1265
1357
  const nextRequest = requests[nextRound];
1266
1358
  if (nextRequest) {
1267
- const guarded = await runRoundSuccess(options.tool, options.rawArgs, options.runTool, transportContext(options.context, options.tool.name, "input_required", nextRound));
1268
- if (!guarded.ok) {
1269
- return { kind: "response", response: options.formatFailure(guarded) };
1359
+ if (!alreadyGuarded) {
1360
+ const guarded = await runRoundSuccess(options.tool, options.rawArgs, options.runTool, transportContext(options.context, options.tool.name, "input_required", nextRound));
1361
+ if (!guarded.ok) {
1362
+ return { kind: "response", response: options.formatFailure(guarded) };
1363
+ }
1270
1364
  }
1271
1365
  const requestState = await options.runtime.codec.mint({
1272
1366
  identity: state.identity,
1273
1367
  argumentsDigest: state.argumentsDigest,
1274
1368
  round: nextRound,
1275
- accepted
1369
+ accepted,
1370
+ planDigest
1276
1371
  }, options.context);
1277
1372
  return {
1278
1373
  kind: "response",
@@ -1332,13 +1427,13 @@ function runInMcpRequestContext(context, toolName, body) {
1332
1427
  import {
1333
1428
  isCallToolResult
1334
1429
  } from "@modelcontextprotocol/server";
1335
- import { z as z3 } from "zod";
1430
+ import { z as z4 } from "zod";
1336
1431
  function mountPreparedRuntimeMcp(server, tools, config) {
1337
1432
  for (const { definition, descriptor } of tools) {
1338
1433
  const { mountable } = descriptor;
1339
1434
  const toolConfig = {
1340
1435
  description: definition.description,
1341
- inputSchema: z3.looseObject({}).meta(presentationMetadata(descriptor.inputSchema))
1436
+ inputSchema: z4.looseObject({}).meta(presentationMetadata(descriptor.inputSchema))
1342
1437
  };
1343
1438
  if (descriptor.outputSchema)
1344
1439
  toolConfig.outputSchema = descriptor.outputSchema;
@@ -1430,7 +1525,7 @@ function mountPreparedMcp(mcpServer, prepared, config = {}) {
1430
1525
  const { mountable } = descriptor;
1431
1526
  const toolConfig = {
1432
1527
  description: mountable.method.desc,
1433
- inputSchema: z4.looseObject({}).meta(presentationMetadata(descriptor.inputSchema))
1528
+ inputSchema: z5.looseObject({}).meta(presentationMetadata(descriptor.inputSchema))
1434
1529
  };
1435
1530
  if (descriptor.outputSchema)
1436
1531
  toolConfig.outputSchema = descriptor.outputSchema;
@@ -1868,7 +1963,7 @@ function bindStdioProcessSignals(handle, options = {}) {
1868
1963
  return { promise, close };
1869
1964
  }
1870
1965
  // src/tools/mount-download.ts
1871
- import { z as z5 } from "zod";
1966
+ import { z as z6 } from "zod";
1872
1967
 
1873
1968
  // src/tools/native-result.ts
1874
1969
  function textResult(text, isError = false) {
@@ -1880,7 +1975,7 @@ function textResult(text, isError = false) {
1880
1975
  function mountDownload(server, config) {
1881
1976
  const name = config.name ?? "download";
1882
1977
  assertToolName(name, "<native>", "download");
1883
- server.registerTool(name, { description: config.description, inputSchema: z5.object(config.inputSchema) }, async (rawArgs) => {
1978
+ server.registerTool(name, { description: config.description, inputSchema: z6.object(config.inputSchema) }, async (rawArgs) => {
1884
1979
  const args = isRecord(rawArgs) ? rawArgs : {};
1885
1980
  try {
1886
1981
  const url = await config.resolveUrl(args);
@@ -1928,19 +2023,33 @@ function mountUpload(server, config) {
1928
2023
  });
1929
2024
  }
1930
2025
  // src/tools/mount-wait.ts
1931
- import { z as z6 } from "zod";
2026
+ import { z as z7 } from "zod";
1932
2027
  function mountWait(server, config) {
1933
2028
  const name = config.name ?? "wait";
1934
2029
  assertToolName(name, "<native>", "wait");
1935
- server.registerTool(name, { description: config.description, inputSchema: z6.object(config.inputSchema) }, async (rawArgs) => {
2030
+ server.registerTool(name, { description: config.description, inputSchema: z7.object(config.inputSchema) }, async (rawArgs, mcpContext) => {
1936
2031
  const args = isRecord(rawArgs) ? rawArgs : {};
2032
+ const report = createMcpProgressReporter(mcpContext);
2033
+ let last;
1937
2034
  try {
1938
2035
  const { state, timedOut } = await runWaitOperation({
1939
2036
  input: args,
1940
- poll: (input) => config.poll(input),
2037
+ poll: async (input) => {
2038
+ last = await config.poll(input);
2039
+ return last;
2040
+ },
1941
2041
  done: config.done,
1942
2042
  backoff: config.backoff,
1943
- timeoutSec: config.timeoutFromArgs?.(args) ?? config.defaultTimeout
2043
+ timeoutSec: config.timeoutFromArgs?.(args) ?? config.defaultTimeout,
2044
+ onTick: (attempt, elapsedSec) => {
2045
+ const snapshot = isRecord(last) ? last : undefined;
2046
+ const phase = typeof snapshot?.phase === "string" ? snapshot.phase : undefined;
2047
+ const measured = typeof snapshot?.progress === "number" && Number.isFinite(snapshot.progress) ? snapshot.progress : undefined;
2048
+ report({
2049
+ progress: measured ?? attempt,
2050
+ message: phase ? `${phase} — poll ${attempt}, ${Math.round(elapsedSec)}s elapsed` : `poll ${attempt}, ${Math.round(elapsedSec)}s elapsed`
2051
+ });
2052
+ }
1944
2053
  });
1945
2054
  const rendered = config.render ? config.render(state, timedOut) : { text: JSON.stringify(state, null, 2), isError: timedOut };
1946
2055
  return textResult(rendered.text, rendered.isError);
@@ -1951,19 +2060,19 @@ function mountWait(server, config) {
1951
2060
  }
1952
2061
  // src/tools/oauth-provider.ts
1953
2062
  import { randomUUID } from "node:crypto";
1954
- import { z as z7 } from "zod";
2063
+ import { z as z8 } from "zod";
1955
2064
  function isPlainDisplayCharacter(character) {
1956
2065
  const codePoint = character.codePointAt(0);
1957
2066
  return codePoint !== undefined && codePoint >= 32 && codePoint !== 127 && character !== "<" && character !== ">";
1958
2067
  }
1959
- var CimdClientMetadataSchema = z7.object({
1960
- client_id: z7.url(),
1961
- redirect_uris: z7.array(z7.url()).min(1),
1962
- client_name: z7.string().trim().min(1).max(200).refine((value) => Array.from(value).every(isPlainDisplayCharacter), {
2068
+ var CimdClientMetadataSchema = z8.object({
2069
+ client_id: z8.url(),
2070
+ redirect_uris: z8.array(z8.url()).min(1),
2071
+ client_name: z8.string().trim().min(1).max(200).refine((value) => Array.from(value).every(isPlainDisplayCharacter), {
1963
2072
  message: "client_name must be plain display text"
1964
2073
  }),
1965
- token_endpoint_auth_method: z7.literal("none"),
1966
- application_type: z7.enum(["native", "web"]).optional()
2074
+ token_endpoint_auth_method: z8.literal("none"),
2075
+ application_type: z8.enum(["native", "web"]).optional()
1967
2076
  });
1968
2077
  function createSecureClientMetadataFetcher(policy = {}) {
1969
2078
  assertPositiveInteger("cimd.maxBytes", policy.maxBytes ?? DEFAULT_CIMD_MAX_BYTES);