@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 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 sessionToken = request.headers.get("X-APIClaw-Session");
122
- const subagentId = request.headers.get("X-APIClaw-Subagent") || "unknown";
121
+ const identifier = request.headers.get("X-APIClaw-Identifier");
122
+ const subagentId = request.headers.get("X-APIClaw-Subagent") || "main";
123
123
 
124
- if (!sessionToken) {
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
- // Validate session
131
- const session = await ctx.runQuery(api.workspaces.getSession, { token: sessionToken });
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
- action,
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] Session validation error:", e);
156
- // Allow call but don't log on error
157
- return { valid: true, subagentId };
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
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAe3E;AAED,eAAO,MAAM,eAAe,UAAkN,CAAC"}
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
- const PROXY_BASE = "https://adventurous-avocet-799.convex.site/proxy";
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: { "Content-Type": "application/json" },
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,kDAAkD,CAAC;AAEtE,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAAgB,EAAE,MAAW;IAC3D,MAAM,GAAG,GAAG,GAAG,UAAU,IAAI,QAAQ,EAAE,CAAC;IAExC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAChC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,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"}
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:getSessionWorkspace",
30
- args: { token },
29
+ path: "workspaces:verifySession",
30
+ args: { sessionToken: token },
31
31
  }),
32
32
  });
33
33
 
@@ -14,7 +14,7 @@ import { PhoneDemo } from "@/components/demo";
14
14
  import { AITestimonials } from "@/components/AITestimonials";
15
15
 
16
16
  const stats = [
17
- { number: ((statsData as any).npmDownloads || 3000).toLocaleString() + "+", label: "Installs", live: true },
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 === "pro" || workspace?.tier === "usage_based"
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
 
@@ -3,7 +3,7 @@
3
3
  "openApiCount": 1636,
4
4
  "directCallCount": 18,
5
5
  "categoryCount": 13,
6
- "npmDownloads": 3396,
6
+ "npmDownloads": 4232,
7
7
  "lastUpdated": "2026-02-27T09:10:41.344767",
8
8
  "generatedAt": "2026-03-05T09:30:00.000Z",
9
9
  "categoryBreakdown": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nordsym/apiclaw",
3
- "version": "1.5.1",
3
+ "version": "1.5.3",
4
4
  "description": "The API layer for AI agents. Dashboard + 22K APIs + 18 Direct Call providers. MCP native.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
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
- const PROXY_BASE = "https://adventurous-avocet-799.convex.site/proxy";
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: { "Content-Type": "application/json" },
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