@nordsym/apiclaw 1.2.2 → 1.2.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.
- package/AGENTS.md +50 -33
- package/README.md +22 -12
- package/SOUL.md +60 -19
- package/STATUS.md +91 -169
- package/convex/_generated/api.d.ts +6 -0
- package/convex/directCall.ts +598 -0
- package/convex/providers.ts +341 -26
- package/convex/schema.ts +87 -0
- package/convex/usage.ts +260 -0
- package/convex/waitlist.ts +55 -0
- package/data/combined-02-26.json +22102 -0
- package/data/night-expansion-02-26-06-batch2.json +1898 -0
- package/data/night-expansion-02-26-06-batch3.json +1410 -0
- package/data/night-expansion-02-26-06.json +3146 -0
- package/data/night-expansion-02-26-full.json +9726 -0
- package/data/night-expansion-02-26-v2.json +330 -0
- package/data/night-expansion-02-26.json +171 -0
- package/dist/crypto.d.ts +7 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +67 -0
- package/dist/crypto.js.map +1 -0
- package/dist/execute-dynamic.d.ts +116 -0
- package/dist/execute-dynamic.d.ts.map +1 -0
- package/dist/execute-dynamic.js +456 -0
- package/dist/execute-dynamic.js.map +1 -0
- package/dist/execute.d.ts +2 -1
- package/dist/execute.d.ts.map +1 -1
- package/dist/execute.js +35 -5
- package/dist/execute.js.map +1 -1
- package/dist/index.js +33 -4
- package/dist/index.js.map +1 -1
- package/dist/registry/apis.json +2081 -3
- package/docs/PRD-customer-key-passthrough.md +184 -0
- package/landing/public/badges/available-on-apiclaw.svg +14 -0
- package/landing/scripts/generate-stats.js +75 -4
- package/landing/src/app/admin/page.tsx +1 -1
- package/landing/src/app/api/auth/magic-link/route.ts +1 -1
- package/landing/src/app/api/auth/session/route.ts +1 -1
- package/landing/src/app/api/auth/verify/route.ts +1 -1
- package/landing/src/app/api/og/route.tsx +5 -3
- package/landing/src/app/docs/page.tsx +5 -4
- package/landing/src/app/earn/page.tsx +14 -11
- package/landing/src/app/globals.css +16 -15
- package/landing/src/app/layout.tsx +2 -2
- package/landing/src/app/page.tsx +425 -254
- package/landing/src/app/providers/dashboard/[apiId]/actions/[actionId]/edit/page.tsx +600 -0
- package/landing/src/app/providers/dashboard/[apiId]/actions/new/page.tsx +583 -0
- package/landing/src/app/providers/dashboard/[apiId]/actions/page.tsx +301 -0
- package/landing/src/app/providers/dashboard/[apiId]/direct-call/page.tsx +659 -0
- package/landing/src/app/providers/dashboard/[apiId]/page.tsx +381 -0
- package/landing/src/app/providers/dashboard/[apiId]/test/page.tsx +418 -0
- package/landing/src/app/providers/dashboard/layout.tsx +292 -0
- package/landing/src/app/providers/dashboard/page.tsx +353 -290
- package/landing/src/app/providers/register/page.tsx +87 -10
- package/landing/src/components/AiClientDropdown.tsx +85 -0
- package/landing/src/components/ConfigHelperModal.tsx +113 -0
- package/landing/src/components/HeroTabs.tsx +187 -0
- package/landing/src/components/ShareIntegrationModal.tsx +198 -0
- package/landing/src/hooks/useDashboardData.ts +53 -1
- package/landing/src/lib/apis.json +46554 -174
- package/landing/src/lib/convex-client.ts +22 -3
- package/landing/src/lib/stats.json +4 -4
- package/landing/tsconfig.tsbuildinfo +1 -1
- package/night-expansion-02-26-06-batch2.py +368 -0
- package/night-expansion-02-26-06-batch3.py +299 -0
- package/night-expansion-02-26-06.py +756 -0
- package/package.json +1 -1
- package/scripts/bulk-add-public-apis-v2.py +418 -0
- package/scripts/night-expansion-02-26-v2.py +296 -0
- package/scripts/night-expansion-02-26.py +890 -0
- package/scripts/seed-complete-api.js +181 -0
- package/scripts/seed-demo-api.sh +44 -0
- package/src/crypto.ts +75 -0
- package/src/execute-dynamic.ts +589 -0
- package/src/execute.ts +41 -5
- package/src/index.ts +38 -4
- package/src/registry/apis.json +2081 -3
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useState, useEffect } from "react";
|
|
4
|
+
import { useParams, useRouter } from "next/navigation";
|
|
5
|
+
import Link from "next/link";
|
|
6
|
+
import {
|
|
7
|
+
Plus,
|
|
8
|
+
Settings,
|
|
9
|
+
Trash2,
|
|
10
|
+
Loader2,
|
|
11
|
+
AlertCircle,
|
|
12
|
+
Check,
|
|
13
|
+
X,
|
|
14
|
+
ArrowLeft,
|
|
15
|
+
PlayCircle,
|
|
16
|
+
} from "lucide-react";
|
|
17
|
+
|
|
18
|
+
interface ActionParam {
|
|
19
|
+
name: string;
|
|
20
|
+
type: string;
|
|
21
|
+
required: boolean;
|
|
22
|
+
description: string;
|
|
23
|
+
in: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface ProviderAction {
|
|
27
|
+
_id: string;
|
|
28
|
+
name: string;
|
|
29
|
+
displayName: string;
|
|
30
|
+
description: string;
|
|
31
|
+
method: string;
|
|
32
|
+
path: string;
|
|
33
|
+
params: ActionParam[];
|
|
34
|
+
enabled: boolean;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const CONVEX_URL = process.env.NEXT_PUBLIC_CONVEX_URL || 'https://adventurous-avocet-799.convex.cloud';
|
|
38
|
+
|
|
39
|
+
export default function ActionsPage() {
|
|
40
|
+
const params = useParams();
|
|
41
|
+
const router = useRouter();
|
|
42
|
+
const apiId = params.apiId as string;
|
|
43
|
+
|
|
44
|
+
const [actions, setActions] = useState<ProviderAction[]>([]);
|
|
45
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
46
|
+
const [error, setError] = useState<string | null>(null);
|
|
47
|
+
const [directCallId, setDirectCallId] = useState<string | null>(null);
|
|
48
|
+
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
const loadActions = async () => {
|
|
51
|
+
const token = localStorage.getItem("apiclaw_session");
|
|
52
|
+
if (!token) {
|
|
53
|
+
router.push("/providers/dashboard/login");
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
// First get the direct call config to get directCallId
|
|
59
|
+
const configRes = await fetch(`${CONVEX_URL}/api/query`, {
|
|
60
|
+
method: 'POST',
|
|
61
|
+
headers: { 'Content-Type': 'application/json' },
|
|
62
|
+
body: JSON.stringify({
|
|
63
|
+
path: 'directCall:getDirectCallConfigByApiId',
|
|
64
|
+
args: { apiId }
|
|
65
|
+
})
|
|
66
|
+
});
|
|
67
|
+
const configData = await configRes.json();
|
|
68
|
+
|
|
69
|
+
if (!configData || !configData._id) {
|
|
70
|
+
setError("Direct Call not configured. Please set up Direct Call first.");
|
|
71
|
+
setIsLoading(false);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
setDirectCallId(configData._id);
|
|
76
|
+
|
|
77
|
+
// Then get actions
|
|
78
|
+
const actionsRes = await fetch(`${CONVEX_URL}/api/query`, {
|
|
79
|
+
method: 'POST',
|
|
80
|
+
headers: { 'Content-Type': 'application/json' },
|
|
81
|
+
body: JSON.stringify({
|
|
82
|
+
path: 'directCall:getActions',
|
|
83
|
+
args: { directCallId: configData._id }
|
|
84
|
+
})
|
|
85
|
+
});
|
|
86
|
+
const actionsData = await actionsRes.json();
|
|
87
|
+
setActions(actionsData || []);
|
|
88
|
+
} catch (err) {
|
|
89
|
+
console.error("Failed to load actions:", err);
|
|
90
|
+
setError(err instanceof Error ? err.message : "Failed to load actions");
|
|
91
|
+
} finally {
|
|
92
|
+
setIsLoading(false);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
loadActions();
|
|
97
|
+
}, [apiId, router]);
|
|
98
|
+
|
|
99
|
+
const deleteAction = async (actionId: string) => {
|
|
100
|
+
if (!confirm("Are you sure you want to delete this action?")) return;
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
await fetch(`${CONVEX_URL}/api/mutation`, {
|
|
104
|
+
method: 'POST',
|
|
105
|
+
headers: { 'Content-Type': 'application/json' },
|
|
106
|
+
body: JSON.stringify({
|
|
107
|
+
path: 'directCall:deleteAction',
|
|
108
|
+
args: { actionId }
|
|
109
|
+
})
|
|
110
|
+
});
|
|
111
|
+
setActions(actions.filter(a => a._id !== actionId));
|
|
112
|
+
} catch (err) {
|
|
113
|
+
alert("Failed to delete action");
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const toggleAction = async (actionId: string, enabled: boolean) => {
|
|
118
|
+
try {
|
|
119
|
+
await fetch(`${CONVEX_URL}/api/mutation`, {
|
|
120
|
+
method: 'POST',
|
|
121
|
+
headers: { 'Content-Type': 'application/json' },
|
|
122
|
+
body: JSON.stringify({
|
|
123
|
+
path: 'directCall:saveAction',
|
|
124
|
+
args: {
|
|
125
|
+
directCallId,
|
|
126
|
+
action: { _id: actionId, enabled: !enabled }
|
|
127
|
+
}
|
|
128
|
+
})
|
|
129
|
+
});
|
|
130
|
+
setActions(actions.map(a =>
|
|
131
|
+
a._id === actionId ? { ...a, enabled: !enabled } : a
|
|
132
|
+
));
|
|
133
|
+
} catch (err) {
|
|
134
|
+
alert("Failed to update action");
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const getMethodColor = (method: string) => {
|
|
139
|
+
switch (method.toUpperCase()) {
|
|
140
|
+
case 'GET': return 'bg-green-500/20 text-green-500';
|
|
141
|
+
case 'POST': return 'bg-blue-500/20 text-blue-500';
|
|
142
|
+
case 'PUT': return 'bg-yellow-500/20 text-yellow-600';
|
|
143
|
+
case 'PATCH': return 'bg-orange-500/20 text-orange-500';
|
|
144
|
+
case 'DELETE': return 'bg-red-500/20 text-red-500';
|
|
145
|
+
default: return 'bg-gray-500/20 text-gray-500';
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
if (isLoading) {
|
|
150
|
+
return (
|
|
151
|
+
<div className="flex items-center justify-center py-24">
|
|
152
|
+
<Loader2 className="w-8 h-8 text-accent animate-spin" />
|
|
153
|
+
</div>
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (error) {
|
|
158
|
+
return (
|
|
159
|
+
<div className="text-center py-24">
|
|
160
|
+
<AlertCircle className="w-16 h-16 text-yellow-500 mx-auto mb-4" />
|
|
161
|
+
<h1 className="text-2xl font-bold mb-2">Setup Required</h1>
|
|
162
|
+
<p className="text-text-muted mb-6">{error}</p>
|
|
163
|
+
<Link href={`/providers/dashboard/${apiId}/direct-call`} className="btn-primary">
|
|
164
|
+
Set Up Direct Call
|
|
165
|
+
</Link>
|
|
166
|
+
</div>
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return (
|
|
171
|
+
<div className="space-y-6">
|
|
172
|
+
{/* Header */}
|
|
173
|
+
<div className="flex items-center justify-between">
|
|
174
|
+
<div className="flex items-center gap-4">
|
|
175
|
+
<Link
|
|
176
|
+
href={`/providers/dashboard/${apiId}`}
|
|
177
|
+
className="p-2 hover:bg-surface rounded-lg transition"
|
|
178
|
+
>
|
|
179
|
+
<ArrowLeft className="w-5 h-5" />
|
|
180
|
+
</Link>
|
|
181
|
+
<div>
|
|
182
|
+
<h1 className="text-2xl font-bold">Actions</h1>
|
|
183
|
+
<p className="text-text-muted">Define the endpoints agents can call</p>
|
|
184
|
+
</div>
|
|
185
|
+
</div>
|
|
186
|
+
<Link
|
|
187
|
+
href={`/providers/dashboard/${apiId}/actions/new`}
|
|
188
|
+
className="btn-primary"
|
|
189
|
+
>
|
|
190
|
+
<Plus className="w-4 h-4" />
|
|
191
|
+
Add Action
|
|
192
|
+
</Link>
|
|
193
|
+
</div>
|
|
194
|
+
|
|
195
|
+
{/* Actions List */}
|
|
196
|
+
{actions.length === 0 ? (
|
|
197
|
+
<div className="text-center py-16 rounded-2xl border border-dashed border-border">
|
|
198
|
+
<Settings className="w-12 h-12 text-text-muted mx-auto mb-4" />
|
|
199
|
+
<h2 className="text-xl font-semibold mb-2">No actions yet</h2>
|
|
200
|
+
<p className="text-text-muted mb-6">
|
|
201
|
+
Define your first action to let agents call your API
|
|
202
|
+
</p>
|
|
203
|
+
<Link
|
|
204
|
+
href={`/providers/dashboard/${apiId}/actions/new`}
|
|
205
|
+
className="btn-primary"
|
|
206
|
+
>
|
|
207
|
+
<Plus className="w-4 h-4" />
|
|
208
|
+
Add First Action
|
|
209
|
+
</Link>
|
|
210
|
+
</div>
|
|
211
|
+
) : (
|
|
212
|
+
<div className="space-y-3">
|
|
213
|
+
{actions.map((action) => (
|
|
214
|
+
<div
|
|
215
|
+
key={action._id}
|
|
216
|
+
className="rounded-xl border border-border bg-surface-elevated p-4 hover:border-accent/30 transition"
|
|
217
|
+
>
|
|
218
|
+
<div className="flex items-center justify-between">
|
|
219
|
+
<div className="flex items-center gap-4">
|
|
220
|
+
<span className={`px-2.5 py-1 rounded text-xs font-bold ${getMethodColor(action.method)}`}>
|
|
221
|
+
{action.method}
|
|
222
|
+
</span>
|
|
223
|
+
<div>
|
|
224
|
+
<div className="flex items-center gap-2">
|
|
225
|
+
<h3 className="font-semibold">{action.displayName}</h3>
|
|
226
|
+
<code className="text-xs text-text-muted bg-surface px-2 py-0.5 rounded">
|
|
227
|
+
{action.name}
|
|
228
|
+
</code>
|
|
229
|
+
</div>
|
|
230
|
+
<p className="text-sm text-text-muted font-mono">{action.path}</p>
|
|
231
|
+
</div>
|
|
232
|
+
</div>
|
|
233
|
+
<div className="flex items-center gap-2">
|
|
234
|
+
<button
|
|
235
|
+
onClick={() => toggleAction(action._id, action.enabled)}
|
|
236
|
+
className={`p-2 rounded-lg transition ${
|
|
237
|
+
action.enabled
|
|
238
|
+
? 'bg-green-500/20 text-green-500 hover:bg-green-500/30'
|
|
239
|
+
: 'bg-gray-500/20 text-gray-500 hover:bg-gray-500/30'
|
|
240
|
+
}`}
|
|
241
|
+
title={action.enabled ? 'Disable' : 'Enable'}
|
|
242
|
+
>
|
|
243
|
+
{action.enabled ? <Check className="w-4 h-4" /> : <X className="w-4 h-4" />}
|
|
244
|
+
</button>
|
|
245
|
+
<Link
|
|
246
|
+
href={`/providers/dashboard/${apiId}/actions/${action._id}/edit`}
|
|
247
|
+
className="p-2 rounded-lg hover:bg-surface transition"
|
|
248
|
+
title="Edit"
|
|
249
|
+
>
|
|
250
|
+
<Settings className="w-4 h-4" />
|
|
251
|
+
</Link>
|
|
252
|
+
<button
|
|
253
|
+
onClick={() => deleteAction(action._id)}
|
|
254
|
+
className="p-2 rounded-lg hover:bg-red-500/20 text-text-muted hover:text-red-500 transition"
|
|
255
|
+
title="Delete"
|
|
256
|
+
>
|
|
257
|
+
<Trash2 className="w-4 h-4" />
|
|
258
|
+
</button>
|
|
259
|
+
</div>
|
|
260
|
+
</div>
|
|
261
|
+
{action.description && (
|
|
262
|
+
<p className="text-sm text-text-muted mt-2 ml-[72px]">{action.description}</p>
|
|
263
|
+
)}
|
|
264
|
+
{action.params.length > 0 && (
|
|
265
|
+
<div className="flex items-center gap-2 mt-3 ml-[72px]">
|
|
266
|
+
<span className="text-xs text-text-muted">Params:</span>
|
|
267
|
+
{action.params.slice(0, 5).map((p, i) => (
|
|
268
|
+
<span
|
|
269
|
+
key={i}
|
|
270
|
+
className={`text-xs px-2 py-0.5 rounded ${
|
|
271
|
+
p.required ? 'bg-accent/20 text-accent' : 'bg-surface text-text-muted'
|
|
272
|
+
}`}
|
|
273
|
+
>
|
|
274
|
+
{p.name}
|
|
275
|
+
</span>
|
|
276
|
+
))}
|
|
277
|
+
{action.params.length > 5 && (
|
|
278
|
+
<span className="text-xs text-text-muted">+{action.params.length - 5} more</span>
|
|
279
|
+
)}
|
|
280
|
+
</div>
|
|
281
|
+
)}
|
|
282
|
+
</div>
|
|
283
|
+
))}
|
|
284
|
+
</div>
|
|
285
|
+
)}
|
|
286
|
+
|
|
287
|
+
{/* Test Console Link */}
|
|
288
|
+
{actions.length > 0 && (
|
|
289
|
+
<div className="flex justify-center pt-4">
|
|
290
|
+
<Link
|
|
291
|
+
href={`/providers/dashboard/${apiId}/test`}
|
|
292
|
+
className="btn-secondary"
|
|
293
|
+
>
|
|
294
|
+
<PlayCircle className="w-4 h-4" />
|
|
295
|
+
Test Actions
|
|
296
|
+
</Link>
|
|
297
|
+
</div>
|
|
298
|
+
)}
|
|
299
|
+
</div>
|
|
300
|
+
);
|
|
301
|
+
}
|