@nordsym/apiclaw 1.3.7 → 1.3.9
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/README.md +436 -200
- package/convex/_generated/api.d.ts +4 -0
- package/convex/agents.ts +403 -0
- package/convex/directCall.ts +80 -0
- package/convex/earnProgress.ts +753 -0
- package/convex/logs.ts +17 -0
- package/convex/providerKeys.ts +82 -2
- package/convex/schema.ts +71 -2
- package/convex/workspaces.ts +84 -2
- package/dist/adapters/base.d.ts +112 -0
- package/dist/adapters/base.d.ts.map +1 -0
- package/dist/adapters/base.js +247 -0
- package/dist/adapters/base.js.map +1 -0
- package/dist/adapters/claude-desktop.d.ts +12 -0
- package/dist/adapters/claude-desktop.d.ts.map +1 -0
- package/dist/adapters/claude-desktop.js +36 -0
- package/dist/adapters/claude-desktop.js.map +1 -0
- package/dist/adapters/cline.d.ts +20 -0
- package/dist/adapters/cline.d.ts.map +1 -0
- package/dist/adapters/cline.js +77 -0
- package/dist/adapters/cline.js.map +1 -0
- package/dist/adapters/continue.d.ts +26 -0
- package/dist/adapters/continue.d.ts.map +1 -0
- package/dist/adapters/continue.js +68 -0
- package/dist/adapters/continue.js.map +1 -0
- package/dist/adapters/cursor.d.ts +12 -0
- package/dist/adapters/cursor.d.ts.map +1 -0
- package/dist/adapters/cursor.js +38 -0
- package/dist/adapters/cursor.js.map +1 -0
- package/dist/adapters/custom.d.ts +47 -0
- package/dist/adapters/custom.d.ts.map +1 -0
- package/dist/adapters/custom.js +146 -0
- package/dist/adapters/custom.js.map +1 -0
- package/dist/adapters/detect.d.ts +69 -0
- package/dist/adapters/detect.d.ts.map +1 -0
- package/dist/adapters/detect.js +158 -0
- package/dist/adapters/detect.js.map +1 -0
- package/dist/adapters/index.d.ts +21 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +23 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/windsurf.d.ts +12 -0
- package/dist/adapters/windsurf.d.ts.map +1 -0
- package/dist/adapters/windsurf.js +39 -0
- package/dist/adapters/windsurf.js.map +1 -0
- package/dist/bin.d.ts +9 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +19 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +34 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +312 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/index.d.ts +9 -0
- package/dist/cli/commands/index.d.ts.map +1 -0
- package/dist/cli/commands/index.js +9 -0
- package/dist/cli/commands/index.js.map +1 -0
- package/dist/cli/commands/mcp-install.d.ts +14 -0
- package/dist/cli/commands/mcp-install.d.ts.map +1 -0
- package/dist/cli/commands/mcp-install.js +246 -0
- package/dist/cli/commands/mcp-install.js.map +1 -0
- package/dist/cli/commands/restore.d.ts +50 -0
- package/dist/cli/commands/restore.d.ts.map +1 -0
- package/dist/cli/commands/restore.js +260 -0
- package/dist/cli/commands/restore.js.map +1 -0
- package/dist/cli/commands/setup.d.ts +19 -0
- package/dist/cli/commands/setup.d.ts.map +1 -0
- package/dist/cli/commands/setup.js +206 -0
- package/dist/cli/commands/setup.js.map +1 -0
- package/dist/cli/commands/uninstall.d.ts +37 -0
- package/dist/cli/commands/uninstall.d.ts.map +1 -0
- package/dist/cli/commands/uninstall.js +189 -0
- package/dist/cli/commands/uninstall.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +105 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/discovery.d.ts +6 -2
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +296 -2
- package/dist/discovery.js.map +1 -1
- package/dist/enterprise/env.d.ts +56 -0
- package/dist/enterprise/env.d.ts.map +1 -0
- package/dist/enterprise/env.js +124 -0
- package/dist/enterprise/env.js.map +1 -0
- package/dist/enterprise/index.d.ts +7 -0
- package/dist/enterprise/index.d.ts.map +1 -0
- package/dist/enterprise/index.js +7 -0
- package/dist/enterprise/index.js.map +1 -0
- package/dist/enterprise/script-generator.d.ts +32 -0
- package/dist/enterprise/script-generator.d.ts.map +1 -0
- package/dist/enterprise/script-generator.js +461 -0
- package/dist/enterprise/script-generator.js.map +1 -0
- package/dist/execute.d.ts +21 -0
- package/dist/execute.d.ts.map +1 -1
- package/dist/execute.js +231 -0
- package/dist/execute.js.map +1 -1
- package/dist/index.js +79 -7
- package/dist/index.js.map +1 -1
- package/dist/stripe.d.ts +1 -1
- package/dist/stripe.js +1 -1
- package/dist/stripe.js.map +1 -1
- package/dist/types.d.ts +29 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/colors.d.ts +111 -0
- package/dist/ui/colors.d.ts.map +1 -0
- package/dist/ui/colors.js +185 -0
- package/dist/ui/colors.js.map +1 -0
- package/dist/ui/errors.d.ts +69 -0
- package/dist/ui/errors.d.ts.map +1 -0
- package/dist/ui/errors.js +334 -0
- package/dist/ui/errors.js.map +1 -0
- package/dist/ui/index.d.ts +10 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +14 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/prompts.d.ts +88 -0
- package/dist/ui/prompts.d.ts.map +1 -0
- package/dist/ui/prompts.js +295 -0
- package/dist/ui/prompts.js.map +1 -0
- package/dist/ui/spinner.d.ts +112 -0
- package/dist/ui/spinner.d.ts.map +1 -0
- package/dist/ui/spinner.js +229 -0
- package/dist/ui/spinner.js.map +1 -0
- package/dist/utils/backup.d.ts +48 -0
- package/dist/utils/backup.d.ts.map +1 -0
- package/dist/utils/backup.js +182 -0
- package/dist/utils/backup.js.map +1 -0
- package/dist/utils/config.d.ts +80 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +221 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/os.d.ts +45 -0
- package/dist/utils/os.d.ts.map +1 -0
- package/dist/utils/os.js +106 -0
- package/dist/utils/os.js.map +1 -0
- package/dist/utils/paths.d.ts +38 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +160 -0
- package/dist/utils/paths.js.map +1 -0
- package/docs/PRD-BILLING.md +226 -0
- package/docs/PRD-EARN-SYSTEM.md +261 -0
- package/docs/PRD-MCP-AUTO-SETUP.md +623 -0
- package/docs/enterprise-deployment.md +728 -0
- package/landing/next.config.mjs +14 -0
- package/landing/public/book/index.html +24 -5
- package/landing/public/demo-product.jpg +0 -0
- package/landing/public/stats.json +4 -2
- package/landing/scripts/generate-stats.js +13 -0
- package/landing/src/app/api/og/route.tsx +1 -3
- package/landing/src/app/api/workspace-auth/magic-link/route.ts +6 -3
- package/landing/src/app/auth/verify/page.tsx +11 -4
- package/landing/src/app/docs/page.tsx +1 -1
- package/landing/src/app/join/page.tsx +49 -0
- package/landing/src/app/layout.tsx +1 -1
- package/landing/src/app/login/page.tsx +7 -1
- package/landing/src/app/page.tsx +50 -38
- package/landing/src/app/providers/register/page.tsx +1 -1
- package/landing/src/app/workspace/page.tsx +484 -806
- package/landing/src/components/CheckoutButton.tsx +1 -1
- package/landing/src/components/EarnCreditsTab.tsx +842 -0
- package/landing/src/components/HeroTabs.tsx +2 -2
- package/landing/src/components/demo/PhoneDemo.tsx +423 -0
- package/landing/src/components/demo/index.ts +1 -0
- package/landing/src/lib/stats.json +3 -1
- package/landing/tailwind.config.ts +10 -0
- package/package.json +9 -2
- package/src/adapters/base.ts +363 -0
- package/src/adapters/claude-desktop.ts +41 -0
- package/src/adapters/cline.ts +88 -0
- package/src/adapters/continue.ts +91 -0
- package/src/adapters/cursor.ts +43 -0
- package/src/adapters/custom.ts +188 -0
- package/src/adapters/detect.ts +202 -0
- package/src/adapters/index.ts +47 -0
- package/src/adapters/windsurf.ts +44 -0
- package/src/bin.ts +19 -0
- package/src/cli/commands/doctor.ts +367 -0
- package/src/cli/commands/index.ts +9 -0
- package/src/cli/commands/mcp-install.ts +291 -0
- package/src/cli/commands/restore.ts +333 -0
- package/src/cli/commands/setup.ts +276 -0
- package/src/cli/commands/uninstall.ts +240 -0
- package/src/cli/index.ts +116 -0
- package/src/discovery.ts +328 -3
- package/src/enterprise/env.ts +156 -0
- package/src/enterprise/index.ts +7 -0
- package/src/enterprise/script-generator.ts +481 -0
- package/src/execute.ts +256 -0
- package/src/index.ts +85 -7
- package/src/stripe.ts +1 -1
- package/src/types.ts +32 -0
- package/src/ui/colors.ts +219 -0
- package/src/ui/errors.ts +394 -0
- package/src/ui/index.ts +17 -0
- package/src/ui/prompts.ts +390 -0
- package/src/ui/spinner.ts +325 -0
- package/src/utils/backup.ts +224 -0
- package/src/utils/config.ts +315 -0
- package/src/utils/os.ts +124 -0
- package/src/utils/paths.ts +203 -0
- package/STATUS.md +0 -160
- package/landing/tsconfig.tsbuildinfo +0 -1
|
@@ -31,7 +31,7 @@ export function HeroTabs() {
|
|
|
31
31
|
|
|
32
32
|
const configSnippetJson = selectedClient === "chatgpt" ? chatGptInstructions : jsonConfig;
|
|
33
33
|
|
|
34
|
-
const terminalCommand = "npx @nordsym/apiclaw";
|
|
34
|
+
const terminalCommand = "npx @nordsym/apiclaw mcp-install";
|
|
35
35
|
|
|
36
36
|
const copyConfig = () => {
|
|
37
37
|
navigator.clipboard.writeText(configSnippetJson);
|
|
@@ -126,7 +126,7 @@ export function HeroTabs() {
|
|
|
126
126
|
<div className="code-preview-header">terminal</div>
|
|
127
127
|
<div className="code-preview-body">
|
|
128
128
|
<pre className="text-sm">
|
|
129
|
-
<span className="text-green-400">$</span> <span className="text-blue-400">npx</span> @nordsym/apiclaw
|
|
129
|
+
<span className="text-green-400">$</span> <span className="text-blue-400">npx</span> @nordsym/apiclaw mcp-install
|
|
130
130
|
</pre>
|
|
131
131
|
</div>
|
|
132
132
|
</div>
|
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useState, useEffect, useCallback } from "react";
|
|
4
|
+
import Image from "next/image";
|
|
5
|
+
|
|
6
|
+
interface WithMessage {
|
|
7
|
+
role: "user" | "assistant";
|
|
8
|
+
text: string;
|
|
9
|
+
meta?: string;
|
|
10
|
+
typing?: boolean;
|
|
11
|
+
image?: boolean;
|
|
12
|
+
currency?: boolean;
|
|
13
|
+
success?: boolean;
|
|
14
|
+
search?: boolean;
|
|
15
|
+
models?: { name: string; match: string }[];
|
|
16
|
+
results?: { name: string; match: string; cost: string }[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface WithoutMessage {
|
|
20
|
+
role: "step";
|
|
21
|
+
text: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
type Message = WithMessage | WithoutMessage;
|
|
25
|
+
|
|
26
|
+
// Example 1: Direct Call - Replicate
|
|
27
|
+
const DirectCallExample: WithMessage[] = [
|
|
28
|
+
{ role: "user", text: "Generate a product photo of a coffee mug" },
|
|
29
|
+
{ role: "assistant", text: "Direct Call → Replicate", search: true },
|
|
30
|
+
{
|
|
31
|
+
role: "assistant",
|
|
32
|
+
text: "Selecting model...",
|
|
33
|
+
models: [
|
|
34
|
+
{ name: "Flux Pro", match: "Best for products" },
|
|
35
|
+
{ name: "SDXL", match: "Fast generation" },
|
|
36
|
+
{ name: "Stable Diffusion 3", match: "Versatile" },
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
{ role: "assistant", text: "Using Flux Pro", meta: "via Replicate Direct Call" },
|
|
40
|
+
{ role: "assistant", text: "Generating...", typing: true },
|
|
41
|
+
{ role: "assistant", text: "Done", image: true, success: true },
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
// Example 2: Open API - Currency
|
|
45
|
+
const OpenAPIExample: WithMessage[] = [
|
|
46
|
+
{ role: "user", text: "What's the USD to SEK exchange rate?" },
|
|
47
|
+
{ role: "assistant", text: "Open API → Frankfurter", search: true },
|
|
48
|
+
{ role: "assistant", text: "No API key needed", meta: "Free, open access" },
|
|
49
|
+
{ role: "assistant", text: "Fetching rate...", typing: true },
|
|
50
|
+
{ role: "assistant", text: "Current rate", currency: true, success: true },
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
// Example 3: Discovery - Search 22k APIs
|
|
54
|
+
const DiscoveryExample: WithMessage[] = [
|
|
55
|
+
{ role: "user", text: "I need to transcribe meeting recordings" },
|
|
56
|
+
{ role: "assistant", text: "Searching 22,000+ APIs...", search: true },
|
|
57
|
+
{
|
|
58
|
+
role: "assistant",
|
|
59
|
+
text: "Found 4 matches",
|
|
60
|
+
results: [
|
|
61
|
+
{ name: "Deepgram", match: "96%", cost: "$0.0043/min" },
|
|
62
|
+
{ name: "AssemblyAI", match: "94%", cost: "$0.0065/min" },
|
|
63
|
+
{ name: "Rev.ai", match: "91%", cost: "$0.02/min" },
|
|
64
|
+
{ name: "Google STT", match: "89%", cost: "$0.006/min" },
|
|
65
|
+
]
|
|
66
|
+
},
|
|
67
|
+
{ role: "assistant", text: "Deepgram recommended", meta: "Best accuracy + pricing", success: true },
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
const WithoutAPIClaw: WithoutMessage[] = [
|
|
71
|
+
{ role: "step", text: "Search for the right API" },
|
|
72
|
+
{ role: "step", text: "Open 12 tabs, compare providers" },
|
|
73
|
+
{ role: "step", text: "Read documentation for each" },
|
|
74
|
+
{ role: "step", text: "Create account, verify email" },
|
|
75
|
+
{ role: "step", text: "Set up billing, generate key" },
|
|
76
|
+
{ role: "step", text: "Store key securely in .env" },
|
|
77
|
+
{ role: "step", text: "Write API integration code" },
|
|
78
|
+
{ role: "step", text: "Debug authentication errors" },
|
|
79
|
+
{ role: "step", text: "Finally make first API call" },
|
|
80
|
+
];
|
|
81
|
+
|
|
82
|
+
const examples = [
|
|
83
|
+
{ id: "direct", label: "Direct Call", messages: DirectCallExample },
|
|
84
|
+
{ id: "open", label: "Open API", messages: OpenAPIExample },
|
|
85
|
+
{ id: "discovery", label: "Discovery", messages: DiscoveryExample },
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
// OpenAI-style logo
|
|
89
|
+
function OpenAILogo({ className }: { className?: string }) {
|
|
90
|
+
return (
|
|
91
|
+
<svg className={className} viewBox="0 0 24 24" fill="currentColor">
|
|
92
|
+
<path d="M22.282 9.821a5.985 5.985 0 0 0-.516-4.91 6.046 6.046 0 0 0-6.51-2.9A6.065 6.065 0 0 0 4.981 4.18a5.985 5.985 0 0 0-3.998 2.9 6.046 6.046 0 0 0 .743 7.097 5.98 5.98 0 0 0 .51 4.911 6.051 6.051 0 0 0 6.515 2.9A5.985 5.985 0 0 0 13.26 24a6.056 6.056 0 0 0 5.772-4.206 5.99 5.99 0 0 0 3.997-2.9 6.056 6.056 0 0 0-.747-7.073zM13.26 22.43a4.476 4.476 0 0 1-2.876-1.04l.141-.081 4.779-2.758a.795.795 0 0 0 .392-.681v-6.737l2.02 1.168a.071.071 0 0 1 .038.052v5.583a4.504 4.504 0 0 1-4.494 4.494zM3.6 18.304a4.47 4.47 0 0 1-.535-3.014l.142.085 4.783 2.759a.771.771 0 0 0 .78 0l5.843-3.369v2.332a.08.08 0 0 1-.033.062L9.74 19.95a4.5 4.5 0 0 1-6.14-1.646zM2.34 7.896a4.485 4.485 0 0 1 2.366-1.973V11.6a.766.766 0 0 0 .388.676l5.815 3.355-2.02 1.168a.076.076 0 0 1-.071 0l-4.83-2.786A4.504 4.504 0 0 1 2.34 7.872zm16.597 3.855l-5.833-3.387L15.119 7.2a.076.076 0 0 1 .071 0l4.83 2.791a4.494 4.494 0 0 1-.676 8.105v-5.678a.79.79 0 0 0-.407-.667zm2.01-3.023l-.141-.085-4.774-2.782a.776.776 0 0 0-.785 0L9.409 9.23V6.897a.066.066 0 0 1 .028-.061l4.83-2.787a4.5 4.5 0 0 1 6.68 4.66zm-12.64 4.135l-2.02-1.164a.08.08 0 0 1-.038-.057V6.075a4.5 4.5 0 0 1 7.375-3.453l-.142.08L8.704 5.46a.795.795 0 0 0-.393.681zm1.097-2.365l2.602-1.5 2.607 1.5v2.999l-2.597 1.5-2.607-1.5z" />
|
|
93
|
+
</svg>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function PhoneDemo() {
|
|
98
|
+
const [withClaw, setWithClaw] = useState(true);
|
|
99
|
+
const [exampleIndex, setExampleIndex] = useState(0);
|
|
100
|
+
const [visibleMessages, setVisibleMessages] = useState(0);
|
|
101
|
+
const [isPaused, setIsPaused] = useState(false);
|
|
102
|
+
const [completedSteps, setCompletedSteps] = useState<number[]>([]);
|
|
103
|
+
|
|
104
|
+
const currentExample = examples[exampleIndex];
|
|
105
|
+
const messages: Message[] = withClaw ? currentExample.messages : WithoutAPIClaw;
|
|
106
|
+
|
|
107
|
+
// Reset when switching modes or examples
|
|
108
|
+
useEffect(() => {
|
|
109
|
+
setVisibleMessages(0);
|
|
110
|
+
setCompletedSteps([]);
|
|
111
|
+
}, [exampleIndex, withClaw]);
|
|
112
|
+
|
|
113
|
+
// Animate messages appearing
|
|
114
|
+
useEffect(() => {
|
|
115
|
+
if (visibleMessages >= messages.length) return;
|
|
116
|
+
|
|
117
|
+
const delay = withClaw ? 800 : 700;
|
|
118
|
+
const timer = setTimeout(() => {
|
|
119
|
+
setVisibleMessages(v => v + 1);
|
|
120
|
+
// For "Without" mode, mark previous step as completed after a delay
|
|
121
|
+
if (!withClaw && visibleMessages > 0) {
|
|
122
|
+
setTimeout(() => {
|
|
123
|
+
setCompletedSteps(prev => [...prev, visibleMessages - 1]);
|
|
124
|
+
}, 300);
|
|
125
|
+
}
|
|
126
|
+
}, delay);
|
|
127
|
+
|
|
128
|
+
return () => clearTimeout(timer);
|
|
129
|
+
}, [visibleMessages, messages.length, withClaw]);
|
|
130
|
+
|
|
131
|
+
// Mark last step as completed when all visible
|
|
132
|
+
useEffect(() => {
|
|
133
|
+
if (!withClaw && visibleMessages === messages.length && visibleMessages > 0) {
|
|
134
|
+
const timer = setTimeout(() => {
|
|
135
|
+
setCompletedSteps(prev => [...prev, visibleMessages - 1]);
|
|
136
|
+
}, 500);
|
|
137
|
+
return () => clearTimeout(timer);
|
|
138
|
+
}
|
|
139
|
+
}, [visibleMessages, messages.length, withClaw]);
|
|
140
|
+
|
|
141
|
+
// Auto-rotate examples (only when withClaw is true)
|
|
142
|
+
useEffect(() => {
|
|
143
|
+
if (!withClaw || isPaused) return;
|
|
144
|
+
if (visibleMessages < messages.length) return;
|
|
145
|
+
|
|
146
|
+
const timer = setTimeout(() => {
|
|
147
|
+
setExampleIndex((i) => (i + 1) % examples.length);
|
|
148
|
+
}, 3500);
|
|
149
|
+
|
|
150
|
+
return () => clearTimeout(timer);
|
|
151
|
+
}, [visibleMessages, messages.length, withClaw, isPaused]);
|
|
152
|
+
|
|
153
|
+
const handleDotClick = useCallback((index: number) => {
|
|
154
|
+
setExampleIndex(index);
|
|
155
|
+
setIsPaused(true);
|
|
156
|
+
setTimeout(() => setIsPaused(false), 15000);
|
|
157
|
+
}, []);
|
|
158
|
+
|
|
159
|
+
return (
|
|
160
|
+
<div className="w-full max-w-sm mx-auto">
|
|
161
|
+
{/* Toggle */}
|
|
162
|
+
<div className="flex items-center justify-center gap-3 mb-6">
|
|
163
|
+
<button
|
|
164
|
+
onClick={() => setWithClaw(true)}
|
|
165
|
+
className={`px-5 py-2.5 rounded-full font-medium text-sm transition-all duration-200 ${
|
|
166
|
+
withClaw
|
|
167
|
+
? "bg-zinc-900 text-white shadow-lg"
|
|
168
|
+
: "bg-zinc-100 text-zinc-600 hover:bg-zinc-200"
|
|
169
|
+
}`}
|
|
170
|
+
>
|
|
171
|
+
With APIClaw
|
|
172
|
+
</button>
|
|
173
|
+
<button
|
|
174
|
+
onClick={() => setWithClaw(false)}
|
|
175
|
+
className={`px-5 py-2.5 rounded-full font-medium text-sm transition-all duration-200 ${
|
|
176
|
+
!withClaw
|
|
177
|
+
? "bg-zinc-900 text-white shadow-lg"
|
|
178
|
+
: "bg-zinc-100 text-zinc-600 hover:bg-zinc-200"
|
|
179
|
+
}`}
|
|
180
|
+
>
|
|
181
|
+
Without
|
|
182
|
+
</button>
|
|
183
|
+
</div>
|
|
184
|
+
|
|
185
|
+
{/* Example indicator (only show when withClaw) */}
|
|
186
|
+
{withClaw && (
|
|
187
|
+
<div className="flex items-center justify-center gap-2 mb-4">
|
|
188
|
+
{examples.map((ex, i) => (
|
|
189
|
+
<button
|
|
190
|
+
key={ex.id}
|
|
191
|
+
onClick={() => handleDotClick(i)}
|
|
192
|
+
className={`px-3 py-1.5 rounded-full text-xs font-medium transition-all duration-200 ${
|
|
193
|
+
i === exampleIndex
|
|
194
|
+
? "bg-zinc-900 text-white"
|
|
195
|
+
: "bg-zinc-100 text-zinc-500 hover:bg-zinc-200"
|
|
196
|
+
}`}
|
|
197
|
+
>
|
|
198
|
+
{ex.label}
|
|
199
|
+
</button>
|
|
200
|
+
))}
|
|
201
|
+
</div>
|
|
202
|
+
)}
|
|
203
|
+
|
|
204
|
+
{/* ChatGPT-style Phone Frame */}
|
|
205
|
+
<div className="relative mx-auto" style={{ maxWidth: "340px" }}>
|
|
206
|
+
<div className="relative bg-zinc-900 rounded-[2.5rem] p-2 shadow-2xl">
|
|
207
|
+
<div className="bg-white rounded-[2.2rem] overflow-hidden min-h-[480px] flex flex-col">
|
|
208
|
+
{/* Status bar */}
|
|
209
|
+
<div className="flex items-center justify-between px-6 py-2 text-xs text-zinc-900 font-medium">
|
|
210
|
+
<span>9:41</span>
|
|
211
|
+
<div className="flex items-center gap-1">
|
|
212
|
+
<svg className="w-4 h-4" fill="currentColor" viewBox="0 0 24 24"><path d="M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9 9-4.03 9-9-4.03-9-9-9zm0 16c-3.86 0-7-3.14-7-7s3.14-7 7-7 7 3.14 7 7-3.14 7-7 7z"/></svg>
|
|
213
|
+
<svg className="w-4 h-4" fill="currentColor" viewBox="0 0 24 24"><path d="M17 4h-3V2h-4v2H7v18h10V4zm-2 16H9V6h6v14z"/></svg>
|
|
214
|
+
</div>
|
|
215
|
+
</div>
|
|
216
|
+
|
|
217
|
+
{/* App Header */}
|
|
218
|
+
<div className="flex items-center justify-between px-4 py-3 border-b border-zinc-100">
|
|
219
|
+
<div className="flex items-center gap-3">
|
|
220
|
+
{withClaw ? (
|
|
221
|
+
<div className="w-8 h-8 rounded-full bg-zinc-900 flex items-center justify-center">
|
|
222
|
+
<OpenAILogo className="w-5 h-5 text-white" />
|
|
223
|
+
</div>
|
|
224
|
+
) : (
|
|
225
|
+
<div className="w-8 h-8 rounded-full bg-orange-500 flex items-center justify-center">
|
|
226
|
+
<svg className="w-5 h-5 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
|
227
|
+
<path strokeLinecap="round" strokeLinejoin="round" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
228
|
+
</svg>
|
|
229
|
+
</div>
|
|
230
|
+
)}
|
|
231
|
+
<div>
|
|
232
|
+
<div className="text-zinc-900 font-semibold text-sm">
|
|
233
|
+
{withClaw ? "Agent + APIClaw" : "Manual Workflow"}
|
|
234
|
+
</div>
|
|
235
|
+
</div>
|
|
236
|
+
</div>
|
|
237
|
+
</div>
|
|
238
|
+
|
|
239
|
+
{/* Messages area */}
|
|
240
|
+
<div className="flex-1 overflow-y-auto px-4 py-4 space-y-3 bg-white">
|
|
241
|
+
{messages.slice(0, visibleMessages).map((msg, i) => (
|
|
242
|
+
<div
|
|
243
|
+
key={`${withClaw}-${exampleIndex}-${i}`}
|
|
244
|
+
className="transition-all duration-500 ease-out"
|
|
245
|
+
style={{
|
|
246
|
+
opacity: 1,
|
|
247
|
+
transform: 'translateY(0)',
|
|
248
|
+
animation: 'slideUp 0.4s ease-out'
|
|
249
|
+
}}
|
|
250
|
+
>
|
|
251
|
+
{msg.role === "user" ? (
|
|
252
|
+
<div className="flex justify-end">
|
|
253
|
+
<div className="bg-zinc-100 text-zinc-900 px-4 py-2.5 rounded-2xl rounded-br-md max-w-[85%] text-sm">
|
|
254
|
+
{msg.text}
|
|
255
|
+
</div>
|
|
256
|
+
</div>
|
|
257
|
+
) : msg.role === "step" ? (
|
|
258
|
+
<div className="flex items-center gap-3 transition-all duration-300">
|
|
259
|
+
<div className={`w-6 h-6 rounded-full flex items-center justify-center text-xs font-medium flex-shrink-0 transition-all duration-300 ${
|
|
260
|
+
completedSteps.includes(i)
|
|
261
|
+
? "bg-green-500 text-white scale-100"
|
|
262
|
+
: "bg-zinc-100 text-zinc-500"
|
|
263
|
+
}`}>
|
|
264
|
+
{completedSteps.includes(i) ? (
|
|
265
|
+
<svg className="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={3}>
|
|
266
|
+
<path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
|
|
267
|
+
</svg>
|
|
268
|
+
) : (
|
|
269
|
+
i + 1
|
|
270
|
+
)}
|
|
271
|
+
</div>
|
|
272
|
+
<span className={`text-sm transition-all duration-300 ${
|
|
273
|
+
completedSteps.includes(i) ? "text-zinc-400" : "text-zinc-700"
|
|
274
|
+
}`}>
|
|
275
|
+
{msg.text}
|
|
276
|
+
</span>
|
|
277
|
+
{!completedSteps.includes(i) && i === visibleMessages - 1 && (
|
|
278
|
+
<div className="flex gap-0.5 ml-1">
|
|
279
|
+
<span className="w-1 h-1 bg-zinc-400 rounded-full animate-pulse" />
|
|
280
|
+
<span className="w-1 h-1 bg-zinc-400 rounded-full animate-pulse" style={{ animationDelay: "0.15s" }} />
|
|
281
|
+
<span className="w-1 h-1 bg-zinc-400 rounded-full animate-pulse" style={{ animationDelay: "0.3s" }} />
|
|
282
|
+
</div>
|
|
283
|
+
)}
|
|
284
|
+
</div>
|
|
285
|
+
) : (
|
|
286
|
+
<div className="flex gap-3">
|
|
287
|
+
<div className="w-7 h-7 rounded-full bg-zinc-900 flex items-center justify-center flex-shrink-0">
|
|
288
|
+
<OpenAILogo className="w-4 h-4 text-white" />
|
|
289
|
+
</div>
|
|
290
|
+
|
|
291
|
+
<div className="flex-1 min-w-0">
|
|
292
|
+
{msg.search && (
|
|
293
|
+
<div className="flex items-center gap-2 text-zinc-700 text-sm py-1 font-medium">
|
|
294
|
+
<svg className="w-4 h-4 text-zinc-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
|
295
|
+
<path strokeLinecap="round" strokeLinejoin="round" d="M13 10V3L4 14h7v7l9-11h-7z" />
|
|
296
|
+
</svg>
|
|
297
|
+
{msg.text}
|
|
298
|
+
</div>
|
|
299
|
+
)}
|
|
300
|
+
{msg.models && (
|
|
301
|
+
<div className="space-y-2">
|
|
302
|
+
<div className="text-zinc-900 text-sm font-medium">{msg.text}</div>
|
|
303
|
+
<div className="space-y-1.5">
|
|
304
|
+
{msg.models.map((m, j) => (
|
|
305
|
+
<div key={j} className={`flex items-center justify-between text-xs px-3 py-2 rounded-lg transition-all duration-200 ${
|
|
306
|
+
j === 0 ? "bg-zinc-900 text-white" : "bg-zinc-50 text-zinc-600"
|
|
307
|
+
}`}>
|
|
308
|
+
<span className={j === 0 ? "font-medium" : ""}>{m.name}</span>
|
|
309
|
+
<span className={j === 0 ? "text-zinc-300" : "text-zinc-400"}>{m.match}</span>
|
|
310
|
+
</div>
|
|
311
|
+
))}
|
|
312
|
+
</div>
|
|
313
|
+
</div>
|
|
314
|
+
)}
|
|
315
|
+
{msg.results && (
|
|
316
|
+
<div className="space-y-2">
|
|
317
|
+
<div className="text-zinc-900 text-sm font-medium">{msg.text}</div>
|
|
318
|
+
<div className="space-y-1.5">
|
|
319
|
+
{msg.results.map((r, j) => (
|
|
320
|
+
<div key={j} className={`flex items-center justify-between text-xs px-3 py-2 rounded-lg transition-all duration-200 ${
|
|
321
|
+
j === 0 ? "bg-zinc-900 text-white" : "bg-zinc-50 text-zinc-600"
|
|
322
|
+
}`}>
|
|
323
|
+
<span className={j === 0 ? "font-medium" : ""}>{r.name}</span>
|
|
324
|
+
<div className="flex items-center gap-2">
|
|
325
|
+
<span className={j === 0 ? "text-zinc-300" : "text-zinc-400"}>{r.match}</span>
|
|
326
|
+
<span className={j === 0 ? "text-zinc-500" : "text-zinc-300"}>·</span>
|
|
327
|
+
<span className={j === 0 ? "text-zinc-300" : "text-zinc-400"}>{r.cost}</span>
|
|
328
|
+
</div>
|
|
329
|
+
</div>
|
|
330
|
+
))}
|
|
331
|
+
</div>
|
|
332
|
+
</div>
|
|
333
|
+
)}
|
|
334
|
+
{!msg.search && !msg.results && !msg.models && (
|
|
335
|
+
<div className="text-zinc-800 text-sm flex items-center gap-2 py-1">
|
|
336
|
+
{msg.success && (
|
|
337
|
+
<svg className="w-4 h-4 text-green-500" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
|
338
|
+
<path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
|
|
339
|
+
</svg>
|
|
340
|
+
)}
|
|
341
|
+
{msg.typing && (
|
|
342
|
+
<span className="flex gap-1">
|
|
343
|
+
<span className="w-1.5 h-1.5 bg-zinc-400 rounded-full animate-bounce" />
|
|
344
|
+
<span className="w-1.5 h-1.5 bg-zinc-400 rounded-full animate-bounce" style={{ animationDelay: "0.15s" }} />
|
|
345
|
+
<span className="w-1.5 h-1.5 bg-zinc-400 rounded-full animate-bounce" style={{ animationDelay: "0.3s" }} />
|
|
346
|
+
</span>
|
|
347
|
+
)}
|
|
348
|
+
{msg.text}
|
|
349
|
+
</div>
|
|
350
|
+
)}
|
|
351
|
+
{msg.meta && (
|
|
352
|
+
<div className="text-zinc-400 text-xs mt-0.5">{msg.meta}</div>
|
|
353
|
+
)}
|
|
354
|
+
{msg.image && (
|
|
355
|
+
<div className="mt-2 w-44 aspect-square rounded-xl overflow-hidden shadow-md">
|
|
356
|
+
<Image
|
|
357
|
+
src="/demo-product.jpg"
|
|
358
|
+
alt="Generated product image"
|
|
359
|
+
width={176}
|
|
360
|
+
height={176}
|
|
361
|
+
className="w-full h-full object-cover"
|
|
362
|
+
/>
|
|
363
|
+
</div>
|
|
364
|
+
)}
|
|
365
|
+
{msg.currency && (
|
|
366
|
+
<div className="mt-2 bg-zinc-50 border border-zinc-200 rounded-xl p-3 inline-block">
|
|
367
|
+
<div className="flex items-center gap-3">
|
|
368
|
+
<div className="text-2xl font-bold text-zinc-900">10.82</div>
|
|
369
|
+
<div className="text-sm text-zinc-500">
|
|
370
|
+
<div className="font-medium">USD → SEK</div>
|
|
371
|
+
<div className="text-xs text-zinc-400">Live rate</div>
|
|
372
|
+
</div>
|
|
373
|
+
</div>
|
|
374
|
+
</div>
|
|
375
|
+
)}
|
|
376
|
+
</div>
|
|
377
|
+
</div>
|
|
378
|
+
)}
|
|
379
|
+
</div>
|
|
380
|
+
))}
|
|
381
|
+
</div>
|
|
382
|
+
|
|
383
|
+
{/* Input area */}
|
|
384
|
+
<div className="p-3 border-t border-zinc-100">
|
|
385
|
+
<div className="flex items-center gap-2 bg-zinc-50 border border-zinc-200 rounded-2xl px-4 py-3">
|
|
386
|
+
<input
|
|
387
|
+
type="text"
|
|
388
|
+
placeholder="Message..."
|
|
389
|
+
className="flex-1 bg-transparent text-sm text-zinc-900 placeholder-zinc-400 outline-none"
|
|
390
|
+
readOnly
|
|
391
|
+
/>
|
|
392
|
+
<button className="w-7 h-7 bg-zinc-900 rounded-full flex items-center justify-center">
|
|
393
|
+
<svg className="w-3.5 h-3.5 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2.5}>
|
|
394
|
+
<path strokeLinecap="round" strokeLinejoin="round" d="M5 10l7-7m0 0l7 7m-7-7v18" />
|
|
395
|
+
</svg>
|
|
396
|
+
</button>
|
|
397
|
+
</div>
|
|
398
|
+
</div>
|
|
399
|
+
|
|
400
|
+
{/* Home indicator */}
|
|
401
|
+
<div className="flex justify-center pb-2">
|
|
402
|
+
<div className="w-32 h-1 bg-zinc-900 rounded-full" />
|
|
403
|
+
</div>
|
|
404
|
+
</div>
|
|
405
|
+
</div>
|
|
406
|
+
</div>
|
|
407
|
+
|
|
408
|
+
{/* CSS for animations */}
|
|
409
|
+
<style jsx>{`
|
|
410
|
+
@keyframes slideUp {
|
|
411
|
+
from {
|
|
412
|
+
opacity: 0;
|
|
413
|
+
transform: translateY(10px);
|
|
414
|
+
}
|
|
415
|
+
to {
|
|
416
|
+
opacity: 1;
|
|
417
|
+
transform: translateY(0);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
`}</style>
|
|
421
|
+
</div>
|
|
422
|
+
);
|
|
423
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PhoneDemo } from './PhoneDemo';
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"apiCount": 22392,
|
|
3
|
+
"openApiCount": 1636,
|
|
4
|
+
"directCallCount": 18,
|
|
3
5
|
"categoryCount": 13,
|
|
4
6
|
"lastUpdated": "2026-02-27T09:10:41.344767",
|
|
5
|
-
"generatedAt": "2026-
|
|
7
|
+
"generatedAt": "2026-03-01T16:05:56.209Z",
|
|
6
8
|
"categoryBreakdown": {
|
|
7
9
|
"Finance": 1179,
|
|
8
10
|
"Auth & Security": 491,
|
|
@@ -28,8 +28,18 @@ const config: Config = {
|
|
|
28
28
|
'tighter': '-0.03em',
|
|
29
29
|
'widest': '0.15em',
|
|
30
30
|
},
|
|
31
|
+
animation: {
|
|
32
|
+
'fade-in': 'fadeIn 0.3s ease-out forwards',
|
|
33
|
+
},
|
|
34
|
+
keyframes: {
|
|
35
|
+
fadeIn: {
|
|
36
|
+
'0%': { opacity: '0', transform: 'translateY(8px)' },
|
|
37
|
+
'100%': { opacity: '1', transform: 'translateY(0)' },
|
|
38
|
+
},
|
|
39
|
+
},
|
|
31
40
|
},
|
|
32
41
|
},
|
|
33
42
|
plugins: [],
|
|
34
43
|
};
|
|
44
|
+
|
|
35
45
|
export default config;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nordsym/apiclaw",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.9",
|
|
4
4
|
"description": "Agent-native API discovery and Direct Call execution via MCP",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -28,17 +28,24 @@
|
|
|
28
28
|
"@hono/node-server": "^1.19.9",
|
|
29
29
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
30
30
|
"@supabase/supabase-js": "^2.39.0",
|
|
31
|
+
"@types/inquirer": "^9.0.9",
|
|
32
|
+
"chalk": "^5.6.2",
|
|
33
|
+
"commander": "^14.0.3",
|
|
31
34
|
"convex": "^1.32.0",
|
|
32
35
|
"dotenv": "^17.3.1",
|
|
36
|
+
"fs-extra": "^11.3.3",
|
|
33
37
|
"hono": "^4.0.0",
|
|
38
|
+
"inquirer": "^13.3.0",
|
|
39
|
+
"ora": "^9.3.0",
|
|
34
40
|
"stripe": "^20.3.1"
|
|
35
41
|
},
|
|
36
42
|
"devDependencies": {
|
|
43
|
+
"@types/fs-extra": "^11.0.4",
|
|
37
44
|
"@types/node": "^20.10.0",
|
|
38
45
|
"tsx": "^4.7.0",
|
|
39
46
|
"typescript": "^5.3.0"
|
|
40
47
|
},
|
|
41
48
|
"bin": {
|
|
42
|
-
"apiclaw": "./dist/
|
|
49
|
+
"apiclaw": "./dist/bin.js"
|
|
43
50
|
}
|
|
44
51
|
}
|