@schoolai/shipyard-mcp 0.3.2-next.518 → 0.3.2-next.522

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.
@@ -28491,7 +28491,7 @@ init_cjs_shims();
28491
28491
  // ../../packages/schema/dist/index.mjs
28492
28492
  init_cjs_shims();
28493
28493
 
28494
- // ../../packages/schema/dist/yjs-helpers-3DNyE4lF.mjs
28494
+ // ../../packages/schema/dist/yjs-helpers-CNlw-U7T.mjs
28495
28495
  init_cjs_shims();
28496
28496
 
28497
28497
  // ../../packages/schema/dist/plan.mjs
@@ -42547,7 +42547,19 @@ var PlanEventSchema = external_exports.discriminatedUnion("type", [
42547
42547
  data: external_exports.object({
42548
42548
  requestId: external_exports.string(),
42549
42549
  response: external_exports.unknown(),
42550
- answeredBy: external_exports.string()
42550
+ answeredBy: external_exports.string(),
42551
+ requestMessage: external_exports.string().optional(),
42552
+ requestType: external_exports.enum([
42553
+ "text",
42554
+ "multiline",
42555
+ "choice",
42556
+ "confirm",
42557
+ "number",
42558
+ "email",
42559
+ "date",
42560
+ "rating",
42561
+ "multi"
42562
+ ]).optional()
42551
42563
  })
42552
42564
  }),
42553
42565
  PlanEventBaseSchema.extend({
@@ -42696,7 +42708,7 @@ var LocalArtifactParseSchema = external_exports.object({
42696
42708
  localArtifactId: external_exports.string()
42697
42709
  });
42698
42710
 
42699
- // ../../packages/schema/dist/yjs-helpers-3DNyE4lF.mjs
42711
+ // ../../packages/schema/dist/yjs-helpers-CNlw-U7T.mjs
42700
42712
  function assertNever2(value) {
42701
42713
  throw new Error(`Unhandled discriminated union member: ${JSON.stringify(value)}`);
42702
42714
  }
@@ -42902,7 +42914,7 @@ var ChoiceQuestionSchema = QuestionBaseSchema.extend({
42902
42914
  placeholder: external_exports.string().optional()
42903
42915
  });
42904
42916
  var ConfirmQuestionSchema = QuestionBaseSchema.extend({ type: external_exports.literal("confirm") });
42905
- var NumberQuestionSchema = QuestionBaseSchema.extend({
42917
+ var NumberQuestionBaseSchema = QuestionBaseSchema.extend({
42906
42918
  type: external_exports.literal("number"),
42907
42919
  min: external_exports.number().optional(),
42908
42920
  max: external_exports.number().optional(),
@@ -42912,17 +42924,17 @@ var NumberQuestionSchema = QuestionBaseSchema.extend({
42912
42924
  "currency",
42913
42925
  "percentage"
42914
42926
  ]).optional()
42915
- }).refine((data) => data.min === void 0 || data.max === void 0 || data.min <= data.max, { message: "min must be <= max" });
42927
+ });
42916
42928
  var EmailQuestionSchema = QuestionBaseSchema.extend({
42917
42929
  type: external_exports.literal("email"),
42918
42930
  domain: external_exports.string().optional()
42919
42931
  });
42920
- var DateQuestionSchema = QuestionBaseSchema.extend({
42932
+ var DateQuestionBaseSchema = QuestionBaseSchema.extend({
42921
42933
  type: external_exports.literal("date"),
42922
42934
  min: external_exports.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be in YYYY-MM-DD format").optional(),
42923
42935
  max: external_exports.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be in YYYY-MM-DD format").optional()
42924
- }).refine((data) => data.min === void 0 || data.max === void 0 || new Date(data.min) <= new Date(data.max), { message: "min date must be before or equal to max date" });
42925
- var RatingQuestionSchema = QuestionBaseSchema.extend({
42936
+ });
42937
+ var RatingQuestionBaseSchema = QuestionBaseSchema.extend({
42926
42938
  type: external_exports.literal("rating"),
42927
42939
  min: external_exports.number().int().optional(),
42928
42940
  max: external_exports.number().int().optional(),
@@ -42935,20 +42947,58 @@ var RatingQuestionSchema = QuestionBaseSchema.extend({
42935
42947
  low: external_exports.string().optional(),
42936
42948
  high: external_exports.string().optional()
42937
42949
  }).optional()
42938
- }).refine((data) => {
42939
- if (data.min === void 0 || data.max === void 0) return true;
42940
- return data.min <= data.max && data.max - data.min <= 20;
42941
- }, { message: "Rating scale must have min <= max and at most 20 items" });
42950
+ });
42942
42951
  var QuestionSchema = external_exports.discriminatedUnion("type", [
42943
42952
  TextQuestionSchema,
42944
42953
  MultilineQuestionSchema,
42945
42954
  ChoiceQuestionSchema,
42946
42955
  ConfirmQuestionSchema,
42947
- NumberQuestionSchema,
42956
+ NumberQuestionBaseSchema,
42948
42957
  EmailQuestionSchema,
42949
- DateQuestionSchema,
42950
- RatingQuestionSchema
42958
+ DateQuestionBaseSchema,
42959
+ RatingQuestionBaseSchema
42951
42960
  ]);
42961
+ function validateNumberQuestion(q, index, ctx) {
42962
+ if (q.min !== void 0 && q.max !== void 0 && q.min > q.max) ctx.addIssue({
42963
+ code: external_exports.ZodIssueCode.custom,
42964
+ message: "min must be <= max",
42965
+ path: ["questions", index]
42966
+ });
42967
+ }
42968
+ function validateDateQuestion(q, index, ctx) {
42969
+ if (q.min !== void 0 && q.max !== void 0 && new Date(q.min) > new Date(q.max)) ctx.addIssue({
42970
+ code: external_exports.ZodIssueCode.custom,
42971
+ message: "min date must be before or equal to max date",
42972
+ path: ["questions", index]
42973
+ });
42974
+ }
42975
+ function validateRatingQuestion(q, index, ctx) {
42976
+ if (q.min === void 0 || q.max === void 0) return;
42977
+ if (q.min > q.max || q.max - q.min > 20) ctx.addIssue({
42978
+ code: external_exports.ZodIssueCode.custom,
42979
+ message: "Rating scale must have min <= max and at most 20 items",
42980
+ path: ["questions", index]
42981
+ });
42982
+ }
42983
+ function validateQuestionConstraints(questions, ctx) {
42984
+ for (let i = 0; i < questions.length; i++) {
42985
+ const q = questions[i];
42986
+ if (!q) continue;
42987
+ switch (q.type) {
42988
+ case "number":
42989
+ validateNumberQuestion(q, i, ctx);
42990
+ break;
42991
+ case "date":
42992
+ validateDateQuestion(q, i, ctx);
42993
+ break;
42994
+ case "rating":
42995
+ validateRatingQuestion(q, i, ctx);
42996
+ break;
42997
+ default:
42998
+ break;
42999
+ }
43000
+ }
43001
+ }
42952
43002
  var MultiQuestionInputRequestSchema = external_exports.object({
42953
43003
  id: external_exports.string(),
42954
43004
  createdAt: external_exports.number(),
@@ -42961,6 +43011,8 @@ var MultiQuestionInputRequestSchema = external_exports.object({
42961
43011
  answeredAt: external_exports.number().optional(),
42962
43012
  answeredBy: external_exports.string().optional(),
42963
43013
  isBlocker: external_exports.boolean().optional()
43014
+ }).superRefine((data, ctx) => {
43015
+ validateQuestionConstraints(data.questions, ctx);
42964
43016
  });
42965
43017
  var AnyInputRequestSchema = external_exports.union([InputRequestSchema, MultiQuestionInputRequestSchema]);
42966
43018
  var YDOC_KEYS = {
@@ -44516,11 +44568,31 @@ Skip Shipyard for:
44516
44568
  - Pure documentation without implementation`;
44517
44569
  var USER_INPUT_SECTION = `## Human-Agent Communication
44518
44570
 
44519
- **\`${TOOL_NAMES2.REQUEST_USER_INPUT}\` is THE primary way to communicate with humans during active work.**
44571
+ **\`requestUserInput()\` inside \`${TOOL_NAMES2.EXECUTE_CODE}\` is THE primary way to communicate with humans during active work.**
44572
+
44573
+ Shipyard is the central hub where humans manage AI agents. When you need to ask a question, get clarification, or request a decision - use \`requestUserInput()\`. The human is already in the browser viewing your plan. That's where conversations should happen.
44574
+
44575
+ ### Best Practice: Return the Response Value
44576
+
44577
+ **Always RETURN the response in your execute_code result** for clean, structured output:
44578
+
44579
+ \`\`\`typescript
44580
+ const result = await requestUserInput({
44581
+ message: "Which framework?",
44582
+ type: "choice",
44583
+ options: ["React", "Vue", "Angular"]
44584
+ });
44585
+
44586
+ return {
44587
+ userDecision: result.response,
44588
+ timestamp: Date.now()
44589
+ };
44590
+ // Clean, structured - appears once in the final output
44591
+ \`\`\`
44520
44592
 
44521
- Shipyard is the central hub where humans manage AI agents. When you need to ask a question, get clarification, or request a decision - use \`${TOOL_NAMES2.REQUEST_USER_INPUT}\`. The human is already in the browser viewing your plan. That's where conversations should happen.
44593
+ Avoid \`console.log()\` for response values - it clutters output and isn't structured. Use console.log only for debugging intermediate steps.
44522
44594
 
44523
- ### Why Use ${TOOL_NAMES2.REQUEST_USER_INPUT}
44595
+ ### Why Use requestUserInput()
44524
44596
 
44525
44597
  - **Context:** The human sees your question alongside the plan, artifacts, and comments
44526
44598
  - **History:** All exchanges are logged in the plan's activity feed
@@ -44529,40 +44601,62 @@ Shipyard is the central hub where humans manage AI agents. When you need to ask
44529
44601
 
44530
44602
  ### Replace Platform Tools
44531
44603
 
44532
- **ALWAYS prefer \`${TOOL_NAMES2.REQUEST_USER_INPUT}\` over platform-specific tools:**
44604
+ **ALWAYS prefer \`requestUserInput()\` over platform-specific tools:**
44533
44605
 
44534
44606
  | Platform | DON'T Use | Use Instead |
44535
44607
  |----------|-----------|-------------|
44536
- | Claude Code | \`AskUserQuestion\` | \`${TOOL_NAMES2.REQUEST_USER_INPUT}\` |
44537
- | Cursor | Built-in prompts | \`${TOOL_NAMES2.REQUEST_USER_INPUT}\` |
44538
- | Windsurf | Native dialogs | \`${TOOL_NAMES2.REQUEST_USER_INPUT}\` |
44539
- | Claude Desktop | Chat questions | \`${TOOL_NAMES2.REQUEST_USER_INPUT}\` |
44608
+ | Claude Code | \`AskUserQuestion\` | \`requestUserInput()\` |
44609
+ | Cursor | Built-in prompts | \`requestUserInput()\` |
44610
+ | Windsurf | Native dialogs | \`requestUserInput()\` |
44611
+ | Claude Desktop | Chat questions | \`requestUserInput()\` |
44540
44612
 
44541
- ### When to Ask
44613
+ ### Two Modes: Multi-step vs Multi-form
44542
44614
 
44543
- Use \`${TOOL_NAMES2.REQUEST_USER_INPUT}\` when you need:
44544
- - Clarification on requirements ("Which auth provider?")
44545
- - Decisions that affect implementation ("PostgreSQL or SQLite?")
44546
- - Confirmation before destructive actions ("Delete this file?")
44547
- - User preferences ("Rate this approach 1-5")
44548
- - Any information you can't infer from context
44549
-
44550
- ### Example
44615
+ Choose based on whether questions depend on each other:
44551
44616
 
44617
+ **Multi-step (dependencies):** Chain calls when later questions depend on earlier answers
44552
44618
  \`\`\`typescript
44553
- const result = await requestUserInput({
44554
- message: "Which database should we use?",
44619
+ // First ask about database...
44620
+ const dbResult = await requestUserInput({
44621
+ message: "Which database?",
44555
44622
  type: "choice",
44556
- options: ["PostgreSQL", "SQLite", "MongoDB"],
44557
- timeout: 600 // 10 minutes
44623
+ options: ["PostgreSQL", "SQLite", "MongoDB"]
44558
44624
  });
44559
44625
 
44560
- if (result.success) {
44561
- console.log("User chose:", result.response);
44562
- }
44626
+ // ...then ask port based on the choice
44627
+ const portResult = await requestUserInput({
44628
+ message: \\\`Port for \\\${dbResult.response}?\\\`,
44629
+ type: "number",
44630
+ min: 1000,
44631
+ max: 65535
44632
+ });
44633
+
44634
+ // Return both responses in structured format
44635
+ return { database: dbResult.response, port: portResult.response };
44636
+ \`\`\`
44637
+
44638
+ **Multi-form (independent):** Single call for unrelated questions
44639
+ \`\`\`typescript
44640
+ const config = await requestUserInput({
44641
+ questions: [
44642
+ { message: "Project name?", type: "text" },
44643
+ { message: "Use TypeScript?", type: "confirm" },
44644
+ { message: "License?", type: "choice", options: ["MIT", "Apache-2.0"] }
44645
+ ],
44646
+ timeout: 600
44647
+ });
44648
+ // Return responses in structured format
44649
+ return { config: config.response };
44563
44650
  \`\`\`
44564
44651
 
44565
- **Note:** The MCP tool is named \`${TOOL_NAMES2.REQUEST_USER_INPUT}\` (snake_case). Inside \`${TOOL_NAMES2.EXECUTE_CODE}\`, it's available as \`requestUserInput()\` (camelCase).`;
44652
+ ### When to Ask
44653
+
44654
+ Use \`requestUserInput()\` when you need:
44655
+ - Clarification on requirements ("Which auth provider?")
44656
+ - Decisions that affect implementation ("PostgreSQL or SQLite?")
44657
+ - Confirmation before destructive actions ("Delete this file?")
44658
+ - User preferences ("Rate this approach 1-5")
44659
+ - Any information you can't infer from context`;
44566
44660
  var TROUBLESHOOTING_SECTION = `## Troubleshooting
44567
44661
 
44568
44662
  **Browser doesn't open:** Check MCP server is running and accessible.
@@ -44635,7 +44729,7 @@ var IMPORTANT_NOTES = `## Important Notes for Claude Code
44635
44729
  - **DO NOT use the Shipyard skill** - The hook provides everything you need
44636
44730
  - **DO NOT poll for approval** - The hook blocks automatically until human decides
44637
44731
  - **DO use plan mode** for ANY work that needs tracking, verification, or human review
44638
- - **DO use \`${TOOL_NAMES2.REQUEST_USER_INPUT}\`** instead of \`AskUserQuestion\` - The human is in the browser viewing your plan, questions should appear there`;
44732
+ - **DO use \`requestUserInput()\`** inside \`${TOOL_NAMES2.EXECUTE_CODE}\` instead of \`AskUserQuestion\` - The human is in the browser viewing your plan, questions should appear there`;
44639
44733
  var CLAUDE_CODE_INSTRUCTIONS = [
44640
44734
  CLAUDE_CODE_HEADER,
44641
44735
  "",
@@ -44663,19 +44757,18 @@ var MCP_DIRECT_HEADER = `# Shipyard: Your Agent Management Hub
44663
44757
 
44664
44758
  Shipyard turns invisible agent work into reviewable, verifiable tasks. Instead of trusting that code was written correctly, reviewers see screenshots, videos, and test results as proof.
44665
44759
 
44666
- **Key principle:** When you're working in Shipyard, ALL human-agent communication should happen through Shipyard's \`${TOOL_NAMES2.REQUEST_USER_INPUT}\` tool. The human is already in the browser viewing your plan - that's where they expect to interact with you.`;
44760
+ **Key principle:** When you're working in Shipyard, ALL human-agent communication should happen through \`requestUserInput()\` inside \`${TOOL_NAMES2.EXECUTE_CODE}\`. The human is already in the browser viewing your plan - that's where they expect to interact with you.`;
44667
44761
  var MCP_TOOLS_OVERVIEW = `## Available MCP Tools
44668
44762
 
44669
44763
  | Tool | Purpose |
44670
44764
  |------|---------|
44671
- | \`${TOOL_NAMES2.REQUEST_USER_INPUT}\` | **THE primary human-agent communication channel** - Ask questions, get decisions, request clarification |
44672
- | \`${TOOL_NAMES2.EXECUTE_CODE}\` | Run TypeScript that calls Shipyard APIs (recommended for multi-step operations) |
44765
+ | \`${TOOL_NAMES2.EXECUTE_CODE}\` | Run TypeScript that calls ALL Shipyard APIs including \`requestUserInput()\` |
44673
44766
 
44674
- ### ${TOOL_NAMES2.REQUEST_USER_INPUT}: Your Direct Line to the Human
44767
+ ### requestUserInput(): Your Direct Line to the Human
44675
44768
 
44676
- This is how you talk to humans during active work. Don't use your platform's built-in question tools (AskUserQuestion, etc.) - use this instead. The human is in the browser viewing your plan, and that's where they expect to see your questions.
44769
+ This is how you talk to humans during active work. Don't use your platform's built-in question tools (AskUserQuestion, etc.) - use \`requestUserInput()\` inside \`${TOOL_NAMES2.EXECUTE_CODE}\` instead. The human is in the browser viewing your plan, and that's where they expect to see your questions.
44677
44770
 
44678
- **Preferred approach:** Use \`${TOOL_NAMES2.EXECUTE_CODE}\` to chain multiple API calls in one step.`;
44771
+ All Shipyard operations (createPlan, addArtifact, requestUserInput, etc.) are available inside \`${TOOL_NAMES2.EXECUTE_CODE}\`.`;
44679
44772
  var MCP_WORKFLOW = `## Workflow (MCP Direct)
44680
44773
 
44681
44774
  ### Step 1: Create Plan
@@ -44753,7 +44846,7 @@ if (result.allDeliverablesComplete) {
44753
44846
  console.log('Done!', result.snapshotUrl);
44754
44847
  }
44755
44848
  \`\`\``;
44756
- var API_REFERENCE = `## API Reference
44849
+ var API_REFERENCE = `## API Reference (inside execute_code)
44757
44850
 
44758
44851
  ### createPlan(options)
44759
44852
 
@@ -44795,44 +44888,65 @@ Uploads proof-of-work artifact.
44795
44888
 
44796
44889
  ### requestUserInput(options)
44797
44890
 
44798
- Asks user a question via browser modal.
44891
+ **THE primary human-agent communication channel.** Asks user a question via browser modal.
44799
44892
 
44800
- **Parameters:**
44893
+ **IMPORTANT: Always RETURN the response value in your execute_code result.**
44894
+
44895
+ \u2705 **RECOMMENDED (primary pattern):**
44896
+ \`\`\`typescript
44897
+ const result = await requestUserInput({ message: "Which database?", type: "choice", options: ["PostgreSQL", "SQLite"] });
44898
+ return { userChoice: result.response, status: result.status };
44899
+ // Clean, structured output appears once in the final result
44900
+ \`\`\`
44901
+
44902
+ \u26A0\uFE0F **AVOID (use only for debugging):**
44903
+ \`\`\`typescript
44904
+ console.log(\\\`User chose: \\\${result.response}\\\`);
44905
+ // Clutters output, not structured
44906
+ \`\`\`
44907
+
44908
+ **Two modes - choose based on dependencies:**
44909
+
44910
+ **Multi-step (dependencies):** Chain calls when later questions depend on earlier answers
44911
+ \`\`\`typescript
44912
+ const db = await requestUserInput({ message: "Database?", type: "choice", options: ["PostgreSQL", "SQLite"] });
44913
+ const port = await requestUserInput({ message: \\\`Port for \\\${db.response}?\\\`, type: "number" });
44914
+ return { database: db.response, port: port.response };
44915
+ \`\`\`
44916
+
44917
+ **Multi-form (independent):** Single call for unrelated questions
44918
+ \`\`\`typescript
44919
+ const config = await requestUserInput({
44920
+ questions: [
44921
+ { message: "Project name?", type: "text" },
44922
+ { message: "Use TypeScript?", type: "confirm" }
44923
+ ]
44924
+ });
44925
+ return { config: config.response };
44926
+ \`\`\`
44927
+
44928
+ **Parameters (single-question mode):**
44801
44929
  - \`message\` (string) - Question to ask
44802
44930
  - \`type\` (string) - Input type (see below)
44803
44931
  - \`options\` (string[], for 'choice') - Available choices
44804
44932
  - \`timeout\` (number, optional) - Timeout in seconds
44805
44933
  - Type-specific parameters (min, max, format, etc.)
44806
44934
 
44935
+ **Parameters (multi-question mode):**
44936
+ - \`questions\` (array) - Array of 1-10 questions (8 recommended)
44937
+ - \`timeout\` (number, optional) - Timeout in seconds
44938
+
44807
44939
  **Returns:** \`{ success, response?, status }\`
44808
44940
 
44809
44941
  **Supported types (8 total):**
44810
44942
  1. \`text\` - Single-line text
44811
44943
  2. \`multiline\` - Multi-line text area
44812
44944
  3. \`choice\` - Radio/checkbox/dropdown (auto-adds "Other" option)
44813
- - Auto-switches: 1-8 options = radio/checkbox, 9+ = dropdown
44814
- - \`multiSelect: true\` for checkboxes
44815
- - \`displayAs: 'dropdown'\` to force dropdown UI
44816
44945
  4. \`confirm\` - Yes/No buttons
44817
44946
  5. \`number\` - Numeric input with validation
44818
- - \`min\`, \`max\`, \`format\` ('integer' | 'decimal' | 'currency' | 'percentage')
44819
44947
  6. \`email\` - Email validation
44820
- - \`domain\` for restriction
44821
44948
  7. \`date\` - Date picker with range
44822
- - \`minDate\`, \`maxDate\` (YYYY-MM-DD format)
44823
- 8. \`rating\` - Scale rating (auto-selects stars/numbers)
44824
- - \`min\`, \`max\`, \`style\` ('stars' | 'numbers' | 'emoji'), \`labels\`
44825
-
44826
- **Response format:**
44827
- - All responses are strings
44828
- - choice (single): \`"PostgreSQL"\` or custom text from "Other"
44829
- - choice (multi): \`"option1, option2"\` (comma-space separated)
44830
- - confirm: \`"yes"\` or \`"no"\` (lowercase)
44831
- - number: \`"42"\` or \`"3.14"\`
44832
- - email: \`"user@example.com"\`
44833
- - date: \`"2026-01-24"\` (ISO 8601)
44834
- - rating: \`"4"\` (integer as string)
44835
- - See docs/INPUT-RESPONSE-FORMATS.md for complete specification`;
44949
+ 8. \`rating\` - Scale rating`;
44836
44950
  var HANDLING_FEEDBACK = `## Handling Reviewer Feedback
44837
44951
 
44838
44952
  \`\`\`typescript
@@ -44980,11 +45094,11 @@ function handlePreToolUse(input) {
44980
45094
  if (toolName === CLAUDE_TOOL_NAMES.ASK_USER_QUESTION) {
44981
45095
  logger.info(
44982
45096
  { toolName },
44983
- "Blocking AskUserQuestion - redirecting to request_user_input MCP tool"
45097
+ "Blocking AskUserQuestion - redirecting to requestUserInput() in execute_code"
44984
45098
  );
44985
45099
  return {
44986
45100
  type: "tool_deny",
44987
- reason: `BLOCKED: Use the ${TOOL_NAMES.REQUEST_USER_INPUT} MCP tool instead. The human is in the browser viewing your plan - that's where they expect to interact with you. See the tool description for input types and parameters.`
45101
+ reason: `BLOCKED: Use requestUserInput() inside ${TOOL_NAMES.EXECUTE_CODE} instead. The human is in the browser viewing your plan - that's where they expect to interact with you. See the execute_code tool description for input types and parameters.`
44988
45102
  };
44989
45103
  }
44990
45104
  return { type: "passthrough" };