+
+
{tool.description}
+
+ Category:
+ {tool.labels.join(', ')}
+
+
+ Input Types:
+ {tool.input_types.join(', ')}
+
+
+ Output Types:
+ {tool.output_types.join(', ')}
+
+
+ Temporal:
+ {tool.isTemporal ? 'Yes' : 'No'}
+
+
+
+
+
Parameters
+ {tool.parameters.length === 0 ? (
+
This tool requires no parameters.
+ ) : (
+
+
+
+
+ | Name |
+ Type |
+ Description |
+ Default |
+ Options |
+
+
+
+ {tool.parameters.map(param => (
+
+ |
+ {param.name}
+ |
+
+ {param.type}
+ |
+
+ {param.description}
+ |
+
+ {param.default !== undefined ? (
+ {JSON.stringify(param.default)}
+ ) : (
+ —
+ )}
+ |
+
+ {param.enum ? (
+ param.enum.join(', ')
+ ) : (
+ —
+ )}
+ |
+
+ ))}
+
+
+
+ )}
+
+
+ {tool.examples && tool.examples.length > 0 && (
+
+
Examples
+
+ {tool.examples.map((example, index) => (
+
+
+
{example.name}
+
+
+
{JSON.stringify(example.parameters, null, 2)}
+
+
+ ))}
+
+
+ )}
+
+ );
+
+ const renderExampleTab = () => (
+
+
+
Version History
+ {historyData.length > 0 && (
+
+ )}
+
+
+ {historyLoading && (
+
+ )}
+
+ {historyError && (
+
+
❌ Failed to load history: {historyError}
+
+ )}
+
+ {!historyLoading && !historyError && historyData.length === 0 && (
+
+
📝 No version history available for this tool.
+
+ )}
+
+ {!historyLoading && !historyError && historyData.length > 0 && (
+
+ {historyData.map((commit, index) => {
+ const isExpanded = expandedChanges.has(commit.commit);
+ const hasChanges = commit.changes && commit.changes.length > 0;
+
+ return (
+
+
+
+
+ {commit.commit}
+ {index === 0 && Current}
+
+ {new Date(commit.commit_date).toLocaleDateString()}
+
+ {commit.author}
+
+
+
{commit.message}
+ {hasChanges && (
+
+ )}
+
+
+ {hasChanges && isExpanded && (
+
+
Changes:
+
+ {commit.changes.map((change, changeIndex) => (
+ - {change}
+ ))}
+
+
+ )}
+
+
+ );
+ })}
+
+ )}
+
+ );
+
+ return (
+
+
+
+
+
+
+
{tool.name}
+
+
+
+
+
+
+
+
+
+
+ {activeTab === 'overview' && renderOverviewTab()}
+ {activeTab === 'example' && renderExampleTab()}
+ {activeTab === 'history' && renderHistoryTab()}
+
+
+
+ );
+}
+
+export default ToolDetail;
\ No newline at end of file
diff --git a/toolvault-frontend/src/services/bundleLoader.ts b/toolvault-frontend/src/services/bundleLoader.ts
new file mode 100644
index 0000000..03ba930
--- /dev/null
+++ b/toolvault-frontend/src/services/bundleLoader.ts
@@ -0,0 +1,110 @@
+import type { ToolBundle, ToolMetadata, ToolHistory, ToolHistoryCommit } from '../types/tools';
+
+export class BundleLoader {
+ private cache = new Map