@agent-plan/mcp 0.2.27 → 0.2.29
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/dist/index.d.ts.map +1 -1
- package/dist/index.js +84 -84
- package/package.json +3 -3
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AA0kGA,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAItD"}
|
package/dist/index.js
CHANGED
|
@@ -1437,10 +1437,7 @@ server.registerTool("planner-phase-update", {
|
|
|
1437
1437
|
const staleParentRefs = descriptionFreshness?.diagnostics
|
|
1438
1438
|
.filter((entry) => entry.state === "stale" && entry.ownerId === persisted.featureId)
|
|
1439
1439
|
.map((entry) => entry.ownerRef) ?? [];
|
|
1440
|
-
|
|
1441
|
-
? `\n⚠️ Parent description review required: ${staleParentRefs.join(", ")}. Run planner-description-freshness for the non-mutating reconciliation preview.`
|
|
1442
|
-
: "";
|
|
1443
|
-
return text(`✅ Phase updated: ${formatPhaseRef(persisted.number, featureNumberOfPhase(persisted, refreshedFeatures))} — ${persisted.title}${persisted.shortId ? ` · ${persisted.shortId}` : ""}. Fields saved: ${receivedFields.join(", ")}.${freshnessNotice}`, { phase: persisted, updated: true, updatedFields: receivedFields, ...(descriptionFreshness ? { descriptionFreshness, staleParentRefs } : {}) });
|
|
1440
|
+
return text(`✅ Phase updated: ${formatPhaseRef(persisted.number, featureNumberOfPhase(persisted, refreshedFeatures))} — ${persisted.title}${persisted.shortId ? ` · ${persisted.shortId}` : ""}. Fields saved: ${receivedFields.join(", ")}.`, { phase: persisted, updated: true, updatedFields: receivedFields, ...(descriptionFreshness ? { descriptionFreshness, staleParentRefs } : {}) });
|
|
1444
1441
|
});
|
|
1445
1442
|
server.registerTool("planner-phase-delete", {
|
|
1446
1443
|
description: "Delete a phase and unlink it from features.",
|
|
@@ -1748,60 +1745,62 @@ server.registerTool("planner-task-update", {
|
|
|
1748
1745
|
}
|
|
1749
1746
|
let updatedTask;
|
|
1750
1747
|
const timestamp = nowISO();
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
else
|
|
1766
|
-
delete task.descriptionRef;
|
|
1767
|
-
}
|
|
1768
|
-
if (notes !== undefined)
|
|
1769
|
-
task.notes = notes.trim();
|
|
1770
|
-
if (decisions !== undefined)
|
|
1771
|
-
task.decisions = decisions.map((item) => item.trim()).filter(Boolean);
|
|
1772
|
-
if (checklist !== undefined) {
|
|
1773
|
-
task.checklist = checklist.map((item, index) => ({
|
|
1774
|
-
id: createChecklistItemId(task.id, index + 1, item),
|
|
1775
|
-
number: index + 1,
|
|
1776
|
-
title: item.trim(),
|
|
1777
|
-
checked: false,
|
|
1778
|
-
}));
|
|
1779
|
-
}
|
|
1780
|
-
if (subtasks !== undefined) {
|
|
1781
|
-
const existingIds = new Set(task.subtasks.map((item) => item.id));
|
|
1782
|
-
if (subtasks.some((item) => item.id !== undefined && !existingIds.has(item.id))) {
|
|
1783
|
-
throw new PlanStoreError("Subtask IDs must belong to the target task.", undefined, { errorCode: "SUBTASK_ID_INVALID" });
|
|
1748
|
+
try {
|
|
1749
|
+
await st.updateTask(found.phase.id, found.task.id, (task) => {
|
|
1750
|
+
if (title !== undefined)
|
|
1751
|
+
task.title = title.trim();
|
|
1752
|
+
if (priority !== undefined)
|
|
1753
|
+
task.priority = priority;
|
|
1754
|
+
if (description !== undefined)
|
|
1755
|
+
task.description = description.trim();
|
|
1756
|
+
if (rawDescriptionRef !== undefined) {
|
|
1757
|
+
const descriptionRef = normalizeDescriptionRef(rawDescriptionRef);
|
|
1758
|
+
if (descriptionRef)
|
|
1759
|
+
task.descriptionRef = descriptionRef;
|
|
1760
|
+
else
|
|
1761
|
+
delete task.descriptionRef;
|
|
1784
1762
|
}
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
}
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1763
|
+
if (notes !== undefined)
|
|
1764
|
+
task.notes = notes.trim();
|
|
1765
|
+
if (decisions !== undefined)
|
|
1766
|
+
task.decisions = decisions.map((item) => item.trim()).filter(Boolean);
|
|
1767
|
+
if (checklist !== undefined) {
|
|
1768
|
+
task.checklist = checklist.map((item, index) => ({
|
|
1769
|
+
id: createChecklistItemId(task.id, index + 1, item),
|
|
1770
|
+
number: index + 1,
|
|
1771
|
+
title: item.trim(),
|
|
1772
|
+
checked: false,
|
|
1773
|
+
}));
|
|
1774
|
+
}
|
|
1775
|
+
if (subtasks !== undefined) {
|
|
1776
|
+
const existingIds = new Set(task.subtasks.map((item) => item.id));
|
|
1777
|
+
if (subtasks.some((item) => item.id !== undefined && !existingIds.has(item.id))) {
|
|
1778
|
+
throw new PlanStoreError("Subtask IDs must belong to the target task.", undefined, { errorCode: "SUBTASK_ID_INVALID" });
|
|
1779
|
+
}
|
|
1780
|
+
task.subtasks = subtasks.map((item) => ({ id: item.id ?? randomUUID(), title: item.title.trim(), description: item.description?.trim() ?? "", status: item.status ?? "planned", createdAt: task.subtasks.find((candidate) => candidate.id === item.id)?.createdAt ?? timestamp, updatedAt: timestamp }));
|
|
1781
|
+
}
|
|
1782
|
+
if (status !== undefined && status !== task.status) {
|
|
1783
|
+
// Record status change in the incremental statusLog.
|
|
1784
|
+
const entry = {
|
|
1785
|
+
id: createChecklistItemId(task.id, (task.statusLog?.length ?? 0) + 1, `${task.status}-${status}`),
|
|
1786
|
+
date: timestamp,
|
|
1787
|
+
fromStatus: task.status,
|
|
1788
|
+
toStatus: status,
|
|
1789
|
+
title: motivation?.split("\n")[0]?.trim() || `${task.status} → ${status}`,
|
|
1790
|
+
description: motivation?.trim() || "",
|
|
1791
|
+
};
|
|
1792
|
+
task.statusLog = [...(task.statusLog ?? []), entry];
|
|
1793
|
+
applyTaskLifecycleDates(task, status, timestamp);
|
|
1794
|
+
}
|
|
1795
|
+
task.updatedAt = timestamp;
|
|
1796
|
+
updatedTask = task;
|
|
1797
|
+
return task;
|
|
1798
|
+
});
|
|
1799
|
+
}
|
|
1800
|
+
catch (error) {
|
|
1801
|
+
const details = error instanceof PlanStoreError ? error.details : undefined;
|
|
1802
|
+
return { ...text(`Task update failed: ${error instanceof Error ? error.message : "unknown error"}`, { updated: false, errorCode: details?.errorCode ?? "TASK_UPDATE_FAILED" }), isError: true };
|
|
1803
|
+
}
|
|
1805
1804
|
await st.syncTaskStatusRollup(found.phase.id);
|
|
1806
1805
|
const features = (await st.loadFeatures()).features;
|
|
1807
1806
|
const t = updatedTask ?? found.task;
|
|
@@ -1827,13 +1826,10 @@ server.registerTool("planner-task-update", {
|
|
|
1827
1826
|
const staleParentRefs = descriptionFreshness?.diagnostics
|
|
1828
1827
|
.filter((entry) => entry.state === "stale" && ownerIds.has(entry.ownerId))
|
|
1829
1828
|
.map((entry) => entry.ownerRef) ?? [];
|
|
1830
|
-
const freshnessNotice = staleParentRefs.length > 0
|
|
1831
|
-
? `\n⚠️ Parent description review required: ${staleParentRefs.join(", ")}. Run planner-description-freshness for the non-mutating reconciliation preview.`
|
|
1832
|
-
: "";
|
|
1833
1829
|
const details = resumeRequired
|
|
1834
1830
|
? { task: t, updated: true, updatedFields: receivedFields, resumeRequired, ...(descriptionFreshness ? { descriptionFreshness, staleParentRefs } : {}) }
|
|
1835
1831
|
: { task: t, updated: true, updatedFields: receivedFields, ...(descriptionFreshness ? { descriptionFreshness, staleParentRefs } : {}) };
|
|
1836
|
-
return writeAndSummarize(st, `✅ Task updated: ${taskCompositeRef(t, found.phase, features)} — ${t.title} (${t.status})${t.shortId ? ` · ${t.shortId}` : ""}. Fields saved: ${receivedFields.join(", ")}.${
|
|
1832
|
+
return writeAndSummarize(st, `✅ Task updated: ${taskCompositeRef(t, found.phase, features)} — ${t.title} (${t.status})${t.shortId ? ` · ${t.shortId}` : ""}. Fields saved: ${receivedFields.join(", ")}.${resumeNotice}`, details);
|
|
1837
1833
|
});
|
|
1838
1834
|
server.registerTool("planner-task-checklist-toggle", {
|
|
1839
1835
|
description: "Tick/untick a task checklist item (a 'step') without rewriting the whole list. Accepts the item as C{n} (e.g. C2), the item id, or the title (case-insensitive, first match). Pass checked=true/false to set explicitly, or omit to toggle. Use this instead of writing DONE in step titles. Items are numbered C1/C2… per task.",
|
|
@@ -2564,8 +2560,8 @@ server.registerTool("planner-handoff-show", {
|
|
|
2564
2560
|
&& phase.handoffAudit.contentLength === phase.handoff.length);
|
|
2565
2561
|
const resumeReady = persistenceVerified && Boolean(phase.handoffAudit?.resumeReadyAt);
|
|
2566
2562
|
const status = resumeReady
|
|
2567
|
-
? "Resume-ready: persisted read-back
|
|
2568
|
-
: "NOT resume-ready: after reading this
|
|
2563
|
+
? "Resume-ready: persisted compact capsule read-back completed."
|
|
2564
|
+
: "NOT resume-ready: after reading this persisted capsule, call planner-handoff-verify with its contentHash. The planner derives legacy evidence from persisted state; rewrite only if the capsule itself omits resume-critical context.";
|
|
2569
2565
|
return text(`Handoff for ${r.compositeRef}\n${status}\nContent hash: ${contentHash}\n\n${phaseWorkMap.content}\n\nBefore proposing new work, reread the canonical phase and relevant sibling task full view; do not duplicate an already-owned capability.\n\n${bounded.content}`, {
|
|
2570
2566
|
phaseRef: r.compositeRef,
|
|
2571
2567
|
phaseId: r.phase.id,
|
|
@@ -2579,15 +2575,15 @@ server.registerTool("planner-handoff-show", {
|
|
|
2579
2575
|
});
|
|
2580
2576
|
});
|
|
2581
2577
|
server.registerTool("planner-handoff-verify", {
|
|
2582
|
-
description: "Finalize one persisted handoff as resume-ready
|
|
2578
|
+
description: "Finalize one persisted handoff as resume-ready after planner-handoff-show confirms the persisted compact resume capsule. Legacy sourceReviews and omissionsFound evidence remains accepted but is optional; the planner derives omitted evidence from persisted state.",
|
|
2583
2579
|
inputSchema: {
|
|
2584
2580
|
phaseRef: z.string().min(1),
|
|
2585
2581
|
expectedContentHash: z.string().regex(/^[a-f0-9]{64}$/),
|
|
2586
2582
|
sourceReviews: z.array(z.object({
|
|
2587
2583
|
source: z.enum(["conversation", "planner-entities", "working-tree", "verification-runtime", "peer-agent-output"]),
|
|
2588
2584
|
detail: z.string().min(12),
|
|
2589
|
-
})),
|
|
2590
|
-
omissionsFound: z.array(z.string().min(1)),
|
|
2585
|
+
})).optional().describe("Optional legacy evidence; omitted for compact handoffs."),
|
|
2586
|
+
omissionsFound: z.array(z.string().min(1)).optional().describe("Optional read-back gaps; omit when the persisted capsule is complete."),
|
|
2591
2587
|
},
|
|
2592
2588
|
}, async ({ phaseRef, expectedContentHash, sourceReviews, omissionsFound }) => {
|
|
2593
2589
|
const st = await requireStore();
|
|
@@ -2595,7 +2591,11 @@ server.registerTool("planner-handoff-verify", {
|
|
|
2595
2591
|
if (!r.ok)
|
|
2596
2592
|
return text(`❌ ${r.error}`, { resumeReady: false });
|
|
2597
2593
|
try {
|
|
2598
|
-
const result = await st.verifyPhaseHandoffReadBack(r.phase.id, {
|
|
2594
|
+
const result = await st.verifyPhaseHandoffReadBack(r.phase.id, {
|
|
2595
|
+
expectedContentHash,
|
|
2596
|
+
...(sourceReviews ? { sourceReviews } : {}),
|
|
2597
|
+
...(omissionsFound ? { omissionsFound } : {}),
|
|
2598
|
+
});
|
|
2599
2599
|
await st.writeGenerated();
|
|
2600
2600
|
return text(`✅ Handoff on ${r.compositeRef} is resume-ready after persisted read-back and source reconciliation.`, {
|
|
2601
2601
|
phaseRef: r.compositeRef,
|
|
@@ -2881,7 +2881,7 @@ server.registerTool("planner-idea-promotion-finalize", {
|
|
|
2881
2881
|
return text(`Idea promoted: ${formatIdeaRef(promoted.number)} → ${promoted.promotion.targetRef}`, { idea: promoted, promoted: true, targetRef: promoted.promotion.targetRef });
|
|
2882
2882
|
});
|
|
2883
2883
|
server.registerTool("planner-handoff-write", {
|
|
2884
|
-
description: "Persist a reconciled handoff candidate with durable context synchronization
|
|
2884
|
+
description: "Persist a compact reconciled handoff candidate with durable context synchronization. The result always has resumeReady=false until a separate planner-handoff-show read-back and planner-handoff-verify succeeds. Run planner-handoff-prepare first; provide only resume-critical context and link optional extended detail from .planner/docs/ Markdown.",
|
|
2885
2885
|
inputSchema: {
|
|
2886
2886
|
phaseRef: z.string().min(1).describe("Exact confirmed phase ref: P00x | P00x(F00x) | UUID | title."),
|
|
2887
2887
|
title: z.string().min(3).optional().describe("Meaningful handoff title summarizing the work."),
|
|
@@ -2897,7 +2897,7 @@ server.registerTool("planner-handoff-write", {
|
|
|
2897
2897
|
status: z.enum(["captured", "not-applicable"]),
|
|
2898
2898
|
detail: z.string().min(1),
|
|
2899
2899
|
})),
|
|
2900
|
-
}).optional().describe("
|
|
2900
|
+
}).optional().describe("Optional legacy completeness evidence. Compact handoffs omit this duplicate prose."),
|
|
2901
2901
|
coldStartInventory: z.object({
|
|
2902
2902
|
version: z.literal(HANDOFF_COLD_START_INVENTORY_VERSION),
|
|
2903
2903
|
sourceReviews: z.array(z.object({ source: z.string().min(1), detail: z.string().min(1) })),
|
|
@@ -2906,7 +2906,7 @@ server.registerTool("planner-handoff-write", {
|
|
|
2906
2906
|
items: z.array(z.string().min(1)),
|
|
2907
2907
|
notApplicableReason: z.string().min(1).optional().describe("Optional explanation only; every category still requires a concrete item, using an explicit verified-negative statement when nothing exists."),
|
|
2908
2908
|
})),
|
|
2909
|
-
}).optional().describe("
|
|
2909
|
+
}).optional().describe("Optional legacy cold-start evidence. Compact handoffs omit this duplicate prose."),
|
|
2910
2910
|
supportingDocuments: z.array(z.object({
|
|
2911
2911
|
path: z.string().min(1).describe("Committed Markdown path under .planner/docs/."),
|
|
2912
2912
|
description: z.string().min(1).describe("What the document contains and why the next agent needs it."),
|
|
@@ -2993,7 +2993,7 @@ server.registerTool("planner-handoff-write", {
|
|
|
2993
2993
|
},
|
|
2994
2994
|
});
|
|
2995
2995
|
await st.writeGenerated();
|
|
2996
|
-
return text(`⚠️ Handoff candidate persisted on ${r.compositeRef}, but it is NOT resume-ready yet. Required next action: call planner-handoff-show ${r.compositeRef}, read the
|
|
2996
|
+
return text(`⚠️ Handoff candidate persisted on ${r.compositeRef}, but it is NOT resume-ready yet. Required next action: call planner-handoff-show ${r.compositeRef}, read the persisted compact capsule, then call planner-handoff-verify with the returned contentHash. Rewrite only if resume-critical context is missing.`, {
|
|
2997
2997
|
phaseRef: r.compositeRef,
|
|
2998
2998
|
phaseId: r.phase.id,
|
|
2999
2999
|
updatedTaskIds: result.updatedTaskIds,
|
|
@@ -3004,8 +3004,7 @@ server.registerTool("planner-handoff-write", {
|
|
|
3004
3004
|
verificationRequired: true,
|
|
3005
3005
|
nextActions: [
|
|
3006
3006
|
`Call planner-handoff-show ${r.compositeRef} and read the entire persisted body.`,
|
|
3007
|
-
"
|
|
3008
|
-
"If any omission exists, run planner-handoff-prepare and planner-handoff-write again; otherwise call planner-handoff-verify with the shown contentHash.",
|
|
3007
|
+
"Call planner-handoff-verify with the shown contentHash; legacy sourceReviews and omissionsFound are optional because the planner derives omitted evidence from persisted state.",
|
|
3009
3008
|
],
|
|
3010
3009
|
});
|
|
3011
3010
|
}
|
|
@@ -3017,7 +3016,7 @@ server.registerTool("planner-handoff-write", {
|
|
|
3017
3016
|
}
|
|
3018
3017
|
});
|
|
3019
3018
|
server.registerTool("planner-handoff-prepare", {
|
|
3020
|
-
description: "Identify or
|
|
3019
|
+
description: "Identify or prepare the exact handoff target. With a confirmed phaseRef, returns a compact resume scaffold, bounded priority-ordered phase work map, current token, missing task evidence, and inline budget. Reread the canonical phase and relevant sibling tasks before proposing work.",
|
|
3021
3020
|
inputSchema: { phaseRef: z.string().min(1).optional() },
|
|
3022
3021
|
}, async ({ phaseRef }) => {
|
|
3023
3022
|
if (!phaseRef)
|
|
@@ -3032,9 +3031,10 @@ server.registerTool("planner-handoff-prepare", {
|
|
|
3032
3031
|
return text(`❌ ${r.error}`);
|
|
3033
3032
|
try {
|
|
3034
3033
|
const audit = await st.preparePhaseHandoff(r.phase.id);
|
|
3034
|
+
const { completenessCategories: _completenessCategories, coldStartSourceReviews: _coldStartSourceReviews, coldStartInventoryCategories: _coldStartInventoryCategories, ...compactAudit } = audit;
|
|
3035
3035
|
const missing = audit.missingCompletionTasks.map((task) => `- T${String(task.number).padStart(3, "0")} — ${task.title}`).join("\n") || "- None";
|
|
3036
3036
|
return text([
|
|
3037
|
-
`Handoff preparation
|
|
3037
|
+
`Handoff preparation for ${r.compositeRef}`,
|
|
3038
3038
|
`Base handoffUpdatedAt: ${audit.handoffUpdatedAt || "(empty)"}`,
|
|
3039
3039
|
"Required human inputs before drafting:",
|
|
3040
3040
|
...audit.requiredHumanInputs.map((input) => `- ${input.id} — ${input.description}`),
|
|
@@ -3045,18 +3045,18 @@ server.registerTool("planner-handoff-prepare", {
|
|
|
3045
3045
|
"Done tasks missing durable completion/verification evidence:",
|
|
3046
3046
|
missing,
|
|
3047
3047
|
"",
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
"",
|
|
3051
|
-
`
|
|
3052
|
-
...audit.coldStartSourceReviews.map((entry) => `- ${entry.id} — ${entry.label}`),
|
|
3053
|
-
"Required cold-start inventory — every category needs a concrete item (use an explicit verified-negative statement when nothing exists), and every item must appear verbatim in the handoff or a validated supporting document:",
|
|
3054
|
-
...audit.coldStartInventoryCategories.map((entry) => `- ${entry.id} — ${entry.label}`),
|
|
3055
|
-
`Maximum canonical inline content: ${audit.maxContentChars} characters. Link extended material from .planner/docs/.`,
|
|
3048
|
+
"Compact handoff contract: include only the exact focus/resume point, current or partial state, constraints, blockers, decisions, verification, and ordered next actions needed by the next agent.",
|
|
3049
|
+
"No Markdown heading is mandatory: concise free-form resume prose is accepted. Use headings only when they make the capsule clearer.",
|
|
3050
|
+
"Completeness audit and cold-start evidence are planner-owned metadata; do not copy their categories or source reviews into Markdown.",
|
|
3051
|
+
`Inline target: ${audit.targetContentChars} characters; absolute compatibility ceiling: ${audit.maxContentChars}. Extended detail is externalized automatically when needed.`,
|
|
3056
3052
|
"",
|
|
3057
3053
|
"Existing active handoff (reconcile all still-relevant content):",
|
|
3058
3054
|
audit.handoff.trim() || "(none)",
|
|
3059
|
-
].join("\n"), {
|
|
3055
|
+
].join("\n"), {
|
|
3056
|
+
phaseRef: r.compositeRef,
|
|
3057
|
+
...compactAudit,
|
|
3058
|
+
evidenceContract: "Planner-owned completeness and cold-start evidence is derived from persisted state; no category inventory is required from the agent.",
|
|
3059
|
+
});
|
|
3060
3060
|
}
|
|
3061
3061
|
catch (error) {
|
|
3062
3062
|
const message = error instanceof Error ? error.message : String(error);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-plan/mcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.29",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "MCP server for Agent Plan, exposing planner-* tools over stdio.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@modelcontextprotocol/sdk": "^1.17.0",
|
|
45
45
|
"zod": "^3.24.0",
|
|
46
|
-
"@agent-plan/core": "0.2.
|
|
47
|
-
"@agent-plan/server": "0.2.
|
|
46
|
+
"@agent-plan/core": "0.2.29",
|
|
47
|
+
"@agent-plan/server": "0.2.29"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"build": "tsc -p tsconfig.json",
|