@schoolai/shipyard-mcp 0.1.3-next.466 → 0.1.3-next.468

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.
@@ -28494,7 +28494,7 @@ init_cjs_shims();
28494
28494
  // ../../packages/schema/dist/index.mjs
28495
28495
  init_cjs_shims();
28496
28496
 
28497
- // ../../packages/schema/dist/yjs-helpers-CFQmkNYl.mjs
28497
+ // ../../packages/schema/dist/yjs-helpers-BBG4tC2R.mjs
28498
28498
  init_cjs_shims();
28499
28499
 
28500
28500
  // ../../packages/schema/dist/plan.mjs
@@ -42665,7 +42665,7 @@ var PRReviewCommentSchema = external_exports.object({
42665
42665
  resolved: external_exports.boolean().optional()
42666
42666
  });
42667
42667
 
42668
- // ../../packages/schema/dist/yjs-helpers-CFQmkNYl.mjs
42668
+ // ../../packages/schema/dist/yjs-helpers-BBG4tC2R.mjs
42669
42669
  function assertNever2(value) {
42670
42670
  throw new Error(`Unhandled discriminated union member: ${JSON.stringify(value)}`);
42671
42671
  }
@@ -45704,9 +45704,8 @@ init_cjs_shims();
45704
45704
 
45705
45705
  // src/config/env/web.ts
45706
45706
  init_cjs_shims();
45707
- var defaultWebUrl = process.env.NODE_ENV === "production" ? "https://schoolai.github.io/shipyard" : "http://localhost:5173";
45708
45707
  var schema3 = external_exports.object({
45709
- SHIPYARD_WEB_URL: external_exports.string().url().default(defaultWebUrl)
45708
+ SHIPYARD_WEB_URL: external_exports.string().url().default("https://schoolai.github.io/shipyard")
45710
45709
  });
45711
45710
  var webConfig = loadEnv(schema3);
45712
45711
 
@@ -1,5 +1,7 @@
1
1
  # Server Environment Variables
2
2
  # Copy this file to .env and adjust values for local development
3
+ #
4
+ # NOTE: Production URLs are the defaults. Only set these for local development.
3
5
 
4
6
  # Server configuration
5
7
  NODE_ENV=development
@@ -10,8 +12,15 @@ REGISTRY_PORT=32191
10
12
  SHIPYARD_STATE_DIR=~/.shipyard
11
13
 
12
14
  # Web UI URL (for links generated by server)
15
+ # Default: https://schoolai.github.io/shipyard (production)
16
+ # Uncomment for local development:
13
17
  SHIPYARD_WEB_URL=http://localhost:5173
14
18
 
19
+ # WebRTC signaling server
20
+ # Default: wss://shipyard-signaling.jacob-191.workers.dev (production)
21
+ # Uncomment for local development:
22
+ SIGNALING_URL=ws://localhost:4444
23
+
15
24
  # GitHub integration (optional - falls back to gh CLI)
16
25
  GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
17
26
 
@@ -863,7 +863,7 @@ function createHandedOffConversationVersion(params) {
863
863
  return ConversationVersionSchema.parse(version);
864
864
  }
865
865
 
866
- // ../../packages/schema/dist/yjs-helpers-CFQmkNYl.mjs
866
+ // ../../packages/schema/dist/yjs-helpers-BBG4tC2R.mjs
867
867
  import { z as z2 } from "zod";
868
868
  import { nanoid as nanoid2 } from "nanoid";
869
869
  import * as Y from "yjs";
@@ -1176,6 +1176,30 @@ function applyStatusTransitionFields(map, transition) {
1176
1176
  assertNever(transition);
1177
1177
  }
1178
1178
  }
1179
+ function resetPlanToDraft(ydoc, actor) {
1180
+ const metadataResult = getPlanMetadataWithValidation(ydoc);
1181
+ if (!metadataResult.success) return {
1182
+ success: false,
1183
+ error: metadataResult.error
1184
+ };
1185
+ if (metadataResult.data.status === "draft") return {
1186
+ success: false,
1187
+ error: "Plan is already in draft status"
1188
+ };
1189
+ ydoc.transact(() => {
1190
+ const map = ydoc.getMap(YDOC_KEYS.METADATA);
1191
+ map.set("status", "draft");
1192
+ map.delete("reviewRequestId");
1193
+ map.delete("reviewedAt");
1194
+ map.delete("reviewedBy");
1195
+ map.delete("reviewComment");
1196
+ map.delete("completedAt");
1197
+ map.delete("completedBy");
1198
+ map.delete("snapshotUrl");
1199
+ map.set("updatedAt", Date.now());
1200
+ }, actor ? { actor } : void 0);
1201
+ return { success: true };
1202
+ }
1179
1203
  function transitionPlanStatus(ydoc, transition, actor) {
1180
1204
  const metadataResult = getPlanMetadataWithValidation(ydoc);
1181
1205
  if (!metadataResult.success) return {
@@ -2816,6 +2840,7 @@ export {
2816
2840
  getPlanMetadata,
2817
2841
  getPlanMetadataWithValidation,
2818
2842
  setPlanMetadata,
2843
+ resetPlanToDraft,
2819
2844
  transitionPlanStatus,
2820
2845
  initPlanMetadata,
2821
2846
  getStepCompletions,
@@ -3,7 +3,7 @@ import {
3
3
  YDOC_KEYS,
4
4
  createInputRequest,
5
5
  logPlanEvent
6
- } from "./chunk-75NZRAN5.js";
6
+ } from "./chunk-76JWRTPI.js";
7
7
  import {
8
8
  logger
9
9
  } from "./chunk-GSGLHRWX.js";
@@ -187,6 +187,7 @@ import {
187
187
  removePlanIndexEntry,
188
188
  removePlanTag,
189
189
  removeViewedByFromIndex,
190
+ resetPlanToDraft,
190
191
  resolvePRReviewComment,
191
192
  revokeUser,
192
193
  setAgentPresence,
@@ -203,7 +204,7 @@ import {
203
204
  updateLinkedPRStatus,
204
205
  updatePlanIndexViewedBy,
205
206
  validateA2AMessages
206
- } from "./chunk-75NZRAN5.js";
207
+ } from "./chunk-76JWRTPI.js";
207
208
  import "./chunk-JSBRDJBE.js";
208
209
  export {
209
210
  A2ADataPartSchema,
@@ -394,6 +395,7 @@ export {
394
395
  removePlanIndexEntry,
395
396
  removePlanTag,
396
397
  removeViewedByFromIndex,
398
+ resetPlanToDraft,
397
399
  resolvePRReviewComment,
398
400
  revokeUser,
399
401
  setAgentPresence,
@@ -19,7 +19,7 @@ import {
19
19
  } from "./chunk-EBNL5ZX7.js";
20
20
  import {
21
21
  InputRequestManager
22
- } from "./chunk-MZTJGBLT.js";
22
+ } from "./chunk-BWP37ADP.js";
23
23
  import {
24
24
  ArtifactSchema,
25
25
  DeliverableSchema,
@@ -63,12 +63,13 @@ import {
63
63
  logPlanEvent,
64
64
  parseClaudeCodeOrigin,
65
65
  parseThreads,
66
+ resetPlanToDraft,
66
67
  setAgentPresence,
67
68
  setPlanIndexEntry,
68
69
  setPlanMetadata,
69
70
  touchPlanIndexEntry,
70
71
  transitionPlanStatus
71
- } from "./chunk-75NZRAN5.js";
72
+ } from "./chunk-76JWRTPI.js";
72
73
  import {
73
74
  loadEnv,
74
75
  logger
@@ -558,9 +559,8 @@ import open from "open";
558
559
 
559
560
  // src/config/env/web.ts
560
561
  import { z as z2 } from "zod";
561
- var defaultWebUrl = process.env.NODE_ENV === "production" ? "https://schoolai.github.io/shipyard" : "http://localhost:5173";
562
562
  var schema2 = z2.object({
563
- SHIPYARD_WEB_URL: z2.string().url().default(defaultWebUrl)
563
+ SHIPYARD_WEB_URL: z2.string().url().default("https://schoolai.github.io/shipyard")
564
564
  });
565
565
  var webConfig = loadEnv(schema2);
566
566
 
@@ -2266,8 +2266,7 @@ async function isRegistryRunning() {
2266
2266
  // src/webrtc-provider.ts
2267
2267
  import wrtc from "@roamhq/wrtc";
2268
2268
  import { WebrtcProvider } from "y-webrtc";
2269
- var defaultSignaling = process.env.NODE_ENV === "production" ? "wss://shipyard-signaling.jacob-191.workers.dev" : "ws://localhost:4444";
2270
- var SIGNALING_SERVER = process.env.SIGNALING_URL || defaultSignaling;
2269
+ var SIGNALING_SERVER = process.env.SIGNALING_URL || "wss://shipyard-signaling.jacob-191.workers.dev";
2271
2270
  if (typeof globalThis.RTCPeerConnection === "undefined") {
2272
2271
  globalThis.RTCPeerConnection = wrtc.RTCPeerConnection;
2273
2272
  globalThis.RTCSessionDescription = wrtc.RTCSessionDescription;
@@ -2858,6 +2857,7 @@ Linked to deliverable: ${input.deliverableId}` : "";
2858
2857
  const fragment = doc.getXmlFragment("document");
2859
2858
  const blocks = editor.yXmlFragmentToBlocks(fragment);
2860
2859
  const artifacts = getArtifacts(doc);
2860
+ const hasLocalArtifacts = artifacts.some((a) => a.storage === "local");
2861
2861
  const completionSnapshot = createPlanSnapshot(
2862
2862
  doc,
2863
2863
  "Task completed - all deliverables fulfilled",
@@ -2943,7 +2943,7 @@ URL: ${artifactUrl}${linkedText}
2943
2943
  \u{1F389} ALL DELIVERABLES COMPLETE! Task auto-completed.${prText}
2944
2944
 
2945
2945
  Snapshot URL saved to: ${snapshotFile}
2946
- (Note: Very long URL - recommend not reading directly. Use file path to attach to PR or access later.)`
2946
+ (Note: Very long URL - recommend not reading directly. Use file path to attach to PR or access later.)${hasLocalArtifacts ? "\n\n\u26A0\uFE0F WARNING: This plan contains local artifacts that will not be visible to remote viewers. For full remote access, configure GITHUB_TOKEN to upload artifacts to GitHub." : ""}`
2947
2947
  }
2948
2948
  ],
2949
2949
  // Keep structured data for execute_code wrapper
@@ -3248,6 +3248,7 @@ RETURNS:
3248
3248
  };
3249
3249
  }
3250
3250
  const artifacts = getArtifacts(ydoc);
3251
+ const hasLocalArtifacts = artifacts.some((a) => a.storage === "local");
3251
3252
  if (artifacts.length === 0) {
3252
3253
  return {
3253
3254
  content: [
@@ -3367,6 +3368,9 @@ Generated with [Shipyard](https://github.com/SchoolAI/shipyard)"
3367
3368
  linkPR({ planId, sessionToken, prNumber: 42 })
3368
3369
  \`\`\``;
3369
3370
  }
3371
+ if (hasLocalArtifacts) {
3372
+ responseText += "\n\n\u26A0\uFE0F WARNING: This plan contains local artifacts that will not be visible to remote viewers. For full remote access, configure GITHUB_TOKEN to upload artifacts to GitHub.";
3373
+ }
3370
3374
  return {
3371
3375
  content: [{ type: "text", text: responseText }]
3372
3376
  };
@@ -4539,7 +4543,40 @@ async function applyOperation(blocks, operation, editor) {
4539
4543
 
4540
4544
  // src/tools/update-plan.ts
4541
4545
  import { ServerBlockNoteEditor as ServerBlockNoteEditor7 } from "@blocknote/server-util";
4546
+ import { nanoid as nanoid7 } from "nanoid";
4542
4547
  import { z as z11 } from "zod";
4548
+ function buildStatusTransition(targetStatus, actorName) {
4549
+ const now = Date.now();
4550
+ switch (targetStatus) {
4551
+ case "pending_review":
4552
+ return {
4553
+ status: "pending_review",
4554
+ reviewRequestId: nanoid7()
4555
+ };
4556
+ case "changes_requested":
4557
+ return {
4558
+ status: "changes_requested",
4559
+ reviewedAt: now,
4560
+ reviewedBy: actorName
4561
+ };
4562
+ case "in_progress":
4563
+ return {
4564
+ status: "in_progress",
4565
+ reviewedAt: now,
4566
+ reviewedBy: actorName
4567
+ };
4568
+ case "completed":
4569
+ return {
4570
+ status: "completed",
4571
+ completedAt: now,
4572
+ completedBy: actorName
4573
+ };
4574
+ case "draft":
4575
+ return null;
4576
+ default:
4577
+ return null;
4578
+ }
4579
+ }
4543
4580
  var UpdatePlanInput = z11.object({
4544
4581
  planId: z11.string().describe("The plan ID to update"),
4545
4582
  sessionToken: z11.string().describe("Session token from create_plan"),
@@ -4589,6 +4626,7 @@ STATUSES:
4589
4626
  required: ["planId", "sessionToken"]
4590
4627
  }
4591
4628
  },
4629
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: tool handler orchestrates validation, snapshots, and state transitions
4592
4630
  handler: async (args) => {
4593
4631
  const input = UpdatePlanInput.parse(args);
4594
4632
  const doc = await getOrCreateDoc3(input.planId);
@@ -4616,12 +4654,6 @@ STATUSES:
4616
4654
  isError: true
4617
4655
  };
4618
4656
  }
4619
- const updates = {
4620
- updatedAt: Date.now()
4621
- };
4622
- if (input.title) updates.title = input.title;
4623
- if (input.status) updates.status = input.status;
4624
- if (input.tags !== void 0) updates.tags = input.tags;
4625
4657
  const statusChanged = input.status && input.status !== existingMetadata.status;
4626
4658
  if (statusChanged && input.status) {
4627
4659
  const editor = ServerBlockNoteEditor7.create();
@@ -4630,8 +4662,52 @@ STATUSES:
4630
4662
  const reason = `Status changed to ${input.status}`;
4631
4663
  const snapshot = createPlanSnapshot(doc, reason, actorName, input.status, blocks);
4632
4664
  addSnapshot(doc, snapshot);
4665
+ if (input.status === "draft") {
4666
+ const resetResult = resetPlanToDraft(doc, actorName);
4667
+ if (!resetResult.success) {
4668
+ return {
4669
+ content: [
4670
+ {
4671
+ type: "text",
4672
+ text: `Failed to reset plan to draft: ${resetResult.error}`
4673
+ }
4674
+ ],
4675
+ isError: true
4676
+ };
4677
+ }
4678
+ } else {
4679
+ const transition = buildStatusTransition(input.status, actorName);
4680
+ if (!transition) {
4681
+ return {
4682
+ content: [
4683
+ {
4684
+ type: "text",
4685
+ text: `Invalid status: ${input.status}`
4686
+ }
4687
+ ],
4688
+ isError: true
4689
+ };
4690
+ }
4691
+ const transitionResult = transitionPlanStatus(doc, transition, actorName);
4692
+ if (!transitionResult.success) {
4693
+ return {
4694
+ content: [
4695
+ {
4696
+ type: "text",
4697
+ text: `Failed to transition status: ${transitionResult.error}`
4698
+ }
4699
+ ],
4700
+ isError: true
4701
+ };
4702
+ }
4703
+ }
4704
+ }
4705
+ const updates = {};
4706
+ if (input.title) updates.title = input.title;
4707
+ if (input.tags !== void 0) updates.tags = input.tags;
4708
+ if (Object.keys(updates).length > 0) {
4709
+ setPlanMetadata(doc, updates, actorName);
4633
4710
  }
4634
- setPlanMetadata(doc, updates, actorName);
4635
4711
  const indexDoc = await getOrCreateDoc3(PLAN_INDEX_DOC_NAME);
4636
4712
  if (existingMetadata.ownerId) {
4637
4713
  setPlanIndexEntry(indexDoc, {
@@ -5088,7 +5164,7 @@ async function addArtifact2(opts) {
5088
5164
  const metadata = getPlanMetadata(ydoc);
5089
5165
  let artifactUrl = "";
5090
5166
  if (addedArtifact) {
5091
- artifactUrl = addedArtifact.storage === "github" ? addedArtifact.url : `http://localhost:${process.env.REGISTRY_PORT || 3e3}/artifacts/${addedArtifact.localArtifactId}`;
5167
+ artifactUrl = addedArtifact.storage === "github" ? addedArtifact.url : `http://localhost:${registryConfig.REGISTRY_PORT[0]}/artifacts/${addedArtifact.localArtifactId}`;
5092
5168
  }
5093
5169
  return {
5094
5170
  artifactId: addedArtifact?.id || "",
@@ -5148,7 +5224,7 @@ async function setupReviewNotification(planId, pollIntervalSeconds) {
5148
5224
  return { script, fullResponse: text };
5149
5225
  }
5150
5226
  async function requestUserInput(opts) {
5151
- const { InputRequestManager: InputRequestManager2 } = await import("./input-request-manager-43QSOJS3.js");
5227
+ const { InputRequestManager: InputRequestManager2 } = await import("./input-request-manager-73GSTOIB.js");
5152
5228
  const ydoc = await getOrCreateDoc3(PLAN_INDEX_DOC_NAME);
5153
5229
  const manager = new InputRequestManager2();
5154
5230
  const params = opts.type === "choice" ? {
@@ -5192,12 +5268,12 @@ async function requestUserInput(opts) {
5192
5268
  };
5193
5269
  }
5194
5270
  async function postActivityUpdate(opts) {
5195
- const { logPlanEvent: logPlanEvent2 } = await import("./dist-HIDISXZO.js");
5271
+ const { logPlanEvent: logPlanEvent2 } = await import("./dist-ORKL4P3L.js");
5196
5272
  const { getGitHubUsername: getGitHubUsername2 } = await import("./server-identity-6PHKR2FY.js");
5197
- const { nanoid: nanoid7 } = await import("nanoid");
5273
+ const { nanoid: nanoid8 } = await import("nanoid");
5198
5274
  const doc = await getOrCreateDoc3(opts.planId);
5199
5275
  const actorName = await getGitHubUsername2();
5200
- const requestId = nanoid7();
5276
+ const requestId = nanoid8();
5201
5277
  const eventId = logPlanEvent2(
5202
5278
  doc,
5203
5279
  "agent_activity",
@@ -5215,7 +5291,7 @@ async function postActivityUpdate(opts) {
5215
5291
  return { success: true, eventId, requestId };
5216
5292
  }
5217
5293
  async function resolveActivityRequest(opts) {
5218
- const { logPlanEvent: logPlanEvent2, getPlanEvents } = await import("./dist-HIDISXZO.js");
5294
+ const { logPlanEvent: logPlanEvent2, getPlanEvents } = await import("./dist-ORKL4P3L.js");
5219
5295
  const { getGitHubUsername: getGitHubUsername2 } = await import("./server-identity-6PHKR2FY.js");
5220
5296
  const doc = await getOrCreateDoc3(opts.planId);
5221
5297
  const actorName = await getGitHubUsername2();
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  InputRequestManager
3
- } from "./chunk-MZTJGBLT.js";
4
- import "./chunk-75NZRAN5.js";
3
+ } from "./chunk-BWP37ADP.js";
4
+ import "./chunk-76JWRTPI.js";
5
5
  import "./chunk-GSGLHRWX.js";
6
6
  import "./chunk-JSBRDJBE.js";
7
7
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schoolai/shipyard-mcp",
3
- "version": "0.1.3-next.466",
3
+ "version": "0.1.3-next.468",
4
4
  "description": "Shipyard MCP server and CLI tools for distributed planning with CRDTs",
5
5
  "type": "module",
6
6
  "bin": {