@schoolai/shipyard-mcp 0.2.2-next.493 → 0.2.2-next.497
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 +21 -1
- package/apps/server/dist/{chunk-ZD2SHV5V.js → chunk-BL4TO47B.js} +1 -1
- package/apps/server/dist/{chunk-5V7HUMDU.js → chunk-RSQQVNON.js} +21 -1
- package/apps/server/dist/{dist-2W7US5HB.js → dist-XVATLWFP.js} +1 -1
- package/apps/server/dist/index.js +68 -26
- package/apps/server/dist/{input-request-manager-QX7MYHH7.js → input-request-manager-S5RMTI23.js} +2 -2
- package/package.json +1 -1
package/apps/hook/dist/index.cjs
CHANGED
|
@@ -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({
|
|
@@ -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-BL4TO47B.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-RSQQVNON.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 = "";
|
|
@@ -5650,7 +5692,7 @@ async function setupReviewNotification(planId, pollIntervalSeconds) {
|
|
|
5650
5692
|
return { script, fullResponse: text };
|
|
5651
5693
|
}
|
|
5652
5694
|
async function requestUserInput(opts) {
|
|
5653
|
-
const { InputRequestManager: InputRequestManager2 } = await import("./input-request-manager-
|
|
5695
|
+
const { InputRequestManager: InputRequestManager2 } = await import("./input-request-manager-S5RMTI23.js");
|
|
5654
5696
|
const ydoc = await getOrCreateDoc3(PLAN_INDEX_DOC_NAME);
|
|
5655
5697
|
const manager = new InputRequestManager2();
|
|
5656
5698
|
const params = opts.type === "choice" ? {
|
|
@@ -5694,7 +5736,7 @@ async function requestUserInput(opts) {
|
|
|
5694
5736
|
};
|
|
5695
5737
|
}
|
|
5696
5738
|
async function postActivityUpdate(opts) {
|
|
5697
|
-
const { logPlanEvent: logPlanEvent2 } = await import("./dist-
|
|
5739
|
+
const { logPlanEvent: logPlanEvent2 } = await import("./dist-XVATLWFP.js");
|
|
5698
5740
|
const { getGitHubUsername: getGitHubUsername2 } = await import("./server-identity-LSZ4CZRK.js");
|
|
5699
5741
|
const { nanoid: nanoid8 } = await import("nanoid");
|
|
5700
5742
|
const doc = await getOrCreateDoc3(opts.planId);
|
|
@@ -5717,7 +5759,7 @@ async function postActivityUpdate(opts) {
|
|
|
5717
5759
|
return { success: true, eventId, requestId };
|
|
5718
5760
|
}
|
|
5719
5761
|
async function resolveActivityRequest(opts) {
|
|
5720
|
-
const { logPlanEvent: logPlanEvent2, getPlanEvents } = await import("./dist-
|
|
5762
|
+
const { logPlanEvent: logPlanEvent2, getPlanEvents } = await import("./dist-XVATLWFP.js");
|
|
5721
5763
|
const { getGitHubUsername: getGitHubUsername2 } = await import("./server-identity-LSZ4CZRK.js");
|
|
5722
5764
|
const doc = await getOrCreateDoc3(opts.planId);
|
|
5723
5765
|
const actorName = await getGitHubUsername2();
|