@schoolai/shipyard-mcp 0.2.2-next.494 → 0.2.2-next.499
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/hook/dist/index.cjs +24 -4
- package/apps/server/dist/{chunk-ZD2SHV5V.js → chunk-CSSWBPUN.js} +1 -1
- package/apps/server/dist/{chunk-5V7HUMDU.js → chunk-X4N6BYDY.js} +23 -3
- package/apps/server/dist/{dist-2W7US5HB.js → dist-R4AR63HS.js} +1 -1
- package/apps/server/dist/index.js +81 -29
- package/apps/server/dist/{input-request-manager-QX7MYHH7.js → input-request-manager-4SL6YBFD.js} +2 -2
- package/package.json +1 -1
package/apps/hook/dist/index.cjs
CHANGED
|
@@ -28830,7 +28830,7 @@ init_cjs_shims();
|
|
|
28830
28830
|
// ../../packages/schema/dist/index.mjs
|
|
28831
28831
|
init_cjs_shims();
|
|
28832
28832
|
|
|
28833
|
-
// ../../packages/schema/dist/yjs-helpers-
|
|
28833
|
+
// ../../packages/schema/dist/yjs-helpers-BQ7VTqc2.mjs
|
|
28834
28834
|
init_cjs_shims();
|
|
28835
28835
|
|
|
28836
28836
|
// ../../packages/schema/dist/plan.mjs
|
|
@@ -43001,7 +43001,7 @@ var PRReviewCommentSchema = external_exports.object({
|
|
|
43001
43001
|
resolved: external_exports.boolean().optional()
|
|
43002
43002
|
});
|
|
43003
43003
|
|
|
43004
|
-
// ../../packages/schema/dist/yjs-helpers-
|
|
43004
|
+
// ../../packages/schema/dist/yjs-helpers-BQ7VTqc2.mjs
|
|
43005
43005
|
function assertNever2(value) {
|
|
43006
43006
|
throw new Error(`Unhandled discriminated union member: ${JSON.stringify(value)}`);
|
|
43007
43007
|
}
|
|
@@ -43106,7 +43106,7 @@ var InputRequestBaseSchema = external_exports.object({
|
|
|
43106
43106
|
message: external_exports.string().min(1, "Message cannot be empty"),
|
|
43107
43107
|
status: external_exports.enum(InputRequestStatusValues),
|
|
43108
43108
|
defaultValue: external_exports.string().optional(),
|
|
43109
|
-
timeout: external_exports.number().int().min(
|
|
43109
|
+
timeout: external_exports.number().int().min(300, "Timeout must be at least 5 minutes (300 seconds)").max(1800, "Timeout cannot exceed 30 minutes (1800 seconds)").optional(),
|
|
43110
43110
|
planId: external_exports.string().optional(),
|
|
43111
43111
|
response: external_exports.unknown().optional(),
|
|
43112
43112
|
answeredAt: external_exports.number().optional(),
|
|
@@ -44411,9 +44411,29 @@ var planRouter = router({
|
|
|
44411
44411
|
if (!cwd) return {
|
|
44412
44412
|
available: false,
|
|
44413
44413
|
reason: "no_cwd",
|
|
44414
|
-
message: "Plan has no associated working directory.
|
|
44414
|
+
message: "Plan has no associated working directory. Local changes are only available for plans created with working directory metadata."
|
|
44415
44415
|
};
|
|
44416
44416
|
return ctx.getLocalChanges(cwd);
|
|
44417
|
+
}),
|
|
44418
|
+
getFileContent: publicProcedure.input(external_exports.object({
|
|
44419
|
+
planId: PlanIdSchema.shape.planId,
|
|
44420
|
+
filePath: external_exports.string()
|
|
44421
|
+
})).output(external_exports.object({
|
|
44422
|
+
content: external_exports.string().nullable(),
|
|
44423
|
+
error: external_exports.string().optional()
|
|
44424
|
+
})).query(async ({ input, ctx }) => {
|
|
44425
|
+
const metadata = getPlanMetadata(await ctx.getOrCreateDoc(input.planId));
|
|
44426
|
+
if (!metadata) throw new TRPCError({
|
|
44427
|
+
code: "NOT_FOUND",
|
|
44428
|
+
message: "Plan not found"
|
|
44429
|
+
});
|
|
44430
|
+
const origin = metadata.origin;
|
|
44431
|
+
const cwd = origin?.platform === "claude-code" ? origin.cwd : void 0;
|
|
44432
|
+
if (!cwd) return {
|
|
44433
|
+
content: null,
|
|
44434
|
+
error: "No working directory available"
|
|
44435
|
+
};
|
|
44436
|
+
return ctx.getFileContent(cwd, input.filePath);
|
|
44417
44437
|
})
|
|
44418
44438
|
});
|
|
44419
44439
|
var subscriptionRouter = router({
|
|
@@ -864,7 +864,7 @@ function createHandedOffConversationVersion(params) {
|
|
|
864
864
|
return ConversationVersionSchema.parse(version);
|
|
865
865
|
}
|
|
866
866
|
|
|
867
|
-
// ../../packages/schema/dist/yjs-helpers-
|
|
867
|
+
// ../../packages/schema/dist/yjs-helpers-BQ7VTqc2.mjs
|
|
868
868
|
import { z as z2 } from "zod";
|
|
869
869
|
import { nanoid as nanoid2 } from "nanoid";
|
|
870
870
|
import * as Y from "yjs";
|
|
@@ -979,7 +979,7 @@ var InputRequestBaseSchema = z2.object({
|
|
|
979
979
|
message: z2.string().min(1, "Message cannot be empty"),
|
|
980
980
|
status: z2.enum(InputRequestStatusValues),
|
|
981
981
|
defaultValue: z2.string().optional(),
|
|
982
|
-
timeout: z2.number().int().min(
|
|
982
|
+
timeout: z2.number().int().min(300, "Timeout must be at least 5 minutes (300 seconds)").max(1800, "Timeout cannot exceed 30 minutes (1800 seconds)").optional(),
|
|
983
983
|
planId: z2.string().optional(),
|
|
984
984
|
response: z2.unknown().optional(),
|
|
985
985
|
answeredAt: z2.number().optional(),
|
|
@@ -2811,9 +2811,29 @@ var planRouter = router({
|
|
|
2811
2811
|
if (!cwd) return {
|
|
2812
2812
|
available: false,
|
|
2813
2813
|
reason: "no_cwd",
|
|
2814
|
-
message: "Plan has no associated working directory.
|
|
2814
|
+
message: "Plan has no associated working directory. Local changes are only available for plans created with working directory metadata."
|
|
2815
2815
|
};
|
|
2816
2816
|
return ctx.getLocalChanges(cwd);
|
|
2817
|
+
}),
|
|
2818
|
+
getFileContent: publicProcedure.input(z3.object({
|
|
2819
|
+
planId: PlanIdSchema.shape.planId,
|
|
2820
|
+
filePath: z3.string()
|
|
2821
|
+
})).output(z3.object({
|
|
2822
|
+
content: z3.string().nullable(),
|
|
2823
|
+
error: z3.string().optional()
|
|
2824
|
+
})).query(async ({ input, ctx }) => {
|
|
2825
|
+
const metadata = getPlanMetadata(await ctx.getOrCreateDoc(input.planId));
|
|
2826
|
+
if (!metadata) throw new TRPCError({
|
|
2827
|
+
code: "NOT_FOUND",
|
|
2828
|
+
message: "Plan not found"
|
|
2829
|
+
});
|
|
2830
|
+
const origin = metadata.origin;
|
|
2831
|
+
const cwd = origin?.platform === "claude-code" ? origin.cwd : void 0;
|
|
2832
|
+
if (!cwd) return {
|
|
2833
|
+
content: null,
|
|
2834
|
+
error: "No working directory available"
|
|
2835
|
+
};
|
|
2836
|
+
return ctx.getFileContent(cwd, input.filePath);
|
|
2817
2837
|
})
|
|
2818
2838
|
});
|
|
2819
2839
|
var subscriptionRouter = router({
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
} from "./chunk-EBNL5ZX7.js";
|
|
21
21
|
import {
|
|
22
22
|
InputRequestManager
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-CSSWBPUN.js";
|
|
24
24
|
import {
|
|
25
25
|
ArtifactSchema,
|
|
26
26
|
DeliverableSchema,
|
|
@@ -72,7 +72,7 @@ import {
|
|
|
72
72
|
setPlanMetadata,
|
|
73
73
|
touchPlanIndexEntry,
|
|
74
74
|
transitionPlanStatus
|
|
75
|
-
} from "./chunk-
|
|
75
|
+
} from "./chunk-X4N6BYDY.js";
|
|
76
76
|
import {
|
|
77
77
|
loadEnv,
|
|
78
78
|
logger
|
|
@@ -165,11 +165,11 @@ async function hasActiveConnections(planId) {
|
|
|
165
165
|
}
|
|
166
166
|
|
|
167
167
|
// src/registry-server.ts
|
|
168
|
-
import { mkdirSync, readFileSync, unlinkSync } from "fs";
|
|
168
|
+
import { mkdirSync, readFileSync as readFileSync2, unlinkSync } from "fs";
|
|
169
169
|
import { readFile, unlink, writeFile as writeFile2 } from "fs/promises";
|
|
170
170
|
import http from "http";
|
|
171
171
|
import { homedir as homedir3 } from "os";
|
|
172
|
-
import { join as
|
|
172
|
+
import { join as join4, resolve, sep } from "path";
|
|
173
173
|
import { createExpressMiddleware } from "@trpc/server/adapters/express";
|
|
174
174
|
import express from "express";
|
|
175
175
|
import * as decoding from "lib0/decoding";
|
|
@@ -385,6 +385,8 @@ function attachCRDTValidation(planId, doc) {
|
|
|
385
385
|
|
|
386
386
|
// src/git-local-changes.ts
|
|
387
387
|
import { execSync } from "child_process";
|
|
388
|
+
import { readFileSync } from "fs";
|
|
389
|
+
import { isAbsolute, join as join3, normalize } from "path";
|
|
388
390
|
function getLocalChanges(cwd) {
|
|
389
391
|
try {
|
|
390
392
|
try {
|
|
@@ -395,11 +397,24 @@ function getLocalChanges(cwd) {
|
|
|
395
397
|
stdio: ["pipe", "pipe", "pipe"]
|
|
396
398
|
});
|
|
397
399
|
} catch {
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
400
|
+
logger.info({ cwd }, "Not a git repo, initializing with git init");
|
|
401
|
+
try {
|
|
402
|
+
execSync("git init", {
|
|
403
|
+
cwd,
|
|
404
|
+
encoding: "utf-8",
|
|
405
|
+
timeout: 5e3,
|
|
406
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
407
|
+
});
|
|
408
|
+
logger.info({ cwd }, "Git repository initialized");
|
|
409
|
+
} catch (initError) {
|
|
410
|
+
const message = initError instanceof Error ? initError.message : "Unknown error";
|
|
411
|
+
logger.error({ error: initError, cwd }, "Failed to initialize git repository");
|
|
412
|
+
return {
|
|
413
|
+
available: false,
|
|
414
|
+
reason: "git_error",
|
|
415
|
+
message: `Failed to initialize git repository: ${message}`
|
|
416
|
+
};
|
|
417
|
+
}
|
|
403
418
|
}
|
|
404
419
|
let branch;
|
|
405
420
|
try {
|
|
@@ -623,6 +638,32 @@ function detectStatus(fileDiff) {
|
|
|
623
638
|
}
|
|
624
639
|
return "modified";
|
|
625
640
|
}
|
|
641
|
+
function getFileContent(cwd, filePath) {
|
|
642
|
+
try {
|
|
643
|
+
const normalizedPath = normalize(filePath);
|
|
644
|
+
if (isAbsolute(normalizedPath) || normalizedPath.startsWith("..")) {
|
|
645
|
+
return { content: null, error: "Invalid file path" };
|
|
646
|
+
}
|
|
647
|
+
const fullPath = join3(cwd, normalizedPath);
|
|
648
|
+
if (!fullPath.startsWith(cwd)) {
|
|
649
|
+
return { content: null, error: "Invalid file path" };
|
|
650
|
+
}
|
|
651
|
+
const content = readFileSync(fullPath, { encoding: "utf-8" });
|
|
652
|
+
if (content.length > 10 * 1024 * 1024) {
|
|
653
|
+
return { content: null, error: "File too large to display" };
|
|
654
|
+
}
|
|
655
|
+
return { content };
|
|
656
|
+
} catch (error) {
|
|
657
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
658
|
+
if (message.includes("ENOENT")) {
|
|
659
|
+
return { content: null, error: "File not found" };
|
|
660
|
+
}
|
|
661
|
+
if (message.includes("EISDIR")) {
|
|
662
|
+
return { content: null, error: "Path is a directory" };
|
|
663
|
+
}
|
|
664
|
+
return { content: null, error: `Failed to read file: ${message}` };
|
|
665
|
+
}
|
|
666
|
+
}
|
|
626
667
|
|
|
627
668
|
// src/github-artifacts.ts
|
|
628
669
|
import { Octokit } from "@octokit/rest";
|
|
@@ -1929,9 +1970,9 @@ function getParam(value) {
|
|
|
1929
1970
|
if (Array.isArray(value)) return value[0];
|
|
1930
1971
|
return value;
|
|
1931
1972
|
}
|
|
1932
|
-
var PERSISTENCE_DIR =
|
|
1933
|
-
var HUB_LOCK_FILE =
|
|
1934
|
-
var SHIPYARD_DIR =
|
|
1973
|
+
var PERSISTENCE_DIR = join4(homedir3(), ".shipyard", "plans");
|
|
1974
|
+
var HUB_LOCK_FILE = join4(homedir3(), ".shipyard", "hub.lock");
|
|
1975
|
+
var SHIPYARD_DIR = join4(homedir3(), ".shipyard");
|
|
1935
1976
|
var MAX_LOCK_RETRIES = 3;
|
|
1936
1977
|
var messageSync = 0;
|
|
1937
1978
|
var messageAwareness = 1;
|
|
@@ -2029,9 +2070,9 @@ function isProcessAlive(pid) {
|
|
|
2029
2070
|
}
|
|
2030
2071
|
}
|
|
2031
2072
|
function tryRecoverStaleLock(originalError) {
|
|
2032
|
-
const lockFile =
|
|
2073
|
+
const lockFile = join4(PERSISTENCE_DIR, "LOCK");
|
|
2033
2074
|
try {
|
|
2034
|
-
const hubLockContent =
|
|
2075
|
+
const hubLockContent = readFileSync2(HUB_LOCK_FILE, "utf-8");
|
|
2035
2076
|
const pidStr = hubLockContent.split("\n")[0] ?? "";
|
|
2036
2077
|
const pid = Number.parseInt(pidStr, 10);
|
|
2037
2078
|
if (isProcessAlive(pid)) {
|
|
@@ -2365,7 +2406,8 @@ function createContext() {
|
|
|
2365
2406
|
logger,
|
|
2366
2407
|
hookHandlers: createHookHandlers(),
|
|
2367
2408
|
conversationHandlers: createConversationHandlers(),
|
|
2368
|
-
getLocalChanges
|
|
2409
|
+
getLocalChanges,
|
|
2410
|
+
getFileContent
|
|
2369
2411
|
};
|
|
2370
2412
|
}
|
|
2371
2413
|
function createApp() {
|
|
@@ -2408,7 +2450,7 @@ function createApp() {
|
|
|
2408
2450
|
res.status(400).json({ error: "Missing planId or filename" });
|
|
2409
2451
|
return;
|
|
2410
2452
|
}
|
|
2411
|
-
const ARTIFACTS_DIR2 =
|
|
2453
|
+
const ARTIFACTS_DIR2 = join4(homedir3(), ".shipyard", "artifacts");
|
|
2412
2454
|
const fullPath = resolve(ARTIFACTS_DIR2, planId, filename);
|
|
2413
2455
|
if (!fullPath.startsWith(ARTIFACTS_DIR2 + sep)) {
|
|
2414
2456
|
res.status(400).json({ error: "Invalid artifact path" });
|
|
@@ -2725,11 +2767,11 @@ import { z as z3 } from "zod";
|
|
|
2725
2767
|
// src/local-artifacts.ts
|
|
2726
2768
|
import { mkdir as mkdir2, readFile as readFile2, rm, writeFile as writeFile3 } from "fs/promises";
|
|
2727
2769
|
import { homedir as homedir4 } from "os";
|
|
2728
|
-
import { join as
|
|
2770
|
+
import { join as join5, resolve as resolve2, sep as sep2 } from "path";
|
|
2729
2771
|
async function storeLocalArtifact(planId, filename, buffer) {
|
|
2730
|
-
const planDir =
|
|
2772
|
+
const planDir = join5(ARTIFACTS_DIR, planId);
|
|
2731
2773
|
await mkdir2(planDir, { recursive: true });
|
|
2732
|
-
const filepath =
|
|
2774
|
+
const filepath = join5(planDir, filename);
|
|
2733
2775
|
await writeFile3(filepath, buffer);
|
|
2734
2776
|
logger.info({ planId, filename, size: buffer.length }, "Artifact stored locally");
|
|
2735
2777
|
return `${planId}/${filename}`;
|
|
@@ -2752,7 +2794,7 @@ async function deleteLocalArtifact(artifactId) {
|
|
|
2752
2794
|
return false;
|
|
2753
2795
|
}
|
|
2754
2796
|
}
|
|
2755
|
-
var ARTIFACTS_DIR =
|
|
2797
|
+
var ARTIFACTS_DIR = join5(homedir4(), ".shipyard", "artifacts");
|
|
2756
2798
|
|
|
2757
2799
|
// src/session-token.ts
|
|
2758
2800
|
import { timingSafeEqual } from "crypto";
|
|
@@ -3177,11 +3219,11 @@ Linked to deliverable: ${input.deliverableId}` : "";
|
|
|
3177
3219
|
}
|
|
3178
3220
|
logger.info({ planId, snapshotUrl }, "Task auto-completed");
|
|
3179
3221
|
const { homedir: homedir5 } = await import("os");
|
|
3180
|
-
const { join:
|
|
3222
|
+
const { join: join7 } = await import("path");
|
|
3181
3223
|
const { mkdir: mkdir3 } = await import("fs/promises");
|
|
3182
|
-
const snapshotsDir =
|
|
3224
|
+
const snapshotsDir = join7(homedir5(), ".shipyard", "snapshots");
|
|
3183
3225
|
await mkdir3(snapshotsDir, { recursive: true });
|
|
3184
|
-
const snapshotFile =
|
|
3226
|
+
const snapshotFile = join7(snapshotsDir, `${planId}.txt`);
|
|
3185
3227
|
await writeFile4(snapshotFile, snapshotUrl, "utf-8");
|
|
3186
3228
|
logger.info({ planId, snapshotFile }, "Snapshot URL written to file");
|
|
3187
3229
|
let prText = "";
|
|
@@ -5319,7 +5361,11 @@ Parameters:
|
|
|
5319
5361
|
- options (string[], optional): For 'choice' type - available options (required for choice)
|
|
5320
5362
|
- multiSelect (boolean, optional): For 'choice' type - allow selecting multiple options (uses checkboxes instead of radio buttons)
|
|
5321
5363
|
- defaultValue (string, optional): Pre-filled value for text/multiline inputs
|
|
5322
|
-
- timeout (number, optional): Timeout in seconds (default: 1800, min:
|
|
5364
|
+
- timeout (number, optional): Timeout in seconds (default: 1800, min: 300, max: 1800)
|
|
5365
|
+
- Simple yes/no or quick choices: 300-600 seconds (5-10 minutes)
|
|
5366
|
+
- Complex questions with code examples: 600-1200 seconds (10-20 minutes)
|
|
5367
|
+
- Default (1800 = 30 minutes) is suitable for most cases
|
|
5368
|
+
- Note: System-level timeouts may cause earlier cancellation
|
|
5323
5369
|
- planId (string, optional): Optional metadata to link request to plan (for activity log filtering)
|
|
5324
5370
|
|
|
5325
5371
|
Returns:
|
|
@@ -5339,7 +5385,7 @@ const result = await requestUserInput({
|
|
|
5339
5385
|
message: "Which database should we use?",
|
|
5340
5386
|
type: "choice",
|
|
5341
5387
|
options: ["PostgreSQL", "SQLite", "MongoDB"],
|
|
5342
|
-
timeout:
|
|
5388
|
+
timeout: 600 // 10 minutes
|
|
5343
5389
|
});
|
|
5344
5390
|
|
|
5345
5391
|
if (result.success) {
|
|
@@ -5650,7 +5696,7 @@ async function setupReviewNotification(planId, pollIntervalSeconds) {
|
|
|
5650
5696
|
return { script, fullResponse: text };
|
|
5651
5697
|
}
|
|
5652
5698
|
async function requestUserInput(opts) {
|
|
5653
|
-
const { InputRequestManager: InputRequestManager2 } = await import("./input-request-manager-
|
|
5699
|
+
const { InputRequestManager: InputRequestManager2 } = await import("./input-request-manager-4SL6YBFD.js");
|
|
5654
5700
|
const ydoc = await getOrCreateDoc3(PLAN_INDEX_DOC_NAME);
|
|
5655
5701
|
const manager = new InputRequestManager2();
|
|
5656
5702
|
const params = opts.type === "choice" ? {
|
|
@@ -5694,7 +5740,7 @@ async function requestUserInput(opts) {
|
|
|
5694
5740
|
};
|
|
5695
5741
|
}
|
|
5696
5742
|
async function postActivityUpdate(opts) {
|
|
5697
|
-
const { logPlanEvent: logPlanEvent2 } = await import("./dist-
|
|
5743
|
+
const { logPlanEvent: logPlanEvent2 } = await import("./dist-R4AR63HS.js");
|
|
5698
5744
|
const { getGitHubUsername: getGitHubUsername2 } = await import("./server-identity-LSZ4CZRK.js");
|
|
5699
5745
|
const { nanoid: nanoid8 } = await import("nanoid");
|
|
5700
5746
|
const doc = await getOrCreateDoc3(opts.planId);
|
|
@@ -5717,7 +5763,7 @@ async function postActivityUpdate(opts) {
|
|
|
5717
5763
|
return { success: true, eventId, requestId };
|
|
5718
5764
|
}
|
|
5719
5765
|
async function resolveActivityRequest(opts) {
|
|
5720
|
-
const { logPlanEvent: logPlanEvent2, getPlanEvents } = await import("./dist-
|
|
5766
|
+
const { logPlanEvent: logPlanEvent2, getPlanEvents } = await import("./dist-R4AR63HS.js");
|
|
5721
5767
|
const { getGitHubUsername: getGitHubUsername2 } = await import("./server-identity-LSZ4CZRK.js");
|
|
5722
5768
|
const doc = await getOrCreateDoc3(opts.planId);
|
|
5723
5769
|
const actorName = await getGitHubUsername2();
|
|
@@ -5885,7 +5931,7 @@ var RequestUserInputInput = z14.object({
|
|
|
5885
5931
|
options: z14.array(z14.string()).optional().describe("For 'choice' type - available options (required for choice)"),
|
|
5886
5932
|
multiSelect: z14.boolean().optional().describe("For 'choice' type - allow selecting multiple options"),
|
|
5887
5933
|
defaultValue: z14.string().optional().describe("Pre-filled value for text/multiline inputs"),
|
|
5888
|
-
timeout: z14.number().optional().describe("Timeout in seconds (default: 1800, min:
|
|
5934
|
+
timeout: z14.number().optional().describe("Timeout in seconds (default: 1800, min: 300, max: 1800)"),
|
|
5889
5935
|
planId: z14.string().optional().describe("Optional metadata to link request to plan (for activity log filtering)")
|
|
5890
5936
|
});
|
|
5891
5937
|
var requestUserInputTool = {
|
|
@@ -5914,6 +5960,12 @@ For 'choice' type:
|
|
|
5914
5960
|
This tool is analogous to AskUserQuestion, prompt(), or other agent question mechanisms,
|
|
5915
5961
|
but shows responses in the browser UI where users are already viewing plans.
|
|
5916
5962
|
|
|
5963
|
+
Timeout guidelines:
|
|
5964
|
+
- Simple yes/no or quick choices: 300-600 seconds (5-10 minutes)
|
|
5965
|
+
- Complex questions with code examples: 600-1200 seconds (10-20 minutes)
|
|
5966
|
+
- Default (1800 = 30 minutes) is suitable for most cases
|
|
5967
|
+
- Note: System-level timeouts may cause earlier cancellation regardless of this value
|
|
5968
|
+
|
|
5917
5969
|
NOTE: This is also available as requestUserInput() inside execute_code for multi-step workflows.`,
|
|
5918
5970
|
inputSchema: {
|
|
5919
5971
|
type: "object",
|