@sage-protocol/cli 0.3.2 → 0.3.3
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.
|
@@ -593,6 +593,72 @@ Note: This tool does NOT sign transactions. It prepares everything so you can ex
|
|
|
593
593
|
required: ['manifest']
|
|
594
594
|
}
|
|
595
595
|
},
|
|
596
|
+
{
|
|
597
|
+
name: 'list_templates',
|
|
598
|
+
description: 'List available prompt templates for quick creation.',
|
|
599
|
+
inputSchema: {
|
|
600
|
+
type: 'object',
|
|
601
|
+
properties: {
|
|
602
|
+
category: { type: 'string', description: 'Optional category filter (design, development, analysis, etc.)' },
|
|
603
|
+
search: { type: 'string', description: 'Optional text search over template key/name/description' }
|
|
604
|
+
},
|
|
605
|
+
required: []
|
|
606
|
+
}
|
|
607
|
+
},
|
|
608
|
+
{
|
|
609
|
+
name: 'get_template',
|
|
610
|
+
description: 'Get detailed information about a specific prompt template.',
|
|
611
|
+
inputSchema: {
|
|
612
|
+
type: 'object',
|
|
613
|
+
properties: {
|
|
614
|
+
key: { type: 'string', description: 'Template key' }
|
|
615
|
+
},
|
|
616
|
+
required: ['key']
|
|
617
|
+
}
|
|
618
|
+
},
|
|
619
|
+
{
|
|
620
|
+
name: 'create_from_template',
|
|
621
|
+
description: 'Create a new prompt from a template and save it into a local library via quick_create_prompt.',
|
|
622
|
+
inputSchema: {
|
|
623
|
+
type: 'object',
|
|
624
|
+
properties: {
|
|
625
|
+
template: { type: 'string', description: 'Template key' },
|
|
626
|
+
customize: {
|
|
627
|
+
type: 'object',
|
|
628
|
+
description: 'Values to substitute into the template variables'
|
|
629
|
+
},
|
|
630
|
+
library: {
|
|
631
|
+
type: 'string',
|
|
632
|
+
description: 'Target library name or CID (optional, default: My Library)'
|
|
633
|
+
},
|
|
634
|
+
name: {
|
|
635
|
+
type: 'string',
|
|
636
|
+
description: 'Override prompt display name (optional)'
|
|
637
|
+
}
|
|
638
|
+
},
|
|
639
|
+
required: ['template', 'customize']
|
|
640
|
+
}
|
|
641
|
+
},
|
|
642
|
+
{
|
|
643
|
+
name: 'analyze_dependencies',
|
|
644
|
+
description: 'Analyze variable usage across all prompts in a pinned library.',
|
|
645
|
+
inputSchema: {
|
|
646
|
+
type: 'object',
|
|
647
|
+
properties: {
|
|
648
|
+
library: {
|
|
649
|
+
type: 'string',
|
|
650
|
+
description: 'Pinned library name or CID'
|
|
651
|
+
},
|
|
652
|
+
analysis_type: {
|
|
653
|
+
type: 'string',
|
|
654
|
+
enum: ['variables', 'all'],
|
|
655
|
+
description: 'Type of analysis (v1 supports variables)',
|
|
656
|
+
default: 'variables'
|
|
657
|
+
}
|
|
658
|
+
},
|
|
659
|
+
required: ['library']
|
|
660
|
+
}
|
|
661
|
+
},
|
|
596
662
|
{
|
|
597
663
|
name: 'update_library_metadata',
|
|
598
664
|
description: 'Update library-level metadata (name/description/tags) and optionally propagate tags to prompts.',
|
|
@@ -670,74 +736,33 @@ Note: This tool does NOT sign transactions. It prepares everything so you can ex
|
|
|
670
736
|
}
|
|
671
737
|
},
|
|
672
738
|
{
|
|
673
|
-
name: '
|
|
674
|
-
description: '
|
|
675
|
-
inputSchema: {
|
|
676
|
-
type: 'object',
|
|
677
|
-
properties: {
|
|
678
|
-
category: { type: 'string', description: 'Optional category filter (design, development, analysis, etc.)' },
|
|
679
|
-
search: { type: 'string', description: 'Optional text search over template key/name/description' }
|
|
680
|
-
},
|
|
681
|
-
required: []
|
|
682
|
-
}
|
|
683
|
-
},
|
|
684
|
-
{
|
|
685
|
-
name: 'get_template',
|
|
686
|
-
description: 'Get detailed information about a specific prompt template.',
|
|
687
|
-
inputSchema: {
|
|
688
|
-
type: 'object',
|
|
689
|
-
properties: {
|
|
690
|
-
key: { type: 'string', description: 'Template key' }
|
|
691
|
-
},
|
|
692
|
-
required: ['key']
|
|
693
|
-
}
|
|
694
|
-
},
|
|
695
|
-
{
|
|
696
|
-
name: 'create_from_template',
|
|
697
|
-
description: 'Create a new prompt from a template and save it into a local library via quick_create_prompt.',
|
|
739
|
+
name: 'suggest_subdaos_for_library',
|
|
740
|
+
description: 'Suggest SubDAOs that might be a good fit for publishing a given local library, and provide CLI workflows for creating your own SubDAO and pushing the library.',
|
|
698
741
|
inputSchema: {
|
|
699
742
|
type: 'object',
|
|
700
743
|
properties: {
|
|
701
|
-
template: { type: 'string', description: 'Template key' },
|
|
702
|
-
customize: {
|
|
703
|
-
type: 'object',
|
|
704
|
-
description: 'Values to substitute into the template variables'
|
|
705
|
-
},
|
|
706
744
|
library: {
|
|
707
745
|
type: 'string',
|
|
708
|
-
description: '
|
|
746
|
+
description: 'Local pinned library name or CID'
|
|
709
747
|
},
|
|
710
|
-
|
|
711
|
-
type: '
|
|
712
|
-
description: '
|
|
713
|
-
|
|
714
|
-
},
|
|
715
|
-
required: ['template', 'customize']
|
|
716
|
-
}
|
|
717
|
-
},
|
|
718
|
-
{
|
|
719
|
-
name: 'analyze_dependencies',
|
|
720
|
-
description: 'Analyze variable usage across all prompts in a pinned library.',
|
|
721
|
-
inputSchema: {
|
|
722
|
-
type: 'object',
|
|
723
|
-
properties: {
|
|
724
|
-
library: {
|
|
725
|
-
type: 'string',
|
|
726
|
-
description: 'Pinned library name or CID'
|
|
748
|
+
limit: {
|
|
749
|
+
type: 'number',
|
|
750
|
+
description: 'Max SubDAOs to return (default 5)',
|
|
751
|
+
default: 5
|
|
727
752
|
},
|
|
728
|
-
|
|
753
|
+
mode_filter: {
|
|
729
754
|
type: 'string',
|
|
730
|
-
enum: ['
|
|
731
|
-
description: '
|
|
732
|
-
default: '
|
|
755
|
+
enum: ['any', 'creator', 'squad', 'community'],
|
|
756
|
+
description: 'Optional governance mode preference',
|
|
757
|
+
default: 'any'
|
|
733
758
|
}
|
|
734
759
|
},
|
|
735
760
|
required: ['library']
|
|
736
761
|
}
|
|
737
762
|
},
|
|
738
763
|
{
|
|
739
|
-
name: '
|
|
740
|
-
description: '
|
|
764
|
+
name: 'generate_publishing_commands',
|
|
765
|
+
description: 'Generate ready-to-run CLI commands for validating, uploading, and proposing a library manifest on-chain.',
|
|
741
766
|
inputSchema: {
|
|
742
767
|
type: 'object',
|
|
743
768
|
properties: {
|
|
@@ -745,16 +770,10 @@ Note: This tool does NOT sign transactions. It prepares everything so you can ex
|
|
|
745
770
|
type: 'string',
|
|
746
771
|
description: 'Local pinned library name or CID'
|
|
747
772
|
},
|
|
748
|
-
|
|
749
|
-
type: 'number',
|
|
750
|
-
description: 'Max SubDAOs to return (default 5)',
|
|
751
|
-
default: 5
|
|
752
|
-
},
|
|
753
|
-
mode_filter: {
|
|
773
|
+
target: {
|
|
754
774
|
type: 'string',
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
default: 'any'
|
|
775
|
+
description: 'Target SubDAO address or "auto" to pick a likely candidate',
|
|
776
|
+
default: 'auto'
|
|
758
777
|
}
|
|
759
778
|
},
|
|
760
779
|
required: ['library']
|
|
@@ -1015,6 +1034,7 @@ Note: This tool does NOT sign transactions. It prepares everything so you can ex
|
|
|
1015
1034
|
'tool:create_from_template': (params) => this.createPromptFromTemplate(params),
|
|
1016
1035
|
'tool:analyze_dependencies': (params) => this.analyzeDependencies(params),
|
|
1017
1036
|
'tool:suggest_subdaos_for_library': (params) => this.suggestSubdaosForLibrary(params),
|
|
1037
|
+
'tool:generate_publishing_commands': (params) => this.generatePublishingCommands(params),
|
|
1018
1038
|
});
|
|
1019
1039
|
|
|
1020
1040
|
const toolHandlers = {
|
|
@@ -1048,6 +1068,50 @@ Note: This tool does NOT sign transactions. It prepares everything so you can ex
|
|
|
1048
1068
|
return this.libraryBindingsManager.buildBindingsForSubdao(subdaoAddr);
|
|
1049
1069
|
}
|
|
1050
1070
|
|
|
1071
|
+
async _enrichSubdaos(subdaos) {
|
|
1072
|
+
return Promise.all(subdaos.map(async (s) => {
|
|
1073
|
+
const derivedTags = new Set();
|
|
1074
|
+
let libraryCount = 0;
|
|
1075
|
+
|
|
1076
|
+
try {
|
|
1077
|
+
const libraries = await this.libraryBindingsManager.buildBindingsForSubdao(s.address);
|
|
1078
|
+
libraryCount = libraries.length;
|
|
1079
|
+
|
|
1080
|
+
// Check up to 3 libraries per SubDAO to gather context
|
|
1081
|
+
for (const lib of libraries.slice(0, 3)) {
|
|
1082
|
+
try {
|
|
1083
|
+
const registry = new ethers.Contract(lib.registry, this.libraryRegistryAbi, this.provider);
|
|
1084
|
+
const count = await registry.getManifestCIDCount();
|
|
1085
|
+
if (count > 0) {
|
|
1086
|
+
const cid = await registry.getManifestCID(count - 1n);
|
|
1087
|
+
if (cid) {
|
|
1088
|
+
const { manifest } = await this.manifestFetcher.fetchManifest(cid);
|
|
1089
|
+
if (manifest?.library?.tags) {
|
|
1090
|
+
manifest.library.tags.forEach(t => derivedTags.add(String(t).toLowerCase().trim()));
|
|
1091
|
+
}
|
|
1092
|
+
if (manifest?.prompts) {
|
|
1093
|
+
manifest.prompts.forEach(p => {
|
|
1094
|
+
if (p.tags) p.tags.forEach(t => derivedTags.add(String(t).toLowerCase().trim()));
|
|
1095
|
+
});
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
} catch (e) {
|
|
1100
|
+
// ignore individual library fetch errors
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
} catch (e) {
|
|
1104
|
+
// ignore binding fetch errors
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
return {
|
|
1108
|
+
...s,
|
|
1109
|
+
derivedTags: Array.from(derivedTags),
|
|
1110
|
+
libraryCount
|
|
1111
|
+
};
|
|
1112
|
+
}));
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1051
1115
|
|
|
1052
1116
|
// ───────────────────────────── MCP Prompts helpers ─────────────────────────────
|
|
1053
1117
|
getDiscoveryClient() {
|
|
@@ -1671,7 +1735,8 @@ Note: This tool does NOT sign transactions. It prepares everything so you can ex
|
|
|
1671
1735
|
}
|
|
1672
1736
|
const libTags = Array.from(tagsSet);
|
|
1673
1737
|
|
|
1674
|
-
|
|
1738
|
+
// Fetch candidates - limit to 20 to allow for deeper analysis
|
|
1739
|
+
const subdaos = await this.getSubDAOList({ limit: 20 });
|
|
1675
1740
|
if (!subdaos || !subdaos.length) {
|
|
1676
1741
|
const fallbackText =
|
|
1677
1742
|
'No SubDAOs discovered from subgraph/factory.\n\n' +
|
|
@@ -1686,9 +1751,12 @@ Note: This tool does NOT sign transactions. It prepares everything so you can ex
|
|
|
1686
1751
|
return { content: [{ type: 'text', text: fallbackText }] };
|
|
1687
1752
|
}
|
|
1688
1753
|
|
|
1754
|
+
// Enrich SubDAOs with tags from their attached libraries
|
|
1755
|
+
const enrichedSubdaos = await this._enrichSubdaos(subdaos);
|
|
1756
|
+
|
|
1689
1757
|
const modeFilter = mode_filter || 'any';
|
|
1690
1758
|
const scored = [];
|
|
1691
|
-
for (const s of
|
|
1759
|
+
for (const s of enrichedSubdaos) {
|
|
1692
1760
|
const name = String(s.name || '').toLowerCase();
|
|
1693
1761
|
const desc = String(s.description || '').toLowerCase();
|
|
1694
1762
|
const tokens = new Set(
|
|
@@ -1697,6 +1765,10 @@ Note: This tool does NOT sign transactions. It prepares everything so you can ex
|
|
|
1697
1765
|
.map((t) => t.toLowerCase().trim())
|
|
1698
1766
|
.filter(Boolean),
|
|
1699
1767
|
);
|
|
1768
|
+
|
|
1769
|
+
// Add derived tags to tokens for matching
|
|
1770
|
+
s.derivedTags.forEach(t => tokens.add(t));
|
|
1771
|
+
|
|
1700
1772
|
let matchCount = 0;
|
|
1701
1773
|
const matchedTags = [];
|
|
1702
1774
|
for (const tag of libTags) {
|
|
@@ -1710,20 +1782,22 @@ Note: This tool does NOT sign transactions. It prepares everything so you can ex
|
|
|
1710
1782
|
// Mode-specific filtering can be added in a future iteration.
|
|
1711
1783
|
}
|
|
1712
1784
|
|
|
1713
|
-
|
|
1714
|
-
const fitScore = matchCount + libraryCount * 0.1;
|
|
1785
|
+
// Boost score if we matched on derived tags (stronger signal than just name)
|
|
1786
|
+
const fitScore = matchCount + s.libraryCount * 0.1;
|
|
1715
1787
|
scored.push({
|
|
1716
1788
|
address: s.address,
|
|
1717
1789
|
name: s.name || `SubDAO-${String(s.address).slice(-6)}`,
|
|
1718
1790
|
description: s.description || '',
|
|
1719
1791
|
registryAddress: s.registryAddress || null,
|
|
1720
1792
|
defaultLibraryId: s.defaultLibraryId || 'main',
|
|
1721
|
-
libraryCount,
|
|
1793
|
+
libraryCount: s.libraryCount,
|
|
1722
1794
|
matchedTags,
|
|
1723
1795
|
fitScore,
|
|
1796
|
+
derivedTags: s.derivedTags // Include for debugging/info
|
|
1724
1797
|
});
|
|
1725
1798
|
}
|
|
1726
1799
|
|
|
1800
|
+
const anyTagMatches = scored.some((s) => (s.matchedTags || []).length > 0);
|
|
1727
1801
|
scored.sort((a, b) => (b.fitScore || 0) - (a.fitScore || 0));
|
|
1728
1802
|
const top = scored.slice(0, limit);
|
|
1729
1803
|
|
|
@@ -1731,14 +1805,32 @@ Note: This tool does NOT sign transactions. It prepares everything so you can ex
|
|
|
1731
1805
|
lines.push(`🎯 Suggested SubDAOs for library "${libName}"`);
|
|
1732
1806
|
lines.push('');
|
|
1733
1807
|
|
|
1734
|
-
if (!top.length || !libTags.length) {
|
|
1808
|
+
if (!top.length || !libTags.length || !anyTagMatches) {
|
|
1735
1809
|
lines.push('No strong SubDAO matches found based on tags and names.');
|
|
1810
|
+
if (top.length) {
|
|
1811
|
+
lines.push('');
|
|
1812
|
+
lines.push('Here are some recent SubDAOs you may consider, but scoring is neutral:');
|
|
1813
|
+
lines.push('');
|
|
1814
|
+
top.forEach((s, idx) => {
|
|
1815
|
+
lines.push(`${idx + 1}. ${s.name} (${s.address})`);
|
|
1816
|
+
lines.push(` • Libraries: ${s.libraryCount}`);
|
|
1817
|
+
if (s.description) {
|
|
1818
|
+
lines.push(` • Description: ${s.description}`);
|
|
1819
|
+
}
|
|
1820
|
+
lines.push('');
|
|
1821
|
+
});
|
|
1822
|
+
}
|
|
1736
1823
|
} else {
|
|
1737
1824
|
top.forEach((s, idx) => {
|
|
1738
1825
|
lines.push(`${idx + 1}. ${s.name} (${s.address})`);
|
|
1739
1826
|
if (s.matchedTags.length) {
|
|
1740
1827
|
lines.push(` • Tag overlap: ${s.matchedTags.join(', ')}`);
|
|
1741
1828
|
}
|
|
1829
|
+
if (s.derivedTags.length > 0) {
|
|
1830
|
+
// Show a few derived tags to explain why it matched
|
|
1831
|
+
const displayTags = s.derivedTags.slice(0, 5).join(', ');
|
|
1832
|
+
lines.push(` • Context: ${displayTags}${s.derivedTags.length > 5 ? '...' : ''}`);
|
|
1833
|
+
}
|
|
1742
1834
|
lines.push(` • Libraries: ${s.libraryCount}`);
|
|
1743
1835
|
if (s.description) {
|
|
1744
1836
|
lines.push(` • Description: ${s.description}`);
|
|
@@ -1814,6 +1906,178 @@ Note: This tool does NOT sign transactions. It prepares everything so you can ex
|
|
|
1814
1906
|
}
|
|
1815
1907
|
}
|
|
1816
1908
|
|
|
1909
|
+
async generatePublishingCommands({ library, target = 'auto' } = {}) {
|
|
1910
|
+
try {
|
|
1911
|
+
const lm = this.libraryManager;
|
|
1912
|
+
const pinned = lm.listPinned() || [];
|
|
1913
|
+
const id = String(library || '').trim();
|
|
1914
|
+
if (!id) {
|
|
1915
|
+
return { content: [{ type: 'text', text: 'Error: library parameter is required' }] };
|
|
1916
|
+
}
|
|
1917
|
+
|
|
1918
|
+
let selected = null;
|
|
1919
|
+
let row = pinned.find((r) => r.cid === id);
|
|
1920
|
+
if (row) {
|
|
1921
|
+
selected = lm.loadPinned(row.cid);
|
|
1922
|
+
selected.row = row;
|
|
1923
|
+
} else {
|
|
1924
|
+
const lower = id.toLowerCase();
|
|
1925
|
+
const matches = [];
|
|
1926
|
+
for (const r of pinned) {
|
|
1927
|
+
try {
|
|
1928
|
+
const loaded = lm.loadPinned(r.cid);
|
|
1929
|
+
const libName = String(loaded.manifest?.library?.name || r.name || '').toLowerCase();
|
|
1930
|
+
if (libName === lower) {
|
|
1931
|
+
matches.push({ row: r, ...loaded });
|
|
1932
|
+
}
|
|
1933
|
+
} catch (_) {
|
|
1934
|
+
// ignore corrupt
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1937
|
+
if (matches.length === 0) {
|
|
1938
|
+
return {
|
|
1939
|
+
content: [
|
|
1940
|
+
{
|
|
1941
|
+
type: 'text',
|
|
1942
|
+
text: `No pinned library found matching "${library}". Use list_libraries(source="local") to see available libraries.`,
|
|
1943
|
+
},
|
|
1944
|
+
],
|
|
1945
|
+
};
|
|
1946
|
+
}
|
|
1947
|
+
if (matches.length > 1) {
|
|
1948
|
+
const lines = matches.map(
|
|
1949
|
+
(m) => `- ${m.row.cid} (${m.manifest?.library?.name || m.row.name || 'unnamed'})`,
|
|
1950
|
+
);
|
|
1951
|
+
return {
|
|
1952
|
+
content: [
|
|
1953
|
+
{
|
|
1954
|
+
type: 'text',
|
|
1955
|
+
text:
|
|
1956
|
+
`Ambiguous library match for "${library}". Candidates:\n` +
|
|
1957
|
+
`${lines.join('\n')}\n\nPass an explicit CID to disambiguate.`,
|
|
1958
|
+
},
|
|
1959
|
+
],
|
|
1960
|
+
};
|
|
1961
|
+
}
|
|
1962
|
+
selected = matches[0];
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1965
|
+
const manifest = selected.manifest;
|
|
1966
|
+
const manifestPath = selected.path;
|
|
1967
|
+
const libName = manifest.library?.name || selected.row?.name || library;
|
|
1968
|
+
const libDescription = manifest.library?.description || '';
|
|
1969
|
+
|
|
1970
|
+
let chosenSubdao = '';
|
|
1971
|
+
let subdaoReason = '';
|
|
1972
|
+
if (target && target !== 'auto') {
|
|
1973
|
+
chosenSubdao = target;
|
|
1974
|
+
subdaoReason = 'Target provided explicitly.';
|
|
1975
|
+
} else {
|
|
1976
|
+
const tagsSet = new Set(
|
|
1977
|
+
(manifest.library?.tags || []).map((t) => String(t).toLowerCase().trim()).filter(Boolean),
|
|
1978
|
+
);
|
|
1979
|
+
for (const p of manifest.prompts || []) {
|
|
1980
|
+
if (!p || !Array.isArray(p.tags)) continue;
|
|
1981
|
+
for (const t of p.tags) {
|
|
1982
|
+
const v = String(t).toLowerCase().trim();
|
|
1983
|
+
if (v) tagsSet.add(v);
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
const libTags = Array.from(tagsSet);
|
|
1987
|
+
|
|
1988
|
+
const subdaos = await this.getSubDAOList({ limit: 20 });
|
|
1989
|
+
if (subdaos && subdaos.length && libTags.length) {
|
|
1990
|
+
const enrichedSubdaos = await this._enrichSubdaos(subdaos);
|
|
1991
|
+
const scored = enrichedSubdaos.map((s) => {
|
|
1992
|
+
const name = String(s.name || '').toLowerCase();
|
|
1993
|
+
const desc = String(s.description || '').toLowerCase();
|
|
1994
|
+
const tokens = new Set(
|
|
1995
|
+
(name + ' ' + desc)
|
|
1996
|
+
.split(/[^a-z0-9]+/i)
|
|
1997
|
+
.map((t) => t.toLowerCase().trim())
|
|
1998
|
+
.filter(Boolean),
|
|
1999
|
+
);
|
|
2000
|
+
s.derivedTags.forEach(t => tokens.add(t));
|
|
2001
|
+
|
|
2002
|
+
let matchCount = 0;
|
|
2003
|
+
for (const tag of libTags) {
|
|
2004
|
+
if (tokens.has(tag)) matchCount += 1;
|
|
2005
|
+
}
|
|
2006
|
+
const fitScore = matchCount + s.libraryCount * 0.1;
|
|
2007
|
+
return { subdao: s, fitScore, matchCount, libraryCount: s.libraryCount };
|
|
2008
|
+
});
|
|
2009
|
+
// Only auto-pick if there is at least one SubDAO with tag matches
|
|
2010
|
+
const withMatches = scored.filter((s) => s.matchCount > 0);
|
|
2011
|
+
if (withMatches.length) {
|
|
2012
|
+
withMatches.sort((a, b) => (b.fitScore || 0) - (a.fitScore || 0));
|
|
2013
|
+
const top = withMatches[0];
|
|
2014
|
+
if (top && top.subdao) {
|
|
2015
|
+
chosenSubdao = top.subdao.address;
|
|
2016
|
+
subdaoReason = `Auto-selected based on tag/name overlap and existing libraries (${top.matchCount} matching tag(s)).`;
|
|
2017
|
+
}
|
|
2018
|
+
}
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
2021
|
+
|
|
2022
|
+
const manifestPathHint = manifestPath || `~/.sage/libraries/${selected.row.cid}.json`;
|
|
2023
|
+
const inspectCmd = `sage library cache view ${selected.row.cid}`;
|
|
2024
|
+
const pushCmd = chosenSubdao
|
|
2025
|
+
? `sage library push ${manifestPathHint} --subdao ${chosenSubdao} --pin --wait`
|
|
2026
|
+
: `sage library push ${manifestPathHint} --subdao 0xYourSubDAO --pin --wait`;
|
|
2027
|
+
const proposalsCmd = chosenSubdao
|
|
2028
|
+
? `sage governance proposals --subdao ${chosenSubdao}`
|
|
2029
|
+
: 'sage governance proposals --subdao 0xYourSubDAO';
|
|
2030
|
+
|
|
2031
|
+
const lines = [];
|
|
2032
|
+
lines.push(`📦 Publishing Guide for "${libName}"`);
|
|
2033
|
+
lines.push('');
|
|
2034
|
+
lines.push(`Manifest CID (local cache): ${selected.row.cid}`);
|
|
2035
|
+
lines.push(`Manifest path: ${manifestPathHint}`);
|
|
2036
|
+
if (chosenSubdao) {
|
|
2037
|
+
lines.push(`Target SubDAO: ${chosenSubdao}`);
|
|
2038
|
+
} else {
|
|
2039
|
+
lines.push('Target SubDAO: (not auto-detected; you must choose an address)');
|
|
2040
|
+
}
|
|
2041
|
+
if (subdaoReason) {
|
|
2042
|
+
lines.push(`Reason: ${subdaoReason}`);
|
|
2043
|
+
}
|
|
2044
|
+
lines.push('');
|
|
2045
|
+
lines.push('Step 1: Inspect manifest (optional)');
|
|
2046
|
+
lines.push(` ${inspectCmd}`);
|
|
2047
|
+
lines.push('');
|
|
2048
|
+
lines.push('Step 2: Upload manifest and schedule/propose update');
|
|
2049
|
+
lines.push(` ${pushCmd}`);
|
|
2050
|
+
lines.push('');
|
|
2051
|
+
lines.push('Step 3: Governance follow-up');
|
|
2052
|
+
lines.push(` ${proposalsCmd}`);
|
|
2053
|
+
|
|
2054
|
+
const payload = {
|
|
2055
|
+
library: {
|
|
2056
|
+
cid: selected.row.cid,
|
|
2057
|
+
name: libName,
|
|
2058
|
+
description: libDescription,
|
|
2059
|
+
},
|
|
2060
|
+
targetSubdao: chosenSubdao || null,
|
|
2061
|
+
steps: [
|
|
2062
|
+
{ step: 1, title: 'Inspect manifest', command: inspectCmd },
|
|
2063
|
+
{ step: 2, title: 'Upload & propose', command: pushCmd },
|
|
2064
|
+
],
|
|
2065
|
+
extra: {
|
|
2066
|
+
governanceCommands: [proposalsCmd],
|
|
2067
|
+
},
|
|
2068
|
+
};
|
|
2069
|
+
|
|
2070
|
+
return {
|
|
2071
|
+
content: [
|
|
2072
|
+
{ type: 'text', text: lines.join('\n') },
|
|
2073
|
+
{ type: 'text', text: '```json\n' + JSON.stringify(payload, null, 2) + '\n```' },
|
|
2074
|
+
],
|
|
2075
|
+
};
|
|
2076
|
+
} catch (error) {
|
|
2077
|
+
return { content: [{ type: 'text', text: `Error generating publishing commands: ${error.message}` }] };
|
|
2078
|
+
}
|
|
2079
|
+
}
|
|
2080
|
+
|
|
1817
2081
|
async improvePrompt({ key, library = '', pass = 'single', focus = 'all' } = {}) {
|
|
1818
2082
|
try {
|
|
1819
2083
|
if (!key) {
|
|
@@ -2088,8 +2352,9 @@ Note: This tool does NOT sign transactions. It prepares everything so you can ex
|
|
|
2088
2352
|
publish: `
|
|
2089
2353
|
**Publishing Prompts**
|
|
2090
2354
|
1. Ensure your prompts are ready in a local library.
|
|
2091
|
-
2. Use \`publish_manifest_flow\` to
|
|
2092
|
-
3.
|
|
2355
|
+
2. Use \`publish_manifest_flow\` to validate and build a governance payload.
|
|
2356
|
+
3. When ready, use \`generate_publishing_commands(library=\"...\")\` to get copy-paste CLI commands for \`sage library push\` and proposal follow-up.
|
|
2357
|
+
4. This makes them available on-chain for others to discover.
|
|
2093
2358
|
`,
|
|
2094
2359
|
versioning: `
|
|
2095
2360
|
**Versioning**
|
|
@@ -2097,6 +2362,22 @@ Note: This tool does NOT sign transactions. It prepares everything so you can ex
|
|
|
2097
2362
|
- Prompts are stored as files in \`~/.sage/libraries/prompts/\`, so you can use Git for version control.
|
|
2098
2363
|
- The \`key\` is a stable identifier used to reference the prompt; \`name\` is the human-readable display name.
|
|
2099
2364
|
- Use \`rename_prompt(key="old", newKey="new", name="New Name")\` when you truly need to change the key; otherwise, prefer updating \`name\` only.
|
|
2365
|
+
`,
|
|
2366
|
+
improve: `
|
|
2367
|
+
**Improve Prompt**
|
|
2368
|
+
- \`improve_prompt\` analyzes an existing prompt and returns advisory output only. It does not modify files.
|
|
2369
|
+
- Parameters:
|
|
2370
|
+
- \`key\`: prompt key (required)
|
|
2371
|
+
- \`library\`: optional library name or CID for disambiguation
|
|
2372
|
+
- \`pass\` or \`depth\`: "single" (default) or "deep"
|
|
2373
|
+
- \`focus\`: "variables" | "edge-cases" | "output-quality" | "reusability" | "all"
|
|
2374
|
+
|
|
2375
|
+
Behavior:
|
|
2376
|
+
- \`pass="single"\`: light structural checks + suggested improvement areas + generic interview questions.
|
|
2377
|
+
- \`pass="deep"\`: adds heuristic per-dimension scores (structure, variables, edge cases, reusability) plus richer questions.
|
|
2378
|
+
|
|
2379
|
+
Not implemented (advisory only):
|
|
2380
|
+
- There is currently **no** \`auto_apply\` or \`compare_to\` behavior. Use \`improve_prompt\` to design changes, then apply them via \`quick_iterate_prompt\` or \`bulk_update_prompts\`.
|
|
2100
2381
|
`,
|
|
2101
2382
|
manifest: `
|
|
2102
2383
|
**Manifest Structure (v2)**
|
|
@@ -73,9 +73,15 @@ function createToolArgsValidator({ zodModule } = {}) {
|
|
|
73
73
|
improve_prompt: Z.object({
|
|
74
74
|
key: Z.string().min(1).max(200),
|
|
75
75
|
library: Z.string().min(1).max(200).optional(),
|
|
76
|
-
pass: Z.enum(['single', 'deep']).optional()
|
|
76
|
+
pass: Z.enum(['single', 'deep']).optional(),
|
|
77
|
+
depth: Z.enum(['single', 'deep']).optional(),
|
|
77
78
|
focus: Z.enum(['variables', 'edge-cases', 'output-quality', 'reusability', 'all']).optional().default('all'),
|
|
78
|
-
})
|
|
79
|
+
}).transform((obj) => ({
|
|
80
|
+
key: obj.key,
|
|
81
|
+
library: obj.library,
|
|
82
|
+
pass: obj.depth || obj.pass || 'single',
|
|
83
|
+
focus: obj.focus,
|
|
84
|
+
})),
|
|
79
85
|
rename_prompt: Z.object({
|
|
80
86
|
key: Z.string().min(1).max(200),
|
|
81
87
|
newKey: Z.string().min(1).max(200).optional(),
|
|
@@ -125,6 +131,10 @@ function createToolArgsValidator({ zodModule } = {}) {
|
|
|
125
131
|
limit: Z.number().int().min(1).max(20).optional().default(5),
|
|
126
132
|
mode_filter: Z.enum(['any', 'creator', 'squad', 'community']).optional().default('any'),
|
|
127
133
|
}),
|
|
134
|
+
generate_publishing_commands: Z.object({
|
|
135
|
+
library: Z.string().min(1).max(200),
|
|
136
|
+
target: Z.string().max(200).optional().default('auto'),
|
|
137
|
+
}),
|
|
128
138
|
};
|
|
129
139
|
|
|
130
140
|
return function validate(name, args) {
|