@@ -24,2 +24,4 @@ export interface DaemonLaunchOptions { | ||
| verifiedOnly?: boolean; | ||
| /** Email inbox opt-in (webhook only): <subdomain>@<domain> → the feed. */ | ||
| email?: boolean; | ||
| /** Config profile name (`otterkit up`). */ | ||
@@ -39,2 +41,4 @@ profile?: string; | ||
| auth: boolean; | ||
| /** Present when the endpoint provisioned with an email inbox. */ | ||
| emailAddress?: string; | ||
| profile?: string; | ||
@@ -41,0 +45,0 @@ } |
@@ -19,3 +19,3 @@ /** | ||
| const ttlMs = parseTtlMs(ttl); // validate before spending a credit; null = never | ||
| const { subdomain, publicUrl, connectUrl } = await provisionDaemonTunnel(ttl, options.subdomain, mode); | ||
| const { subdomain, publicUrl, connectUrl, emailAddress } = await provisionDaemonTunnel(ttl, options.subdomain, mode, mode === 'webhook' && options.email === true); | ||
| const startedAt = new Date().toISOString(); | ||
@@ -99,4 +99,5 @@ const expiresAt = ttlMs === null ? 'never' : new Date(Date.now() + ttlMs).toISOString(); | ||
| auth: Boolean(options.auth), | ||
| emailAddress, | ||
| profile: options.profile, | ||
| }; | ||
| } |
+0
-26
@@ -53,29 +53,3 @@ export interface StoredRequest { | ||
| }>; | ||
| export interface SchemaInferResult { | ||
| subdomain: string; | ||
| analyzed: number; | ||
| skipped: { | ||
| nonJson: number; | ||
| binary: number; | ||
| empty: number; | ||
| truncated: number; | ||
| overBudget: number; | ||
| }; | ||
| groups: { | ||
| path: string; | ||
| discriminator?: string; | ||
| discriminatorValue?: string; | ||
| count: number; | ||
| name: string; | ||
| jsonSchema: unknown; | ||
| typescript: string; | ||
| }[]; | ||
| } | ||
| /** | ||
| * Infer JSON Schema + TypeScript types from a session's stored request | ||
| * bodies. Same token-authed surface and error mapping as fetchHistory; the | ||
| * inference runs server-side over the stored history. | ||
| */ | ||
| export declare function fetchSchema(subdomain: string, filters?: Omit<HistoryFilters, 'before'>): Promise<SchemaInferResult>; | ||
| /** | ||
| * Toggle email-on-arrival for a webhook session the account owns. Same | ||
@@ -82,0 +56,0 @@ * token-authed API surface as fetchHistory; the throttling (1 email/15min, |
+0
-29
@@ -72,31 +72,2 @@ /** | ||
| /** | ||
| * Infer JSON Schema + TypeScript types from a session's stored request | ||
| * bodies. Same token-authed surface and error mapping as fetchHistory; the | ||
| * inference runs server-side over the stored history. | ||
| */ | ||
| export async function fetchSchema(subdomain, filters = {}) { | ||
| const token = getToken(); | ||
| if (!token) | ||
| throw new HistoryError('not_logged_in', 'Run `otterkit login` first.'); | ||
| const params = new URLSearchParams(); | ||
| if (filters.limit) | ||
| params.set('limit', String(filters.limit)); | ||
| if (filters.method) | ||
| params.set('method', filters.method); | ||
| if (filters.path) | ||
| params.set('q', filters.path); | ||
| const qs = params.toString(); | ||
| const resp = await fetch(`${API_SERVER}/api/me/webhooks/${encodeURIComponent(subdomain)}/schema${qs ? `?${qs}` : ''}`, { headers: { Authorization: `Bearer ${token}` } }); | ||
| const json = (await resp.json().catch(() => ({}))); | ||
| if (resp.status === 401) | ||
| throw new HistoryError('invalid_token', 'Run `otterkit login` again.'); | ||
| if (resp.status === 404) { | ||
| throw new HistoryError('not_found', `No webhook session "${subdomain}" on this account. Only console (cloud) endpoints store history server-side.`); | ||
| } | ||
| if (!resp.ok || !json.data) { | ||
| throw new HistoryError(json.error ?? `schema_infer_failed_${resp.status}`); | ||
| } | ||
| return json.data; | ||
| } | ||
| /** | ||
| * Toggle email-on-arrival for a webhook session the account owns. Same | ||
@@ -103,0 +74,0 @@ * token-authed API surface as fetchHistory; the throttling (1 email/15min, |
+6
-32
@@ -30,3 +30,3 @@ /** | ||
| import { createWait, listWaits, cancelWait, sessionToken } from './waits.js'; | ||
| import { fetchHistory, fetchSchema, replayStored } from './history.js'; | ||
| import { fetchHistory, replayStored } from './history.js'; | ||
| const { version } = createRequire(import.meta.url)('../package.json'); | ||
@@ -131,2 +131,6 @@ const API_SERVER = process.env.OTTERKIT_API_URL || 'https://api.otterkit.com'; | ||
| .describe('Auto-response body (default {"received":true})'), | ||
| email: z | ||
| .boolean() | ||
| .optional() | ||
| .describe('Give the endpoint an email inbox: mail to <subdomain>@otterkit.app lands in the capture feed as a request with method EMAIL (JSON body: from/subject/text/html) - awaitable with request_await'), | ||
| verify: z | ||
@@ -173,2 +177,3 @@ .object({ | ||
| verify: args.verify, | ||
| email: args.email, | ||
| }); | ||
@@ -623,33 +628,2 @@ return ok({ ...info, logPath: getLogPath(info.subdomain) }); | ||
| }); | ||
| server.registerTool('schema_infer', { | ||
| title: 'Infer request types from stored history', | ||
| description: 'Generate JSON Schema (draft-07) and TypeScript types from the request bodies OtterKit ' + | ||
| 'stored server-side for a webhook endpoint - "what does this provider actually send". ' + | ||
| 'Groups by path (and by a detected event field like type/event), reports field ' + | ||
| 'optionality as present-in-N/M counts. Needs stored history: console (cloud) ' + | ||
| 'endpoints only - CLI webhook captures stay on the machine.', | ||
| inputSchema: { | ||
| subdomain: z.string().describe('Webhook endpoint whose stored bodies to analyze'), | ||
| limit: z | ||
| .number() | ||
| .int() | ||
| .min(1) | ||
| .max(1000) | ||
| .optional() | ||
| .describe('Analyze up to N newest requests (default 500)'), | ||
| method: z.string().optional().describe('Only this HTTP method'), | ||
| path: z.string().optional().describe('Only paths containing this substring'), | ||
| }, | ||
| }, async (args) => { | ||
| try { | ||
| return ok(await fetchSchema(args.subdomain, { | ||
| limit: args.limit, | ||
| method: args.method, | ||
| path: args.path, | ||
| })); | ||
| } | ||
| catch (e) { | ||
| return mapError(e); | ||
| } | ||
| }); | ||
| server.registerTool('account_status', { | ||
@@ -656,0 +630,0 @@ title: 'Account and credit balance', |
@@ -19,2 +19,4 @@ declare const TUNNEL_SERVER: string; | ||
| connectUrl: string; | ||
| /** Present when the endpoint provisioned with an email inbox (--email). */ | ||
| emailAddress?: string; | ||
| } | ||
@@ -31,3 +33,3 @@ interface DaemonProvisionResult extends ProvisionResult { | ||
| export declare function getBackendName(): string; | ||
| export declare function provisionTunnel(subdomain?: string, kind?: 'tunnel' | 'webhook', ttl?: string): Promise<ProvisionResult>; | ||
| export declare function provisionTunnel(subdomain?: string, kind?: 'tunnel' | 'webhook', ttl?: string, email?: boolean): Promise<ProvisionResult>; | ||
| /** A request captured on the /try page before the session was claimed. */ | ||
@@ -51,3 +53,3 @@ export interface ClaimedRequest { | ||
| export declare function claimTrySession(code: string, ttl?: string): Promise<ClaimResult>; | ||
| export declare function provisionDaemonTunnel(ttl: string, subdomain?: string, kind?: 'tunnel' | 'webhook'): Promise<DaemonProvisionResult>; | ||
| export declare function provisionDaemonTunnel(ttl: string, subdomain?: string, kind?: 'tunnel' | 'webhook', email?: boolean): Promise<DaemonProvisionResult>; | ||
| export { TUNNEL_SERVER }; |
@@ -42,3 +42,3 @@ /** | ||
| } | ||
| async function provision(url, subdomain, kind, ttl) { | ||
| async function provision(url, subdomain, kind, ttl, email) { | ||
| const token = getToken(); | ||
@@ -57,2 +57,5 @@ if (!token) | ||
| target.searchParams.set('ttl', ttl); | ||
| // Email inbox opt-in (webhook endpoints): <subdomain>@<domain> → the feed. | ||
| if (email) | ||
| target.searchParams.set('email', '1'); | ||
| const response = await fetch(target.toString(), { | ||
@@ -94,4 +97,4 @@ method: 'POST', | ||
| } | ||
| export async function provisionTunnel(subdomain, kind = 'tunnel', ttl) { | ||
| return (await provision(`${TUNNEL_SERVER}/api/agent/tunnels`, subdomain, kind, ttl)); | ||
| export async function provisionTunnel(subdomain, kind = 'tunnel', ttl, email) { | ||
| return (await provision(`${TUNNEL_SERVER}/api/agent/tunnels`, subdomain, kind, ttl, email)); | ||
| } | ||
@@ -131,5 +134,5 @@ /** | ||
| } | ||
| export async function provisionDaemonTunnel(ttl, subdomain, kind = 'tunnel') { | ||
| return (await provision(`${TUNNEL_SERVER}/api/agent/tunnels/daemon?ttl=${ttl}`, subdomain, kind)); | ||
| export async function provisionDaemonTunnel(ttl, subdomain, kind = 'tunnel', email) { | ||
| return (await provision(`${TUNNEL_SERVER}/api/agent/tunnels/daemon?ttl=${ttl}`, subdomain, kind, undefined, email)); | ||
| } | ||
| export { TUNNEL_SERVER }; |
+1
-1
| { | ||
| "name": "otterkit", | ||
| "version": "0.40.0", | ||
| "version": "0.41.0", | ||
| "description": "OtterKit CLI - provision and connect tunnels for AI agents", | ||
@@ -5,0 +5,0 @@ "mcpName": "io.github.useotterkit/otterkit", |
Sorry, the diff of this file is too big to display
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
26
-3.7%292358
-0.57%6785
-0.82%31
3.33%