@ottocode/openclaw-setu 0.1.3 → 0.1.4
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/dist/chunk-5kkvddc1.js +4 -0
- package/dist/chunk-8pp4as02.js +2 -0
- package/dist/chunk-by6w3tsf.js +3 -0
- package/dist/chunk-e5qz2vx5.js +2 -0
- package/dist/chunk-esz88g73.js +3 -0
- package/dist/chunk-fc5rfx0b.js +3 -0
- package/dist/chunk-g3ma3sec.js +2 -0
- package/dist/chunk-gtxg1zc6.js +2 -0
- package/dist/chunk-h29x1xqe.js +108 -0
- package/dist/chunk-jrrt57tv.js +42 -0
- package/dist/chunk-kn2k3qtn.js +3 -0
- package/dist/chunk-m44tyrbv.js +2 -0
- package/dist/chunk-mbth668g.js +2 -0
- package/dist/chunk-rcdyanw7.js +2 -0
- package/dist/chunk-zy3raqnk.js +3 -0
- package/dist/cli.js +47 -0
- package/dist/index.js +4 -0
- package/package.json +10 -9
- package/src/cli.ts +0 -272
- package/src/config.ts +0 -498
- package/src/index.ts +0 -225
- package/src/proxy.ts +0 -149
- package/src/types.ts +0 -154
- package/src/wallet.ts +0 -79
package/src/proxy.ts
DELETED
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import { createSetuFetch, createWalletContext } from "@ottocode/ai-sdk";
|
|
2
|
-
import { loadWallet } from "./wallet.ts";
|
|
3
|
-
|
|
4
|
-
const DEFAULT_PORT = 8403;
|
|
5
|
-
const DEFAULT_BASE_URL = "https://api.setu.ottocode.io";
|
|
6
|
-
|
|
7
|
-
export interface ProxyOptions {
|
|
8
|
-
port?: number;
|
|
9
|
-
baseURL?: string;
|
|
10
|
-
verbose?: boolean;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function createProxy(options: ProxyOptions = {}) {
|
|
14
|
-
const port = options.port ?? DEFAULT_PORT;
|
|
15
|
-
const baseURL = options.baseURL ?? DEFAULT_BASE_URL;
|
|
16
|
-
const verbose = options.verbose ?? false;
|
|
17
|
-
|
|
18
|
-
const wallet = loadWallet();
|
|
19
|
-
if (!wallet) {
|
|
20
|
-
throw new Error(
|
|
21
|
-
"No wallet found. Run `openclaw-setu setup` or `openclaw-setu wallet generate` first.",
|
|
22
|
-
);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const log = verbose
|
|
26
|
-
? (msg: string) => console.log(`[setu-proxy] ${msg}`)
|
|
27
|
-
: (_msg: string) => {};
|
|
28
|
-
|
|
29
|
-
const walletCtx = createWalletContext({ privateKey: wallet.privateKey });
|
|
30
|
-
|
|
31
|
-
const setuFetch = createSetuFetch({
|
|
32
|
-
wallet: walletCtx,
|
|
33
|
-
baseURL,
|
|
34
|
-
callbacks: {
|
|
35
|
-
onPaymentRequired: (amountUsd) => {
|
|
36
|
-
log(`Payment required: $${amountUsd.toFixed(4)}`);
|
|
37
|
-
},
|
|
38
|
-
onPaymentComplete: (data) => {
|
|
39
|
-
log(
|
|
40
|
-
`Payment complete: $${data.amountUsd.toFixed(4)} | balance: $${data.newBalance.toFixed(4)}`,
|
|
41
|
-
);
|
|
42
|
-
},
|
|
43
|
-
onPaymentError: (error) => {
|
|
44
|
-
console.error(`[setu-proxy] Payment error: ${error}`);
|
|
45
|
-
},
|
|
46
|
-
onBalanceUpdate: (update) => {
|
|
47
|
-
log(
|
|
48
|
-
`Cost: $${update.costUsd.toFixed(4)} | remaining: $${update.balanceRemaining.toFixed(4)}`,
|
|
49
|
-
);
|
|
50
|
-
},
|
|
51
|
-
},
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
const proxyBaseURL = baseURL;
|
|
55
|
-
|
|
56
|
-
const server = Bun.serve({
|
|
57
|
-
port,
|
|
58
|
-
async fetch(req: Request): Promise<Response> {
|
|
59
|
-
const url = new URL(req.url);
|
|
60
|
-
|
|
61
|
-
if (url.pathname === "/health") {
|
|
62
|
-
return Response.json({
|
|
63
|
-
status: "ok",
|
|
64
|
-
wallet: wallet.publicKey,
|
|
65
|
-
provider: "setu",
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (url.pathname === "/v1/models") {
|
|
70
|
-
log("GET /v1/models");
|
|
71
|
-
const resp = await setuFetch(`${proxyBaseURL}/v1/models`, {
|
|
72
|
-
method: "GET",
|
|
73
|
-
headers: { "Content-Type": "application/json" },
|
|
74
|
-
});
|
|
75
|
-
return new Response(resp.body, {
|
|
76
|
-
status: resp.status,
|
|
77
|
-
headers: {
|
|
78
|
-
"Content-Type":
|
|
79
|
-
resp.headers.get("Content-Type") ?? "application/json",
|
|
80
|
-
"Access-Control-Allow-Origin": "*",
|
|
81
|
-
},
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const isCompletions = url.pathname === "/v1/chat/completions";
|
|
86
|
-
const isResponses = url.pathname === "/v1/responses";
|
|
87
|
-
if (!isCompletions && !isResponses) {
|
|
88
|
-
const targetURL = `${proxyBaseURL}${url.pathname}`;
|
|
89
|
-
log(`Proxying ${req.method} ${url.pathname}`);
|
|
90
|
-
const resp = await setuFetch(targetURL, {
|
|
91
|
-
method: req.method,
|
|
92
|
-
headers: { "Content-Type": "application/json" },
|
|
93
|
-
body: req.method !== "GET" ? await req.text() : undefined,
|
|
94
|
-
});
|
|
95
|
-
return new Response(resp.body, {
|
|
96
|
-
status: resp.status,
|
|
97
|
-
headers: {
|
|
98
|
-
"Content-Type":
|
|
99
|
-
resp.headers.get("Content-Type") ?? "application/json",
|
|
100
|
-
"Access-Control-Allow-Origin": "*",
|
|
101
|
-
},
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const body = await req.text();
|
|
106
|
-
let parsed: Record<string, unknown> = {};
|
|
107
|
-
try {
|
|
108
|
-
parsed = JSON.parse(body);
|
|
109
|
-
} catch {
|
|
110
|
-
return Response.json({ error: "Invalid JSON body" }, { status: 400 });
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const model = parsed.model as string;
|
|
114
|
-
const stream = parsed.stream as boolean;
|
|
115
|
-
log(
|
|
116
|
-
`${isCompletions ? "POST /v1/chat/completions" : "POST /v1/responses"} model=${model} stream=${stream}`,
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
const targetURL = `${proxyBaseURL}${url.pathname}`;
|
|
120
|
-
const resp = await setuFetch(targetURL, {
|
|
121
|
-
method: "POST",
|
|
122
|
-
headers: { "Content-Type": "application/json" },
|
|
123
|
-
body,
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
if (stream && resp.body) {
|
|
127
|
-
return new Response(resp.body, {
|
|
128
|
-
status: resp.status,
|
|
129
|
-
headers: {
|
|
130
|
-
"Content-Type": "text/event-stream",
|
|
131
|
-
"Cache-Control": "no-cache",
|
|
132
|
-
Connection: "keep-alive",
|
|
133
|
-
"Access-Control-Allow-Origin": "*",
|
|
134
|
-
},
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
return new Response(resp.body, {
|
|
139
|
-
status: resp.status,
|
|
140
|
-
headers: {
|
|
141
|
-
"Content-Type": "application/json",
|
|
142
|
-
"Access-Control-Allow-Origin": "*",
|
|
143
|
-
},
|
|
144
|
-
});
|
|
145
|
-
},
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
return { server, port, wallet };
|
|
149
|
-
}
|
package/src/types.ts
DELETED
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
export type ModelApi =
|
|
2
|
-
| "openai-completions"
|
|
3
|
-
| "openai-responses"
|
|
4
|
-
| "anthropic-messages"
|
|
5
|
-
| "google-generative-ai"
|
|
6
|
-
| "github-copilot"
|
|
7
|
-
| "bedrock-converse-stream";
|
|
8
|
-
|
|
9
|
-
export type ModelDefinitionConfig = {
|
|
10
|
-
id: string;
|
|
11
|
-
name: string;
|
|
12
|
-
api?: ModelApi;
|
|
13
|
-
reasoning?: boolean;
|
|
14
|
-
input?: Array<"text" | "image">;
|
|
15
|
-
cost?: {
|
|
16
|
-
input: number;
|
|
17
|
-
output: number;
|
|
18
|
-
cacheRead?: number;
|
|
19
|
-
cacheWrite?: number;
|
|
20
|
-
};
|
|
21
|
-
contextWindow?: number;
|
|
22
|
-
maxTokens?: number;
|
|
23
|
-
headers?: Record<string, string>;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export type ModelProviderConfig = {
|
|
27
|
-
baseUrl: string;
|
|
28
|
-
apiKey?: string;
|
|
29
|
-
api?: ModelApi;
|
|
30
|
-
headers?: Record<string, string>;
|
|
31
|
-
authHeader?: boolean;
|
|
32
|
-
models: ModelDefinitionConfig[];
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
export type AuthProfileCredential = {
|
|
36
|
-
apiKey?: string;
|
|
37
|
-
type?: string;
|
|
38
|
-
[key: string]: unknown;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export type ProviderAuthResult = {
|
|
42
|
-
profiles: Array<{ profileId: string; credential: AuthProfileCredential }>;
|
|
43
|
-
configPatch?: Record<string, unknown>;
|
|
44
|
-
defaultModel?: string;
|
|
45
|
-
notes?: string[];
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
export type WizardPrompter = {
|
|
49
|
-
text: (opts: {
|
|
50
|
-
message: string;
|
|
51
|
-
validate?: (value: string) => string | undefined;
|
|
52
|
-
}) => Promise<string | symbol>;
|
|
53
|
-
note: (message: string) => void;
|
|
54
|
-
progress: (message: string) => { stop: (message?: string) => void };
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
export type ProviderAuthContext = {
|
|
58
|
-
config: Record<string, unknown>;
|
|
59
|
-
agentDir?: string;
|
|
60
|
-
workspaceDir?: string;
|
|
61
|
-
prompter: WizardPrompter;
|
|
62
|
-
runtime: { log: (message: string) => void };
|
|
63
|
-
isRemote: boolean;
|
|
64
|
-
openUrl: (url: string) => Promise<void>;
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
export type ProviderAuthMethod = {
|
|
68
|
-
id: string;
|
|
69
|
-
label: string;
|
|
70
|
-
hint?: string;
|
|
71
|
-
kind: "oauth" | "api_key" | "token" | "device_code" | "custom";
|
|
72
|
-
run: (ctx: ProviderAuthContext) => Promise<ProviderAuthResult>;
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
export type ProviderPlugin = {
|
|
76
|
-
id: string;
|
|
77
|
-
label: string;
|
|
78
|
-
docsPath?: string;
|
|
79
|
-
aliases?: string[];
|
|
80
|
-
envVars?: string[];
|
|
81
|
-
models?: ModelProviderConfig;
|
|
82
|
-
auth: ProviderAuthMethod[];
|
|
83
|
-
formatApiKey?: (cred: AuthProfileCredential) => string;
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
export type PluginLogger = {
|
|
87
|
-
debug?: (message: string) => void;
|
|
88
|
-
info: (message: string) => void;
|
|
89
|
-
warn: (message: string) => void;
|
|
90
|
-
error: (message: string) => void;
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
export type OpenClawPluginService = {
|
|
94
|
-
id: string;
|
|
95
|
-
start: () => void | Promise<void>;
|
|
96
|
-
stop?: () => void | Promise<void>;
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
export type OpenClawPluginApi = {
|
|
100
|
-
id: string;
|
|
101
|
-
name: string;
|
|
102
|
-
version?: string;
|
|
103
|
-
description?: string;
|
|
104
|
-
source: string;
|
|
105
|
-
config: Record<string, unknown> & {
|
|
106
|
-
models?: { providers?: Record<string, ModelProviderConfig> };
|
|
107
|
-
agents?: Record<string, unknown>;
|
|
108
|
-
};
|
|
109
|
-
pluginConfig?: Record<string, unknown>;
|
|
110
|
-
logger: PluginLogger;
|
|
111
|
-
registerProvider: (provider: ProviderPlugin) => void;
|
|
112
|
-
registerTool: (tool: unknown, opts?: unknown) => void;
|
|
113
|
-
registerHook: (events: string | string[], handler: unknown, opts?: unknown) => void;
|
|
114
|
-
registerHttpRoute: (params: { path: string; handler: unknown }) => void;
|
|
115
|
-
registerService: (service: OpenClawPluginService) => void;
|
|
116
|
-
registerCommand: (command: unknown) => void;
|
|
117
|
-
resolvePath: (input: string) => string;
|
|
118
|
-
on: (hookName: string, handler: unknown, opts?: unknown) => void;
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
export type OpenClawPluginDefinition = {
|
|
122
|
-
id?: string;
|
|
123
|
-
name?: string;
|
|
124
|
-
description?: string;
|
|
125
|
-
version?: string;
|
|
126
|
-
register?: (api: OpenClawPluginApi) => void | Promise<void>;
|
|
127
|
-
activate?: (api: OpenClawPluginApi) => void | Promise<void>;
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
export type PluginCommandContext = {
|
|
131
|
-
senderId?: string;
|
|
132
|
-
channel: string;
|
|
133
|
-
isAuthorizedSender: boolean;
|
|
134
|
-
args?: string;
|
|
135
|
-
commandBody: string;
|
|
136
|
-
config: Record<string, unknown>;
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
export type PluginCommandResult = {
|
|
140
|
-
text?: string;
|
|
141
|
-
isError?: boolean;
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
export type PluginCommandHandler = (
|
|
145
|
-
ctx: PluginCommandContext,
|
|
146
|
-
) => PluginCommandResult | Promise<PluginCommandResult>;
|
|
147
|
-
|
|
148
|
-
export type OpenClawPluginCommandDefinition = {
|
|
149
|
-
name: string;
|
|
150
|
-
description: string;
|
|
151
|
-
acceptsArgs?: boolean;
|
|
152
|
-
requireAuth?: boolean;
|
|
153
|
-
handler: PluginCommandHandler;
|
|
154
|
-
};
|
package/src/wallet.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import { homedir } from "node:os";
|
|
4
|
-
import {
|
|
5
|
-
generateWallet,
|
|
6
|
-
importWallet,
|
|
7
|
-
isValidPrivateKey,
|
|
8
|
-
fetchBalance,
|
|
9
|
-
fetchWalletUsdcBalance,
|
|
10
|
-
} from "@ottocode/ai-sdk";
|
|
11
|
-
import type { WalletInfo } from "@ottocode/ai-sdk";
|
|
12
|
-
|
|
13
|
-
const WALLET_DIR = join(homedir(), ".openclaw", "setu");
|
|
14
|
-
const WALLET_KEY_PATH = join(WALLET_DIR, "wallet.key");
|
|
15
|
-
|
|
16
|
-
export function getWalletKeyPath(): string {
|
|
17
|
-
return WALLET_KEY_PATH;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function loadWallet(): WalletInfo | null {
|
|
21
|
-
try {
|
|
22
|
-
if (!existsSync(WALLET_KEY_PATH)) return null;
|
|
23
|
-
const privateKey = readFileSync(WALLET_KEY_PATH, "utf-8").trim();
|
|
24
|
-
if (!isValidPrivateKey(privateKey)) return null;
|
|
25
|
-
return importWallet(privateKey);
|
|
26
|
-
} catch {
|
|
27
|
-
return null;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function saveWallet(privateKey: string): WalletInfo {
|
|
32
|
-
if (!isValidPrivateKey(privateKey)) {
|
|
33
|
-
throw new Error("Invalid Solana private key");
|
|
34
|
-
}
|
|
35
|
-
const wallet = importWallet(privateKey);
|
|
36
|
-
mkdirSync(WALLET_DIR, { recursive: true });
|
|
37
|
-
writeFileSync(WALLET_KEY_PATH, privateKey, { mode: 0o600 });
|
|
38
|
-
return wallet;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function ensureWallet(): WalletInfo {
|
|
42
|
-
const existing = loadWallet();
|
|
43
|
-
if (existing) return existing;
|
|
44
|
-
const wallet = generateWallet();
|
|
45
|
-
saveWallet(wallet.privateKey);
|
|
46
|
-
return wallet;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function exportWalletKey(): string | null {
|
|
50
|
-
try {
|
|
51
|
-
if (!existsSync(WALLET_KEY_PATH)) return null;
|
|
52
|
-
return readFileSync(WALLET_KEY_PATH, "utf-8").trim();
|
|
53
|
-
} catch {
|
|
54
|
-
return null;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export async function getSetuBalance(privateKey: string): Promise<{
|
|
59
|
-
setu: { balance: number; totalSpent: number; requestCount: number } | null;
|
|
60
|
-
wallet: { usdcBalance: number; network: string } | null;
|
|
61
|
-
}> {
|
|
62
|
-
const [setu, wallet] = await Promise.all([
|
|
63
|
-
fetchBalance({ privateKey }),
|
|
64
|
-
fetchWalletUsdcBalance({ privateKey }),
|
|
65
|
-
]);
|
|
66
|
-
|
|
67
|
-
return {
|
|
68
|
-
setu: setu
|
|
69
|
-
? {
|
|
70
|
-
balance: setu.balance,
|
|
71
|
-
totalSpent: setu.totalSpent,
|
|
72
|
-
requestCount: setu.requestCount,
|
|
73
|
-
}
|
|
74
|
-
: null,
|
|
75
|
-
wallet: wallet
|
|
76
|
-
? { usdcBalance: wallet.usdcBalance, network: wallet.network }
|
|
77
|
-
: null,
|
|
78
|
-
};
|
|
79
|
-
}
|