@nordsym/apiclaw 1.5.1 → 1.5.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/convex/http.ts +71 -31
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +12 -2
- package/dist/proxy.js.map +1 -1
- package/landing/src/app/api/billing/checkout/route.ts +2 -2
- package/landing/src/app/page.tsx +1 -1
- package/landing/src/app/workspace/page.tsx +6 -4
- package/landing/src/lib/stats.json +1 -1
- package/package.json +1 -1
- package/src/proxy.ts +14 -2
package/convex/http.ts
CHANGED
|
@@ -118,44 +118,53 @@ async function validateAndLogProxyCall(
|
|
|
118
118
|
provider: string,
|
|
119
119
|
action: string
|
|
120
120
|
): Promise<{ valid: boolean; workspaceId?: string; subagentId?: string; error?: string }> {
|
|
121
|
-
const
|
|
122
|
-
const subagentId = request.headers.get("X-APIClaw-Subagent") || "
|
|
121
|
+
const identifier = request.headers.get("X-APIClaw-Identifier");
|
|
122
|
+
const subagentId = request.headers.get("X-APIClaw-Subagent") || "main";
|
|
123
123
|
|
|
124
|
-
|
|
125
|
-
// Allow calls without session but don't log to workspace
|
|
126
|
-
return { valid: true, subagentId };
|
|
127
|
-
}
|
|
124
|
+
console.log("[Proxy] Call received", { provider, action, identifier, subagentId });
|
|
128
125
|
|
|
126
|
+
// ALWAYS log to analytics (even if identifier is missing)
|
|
129
127
|
try {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
if (!session) {
|
|
134
|
-
// Allow call anyway but log warning
|
|
135
|
-
console.warn("[Proxy] Invalid session token, allowing call but not logging");
|
|
136
|
-
return { valid: true, subagentId };
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Log the API call
|
|
140
|
-
await ctx.runMutation(api.logs.createProxyLog, {
|
|
141
|
-
workspaceId: session.workspaceId,
|
|
128
|
+
const result = await ctx.runMutation(api.analytics.log, {
|
|
129
|
+
event: "api_call",
|
|
142
130
|
provider,
|
|
143
|
-
|
|
144
|
-
subagentId,
|
|
145
|
-
sessionToken,
|
|
131
|
+
identifier: identifier || "unknown",
|
|
132
|
+
metadata: { action, subagentId },
|
|
146
133
|
});
|
|
147
|
-
|
|
148
|
-
// Increment usage
|
|
149
|
-
await ctx.runMutation(api.workspaces.incrementUsage, {
|
|
150
|
-
workspaceId: session.workspaceId,
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
return { valid: true, workspaceId: session.workspaceId, subagentId };
|
|
134
|
+
console.log("[Proxy] Analytics logged:", result);
|
|
154
135
|
} catch (e: any) {
|
|
155
|
-
console.error("[Proxy]
|
|
156
|
-
//
|
|
157
|
-
|
|
136
|
+
console.error("[Proxy] Analytics logging failed:", e.message, e.stack);
|
|
137
|
+
// Continue even if analytics fails
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// If we have an identifier and it's a workspace ID (not anon:), log to workspace
|
|
141
|
+
if (identifier && !identifier.startsWith("anon:") && identifier !== "unknown") {
|
|
142
|
+
try {
|
|
143
|
+
// Validate it's actually a workspace ID by checking format
|
|
144
|
+
if (identifier.length > 20) {
|
|
145
|
+
await ctx.runMutation(api.logs.createProxyLog, {
|
|
146
|
+
workspaceId: identifier as any,
|
|
147
|
+
provider,
|
|
148
|
+
action,
|
|
149
|
+
subagentId,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// Increment workspace usage
|
|
153
|
+
await ctx.runMutation(api.workspaces.incrementUsage, {
|
|
154
|
+
workspaceId: identifier as any,
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
console.log("[Proxy] Workspace logged for:", identifier);
|
|
158
|
+
return { valid: true, workspaceId: identifier, subagentId };
|
|
159
|
+
}
|
|
160
|
+
} catch (e: any) {
|
|
161
|
+
console.error("[Proxy] Workspace logging failed:", e.message);
|
|
162
|
+
// Continue even if workspace logging fails
|
|
163
|
+
}
|
|
158
164
|
}
|
|
165
|
+
|
|
166
|
+
// Return success regardless (don't block API calls)
|
|
167
|
+
return { valid: true, subagentId };
|
|
159
168
|
}
|
|
160
169
|
|
|
161
170
|
// OPTIONS handler for CORS
|
|
@@ -1011,3 +1020,34 @@ http.route({
|
|
|
1011
1020
|
method: "OPTIONS",
|
|
1012
1021
|
handler: webhookOptions,
|
|
1013
1022
|
});
|
|
1023
|
+
|
|
1024
|
+
// Test endpoint to debug logging
|
|
1025
|
+
http.route({
|
|
1026
|
+
path: "/proxy/test-logging",
|
|
1027
|
+
method: "POST",
|
|
1028
|
+
handler: httpAction(async (ctx, request) => {
|
|
1029
|
+
const identifier = request.headers.get("X-APIClaw-Identifier");
|
|
1030
|
+
|
|
1031
|
+
try {
|
|
1032
|
+
const logId = await ctx.runMutation(api.analytics.log, {
|
|
1033
|
+
event: "test_endpoint",
|
|
1034
|
+
provider: "test",
|
|
1035
|
+
identifier: identifier || "test",
|
|
1036
|
+
metadata: { test: true },
|
|
1037
|
+
});
|
|
1038
|
+
|
|
1039
|
+
return jsonResponse({
|
|
1040
|
+
success: true,
|
|
1041
|
+
identifier,
|
|
1042
|
+
logId,
|
|
1043
|
+
message: "Logged successfully"
|
|
1044
|
+
});
|
|
1045
|
+
} catch (e: any) {
|
|
1046
|
+
return jsonResponse({
|
|
1047
|
+
success: false,
|
|
1048
|
+
error: e.message,
|
|
1049
|
+
stack: e.stack
|
|
1050
|
+
}, 500);
|
|
1051
|
+
}
|
|
1052
|
+
}),
|
|
1053
|
+
});
|
package/dist/proxy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAyB3E;AAED,eAAO,MAAM,eAAe,UAAkN,CAAC"}
|
package/dist/proxy.js
CHANGED
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* APIClaw Proxy - Fallback to hosted API when no local credentials
|
|
3
3
|
*/
|
|
4
|
-
|
|
4
|
+
import { readSession, getMachineFingerprint } from './session.js';
|
|
5
|
+
const PROXY_BASE = "https://brilliant-puffin-712.eu-west-1.convex.site/proxy";
|
|
5
6
|
export async function callProxy(provider, params) {
|
|
6
7
|
const url = `${PROXY_BASE}/${provider}`;
|
|
8
|
+
// Get session and fingerprint for tracking
|
|
9
|
+
const session = readSession();
|
|
10
|
+
const fingerprint = getMachineFingerprint();
|
|
11
|
+
const identifier = session?.workspaceId || `anon:${fingerprint}`;
|
|
7
12
|
const response = await fetch(url, {
|
|
8
13
|
method: "POST",
|
|
9
|
-
headers: {
|
|
14
|
+
headers: {
|
|
15
|
+
"Content-Type": "application/json",
|
|
16
|
+
"X-APIClaw-Identifier": identifier,
|
|
17
|
+
"X-APIClaw-Provider": provider,
|
|
18
|
+
"X-APIClaw-Action": params.action || "call",
|
|
19
|
+
},
|
|
10
20
|
body: JSON.stringify(params),
|
|
11
21
|
});
|
|
12
22
|
if (!response.ok) {
|
package/dist/proxy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,UAAU,GAAG,
|
|
1
|
+
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAElE,MAAM,UAAU,GAAG,0DAA0D,CAAC;AAE9E,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAAgB,EAAE,MAAW;IAC3D,MAAM,GAAG,GAAG,GAAG,UAAU,IAAI,QAAQ,EAAE,CAAC;IAExC,2CAA2C;IAC3C,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;IAC9B,MAAM,WAAW,GAAG,qBAAqB,EAAE,CAAC;IAC5C,MAAM,UAAU,GAAG,OAAO,EAAE,WAAW,IAAI,QAAQ,WAAW,EAAE,CAAC;IAEjE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAChC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,sBAAsB,EAAE,UAAU;YAClC,oBAAoB,EAAE,QAAQ;YAC9B,kBAAkB,EAAE,MAAM,CAAC,MAAM,IAAI,MAAM;SAC5C;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;KAC7B,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC,CAAuB,CAAC;QAC/G,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,KAAK,IAAI,gBAAgB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,YAAY,EAAE,cAAc,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC"}
|
|
@@ -26,8 +26,8 @@ export async function POST(req: NextRequest) {
|
|
|
26
26
|
method: "POST",
|
|
27
27
|
headers: { "Content-Type": "application/json" },
|
|
28
28
|
body: JSON.stringify({
|
|
29
|
-
path: "workspaces:
|
|
30
|
-
args: { token },
|
|
29
|
+
path: "workspaces:verifySession",
|
|
30
|
+
args: { sessionToken: token },
|
|
31
31
|
}),
|
|
32
32
|
});
|
|
33
33
|
|
package/landing/src/app/page.tsx
CHANGED
|
@@ -14,7 +14,7 @@ import { PhoneDemo } from "@/components/demo";
|
|
|
14
14
|
import { AITestimonials } from "@/components/AITestimonials";
|
|
15
15
|
|
|
16
16
|
const stats = [
|
|
17
|
-
{ number:
|
|
17
|
+
{ number: "4,232+", label: "Installs", live: true },
|
|
18
18
|
{ number: statsData.apiCount.toLocaleString(), label: "APIs Indexed", live: true },
|
|
19
19
|
{ number: statsData.openApiCount.toLocaleString(), label: "Open APIs", live: true },
|
|
20
20
|
{ number: statsData.directCallCount.toString(), label: "Direct Call", live: true },
|
|
@@ -5868,7 +5868,7 @@ function SettingsTab({ workspace, sessionToken }: { workspace: Workspace | null;
|
|
|
5868
5868
|
<p className="text-sm text-[var(--text-muted)]">Current subscription plan</p>
|
|
5869
5869
|
</div>
|
|
5870
5870
|
<span className="px-3 py-1 rounded-full bg-[#ef4444]/20 text-[#ef4444] text-sm font-medium capitalize">
|
|
5871
|
-
{workspace?.tier || "Free"}
|
|
5871
|
+
{workspace?.tier === "backer" ? "Founding Backer" : workspace?.tier === "pro" ? "Pro" : workspace?.tier === "usage_based" ? "Pay as you go" : workspace?.tier || "Free"}
|
|
5872
5872
|
</span>
|
|
5873
5873
|
</div>
|
|
5874
5874
|
</div>
|
|
@@ -5889,15 +5889,17 @@ function SettingsTab({ workspace, sessionToken }: { workspace: Workspace | null;
|
|
|
5889
5889
|
<div>
|
|
5890
5890
|
<p className="font-medium">Current Plan</p>
|
|
5891
5891
|
<p className="text-sm text-[var(--text-muted)]">
|
|
5892
|
-
{workspace?.tier === "pro" || workspace?.tier === "usage_based" ? "Usage-Based" : "Free Tier"}
|
|
5892
|
+
{workspace?.tier === "backer" ? "Unlimited until 2027" : workspace?.tier === "pro" || workspace?.tier === "usage_based" ? "Usage-Based" : "Free Tier"}
|
|
5893
5893
|
</p>
|
|
5894
5894
|
</div>
|
|
5895
5895
|
<span className={`px-3 py-1 rounded-full text-sm font-medium ${
|
|
5896
|
-
workspace?.tier === "
|
|
5896
|
+
workspace?.tier === "backer"
|
|
5897
|
+
? "bg-[#ef4444]/20 text-[#ef4444]"
|
|
5898
|
+
: workspace?.tier === "pro" || workspace?.tier === "usage_based"
|
|
5897
5899
|
? "bg-green-500/20 text-green-500"
|
|
5898
5900
|
: "bg-[var(--surface-elevated)] text-[var(--text-muted)]"
|
|
5899
5901
|
}`}>
|
|
5900
|
-
{workspace?.tier === "pro" || workspace?.tier === "usage_based" ? "Active" : "Free"}
|
|
5902
|
+
{workspace?.tier === "backer" ? "Active" : workspace?.tier === "pro" || workspace?.tier === "usage_based" ? "Active" : "Free"}
|
|
5901
5903
|
</span>
|
|
5902
5904
|
</div>
|
|
5903
5905
|
|
package/package.json
CHANGED
package/src/proxy.ts
CHANGED
|
@@ -2,14 +2,26 @@
|
|
|
2
2
|
* APIClaw Proxy - Fallback to hosted API when no local credentials
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
import { readSession, getMachineFingerprint } from './session.js';
|
|
6
|
+
|
|
7
|
+
const PROXY_BASE = "https://brilliant-puffin-712.eu-west-1.convex.site/proxy";
|
|
6
8
|
|
|
7
9
|
export async function callProxy(provider: string, params: any): Promise<any> {
|
|
8
10
|
const url = `${PROXY_BASE}/${provider}`;
|
|
9
11
|
|
|
12
|
+
// Get session and fingerprint for tracking
|
|
13
|
+
const session = readSession();
|
|
14
|
+
const fingerprint = getMachineFingerprint();
|
|
15
|
+
const identifier = session?.workspaceId || `anon:${fingerprint}`;
|
|
16
|
+
|
|
10
17
|
const response = await fetch(url, {
|
|
11
18
|
method: "POST",
|
|
12
|
-
headers: {
|
|
19
|
+
headers: {
|
|
20
|
+
"Content-Type": "application/json",
|
|
21
|
+
"X-APIClaw-Identifier": identifier,
|
|
22
|
+
"X-APIClaw-Provider": provider,
|
|
23
|
+
"X-APIClaw-Action": params.action || "call",
|
|
24
|
+
},
|
|
13
25
|
body: JSON.stringify(params),
|
|
14
26
|
});
|
|
15
27
|
|