@clawcash/forge 0.1.5 → 0.1.8
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 +15 -2
- package/dist/index.cjs +265 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +121 -6
- package/dist/index.d.ts +121 -6
- package/dist/index.js +257 -15
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -72,14 +72,19 @@ interface MountOptions {
|
|
|
72
72
|
/** Skip x402 (local dev only). Defaults to false. */
|
|
73
73
|
skipPayment?: boolean;
|
|
74
74
|
/**
|
|
75
|
-
*
|
|
76
|
-
*
|
|
75
|
+
* Gateway heartbeat after mount. Only FORGE_API_KEY is required as env;
|
|
76
|
+
* the URL defaults to the ClawCash gateway, the handle is baked by Forge
|
|
77
|
+
* codegen, and the public base URL is resolved from platform vars or
|
|
78
|
+
* inferred (self-verified) from the first inbound probe.
|
|
77
79
|
*/
|
|
78
80
|
gateway?: {
|
|
81
|
+
/** Defaults to https://gateway.clawca.sh (or GATEWAY_URL env). */
|
|
79
82
|
url?: string;
|
|
83
|
+
/** Merchant handle — baked by Forge codegen (or FORGE_HANDLE env). */
|
|
80
84
|
handle?: string;
|
|
85
|
+
/** @deprecated Prefer FORGE_API_KEY env — per-project key from Forge dashboard. */
|
|
81
86
|
registerSecret?: string;
|
|
82
|
-
/** Merchant public base URL
|
|
87
|
+
/** Merchant public base URL. Usually omitted — resolved automatically. */
|
|
83
88
|
publicBaseUrl?: string;
|
|
84
89
|
};
|
|
85
90
|
/**
|
|
@@ -103,6 +108,7 @@ declare function defineAgentService<TInput extends Record<string, unknown> = Rec
|
|
|
103
108
|
|
|
104
109
|
/**
|
|
105
110
|
* Mount Forge agent services on an Express app.
|
|
111
|
+
* - GET /forge/health, GET /forge/status, GET /.well-known/clawcash.json — liveliness
|
|
106
112
|
* - POST {basePath}/{kebab-name} — optional public x402 agent surface
|
|
107
113
|
* - POST /forge/fulfill/{kebab-name} — private gateway fulfillment after payment
|
|
108
114
|
*
|
|
@@ -133,6 +139,42 @@ declare function resolvePayTo(opts: {
|
|
|
133
139
|
timeoutMs?: number;
|
|
134
140
|
}): Promise<string>;
|
|
135
141
|
|
|
142
|
+
/**
|
|
143
|
+
* Public base URL resolution, in trust order:
|
|
144
|
+
* 1. PUBLIC_BASE_URL env — explicit override.
|
|
145
|
+
* 2. Platform-provided vars (Railway, Render, Vercel, Fly, Heroku) — set by
|
|
146
|
+
* the host, not by request input, so safe to trust as-is.
|
|
147
|
+
* 3. Lazy inference from the first inbound request to the Forge surface
|
|
148
|
+
* (X-Forwarded-Proto + Host). Host is attacker-controlled, so a candidate
|
|
149
|
+
* is only accepted after self-verification: we fetch our own
|
|
150
|
+
* /forge/health at the candidate URL and check it returns this
|
|
151
|
+
* instance's boot nonce.
|
|
152
|
+
*/
|
|
153
|
+
declare function resolveBaseUrlFromEnv(explicit?: string): string | null;
|
|
154
|
+
declare class PublicBaseUrlResolver {
|
|
155
|
+
/** Per-boot nonce, echoed by /forge/health for self-verification. */
|
|
156
|
+
readonly instanceNonce: string;
|
|
157
|
+
private resolved;
|
|
158
|
+
private verifying;
|
|
159
|
+
private rejected;
|
|
160
|
+
private attempts;
|
|
161
|
+
private onResolved;
|
|
162
|
+
constructor(opts: {
|
|
163
|
+
/** URL already known from env/platform vars (trusted, no verification). */
|
|
164
|
+
initial: string | null;
|
|
165
|
+
/** Called once when a base URL first becomes known via inference. */
|
|
166
|
+
onResolved?: (baseUrl: string) => void;
|
|
167
|
+
});
|
|
168
|
+
get(): string | null;
|
|
169
|
+
/**
|
|
170
|
+
* Feed an inbound Forge-surface request. No-op once resolved. Kicks off
|
|
171
|
+
* async self-verification of the candidate URL derived from the request.
|
|
172
|
+
*/
|
|
173
|
+
considerRequest(req: Request): void;
|
|
174
|
+
/** Fetch our own /forge/health at the candidate and match the boot nonce. */
|
|
175
|
+
private verify;
|
|
176
|
+
}
|
|
177
|
+
|
|
136
178
|
/**
|
|
137
179
|
* Notify ClawCash gateway of this merchant's live public base URL.
|
|
138
180
|
* Full action registration still happens from Forge "Go live".
|
|
@@ -145,9 +187,82 @@ declare function heartbeatGateway(opts: {
|
|
|
145
187
|
}): Promise<void>;
|
|
146
188
|
|
|
147
189
|
/**
|
|
148
|
-
*
|
|
149
|
-
|
|
190
|
+
* Merchant-side Forge surface status — public probes for deploy / go-live checks.
|
|
191
|
+
*/
|
|
192
|
+
type ForgeHeartbeatState = {
|
|
193
|
+
attempted: boolean;
|
|
194
|
+
ok: boolean | null;
|
|
195
|
+
at: string | null;
|
|
196
|
+
error: string | null;
|
|
197
|
+
};
|
|
198
|
+
type ForgeSurfaceStatus = {
|
|
199
|
+
ok: boolean;
|
|
200
|
+
forge: true;
|
|
201
|
+
version: string;
|
|
202
|
+
handle: string | null;
|
|
203
|
+
publicBaseUrl: string | null;
|
|
204
|
+
gatewayUrl: string | null;
|
|
205
|
+
/** True when FORGE_API_KEY is set so /forge/fulfill is mounted. */
|
|
206
|
+
fulfillMounted: boolean;
|
|
207
|
+
fulfillPath: string;
|
|
208
|
+
agentBasePath: string;
|
|
209
|
+
skipPayment: boolean;
|
|
210
|
+
actions: Array<{
|
|
211
|
+
name: string;
|
|
212
|
+
path: string;
|
|
213
|
+
price: string;
|
|
214
|
+
}>;
|
|
215
|
+
/** Env + fulfill ready — merchant can accept gateway fulfillment. */
|
|
216
|
+
ready: boolean;
|
|
217
|
+
heartbeat: ForgeHeartbeatState;
|
|
218
|
+
endpoints: {
|
|
219
|
+
health: string;
|
|
220
|
+
status: string;
|
|
221
|
+
wellKnown: string;
|
|
222
|
+
fulfill: string;
|
|
223
|
+
agent: string;
|
|
224
|
+
};
|
|
225
|
+
};
|
|
226
|
+
declare function recordHeartbeatResult(result: {
|
|
227
|
+
ok: true;
|
|
228
|
+
} | {
|
|
229
|
+
ok: false;
|
|
230
|
+
error: string;
|
|
231
|
+
}): void;
|
|
232
|
+
declare function getLastHeartbeat(): ForgeHeartbeatState;
|
|
233
|
+
declare function buildForgeSurfaceStatus(opts: {
|
|
234
|
+
handle: string | null;
|
|
235
|
+
publicBaseUrl: string | null;
|
|
236
|
+
gatewayUrl: string | null;
|
|
237
|
+
fulfillMounted: boolean;
|
|
238
|
+
fulfillPath: string;
|
|
239
|
+
agentBasePath: string;
|
|
240
|
+
skipPayment: boolean;
|
|
241
|
+
actions: Array<{
|
|
242
|
+
name: string;
|
|
243
|
+
path: string;
|
|
244
|
+
price: string;
|
|
245
|
+
}>;
|
|
246
|
+
}): ForgeSurfaceStatus;
|
|
247
|
+
declare function buildWellKnownDocument(status: ForgeSurfaceStatus): {
|
|
248
|
+
forge: true;
|
|
249
|
+
version: string;
|
|
250
|
+
health: string;
|
|
251
|
+
status: string;
|
|
252
|
+
handle: string | null;
|
|
253
|
+
ready: boolean;
|
|
254
|
+
};
|
|
255
|
+
declare function forgeSdkVersion(): string;
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Per-project Forge API key for gateway → merchant fulfillment.
|
|
259
|
+
* Merchants set FORGE_API_KEY from the Forge dashboard (never the shared
|
|
260
|
+
* GATEWAY_REGISTER_SECRET — that is Forge↔gateway platform auth only).
|
|
261
|
+
*
|
|
262
|
+
* GATEWAY_REGISTER_SECRET is accepted as a deprecated fallback for older deploys.
|
|
150
263
|
*/
|
|
264
|
+
declare function getForgeApiKey(explicit?: string | null): string | null;
|
|
265
|
+
/** @deprecated Use getForgeApiKey */
|
|
151
266
|
declare function getForgeGatewaySecret(explicit?: string | null): string | null;
|
|
152
267
|
declare function isForgeGatewayRequest(req: Request, secret?: string | null): boolean;
|
|
153
268
|
/** Synthetic user id for DB rows created by gateway-driven fulfillment. */
|
|
@@ -156,4 +271,4 @@ declare function requireForgeGateway(secret?: string | null): (req: Request, res
|
|
|
156
271
|
/** Headers merchant execute() should send on loopback calls during fulfillment. */
|
|
157
272
|
declare function forgeGatewayLoopbackHeaders(secret?: string | null): Record<string, string>;
|
|
158
273
|
|
|
159
|
-
export { type AgentServiceConfig, type AgentServiceContext, type DefinedAgentService, FORGE_GATEWAY_USER_ID, type ForgePayToSource, type InputSchema, type MountOptions, type OutputSchema, type PaymentConfig, type SchemaFieldType, type SkillMeta, type WaitUntilOptions, createContext, createForgeRouter, defineAgentService, forgeGatewayLoopbackHeaders, generateSkillMarkdown, getForgeGatewaySecret, heartbeatGateway, isForgeGatewayRequest, isZeroAddress, mountAgentServices, requireForgeGateway, resolvePayTo, toKebabCase, waitUntil };
|
|
274
|
+
export { type AgentServiceConfig, type AgentServiceContext, type DefinedAgentService, FORGE_GATEWAY_USER_ID, type ForgeHeartbeatState, type ForgePayToSource, type ForgeSurfaceStatus, type InputSchema, type MountOptions, type OutputSchema, type PaymentConfig, PublicBaseUrlResolver, type SchemaFieldType, type SkillMeta, type WaitUntilOptions, buildForgeSurfaceStatus, buildWellKnownDocument, createContext, createForgeRouter, defineAgentService, forgeGatewayLoopbackHeaders, forgeSdkVersion, generateSkillMarkdown, getForgeApiKey, getForgeGatewaySecret, getLastHeartbeat, heartbeatGateway, isForgeGatewayRequest, isZeroAddress, mountAgentServices, recordHeartbeatResult, requireForgeGateway, resolveBaseUrlFromEnv, resolvePayTo, toKebabCase, waitUntil };
|
package/dist/index.d.ts
CHANGED
|
@@ -72,14 +72,19 @@ interface MountOptions {
|
|
|
72
72
|
/** Skip x402 (local dev only). Defaults to false. */
|
|
73
73
|
skipPayment?: boolean;
|
|
74
74
|
/**
|
|
75
|
-
*
|
|
76
|
-
*
|
|
75
|
+
* Gateway heartbeat after mount. Only FORGE_API_KEY is required as env;
|
|
76
|
+
* the URL defaults to the ClawCash gateway, the handle is baked by Forge
|
|
77
|
+
* codegen, and the public base URL is resolved from platform vars or
|
|
78
|
+
* inferred (self-verified) from the first inbound probe.
|
|
77
79
|
*/
|
|
78
80
|
gateway?: {
|
|
81
|
+
/** Defaults to https://gateway.clawca.sh (or GATEWAY_URL env). */
|
|
79
82
|
url?: string;
|
|
83
|
+
/** Merchant handle — baked by Forge codegen (or FORGE_HANDLE env). */
|
|
80
84
|
handle?: string;
|
|
85
|
+
/** @deprecated Prefer FORGE_API_KEY env — per-project key from Forge dashboard. */
|
|
81
86
|
registerSecret?: string;
|
|
82
|
-
/** Merchant public base URL
|
|
87
|
+
/** Merchant public base URL. Usually omitted — resolved automatically. */
|
|
83
88
|
publicBaseUrl?: string;
|
|
84
89
|
};
|
|
85
90
|
/**
|
|
@@ -103,6 +108,7 @@ declare function defineAgentService<TInput extends Record<string, unknown> = Rec
|
|
|
103
108
|
|
|
104
109
|
/**
|
|
105
110
|
* Mount Forge agent services on an Express app.
|
|
111
|
+
* - GET /forge/health, GET /forge/status, GET /.well-known/clawcash.json — liveliness
|
|
106
112
|
* - POST {basePath}/{kebab-name} — optional public x402 agent surface
|
|
107
113
|
* - POST /forge/fulfill/{kebab-name} — private gateway fulfillment after payment
|
|
108
114
|
*
|
|
@@ -133,6 +139,42 @@ declare function resolvePayTo(opts: {
|
|
|
133
139
|
timeoutMs?: number;
|
|
134
140
|
}): Promise<string>;
|
|
135
141
|
|
|
142
|
+
/**
|
|
143
|
+
* Public base URL resolution, in trust order:
|
|
144
|
+
* 1. PUBLIC_BASE_URL env — explicit override.
|
|
145
|
+
* 2. Platform-provided vars (Railway, Render, Vercel, Fly, Heroku) — set by
|
|
146
|
+
* the host, not by request input, so safe to trust as-is.
|
|
147
|
+
* 3. Lazy inference from the first inbound request to the Forge surface
|
|
148
|
+
* (X-Forwarded-Proto + Host). Host is attacker-controlled, so a candidate
|
|
149
|
+
* is only accepted after self-verification: we fetch our own
|
|
150
|
+
* /forge/health at the candidate URL and check it returns this
|
|
151
|
+
* instance's boot nonce.
|
|
152
|
+
*/
|
|
153
|
+
declare function resolveBaseUrlFromEnv(explicit?: string): string | null;
|
|
154
|
+
declare class PublicBaseUrlResolver {
|
|
155
|
+
/** Per-boot nonce, echoed by /forge/health for self-verification. */
|
|
156
|
+
readonly instanceNonce: string;
|
|
157
|
+
private resolved;
|
|
158
|
+
private verifying;
|
|
159
|
+
private rejected;
|
|
160
|
+
private attempts;
|
|
161
|
+
private onResolved;
|
|
162
|
+
constructor(opts: {
|
|
163
|
+
/** URL already known from env/platform vars (trusted, no verification). */
|
|
164
|
+
initial: string | null;
|
|
165
|
+
/** Called once when a base URL first becomes known via inference. */
|
|
166
|
+
onResolved?: (baseUrl: string) => void;
|
|
167
|
+
});
|
|
168
|
+
get(): string | null;
|
|
169
|
+
/**
|
|
170
|
+
* Feed an inbound Forge-surface request. No-op once resolved. Kicks off
|
|
171
|
+
* async self-verification of the candidate URL derived from the request.
|
|
172
|
+
*/
|
|
173
|
+
considerRequest(req: Request): void;
|
|
174
|
+
/** Fetch our own /forge/health at the candidate and match the boot nonce. */
|
|
175
|
+
private verify;
|
|
176
|
+
}
|
|
177
|
+
|
|
136
178
|
/**
|
|
137
179
|
* Notify ClawCash gateway of this merchant's live public base URL.
|
|
138
180
|
* Full action registration still happens from Forge "Go live".
|
|
@@ -145,9 +187,82 @@ declare function heartbeatGateway(opts: {
|
|
|
145
187
|
}): Promise<void>;
|
|
146
188
|
|
|
147
189
|
/**
|
|
148
|
-
*
|
|
149
|
-
|
|
190
|
+
* Merchant-side Forge surface status — public probes for deploy / go-live checks.
|
|
191
|
+
*/
|
|
192
|
+
type ForgeHeartbeatState = {
|
|
193
|
+
attempted: boolean;
|
|
194
|
+
ok: boolean | null;
|
|
195
|
+
at: string | null;
|
|
196
|
+
error: string | null;
|
|
197
|
+
};
|
|
198
|
+
type ForgeSurfaceStatus = {
|
|
199
|
+
ok: boolean;
|
|
200
|
+
forge: true;
|
|
201
|
+
version: string;
|
|
202
|
+
handle: string | null;
|
|
203
|
+
publicBaseUrl: string | null;
|
|
204
|
+
gatewayUrl: string | null;
|
|
205
|
+
/** True when FORGE_API_KEY is set so /forge/fulfill is mounted. */
|
|
206
|
+
fulfillMounted: boolean;
|
|
207
|
+
fulfillPath: string;
|
|
208
|
+
agentBasePath: string;
|
|
209
|
+
skipPayment: boolean;
|
|
210
|
+
actions: Array<{
|
|
211
|
+
name: string;
|
|
212
|
+
path: string;
|
|
213
|
+
price: string;
|
|
214
|
+
}>;
|
|
215
|
+
/** Env + fulfill ready — merchant can accept gateway fulfillment. */
|
|
216
|
+
ready: boolean;
|
|
217
|
+
heartbeat: ForgeHeartbeatState;
|
|
218
|
+
endpoints: {
|
|
219
|
+
health: string;
|
|
220
|
+
status: string;
|
|
221
|
+
wellKnown: string;
|
|
222
|
+
fulfill: string;
|
|
223
|
+
agent: string;
|
|
224
|
+
};
|
|
225
|
+
};
|
|
226
|
+
declare function recordHeartbeatResult(result: {
|
|
227
|
+
ok: true;
|
|
228
|
+
} | {
|
|
229
|
+
ok: false;
|
|
230
|
+
error: string;
|
|
231
|
+
}): void;
|
|
232
|
+
declare function getLastHeartbeat(): ForgeHeartbeatState;
|
|
233
|
+
declare function buildForgeSurfaceStatus(opts: {
|
|
234
|
+
handle: string | null;
|
|
235
|
+
publicBaseUrl: string | null;
|
|
236
|
+
gatewayUrl: string | null;
|
|
237
|
+
fulfillMounted: boolean;
|
|
238
|
+
fulfillPath: string;
|
|
239
|
+
agentBasePath: string;
|
|
240
|
+
skipPayment: boolean;
|
|
241
|
+
actions: Array<{
|
|
242
|
+
name: string;
|
|
243
|
+
path: string;
|
|
244
|
+
price: string;
|
|
245
|
+
}>;
|
|
246
|
+
}): ForgeSurfaceStatus;
|
|
247
|
+
declare function buildWellKnownDocument(status: ForgeSurfaceStatus): {
|
|
248
|
+
forge: true;
|
|
249
|
+
version: string;
|
|
250
|
+
health: string;
|
|
251
|
+
status: string;
|
|
252
|
+
handle: string | null;
|
|
253
|
+
ready: boolean;
|
|
254
|
+
};
|
|
255
|
+
declare function forgeSdkVersion(): string;
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Per-project Forge API key for gateway → merchant fulfillment.
|
|
259
|
+
* Merchants set FORGE_API_KEY from the Forge dashboard (never the shared
|
|
260
|
+
* GATEWAY_REGISTER_SECRET — that is Forge↔gateway platform auth only).
|
|
261
|
+
*
|
|
262
|
+
* GATEWAY_REGISTER_SECRET is accepted as a deprecated fallback for older deploys.
|
|
150
263
|
*/
|
|
264
|
+
declare function getForgeApiKey(explicit?: string | null): string | null;
|
|
265
|
+
/** @deprecated Use getForgeApiKey */
|
|
151
266
|
declare function getForgeGatewaySecret(explicit?: string | null): string | null;
|
|
152
267
|
declare function isForgeGatewayRequest(req: Request, secret?: string | null): boolean;
|
|
153
268
|
/** Synthetic user id for DB rows created by gateway-driven fulfillment. */
|
|
@@ -156,4 +271,4 @@ declare function requireForgeGateway(secret?: string | null): (req: Request, res
|
|
|
156
271
|
/** Headers merchant execute() should send on loopback calls during fulfillment. */
|
|
157
272
|
declare function forgeGatewayLoopbackHeaders(secret?: string | null): Record<string, string>;
|
|
158
273
|
|
|
159
|
-
export { type AgentServiceConfig, type AgentServiceContext, type DefinedAgentService, FORGE_GATEWAY_USER_ID, type ForgePayToSource, type InputSchema, type MountOptions, type OutputSchema, type PaymentConfig, type SchemaFieldType, type SkillMeta, type WaitUntilOptions, createContext, createForgeRouter, defineAgentService, forgeGatewayLoopbackHeaders, generateSkillMarkdown, getForgeGatewaySecret, heartbeatGateway, isForgeGatewayRequest, isZeroAddress, mountAgentServices, requireForgeGateway, resolvePayTo, toKebabCase, waitUntil };
|
|
274
|
+
export { type AgentServiceConfig, type AgentServiceContext, type DefinedAgentService, FORGE_GATEWAY_USER_ID, type ForgeHeartbeatState, type ForgePayToSource, type ForgeSurfaceStatus, type InputSchema, type MountOptions, type OutputSchema, type PaymentConfig, PublicBaseUrlResolver, type SchemaFieldType, type SkillMeta, type WaitUntilOptions, buildForgeSurfaceStatus, buildWellKnownDocument, createContext, createForgeRouter, defineAgentService, forgeGatewayLoopbackHeaders, forgeSdkVersion, generateSkillMarkdown, getForgeApiKey, getForgeGatewaySecret, getLastHeartbeat, heartbeatGateway, isForgeGatewayRequest, isZeroAddress, mountAgentServices, recordHeartbeatResult, requireForgeGateway, resolveBaseUrlFromEnv, resolvePayTo, toKebabCase, waitUntil };
|