🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

otterkit

Package Overview
Dependencies
Maintainers
1
Versions
41
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

otterkit - npm Package Compare versions

Comparing version
0.34.0
to
0.35.0
+34
dist/pulse.d.ts
export interface PulseOptions {
interval?: string;
url?: string;
expect?: string;
method?: string;
headers?: Record<string, string>;
body?: string;
ttl?: string;
subdomain?: string;
}
export interface PulseResult {
subdomain: string;
publicUrl: string;
mode: 'active' | 'expect';
intervalMs: number;
target?: string;
method?: string;
autoStopAt: string | null;
stopToken: string;
pricing: {
runsPerCredit: number;
monthlyCapCredits: number;
note: string;
};
cost: number;
balance: number;
}
export declare class PulseError extends Error {
code: string;
constructor(code: string, message?: string);
}
export declare function createPulse(opts: PulseOptions): Promise<PulseResult>;
/** Stop a pulse with the stopToken returned at creation. */
export declare function stopPulse(subdomain: string, stopToken: string): Promise<void>;
/**
* `otterkit pulse` - the third primitive: scheduled, stateful HTTP.
* Active mode calls a URL on an interval and stores every run server-side;
* expect mode is a dead-man's switch that alerts when check-ins stop.
* Fully server-side (no daemon): the CLI provisions and walks away.
*/
import { getToken } from './credentials.js';
const TUNNEL_SERVER = process.env.OTTERKIT_TUNNEL_URL || 'https://otterkit.app';
export class PulseError extends Error {
code;
constructor(code, message) {
super(message ?? code);
this.code = code;
this.name = 'PulseError';
}
}
export async function createPulse(opts) {
const token = getToken();
if (!token)
throw new PulseError('not_logged_in', 'Run `otterkit login` first.');
const resp = await fetch(`${TUNNEL_SERVER}/api/agent/pulses`, {
method: 'POST',
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({
interval: opts.interval,
url: opts.url,
expect: opts.expect,
method: opts.method,
headers: opts.headers,
body: opts.body,
ttl: opts.ttl,
subdomain: opts.subdomain,
}),
});
const json = (await resp.json().catch(() => ({})));
if (!resp.ok) {
throw new PulseError(json.error ?? `http_${resp.status}`, json.message ?? `Pulse provisioning failed (${resp.status}).`);
}
return json;
}
/** Stop a pulse with the stopToken returned at creation. */
export async function stopPulse(subdomain, stopToken) {
const resp = await fetch(`${TUNNEL_SERVER}/api/agent/tunnels/${subdomain}?token=${encodeURIComponent(stopToken)}`, { method: 'DELETE' });
if (!resp.ok)
throw new PulseError(`http_${resp.status}`, 'Could not stop the pulse.');
}
+46
-0

@@ -26,2 +26,3 @@ /**

import { sendCore, verifyCore, SendError } from './send.js';
import { createPulse } from './pulse.js';
import { listEvents } from './providers.js';

@@ -463,2 +464,47 @@ import { createWait, listWaits, cancelWait, sessionToken } from './waits.js';

});
server.registerTool('pulse_create', {
title: 'Create a pulse (scheduled HTTP / dead-man switch)',
description: 'Provision a pulse - the scheduled third primitive. Active mode calls a public URL on an interval (min 30s) and stores every response as run history (read it with webhook_history). Expect mode returns a URL that must be pinged within the window, alerting the owner on silence. Fully server-side: survives this machine dying. Costs 1 credit per 100 runs, never more than 300 credits/30 days; 1 credit charged at creation. Default TTL "never".',
inputSchema: {
interval: z
.string()
.optional()
.describe('Active mode: run every e.g. 30s, 10m, 4h, 1d (min 30s)'),
url: z.string().optional().describe('Active mode: public http(s) URL to call each run'),
expect: z
.string()
.optional()
.describe('Expect mode: alert if no check-in arrives within e.g. 15m, 1h, 1d'),
method: z.string().optional().describe('HTTP method for active runs (default GET)'),
body: z.string().optional().describe('Request body for active runs'),
ttl: z.string().optional().describe('Auto-stop after e.g. 4h, 3d (default: never)'),
subdomain: z.string().optional().describe('Stable name for the pulse'),
},
}, async (args) => {
try {
const r = await createPulse({
interval: args.interval,
url: args.url,
expect: args.expect,
method: args.method,
body: args.body,
ttl: args.ttl,
subdomain: args.subdomain,
});
return {
content: [{ type: 'text', text: JSON.stringify(r) }],
};
}
catch (e) {
return {
content: [
{
type: 'text',
text: JSON.stringify({ error: e.message }),
},
],
isError: true,
};
}
});
server.registerTool('webhook_history', {

@@ -465,0 +511,0 @@ title: 'Server-side stored capture history',

+1
-1
{
"name": "otterkit",
"version": "0.34.0",
"version": "0.35.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